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

Rename config files and clarify their purposes (#969) #1058

Merged
merged 4 commits into from
Sep 27, 2015
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
7 changes: 6 additions & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

Major changes:

* "stack setup" now supports building and booting GHCJS from source tarball.
* "stack setup" now supports building and booting GHCJS from source tarball
* Rename config files and clarify their purposes (#969)
* `~/.stack/stack.yaml` --> `~/.stack/config.yaml`
* `~/.stack/global` --> `~/.stack/global-project`
* `/etc/stack/config` --> `/etc/stack/config.yaml`
* Old locations still supported, with deprecation warnings

## 0.1.5.0

Expand Down
10 changes: 5 additions & 5 deletions doc/GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Downloading template "new-template" to create project "helloworld" in helloworld
Using the following authorship configuration:
author-email: example@example.com
author-name: Example Author Name
Copy these to /home/michael/.stack/stack.yaml and edit to use different values.
Copy these to /home/michael/.stack/config.yaml and edit to use different values.
Writing default config file to: /home/michael/helloworld/stack.yaml
Basing on cabal files:
- /home/michael/helloworld/helloworld.cabal
Expand Down Expand Up @@ -1321,7 +1321,7 @@ follows the Unix convention of `--` to separate these, e.g.:

```
michael@d30748af6d3d:~$ stack exec --package stm -- echo I installed the stm package via --package stm
Run from outside a project, using implicit global config
Run from outside a project, using implicit global project config
Using latest snapshot resolver: lts-3.2
Writing global (non-project-specific) config file to: /home/michael/.stack/global/stack.yaml
Note: You can change the snapshot via the resolver field there.
Expand Down Expand Up @@ -1368,14 +1368,14 @@ import Turtle
main = echo "Hello World!"
michael@d30748af6d3d:~$ chmod +x turtle.hs
michael@d30748af6d3d:~$ ./turtle.hs
Run from outside a project, using implicit global config
Run from outside a project, using implicit global project config
Using resolver: lts-3.2 specified on command line
hashable-1.2.3.3: configure
# installs some more dependencies
Completed all 22 actions.
Hello World!
michael@d30748af6d3d:~$ ./turtle.hs
Run from outside a project, using implicit global config
Run from outside a project, using implicit global project config
Using resolver: lts-3.2 specified on command line
Hello World!
```
Expand Down Expand Up @@ -1545,7 +1545,7 @@ Downloading template "yesod-simple" to create project "my-yesod-project" in my-y
Using the following authorship configuration:
author-email: example@example.com
author-name: Example Author Name
Copy these to /home/michael/.stack/stack.yaml and edit to use different values.
Copy these to /home/michael/.stack/config.yaml and edit to use different values.
Writing default config file to: /home/michael/my-yesod-project/stack.yaml
Basing on cabal files:
- /home/michael/my-yesod-project/my-yesod-project.cabal
Expand Down
2 changes: 1 addition & 1 deletion doc/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ stack has two layers of configuration: project and non-project. All of these
are stored in stack.yaml files, but the former has extra fields (resolver,
packages, extra-deps, and flags). The latter can be monoidally combined so that
a system config file provides defaults, which a user can override with
~/.stack/stack.yaml, and a project can further customize. In addition,
`~/.stack/config.yaml`, and a project can further customize. In addition,
environment variables STACK\_ROOT and STACK\_YAML can be used to tweak where
stack gets its configuration from.

Expand Down
6 changes: 3 additions & 3 deletions doc/yaml_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ The stack.yaml configuration options break down into [project specific](#project

and [non-project specific](#non-project-config) options in:

- `/etc/stack/config` -- for system global non-project default options
- `~/.stack/stack.yaml` -- for user non-project default options
- `/etc/stack/config.yaml` -- for system global non-project default options
- `~/.stack/config.yaml` -- for user non-project default options
- The project file itself may also contain non-project specific options

*Note:* When stack is invoked outside a stack project it will source project specific options from `~/.stack/global/stack.yaml`. Options in this file will be ignored for a project with its own `<project dir>/stack.yaml`.
Expand Down Expand Up @@ -115,7 +115,7 @@ image:

## Non-project config

Non-project config options may go in the global config (`/etc/stack/config`) or the user config (`~/.stack/stack.yaml`).
Non-project config options may go in the global config (`/etc/stack/config.yaml`) or the user config (`~/.stack/config.yaml`).

### docker

Expand Down
2 changes: 1 addition & 1 deletion src/Stack/Build/Target.hs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ data NeedTargets

parseTargets :: (MonadThrow m, MonadIO m)
=> NeedTargets -- ^ need at least one target
-> Bool -- ^ using implicit global?
-> Bool -- ^ using implicit global project?
-> Map PackageName Version -- ^ snapshot
-> Map PackageName Version -- ^ extra deps
-> Map PackageName LocalPackageView
Expand Down
97 changes: 76 additions & 21 deletions src/Stack/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module Stack.Config
,loadMiniConfig
,packagesParser
,resolvePackageEntry
,getImplicitGlobalProjectDir
) where

import qualified Codec.Archive.Tar as Tar
Expand All @@ -41,6 +42,7 @@ import Control.Monad.Reader (MonadReader, ask, runReaderT)
import Control.Monad.Trans.Control (MonadBaseControl)
import qualified Crypto.Hash.SHA256 as SHA256
import Data.Aeson.Extended
import qualified Data.ByteString as S
import qualified Data.ByteString.Base16 as B16
import qualified Data.ByteString.Lazy as L
import qualified Data.IntMap as IntMap
Expand Down Expand Up @@ -89,18 +91,15 @@ getLatestResolver = do
Just lts -> lts
return (ResolverSnapshot snap)

-- | Note that this will be @Nothing@ on Windows, which is by design.
defaultStackGlobalConfig :: Maybe (Path Abs File)
defaultStackGlobalConfig = parseAbsFile "/etc/stack/config"

-- Interprets ConfigMonoid options.
configFromConfigMonoid
:: (MonadLogger m, MonadIO m, MonadCatch m, MonadReader env m, HasHttpManager env)
=> Path Abs Dir -- ^ stack root, e.g. ~/.stack
-> Path Abs File -- ^ user config file path, e.g. ~/.stack/config.yaml
-> Maybe Project
-> ConfigMonoid
-> m Config
configFromConfigMonoid configStackRoot mproject configMonoid@ConfigMonoid{..} = do
configFromConfigMonoid configStackRoot configUserConfigPath mproject configMonoid@ConfigMonoid{..} = do
let configDocker = Docker.dockerOptsFromMonoid mproject configStackRoot configMonoidDockerOpts
configConnectionCount = fromMaybe 8 configMonoidConnectionCount
configHideTHLoading = fromMaybe True configMonoidHideTHLoading
Expand Down Expand Up @@ -257,17 +256,18 @@ loadConfig :: (MonadLogger m,MonadIO m,MonadCatch m,MonadThrow m,MonadBaseContro
-> m (LoadConfig m)
loadConfig configArgs mstackYaml = do
stackRoot <- determineStackRoot
extraConfigs <- getExtraConfigs stackRoot >>= mapM loadYaml
userConfigPath <- getDefaultUserConfigPath stackRoot
extraConfigs <- getExtraConfigs userConfigPath >>= mapM loadYaml
mproject <- loadProjectConfig mstackYaml
config <- configFromConfigMonoid stackRoot (fmap (\(proj, _, _) -> proj) mproject) $ mconcat $
config <- configFromConfigMonoid stackRoot userConfigPath (fmap (\(proj, _, _) -> proj) mproject) $ mconcat $
case mproject of
Nothing -> configArgs : extraConfigs
Just (_, _, projectConfig) -> configArgs : projectConfig : extraConfigs
unless (fromCabalVersion Meta.version `withinRange` configRequireStackVersion config)
(throwM (BadStackVersionException (configRequireStackVersion config)))
return $ LoadConfig
{ lcConfig = config
, lcLoadBuildConfig = loadBuildConfig mproject config stackRoot
, lcLoadBuildConfig = loadBuildConfig mproject config
, lcProjectRoot = fmap (\(_, fp, _) -> parent fp) mproject
}

Expand All @@ -276,20 +276,19 @@ loadConfig configArgs mstackYaml = do
loadBuildConfig :: (MonadLogger m, MonadIO m, MonadCatch m, MonadReader env m, HasHttpManager env, MonadBaseControl IO m, HasTerminal env)
=> Maybe (Project, Path Abs File, ConfigMonoid)
-> Config
-> Path Abs Dir
-> Maybe AbstractResolver -- override resolver
-> m BuildConfig
loadBuildConfig mproject config stackRoot mresolver = do
loadBuildConfig mproject config mresolver = do
env <- ask
miniConfig <- loadMiniConfig config

(project', stackYamlFP) <- case mproject of
Just (project, fp, _) -> return (project, fp)
Nothing -> do
$logInfo "Run from outside a project, using implicit global config"
$logInfo "Run from outside a project, using implicit global project config"
destDir <- getImplicitGlobalProjectDir config
let dest :: Path Abs File
dest = destDir </> stackDotYaml
destDir = implicitGlobalDir stackRoot
dest' :: FilePath
dest' = toFilePath dest
createTree destDir
Expand All @@ -301,7 +300,7 @@ loadBuildConfig mproject config stackRoot mresolver = do
case mresolver of
Nothing ->
$logInfo ("Using resolver: " <> resolverName (projectResolver project) <>
" from global config file: " <> T.pack dest')
" from implicit global project's config file: " <> T.pack dest')
Just aresolver -> do
let name =
case aresolver of
Expand All @@ -316,15 +315,28 @@ loadBuildConfig mproject config stackRoot mresolver = do
else do
r <- runReaderT getLatestResolver miniConfig
$logInfo ("Using latest snapshot resolver: " <> resolverName r)
$logInfo ("Writing global (non-project-specific) config file to: " <> T.pack dest')
$logInfo ("Writing implicit global project config file to: " <> T.pack dest')
$logInfo "Note: You can change the snapshot via the resolver field there."
let p = Project
{ projectPackages = mempty
, projectExtraDeps = mempty
, projectFlags = mempty
, projectResolver = r
}
liftIO $ Yaml.encodeFile dest' p
liftIO $ do
S.writeFile dest'
("# This is the implicit global project's config file, which is only used when\n" <>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit of code has bad complexity characteristics. It would be better to use S.concat or a Builder.

"# 'stack' is run outside of a real project. Settings here do _not_ act as\n" <>
"# defaults for all projects. To change stack's default settings, edit\n" <>
"# '" <> encodeUtf8 (T.pack $ toFilePath $ configUserConfigPath config) <> "' instead.\n" <>
"#\n" <>
"# For more information about stack's configuration, see\n" <>
"# https://github.com/commercialhaskell/stack/blob/release/doc/yaml_configuration.md\n" <>
"#\n" <>
Yaml.encode p)
S.writeFile (toFilePath $ parent dest </> $(mkRelFile "README.txt")) $
"This is the implicit global project, which is used only when 'stack' is run\n" <>
"outside of a real project.\n"
return (p, dest)
resolver <-
case mresolver of
Expand Down Expand Up @@ -372,7 +384,7 @@ resolvePackageEntry menv projRoot pe = do
subs -> mapM (resolveDir entryRoot) subs
case peValidWanted pe of
Nothing -> return ()
Just _ -> $logWarn "Warning: you are using the deprecated valid-wanted field. You should instead use extra-dep. See: https://github.com/commercialhaskell/stack/blob/master/doc/yaml_configuration.md#packages"
Just _ -> $logWarn "Warning: you are using the deprecated valid-wanted field. You should instead use extra-dep. See: https://github.com/commercialhaskell/stack/blob/release/doc/yaml_configuration.md#packages"
return $ map (, not $ peExtraDep pe) paths

-- | Resolve a PackageLocation into a path, downloading and cloning as
Expand Down Expand Up @@ -460,10 +472,12 @@ determineStackRoot = do
-- | Determine the extra config file locations which exist.
--
-- Returns most local first
getExtraConfigs :: MonadIO m
=> Path Abs Dir -- ^ stack root
getExtraConfigs :: (MonadIO m, MonadLogger m)
=> Path Abs File -- ^ use config path
-> m [Path Abs File]
getExtraConfigs stackRoot = liftIO $ do
getExtraConfigs userConfigPath = do
defaultStackGlobalConfigPath <- getDefaultGlobalConfigPath
liftIO $ do
env <- getEnvironment
mstackConfig <-
maybe (return Nothing) (fmap Just . parseAbsFile)
Expand All @@ -472,8 +486,8 @@ getExtraConfigs stackRoot = liftIO $ do
maybe (return Nothing) (fmap Just . parseAbsFile)
$ lookup "STACK_GLOBAL_CONFIG" env
filterM fileExists
$ fromMaybe (stackRoot </> stackDotYaml) mstackConfig
: maybe [] return (mstackGlobalConfig <|> defaultStackGlobalConfig)
$ fromMaybe userConfigPath mstackConfig
: maybe [] return (mstackGlobalConfig <|> defaultStackGlobalConfigPath)

-- | Load and parse YAML from the given file.
loadYaml :: (FromJSON (a, [JSONWarning]), MonadIO m, MonadLogger m) => Path Abs File -> m a
Expand Down Expand Up @@ -542,5 +556,46 @@ loadProjectConfig mstackYaml = do
ProjectAndConfigMonoid project config <- loadYaml fp
return $ Just (project, fp, config)

-- | Get the location of the default stack configuration file.
-- If a file already exists at the deprecated location, its location is returned.
-- Otherwise, the new location is returned.
getDefaultGlobalConfigPath
:: (MonadIO m, MonadLogger m)
=> m (Maybe (Path Abs File))
getDefaultGlobalConfigPath =
case (defaultGlobalConfigPath, defaultGlobalConfigPathDeprecated) of
(Just new,Just old) ->
liftM (Just . fst ) $
tryDeprecatedPath
(Just "non-project global configuration file")
fileExists
new
old
(Just new,Nothing) -> return (Just new)
_ -> return Nothing

-- | Get the location of the default user configuration file.
-- If a file already exists at the deprecated location, its location is returned.
-- Otherwise, the new location is returned.
getDefaultUserConfigPath
:: (MonadIO m, MonadLogger m)
=> Path Abs Dir -> m (Path Abs File)
getDefaultUserConfigPath stackRoot = do
(path, exists) <- tryDeprecatedPath
(Just "non-project configuration file")
fileExists
(defaultUserConfigPath stackRoot)
(defaultUserConfigPathDeprecated stackRoot)
unless exists $ do
createTree (parent path)
liftIO $ S.writeFile (toFilePath path) $
"# This file contains default non-project-specific settings for 'stack', used\n" <>
"# in all projects. For more information about stack's configuration, see\n" <>
"# https://github.com/commercialhaskell/stack/blob/release/doc/yaml_configuration.md\n" <>
"#\n" <>
Yaml.encode (mempty :: Object)
return path


packagesParser :: Parser [String]
packagesParser = many (strOption (long "package" <> help "Additional packages that must be installed"))
46 changes: 37 additions & 9 deletions src/Stack/Constants.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ module Stack.Constants
,stackProgName
,wiredInPackages
,cabalPackageName
,implicitGlobalDir
,implicitGlobalProjectDirDeprecated
,implicitGlobalProjectDir
,hpcRelativeDir
,hpcDirFromDir
,dotHpc
,objectInterfaceDir
,templatesDir
,globalConfigPath
,defaultUserConfigPathDeprecated
,defaultUserConfigPath
,defaultGlobalConfigPathDeprecated
,defaultGlobalConfigPath
)
where

Expand Down Expand Up @@ -285,17 +289,41 @@ cabalPackageName :: PackageName
cabalPackageName =
$(mkPackageName "Cabal")

-- | Implicit global directory used when outside of a project.
implicitGlobalDir :: Path Abs Dir -- ^ Stack root.
-> Path Abs Dir
implicitGlobalDir p =
-- | Deprecated implicit global project directory used when outside of a project.
implicitGlobalProjectDirDeprecated :: Path Abs Dir -- ^ Stack root.
-> Path Abs Dir
implicitGlobalProjectDirDeprecated p =
p </>
$(mkRelDir "global")

-- | Implicit global project directory used when outside of a project.
-- Normally, @getImplicitGlobalProjectDir@ should be used instead.
implicitGlobalProjectDir :: Path Abs Dir -- ^ Stack root.
-> Path Abs Dir
implicitGlobalProjectDir p =
p </>
$(mkRelDir "global-project")

-- | Where .mix files go.
dotHpc :: Path Rel Dir
dotHpc = $(mkRelDir ".hpc")

-- | Global config path.
globalConfigPath :: Config -> Path Abs File
globalConfigPath = (</> $(mkRelFile "stack.yaml")) . configStackRoot
-- | Deprecated default global config path.
defaultUserConfigPathDeprecated :: Path Abs Dir -> Path Abs File
defaultUserConfigPathDeprecated = (</> $(mkRelFile "stack.yaml"))

-- | Default global config path.
-- Normally, @getDefaultUserConfigPath@ should be used instead.
defaultUserConfigPath :: Path Abs Dir -> Path Abs File
defaultUserConfigPath = (</> $(mkRelFile "config.yaml"))

-- | Deprecated default global config path.
-- Note that this will be @Nothing@ on Windows, which is by design.
defaultGlobalConfigPathDeprecated :: Maybe (Path Abs File)
defaultGlobalConfigPathDeprecated = parseAbsFile "/etc/stack/config"

-- | Default global config path.
-- Normally, @getDefaultGlobalConfigPath@ should be used instead.
-- Note that this will be @Nothing@ on Windows, which is by design.
defaultGlobalConfigPath :: Maybe (Path Abs File)
defaultGlobalConfigPath = parseAbsFile "/etc/stack/config.yaml"
Loading