22{-# LANGUAGE OverloadedStrings #-}
33{-# LANGUAGE ScopedTypeVariables #-}
44
5- -- | Make changes to the stack yaml file
6-
5+ -- | Make changes to project or global configuration.
76module Stack.ConfigCmd
87 (ConfigCmdSet (.. )
98 ,configCmdSetParser
@@ -19,8 +18,7 @@ import Control.Monad.Reader (MonadReader, asks)
1918import Control.Monad.Trans.Control (MonadBaseControl )
2019import qualified Data.ByteString as S
2120import qualified Data.HashMap.Strict as HMap
22- import Data.Map (Map )
23- import qualified Data.Map.Strict as Map
21+ import Data.Monoid
2422import Data.Text (Text )
2523import qualified Data.Text as T
2624import qualified Data.Yaml.Extra as Yaml
@@ -36,8 +34,22 @@ import Stack.Types.Config
3634
3735data ConfigCmdSet
3836 = ConfigCmdSetResolver AbstractResolver
39- | ConfigCmdSetSystemGhc Bool
40- | ConfigCmdSetInstallGhc Bool
37+ | ConfigCmdSetSystemGhc CommandScope
38+ Bool
39+ | ConfigCmdSetInstallGhc CommandScope
40+ Bool
41+
42+ data CommandScope
43+ = CommandScopeGlobal
44+ -- ^ Apply changes to the global configuration,
45+ -- typically at @~/.stack/config.yaml@.
46+ | CommandScopeProject
47+ -- ^ Apply changes to the project @stack.yaml@.
48+
49+ configCmdSetScope :: ConfigCmdSet -> CommandScope
50+ configCmdSetScope (ConfigCmdSetResolver _) = CommandScopeProject
51+ configCmdSetScope (ConfigCmdSetSystemGhc scope _) = scope
52+ configCmdSetScope (ConfigCmdSetInstallGhc scope _) = scope
4153
4254cfgCmdSet :: ( MonadIO m
4355 , MonadBaseControl IO m
@@ -49,25 +61,19 @@ cfgCmdSet :: ( MonadIO m
4961 , MonadLogger m )
5062 => ConfigCmdSet -> m ()
5163cfgCmdSet cmd = do
52- stackYaml <- fmap bcStackYaml (asks getBuildConfig)
53- let stackYamlFp =
54- toFilePath stackYaml
64+ configFilePath <-
65+ asks
66+ (toFilePath .
67+ case configCmdSetScope cmd of
68+ CommandScopeProject -> bcStackYaml . getBuildConfig
69+ CommandScopeGlobal -> configUserConfigPath . getConfig)
5570 -- We don't need to worry about checking for a valid yaml here
56- (projectYamlConfig :: Yaml. Object ) <-
57- liftIO (Yaml. decodeFileEither stackYamlFp) >>=
58- either throwM return
71+ (config :: Yaml. Object ) <-
72+ liftIO (Yaml. decodeFileEither configFilePath) >>= either throwM return
5973 newValue <- cfgCmdSetValue cmd
6074 let cmdKey = cfgCmdSetOptionName cmd
61- projectYamlConfig' =
62- HMap. insert
63- cmdKey
64- newValue
65- projectYamlConfig
66- liftIO
67- (S. writeFile
68- stackYamlFp
69- (Yaml. encode projectYamlConfig'))
70- return ()
75+ config' = HMap. insert cmdKey newValue config
76+ liftIO (S. writeFile configFilePath (Yaml. encode config'))
7177
7278cfgCmdSetValue
7379 :: ( MonadIO m
@@ -87,15 +93,15 @@ cfgCmdSetValue (ConfigCmdSetResolver newResolver) = do
8793 snap <- parseSnapName newResolverText
8894 _ <- loadMiniBuildPlan snap
8995 return (Yaml. String newResolverText)
90- cfgCmdSetValue (ConfigCmdSetSystemGhc bool) = do
96+ cfgCmdSetValue (ConfigCmdSetSystemGhc _ bool) =
9197 return (Yaml. Bool bool)
92- cfgCmdSetValue (ConfigCmdSetInstallGhc bool) = do
98+ cfgCmdSetValue (ConfigCmdSetInstallGhc _ bool) =
9399 return (Yaml. Bool bool)
94100
95101cfgCmdSetOptionName :: ConfigCmdSet -> Text
96102cfgCmdSetOptionName (ConfigCmdSetResolver _) = " resolver"
97- cfgCmdSetOptionName (ConfigCmdSetSystemGhc _) = configMonoidSystemGHCName
98- cfgCmdSetOptionName (ConfigCmdSetInstallGhc _) = configMonoidInstallGHCName
103+ cfgCmdSetOptionName (ConfigCmdSetSystemGhc _ _ ) = configMonoidSystemGHCName
104+ cfgCmdSetOptionName (ConfigCmdSetInstallGhc _ _ ) = configMonoidInstallGHCName
99105
100106cfgCmdName :: String
101107cfgCmdName = " config"
@@ -105,39 +111,40 @@ cfgCmdSetName = "set"
105111
106112configCmdSetParser :: OA. Parser ConfigCmdSet
107113configCmdSetParser =
108- OA. fromM
109- (do field <-
110- OA. oneM
111- (OA. strArgument
112- (OA. metavar " FIELD VALUE" ))
113- OA. oneM (fieldToValParser field))
114- where
115- fieldToValParser :: String -> OA. Parser ConfigCmdSet
116- fieldToValParser s =
117- Map. findWithDefault
118- (error $ concat $
119- [ " Invalid field "
120- , show s
121- , " : Only the following fields are currently implemented:"
122- ] ++
123- map
124- ((" \n - " ++ ) . T. unpack)
125- (Map. keys fieldToValParser'))
126- (T. pack s)
127- fieldToValParser'
128- fieldToValParser' :: Map Text (OA. Parser ConfigCmdSet )
129- fieldToValParser' =
130- Map. fromList
131- [ ( " resolver"
132- , ConfigCmdSetResolver <$>
133- OA. argument
134- readAbstractResolver
135- OA. idm)
136- , ( configMonoidSystemGHCName
137- , ConfigCmdSetSystemGhc <$> boolArgument)
138- , ( configMonoidInstallGHCName
139- , ConfigCmdSetInstallGhc <$> boolArgument)
140- ]
114+ OA. hsubparser $
115+ mconcat
116+ [ OA. command
117+ " resolver"
118+ (OA. info
119+ (ConfigCmdSetResolver <$>
120+ OA. argument
121+ readAbstractResolver
122+ (OA. metavar " RESOLVER" <>
123+ OA. help " E.g. \" nightly\" or \" lts-7.2\" " ))
124+ (OA. progDesc
125+ " Change the resolver of the current project. See https://docs.haskellstack.org/en/stable/yaml_configuration/#resolver for more info." ))
126+ , OA. command
127+ (T. unpack configMonoidSystemGHCName)
128+ (OA. info
129+ (ConfigCmdSetSystemGhc <$> scopeFlag <*> boolArgument)
130+ (OA. progDesc
131+ " Configure whether stack should use a system GHC installation or not." ))
132+ , OA. command
133+ (T. unpack configMonoidInstallGHCName)
134+ (OA. info
135+ (ConfigCmdSetInstallGhc <$> scopeFlag <*> boolArgument)
136+ (OA. progDesc
137+ " Configure whether stack should automatically install GHC when necessary." ))
138+ ]
139+
140+ scopeFlag :: OA. Parser CommandScope
141+ scopeFlag =
142+ OA. flag
143+ CommandScopeProject
144+ CommandScopeGlobal
145+ (OA. long " global" <>
146+ OA. help
147+ " Modify the global configuration (typically at \" ~/.stack/config.yaml\" ) instead of the project stack.yaml." )
141148
142149readBool :: OA. ReadM Bool
143150readBool = do
@@ -148,4 +155,4 @@ readBool = do
148155 _ -> OA. readerError (" Invalid value " ++ show s ++ " : Expected \" true\" or \" false\" " )
149156
150157boolArgument :: OA. Parser Bool
151- boolArgument = OA. argument readBool OA. idm
158+ boolArgument = OA. argument readBool ( OA. metavar " true/false " )
0 commit comments