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

Add the config env command (fixes #620) #4642

Merged
merged 3 commits into from
Mar 24, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ Other enhancements:
* Both `stack dot` and `stack ls dependencies` accept a
`--global-hints` flag to bypass the need for an installed GHC. See
[#4390](https://github.com/commercialhaskell/stack/issues/4390).
* Add the `stack config env` command for getting shell script environment
variables. See [#620](https://github.com/commercialhaskell/stack/issues/620).

Bug fixes:

Expand Down
47 changes: 47 additions & 0 deletions src/Stack/ConfigCmd.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,29 @@ module Stack.ConfigCmd
,configCmdSetParser
,cfgCmdSet
,cfgCmdSetName
,configCmdEnvParser
,cfgCmdEnv
,cfgCmdEnvName
,cfgCmdName) where

import Stack.Prelude
import qualified Data.ByteString as S
import qualified Data.Map.Merge.Strict as Map
import qualified Data.HashMap.Strict as HMap
import qualified Data.Text as T
import qualified Data.Yaml as Yaml
import qualified Options.Applicative as OA
import qualified Options.Applicative.Types as OA
import Options.Applicative.Builder.Extra
import Path
import qualified RIO.Map as Map
import RIO.Process (envVarsL)
import Stack.Config (makeConcreteResolver, getProjectConfig, getImplicitGlobalProjectDir)
import Stack.Constants
import Stack.Snapshot (loadResolver)
import Stack.Types.Config
import Stack.Types.Resolver
import System.Environment (getEnvironment)

data ConfigCmdSet
= ConfigCmdSetResolver (Unresolved AbstractResolver)
Expand Down Expand Up @@ -101,6 +109,9 @@ cfgCmdName = "config"
cfgCmdSetName :: String
cfgCmdSetName = "set"

cfgCmdEnvName :: String
cfgCmdEnvName = "env"

configCmdSetParser :: OA.Parser ConfigCmdSet
configCmdSetParser =
OA.hsubparser $
Expand Down Expand Up @@ -148,3 +159,39 @@ readBool = do

boolArgument :: OA.Parser Bool
boolArgument = OA.argument readBool (OA.metavar "true|false" <> OA.completeWith ["true", "false"])

configCmdEnvParser :: OA.Parser EnvSettings
configCmdEnvParser = EnvSettings
<$> boolFlags True "locals" "include local package information" mempty
<*> boolFlags True "ghc-package-path" "set GHC_PACKAGE_PATH variable" mempty
<*> boolFlags True "stack-exe" "set STACK_EXE environment variable" mempty
<*> boolFlags False "locale-utf8" "set the GHC_CHARENC environment variable to UTF8" mempty
<*> boolFlags False "keep-ghc-rts" "keep any GHC_RTS environment variables" mempty

data EnvVarAction = EVASet !Text | EVAUnset
deriving Show

cfgCmdEnv :: EnvSettings -> RIO EnvConfig ()
cfgCmdEnv es = do
origEnv <- liftIO $ Map.fromList . map (first fromString) <$> getEnvironment
mkPC <- view $ configL.to configProcessContextSettings
pc <- liftIO $ mkPC es
let newEnv = pc ^. envVarsL
actions = Map.merge
(pure EVAUnset)
(Map.traverseMissing $ \_k new -> pure (EVASet new))
(Map.zipWithMaybeAMatched $ \_k old new -> pure $
if fromString old == new
then Nothing
else Just (EVASet new))
origEnv
newEnv
toLine key EVAUnset = "unset " <> encodeUtf8Builder key <> ";\n"
toLine key (EVASet value) =
encodeUtf8Builder key <> "='" <>
encodeUtf8Builder (T.concatMap escape value) <> -- TODO more efficient to use encodeUtf8BuilderEscaped
"'; export " <>
encodeUtf8Builder key <> ";\n"
escape '\'' = "'\"'\"'"
escape c = T.singleton c
hPutBuilder stdout $ Map.foldMapWithKey toLine actions
2 changes: 1 addition & 1 deletion src/Stack/Setup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ setupEnv needTargets boptsCLI mResolveMissingGHC = do
extras <- runReaderT packageDatabaseExtra envConfig0
let mkGPP locals = mkGhcPackagePath locals localdb deps extras globaldb

distDir <- runReaderT distRelativeDir envConfig0
distDir <- runReaderT distRelativeDir envConfig0 >>= canonicalizePath

executablePath <- liftIO getExecutablePath

Expand Down
13 changes: 9 additions & 4 deletions src/main/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,15 @@ commandLineHandler currentDir progName isInterpreter = complicatedOptions
addSubCommands'
ConfigCmd.cfgCmdName
"Subcommands specific to modifying stack.yaml files"
(addCommand' ConfigCmd.cfgCmdSetName
"Sets a field in the project's stack.yaml to value"
(withConfig . cfgCmdSet)
configCmdSetParser)
(do
addCommand' ConfigCmd.cfgCmdSetName
"Sets a field in the project's stack.yaml to value"
(withConfig . cfgCmdSet)
configCmdSetParser
addCommand' ConfigCmd.cfgCmdEnvName
"Print environment variables for use in a shell"
(withConfig . withDefaultEnvConfig . cfgCmdEnv)
configCmdEnvParser)
addSubCommands'
"hpc"
"Subcommands specific to Haskell Program Coverage"
Expand Down
6 changes: 6 additions & 0 deletions test/integration/tests/620-env-command/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import StackTest
import System.Process
import Control.Exception (throwIO)

main :: IO ()
main = rawSystem "bash" ["run.sh"] >>= throwIO
2 changes: 2 additions & 0 deletions test/integration/tests/620-env-command/files/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Main
Main.exe
4 changes: 4 additions & 0 deletions test/integration/tests/620-env-command/files/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Control.Concurrent.Async ()

main :: IO ()
main = pure ()
7 changes: 7 additions & 0 deletions test/integration/tests/620-env-command/files/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash

set -euxo pipefail

stack build --resolver lts-11.22 async
eval `stack config env --resolver lts-11.22`
ghc Main.hs