diff --git a/dev-ui-install.sh b/dev-ui-install.sh new file mode 100755 index 000000000..e9aa6203b --- /dev/null +++ b/dev-ui-install.sh @@ -0,0 +1,10 @@ +echo "This script downloads the latest codebase UI release" +echo "and puts it in the correct spot next to the unison" +echo "executable built by stack." +echo "" + +stack build +curl -L https://github.com/unisonweb/codebase-ui/releases/download/latest/ucm.zip --output ucm.zip +parent_dir="$(dirname -- $(stack exec which unison))" +mkdir -p "$parent_dir/ui" +unzip -o ucm.zip -d "$parent_dir/ui" diff --git a/development.markdown b/development.markdown index 6c7de3324..a2f012c2a 100644 --- a/development.markdown +++ b/development.markdown @@ -8,9 +8,13 @@ _Disclaimer_ If you have trouble getting started, please get in touch via [Slack To get cracking with Unison: -* [Install `stack`](https://docs.haskellstack.org/en/stable/README/#how-to-install). -* Build the project with `stack build`. This builds all executables. -* After building, `stack exec unison` will fire up the codebase editor, create a codebase in the current directory, and watch for `.u` file changes. If you want to run it in a different directory, just add `unison` to your `PATH`, after finding it with `find .stack-work -name unison -type f`. (For me, this finds two, they both work, but have different contents. ¯\\\_(ツ)\_/¯ ) +1. [Install `stack`](https://docs.haskellstack.org/en/stable/README/#how-to-install). +2. Build the project with `stack build`. This builds all executables. +3. (Optional) Run `./dev-ui-install.hs` to fetch the latest release of the codebase UI. If you don't care about running the codebase UI locally you can ignore this step. +4. After building do `stack exec unison -- init` will initialize a codebase in your home directory (in `~/.unison`). This only needs to be done once. +5. `stack exec unison` starts Unison and watches for `.u` file changes in the current directory. If you want to run it in a different directory, just add `unison` to your `PATH`, after finding it with `stack exec which unison`. + +On startup, Unison prints a url for the codebase UI. If you did step 3 above, then visiting that URL in a browser will give you a nice interface to your codebase. ## Running Tests diff --git a/parser-typechecker/src/Unison/Server/CodebaseServer.hs b/parser-typechecker/src/Unison/Server/CodebaseServer.hs index 68c000cc6..6152c5080 100644 --- a/parser-typechecker/src/Unison/Server/CodebaseServer.hs +++ b/parser-typechecker/src/Unison/Server/CodebaseServer.hs @@ -87,9 +87,10 @@ import Servant.Server err404, ) import Servant.Server.StaticFiles (serveDirectoryWebApp) -import System.Directory (doesFileExist) -import System.Environment (getArgs, lookupEnv) -import System.FilePath.Posix (()) +import System.Directory (doesFileExist, canonicalizePath) +import System.Environment (getArgs, lookupEnv, getExecutablePath) +import System.FilePath (()) +import qualified System.FilePath as FilePath import System.Random.Stateful (getStdGen, newAtomicGenM, uniformByteStringM) import Text.Read (readMaybe) import Unison.Codebase (Codebase) @@ -165,7 +166,7 @@ serverAPI = Proxy app :: Var v => Codebase IO v Ann - -> Maybe FilePath + -> FilePath -> Strict.ByteString -> Application app codebase uiPath expectedToken = @@ -263,7 +264,10 @@ startServer -> Maybe Port -> Maybe String -> IO () -startServer codebase k envToken envHost envPort envUI = do +startServer codebase k envToken envHost envPort envUI0 = do + -- the `canonicalizePath` resolves symlinks + exePath <- canonicalizePath =<< getExecutablePath + envUI <- canonicalizePath $ fromMaybe (FilePath.takeDirectory exePath "ui") envUI0 token <- case envToken of Just t -> return $ C8.pack t _ -> genToken @@ -301,19 +305,17 @@ serveIndex path = do <> " environment variable to the directory where the UI is installed." } -serveUI :: Handler () -> Maybe FilePath -> Server WebUI -serveUI tryAuth p _ = - let path = fromMaybe "ui" p - in tryAuth *> serveIndex path +serveUI :: Handler () -> FilePath -> Server WebUI +serveUI tryAuth path _ = tryAuth *> serveIndex path server :: Var v => Codebase IO v Ann - -> Maybe FilePath + -> FilePath -> Strict.ByteString -> Server AuthedServerAPI server codebase uiPath token = - serveDirectoryWebApp (fromMaybe "ui" uiPath "static") + serveDirectoryWebApp (uiPath "static") :<|> ((\t -> serveUI (tryAuth t) uiPath :<|> ( ( (serveNamespace (tryAuth t) codebase)