Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

daml-assistant: Install bash completion scripts on Linux and Mac. #3946

Merged
merged 10 commits into from
Jan 6, 2020
Merged
3 changes: 2 additions & 1 deletion daml-assistant/exe/DA/Daml/Assistant.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ main = displayErrors $ do
]
exitFailure

versionChecks env
sdkConfig <- readSdkConfig (fromJust envSdkPath)
sdkCommands <- fromRightM throwIO (listSdkCommands sdkConfig)
userCommand <- getCommand sdkCommands
versionChecks env
handleCommand env userCommand

-- | Perform version checks, i.e. warn user if project SDK version or assistant SDK
Expand Down Expand Up @@ -111,6 +111,7 @@ autoInstall env@Env{..} = do
, iActivate = ActivateInstall False
, iForce = ForceInstall False
, iSetPath = SetPath True
, iBashCompletions = BashCompletions Auto
}
installEnv = InstallEnv
{ options = options
Expand Down
5 changes: 2 additions & 3 deletions daml-assistant/src/DA/Daml/Assistant/Command.hs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,13 @@ versionParser = VersionOptions

installParser :: Parser InstallOptions
installParser = InstallOptions
<$> optional (RawInstallTarget <$> argument str (metavar "TARGET" <> help "The SDK version to install. Use 'latest' to download and install the latest stable SDK version available. Run 'daml install' to see the full set of options."))
<$> optional (RawInstallTarget <$> argument str (metavar "TARGET" <> completeWith ["latest"] <> help "The SDK version to install. Use 'latest' to download and install the latest stable SDK version available. Run 'daml install' to see the full set of options."))
<*> (InstallAssistant <$> flagYesNoAuto' "install-assistant" "Install associated DAML assistant version. Can be set to \"yes\" (always installs), \"no\" (never installs), or \"auto\" (installs if newer). Default is \"auto\"." idm)
<*> iflag ActivateInstall "activate" hidden "Activate installed version of daml"
<*> iflag ForceInstall "force" (short 'f') "Overwrite existing installation"
<*> iflag QuietInstall "quiet" (short 'q') "Don't display installation messages"
<*> fmap SetPath (flagYesNoAuto "set-path" True "Adjust PATH automatically. This option only has an effect on Windows." idm)
<*> fmap BashCompletions (flagYesNoAuto' "bash-completions" "Install bash completions for DAML assistant. Default is yes for linux and mac, no for windows." idm)
where
iflag p name opts desc = fmap p (switch (long name <> help desc <> opts))

Expand All @@ -99,5 +100,3 @@ uninstallParser =
readSdkVersion :: ReadM SdkVersion
readSdkVersion =
eitherReader (mapLeft displayException . parseVersion . pack)


2 changes: 2 additions & 0 deletions daml-assistant/src/DA/Daml/Assistant/Install.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import DA.Daml.Assistant.Types
import DA.Daml.Assistant.Util
import qualified DA.Daml.Assistant.Install.Github as Github
import DA.Daml.Assistant.Install.Path
import DA.Daml.Assistant.Install.BashCompletion
import DA.Daml.Project.Consts
import DA.Daml.Project.Config
import DA.Daml.Project.Util
Expand Down Expand Up @@ -190,6 +191,7 @@ activateDaml env@InstallEnv{..} targetPath = do
else createSymbolicLink damlBinarySourcePath damlBinaryTargetPath

updatePath options (\s -> unlessQuiet env (output s)) damlBinaryTargetDir
installBashCompletions options damlPath (\s -> unlessQuiet env (output s))

data WalkCallbacks = WalkCallbacks
{ walkOnFile :: FilePath -> IO ()
Expand Down
62 changes: 62 additions & 0 deletions daml-assistant/src/DA/Daml/Assistant/Install/BashCompletion.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
-- Copyright (c) 2020 The DAML Authors. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0

-- | Installation of bash completions. These are installed in
-- /usr/local/etc/bash_completion.d (on Mac) or
-- /etc/bash_completion.d (elsewhere). These are not installed on
-- Windows by default, and won't be reinstalled unless the user
-- asks by passing @--bash-completions=yes@ explicitly.
module DA.Daml.Assistant.Install.BashCompletion
( installBashCompletions
) where

import DA.Daml.Assistant.Types

import qualified Data.ByteString.Lazy as BSL
import Control.Monad.Extra (andM, whenM)
import System.Directory (doesDirectoryExist, doesFileExist)
import System.FilePath ((</>))
import System.Info.Extra (isMac, isWindows)
import System.Process.Typed (proc, readProcessStdout_)

installBashCompletions :: InstallOptions -> DamlPath -> (String -> IO ()) -> IO ()
installBashCompletions options damlPath output =
whenM (shouldInstallBashCompletions options) $
doInstallBashCompletions damlPath output

shouldInstallBashCompletions :: InstallOptions -> IO Bool
shouldInstallBashCompletions options =
case iBashCompletions options of
BashCompletions Yes -> pure True
BashCompletions No -> pure False
BashCompletions Auto -> andM
[ pure (not isWindows)
, doesDirectoryExist bashCompletionDirPath
, not <$> doesFileExist bashCompletionScriptPath
]

doInstallBashCompletions :: DamlPath -> (String -> IO ()) -> IO ()
doInstallBashCompletions damlPath output = do
dirExists <- doesDirectoryExist bashCompletionDirPath
if dirExists
then do
completionScript <- getCompletionScript damlPath
BSL.writeFile bashCompletionScriptPath completionScript
output "Bash completions installed for DAML assistant."
else output ("Bash completions not installed for DAML assistant: " <> bashCompletionDirPath <> " does not exist")

getCompletionScript :: DamlPath -> IO BSL.ByteString
getCompletionScript damlPath = do
let assistant = assistantPath damlPath
readProcessStdout_ (proc assistant ["--bash-completion-script", assistant])

assistantPath :: DamlPath -> FilePath
assistantPath (DamlPath p) = p </> "bin" </> "daml"

bashCompletionDirPath :: FilePath
bashCompletionDirPath
| isMac = "/usr/local/etc/bash_completion.d"
This conversation was marked as resolved.
Show resolved Hide resolved
| otherwise = "/etc/bash_completion.d"
This conversation was marked as resolved.
Show resolved Hide resolved

bashCompletionScriptPath :: FilePath
bashCompletionScriptPath = bashCompletionDirPath </> "daml"
4 changes: 2 additions & 2 deletions daml-assistant/src/DA/Daml/Assistant/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ data InstallOptions = InstallOptions
, iForce :: ForceInstall -- ^ force reinstall if already installed
, iQuiet :: QuietInstall -- ^ don't print messages
, iSetPath :: SetPath -- ^ set the user's PATH (on Windows)
, iBashCompletions :: BashCompletions -- ^ install bash completions for the daml assistant
} deriving (Eq, Show)

-- | An install URL is a fully qualified HTTP[S] URL to an SDK release tarball. For example:
Expand All @@ -102,5 +103,4 @@ newtype QuietInstall = QuietInstall { unQuietInstall :: Bool } deriving (Eq, Sho
newtype ActivateInstall = ActivateInstall { unActivateInstall :: Bool } deriving (Eq, Show)
newtype SetPath = SetPath Bool deriving (Eq, Show)
newtype InstallAssistant = InstallAssistant { unwrapInstallAssistant :: YesNoAuto } deriving (Eq, Show)


newtype BashCompletions = BashCompletions { unwrapBashCompletions :: YesNoAuto } deriving (Eq, Show)
4 changes: 4 additions & 0 deletions daml-assistant/test/DA/Daml/Assistant/Tests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ testInstall = Tasty.testGroup "DA.Daml.Assistant.Install"
, iQuiet = QuietInstall True
, iForce = ForceInstall False
, iSetPath = SetPath False
, iBashCompletions = BashCompletions No
}

setCurrentDirectory base
Expand Down Expand Up @@ -411,6 +412,7 @@ testInstallUnix = Tasty.testGroup "unix-specific tests"
, iQuiet = QuietInstall True
, iForce = ForceInstall False
, iSetPath = SetPath False
, iBashCompletions = BashCompletions No
}

setCurrentDirectory base
Expand Down Expand Up @@ -439,6 +441,7 @@ testInstallUnix = Tasty.testGroup "unix-specific tests"
, iQuiet = QuietInstall True
, iForce = ForceInstall False
, iSetPath = SetPath False
, iBashCompletions = BashCompletions No
}

setCurrentDirectory base
Expand Down Expand Up @@ -467,6 +470,7 @@ testInstallUnix = Tasty.testGroup "unix-specific tests"
, iQuiet = QuietInstall True
, iForce = ForceInstall False
, iSetPath = SetPath False
, iBashCompletions = BashCompletions No
}

setCurrentDirectory base
Expand Down
3 changes: 1 addition & 2 deletions libs-haskell/da-hs-base/src/Options/Applicative/Extended.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ determineAuto b = \case
-- This maps yes to "Just true", no to "Just False" and auto to "Nothing"
flagYesNoAuto' :: String -> String -> Mod OptionFields YesNoAuto -> Parser YesNoAuto
flagYesNoAuto' flagName helpText mods =
option reader (long flagName <> value Auto <> help helpText <> mods)
option reader (long flagName <> value Auto <> help helpText <> completeWith ["yes", "no", "auto"] <> mods)
where reader = eitherReader $ \case
"yes" -> Right Yes
"no" -> Right No
Expand All @@ -43,4 +43,3 @@ flagYesNoAuto flagName defaultValue helpText mods =
determineAuto defaultValue <$> flagYesNoAuto' flagName (helpText <> commonHelp) mods
where
commonHelp = " Can be set to \"yes\", \"no\" or \"auto\" to select the default (" <> show defaultValue <> ")"