packages feed

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 view
@@ -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** 
doc/ChangeLog.md view
@@ -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** 
doc/GUIDE.md view
@@ -410,7 +410,7 @@  ``` dependencies:-- base >= 4.7 && 5+- base >= 4.7 && < 5 - text - filepath - containers
doc/README.md view
@@ -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).
doc/docker_integration.md view
@@ -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)
doc/install_and_upgrade.md view
@@ -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) 
doc/yaml_configuration.md view
@@ -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 
src/Stack/Build/Cache.hs view
@@ -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
src/Stack/Build/Execute.hs view
@@ -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
src/Stack/Config.hs view
@@ -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
src/Stack/Docker.hs view
@@ -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
src/Stack/Lock.hs view
@@ -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
src/Stack/Nix.hs view
@@ -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)
src/Stack/Options/DotParser.hs view
@@ -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
src/Stack/Package.hs view
@@ -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) $
src/Stack/Prelude.hs view
@@ -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
src/Stack/Runners.hs view
@@ -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
src/Stack/Setup.hs view
@@ -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
− src/Stack/Storage.hs
@@ -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]
+ src/Stack/Storage/Project.hs view
@@ -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]
+ src/Stack/Storage/User.hs view
@@ -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]
+ src/Stack/Storage/Util.hs view
@@ -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)
src/Stack/Types/Config.hs view
@@ -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
src/test/Stack/ConfigSpec.hs view
@@ -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" $
stack.cabal view
@@ -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
test/integration/lib/StackTest.hs view
@@ -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