stack 2.7.1 → 2.7.3
raw patch · 21 files changed
+378/−119 lines, 21 filesdep ~Cabaldep ~aesondep ~base
Dependency ranges changed: Cabal, aeson, base, file-embed, pantry, path-io, unliftio, unordered-containers
Files
- ChangeLog.md +33/−0
- README.md +10/−1
- doc/ChangeLog.md +33/−0
- doc/GUIDE.md +9/−5
- doc/README.md +1/−0
- doc/build_command.md +0/−2
- doc/yaml_configuration.md +2/−2
- src/Stack/Build/Cache.hs +15/−0
- src/Stack/Build/Execute.hs +10/−3
- src/Stack/Constants.hs +10/−8
- src/Stack/New.hs +1/−1
- src/Stack/Options/ScriptParser.hs +5/−0
- src/Stack/Script.hs +16/−2
- src/Stack/Setup.hs +158/−65
- src/Stack/Storage/Project.hs +3/−2
- src/Stack/Storage/User.hs +3/−2
- src/Stack/Types/Build.hs +40/−1
- src/Stack/Types/Config.hs +4/−1
- stack.cabal +21/−21
- stack.yaml +1/−3
- test/integration/lib/StackTest.hs +3/−0
ChangeLog.md view
@@ -1,6 +1,39 @@ # Changelog +## v2.7.3++**Changes since v2.7.1:**++Other enhancements:++* `stack upgrade` will download from `haskellstack.org` before trying+ `github.com`. See+ [#5288](https://github.com/commercialhaskell/stack/issues/5288)+* `stack upgrade` makes less assumptions about archive format. See+ [#5288](https://github.com/commercialhaskell/stack/issues/5288)+* Add a `--no-run` flag to the `script` command when compiling.++Bug fixes:++* GHC source builds work properly for recent GHC versions again. See+ [#5528](https://github.com/commercialhaskell/stack/issues/5528)+* `stack setup` always looks for the unpacked directory name to support+ different tar file naming conventions. See+ [#5545](https://github.com/commercialhaskell/stack/issues/5545)+* Bump `pantry` version for better OS support. See+ [pantry#33](https://github.com/commercialhaskell/pantry/issues/33)+* When building the sanity check for a new GHC install, make sure to clear+ `GHC_PACKAGE_PATH`.+* Specifying GHC RTS flags in the `stack.yaml` no longer fails with an error.+ [#5568](https://github.com/commercialhaskell/stack/pull/5568)+* `stack setup` will look in sandboxed directories for executables, not+ relying on `findExecutables. See+ [GHC issue 20074](https://gitlab.haskell.org/ghc/ghc/-/issues/20074)+* Track changes to `setup-config` properly to avoid reconfiguring on every+ change. See [#5578](https://github.com/commercialhaskell/stack/issues/5578)++ ## v2.7.1 **Changes since v2.5.1.1:**
README.md view
@@ -3,9 +3,18 @@   [](https://github.com/commercialhaskell/stack/releases)-[](https://gitter.im/commercialhaskell/stack?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Stack is a cross-platform program for developing Haskell projects. It is intended for Haskellers both new and experienced. See [haskellstack.org](http://haskellstack.org) or the [doc](./doc) directory for more information.++### Community++You can participate with the Stack community in the following areas:++* [Haskell Foundation Slack](https://join.slack.com/t/haskell-foundation/shared_invite/zt-mjh76fw0-CEjg2NbyVE8rVQDvR~0F4A)+ * `#stack-users` for general Stack discussion+ * `#stack-collaborators` for working on the Stack code base+* [Stack Google Group mailing list](https://groups.google.com/g/haskell-stack)+* [Haskell Community Discourse](https://discourse.haskell.org/)
doc/ChangeLog.md view
@@ -1,6 +1,39 @@ # Changelog +## v2.7.3++**Changes since v2.7.1:**++Other enhancements:++* `stack upgrade` will download from `haskellstack.org` before trying+ `github.com`. See+ [#5288](https://github.com/commercialhaskell/stack/issues/5288)+* `stack upgrade` makes less assumptions about archive format. See+ [#5288](https://github.com/commercialhaskell/stack/issues/5288)+* Add a `--no-run` flag to the `script` command when compiling.++Bug fixes:++* GHC source builds work properly for recent GHC versions again. See+ [#5528](https://github.com/commercialhaskell/stack/issues/5528)+* `stack setup` always looks for the unpacked directory name to support+ different tar file naming conventions. See+ [#5545](https://github.com/commercialhaskell/stack/issues/5545)+* Bump `pantry` version for better OS support. See+ [pantry#33](https://github.com/commercialhaskell/pantry/issues/33)+* When building the sanity check for a new GHC install, make sure to clear+ `GHC_PACKAGE_PATH`.+* Specifying GHC RTS flags in the `stack.yaml` no longer fails with an error.+ [#5568](https://github.com/commercialhaskell/stack/pull/5568)+* `stack setup` will look in sandboxed directories for executables, not+ relying on `findExecutables. See+ [GHC issue 20074](https://gitlab.haskell.org/ghc/ghc/-/issues/20074)+* Track changes to `setup-config` properly to avoid reconfiguring on every+ change. See [#5578](https://github.com/commercialhaskell/stack/issues/5578)++ ## v2.7.1 **Changes since v2.5.1.1:**
doc/GUIDE.md view
@@ -450,7 +450,7 @@ also known as *snapshots*. We mentioned the LTS resolvers, and you can get quite a bit of information about it at [https://www.stackage.org/lts](https://www.stackage.org/lts), including: -* The appropriate resolver value (`resolver: lts-17.9`, as is currently the latest LTS)+* The appropriate resolver value (`resolver: lts-18.3`, as is currently the latest LTS) * The GHC version used * A full list of all packages available in this snapshot * The ability to perform a Hoogle search on the packages in this snapshot@@ -467,7 +467,7 @@ ## Resolvers and changing your compiler version -Let's explore package sets a bit further. Instead of lts-17.9, let's change our+Let's explore package sets a bit further. Instead of lts-18.3, let's change our `stack.yaml` file to use [the latest nightly](https://www.stackage.org/nightly). Right now, this is currently 2020-03-24 - please see the resolve from the link above to get the latest. @@ -483,8 +483,8 @@ Continuous Integration (CI) setting, like on Travis. For example: ```-michael@d30748af6d3d:~/helloworld$ stack --resolver lts-17.9 build-Downloaded lts-17.9 build plan.+michael@d30748af6d3d:~/helloworld$ stack --resolver lts-18.3 build+Downloaded lts-18.3 build plan. # build output ... ``` @@ -1143,7 +1143,7 @@ ``` michael@d30748af6d3d:~$ stack exec --package stm -- echo I installed the stm package via --package stm Run from outside a project, using implicit global project config-Using latest snapshot resolver: lts-17.9+Using latest snapshot resolver: lts-18.3 Writing global (non-project-specific) config file to: /home/michael/.stack/global/stack.yaml Note: You can change the snapshot via the resolver field there. I installed the stm package via --package stm@@ -1156,6 +1156,10 @@ * `--no-ghc-package-path` can be used to stop the `GHC_PACKAGE_PATH` environment variable from being set. Some tools — notably cabal-install — do not behave well with that variable set.++You may also find it convenient to use `stack exec` to launch a subshell (substitute `bash` with your preferred shell) where your compiled executable is available at the front of your `PATH`:++ stack exec bash ## ghci (the repl)
doc/README.md view
@@ -30,6 +30,7 @@ On Windows, you can download and install the [Windows 64-bit Installer](https://get.haskellstack.org/stable/windows-x86_64-installer.exe).+Note that systems with antivirus software may need `stack` added to the list of "trusted" applications. For other operating systems and direct downloads, check out the [install and upgrade guide](install_and_upgrade.md).
doc/build_command.md view
@@ -96,8 +96,6 @@ the local packages." This will result in an error if multiple packages have a component with the same name. To continue the above example, `stack build :mytestsuite`.- * Side note: the commonly requested `run` command is not available- because it's a simple combination of `stack build :exename && stack exec exename` * *directory*, e.g. `stack build foo/bar`, will find all local packages that exist in the given directory hierarchy and then follow the same procedure as
doc/yaml_configuration.md view
@@ -41,7 +41,7 @@ built when needed. Shadowing semantics, described-[here](http://docs.haskellstack.org/en/stable/architecture/#shadowing), are+[here](https://docs.haskellstack.org/en/v1.5.1/architecture/#shadowing), are applied to your configuration. So, if you add a package to your `packages` list, it will be used even if you're using a snapshot that specifies a particular version. Similarly, `extra-deps` will shadow the version specified in the@@ -531,7 +531,7 @@ #### Bootstrapping compiler Building GHC from source requires a working GHC (known as the bootstrap-compiler). As we use a Stack based version of Hadrian (`hadrian/build.stack.sh` in+compiler). As we use a Stack based version of Hadrian (`hadrian/build-stack` in GHC sources), the bootstrap compiler is configured into `hadrian/stack.yaml` and fully managed by Stack.
src/Stack/Build/Cache.hs view
@@ -21,6 +21,7 @@ , writeBuildCache , writeConfigCache , writeCabalMod+ , writeSetupConfigMod , TestStatus (..) , setTestStatus , getTestStatus@@ -179,6 +180,20 @@ -> RIO env () writeCabalMod dir x = do fp <- configCabalMod dir+ writeBinaryFileAtomic fp "Just used for its modification time"+ liftIO $ setFileTimes (toFilePath fp) x x++-- | See 'tryGetSetupConfigMod'+writeSetupConfigMod+ :: HasEnvConfig env+ => Path Abs Dir+ -> Maybe CTime+ -> RIO env ()+writeSetupConfigMod dir Nothing = do+ fp <- configSetupConfigMod dir+ ignoringAbsence $ removeFile fp+writeSetupConfigMod dir (Just x) = do+ fp <- configSetupConfigMod dir writeBinaryFileAtomic fp "Just used for its modification time" liftIO $ setFileTimes (toFilePath fp) x x
src/Stack/Build/Execute.hs view
@@ -845,8 +845,10 @@ ensureConfig newConfigCache pkgDir ExecuteEnv {..} announce cabal cabalfp task = do newCabalMod <- liftIO $ modificationTime <$> getFileStatus (toFilePath cabalfp) setupConfigfp <- setupConfigFromDir pkgDir- newSetupConfigMod <- liftIO $ either (const Nothing) (Just . modificationTime) <$>- tryJust (guard . isDoesNotExistError) (getFileStatus (toFilePath setupConfigfp))+ let getNewSetupConfigMod =+ liftIO $ either (const Nothing) (Just . modificationTime) <$>+ tryJust (guard . isDoesNotExistError) (getFileStatus (toFilePath setupConfigfp))+ newSetupConfigMod <- getNewSetupConfigMod -- See https://github.com/commercialhaskell/stack/issues/3554 taskAnyMissingHack <- view $ actualCompilerVersionL.to getGhcVersion.to (< mkVersion [8, 4]) needConfig <-@@ -905,6 +907,11 @@ TTLocalMutable{} -> writeConfigCache pkgDir newConfigCache TTRemotePackage{} -> return () writeCabalMod pkgDir newCabalMod+ -- This file gets updated one more time by the configure step, so get+ -- the most recent value. We could instead change our logic above to+ -- check if our config mod file is newer than the file above, but this+ -- seems reasonable too.+ getNewSetupConfigMod >>= writeSetupConfigMod pkgDir return needConfig where@@ -997,7 +1004,7 @@ announce $ "still blocking for directory lock on " <> fromString (toFilePath lockFP) <> "; maybe another Stack process is running?"- withCompanion complainer $+ withCompanion (\x -> complainer x) $ \stopComplaining -> withRunInIO $ \run -> withFileLock (toFilePath lockFP) Exclusive $ \_ ->
src/Stack/Constants.hs view
@@ -115,8 +115,8 @@ ,relFileStackDotTmpDotExe ,relFileStackDotTmp ,ghcShowOptionsOutput- ,hadrianCmdWindows- ,hadrianCmdPosix+ ,hadrianScriptsWindows+ ,hadrianScriptsPosix ,usrLibDirs ,testGhcEnvRelFile ,relFileBuildLock@@ -533,13 +533,15 @@ ghcShowOptionsOutput = $(TH.runIO (readProcess "ghc" ["--show-options"] "") >>= TH.lift . lines) --- | Relative path inside a GHC repo to the Hadrian build batch script-hadrianCmdWindows :: Path Rel File-hadrianCmdWindows = $(mkRelFile "hadrian/build.stack.bat")+-- | Relative paths inside a GHC repo to the Hadrian build batch script.+-- The second path is maintained for compatibility with older GHC versions.+hadrianScriptsWindows :: [Path Rel File]+hadrianScriptsWindows = [$(mkRelFile "hadrian/build-stack.bat"), $(mkRelFile "hadrian/build.stack.bat")] --- | Relative path inside a GHC repo to the Hadrian build shell script-hadrianCmdPosix :: Path Rel File-hadrianCmdPosix = $(mkRelFile "hadrian/build.stack.sh")+-- | Relative paths inside a GHC repo to the Hadrian build shell script+-- The second path is maintained for compatibility with older GHC versions.+hadrianScriptsPosix :: [Path Rel File]+hadrianScriptsPosix = [$(mkRelFile "hadrian/build-stack"), $(mkRelFile "hadrian/build.stack.sh")] -- | Used in Stack.Setup for detecting libtinfo, see comments at use site usrLibDirs :: [Path Abs Dir]
src/Stack/New.hs view
@@ -421,7 +421,7 @@ show (AttemptedOverwrites fps) = "The template would create the following files, but they already exist:\n" <> unlines (map ((" " ++) . toFilePath) fps) <>- "Use --force to ignore this, and overwite these files."+ "Use --force to ignore this, and overwrite these files." show (FailedToDownloadTemplatesHelp ex) = "Failed to download `stack templates` help. The HTTP error was: " <> show ex show (BadTemplatesHelpEncoding url err) =
src/Stack/Options/ScriptParser.hs view
@@ -13,6 +13,7 @@ , soCompile :: !ScriptExecute , soGhcOptions :: ![String] , soScriptExtraDeps :: ![PackageIdentifierRevision]+ , soShouldRun :: !ShouldRun } deriving Show @@ -22,6 +23,9 @@ | SEOptimize deriving Show +data ShouldRun = YesRun | NoRun+ deriving Show+ scriptOptsParser :: Parser ScriptOpts scriptOptsParser = ScriptOpts <$> many (strOption@@ -48,5 +52,6 @@ (long "extra-dep" <> metavar "PACKAGE-VERSION" <> help "Extra dependencies to be added to the snapshot"))+ <*> (flag' NoRun (long "no-run" <> help "Don't run, just compile.") <|> pure YesRun) where extraDepRead = eitherReader $ mapLeft show . parsePackageIdentifierRevision . fromString
src/Stack/Script.hs view
@@ -84,6 +84,15 @@ , globalStackYaml = SYLNoProject $ soScriptExtraDeps opts } + case soShouldRun opts of+ YesRun -> pure ()+ NoRun -> do+ unless (null $ soArgs opts) $ throwString "--no-run incompatible with arguments"+ case soCompile opts of+ SEInterpret -> throwString "--no-run requires either --compile or --optimize"+ SECompile -> pure ()+ SEOptimize -> pure ()+ -- Optimization: if we're compiling, and the executable is newer -- than the source file, run it immediately. local (over globalOptsL modifyGO) $@@ -93,11 +102,16 @@ SEOptimize -> shortCut file scriptDir where+ runCompiled file = do+ let exeName = toExeName $ toFilePath file+ case soShouldRun opts of+ YesRun -> exec exeName (soArgs opts)+ NoRun -> logInfo $ "Compilation finished, executable available at " <> fromString exeName shortCut file scriptDir = handleIO (const $ longWay file scriptDir) $ do srcMod <- getModificationTime file exeMod <- Dir.getModificationTime $ toExeName $ toFilePath file if srcMod < exeMod- then exec (toExeName $ toFilePath file) (soArgs opts)+ then runCompiled file else longWay file scriptDir longWay file scriptDir =@@ -168,7 +182,7 @@ compilerExeName (ghcArgs ++ [toFilePath file]) (void . readProcessStdout_)- exec (toExeName $ toFilePath file) (soArgs opts)+ runCompiled file toPackageName = reverse . drop 1 . dropWhile (/= '-') . reverse
src/Stack/Setup.hs view
@@ -54,10 +54,13 @@ import Distribution.Text (simpleParse) import Distribution.Types.PackageName (mkPackageName) import Distribution.Version (mkVersion)+import Network.HTTP.Client (redirectCount) import Network.HTTP.StackClient (CheckHexDigest (..), HashCheck (..), getResponseBody, getResponseStatusCode, httpLbs, httpJSON, mkDownloadRequest, parseRequest, parseUrlThrow, setGithubHeaders,- setHashChecks, setLengthCheck, verifiedDownloadWithProgress, withResponse)+ setHashChecks, setLengthCheck, verifiedDownloadWithProgress, withResponse,+ setRequestMethod)+import Network.HTTP.Simple (getResponseHeader) import Path hiding (fileExtension) import Path.CheckInstall (warnInstallSearchPathIssues) import Path.Extended (fileExtension)@@ -525,7 +528,7 @@ Just x -> return x Nothing -> throwString $ "MSYS2 not found for " ++ T.unpack osKey let tool = Tool (PackageIdentifier (mkPackageName "msys2") version)- Just <$> downloadAndInstallTool (configLocalPrograms config) info tool (installMsys2Windows osKey si)+ Just <$> downloadAndInstallTool (configLocalPrograms config) info tool (installMsys2Windows si) | otherwise -> do logWarn "Continuing despite missing tool: msys2" return Nothing@@ -664,18 +667,36 @@ WCGhc version -> pure ["ghc-" ++ versionString version, "ghc"] WCGhcGit{} -> pure ["ghc"] WCGhcjs{} -> throwIO GhcjsNotSupported++ -- Previously, we used findExecutable to locate these executables. This was+ -- actually somewhat sloppy, as it could discover executables outside of the+ -- sandbox. This led to a specific issue on Windows with GHC 9.0.1. See+ -- https://gitlab.haskell.org/ghc/ghc/-/issues/20074. Instead, now, we look+ -- on the paths specified only. let loop [] = do logError $ "Looked for sandboxed compiler named one of: " <> displayShow names logError $ "Could not find it on the paths " <> displayShow (edBins paths) throwString "Could not find sandboxed compiler" loop (x:xs) = do- res <- findExecutable x+ res <- liftIO $ D.findExecutablesInDirectories (map toFilePath (edBins paths)) x case res of- Left _ -> loop xs- Right y -> parseAbsFile y- compiler <- withProcessContext menv $ loop names+ [] -> loop xs+ compiler:rest -> do+ unless (null rest) $ do+ logWarn "Found multiple candidate compilers:"+ for_ res $ \y -> logWarn $ "- " <> fromString y+ logWarn $ "This usually indicates a failed installation. Trying anyway with " <> fromString compiler+ parseAbsFile compiler+ compiler <- withProcessContext menv $ do+ compiler <- loop names - when (soptsSanityCheck sopts) $ sanityCheck compiler+ -- Run this here to ensure that the sanity check uses the modified+ -- environment, otherwise we may infect GHC_PACKAGE_PATH and break sanity+ -- checks.+ when (soptsSanityCheck sopts) $ sanityCheck compiler++ pure compiler+ cp <- pathsFromCompiler wc compilerBuild True compiler pure (cp, paths) @@ -836,10 +857,13 @@ , "--flavour=" <> flavour -- selected flavour , "binary-dist" ]- hadrianCmd- | osIsWindows = hadrianCmdWindows- | otherwise = hadrianCmdPosix+ hadrianScripts+ | osIsWindows = hadrianScriptsWindows+ | otherwise = hadrianScriptsPosix + foundHadrianPaths <- filterM doesFileExist $ (cwd </>) <$> hadrianScripts+ hadrianPath <- maybe (throwString "No Hadrian build script found") pure $ listToMaybe foundHadrianPaths+ logSticky $ "Building GHC from source with `" <> RIO.display flavour <> "` flavour. It can take a long time (more than one hour)..."@@ -847,7 +871,7 @@ -- We need to provide an absolute path to the script since -- the process package only sets working directory _after_ -- discovering the executable- proc (toFilePath (cwd </> hadrianCmd)) hadrianArgs runProcess_+ proc (toFilePath hadrianPath) hadrianArgs runProcess_ -- find the bindist and install it bindistPath <- parseRelDir "_build/bindist"@@ -872,8 +896,8 @@ } ghcdlinfo = GHCDownloadInfo mempty mempty dlinfo installer- | osIsWindows = installGHCWindows Nothing- | otherwise = installGHCPosix Nothing ghcdlinfo+ | osIsWindows = installGHCWindows+ | otherwise = installGHCPosix ghcdlinfo si <- runMemoized getSetupInfo' _ <- downloadAndInstallTool (configLocalPrograms config)@@ -1136,8 +1160,8 @@ config <- view configL let installer = case configPlatform config of- Platform _ Cabal.Windows -> installGHCWindows (Just selectedVersion)- _ -> installGHCPosix (Just selectedVersion) downloadInfo+ Platform _ Cabal.Windows -> installGHCWindows+ _ -> installGHCPosix downloadInfo logInfo $ "Preparing to install GHC" <> (case ghcVariant of@@ -1309,15 +1333,14 @@ | SevenZ installGHCPosix :: HasConfig env- => Maybe Version- -> GHCDownloadInfo+ => GHCDownloadInfo -> SetupInfo -> Path Abs File -> ArchiveType -> Path Abs Dir -> Path Abs Dir -> RIO env ()-installGHCPosix mversion downloadInfo _ archiveFile archiveType tempDir destDir = do+installGHCPosix downloadInfo _ archiveFile archiveType tempDir destDir = do platform <- view platformL menv0 <- view processContextL menv <- mkProcessContext (removeHaskellEnvVars (view envVarsL menv0))@@ -1380,11 +1403,7 @@ logDebug $ "Unpacking " <> fromString (toFilePath archiveFile) runStep "unpacking" tempDir mempty tarTool [compOpt : "xf", toFilePath archiveFile] - dir <- case mversion of- Just version -> do- relDir <- parseRelDir $ "ghc-" ++ versionString version- return (tempDir </> relDir)- Nothing -> expectSingleUnpackedDir archiveFile tempDir+ dir <- expectSingleUnpackedDir archiveFile tempDir logSticky "Configuring GHC ..." runStep "configuring" dir@@ -1430,27 +1449,24 @@ Right x' -> return $ Right x' installGHCWindows :: HasBuildConfig env- => Maybe Version- -> SetupInfo+ => SetupInfo -> Path Abs File -> ArchiveType -> Path Abs Dir -> Path Abs Dir -> RIO env ()-installGHCWindows mversion si archiveFile archiveType _tempDir destDir = do- tarComponent <- mapM (\v -> parseRelDir $ "ghc-" ++ versionString v) mversion- withUnpackedTarball7z "GHC" si archiveFile archiveType tarComponent destDir+installGHCWindows si archiveFile archiveType _tempDir destDir = do+ withUnpackedTarball7z "GHC" si archiveFile archiveType destDir logInfo $ "GHC installed to " <> fromString (toFilePath destDir) installMsys2Windows :: HasBuildConfig env- => Text -- ^ OS Key- -> SetupInfo+ => SetupInfo -> Path Abs File -> ArchiveType -> Path Abs Dir -> Path Abs Dir -> RIO env ()-installMsys2Windows osKey si archiveFile archiveType _tempDir destDir = do+installMsys2Windows si archiveFile archiveType _tempDir destDir = do exists <- liftIO $ D.doesDirectoryExist $ toFilePath destDir when exists $ liftIO (D.removeDirectoryRecursive $ toFilePath destDir) `catchIO` \e -> do logError $@@ -1458,8 +1474,7 @@ fromString (toFilePath destDir) throwM e - msys <- parseRelDir $ "msys" ++ T.unpack (fromMaybe "32" $ T.stripPrefix "windows" osKey)- withUnpackedTarball7z "MSYS2" si archiveFile archiveType (Just msys) destDir+ withUnpackedTarball7z "MSYS2" si archiveFile archiveType destDir -- I couldn't find this officially documented anywhere, but you need to run@@ -1488,10 +1503,9 @@ -> SetupInfo -> Path Abs File -- ^ Path to archive file -> ArchiveType- -> Maybe (Path Rel Dir) -- ^ Name of directory expected in archive. If Nothing, expects a single folder. -> Path Abs Dir -- ^ Destination directory. -> RIO env ()-withUnpackedTarball7z name si archiveFile archiveType msrcDir destDir = do+withUnpackedTarball7z name si archiveFile archiveType destDir = do suffix <- case archiveType of TarXz -> return ".xz"@@ -1509,9 +1523,7 @@ liftIO $ ignoringAbsence (removeDirRecur destDir) run7z tmpDir archiveFile run7z tmpDir (tmpDir </> tarFile)- absSrcDir <- case msrcDir of- Just srcDir -> return $ tmpDir </> srcDir- Nothing -> expectSingleUnpackedDir archiveFile tmpDir+ absSrcDir <- expectSingleUnpackedDir archiveFile tmpDir renameDir absSrcDir destDir expectSingleUnpackedDir :: (MonadIO m, MonadThrow m) => Path Abs File -> Path Abs Dir -> m (Path Abs Dir)@@ -1782,14 +1794,92 @@ -- Binary Stack upgrades -newtype StackReleaseInfo = StackReleaseInfo Value+-- | Information on a binary release of Stack+data StackReleaseInfo+ = SRIGithub !Value+ -- ^ Metadata downloaded from GitHub releases about available binaries.+ | SRIHaskellStackOrg !HaskellStackOrg+ -- ^ Information on the latest available binary for the current platforms. -downloadStackReleaseInfo :: (MonadIO m, MonadThrow m)- => Maybe String -- Github org- -> Maybe String -- Github repo- -> Maybe String -- ^ optional version- -> m StackReleaseInfo-downloadStackReleaseInfo morg mrepo mver = liftIO $ do+data HaskellStackOrg = HaskellStackOrg+ { hsoUrl :: !Text+ , hsoVersion :: !Version+ }+ deriving Show++downloadStackReleaseInfo+ :: (HasPlatform env, HasLogFunc env)+ => Maybe String -- Github org+ -> Maybe String -- Github repo+ -> Maybe String -- ^ optional version+ -> RIO env StackReleaseInfo+downloadStackReleaseInfo Nothing Nothing Nothing = do+ platform <- view platformL+ -- Fallback list of URLs to try for upgrading.+ let urls0 =+ case platform of+ Platform X86_64 Cabal.Linux ->+ [ "https://get.haskellstack.org/upgrade/linux-x86_64-static.tar.gz"+ , "https://get.haskellstack.org/upgrade/linux-x86_64.tar.gz"+ ]+ Platform X86_64 Cabal.OSX ->+ [ "https://get.haskellstack.org/upgrade/osx-x86_64.tar.gz"+ ]+ Platform X86_64 Cabal.Windows ->+ [ "https://get.haskellstack.org/upgrade/windows-x86_64.tar.gz"+ ]+ _ -> []+ -- Helper function: extract the version from a GitHub releases URL.+ let extractVersion loc = do+ version0 <-+ case reverse $ splitOn "/" $ T.unpack loc of+ _final:version0:_ -> Right version0+ _ -> Left $ "Insufficient pieces in location: " ++ show loc+ version1 <- maybe (Left "no leading v on version") Right $ stripPrefix "v" version0+ maybe (Left $ "Invalid version: " ++ show version1) Right $ parseVersion version1++ -- Try out different URLs. If we've exhausted all of them, fall back to GitHub.+ loop [] = do+ logDebug "Could not get binary from haskellstack.org, trying GitHub"+ downloadStackReleaseInfoGithub Nothing Nothing Nothing++ -- Try the next URL+ loop (url:urls) = do+ -- Make a HEAD request without any redirects+ req <- setRequestMethod "HEAD" <$> parseRequest (T.unpack url)+ res <- httpLbs req { redirectCount = 0 }++ -- Look for a redirect. We're looking for a standard GitHub releases+ -- URL where we can extract version information from.+ case getResponseHeader "location" res of+ [] -> logDebug "No location header found, continuing" *> loop urls+ -- Exactly one location header.+ [locBS] ->+ case decodeUtf8' locBS of+ Left e -> logDebug ("Invalid UTF8: " <> displayShow (locBS, e)) *> loop urls+ Right loc ->+ case extractVersion loc of+ Left s -> logDebug ("No version found: " <> displayShow (url, loc, s)) *> loop (loc:urls)+ -- We found a valid URL, let's use it!+ Right version -> do+ let hso = HaskellStackOrg+ { hsoUrl = loc+ , hsoVersion = version+ }+ logDebug $ "Downloading from haskellstack.org: " <> displayShow hso+ pure $ SRIHaskellStackOrg hso+ locs -> logDebug ("Multiple location headers found: " <> displayShow locs) *> loop urls+ loop urls0+downloadStackReleaseInfo morg mrepo mver = downloadStackReleaseInfoGithub morg mrepo mver++-- | Same as above, but always uses Github+downloadStackReleaseInfoGithub+ :: (MonadIO m, MonadThrow m)+ => Maybe String -- Github org+ -> Maybe String -- Github repo+ -> Maybe String -- ^ optional version+ -> m StackReleaseInfo+downloadStackReleaseInfoGithub morg mrepo mver = liftIO $ do let org = fromMaybe "commercialhaskell" morg repo = fromMaybe "stack" mrepo let url = concat@@ -1806,7 +1896,7 @@ res <- httpJSON $ setGithubHeaders req let code = getResponseStatusCode res if code >= 200 && code < 300- then return $ StackReleaseInfo $ getResponseBody res+ then return $ SRIGithub $ getResponseBody res else throwString $ "Could not get release information for Stack from: " ++ url preferredPlatforms :: (MonadReader env m, HasPlatform env, MonadThrow m)@@ -1901,7 +1991,7 @@ `catchAny` (logError . displayShow) where - findArchive (StackReleaseInfo val) pattern = do+ findArchive (SRIGithub val) pattern = do Object top <- return val Array assets <- HashMap.lookup "assets" top getFirst $ fold $ fmap (First . findMatch pattern') assets@@ -1915,6 +2005,7 @@ String url <- HashMap.lookup "browser_download_url" o Just url findMatch _ _ = Nothing+ findArchive (SRIHaskellStackOrg hso) _ = pure $ hsoUrl hso handleTarball :: Path Abs File -> Bool -> T.Text -> IO () handleTarball tmpFile isWindows url = do@@ -1930,25 +2021,26 @@ , T.unpack url ] loop (Tar.Fail e) = throwM e- loop (Tar.Next e es)- | Tar.entryPath e == exeName =- case Tar.entryContent e of- Tar.NormalFile lbs _ -> do- ensureDir destDir- LBS.writeFile (toFilePath tmpFile) lbs- _ -> error $ concat- [ "Invalid file type for tar entry named "- , exeName- , " downloaded from "- , T.unpack url- ]- | otherwise = loop es+ loop (Tar.Next e es) =+ case FP.splitPath (Tar.entryPath e) of+ -- Ignore the first component, see: https://github.com/commercialhaskell/stack/issues/5288+ [_ignored, name] | name == exeName -> do+ case Tar.entryContent e of+ Tar.NormalFile lbs _ -> do+ ensureDir destDir+ LBS.writeFile (toFilePath tmpFile) lbs+ _ -> error $ concat+ [ "Invalid file type for tar entry named "+ , Tar.entryPath e+ , " downloaded from "+ , T.unpack url+ ]+ _ -> loop es loop entries where- -- The takeBaseName drops the .gz, dropExtension drops the .tar- exeName =- let base = FP.dropExtension (FP.takeBaseName (T.unpack url)) FP.</> "stack"- in if isWindows then base FP.<.> "exe" else base+ exeName+ | isWindows = "stack.exe"+ | otherwise = "stack" -- | Ensure that the Stack executable download is in the same location -- as the currently running executable. See:@@ -2006,8 +2098,9 @@ | otherwise -> throwM e getDownloadVersion :: StackReleaseInfo -> Maybe Version-getDownloadVersion (StackReleaseInfo val) = do+getDownloadVersion (SRIGithub val) = do Object o <- Just val String rawName <- HashMap.lookup "name" o -- drop the "v" at the beginning of the name parseVersion $ T.unpack (T.drop 1 rawName)+getDownloadVersion (SRIHaskellStackOrg hso) = Just $ hsoVersion hso
src/Stack/Storage/Project.hs view
@@ -93,8 +93,9 @@ (HasBuildConfig env, HasLogFunc env) => ReaderT SqlBackend (RIO env) a -> RIO env a-withProjectStorage inner =- flip SQLite.withStorage_ inner =<< view (buildConfigL . to bcProjectStorage . to unProjectStorage)+withProjectStorage inner = do+ storage <- view (buildConfigL . to bcProjectStorage . to unProjectStorage)+ SQLite.withStorage_ storage inner -- | Key used to retrieve configuration or flag cache type ConfigCacheKey = Unique ConfigCacheParent
src/Stack/Storage/User.hs view
@@ -134,8 +134,9 @@ (HasConfig env, HasLogFunc env) => ReaderT SqlBackend (RIO env) a -> RIO env a-withUserStorage inner =- flip SQLite.withStorage_ inner =<< view (configL . to configUserStorage . to unUserStorage)+withUserStorage inner = do+ storage <- view (configL . to configUserStorage . to unUserStorage)+ SQLite.withStorage_ storage inner -- | Key used to retrieve the precompiled cache type PrecompiledCacheKey = Unique PrecompiledCacheParent
src/Stack/Types/Build.hs view
@@ -629,7 +629,7 @@ flagNameString name) (Map.toList flags) , map T.unpack $ packageCabalConfigOpts package- , concatMap (\x -> [compilerOptionsCabalFlag wc, T.unpack x]) (packageGhcOptions package)+ , processGhcOptions (packageGhcOptions package) , map ("--extra-include-dirs=" ++) (configExtraIncludeDirs config) , map ("--extra-lib-dirs=" ++) (configExtraLibDirs config) , maybe [] (\customGcc -> ["--with-gcc=" ++ toFilePath customGcc]) (configOverrideGccPath config)@@ -637,6 +637,45 @@ , ["--ghc-option=-fhide-source-paths" | hideSourcePaths cv] ] where+ -- This function parses the GHC options that are providing in the+ -- stack.yaml file. In order to handle RTS arguments correctly, we need+ -- to provide the RTS arguments as a single argument.+ processGhcOptions :: [Text] -> [String]+ processGhcOptions args =+ let+ (preRtsArgs, mid) =+ break ("+RTS" ==) args+ (rtsArgs, end) =+ break ("-RTS" ==) mid+ fullRtsArgs =+ case rtsArgs of+ [] ->+ -- This means that we didn't have any RTS args - no+ -- `+RTS` - and therefore no need for a `-RTS`.+ []+ _ ->+ -- In this case, we have some RTS args. `break`+ -- puts the `"-RTS"` string in the `snd` list, so+ -- we want to append it on the end of `rtsArgs`+ -- here.+ --+ -- We're not checking that `-RTS` is the first+ -- element of `end`. This is because the GHC RTS+ -- allows you to omit a trailing -RTS if that's the+ -- last of the arguments. This permits a GHC+ -- options in stack.yaml that matches what you+ -- might pass directly to GHC.+ [T.unwords $ rtsArgs ++ ["-RTS"]]+ -- We drop the first element from `end`, because it is always+ -- either `"-RTS"` (and we don't want that as a separate+ -- argument) or the list is empty (and `drop _ [] = []`).+ postRtsArgs =+ drop 1 end+ newArgs =+ concat [preRtsArgs, fullRtsArgs, postRtsArgs]+ in+ concatMap (\x -> [compilerOptionsCabalFlag wc, T.unpack x]) newArgs+ wc = view (actualCompilerVersionL.to whichCompiler) econfig cv = view (actualCompilerVersionL.to getGhcVersion) econfig
src/Stack/Types/Config.hs view
@@ -1212,7 +1212,10 @@ , ") is outside the required\n" ,"version range specified in stack.yaml (" , T.unpack (versionRangeText requiredRange)- , ")." ]+ , ").\n"+ , "You can upgrade stack by running:\n\n"+ , "stack upgrade"+ ] show (NoMatchingSnapshot names) = concat [ "None of the following snapshots provides a compiler matching " , "your package(s):\n"
stack.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: stack-version: 2.7.1+version: 2.7.3 license: BSD3 license-file: LICENSE maintainer: manny@fpcomplete.com@@ -253,7 +253,7 @@ echo >=0.1.4, exceptions >=0.10.4, extra >=1.7.9,- file-embed >=0.0.13.0,+ file-embed >=0.0.14.0, filelock >=0.1.1.5, filepath >=1.4.2.1, fsnotify >=0.3.0.1,@@ -278,9 +278,9 @@ network-uri >=2.6.4.1, open-browser >=0.2.1.0, optparse-applicative >=0.14.3.0,- pantry >=0.5.1.3,+ pantry >=0.5.2, path >=0.7.0,- path-io >=1.6.2,+ path-io >=1.6.3, persistent >=2.11.0.4, persistent-sqlite >=2.11.1.0, persistent-template >=2.9.1.0,@@ -308,8 +308,8 @@ typed-process >=0.2.6.0, unicode-transforms >=0.3.7.1, unix-compat >=0.5.3,- unliftio >=0.2.14,- unordered-containers >=0.2.13.0,+ unliftio >=0.2.18,+ unordered-containers >=0.2.14.0, vector >=0.12.1.2, yaml >=0.11.5.0, zip-archive >=0.4.1,@@ -380,7 +380,7 @@ echo >=0.1.4, exceptions >=0.10.4, extra >=1.7.9,- file-embed >=0.0.13.0,+ file-embed >=0.0.14.0, filelock >=0.1.1.5, filepath >=1.4.2.1, fsnotify >=0.3.0.1,@@ -405,9 +405,9 @@ network-uri >=2.6.4.1, open-browser >=0.2.1.0, optparse-applicative >=0.14.3.0,- pantry >=0.5.1.3,+ pantry >=0.5.2, path >=0.7.0,- path-io >=1.6.2,+ path-io >=1.6.3, persistent >=2.11.0.4, persistent-sqlite >=2.11.1.0, persistent-template >=2.9.1.0,@@ -436,8 +436,8 @@ typed-process >=0.2.6.0, unicode-transforms >=0.3.7.1, unix-compat >=0.5.3,- unliftio >=0.2.14,- unordered-containers >=0.2.13.0,+ unliftio >=0.2.18,+ unordered-containers >=0.2.14.0, vector >=0.12.1.2, yaml >=0.11.5.0, zip-archive >=0.4.1,@@ -509,7 +509,7 @@ echo >=0.1.4, exceptions >=0.10.4, extra >=1.7.9,- file-embed >=0.0.13.0,+ file-embed >=0.0.14.0, filelock >=0.1.1.5, filepath >=1.4.2.1, fsnotify >=0.3.0.1,@@ -536,9 +536,9 @@ open-browser >=0.2.1.0, optparse-applicative >=0.14.3.0, optparse-generic >=1.3.1,- pantry >=0.5.1.3,+ pantry >=0.5.2, path >=0.7.0,- path-io >=1.6.2,+ path-io >=1.6.3, persistent >=2.11.0.4, persistent-sqlite >=2.11.1.0, persistent-template >=2.9.1.0,@@ -566,8 +566,8 @@ typed-process >=0.2.6.0, unicode-transforms >=0.3.7.1, unix-compat >=0.5.3,- unliftio >=0.2.14,- unordered-containers >=0.2.13.0,+ unliftio >=0.2.18,+ unordered-containers >=0.2.14.0, vector >=0.12.1.2, yaml >=0.11.5.0, zip-archive >=0.4.1,@@ -645,7 +645,7 @@ echo >=0.1.4, exceptions >=0.10.4, extra >=1.7.9,- file-embed >=0.0.13.0,+ file-embed >=0.0.14.0, filelock >=0.1.1.5, filepath >=1.4.2.1, fsnotify >=0.3.0.1,@@ -671,9 +671,9 @@ network-uri >=2.6.4.1, open-browser >=0.2.1.0, optparse-applicative >=0.14.3.0,- pantry >=0.5.1.3,+ pantry >=0.5.2, path >=0.7.0,- path-io >=1.6.2,+ path-io >=1.6.3, persistent >=2.11.0.4, persistent-sqlite >=2.11.1.0, persistent-template >=2.9.1.0,@@ -704,8 +704,8 @@ typed-process >=0.2.6.0, unicode-transforms >=0.3.7.1, unix-compat >=0.5.3,- unliftio >=0.2.14,- unordered-containers >=0.2.13.0,+ unliftio >=0.2.18,+ unordered-containers >=0.2.14.0, vector >=0.12.1.2, yaml >=0.11.5.0, zip-archive >=0.4.1,
stack.yaml view
@@ -1,4 +1,4 @@-resolver: lts-17.10+resolver: lts-17.15 packages: - .@@ -19,8 +19,6 @@ ghc-options: "$locals": -fhide-source-paths--extra-deps: [] drop-packages: # See https://github.com/commercialhaskell/stack/pull/4712
test/integration/lib/StackTest.hs view
@@ -252,6 +252,9 @@ isWindows :: Bool isWindows = os == "mingw32" +isLinux :: Bool+isLinux = os == "linux"+ -- | Is the OS Alpine Linux? getIsAlpine :: IO Bool getIsAlpine = doesFileExist "/etc/alpine-release"