stack 2.1.1.1 → 2.1.3
raw patch · 26 files changed
+1631/−1356 lines, 26 filesdep +pantrydep −pantry-tmpdep ~Cabaldep ~QuickCheckdep ~aeson
Dependencies added: pantry
Dependencies removed: pantry-tmp
Dependency ranges changed: Cabal, QuickCheck, aeson, annotated-wl-pprint, ansi-terminal, array, async, attoparsec, base64-bytestring, bytestring, colour, conduit, conduit-extra, containers, cryptonite, cryptonite-conduit, deepseq, directory, echo, exceptions, extra, file-embed, filelock, filepath, fsnotify, generic-deriving, githash, hackage-security, hashable, hi-file-parser, hpack, hpc, hspec, http-client, http-client-tls, http-conduit, http-download, http-types, memory, microlens, mintty, mono-traversable, mtl, mustache, neat-interpolation, network-uri, open-browser, optparse-applicative, optparse-generic, optparse-simple, path, path-io, persistent, persistent-sqlite, persistent-template, pretty, primitive, process, project-template, raw-strings-qq, regex-applicative-text, resource-pool, resourcet, retry, rio, rio-prettyprint, semigroups, smallcheck, split, stm, streaming-commons, tar, template-haskell, temporary, terminal-size, text, text-metrics, th-reify-many, time, tls, transformers, typed-process, unicode-transforms, unix, unix-compat, unliftio, unordered-containers, vector, yaml, zip-archive, zlib
Files
- ChangeLog.md +69/−0
- doc/ChangeLog.md +69/−0
- doc/GUIDE.md +1/−1
- doc/README.md +8/−0
- doc/docker_integration.md +4/−2
- doc/install_and_upgrade.md +4/−10
- doc/yaml_configuration.md +5/−1
- src/Stack/Build/Cache.hs +31/−24
- src/Stack/Build/Execute.hs +35/−12
- src/Stack/Config.hs +23/−13
- src/Stack/Docker.hs +1/−1
- src/Stack/Lock.hs +1/−1
- src/Stack/Nix.hs +7/−7
- src/Stack/Options/DotParser.hs +1/−1
- src/Stack/Package.hs +2/−2
- src/Stack/Prelude.hs +4/−4
- src/Stack/Runners.hs +1/−9
- src/Stack/Setup.hs +5/−5
- src/Stack/Storage.hs +0/−570
- src/Stack/Storage/Project.hs +215/−0
- src/Stack/Storage/User.hs +351/−0
- src/Stack/Storage/Util.hs +69/−0
- src/Stack/Types/Config.hs +21/−10
- src/test/Stack/ConfigSpec.hs +3/−3
- stack.cabal +687/−680
- test/integration/lib/StackTest.hs +14/−0
@@ -1,6 +1,66 @@ # Changelog +## v2.1.3++**Changes since v2.1.1**++Behavior changes:++* Disable WAL mode for SQLite3 databases, to improve compatibility with+ some platforms and filesystems. See+ [#4876](https://github.com/commercialhaskell/stack/issues/4876).++* By default, do not perform expiry checks in Hackage Security. See+ [#4928](https://github.com/commercialhaskell/stack/issues/4928).++Other enhancements:++* Do not rerun expected test failures. This is mostly a change that+ will only affect the Stackage Curator use case, but there is now an+ additional message letting the user know when a previously-failed+ test case is being rerun.++* Move configure information for local packages back to .stack-work to+ improve caching. See+ [#4893](https://github.com/commercialhaskell/stack/issues/4893).++Bug fixes:++* Fix to allow dependencies on specific versions of local git repositories. See+ [#4862](https://github.com/commercialhaskell/stack/pull/4862)++* Allow Stack commands to be run in Nix mode without having a project file+ available. See+ [#4854](https://github.com/commercialhaskell/stack/issues/4864).++* Removes dependency on gnu-tar for OSX and Linux environment. The+ `--force-local` option was required only for windows environment.++* Properly wait for the `tar` subprocess to complete before returning, thereby+ avoiding a SIGTERM screwing up GHC installation. See+ [#4888](https://github.com/commercialhaskell/stack/issues/4888).++* Use package complete locations from lock files when resolving dependencies+ in `extra-deps`. See+ [#4887](https://github.com/commercialhaskell/stack/issues/4887).++* Set the `HASKELL_DIST_DIR` environment to a proper package dist+ directory so `doctest` is able to load modules autogenerated by Cabal.++* Expose package library when running tests.++* Fix support for non-ASCII module names. See+ [4938](https://github.com/commercialhaskell/stack/issues/4938)++Other changes:++* Rename `pantry-tmp` package back to `pantry`, now that we have gained+ maintainership (which had been used by someone else for a candidate-only test+ that made it look like the name was free but prevented uploading a real+ package).++ ## v2.1.1.1 Hackage-only release that removes `stack.yaml` from the sdist. This is because@@ -16,6 +76,15 @@ ## v2.1.1++The Stack 2 release represents a series of significant changes to how Stack+works internally. For the vast majority of cases, these changes are backwards+compatible, in that existing projects will continue to build in the same way+with Stack 2 as they did with Stack 1. The large version bump is due to the+fundamental internal changes to cache handling, database storage (using SQLite+in place of binary files), implicit snapshots (which greatly improve the+precompiled cache), and moving to Pantry. We have also removed some less used+features, as listed below. **Changes since v1.9.3**
@@ -1,6 +1,66 @@ # Changelog +## v2.1.3++**Changes since v2.1.1**++Behavior changes:++* Disable WAL mode for SQLite3 databases, to improve compatibility with+ some platforms and filesystems. See+ [#4876](https://github.com/commercialhaskell/stack/issues/4876).++* By default, do not perform expiry checks in Hackage Security. See+ [#4928](https://github.com/commercialhaskell/stack/issues/4928).++Other enhancements:++* Do not rerun expected test failures. This is mostly a change that+ will only affect the Stackage Curator use case, but there is now an+ additional message letting the user know when a previously-failed+ test case is being rerun.++* Move configure information for local packages back to .stack-work to+ improve caching. See+ [#4893](https://github.com/commercialhaskell/stack/issues/4893).++Bug fixes:++* Fix to allow dependencies on specific versions of local git repositories. See+ [#4862](https://github.com/commercialhaskell/stack/pull/4862)++* Allow Stack commands to be run in Nix mode without having a project file+ available. See+ [#4854](https://github.com/commercialhaskell/stack/issues/4864).++* Removes dependency on gnu-tar for OSX and Linux environment. The+ `--force-local` option was required only for windows environment.++* Properly wait for the `tar` subprocess to complete before returning, thereby+ avoiding a SIGTERM screwing up GHC installation. See+ [#4888](https://github.com/commercialhaskell/stack/issues/4888).++* Use package complete locations from lock files when resolving dependencies+ in `extra-deps`. See+ [#4887](https://github.com/commercialhaskell/stack/issues/4887).++* Set the `HASKELL_DIST_DIR` environment to a proper package dist+ directory so `doctest` is able to load modules autogenerated by Cabal.++* Expose package library when running tests.++* Fix support for non-ASCII module names. See+ [4938](https://github.com/commercialhaskell/stack/issues/4938)++Other changes:++* Rename `pantry-tmp` package back to `pantry`, now that we have gained+ maintainership (which had been used by someone else for a candidate-only test+ that made it look like the name was free but prevented uploading a real+ package).++ ## v2.1.1.1 Hackage-only release that removes `stack.yaml` from the sdist. This is because@@ -16,6 +76,15 @@ ## v2.1.1++The Stack 2 release represents a series of significant changes to how Stack+works internally. For the vast majority of cases, these changes are backwards+compatible, in that existing projects will continue to build in the same way+with Stack 2 as they did with Stack 1. The large version bump is due to the+fundamental internal changes to cache handling, database storage (using SQLite+in place of binary files), implicit snapshots (which greatly improve the+precompiled cache), and moving to Pantry. We have also removed some less used+features, as listed below. **Changes since v1.9.3**
@@ -410,7 +410,7 @@ ``` dependencies:-- base >= 4.7 && 5+- base >= 4.7 && < 5 - text - filepath - containers
@@ -38,6 +38,14 @@ installation instructions in the [install and upgrade guide](install_and_upgrade.md). +#### How to upgrade++If you already have `stack` installed, upgrade it to the latest version+by running:++ stack upgrade++ #### Quick Start Guide First you need to [install it (see previous section)](#how-to-install).
@@ -229,8 +229,10 @@ - "BAR=BAZ QUUX" # Location of a Docker container-compatible 'stack' executable with the- # matching version. This executable must be built on linux-x86_64 and- # statically linked.+ # matching version. This executable must be compatible with the Docker+ # image in terms of platform (linux-x86_64) and shared libraries+ # (statically linked is best, otherwise the image needs to have the+ # same shared libraries installed). # Valid values are: # host: use the host's executable. This is the default when the host's # executable is known to work (e.g., from official linux-x86_64 bindist)
@@ -24,7 +24,7 @@ Binary packages are signed with this [signing key](SIGNING_KEY.md). If you are writing a script that needs to download the latest binary, you can-use URLs like `https://get.haskellstack.org/stable/<PLATFORM>.<EXTENSION>` (e.g. https://get.haskellstack.org/stable/linux-x86_64.tar.gz) that always point to the latest stable release.+use URLs like `https://get.haskellstack.org/stable/<PLATFORM>.<EXTENSION>` (e.g. https://get.haskellstack.org/stable/linux-x86_64-static.tar.gz) that always point to the latest stable release. ## Windows @@ -238,17 +238,11 @@ * Download the latest release: - * [Linux 64-bit, standard](https://get.haskellstack.org/stable/linux-x86_64.tar.gz)-- * [Linux 64-bit, libgmp4](https://get.haskellstack.org/stable/linux-x86_64-gmp4.tar.gz)- (if you are on an older 64-bit distribution that only includes libgmp4- (libgmp.so.3), such as CentOS/RHEL/Amazon Linux 6.)+ * [Linux 64-bit, static](https://get.haskellstack.org/stable/linux-x86_64-static.tar.gz) * [Linux 32-bit, standard](https://get.haskellstack.org/stable/linux-i386.tar.gz)-- * [Linux 32-bit, libgmp4](https://get.haskellstack.org/stable/linux-i386-gmp4.tar.gz)- (if you are on an older 32-bit distribution that only includes libgmp4- (libgmp.so.3), such as CentOS/RHEL/Amazon Linux 6.)+ (note: requires libgmp.so.10, and will not work on some older+ distributions that have libgmp.so.3, such as CentOS 6) * [Linux ARMv7](https://get.haskellstack.org/stable/linux-arm.tar.gz)
@@ -337,12 +337,16 @@ key-threshold: 3 # number of keys required # ignore expiration date, see https://github.com/commercialhaskell/stack/pull/4614- ignore-expiry: no+ ignore-expiry: true ``` If you provide a replacement index which does not mirror Hackage, it is likely that you'll end up with significant breakage, such as most snapshots failing to work.++Note: since Stack v2.1.3, `ignore-expiry` was changed to `true` by+default. For more information on this change, see [issue+#4928](https://github.com/commercialhaskell/stack/issues/4928). ### system-ghc
@@ -20,9 +20,9 @@ , writeBuildCache , writeConfigCache , writeCabalMod- , setTestSuccess- , unsetTestSuccess- , checkTestSuccess+ , TestStatus (..)+ , setTestStatus+ , getTestStatus , writePrecompiledCache , readPrecompiledCache -- Exported for testing@@ -41,7 +41,8 @@ import Path.IO import Stack.Constants import Stack.Constants.Config-import Stack.Storage+import Stack.Storage.Project+import Stack.Storage.User import Stack.Types.Build import Stack.Types.Cache import Stack.Types.Config@@ -207,36 +208,42 @@ key <- flagCacheKey gid saveConfigCache key cache -successBS, failureBS :: IsString s => s+successBS, failureBS, unknownBS :: IsString s => s successBS = "success" failureBS = "failure"+unknownBS = "unknown" --- | Mark a test suite as having succeeded-setTestSuccess :: HasEnvConfig env- => Path Abs Dir- -> RIO env ()-setTestSuccess dir = do- fp <- testSuccessFile dir- writeBinaryFileAtomic fp successBS+-- | Status of a test suite+data TestStatus = TSSuccess | TSFailure | TSUnknown --- | Mark a test suite as not having succeeded-unsetTestSuccess :: HasEnvConfig env- => Path Abs Dir- -> RIO env ()-unsetTestSuccess dir = do+-- | Mark test suite status+setTestStatus :: HasEnvConfig env+ => Path Abs Dir+ -> TestStatus+ -> RIO env ()+setTestStatus dir status = do fp <- testSuccessFile dir- writeBinaryFileAtomic fp failureBS+ writeBinaryFileAtomic fp $+ case status of+ TSSuccess -> successBS+ TSFailure -> failureBS+ TSUnknown -> unknownBS -- | Check if the test suite already passed-checkTestSuccess :: HasEnvConfig env- => Path Abs Dir- -> RIO env Bool-checkTestSuccess dir = do+getTestStatus :: HasEnvConfig env+ => Path Abs Dir+ -> RIO env TestStatus+getTestStatus dir = do fp <- testSuccessFile dir -- we could ensure the file is the right size first, -- but we're not expected an attack from the user's filesystem- either (const False) (== successBS)- <$> tryIO (readFileBinary $ toFilePath fp)+ eres <- tryIO (readFileBinary $ toFilePath fp)+ pure $+ case eres of+ Right bs+ | bs == successBS -> TSSuccess+ | bs == failureBS -> TSFailure+ _ -> TSUnknown -------------------------------------- -- Precompiled Cache
@@ -1597,7 +1597,7 @@ markExeNotInstalled (taskLocation task) taskProvides case taskType of TTLocalMutable lp -> do- when enableTests $ unsetTestSuccess pkgDir+ when enableTests $ setTestStatus pkgDir TSUnknown caches <- runMemoizedWith $ lpNewBuildCaches lp mapM_ (uncurry (writeBuildCache pkgDir)) (Map.toList caches)@@ -1656,7 +1656,7 @@ ec <- withWorkingDir (toFilePath eeTempDir) $ proc "haddock" ["--hyperlinked-source"]- $ \pc -> withProcess+ $ \pc -> withProcessWait (setStdout createSource $ setStderr createSource pc) $ \p -> runConcurrently $ Concurrently (runConduit $ getStdout p .| CL.sinkNull)@@ -1886,12 +1886,19 @@ else if toRerunTests topts then return True else do- success <- checkTestSuccess pkgDir- if success- then do- unless (null testsToRun) $ announce "skipping already passed test"- return False- else return True+ status <- getTestStatus pkgDir+ case status of+ TSSuccess -> do+ unless (null testsToRun) $ announce "skipping already passed test"+ return False+ TSFailure+ | expectFailure -> do+ announce "skipping already failed test that's expected to fail"+ return False+ | otherwise -> do+ announce "rerunning previously failed test"+ return True+ TSUnknown -> return True when toRun $ do buildDir <- distDirFromDir pkgDir@@ -1920,6 +1927,18 @@ tixPath <- liftM (pkgDir </>) $ parseRelFile $ exeName ++ ".tix" exePath <- liftM (buildDir </>) $ parseRelFile $ "build/" ++ testName' ++ "/" ++ exeName exists <- doesFileExist exePath+ -- in Stack.Package.packageFromPackageDescription we filter out+ -- package itself of any dependencies so any tests requiring loading+ -- of their own package library will fail+ -- so to prevent this we return it back here but unfortunately unconditionally+ installed <- case Map.lookup pname installedMap of+ Just (_, installed) -> pure $ Just installed+ Nothing -> do+ idMap <- liftIO $ readTVarIO (eeGhcPkgIds ee)+ pure $ Map.lookup (taskProvides task) idMap+ let pkgGhcIdList = case installed of+ Just (Library _ ghcPkgId _) -> [ghcPkgId]+ _ -> [] -- doctest relies on template-haskell in QuickCheck-based tests thGhcId <- case find ((== "template-haskell") . pkgName . dpPackageIdent. snd) (Map.toList $ eeGlobalDumpPkgs ee) of@@ -1928,7 +1947,10 @@ -- env variable GHC_ENVIRONMENT is set for doctest so module names for -- packages with proper dependencies should no longer get ambiguous -- see e.g. https://github.com/doctest/issues/119+ -- also we set HASKELL_DIST_DIR to a package dist directory so+ -- doctest will be able to load modules autogenerated by Cabal let setEnv f pc = modifyEnvVars pc $ \envVars ->+ Map.insert "HASKELL_DIST_DIR" (T.pack $ toFilePath buildDir) $ Map.insert "GHC_ENVIRONMENT" (T.pack f) envVars fp = toFilePath $ eeTempDir ee </> testGhcEnvRelFile snapDBPath = toFilePathNoTrailingSep (bcoSnapDB $ eeBaseConfigOpts ee)@@ -1939,7 +1961,7 @@ "package-db " <> fromString snapDBPath <> "\n" <> "package-db " <> fromString localDBPath <> "\n" <> foldMap (\ghcId -> "package-id " <> RIO.display (unGhcPkgId ghcId) <> "\n")- (thGhcId:M.elems allDepsMap)+ (pkgGhcIdList ++ thGhcId:M.elems allDepsMap) writeFileUtf8Builder fp ghcEnv menv <- liftIO $ setEnv fp =<< configProcessContextSettings config EnvSettings { esIncludeLocals = taskLocation task == Local@@ -2004,7 +2026,7 @@ $ setStdout output $ setStderr output pc0- withProcess pc $ \p -> do+ withProcessWait pc $ \p -> do case (getStdout p, getStderr p) of (Nothing, Nothing) -> pure () (Just x, Just y) -> concurrently_ x y@@ -2058,7 +2080,8 @@ hClose h S.readFile $ toFilePath logFile - unless (Map.null errs || expectFailure) $ throwM $ TestSuiteFailure+ let succeeded = Map.null errs+ unless (succeeded || expectFailure) $ throwM $ TestSuiteFailure (taskProvides task) errs (case outputType of@@ -2066,7 +2089,7 @@ OTConsole _ -> Nothing) bs - setTestSuccess pkgDir+ setTestStatus pkgDir $ if succeeded then TSSuccess else TSFailure -- | Implements running a package's benchmarks. singleBench :: HasEnvConfig env
@@ -29,7 +29,7 @@ ,getInNixShell ,defaultConfigYaml ,getProjectConfig- ,loadBuildConfig+ ,withBuildConfig ) where import Control.Monad.Extra (firstJustM)@@ -64,7 +64,8 @@ import Stack.Constants import Stack.Build.Haddock (shouldHaddockDeps) import Stack.Lock (lockCachedWanted)-import Stack.Storage (initStorage)+import Stack.Storage.Project (initProjectStorage)+import Stack.Storage.User (initUserStorage) import Stack.SourceMap import Stack.Types.Build import Stack.Types.Compiler@@ -373,9 +374,9 @@ hsc (maybe HpackBundled HpackCommand $ getFirst configMonoidOverrideHpack) clConnectionCount- (\configPantryConfig -> initStorage+ (\configPantryConfig -> initUserStorage (configStackRoot </> relFileStorage)- (\configStorage -> inner Config {..}))+ (\configUserStorage -> inner Config {..})) -- | Get the default location of the local programs directory. getDefaultLocalProgramsBase :: MonadThrow m@@ -448,8 +449,10 @@ -- | Load the build configuration, adds build-specific values to config loaded by @loadConfig@. -- values.-loadBuildConfig :: RIO Config BuildConfig-loadBuildConfig = do+withBuildConfig+ :: RIO BuildConfig a+ -> RIO Config a+withBuildConfig inner = do config <- ask -- If provided, turn the AbstractResolver from the command line@@ -526,13 +529,20 @@ wanted <- lockCachedWanted stackYamlFP (projectResolver project) $ fillProjectWanted stackYamlFP config project - return BuildConfig- { bcConfig = config- , bcSMWanted = wanted- , bcExtraPackageDBs = extraPackageDBs- , bcStackYaml = stackYamlFP- , bcCurator = projectCurator project- }+ -- Unfortunately redoes getProjectWorkDir, since we don't have a BuildConfig yet+ workDir <- view workDirL+ let projectStorageFile = parent stackYamlFP </> workDir </> relFileStorage++ initProjectStorage projectStorageFile $ \projectStorage -> do+ let bc = BuildConfig+ { bcConfig = config+ , bcSMWanted = wanted+ , bcExtraPackageDBs = extraPackageDBs+ , bcStackYaml = stackYamlFP+ , bcCurator = projectCurator project+ , bcProjectStorage = projectStorage+ }+ runRIO bc inner where getEmptyProject :: Maybe RawSnapshotLocation -> [PackageIdentifierRevision] -> RIO Config Project getEmptyProject mresolver extraDeps = do
@@ -49,7 +49,7 @@ import Stack.Constants import Stack.Constants.Config import Stack.Setup (ensureDockerStackExe)-import Stack.Storage (loadDockerImageExeCache,saveDockerImageExeCache)+import Stack.Storage.User (loadDockerImageExeCache,saveDockerImageExeCache) import Stack.Types.Version import Stack.Types.Config import Stack.Types.Docker
@@ -121,7 +121,7 @@ loadAndCompleteSnapshotRaw resolver slocCache pkgLocCache let compiler = snapshotCompiler snap snPkgs = Map.mapWithKey (\n p h -> snapToDepPackage h n p) (snapshotPackages snap)- (wanted, prjCompleted) <- fillWanted Map.empty compiler snPkgs+ (wanted, prjCompleted) <- fillWanted pkgLocCache compiler snPkgs let lockLocations = map (\(CompletedPLI r c) -> LockedLocation r c) differentSnapLocs (CompletedSL raw complete) | raw == toRawSL complete = Nothing
@@ -18,13 +18,12 @@ import Lens.Micro (set) import Path.IO import qualified Paths_stack as Meta-import Stack.Config (getInContainer, loadBuildConfig)+import Stack.Config (getInContainer, withBuildConfig) import Stack.Config.Nix (nixCompiler) import Stack.Constants (platformVariantEnvVar,inNixShellEnvVar,inContainerEnvVar) import Stack.Types.Config import Stack.Types.Docker import Stack.Types.Nix-import Stack.Docker (getProjectRoot) import System.Environment (getArgs,getExecutablePath,lookupEnv) import qualified System.FilePath as F import RIO.Process (processContextL, exec)@@ -43,18 +42,19 @@ local (set processContextL envOverride) $ do let cmnd = escape exePath args' = map escape args- projectRoot <- getProjectRoot- mshellFile <-- traverse (resolveFile projectRoot) $- nixInitFile (configNix config) + mshellFile <- case configProjectRoot config of+ Just projectRoot ->+ traverse (resolveFile projectRoot) $ nixInitFile (configNix config)+ Nothing -> pure Nothing+ -- This will never result in double loading the build config, since: -- -- 1. This function explicitly takes a Config, not a HasConfig -- -- 2. This function ends up exiting before running other code -- (thus the void return type)- compilerVersion <- view wantedCompilerVersionL <$> loadBuildConfig+ compilerVersion <- withBuildConfig $ view wantedCompilerVersionL ghc <- either throwIO return $ nixCompiler compilerVersion let pkgsInConfig = nixPackages (configNix config)
@@ -20,7 +20,7 @@ DotOpts <$> includeExternal <*> includeBase <*> depthLimit- <*> fmap (maybe Set.empty Set.fromList . fmap splitNames) prunedPkgs+ <*> fmap (maybe Set.empty $ Set.fromList . splitNames) prunedPkgs <*> targetsParser <*> flagsParser <*> testTargets
@@ -27,7 +27,6 @@ ,applyForceCustomBuild ) where -import qualified Data.ByteString.Char8 as B8 import Data.List (find, isPrefixOf, unzip) import Data.Maybe (maybe) import qualified Data.Map.Strict as M@@ -1117,7 +1116,8 @@ ] pure (S.empty, []) Right iface -> do- let moduleNames = fmap (fromString . B8.unpack . fst) . Iface.unList . Iface.dmods . Iface.deps+ let moduleNames = fmap (fromString . T.unpack . decodeUtf8Lenient . fst) .+ Iface.unList . Iface.dmods . Iface.deps resolveFileDependency file = do resolved <- liftIO (forgivingAbsence (resolveFile dir file)) >>= rejectMissingFile when (isNothing resolved) $
@@ -40,7 +40,7 @@ import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL import Data.Conduit.Process.Typed (withLoggedProcess_, createSource, byteStringInput)-import RIO.Process (HasProcessContext (..), ProcessContext, setStdin, closed, getStderr, getStdout, proc, withProcess_, setStdout, setStderr, ProcessConfig, readProcess_, workingDirL)+import RIO.Process (HasProcessContext (..), ProcessContext, setStdin, closed, getStderr, getStdout, proc, withProcessWait_, setStdout, setStderr, ProcessConfig, readProcess_, workingDirL, waitExitCode) import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode) @@ -79,9 +79,9 @@ -- See https://github.com/commercialhaskell/stack/pull/4722 $ setStdin (byteStringInput "") pc0- withProcess_ pc $ \p ->- runConduit (getStderr p .| sinkStderr) `concurrently`- runConduit (getStdout p .| sinkStdout)+ withProcessWait_ pc $ \p ->+ (runConduit (getStderr p .| sinkStderr) `concurrently`+ runConduit (getStdout p .| sinkStdout)) <* waitExitCode p -- | Consume the stdout of a process feeding strict 'ByteString's to a consumer. -- If the process fails, spits out stdout and stderr as error log
@@ -29,7 +29,7 @@ import qualified Stack.Docker as Docker import qualified Stack.Nix as Nix import Stack.Setup-import Stack.Storage (upgradeChecksSince, logUpgradeCheck)+import Stack.Storage.User (upgradeChecksSince, logUpgradeCheck) import Stack.Types.Config import Stack.Types.Docker (dockerEnable) import Stack.Types.Nix (nixEnable)@@ -54,14 +54,6 @@ :: RIO EnvConfig a -> RIO Config a withDefaultEnvConfig = withEnvConfig AllowNoTargets defaultBuildOptsCLI---- | Upgrade a 'Config' environment to a 'BuildConfig' environment by--- performing further parsing of project-specific configuration. This--- is intended to be run inside a call to 'withConfig'.-withBuildConfig :: RIO BuildConfig a -> RIO Config a-withBuildConfig inner = do- bconfig <- loadBuildConfig- runRIO bconfig inner -- | Upgrade a 'Config' environment to an 'EnvConfig' environment by -- performing further parsing of project-specific configuration (like
@@ -81,7 +81,7 @@ import Stack.Prelude hiding (Display (..)) import Stack.SourceMap import Stack.Setup.Installed-import Stack.Storage (loadCompilerPaths, saveCompilerPaths)+import Stack.Storage.User (loadCompilerPaths, saveCompilerPaths) import Stack.Types.Build import Stack.Types.Compiler import Stack.Types.CompilerBuild@@ -504,10 +504,10 @@ if | cabalVersion < mkVersion [1, 19, 2] -> do- logWarn $ "Stack no longer supported Cabal versions below 1.19.2,"- logWarn $ "but version " <> fromString (versionString cabalVersion) <> "was found."+ logWarn $ "Stack no longer supports Cabal versions below 1.19.2,"+ logWarn $ "but version " <> fromString (versionString cabalVersion) <> " was found." logWarn "This invocation will most likely fail."- logWarn "To fix this, either use a newer version of Stack or a newer resolver"+ logWarn "To fix this, either use an older version of Stack or a newer resolver" logWarn "Acceptable resolvers: lts-3.0/nightly-2015-05-05 or later" | cabalVersion >= mkVersion [2, 5] -> logWarn $@@ -1561,7 +1561,7 @@ ec <- proc cmd args $ \pc -> if isExtract- then withProcess (setStdout createSource pc) $ \p -> do+ then withProcessWait (setStdout createSource pc) $ \p -> do total <- runConduit $ getStdout p .| filterCE (== 10) -- newline characters
@@ -1,570 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-identities #-}---- | Work with SQLite database used for caches.-module Stack.Storage- ( initStorage- , withStorage- , ConfigCacheKey- , configCacheKey- , loadConfigCache- , saveConfigCache- , deactiveConfigCache- , PrecompiledCacheKey- , precompiledCacheKey- , loadPrecompiledCache- , savePrecompiledCache- , loadDockerImageExeCache- , saveDockerImageExeCache- , loadCompilerPaths- , saveCompilerPaths- , upgradeChecksSince- , logUpgradeCheck- ) where--import qualified Data.ByteString as S-import qualified Data.Set as Set-import qualified Data.Text as T-import Data.Time.Clock (UTCTime)-import Database.Persist.Sql (SqlBackend)-import Database.Persist.Sqlite-import Database.Persist.TH-import Distribution.Text (simpleParse, display)-import Foreign.C.Types (CTime (..))-import qualified Pantry.Internal as SQLite-import Path-import Path.IO (resolveFile', resolveDir')-import qualified RIO.FilePath as FP-import Stack.Prelude hiding (MigrationFailure)-import Stack.Types.Build-import Stack.Types.Cache-import Stack.Types.Compiler-import Stack.Types.CompilerBuild (CompilerBuild)-import Stack.Types.Config (HasConfig, configL, configStorage, CompilerPaths (..), GhcPkgExe (..))-import Stack.Types.GhcPkgId-import System.Posix.Types (COff (..))-import System.PosixCompat.Files (getFileStatus, fileSize, modificationTime)--share [ mkPersist sqlSettings- , mkDeleteCascade sqlSettings- , mkMigrate "migrateAll"- ]- [persistLowerCase|-ConfigCacheParent sql="config_cache"- directory FilePath "default=(hex(randomblob(16)))"- type ConfigCacheType- pkgSrc CachePkgSrc- active Bool- pathEnvVar Text- haddock Bool default=0- UniqueConfigCacheParent directory type sql="unique_config_cache"- deriving Show--ConfigCacheDirOption- parent ConfigCacheParentId sql="config_cache_id"- index Int- value String sql="option"- UniqueConfigCacheDirOption parent index- deriving Show--ConfigCacheNoDirOption- parent ConfigCacheParentId sql="config_cache_id"- index Int- value String sql="option"- UniqueConfigCacheNoDirOption parent index- deriving Show--ConfigCacheDep- parent ConfigCacheParentId sql="config_cache_id"- value GhcPkgId sql="ghc_pkg_id"- UniqueConfigCacheDep parent value- deriving Show--ConfigCacheComponent- parent ConfigCacheParentId sql="config_cache_id"- value S.ByteString sql="component"- UniqueConfigCacheComponent parent value- deriving Show--PrecompiledCacheParent sql="precompiled_cache"- platformGhcDir FilePath "default=(hex(randomblob(16)))"- compiler Text- cabalVersion Text- packageKey Text- optionsHash ByteString- haddock Bool default=0- library FilePath Maybe- UniquePrecompiledCacheParent platformGhcDir compiler cabalVersion packageKey optionsHash haddock sql="unique_precompiled_cache"- deriving Show--PrecompiledCacheSubLib- parent PrecompiledCacheParentId sql="precompiled_cache_id"- value FilePath sql="sub_lib"- UniquePrecompiledCacheSubLib parent value- deriving Show--PrecompiledCacheExe- parent PrecompiledCacheParentId sql="precompiled_cache_id"- value FilePath sql="exe"- UniquePrecompiledCacheExe parent value- deriving Show--DockerImageExeCache- imageHash Text- exePath FilePath- exeTimestamp UTCTime- compatible Bool- DockerImageExeCacheUnique imageHash exePath exeTimestamp- deriving Show--CompilerCache- actualVersion ActualCompiler- arch Text-- -- Include ghc executable size and modified time for sanity checking entries- ghcPath FilePath- ghcSize Int64- ghcModified Int64-- ghcPkgPath FilePath- runghcPath FilePath- haddockPath FilePath-- cabalVersion Text- globalDb FilePath- globalDbCacheSize Int64- globalDbCacheModified Int64- info ByteString-- -- This is the ugliest part of this table, simply storing a Show/Read version of the- -- data. We could do a better job with normalized data and proper table structure.- -- However, recomputing this value in the future if the data representation changes- -- is very cheap, so we'll take the easy way out for now.- globalDump Text-- UniqueCompilerInfo ghcPath---- Last time certain actions were performed-LastPerformed- action Action- timestamp UTCTime- UniqueAction action-|]---- | Initialize the database.-initStorage ::- HasLogFunc env- => Path Abs File -- ^ storage file- -> (SQLite.Storage -> RIO env a)- -> RIO env a-initStorage = SQLite.initStorage "Stack" migrateAll---- | Run an action in a database transaction-withStorage ::- (HasConfig env, HasLogFunc env)- => ReaderT SqlBackend (RIO env) a- -> RIO env a-withStorage inner =- flip SQLite.withStorage_ inner =<< view (configL . to configStorage)---- | Key used to retrieve configuration or flag cache-type ConfigCacheKey = Unique ConfigCacheParent---- | Build key used to retrieve configuration or flag cache-configCacheKey :: Path Abs Dir -> ConfigCacheType -> ConfigCacheKey-configCacheKey dir = UniqueConfigCacheParent (toFilePath dir)---- | Internal helper to read the 'ConfigCache'-readConfigCache ::- (HasConfig env, HasLogFunc env)- => Entity ConfigCacheParent- -> ReaderT SqlBackend (RIO env) ConfigCache-readConfigCache (Entity parentId ConfigCacheParent {..}) = do- let configCachePkgSrc = configCacheParentPkgSrc- coDirs <-- map (configCacheDirOptionValue . entityVal) <$>- selectList- [ConfigCacheDirOptionParent ==. parentId]- [Asc ConfigCacheDirOptionIndex]- coNoDirs <-- map (configCacheNoDirOptionValue . entityVal) <$>- selectList- [ConfigCacheNoDirOptionParent ==. parentId]- [Asc ConfigCacheNoDirOptionIndex]- let configCacheOpts = ConfigureOpts {..}- configCacheDeps <-- Set.fromList . map (configCacheDepValue . entityVal) <$>- selectList [ConfigCacheDepParent ==. parentId] []- configCacheComponents <-- Set.fromList . map (configCacheComponentValue . entityVal) <$>- selectList [ConfigCacheComponentParent ==. parentId] []- let configCachePathEnvVar = configCacheParentPathEnvVar- let configCacheHaddock = configCacheParentHaddock- return ConfigCache {..}---- | Load 'ConfigCache' from the database.-loadConfigCache ::- (HasConfig env, HasLogFunc env)- => ConfigCacheKey- -> RIO env (Maybe ConfigCache)-loadConfigCache key =- withStorage $ do- mparent <- getBy key- case mparent of- Nothing -> return Nothing- Just parentEntity@(Entity _ ConfigCacheParent {..})- | configCacheParentActive ->- Just <$> readConfigCache parentEntity- | otherwise -> return Nothing---- | Insert or update 'ConfigCache' to the database.-saveConfigCache ::- (HasConfig env, HasLogFunc env)- => ConfigCacheKey- -> ConfigCache- -> RIO env ()-saveConfigCache key@(UniqueConfigCacheParent dir type_) new =- withStorage $ do- mparent <- getBy key- (parentId, mold) <-- case mparent of- Nothing ->- (, Nothing) <$>- insert- ConfigCacheParent- { configCacheParentDirectory = dir- , configCacheParentType = type_- , configCacheParentPkgSrc = configCachePkgSrc new- , configCacheParentActive = True- , configCacheParentPathEnvVar = configCachePathEnvVar new- , configCacheParentHaddock = configCacheHaddock new- }- Just parentEntity@(Entity parentId _) -> do- old <- readConfigCache parentEntity- update- parentId- [ ConfigCacheParentPkgSrc =. configCachePkgSrc new- , ConfigCacheParentActive =. True- , ConfigCacheParentPathEnvVar =. configCachePathEnvVar new- ]- return (parentId, Just old)- updateList- ConfigCacheDirOption- ConfigCacheDirOptionParent- parentId- ConfigCacheDirOptionIndex- (maybe [] (coDirs . configCacheOpts) mold)- (coDirs $ configCacheOpts new)- updateList- ConfigCacheNoDirOption- ConfigCacheNoDirOptionParent- parentId- ConfigCacheNoDirOptionIndex- (maybe [] (coNoDirs . configCacheOpts) mold)- (coNoDirs $ configCacheOpts new)- updateSet- ConfigCacheDep- ConfigCacheDepParent- parentId- ConfigCacheDepValue- (maybe Set.empty configCacheDeps mold)- (configCacheDeps new)- updateSet- ConfigCacheComponent- ConfigCacheComponentParent- parentId- ConfigCacheComponentValue- (maybe Set.empty configCacheComponents mold)- (configCacheComponents new)---- | Mark 'ConfigCache' as inactive in the database.--- We use a flag instead of deleting the records since, in most cases, the same--- cache will be written again within in a few seconds (after--- `cabal configure`), so this avoids unnecessary database churn.-deactiveConfigCache :: HasConfig env => ConfigCacheKey -> RIO env ()-deactiveConfigCache (UniqueConfigCacheParent dir type_) =- withStorage $- updateWhere- [ConfigCacheParentDirectory ==. dir, ConfigCacheParentType ==. type_]- [ConfigCacheParentActive =. False]---- | Key used to retrieve the precompiled cache-type PrecompiledCacheKey = Unique PrecompiledCacheParent---- | Build key used to retrieve the precompiled cache-precompiledCacheKey ::- Path Rel Dir- -> ActualCompiler- -> Version- -> Text- -> ByteString- -> Bool- -> PrecompiledCacheKey-precompiledCacheKey platformGhcDir compiler cabalVersion =- UniquePrecompiledCacheParent- (toFilePath platformGhcDir)- (compilerVersionText compiler)- (T.pack $ versionString cabalVersion)---- | Internal helper to read the 'PrecompiledCache' from the database-readPrecompiledCache ::- (HasConfig env, HasLogFunc env)- => PrecompiledCacheKey- -> ReaderT SqlBackend (RIO env) (Maybe ( PrecompiledCacheParentId- , PrecompiledCache Rel))-readPrecompiledCache key = do- mparent <- getBy key- forM mparent $ \(Entity parentId PrecompiledCacheParent {..}) -> do- pcLibrary <- mapM parseRelFile precompiledCacheParentLibrary- pcSubLibs <-- mapM (parseRelFile . precompiledCacheSubLibValue . entityVal) =<<- selectList [PrecompiledCacheSubLibParent ==. parentId] []- pcExes <-- mapM (parseRelFile . precompiledCacheExeValue . entityVal) =<<- selectList [PrecompiledCacheExeParent ==. parentId] []- return (parentId, PrecompiledCache {..})---- | Load 'PrecompiledCache' from the database.-loadPrecompiledCache ::- (HasConfig env, HasLogFunc env)- => PrecompiledCacheKey- -> RIO env (Maybe (PrecompiledCache Rel))-loadPrecompiledCache key = withStorage $ fmap snd <$> readPrecompiledCache key---- | Insert or update 'PrecompiledCache' to the database.-savePrecompiledCache ::- (HasConfig env, HasLogFunc env)- => PrecompiledCacheKey- -> PrecompiledCache Rel- -> RIO env ()-savePrecompiledCache key@(UniquePrecompiledCacheParent precompiledCacheParentPlatformGhcDir precompiledCacheParentCompiler precompiledCacheParentCabalVersion precompiledCacheParentPackageKey precompiledCacheParentOptionsHash precompiledCacheParentHaddock) new =- withStorage $ do- let precompiledCacheParentLibrary = fmap toFilePath (pcLibrary new)- mIdOld <- readPrecompiledCache key- (parentId, mold) <-- case mIdOld of- Nothing -> (, Nothing) <$> insert PrecompiledCacheParent {..}- Just (parentId, old) -> do- update- parentId- [ PrecompiledCacheParentLibrary =.- precompiledCacheParentLibrary- ]- return (parentId, Just old)- updateSet- PrecompiledCacheSubLib- PrecompiledCacheSubLibParent- parentId- PrecompiledCacheSubLibValue- (maybe Set.empty (toFilePathSet . pcSubLibs) mold)- (toFilePathSet $ pcSubLibs new)- updateSet- PrecompiledCacheExe- PrecompiledCacheExeParent- parentId- PrecompiledCacheExeValue- (maybe Set.empty (toFilePathSet . pcExes) mold)- (toFilePathSet $ pcExes new)- where- toFilePathSet = Set.fromList . map toFilePath---- | Get the record of whether an executable is compatible with a Docker image-loadDockerImageExeCache ::- (HasConfig env, HasLogFunc env)- => Text- -> Path Abs File- -> UTCTime- -> RIO env (Maybe Bool)-loadDockerImageExeCache imageId exePath exeTimestamp =- withStorage $- fmap (dockerImageExeCacheCompatible . entityVal) <$>- getBy (DockerImageExeCacheUnique imageId (toFilePath exePath) exeTimestamp)---- | Sest the record of whether an executable is compatible with a Docker image-saveDockerImageExeCache ::- (HasConfig env, HasLogFunc env)- => Text- -> Path Abs File- -> UTCTime- -> Bool- -> RIO env ()-saveDockerImageExeCache imageId exePath exeTimestamp compatible =- void $- withStorage $- upsert- (DockerImageExeCache- imageId- (toFilePath exePath)- exeTimestamp- compatible)- []---- | Efficiently update a set of values stored in a database table-updateSet ::- ( PersistEntityBackend record ~ BaseBackend backend- , PersistField parentid- , PersistField value- , Ord value- , PersistEntity record- , MonadIO m- , PersistQueryWrite backend- )- => (parentid -> value -> record)- -> EntityField record parentid- -> parentid- -> EntityField record value- -> Set value- -> Set value- -> ReaderT backend m ()-updateSet recordCons parentFieldCons parentId valueFieldCons old new =- when (old /= new) $ do- deleteWhere- [ parentFieldCons ==. parentId- , valueFieldCons <-. Set.toList (Set.difference old new)- ]- insertMany_ $- map (recordCons parentId) $ Set.toList (Set.difference new old)---- | Efficiently update a list of values stored in a database table.-updateList ::- ( PersistEntityBackend record ~ BaseBackend backend- , PersistField parentid- , Ord value- , PersistEntity record- , MonadIO m- , PersistQueryWrite backend- )- => (parentid -> Int -> value -> record)- -> EntityField record parentid- -> parentid- -> EntityField record Int- -> [value]- -> [value]- -> ReaderT backend m ()-updateList recordCons parentFieldCons parentId indexFieldCons old new =- when (old /= new) $ do- let oldSet = Set.fromList (zip [0 ..] old)- newSet = Set.fromList (zip [0 ..] new)- deleteWhere- [ parentFieldCons ==. parentId- , indexFieldCons <-.- map fst (Set.toList $ Set.difference oldSet newSet)- ]- insertMany_ $- map (uncurry $ recordCons parentId) $- Set.toList (Set.difference newSet oldSet)---- | Type-restricted version of 'fromIntegral' to ensure we're making--- the value bigger, not smaller.-sizeToInt64 :: COff -> Int64-sizeToInt64 (COff i) = fromIntegral i -- fromIntegral added for 32-bit systems---- | Type-restricted version of 'fromIntegral' to ensure we're making--- the value bigger, not smaller.-timeToInt64 :: CTime -> Int64-timeToInt64 (CTime i) = fromIntegral i -- fromIntegral added for 32-bit systems---- | Load compiler information, if available, and confirm that the--- referenced files are unchanged. May throw exceptions!-loadCompilerPaths- :: HasConfig env- => Path Abs File -- ^ compiler executable- -> CompilerBuild- -> Bool -- ^ sandboxed?- -> RIO env (Maybe CompilerPaths)-loadCompilerPaths compiler build sandboxed = do- mres <- withStorage $ getBy $ UniqueCompilerInfo $ toFilePath compiler- for mres $ \(Entity _ CompilerCache {..}) -> do- compilerStatus <- liftIO $ getFileStatus $ toFilePath compiler- when- (compilerCacheGhcSize /= sizeToInt64 (fileSize compilerStatus) ||- compilerCacheGhcModified /= timeToInt64 (modificationTime compilerStatus))- (throwString "Compiler file metadata mismatch, ignoring cache")- globalDbStatus <- liftIO $ getFileStatus $ compilerCacheGlobalDb FP.</> "package.cache"- when- (compilerCacheGlobalDbCacheSize /= sizeToInt64 (fileSize globalDbStatus) ||- compilerCacheGlobalDbCacheModified /= timeToInt64 (modificationTime globalDbStatus))- (throwString "Global package cache file metadata mismatch, ignoring cache")-- -- We could use parseAbsFile instead of resolveFile' below to- -- bypass some system calls, at the cost of some really wonky- -- error messages in case someone screws up their GHC installation- pkgexe <- resolveFile' compilerCacheGhcPkgPath- runghc <- resolveFile' compilerCacheRunghcPath- haddock <- resolveFile' compilerCacheHaddockPath- globaldb <- resolveDir' compilerCacheGlobalDb-- cabalVersion <- parseVersionThrowing $ T.unpack compilerCacheCabalVersion- globalDump <-- case readMaybe $ T.unpack compilerCacheGlobalDump of- Nothing -> throwString "Global dump did not parse correctly"- Just globalDump -> pure globalDump- arch <-- case simpleParse $ T.unpack compilerCacheArch of- Nothing -> throwString $ "Invalid arch: " ++ show compilerCacheArch- Just arch -> pure arch-- pure CompilerPaths- { cpCompiler = compiler- , cpCompilerVersion = compilerCacheActualVersion- , cpArch = arch- , cpBuild = build- , cpPkg = GhcPkgExe pkgexe- , cpInterpreter = runghc- , cpHaddock = haddock- , cpSandboxed = sandboxed- , cpCabalVersion = cabalVersion- , cpGlobalDB = globaldb- , cpGhcInfo = compilerCacheInfo- , cpGlobalDump = globalDump- }---- | Save compiler information. May throw exceptions!-saveCompilerPaths- :: HasConfig env- => CompilerPaths- -> RIO env ()-saveCompilerPaths CompilerPaths {..} = withStorage $ do- deleteBy $ UniqueCompilerInfo $ toFilePath cpCompiler- compilerStatus <- liftIO $ getFileStatus $ toFilePath cpCompiler- globalDbStatus <- liftIO $ getFileStatus $ toFilePath $ cpGlobalDB </> $(mkRelFile "package.cache")- let GhcPkgExe pkgexe = cpPkg- insert_ CompilerCache- { compilerCacheActualVersion = cpCompilerVersion- , compilerCacheGhcPath = toFilePath cpCompiler- , compilerCacheGhcSize = sizeToInt64 $ fileSize compilerStatus- , compilerCacheGhcModified = timeToInt64 $ modificationTime compilerStatus- , compilerCacheGhcPkgPath = toFilePath pkgexe- , compilerCacheRunghcPath = toFilePath cpInterpreter- , compilerCacheHaddockPath = toFilePath cpHaddock- , compilerCacheCabalVersion = T.pack $ versionString cpCabalVersion- , compilerCacheGlobalDb = toFilePath cpGlobalDB- , compilerCacheGlobalDbCacheSize = sizeToInt64 $ fileSize globalDbStatus- , compilerCacheGlobalDbCacheModified = timeToInt64 $ modificationTime globalDbStatus- , compilerCacheInfo = cpGhcInfo- , compilerCacheGlobalDump = tshow cpGlobalDump- , compilerCacheArch = T.pack $ Distribution.Text.display cpArch- }---- | How many upgrade checks have occurred since the given timestamp?-upgradeChecksSince :: HasConfig env => UTCTime -> RIO env Int-upgradeChecksSince since = withStorage $ count- [ LastPerformedAction ==. UpgradeCheck- , LastPerformedTimestamp >=. since- ]---- | Log in the database that an upgrade check occurred at the given time.-logUpgradeCheck :: HasConfig env => UTCTime -> RIO env ()-logUpgradeCheck time = withStorage $ void $ upsert- (LastPerformed UpgradeCheck time)- [LastPerformedTimestamp =. time]
@@ -0,0 +1,215 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-identities #-}++-- | Work with SQLite database used for caches across a single project.+module Stack.Storage.Project+ ( initProjectStorage+ , ConfigCacheKey+ , configCacheKey+ , loadConfigCache+ , saveConfigCache+ , deactiveConfigCache+ ) where++import qualified Data.ByteString as S+import qualified Data.Set as Set+import Database.Persist.Sql (SqlBackend)+import Database.Persist.Sqlite+import Database.Persist.TH+import qualified Pantry.Internal as SQLite+import Path+import Stack.Prelude hiding (MigrationFailure)+import Stack.Storage.Util+import Stack.Types.Build+import Stack.Types.Cache+import Stack.Types.Config (HasBuildConfig, buildConfigL, bcProjectStorage, ProjectStorage (..))+import Stack.Types.GhcPkgId++share [ mkPersist sqlSettings+ , mkDeleteCascade sqlSettings+ , mkMigrate "migrateAll"+ ]+ [persistLowerCase|+ConfigCacheParent sql="config_cache"+ directory FilePath "default=(hex(randomblob(16)))"+ type ConfigCacheType+ pkgSrc CachePkgSrc+ active Bool+ pathEnvVar Text+ haddock Bool default=0+ UniqueConfigCacheParent directory type sql="unique_config_cache"+ deriving Show++ConfigCacheDirOption+ parent ConfigCacheParentId sql="config_cache_id"+ index Int+ value String sql="option"+ UniqueConfigCacheDirOption parent index+ deriving Show++ConfigCacheNoDirOption+ parent ConfigCacheParentId sql="config_cache_id"+ index Int+ value String sql="option"+ UniqueConfigCacheNoDirOption parent index+ deriving Show++ConfigCacheDep+ parent ConfigCacheParentId sql="config_cache_id"+ value GhcPkgId sql="ghc_pkg_id"+ UniqueConfigCacheDep parent value+ deriving Show++ConfigCacheComponent+ parent ConfigCacheParentId sql="config_cache_id"+ value S.ByteString sql="component"+ UniqueConfigCacheComponent parent value+ deriving Show+|]++-- | Initialize the database.+initProjectStorage ::+ HasLogFunc env+ => Path Abs File -- ^ storage file+ -> (ProjectStorage -> RIO env a)+ -> RIO env a+initProjectStorage fp f = SQLite.initStorage "Stack" migrateAll fp $ f . ProjectStorage++-- | Run an action in a database transaction+withProjectStorage ::+ (HasBuildConfig env, HasLogFunc env)+ => ReaderT SqlBackend (RIO env) a+ -> RIO env a+withProjectStorage inner =+ flip SQLite.withStorage_ inner =<< view (buildConfigL . to bcProjectStorage . to unProjectStorage)++-- | Key used to retrieve configuration or flag cache+type ConfigCacheKey = Unique ConfigCacheParent++-- | Build key used to retrieve configuration or flag cache+configCacheKey :: Path Abs Dir -> ConfigCacheType -> ConfigCacheKey+configCacheKey dir = UniqueConfigCacheParent (toFilePath dir)++-- | Internal helper to read the 'ConfigCache'+readConfigCache ::+ (HasBuildConfig env, HasLogFunc env)+ => Entity ConfigCacheParent+ -> ReaderT SqlBackend (RIO env) ConfigCache+readConfigCache (Entity parentId ConfigCacheParent {..}) = do+ let configCachePkgSrc = configCacheParentPkgSrc+ coDirs <-+ map (configCacheDirOptionValue . entityVal) <$>+ selectList+ [ConfigCacheDirOptionParent ==. parentId]+ [Asc ConfigCacheDirOptionIndex]+ coNoDirs <-+ map (configCacheNoDirOptionValue . entityVal) <$>+ selectList+ [ConfigCacheNoDirOptionParent ==. parentId]+ [Asc ConfigCacheNoDirOptionIndex]+ let configCacheOpts = ConfigureOpts {..}+ configCacheDeps <-+ Set.fromList . map (configCacheDepValue . entityVal) <$>+ selectList [ConfigCacheDepParent ==. parentId] []+ configCacheComponents <-+ Set.fromList . map (configCacheComponentValue . entityVal) <$>+ selectList [ConfigCacheComponentParent ==. parentId] []+ let configCachePathEnvVar = configCacheParentPathEnvVar+ let configCacheHaddock = configCacheParentHaddock+ return ConfigCache {..}++-- | Load 'ConfigCache' from the database.+loadConfigCache ::+ (HasBuildConfig env, HasLogFunc env)+ => ConfigCacheKey+ -> RIO env (Maybe ConfigCache)+loadConfigCache key =+ withProjectStorage $ do+ mparent <- getBy key+ case mparent of+ Nothing -> return Nothing+ Just parentEntity@(Entity _ ConfigCacheParent {..})+ | configCacheParentActive ->+ Just <$> readConfigCache parentEntity+ | otherwise -> return Nothing++-- | Insert or update 'ConfigCache' to the database.+saveConfigCache ::+ (HasBuildConfig env, HasLogFunc env)+ => ConfigCacheKey+ -> ConfigCache+ -> RIO env ()+saveConfigCache key@(UniqueConfigCacheParent dir type_) new =+ withProjectStorage $ do+ mparent <- getBy key+ (parentId, mold) <-+ case mparent of+ Nothing ->+ (, Nothing) <$>+ insert+ ConfigCacheParent+ { configCacheParentDirectory = dir+ , configCacheParentType = type_+ , configCacheParentPkgSrc = configCachePkgSrc new+ , configCacheParentActive = True+ , configCacheParentPathEnvVar = configCachePathEnvVar new+ , configCacheParentHaddock = configCacheHaddock new+ }+ Just parentEntity@(Entity parentId _) -> do+ old <- readConfigCache parentEntity+ update+ parentId+ [ ConfigCacheParentPkgSrc =. configCachePkgSrc new+ , ConfigCacheParentActive =. True+ , ConfigCacheParentPathEnvVar =. configCachePathEnvVar new+ ]+ return (parentId, Just old)+ updateList+ ConfigCacheDirOption+ ConfigCacheDirOptionParent+ parentId+ ConfigCacheDirOptionIndex+ (maybe [] (coDirs . configCacheOpts) mold)+ (coDirs $ configCacheOpts new)+ updateList+ ConfigCacheNoDirOption+ ConfigCacheNoDirOptionParent+ parentId+ ConfigCacheNoDirOptionIndex+ (maybe [] (coNoDirs . configCacheOpts) mold)+ (coNoDirs $ configCacheOpts new)+ updateSet+ ConfigCacheDep+ ConfigCacheDepParent+ parentId+ ConfigCacheDepValue+ (maybe Set.empty configCacheDeps mold)+ (configCacheDeps new)+ updateSet+ ConfigCacheComponent+ ConfigCacheComponentParent+ parentId+ ConfigCacheComponentValue+ (maybe Set.empty configCacheComponents mold)+ (configCacheComponents new)++-- | Mark 'ConfigCache' as inactive in the database.+-- We use a flag instead of deleting the records since, in most cases, the same+-- cache will be written again within in a few seconds (after+-- `cabal configure`), so this avoids unnecessary database churn.+deactiveConfigCache :: HasBuildConfig env => ConfigCacheKey -> RIO env ()+deactiveConfigCache (UniqueConfigCacheParent dir type_) =+ withProjectStorage $+ updateWhere+ [ConfigCacheParentDirectory ==. dir, ConfigCacheParentType ==. type_]+ [ConfigCacheParentActive =. False]
@@ -0,0 +1,351 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-identities #-}++-- | Work with SQLite database used for caches across an entire user account.+module Stack.Storage.User+ ( initUserStorage+ , PrecompiledCacheKey+ , precompiledCacheKey+ , loadPrecompiledCache+ , savePrecompiledCache+ , loadDockerImageExeCache+ , saveDockerImageExeCache+ , loadCompilerPaths+ , saveCompilerPaths+ , upgradeChecksSince+ , logUpgradeCheck+ ) where++import qualified Data.Set as Set+import qualified Data.Text as T+import Data.Time.Clock (UTCTime)+import Database.Persist.Sql (SqlBackend)+import Database.Persist.Sqlite+import Database.Persist.TH+import Distribution.Text (simpleParse, display)+import Foreign.C.Types (CTime (..))+import qualified Pantry.Internal as SQLite+import Path+import Path.IO (resolveFile', resolveDir')+import qualified RIO.FilePath as FP+import Stack.Prelude hiding (MigrationFailure)+import Stack.Storage.Util+import Stack.Types.Build+import Stack.Types.Cache+import Stack.Types.Compiler+import Stack.Types.CompilerBuild (CompilerBuild)+import Stack.Types.Config (HasConfig, configL, configUserStorage, CompilerPaths (..), GhcPkgExe (..), UserStorage (..))+import System.Posix.Types (COff (..))+import System.PosixCompat.Files (getFileStatus, fileSize, modificationTime)++share [ mkPersist sqlSettings+ , mkDeleteCascade sqlSettings+ , mkMigrate "migrateAll"+ ]+ [persistLowerCase|+PrecompiledCacheParent sql="precompiled_cache"+ platformGhcDir FilePath "default=(hex(randomblob(16)))"+ compiler Text+ cabalVersion Text+ packageKey Text+ optionsHash ByteString+ haddock Bool default=0+ library FilePath Maybe+ UniquePrecompiledCacheParent platformGhcDir compiler cabalVersion packageKey optionsHash haddock sql="unique_precompiled_cache"+ deriving Show++PrecompiledCacheSubLib+ parent PrecompiledCacheParentId sql="precompiled_cache_id"+ value FilePath sql="sub_lib"+ UniquePrecompiledCacheSubLib parent value+ deriving Show++PrecompiledCacheExe+ parent PrecompiledCacheParentId sql="precompiled_cache_id"+ value FilePath sql="exe"+ UniquePrecompiledCacheExe parent value+ deriving Show++DockerImageExeCache+ imageHash Text+ exePath FilePath+ exeTimestamp UTCTime+ compatible Bool+ DockerImageExeCacheUnique imageHash exePath exeTimestamp+ deriving Show++CompilerCache+ actualVersion ActualCompiler+ arch Text++ -- Include ghc executable size and modified time for sanity checking entries+ ghcPath FilePath+ ghcSize Int64+ ghcModified Int64++ ghcPkgPath FilePath+ runghcPath FilePath+ haddockPath FilePath++ cabalVersion Text+ globalDb FilePath+ globalDbCacheSize Int64+ globalDbCacheModified Int64+ info ByteString++ -- This is the ugliest part of this table, simply storing a Show/Read version of the+ -- data. We could do a better job with normalized data and proper table structure.+ -- However, recomputing this value in the future if the data representation changes+ -- is very cheap, so we'll take the easy way out for now.+ globalDump Text++ UniqueCompilerInfo ghcPath++-- Last time certain actions were performed+LastPerformed+ action Action+ timestamp UTCTime+ UniqueAction action+|]++-- | Initialize the database.+initUserStorage ::+ HasLogFunc env+ => Path Abs File -- ^ storage file+ -> (UserStorage -> RIO env a)+ -> RIO env a+initUserStorage fp f = SQLite.initStorage "Stack" migrateAll fp $ f . UserStorage++-- | Run an action in a database transaction+withUserStorage ::+ (HasConfig env, HasLogFunc env)+ => ReaderT SqlBackend (RIO env) a+ -> RIO env a+withUserStorage inner =+ flip SQLite.withStorage_ inner =<< view (configL . to configUserStorage . to unUserStorage)++-- | Key used to retrieve the precompiled cache+type PrecompiledCacheKey = Unique PrecompiledCacheParent++-- | Build key used to retrieve the precompiled cache+precompiledCacheKey ::+ Path Rel Dir+ -> ActualCompiler+ -> Version+ -> Text+ -> ByteString+ -> Bool+ -> PrecompiledCacheKey+precompiledCacheKey platformGhcDir compiler cabalVersion =+ UniquePrecompiledCacheParent+ (toFilePath platformGhcDir)+ (compilerVersionText compiler)+ (T.pack $ versionString cabalVersion)++-- | Internal helper to read the 'PrecompiledCache' from the database+readPrecompiledCache ::+ (HasConfig env, HasLogFunc env)+ => PrecompiledCacheKey+ -> ReaderT SqlBackend (RIO env) (Maybe ( PrecompiledCacheParentId+ , PrecompiledCache Rel))+readPrecompiledCache key = do+ mparent <- getBy key+ forM mparent $ \(Entity parentId PrecompiledCacheParent {..}) -> do+ pcLibrary <- mapM parseRelFile precompiledCacheParentLibrary+ pcSubLibs <-+ mapM (parseRelFile . precompiledCacheSubLibValue . entityVal) =<<+ selectList [PrecompiledCacheSubLibParent ==. parentId] []+ pcExes <-+ mapM (parseRelFile . precompiledCacheExeValue . entityVal) =<<+ selectList [PrecompiledCacheExeParent ==. parentId] []+ return (parentId, PrecompiledCache {..})++-- | Load 'PrecompiledCache' from the database.+loadPrecompiledCache ::+ (HasConfig env, HasLogFunc env)+ => PrecompiledCacheKey+ -> RIO env (Maybe (PrecompiledCache Rel))+loadPrecompiledCache key = withUserStorage $ fmap snd <$> readPrecompiledCache key++-- | Insert or update 'PrecompiledCache' to the database.+savePrecompiledCache ::+ (HasConfig env, HasLogFunc env)+ => PrecompiledCacheKey+ -> PrecompiledCache Rel+ -> RIO env ()+savePrecompiledCache key@(UniquePrecompiledCacheParent precompiledCacheParentPlatformGhcDir precompiledCacheParentCompiler precompiledCacheParentCabalVersion precompiledCacheParentPackageKey precompiledCacheParentOptionsHash precompiledCacheParentHaddock) new =+ withUserStorage $ do+ let precompiledCacheParentLibrary = fmap toFilePath (pcLibrary new)+ mIdOld <- readPrecompiledCache key+ (parentId, mold) <-+ case mIdOld of+ Nothing -> (, Nothing) <$> insert PrecompiledCacheParent {..}+ Just (parentId, old) -> do+ update+ parentId+ [ PrecompiledCacheParentLibrary =.+ precompiledCacheParentLibrary+ ]+ return (parentId, Just old)+ updateSet+ PrecompiledCacheSubLib+ PrecompiledCacheSubLibParent+ parentId+ PrecompiledCacheSubLibValue+ (maybe Set.empty (toFilePathSet . pcSubLibs) mold)+ (toFilePathSet $ pcSubLibs new)+ updateSet+ PrecompiledCacheExe+ PrecompiledCacheExeParent+ parentId+ PrecompiledCacheExeValue+ (maybe Set.empty (toFilePathSet . pcExes) mold)+ (toFilePathSet $ pcExes new)+ where+ toFilePathSet = Set.fromList . map toFilePath++-- | Get the record of whether an executable is compatible with a Docker image+loadDockerImageExeCache ::+ (HasConfig env, HasLogFunc env)+ => Text+ -> Path Abs File+ -> UTCTime+ -> RIO env (Maybe Bool)+loadDockerImageExeCache imageId exePath exeTimestamp =+ withUserStorage $+ fmap (dockerImageExeCacheCompatible . entityVal) <$>+ getBy (DockerImageExeCacheUnique imageId (toFilePath exePath) exeTimestamp)++-- | Sest the record of whether an executable is compatible with a Docker image+saveDockerImageExeCache ::+ (HasConfig env, HasLogFunc env)+ => Text+ -> Path Abs File+ -> UTCTime+ -> Bool+ -> RIO env ()+saveDockerImageExeCache imageId exePath exeTimestamp compatible =+ void $+ withUserStorage $+ upsert+ (DockerImageExeCache+ imageId+ (toFilePath exePath)+ exeTimestamp+ compatible)+ []++-- | Type-restricted version of 'fromIntegral' to ensure we're making+-- the value bigger, not smaller.+sizeToInt64 :: COff -> Int64+sizeToInt64 (COff i) = fromIntegral i -- fromIntegral added for 32-bit systems++-- | Type-restricted version of 'fromIntegral' to ensure we're making+-- the value bigger, not smaller.+timeToInt64 :: CTime -> Int64+timeToInt64 (CTime i) = fromIntegral i -- fromIntegral added for 32-bit systems++-- | Load compiler information, if available, and confirm that the+-- referenced files are unchanged. May throw exceptions!+loadCompilerPaths+ :: HasConfig env+ => Path Abs File -- ^ compiler executable+ -> CompilerBuild+ -> Bool -- ^ sandboxed?+ -> RIO env (Maybe CompilerPaths)+loadCompilerPaths compiler build sandboxed = do+ mres <- withUserStorage $ getBy $ UniqueCompilerInfo $ toFilePath compiler+ for mres $ \(Entity _ CompilerCache {..}) -> do+ compilerStatus <- liftIO $ getFileStatus $ toFilePath compiler+ when+ (compilerCacheGhcSize /= sizeToInt64 (fileSize compilerStatus) ||+ compilerCacheGhcModified /= timeToInt64 (modificationTime compilerStatus))+ (throwString "Compiler file metadata mismatch, ignoring cache")+ globalDbStatus <- liftIO $ getFileStatus $ compilerCacheGlobalDb FP.</> "package.cache"+ when+ (compilerCacheGlobalDbCacheSize /= sizeToInt64 (fileSize globalDbStatus) ||+ compilerCacheGlobalDbCacheModified /= timeToInt64 (modificationTime globalDbStatus))+ (throwString "Global package cache file metadata mismatch, ignoring cache")++ -- We could use parseAbsFile instead of resolveFile' below to+ -- bypass some system calls, at the cost of some really wonky+ -- error messages in case someone screws up their GHC installation+ pkgexe <- resolveFile' compilerCacheGhcPkgPath+ runghc <- resolveFile' compilerCacheRunghcPath+ haddock <- resolveFile' compilerCacheHaddockPath+ globaldb <- resolveDir' compilerCacheGlobalDb++ cabalVersion <- parseVersionThrowing $ T.unpack compilerCacheCabalVersion+ globalDump <-+ case readMaybe $ T.unpack compilerCacheGlobalDump of+ Nothing -> throwString "Global dump did not parse correctly"+ Just globalDump -> pure globalDump+ arch <-+ case simpleParse $ T.unpack compilerCacheArch of+ Nothing -> throwString $ "Invalid arch: " ++ show compilerCacheArch+ Just arch -> pure arch++ pure CompilerPaths+ { cpCompiler = compiler+ , cpCompilerVersion = compilerCacheActualVersion+ , cpArch = arch+ , cpBuild = build+ , cpPkg = GhcPkgExe pkgexe+ , cpInterpreter = runghc+ , cpHaddock = haddock+ , cpSandboxed = sandboxed+ , cpCabalVersion = cabalVersion+ , cpGlobalDB = globaldb+ , cpGhcInfo = compilerCacheInfo+ , cpGlobalDump = globalDump+ }++-- | Save compiler information. May throw exceptions!+saveCompilerPaths+ :: HasConfig env+ => CompilerPaths+ -> RIO env ()+saveCompilerPaths CompilerPaths {..} = withUserStorage $ do+ deleteBy $ UniqueCompilerInfo $ toFilePath cpCompiler+ compilerStatus <- liftIO $ getFileStatus $ toFilePath cpCompiler+ globalDbStatus <- liftIO $ getFileStatus $ toFilePath $ cpGlobalDB </> $(mkRelFile "package.cache")+ let GhcPkgExe pkgexe = cpPkg+ insert_ CompilerCache+ { compilerCacheActualVersion = cpCompilerVersion+ , compilerCacheGhcPath = toFilePath cpCompiler+ , compilerCacheGhcSize = sizeToInt64 $ fileSize compilerStatus+ , compilerCacheGhcModified = timeToInt64 $ modificationTime compilerStatus+ , compilerCacheGhcPkgPath = toFilePath pkgexe+ , compilerCacheRunghcPath = toFilePath cpInterpreter+ , compilerCacheHaddockPath = toFilePath cpHaddock+ , compilerCacheCabalVersion = T.pack $ versionString cpCabalVersion+ , compilerCacheGlobalDb = toFilePath cpGlobalDB+ , compilerCacheGlobalDbCacheSize = sizeToInt64 $ fileSize globalDbStatus+ , compilerCacheGlobalDbCacheModified = timeToInt64 $ modificationTime globalDbStatus+ , compilerCacheInfo = cpGhcInfo+ , compilerCacheGlobalDump = tshow cpGlobalDump+ , compilerCacheArch = T.pack $ Distribution.Text.display cpArch+ }++-- | How many upgrade checks have occurred since the given timestamp?+upgradeChecksSince :: HasConfig env => UTCTime -> RIO env Int+upgradeChecksSince since = withUserStorage $ count+ [ LastPerformedAction ==. UpgradeCheck+ , LastPerformedTimestamp >=. since+ ]++-- | Log in the database that an upgrade check occurred at the given time.+logUpgradeCheck :: HasConfig env => UTCTime -> RIO env ()+logUpgradeCheck time = withUserStorage $ void $ upsert+ (LastPerformed UpgradeCheck time)+ [LastPerformedTimestamp =. time]
@@ -0,0 +1,69 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+-- | Utils for the other Stack.Storage modules+module Stack.Storage.Util+ ( updateList+ , updateSet+ ) where++import qualified Data.Set as Set+import Database.Persist+import Stack.Prelude hiding (MigrationFailure)++-- | Efficiently update a set of values stored in a database table+updateSet ::+ ( PersistEntityBackend record ~ BaseBackend backend+ , PersistField parentid+ , PersistField value+ , Ord value+ , PersistEntity record+ , MonadIO m+ , PersistQueryWrite backend+ )+ => (parentid -> value -> record)+ -> EntityField record parentid+ -> parentid+ -> EntityField record value+ -> Set value+ -> Set value+ -> ReaderT backend m ()+updateSet recordCons parentFieldCons parentId valueFieldCons old new =+ when (old /= new) $ do+ deleteWhere+ [ parentFieldCons ==. parentId+ , valueFieldCons <-. Set.toList (Set.difference old new)+ ]+ insertMany_ $+ map (recordCons parentId) $ Set.toList (Set.difference new old)++-- | Efficiently update a list of values stored in a database table.+updateList ::+ ( PersistEntityBackend record ~ BaseBackend backend+ , PersistField parentid+ , Ord value+ , PersistEntity record+ , MonadIO m+ , PersistQueryWrite backend+ )+ => (parentid -> Int -> value -> record)+ -> EntityField record parentid+ -> parentid+ -> EntityField record Int+ -> [value]+ -> [value]+ -> ReaderT backend m ()+updateList recordCons parentFieldCons parentId indexFieldCons old new =+ when (old /= new) $ do+ let oldSet = Set.fromList (zip [0 ..] old)+ newSet = Set.fromList (zip [0 ..] new)+ deleteWhere+ [ parentFieldCons ==. parentId+ , indexFieldCons <-.+ map fst (Set.toList $ Set.difference oldSet newSet)+ ]+ insertMany_ $+ map (uncurry $ recordCons parentId) $+ Set.toList (Set.difference newSet oldSet)
@@ -46,6 +46,9 @@ ,stackYamlL ,projectRootL ,HasBuildConfig(..)+ -- ** Storage databases+ ,UserStorage(..)+ ,ProjectStorage(..) -- ** GHCVariant & HasGHCVariant ,GHCVariant(..) ,ghcVariantName@@ -365,14 +368,24 @@ ,configStackRoot :: !(Path Abs Dir) ,configResolver :: !(Maybe AbstractResolver) -- ^ Any resolver override from the command line- ,configStorage :: !Storage- -- ^ Database connection pool for Stack database+ ,configUserStorage :: !UserStorage+ -- ^ Database connection pool for user Stack database ,configHideSourcePaths :: !Bool -- ^ Enable GHC hiding source paths? ,configRecommendUpgrade :: !Bool -- ^ Recommend a Stack upgrade? } +-- | A bit of type safety to ensure we're talking to the right database.+newtype UserStorage = UserStorage+ { unUserStorage :: Storage+ }++-- | A bit of type safety to ensure we're talking to the right database.+newtype ProjectStorage = ProjectStorage+ { unProjectStorage :: Storage+ }+ -- | The project root directory, if in a project. configProjectRoot :: Config -> Maybe (Path Abs Dir) configProjectRoot c =@@ -611,6 +624,8 @@ -- Note: if the STACK_YAML environment variable is used, this may be -- different from projectRootL </> "stack.yaml" if a different file -- name is used.+ , bcProjectStorage :: !ProjectStorage+ -- ^ Database connection pool for project Stack database , bcCurator :: !(Maybe Curator) } @@ -1750,14 +1765,10 @@ explicitSetupDeps name = do m <- view $ configL.to configExplicitSetupDeps return $- -- Yes there are far cleverer ways to write this. I honestly consider- -- the explicit pattern matching much easier to parse at a glance.- case Map.lookup (Just name) m of- Just b -> b- Nothing ->- case Map.lookup Nothing m of- Just b -> b- Nothing -> False -- default value+ Map.findWithDefault+ (Map.findWithDefault False Nothing m)+ (Just name)+ m -- | Data passed into Docker container for the Docker entrypoint's use newtype DockerEntrypoint = DockerEntrypoint
@@ -191,7 +191,7 @@ createDirectory childDir setCurrentDirectory childDir loadConfig' $ \config -> liftIO $ do- bc <- runRIO config loadBuildConfig+ bc <- runRIO config $ withBuildConfig ask view projectRootL bc `shouldBe` parentDir it "respects the STACK_YAML env variable" $ inTempDir $ do@@ -200,7 +200,7 @@ writeFile stackYamlFp sampleConfig writeFile (toFilePath dir ++ "/package.yaml") "name: foo" withEnvVar "STACK_YAML" stackYamlFp $ loadConfig' $ \config -> liftIO $ do- BuildConfig{..} <- runRIO config loadBuildConfig+ BuildConfig{..} <- runRIO config $ withBuildConfig ask bcStackYaml `shouldBe` dir </> stackDotYaml parent bcStackYaml `shouldBe` dir @@ -214,7 +214,7 @@ writeFile (toFilePath yamlAbs) "resolver: ghc-7.8" writeFile (toFilePath packageYaml) "name: foo" withEnvVar "STACK_YAML" (toFilePath yamlRel) $ loadConfig' $ \config -> liftIO $ do- BuildConfig{..} <- runRIO config loadBuildConfig+ BuildConfig{..} <- runRIO config $ withBuildConfig ask bcStackYaml `shouldBe` yamlAbs describe "defaultConfigYaml" $
@@ -1,681 +1,688 @@ cabal-version: 2.0---- This file has been generated from package.yaml by hpack version 0.31.2.------ see: https://github.com/sol/hpack------ hash: b9d0860d1a25f89644f763eb2ea51d189b05684934421cbda622bea1b3addeb9--name: stack-version: 2.1.1.1-synopsis: The Haskell Tool Stack-description: Please see the documentation at <https://docs.haskellstack.org>- for usage information.- .- If building a 'stack' executable for distribution, please download the- source code from <https://github.com/commercialhaskell/stack/releases>- and build it using Stack itself in order to ensure identical behaviour- to official binaries. This package on Hackage is provided for convenience- and bootstrapping purposes.- .- Note that the API for the library is not currently stable, and may- change significantly, even between minor releases. It is- currently only intended for use by the executable.-category: Development-homepage: http://haskellstack.org-bug-reports: https://github.com/commercialhaskell/stack/issues-author: Commercial Haskell SIG-maintainer: manny@fpcomplete.com-license: BSD3-license-file: LICENSE-build-type: Custom-extra-source-files:- CONTRIBUTING.md- ChangeLog.md- README.md- doc/azure_ci.md- doc/build_command.md- doc/build_overview.md- doc/ChangeLog.md- doc/CONTRIBUTING.md- doc/coverage.md- doc/custom_snapshot.md- doc/dependency_visualization.md- doc/developing_on_windows.md- doc/docker_integration.md- doc/faq.md- doc/ghci.md- doc/ghcjs.md- doc/GUIDE.md- doc/install_and_upgrade.md- doc/lock_files.md- doc/nix_integration.md- doc/nonstandard_project_init.md- doc/pantry.md- doc/README.md- doc/shell_autocompletion.md- doc/SIGNING_KEY.md- doc/stack_yaml_vs_cabal_package_file.md- doc/travis_ci.md- doc/yaml_configuration.md- src/setup-shim/StackSetupShim.hs- test/package-dump/ghc-7.10.txt- test/package-dump/ghc-7.8.4-osx.txt- test/package-dump/ghc-7.8.txt- test/package-dump/ghc-head.txt- src/test/Stack/Untar/test1.tar.gz- src/test/Stack/Untar/test2.tar.gz--source-repository head- type: git- location: https://github.com/commercialhaskell/stack--custom-setup- setup-depends:- Cabal- , base >=4.10 && <5- , filepath--flag disable-git-info- description: Disable compile-time inclusion of current git info in stack- manual: True- default: False--flag hide-dependency-versions- description: Hides dependency versions from "stack --version", used only by building with stack.yaml- manual: True- default: False--flag integration-tests- description: Run the integration test suite- manual: True- default: False--flag static- description: Pass -static/-pthread to ghc when linking the stack binary.- manual: True- default: False--flag supported-build- description: If false, causes "stack --version" to issue a warning about the build being unsupported. True only if building with stack.yaml- manual: True- default: False--library- exposed-modules:- Control.Concurrent.Execute- Data.Attoparsec.Args- Data.Attoparsec.Combinators- Data.Attoparsec.Interpreter- Data.Monoid.Map- Network.HTTP.StackClient- Options.Applicative.Args- Options.Applicative.Builder.Extra- Options.Applicative.Complicated- Path.CheckInstall- Path.Extra- Path.Find- Stack.Build- Stack.Build.Cache- Stack.Build.ConstructPlan- Stack.Build.Execute- Stack.Build.Haddock- Stack.Build.Installed- Stack.Build.Source- Stack.Build.Target- Stack.BuildPlan- Stack.Clean- Stack.Config- Stack.Config.Build- Stack.Config.Docker- Stack.Config.Nix- Stack.ConfigCmd- Stack.Constants- Stack.Constants.Config- Stack.Coverage- Stack.DefaultColorWhen- Stack.Docker- Stack.Dot- Stack.FileWatch- Stack.Freeze- Stack.GhcPkg- Stack.Ghci- Stack.Ghci.Script- Stack.Hoogle- Stack.IDE- Stack.Init- Stack.Ls- Stack.Lock- Stack.New- Stack.Nix- Stack.Options.BenchParser- Stack.Options.BuildMonoidParser- Stack.Options.BuildParser- Stack.Options.CleanParser- Stack.Options.ConfigParser- Stack.Options.Completion- Stack.Options.DockerParser- Stack.Options.DotParser- Stack.Options.ExecParser- Stack.Options.FreezeParser- Stack.Options.GhcBuildParser- Stack.Options.GhciParser- Stack.Options.GhcVariantParser- Stack.Options.GlobalParser- Stack.Options.HaddockParser- Stack.Options.HpcReportParser- Stack.Options.LogLevelParser- Stack.Options.NewParser- Stack.Options.NixParser- Stack.Options.PackageParser- Stack.Options.ResolverParser- Stack.Options.ScriptParser- Stack.Options.SDistParser- Stack.Options.TestParser- Stack.Options.Utils- Stack.Package- Stack.PackageDump- Stack.Path- Stack.Prelude- Stack.Runners- Stack.Script- Stack.SDist- Stack.Setup- Stack.Setup.Installed- Stack.SetupCmd- Stack.SourceMap- Stack.Storage- Stack.Types.Build- Stack.Types.CompilerBuild- Stack.Types.Compiler- Stack.Types.Config- Stack.Types.Config.Build- Stack.Types.Docker- Stack.Types.GhcPkgId- Stack.Types.NamedComponent- Stack.Types.Nix- Stack.Types.Package- Stack.Types.PackageName- Stack.Types.Resolver- Stack.Types.SourceMap- Stack.Types.TemplateName- Stack.Types.Version- Stack.Types.VersionIntervals- Stack.Unpack- Stack.Upgrade- Stack.Upload- System.Info.ShortPathName- System.Permissions- System.Process.Pager- System.Terminal- Paths_stack- other-modules:- Stack.Types.Cache- autogen-modules:- Paths_stack- hs-source-dirs:- src/- ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path -fwarn-identities- build-depends:- Cabal- , aeson- , annotated-wl-pprint- , ansi-terminal- , array- , async- , attoparsec- , base >=4.10 && <5- , base64-bytestring- , bytestring- , colour- , conduit- , conduit-extra- , containers- , cryptonite- , cryptonite-conduit- , deepseq- , directory- , echo- , exceptions- , extra- , file-embed- , filelock- , filepath- , fsnotify- , generic-deriving- , hackage-security- , hashable- , hi-file-parser- , hpack- , hpc- , http-client- , http-client-tls- , http-conduit- , http-download- , http-types- , memory- , microlens- , mintty- , mono-traversable- , mtl- , mustache- , neat-interpolation- , network-uri- , open-browser- , optparse-applicative- , pantry-tmp- , path- , path-io- , persistent- , persistent-sqlite- , persistent-template- , pretty- , primitive- , process- , project-template- , regex-applicative-text- , resource-pool- , resourcet- , retry- , rio- , rio-prettyprint- , semigroups- , split- , stm- , streaming-commons- , tar- , template-haskell- , temporary- , terminal-size- , text- , text-metrics- , th-reify-many- , time- , tls- , transformers- , typed-process- , unicode-transforms- , unix-compat- , unliftio- , unordered-containers- , vector- , yaml- , zip-archive- , zlib- if os(windows)- cpp-options: -DWINDOWS- build-depends:- Win32- else- build-tools:- hsc2hs- build-depends:- unix- if os(windows)- other-modules:- System.Uname- hs-source-dirs:- src/windows/- else- other-modules:- System.Uname- hs-source-dirs:- src/unix/- c-sources:- src/unix/cbits/uname.c- default-language: Haskell2010--executable stack- main-is: Main.hs- other-modules:- BuildInfo- Build_stack- Paths_stack- autogen-modules:- Build_stack- Paths_stack- hs-source-dirs:- src/main- ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path -threaded -rtsopts- build-depends:- Cabal- , aeson- , annotated-wl-pprint- , ansi-terminal- , array- , async- , attoparsec- , base >=4.10 && <5- , base64-bytestring- , bytestring- , colour- , conduit- , conduit-extra- , containers- , cryptonite- , cryptonite-conduit- , deepseq- , directory- , echo- , exceptions- , extra- , file-embed- , filelock- , filepath- , fsnotify- , generic-deriving- , hackage-security- , hashable- , hi-file-parser- , hpack- , hpc- , http-client- , http-client-tls- , http-conduit- , http-download- , http-types- , memory- , microlens- , mintty- , mono-traversable- , mtl- , mustache- , neat-interpolation- , network-uri- , open-browser- , optparse-applicative- , pantry-tmp- , path- , path-io- , persistent- , persistent-sqlite- , persistent-template- , pretty- , primitive- , process- , project-template- , regex-applicative-text- , resource-pool- , resourcet- , retry- , rio- , rio-prettyprint- , semigroups- , split- , stack- , stm- , streaming-commons- , tar- , template-haskell- , temporary- , terminal-size- , text- , text-metrics- , th-reify-many- , time- , tls- , transformers- , typed-process- , unicode-transforms- , unix-compat- , unliftio- , unordered-containers- , vector- , yaml- , zip-archive- , zlib- if os(windows)- cpp-options: -DWINDOWS- build-depends:- Win32- else- build-tools:- hsc2hs- build-depends:- unix- if flag(static)- ld-options: -static -pthread- if !(flag(disable-git-info))- cpp-options: -DUSE_GIT_INFO- build-depends:- githash- , optparse-simple- if flag(hide-dependency-versions)- cpp-options: -DHIDE_DEP_VERSIONS- if flag(supported-build)- cpp-options: -DSUPPORTED_BUILD- default-language: Haskell2010--executable stack-integration-test- main-is: IntegrationSpec.hs- other-modules:- StackTest- Paths_stack- hs-source-dirs:- test/integration- test/integration/lib- ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path -threaded -rtsopts -with-rtsopts=-N- build-depends:- Cabal- , aeson- , annotated-wl-pprint- , ansi-terminal- , array- , async- , attoparsec- , base >=4.10 && <5- , base64-bytestring- , bytestring- , colour- , conduit- , conduit-extra- , containers- , cryptonite- , cryptonite-conduit- , deepseq- , directory- , echo- , exceptions- , extra- , file-embed- , filelock- , filepath- , fsnotify- , generic-deriving- , hackage-security- , hashable- , hi-file-parser- , hpack- , hpc- , hspec- , http-client- , http-client-tls- , http-conduit- , http-download- , http-types- , memory- , microlens- , mintty- , mono-traversable- , mtl- , mustache- , neat-interpolation- , network-uri- , open-browser- , optparse-applicative- , optparse-generic- , pantry-tmp- , path- , path-io- , persistent- , persistent-sqlite- , persistent-template- , pretty- , primitive- , process- , project-template- , regex-applicative-text- , resource-pool- , resourcet- , retry- , rio- , rio-prettyprint- , semigroups- , split- , stm- , streaming-commons- , tar- , template-haskell- , temporary- , terminal-size- , text- , text-metrics- , th-reify-many- , time- , tls- , transformers- , typed-process- , unicode-transforms- , unix-compat- , unliftio- , unordered-containers- , vector- , yaml- , zip-archive- , zlib- if os(windows)- cpp-options: -DWINDOWS- build-depends:- Win32- else- build-tools:- hsc2hs- build-depends:- unix- if !(flag(integration-tests))- buildable: False- default-language: Haskell2010--test-suite stack-test- type: exitcode-stdio-1.0- main-is: Spec.hs- other-modules:- Stack.ArgsSpec- Stack.Build.ExecuteSpec- Stack.Build.TargetSpec- Stack.Config.DockerSpec- Stack.ConfigSpec- Stack.DotSpec- Stack.Ghci.PortableFakePaths- Stack.Ghci.ScriptSpec- Stack.GhciSpec- Stack.LockSpec- Stack.NixSpec- Stack.PackageDumpSpec- Stack.Types.TemplateNameSpec- Stack.UploadSpec- Paths_stack- hs-source-dirs:- src/test- ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path -threaded- build-depends:- Cabal- , QuickCheck- , aeson- , annotated-wl-pprint- , ansi-terminal- , array- , async- , attoparsec- , base >=4.10 && <5- , base64-bytestring- , bytestring- , colour- , conduit- , conduit-extra- , containers- , cryptonite- , cryptonite-conduit- , deepseq- , directory- , echo- , exceptions- , extra- , file-embed- , filelock- , filepath- , fsnotify- , generic-deriving- , hackage-security- , hashable- , hi-file-parser- , hpack- , hpc- , hspec- , http-client- , http-client-tls- , http-conduit- , http-download- , http-types- , memory- , microlens- , mintty- , mono-traversable- , mtl- , mustache- , neat-interpolation- , network-uri- , open-browser- , optparse-applicative- , pantry-tmp- , path- , path-io- , persistent- , persistent-sqlite- , persistent-template- , pretty- , primitive- , process- , project-template- , raw-strings-qq- , regex-applicative-text- , resource-pool- , resourcet- , retry- , rio- , rio-prettyprint- , semigroups- , smallcheck- , split- , stack- , stm- , streaming-commons- , tar- , template-haskell- , temporary- , terminal-size- , text- , text-metrics- , th-reify-many- , time- , tls- , transformers- , typed-process- , unicode-transforms- , unix-compat- , unliftio- , unordered-containers- , vector- , yaml- , zip-archive- , zlib- if os(windows)- cpp-options: -DWINDOWS- build-depends:- Win32- else- build-tools:- hsc2hs- build-depends:- unix- default-language: Haskell2010+name: stack+version: 2.1.3+license: BSD3+license-file: LICENSE+maintainer: manny@fpcomplete.com+author: Commercial Haskell SIG+homepage: http://haskellstack.org+bug-reports: https://github.com/commercialhaskell/stack/issues+synopsis: The Haskell Tool Stack+description:+ Please see the documentation at <https://docs.haskellstack.org>+ for usage information.+ .+ If building a 'stack' executable for distribution, please download the+ source code from <https://github.com/commercialhaskell/stack/releases>+ and build it using Stack itself in order to ensure identical behaviour+ to official binaries. This package on Hackage is provided for convenience+ and bootstrapping purposes.+ .+ Note that the API for the library is not currently stable, and may+ change significantly, even between minor releases. It is+ currently only intended for use by the executable.+category: Development+build-type: Custom+extra-source-files:+ CONTRIBUTING.md+ ChangeLog.md+ README.md+ doc/azure_ci.md+ doc/build_command.md+ doc/build_overview.md+ doc/ChangeLog.md+ doc/CONTRIBUTING.md+ doc/coverage.md+ doc/custom_snapshot.md+ doc/dependency_visualization.md+ doc/developing_on_windows.md+ doc/docker_integration.md+ doc/faq.md+ doc/ghci.md+ doc/ghcjs.md+ doc/GUIDE.md+ doc/install_and_upgrade.md+ doc/lock_files.md+ doc/nix_integration.md+ doc/nonstandard_project_init.md+ doc/pantry.md+ doc/README.md+ doc/shell_autocompletion.md+ doc/SIGNING_KEY.md+ doc/stack_yaml_vs_cabal_package_file.md+ doc/travis_ci.md+ doc/yaml_configuration.md+ src/setup-shim/StackSetupShim.hs+ test/package-dump/ghc-7.10.txt+ test/package-dump/ghc-7.8.4-osx.txt+ test/package-dump/ghc-7.8.txt+ test/package-dump/ghc-head.txt+ src/test/Stack/Untar/test1.tar.gz+ src/test/Stack/Untar/test2.tar.gz++source-repository head+ type: git+ location: https://github.com/commercialhaskell/stack++custom-setup+ setup-depends: Cabal >=2.4.0.1,+ base >=4.10 && <5,+ filepath >=1.4.1.2++flag disable-git-info+ description:+ Disable compile-time inclusion of current git info in stack+ default: False+ manual: True++flag hide-dependency-versions+ description:+ Hides dependency versions from 'stack --version', used only by building Stack and the default 'stack.yaml'. Note to packagers/distributors: DO NOT OVERRIDE THIS FLAG IF YOU ARE BUILDING 'stack' ANY OTHER WAY (e.g. using cabal or from Hackage), as it makes debugging support requests more difficult.+ default: False+ manual: True++flag integration-tests+ description:+ Run the integration test suite+ default: False+ manual: True++flag static+ description:+ Pass -static/-pthread to ghc when linking the stack binary.+ default: False+ manual: True++flag supported-build+ description:+ If false, causes 'stack --version' to issue a warning about the build being unsupported. Should be True only if building with Stack and the default 'stack.yaml'. Note to packagers/distributors: DO NOT OVERRIDE THIS FLAG IF YOU ARE BUILDING 'stack' ANY OTHER WAY (e.g. using cabal or from Hackage), as it makes debugging support requests more difficult.+ default: False+ manual: True++library+ exposed-modules:+ Control.Concurrent.Execute+ Data.Attoparsec.Args+ Data.Attoparsec.Combinators+ Data.Attoparsec.Interpreter+ Data.Monoid.Map+ Network.HTTP.StackClient+ Options.Applicative.Args+ Options.Applicative.Builder.Extra+ Options.Applicative.Complicated+ Path.CheckInstall+ Path.Extra+ Path.Find+ Stack.Build+ Stack.Build.Cache+ Stack.Build.ConstructPlan+ Stack.Build.Execute+ Stack.Build.Haddock+ Stack.Build.Installed+ Stack.Build.Source+ Stack.Build.Target+ Stack.BuildPlan+ Stack.Clean+ Stack.Config+ Stack.Config.Build+ Stack.Config.Docker+ Stack.Config.Nix+ Stack.ConfigCmd+ Stack.Constants+ Stack.Constants.Config+ Stack.Coverage+ Stack.DefaultColorWhen+ Stack.Docker+ Stack.Dot+ Stack.FileWatch+ Stack.Freeze+ Stack.GhcPkg+ Stack.Ghci+ Stack.Ghci.Script+ Stack.Hoogle+ Stack.IDE+ Stack.Init+ Stack.Ls+ Stack.Lock+ Stack.New+ Stack.Nix+ Stack.Options.BenchParser+ Stack.Options.BuildMonoidParser+ Stack.Options.BuildParser+ Stack.Options.CleanParser+ Stack.Options.ConfigParser+ Stack.Options.Completion+ Stack.Options.DockerParser+ Stack.Options.DotParser+ Stack.Options.ExecParser+ Stack.Options.FreezeParser+ Stack.Options.GhcBuildParser+ Stack.Options.GhciParser+ Stack.Options.GhcVariantParser+ Stack.Options.GlobalParser+ Stack.Options.HaddockParser+ Stack.Options.HpcReportParser+ Stack.Options.LogLevelParser+ Stack.Options.NewParser+ Stack.Options.NixParser+ Stack.Options.PackageParser+ Stack.Options.ResolverParser+ Stack.Options.ScriptParser+ Stack.Options.SDistParser+ Stack.Options.TestParser+ Stack.Options.Utils+ Stack.Package+ Stack.PackageDump+ Stack.Path+ Stack.Prelude+ Stack.Runners+ Stack.Script+ Stack.SDist+ Stack.Setup+ Stack.Setup.Installed+ Stack.SetupCmd+ Stack.SourceMap+ Stack.Storage.Project+ Stack.Storage.User+ Stack.Storage.Util+ Stack.Types.Build+ Stack.Types.CompilerBuild+ Stack.Types.Compiler+ Stack.Types.Config+ Stack.Types.Config.Build+ Stack.Types.Docker+ Stack.Types.GhcPkgId+ Stack.Types.NamedComponent+ Stack.Types.Nix+ Stack.Types.Package+ Stack.Types.PackageName+ Stack.Types.Resolver+ Stack.Types.SourceMap+ Stack.Types.TemplateName+ Stack.Types.Version+ Stack.Types.VersionIntervals+ Stack.Unpack+ Stack.Upgrade+ Stack.Upload+ System.Info.ShortPathName+ System.Permissions+ System.Process.Pager+ System.Terminal+ Paths_stack+ hs-source-dirs: src/+ other-modules:+ Stack.Types.Cache+ autogen-modules:+ Paths_stack+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path+ -fwarn-identities+ build-depends:+ Cabal >=2.4.0.1,+ aeson >=1.2.4.0,+ annotated-wl-pprint >=0.7.0,+ ansi-terminal >=0.9,+ array >=0.5.2.0,+ async >=2.1.1.1,+ attoparsec >=0.13.2.2,+ base >=4.10 && <5,+ base64-bytestring >=1.0.0.1,+ bytestring >=0.10.8.2,+ colour >=2.3.4,+ conduit >=1.3.0.3,+ conduit-extra >=1.3.0,+ containers >=0.5.10.2,+ cryptonite >=0.25,+ cryptonite-conduit >=0.2.2,+ deepseq >=1.4.3.0,+ directory >=1.3.0.2,+ echo >=0.1.3,+ exceptions >=0.8.3,+ extra >=1.6.9,+ file-embed >=0.0.10.1,+ filelock >=0.1.1.2,+ filepath >=1.4.1.2,+ fsnotify >=0.3.0.1,+ generic-deriving >=1.12.2,+ hackage-security >=0.5.3.0,+ hashable >=1.2.7.0,+ hi-file-parser >=0.1.0.0,+ hpack >=0.31.2,+ hpc >=0.6.0.3,+ http-client >=0.5.13.1,+ http-client-tls >=0.3.5.3,+ http-conduit >=2.3.2,+ http-download >=0.1.0.0,+ http-types >=0.12.1,+ memory >=0.14.16,+ microlens >=0.4.8.3,+ mintty >=0.1.2,+ mono-traversable >=1.0.9.0,+ mtl >=2.2.2,+ mustache >=2.3.0,+ neat-interpolation >=0.3.2.1,+ network-uri >=2.6.1.0,+ open-browser >=0.2.1.0,+ optparse-applicative >=0.14.2.0,+ pantry >=0.1.1.0,+ path >=0.6.1,+ path-io >=1.3.3,+ persistent >=2.9.2,+ persistent-sqlite >=2.9.3,+ persistent-template >=2.5.4,+ pretty >=1.1.3.3,+ primitive >=0.6.4.0,+ process >=1.6.3.0,+ project-template >=0.2.0.1,+ regex-applicative-text >=0.1.0.1,+ resource-pool >=0.2.3.2,+ resourcet >=1.2.1,+ retry >=0.7.6.3,+ rio >=0.1.10.0,+ rio-prettyprint >=0.1.0.0,+ semigroups >=0.18.5,+ split >=0.2.3.3,+ stm >=2.4.5.0,+ streaming-commons >=0.1.19,+ tar >=0.5.1.0,+ template-haskell >=2.12.0.0,+ temporary >=1.2.1.1,+ terminal-size >=0.3.2.1,+ text >=1.2.3.0,+ text-metrics >=0.3.0,+ th-reify-many >=0.1.8,+ time >=1.8.0.2,+ tls >=1.4.1,+ transformers >=0.5.2.0,+ typed-process >=0.2.6.0,+ unicode-transforms >=0.3.4,+ unix-compat >=0.5.0.1,+ unliftio >=0.2.8.0,+ unordered-containers >=0.2.9.0,+ vector >=0.12.0.1,+ yaml >=0.10.4.0,+ zip-archive >=0.3.3,+ zlib >=0.6.2+ + if os(windows)+ cpp-options: -DWINDOWS+ build-depends:+ Win32 -any+ else+ build-tools: hsc2hs -any+ build-depends:+ unix >=2.7.2.2+ + if os(windows)+ hs-source-dirs: src/windows/+ other-modules:+ System.Uname+ else+ c-sources:+ src/unix/cbits/uname.c+ hs-source-dirs: src/unix/+ other-modules:+ System.Uname++executable stack+ main-is: Main.hs+ hs-source-dirs: src/main+ other-modules:+ BuildInfo+ Build_stack+ Paths_stack+ autogen-modules:+ Build_stack+ Paths_stack+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path+ -threaded -rtsopts+ build-depends:+ Cabal >=2.4.0.1,+ aeson >=1.2.4.0,+ annotated-wl-pprint >=0.7.0,+ ansi-terminal >=0.9,+ array >=0.5.2.0,+ async >=2.1.1.1,+ attoparsec >=0.13.2.2,+ base >=4.10 && <5,+ base64-bytestring >=1.0.0.1,+ bytestring >=0.10.8.2,+ colour >=2.3.4,+ conduit >=1.3.0.3,+ conduit-extra >=1.3.0,+ containers >=0.5.10.2,+ cryptonite >=0.25,+ cryptonite-conduit >=0.2.2,+ deepseq >=1.4.3.0,+ directory >=1.3.0.2,+ echo >=0.1.3,+ exceptions >=0.8.3,+ extra >=1.6.9,+ file-embed >=0.0.10.1,+ filelock >=0.1.1.2,+ filepath >=1.4.1.2,+ fsnotify >=0.3.0.1,+ generic-deriving >=1.12.2,+ hackage-security >=0.5.3.0,+ hashable >=1.2.7.0,+ hi-file-parser >=0.1.0.0,+ hpack >=0.31.2,+ hpc >=0.6.0.3,+ http-client >=0.5.13.1,+ http-client-tls >=0.3.5.3,+ http-conduit >=2.3.2,+ http-download >=0.1.0.0,+ http-types >=0.12.1,+ memory >=0.14.16,+ microlens >=0.4.8.3,+ mintty >=0.1.2,+ mono-traversable >=1.0.9.0,+ mtl >=2.2.2,+ mustache >=2.3.0,+ neat-interpolation >=0.3.2.1,+ network-uri >=2.6.1.0,+ open-browser >=0.2.1.0,+ optparse-applicative >=0.14.2.0,+ pantry >=0.1.1.0,+ path >=0.6.1,+ path-io >=1.3.3,+ persistent >=2.9.2,+ persistent-sqlite >=2.9.3,+ persistent-template >=2.5.4,+ pretty >=1.1.3.3,+ primitive >=0.6.4.0,+ process >=1.6.3.0,+ project-template >=0.2.0.1,+ regex-applicative-text >=0.1.0.1,+ resource-pool >=0.2.3.2,+ resourcet >=1.2.1,+ retry >=0.7.6.3,+ rio >=0.1.10.0,+ rio-prettyprint >=0.1.0.0,+ semigroups >=0.18.5,+ split >=0.2.3.3,+ stack -any,+ stm >=2.4.5.0,+ streaming-commons >=0.1.19,+ tar >=0.5.1.0,+ template-haskell >=2.12.0.0,+ temporary >=1.2.1.1,+ terminal-size >=0.3.2.1,+ text >=1.2.3.0,+ text-metrics >=0.3.0,+ th-reify-many >=0.1.8,+ time >=1.8.0.2,+ tls >=1.4.1,+ transformers >=0.5.2.0,+ typed-process >=0.2.6.0,+ unicode-transforms >=0.3.4,+ unix-compat >=0.5.0.1,+ unliftio >=0.2.8.0,+ unordered-containers >=0.2.9.0,+ vector >=0.12.0.1,+ yaml >=0.10.4.0,+ zip-archive >=0.3.3,+ zlib >=0.6.2+ + if os(windows)+ cpp-options: -DWINDOWS+ build-depends:+ Win32 -any+ else+ build-tools: hsc2hs -any+ build-depends:+ unix >=2.7.2.2+ + if flag(static)+ ld-options: -static -pthread+ + if !flag(disable-git-info)+ cpp-options: -DUSE_GIT_INFO+ build-depends:+ githash >=0.1.3.0,+ optparse-simple >=0.1.0+ + if flag(hide-dependency-versions)+ cpp-options: -DHIDE_DEP_VERSIONS+ + if flag(supported-build)+ cpp-options: -DSUPPORTED_BUILD++executable stack-integration-test+ main-is: IntegrationSpec.hs+ hs-source-dirs: test/integration test/integration/lib+ other-modules:+ StackTest+ Paths_stack+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path+ -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ Cabal >=2.4.0.1,+ aeson >=1.2.4.0,+ annotated-wl-pprint >=0.7.0,+ ansi-terminal >=0.9,+ array >=0.5.2.0,+ async >=2.1.1.1,+ attoparsec >=0.13.2.2,+ base >=4.10 && <5,+ base64-bytestring >=1.0.0.1,+ bytestring >=0.10.8.2,+ colour >=2.3.4,+ conduit >=1.3.0.3,+ conduit-extra >=1.3.0,+ containers >=0.5.10.2,+ cryptonite >=0.25,+ cryptonite-conduit >=0.2.2,+ deepseq >=1.4.3.0,+ directory >=1.3.0.2,+ echo >=0.1.3,+ exceptions >=0.8.3,+ extra >=1.6.9,+ file-embed >=0.0.10.1,+ filelock >=0.1.1.2,+ filepath >=1.4.1.2,+ fsnotify >=0.3.0.1,+ generic-deriving >=1.12.2,+ hackage-security >=0.5.3.0,+ hashable >=1.2.7.0,+ hi-file-parser >=0.1.0.0,+ hpack >=0.31.2,+ hpc >=0.6.0.3,+ hspec >=2.4.8,+ http-client >=0.5.13.1,+ http-client-tls >=0.3.5.3,+ http-conduit >=2.3.2,+ http-download >=0.1.0.0,+ http-types >=0.12.1,+ memory >=0.14.16,+ microlens >=0.4.8.3,+ mintty >=0.1.2,+ mono-traversable >=1.0.9.0,+ mtl >=2.2.2,+ mustache >=2.3.0,+ neat-interpolation >=0.3.2.1,+ network-uri >=2.6.1.0,+ open-browser >=0.2.1.0,+ optparse-applicative >=0.14.2.0,+ optparse-generic >=1.3.0,+ pantry >=0.1.1.0,+ path >=0.6.1,+ path-io >=1.3.3,+ persistent >=2.9.2,+ persistent-sqlite >=2.9.3,+ persistent-template >=2.5.4,+ pretty >=1.1.3.3,+ primitive >=0.6.4.0,+ process >=1.6.3.0,+ project-template >=0.2.0.1,+ regex-applicative-text >=0.1.0.1,+ resource-pool >=0.2.3.2,+ resourcet >=1.2.1,+ retry >=0.7.6.3,+ rio >=0.1.10.0,+ rio-prettyprint >=0.1.0.0,+ semigroups >=0.18.5,+ split >=0.2.3.3,+ stm >=2.4.5.0,+ streaming-commons >=0.1.19,+ tar >=0.5.1.0,+ template-haskell >=2.12.0.0,+ temporary >=1.2.1.1,+ terminal-size >=0.3.2.1,+ text >=1.2.3.0,+ text-metrics >=0.3.0,+ th-reify-many >=0.1.8,+ time >=1.8.0.2,+ tls >=1.4.1,+ transformers >=0.5.2.0,+ typed-process >=0.2.6.0,+ unicode-transforms >=0.3.4,+ unix-compat >=0.5.0.1,+ unliftio >=0.2.8.0,+ unordered-containers >=0.2.9.0,+ vector >=0.12.0.1,+ yaml >=0.10.4.0,+ zip-archive >=0.3.3,+ zlib >=0.6.2+ + if os(windows)+ cpp-options: -DWINDOWS+ build-depends:+ Win32 -any+ else+ build-tools: hsc2hs -any+ build-depends:+ unix >=2.7.2.2+ + if !flag(integration-tests)+ buildable: False++test-suite stack-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs: src/test+ other-modules:+ Stack.ArgsSpec+ Stack.Build.ExecuteSpec+ Stack.Build.TargetSpec+ Stack.Config.DockerSpec+ Stack.ConfigSpec+ Stack.DotSpec+ Stack.Ghci.PortableFakePaths+ Stack.Ghci.ScriptSpec+ Stack.GhciSpec+ Stack.LockSpec+ Stack.NixSpec+ Stack.PackageDumpSpec+ Stack.Types.TemplateNameSpec+ Stack.UploadSpec+ Paths_stack+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path+ -threaded+ build-depends:+ Cabal >=2.4.0.1,+ QuickCheck >=2.10.1,+ aeson >=1.2.4.0,+ annotated-wl-pprint >=0.7.0,+ ansi-terminal >=0.9,+ array >=0.5.2.0,+ async >=2.1.1.1,+ attoparsec >=0.13.2.2,+ base >=4.10 && <5,+ base64-bytestring >=1.0.0.1,+ bytestring >=0.10.8.2,+ colour >=2.3.4,+ conduit >=1.3.0.3,+ conduit-extra >=1.3.0,+ containers >=0.5.10.2,+ cryptonite >=0.25,+ cryptonite-conduit >=0.2.2,+ deepseq >=1.4.3.0,+ directory >=1.3.0.2,+ echo >=0.1.3,+ exceptions >=0.8.3,+ extra >=1.6.9,+ file-embed >=0.0.10.1,+ filelock >=0.1.1.2,+ filepath >=1.4.1.2,+ fsnotify >=0.3.0.1,+ generic-deriving >=1.12.2,+ hackage-security >=0.5.3.0,+ hashable >=1.2.7.0,+ hi-file-parser >=0.1.0.0,+ hpack >=0.31.2,+ hpc >=0.6.0.3,+ hspec >=2.4.8,+ http-client >=0.5.13.1,+ http-client-tls >=0.3.5.3,+ http-conduit >=2.3.2,+ http-download >=0.1.0.0,+ http-types >=0.12.1,+ memory >=0.14.16,+ microlens >=0.4.8.3,+ mintty >=0.1.2,+ mono-traversable >=1.0.9.0,+ mtl >=2.2.2,+ mustache >=2.3.0,+ neat-interpolation >=0.3.2.1,+ network-uri >=2.6.1.0,+ open-browser >=0.2.1.0,+ optparse-applicative >=0.14.2.0,+ pantry >=0.1.1.0,+ path >=0.6.1,+ path-io >=1.3.3,+ persistent >=2.9.2,+ persistent-sqlite >=2.9.3,+ persistent-template >=2.5.4,+ pretty >=1.1.3.3,+ primitive >=0.6.4.0,+ process >=1.6.3.0,+ project-template >=0.2.0.1,+ raw-strings-qq >=1.1,+ regex-applicative-text >=0.1.0.1,+ resource-pool >=0.2.3.2,+ resourcet >=1.2.1,+ retry >=0.7.6.3,+ rio >=0.1.10.0,+ rio-prettyprint >=0.1.0.0,+ semigroups >=0.18.5,+ smallcheck >=1.1.5,+ split >=0.2.3.3,+ stack -any,+ stm >=2.4.5.0,+ streaming-commons >=0.1.19,+ tar >=0.5.1.0,+ template-haskell >=2.12.0.0,+ temporary >=1.2.1.1,+ terminal-size >=0.3.2.1,+ text >=1.2.3.0,+ text-metrics >=0.3.0,+ th-reify-many >=0.1.8,+ time >=1.8.0.2,+ tls >=1.4.1,+ transformers >=0.5.2.0,+ typed-process >=0.2.6.0,+ unicode-transforms >=0.3.4,+ unix-compat >=0.5.0.1,+ unliftio >=0.2.8.0,+ unordered-containers >=0.2.9.0,+ vector >=0.12.0.1,+ yaml >=0.10.4.0,+ zip-archive >=0.3.3,+ zlib >=0.6.2+ + if os(windows)+ cpp-options: -DWINDOWS+ build-depends:+ Win32 -any+ else+ build-tools: hsc2hs -any+ build-depends:+ unix >=2.7.2.2
@@ -1,3 +1,5 @@+{-#LANGUAGE ScopedTypeVariables#-}+ module StackTest where import Control.Monad@@ -58,6 +60,18 @@ stack args = do ec <- stack' args unless (ec == ExitSuccess) $ error $ "Exited with exit code: " ++ show ec++-- Temporary workaround for Windows to ignore exceptions arising out+-- of Windows when we do stack clean. More info here: https://github.com/commercialhaskell/stack/issues/4936+stackCleanFull :: HasCallStack => IO ()+stackCleanFull = stackIgnoreException ["clean", "--full"]++-- Temporary workaround for Windows to ignore exceptions arising out+-- of Windows when we do stack clean. More info here: https://github.com/commercialhaskell/stack/issues/4936+stackIgnoreException :: HasCallStack => [String] -> IO ()+stackIgnoreException args = if isWindows+ then void (stack' args) `catch` (\(_e :: IOException) -> return ())+ else stack args stackErr :: HasCallStack => [String] -> IO () stackErr args = do