packages feed

stack-all 0.6.4 → 0.7

raw patch · 6 files changed

+270/−133 lines, 6 files

Files

ChangeLog.md view
@@ -1,5 +1,16 @@ # Release history for stack-all +## 0.7 (2025-05-25)+- complete rework of stack*.yaml config file logic+- add --stack option to specify stack program (eg stack-2)+- support "snapshot:" as well as "resolver:"+- add -S,--make-all-lts flag (pbrisbin,#4)+- bump default oldest major version from LTS 18 to 20+- error for lts11 with stack > 3+- fix --update-resolver for nightly snapshot+- change --default-resolver short option from -d to -r+- add ghc9.8 alias for lts23+ ## 0.6.4 (2024-10-13) - Fix the missing stack.yaml logic to first check for a .cabal file before   trying parent directory
README.md view
@@ -8,8 +8,7 @@ ## Usage  `stack-all` by default runs `stack build` over Stackage Nightly and-LTS major versions-(the current default range is nightly & major LTS versions back to lts-18)+LTS major versions (the current default range is LTS versions back to lts-20) corresponding to latest major ghc minor versions, using appropriate stack `--resolver` options. @@ -19,24 +18,26 @@ Of course it may still fail to build, but this allows for quick attempts to build a package that does not include a stack.yaml file. -Since 0.6, stack-all also works outside projects, like stack itself does.+Since 0.6, stack-all also works outside projects, like stack itself does+(for commands that do not need a project).  ### Help output `$ stack-all --version`  ```-0.6.4+0.7 ``` `$ stack-all --help`  ``` Build project over Stackage major versions -Usage: stack-all [--version] [-k|--keep-going] [-D|--debug] [--refresh-cache] -                 [-n|--newest MAJOR] [(-o|--oldest MAJOR) | (-a|--all-lts)] -                 [(-c|--create-config) | (-d|--default-resolver MAJOR) | -                   (-u|--update-resolver) | (-s|--make-lts MAJOR) | -                   [MAJORVER... COMMAND...]]+Usage: stack-all [--version] [-k|--keep-going] [-D|--debug] [--refresh-cache]+                 [--stack STACKPROG] [-n|--newest MAJOR]+                 [(-o|--oldest MAJOR) | (-a|--all-lts)]+                 [(-c|--create-config) | (-r|--default-resolver MAJOR) |+                   (-u|--update-resolver) | (-s|--make-lts MAJOR) |+                   (-S|--make-all-lts) | [MAJORVER... COMMAND...]]    https://github.com/juhp/stack-all#readme @@ -46,14 +47,16 @@   -k,--keep-going          Keep going even if an LTS fails   -D,--debug               Verbose stack build output on error   --refresh-cache          Force refresh of stackage snapshots.json cache+  --stack STACKPROG        stack program [default: "stack"]   -n,--newest MAJOR        Newest LTS release to build from   -o,--oldest MAJOR        Oldest compatible LTS release   -a,--all-lts             Try to build back to LTS 1 even   -c,--create-config       Create a project .stack-all file-  -d,--default-resolver MAJOR+  -r,--default-resolver MAJOR                            Set stack.yaml resolver   -u,--update-resolver     Update stack.yaml resolver   -s,--make-lts MAJOR      Create a stack-ltsXX.yaml file+  -S,--make-all-lts        Create all stack-ltsXX.yaml files ```  ### Overriding stack.yaml@@ -63,11 +66,11 @@ older LTS major versions until another `stack-ltsYY.yaml` file is found. `stack-nightly.yaml` is also supported, but used only for nightly. -For example if you have `stack-lts20.yaml` and `stack-lts18.yaml` files+For example if you have `stack-lts22.yaml` and `stack-lts20.yaml` files in your project,-then `stack.yaml` will be used as normal to build nightly, lts-22 and lts-21,-but `stack-lts20.yaml` will be used for building lts-20 and lts-19,-and `stack-lts18.yaml` will be used for lts-18, lts-16 (and older).+then `stack.yaml` will be used as normal to build nightly and lts-23,+but `stack-lts22.yaml` will be used for building lts-22 and lts-21,+and `stack-lts20.yaml` will be used for lts-20 (and older). Since `stack-all` overrides the exact resolver with the latest minor snapshot, the exact minor Stackage version specified in the `stack*.yaml` files doesn't actually matter: `stack-all` always uses the latest published@@ -79,39 +82,47 @@ (Other versioned stack.yaml filenames like stack-ghc-8.8.yaml are not currently supported.) +If you wish you can create `stack-ltsXX.yaml` for all lts versions using+`--make-all-lts` (`-S`), but it is recommended to create only needed files.++Since 0.7, a `stack-ltsXX.yaml` conflicting (overlapping in major version)+with `stack.yaml` gives an error, and stack-all will also refuse to generate+such a file.+ ### Specifying LTS versions You can abbreviate `lts-XX` args to `ltsXX` on the commandline. `lts` is also accepted and resolves to the latest major LTS version. -You can also use ghc major version aliases:-eg `ghc9.6` corresponds to `lts22` or `ghc-9.2` to `lts-20`.+You can also use (hardcoded) ghc major version aliases:+eg `ghc9.8` corresponds to `lts23` or `ghc-9.2` to `lts-20`,+though not for `nightly` currently.  There are `--oldest`  and `--newest` options to specify the range of lts versions to build over: -You can specify the oldest major LTS to build for with eg `stack-all -o lts16`.-Otherwise if not configured the default oldest LTS is currently `lts-18`.+You can specify the oldest major LTS to build for with eg `stack-all -o lts18`.+Otherwise if not configured the default oldest LTS is currently `lts-20`.  Similarly you can specify the newest LTS version to build from with-eg `stack-all -n lts20`. (The default is to build from nightly.)+eg `stack-all -n lts21`. (The default is to build from nightly.)  Alternatively, one can give one or more explicit LTS major versions to build-for as arguments: eg `stack-all lts19` if you only wish to build that version.+for as arguments: eg `stack-all lts22` if you only wish to build that version.  ### Configuring the oldest and/or newest LTS to build You can configure the oldest working LTS major version for your project-by running for example `stack-all -c -o lts-19` which generates a `.stack-all`+by running for example `stack-all -c -o lts-21` which generates a `.stack-all` project config file like this: ``` [versions]-# lts-18 too old-oldest = lts-19+# lts-20 too old+oldest = lts-21 ``` (the comment line can be used to document why the older LTS doesn't work).-This specifies that the oldest LTS version to build for is lts-19.+This specifies that the oldest LTS version to build for is lts-21.  The newest LTS to build with stack-all can similarly be configured:-`stack-all -c -n lts21` or setting `newest = lts-21`.+`stack-all -c -n lts22` or inserting `newest = lts-22`.  ### Running other stack commands By default `stack-all` just runs the stack `build` command over
src/Main.hs view
@@ -1,16 +1,27 @@-{-# LANGUAGE OverloadedStrings, CPP #-}+{-# LANGUAGE BangPatterns, OverloadedStrings, CPP #-} -import Control.Monad.Extra+import Control.Monad.Extra (unless, unlessM, when, whenJustM, (||^)) import Data.Either import Data.Ini.Config-import Data.List.Extra-import Data.Maybe+import Data.List.Extra -- not explicit to avoid awkward CPP+import Data.Maybe (fromMaybe, listToMaybe) import Data.Tuple (swap)-import SimpleCmd+import Data.Version.Extra+import SimpleCmd ((+-+), cmdBool, cmd, cmd_, error',+#if MIN_VERSION_simple_cmd(0,2,4)+                  fileWithExtension+#endif+                 ) import SimpleCmdArgs-import System.Directory+import System.Directory (copyFile, doesFileExist, getCurrentDirectory,+#if !MIN_VERSION_simple_cmd(0,2,4)+                         listDirectory,+#endif+                         setCurrentDirectory, withCurrentDirectory) import System.Exit-import System.FilePath+#if !MIN_VERSION_simple_cmd(0,2,4)+import System.FilePath -- not explicit to avoid awkward CPP+#endif import System.IO import System.Process import qualified Data.Text.IO as T@@ -18,10 +29,10 @@ import MajorVer import Paths_stack_all (version) import Snapshots-import StackYaml (readStackYaml)+import StackYaml  defaultOldestLTS :: MajorVer-defaultOldestLTS = LTS 18+defaultOldestLTS = LTS 20  data VersionLimit = DefaultLimit | Oldest MajorVer | AllVersions @@ -29,6 +40,7 @@              | SetDefaultResolver MajorVer              | UpdateDefaultResolver              | MakeStackLTS MajorVer+             | MakeAllLTS              | RunCmd [String]   deriving Eq @@ -41,22 +53,21 @@     <$> switchWith 'k' "keep-going" "Keep going even if an LTS fails"     <*> switchWith 'D' "debug" "Verbose stack build output on error"     <*> switchLongWith "refresh-cache" "Force refresh of stackage snapshots.json cache"+    <*> strOptionalLongWith "stack" "STACKPROG" "stack program to use" "stack"     <*> optional (readMajor <$> strOptionWith 'n' "newest" "MAJOR" "Newest LTS release to build from")     <*> (Oldest . readMajor <$> strOptionWith 'o' "oldest" "MAJOR" "Oldest compatible LTS release" <|>          flagWith DefaultLimit AllVersions 'a' "all-lts" "Try to build back to LTS 1 even")     <*>     (flagWith' CreateConfig 'c' "create-config" "Create a project .stack-all file" <|>-     (SetDefaultResolver . readMajor <$> strOptionWith 'd' "default-resolver" "MAJOR" ("Set" +-+ stackYaml +-+ "resolver")) <|>+     (SetDefaultResolver . readMajor <$> strOptionWith 'r' "default-resolver" "MAJOR" ("Set" +-+ stackYaml +-+ "resolver")) <|>      flagWith' UpdateDefaultResolver 'u' "update-resolver" ("Update" +-+ stackYaml +-+ "resolver") <|>      (MakeStackLTS . readMajor <$> strOptionWith 's' "make-lts" "MAJOR" "Create a stack-ltsXX.yaml file") <|>+     flagWith' MakeAllLTS 'S' "make-all-lts" "Create all stack-ltsXX.yaml files" <|>      RunCmd <$> many (strArg "MAJORVER... COMMAND...")) -stackYaml :: FilePath-stackYaml = "stack.yaml"--run :: Bool ->Bool -> Bool -> Maybe MajorVer -> VersionLimit -> Command-    -> IO ()-run keepgoing debug refresh mnewest verlimit com = do+run :: Bool ->Bool -> Bool -> FilePath -> Maybe MajorVer -> VersionLimit+    -> Command -> IO ()+run keepgoing debug refresh stack mnewest verlimit com = do   whenJustM findStackProjectDir setCurrentDirectory   case com of     CreateConfig ->@@ -65,12 +76,15 @@         _ -> createStackAll Nothing mnewest     SetDefaultResolver ver -> stackDefaultResolver $ Just ver     UpdateDefaultResolver -> stackDefaultResolver Nothing-    MakeStackLTS ver -> makeStackLTS refresh ver+    MakeStackLTS ver -> makeStackLTS False refresh ver+    MakeAllLTS -> do+      vers <- determineVersions mnewest verlimit []+      mapM_ (makeStackLTS (length vers > 1) refresh) vers     RunCmd verscmd -> do-      (versions, cargs) <- getVersionsCmd verscmd+      (versions, cargs) <- getVersionsAndCmd verscmd       configs <- readStackConfigs-      let newestFilter = maybe id (filter . (>=)) mnewest-      mapM_ (runStack configs keepgoing debug refresh $ if null cargs then ["build"] else cargs) (newestFilter versions)+      let finalvers = maybe id (filter . (>=)) mnewest versions+      mapM_ (runStack configs keepgoing debug refresh stack $ if null cargs then ["build"] else cargs) finalvers   where     findStackProjectDir :: IO (Maybe FilePath)     findStackProjectDir = do@@ -88,7 +102,7 @@           putStrLn $ "creating" +-+ stackYaml +-+ "in" +-+ cwdir           -- FIXME take suggested extra-deps into stack.yaml           -- FIXME stack init content too verbose-          unlessM (cmdBool "stack" ["init"]) $ do+          unlessM (cmdBool stack ["init"]) $ do             snap <- latestLtsSnapshot refresh             writeFile stackYaml $ "resolver: " ++ snap ++ "\n"           return $ Just cwdir@@ -99,50 +113,50 @@           putStrLn "no package/project found"           return Nothing -    getVersionsCmd :: [String] -> IO ([MajorVer],[String])-    getVersionsCmd verscmd = do+    getVersionsAndCmd :: [String] -> IO ([MajorVer],[String])+    getVersionsAndCmd verscmd = do       let partitionMajors = swap . partitionEithers . map eitherReadMajorAlias           (verlist,cmds) = partitionMajors verscmd-      allMajors <- getMajorVers-      versions <--        if null verlist then+      versions <- determineVersions mnewest verlimit verlist+      return (versions,cmds)++inRange :: MajorVer -> MajorVer -> MajorVer -> Bool+inRange newest oldest v = v >= oldest && v <= newest++determineVersions :: Maybe MajorVer -> VersionLimit -> [MajorVerAlias]+                  -> IO [MajorVer]+determineVersions mnewest verlimit verlist = do+        if null verlist then do+          allMajors <- getMajorVers           case verlimit of             DefaultLimit -> do-              (newestLTS, oldestLTS) <- readNewestOldestLTS-              return $ case mnewest of-                         Just newest ->-                           if newest < oldestLTS-                           then filter (inRange newest (LTS 1)) allMajors-                           else filter (inRange newest oldestLTS) allMajors-                         Nothing -> filter (inRange newestLTS oldestLTS) allMajors+              (newestLTS, oldestLTS) <- readNewestOldestLTS mnewest+              return $+                case mnewest of+                  Just newest ->+                    if newest < oldestLTS+                    then filter (inRange newest (LTS 1)) allMajors+                    else filter (inRange newest oldestLTS) allMajors+                  Nothing -> filter (inRange newestLTS oldestLTS) allMajors             AllVersions -> return allMajors-            Oldest ver -> return $ filter (inRange Nightly ver) allMajors+            Oldest ver ->+              return $+              filter (inRange (fromMaybe Nightly mnewest) ver) allMajors         else nub <$> mapM resolveMajor verlist-      return (versions,cmds)-      where-        inRange :: MajorVer -> MajorVer -> MajorVer -> Bool-        inRange newest oldest v = v >= oldest && v <= newest -readStackConfigs :: IO [MajorVer]-readStackConfigs = do-  sort . mapMaybe readStackConf <$> listDirectory "."-  where-    readStackConf :: FilePath -> Maybe MajorVer-    readStackConf "stack-lts.yaml" =-      error' "unversioned stack-lts.yaml is unsupported"-    readStackConf f =-      stripPrefix "stack-" f >>= stripSuffix ".yaml" >>= readCompactMajor--readNewestOldestLTS :: IO (MajorVer,MajorVer)-readNewestOldestLTS = do+readNewestOldestLTS :: Maybe MajorVer -> IO (MajorVer,MajorVer)+readNewestOldestLTS mnewest = do   haveConfig <- doesFileExist stackAllFile   if haveConfig then     readIniConfig stackAllFile $     section "versions" $ do-    mnewest <- fmap readMajor <$> fieldMbOf "newest" string-    moldest <- fmap readMajor <$> fieldMbOf "oldest" string-    return (fromMaybe Nightly mnewest, fromMaybe defaultOldestLTS moldest)-    else return (Nightly, defaultOldestLTS)+    mnewest' <-+      case mnewest of+        Nothing -> fmap readMajor <$> fieldMbOf "newest" string+        _ -> return mnewest+    moldest' <- fmap readMajor <$> fieldMbOf "oldest" string+    return (fromMaybe Nightly mnewest', fromMaybe defaultOldestLTS moldest')+    else return (fromMaybe Nightly mnewest, defaultOldestLTS)   where     readIniConfig :: FilePath -> IniParser a -> IO a     readIniConfig inifile iniparser = do@@ -175,71 +189,90 @@                 in maybe "" (\s -> showMajor s ++ " too old") molder           in "# " ++ older ++ "\noldest = " ++ showMajor oldest ++ "\n" +updateResolver :: String -> FilePath -> IO ()+updateResolver snapshot stackfile =+  cmd_ "sed" ["-i", "-e", "s/\\(resolver:\\|snapshot:\\) .*/\\1 " ++ snapshot ++ "/", stackfile]+ stackDefaultResolver :: Maybe MajorVer -> IO () stackDefaultResolver mver = do   unlessM (doesFileExist stackYaml) $     error' $ "no" +-+ stackYaml +-+ "present"   case mver of     Nothing -> do-      mdef <- readStackYaml stackYaml+      mdef <- readDefaultStackYaml       case mdef of         Nothing -> error' $ "could not determine major version of" +-+ stackYaml         Just ver -> stackDefaultResolver $ Just ver     Just ver ->       whenJustM (latestMajorSnapshot False ver) $ \latest ->-      cmd_ "sed" ["-i", "-e", "s/\\(resolver:\\) .*/\\1 " ++ latest ++ "/", stackYaml]+      updateResolver latest stackYaml -makeStackLTS :: Bool -> MajorVer -> IO ()-makeStackLTS refresh ver = do+makeStackLTS :: Bool -> Bool -> MajorVer -> IO ()+makeStackLTS multiple refresh ver = do   configs <- readStackConfigs-  let newfile = configFile ver-  if ver `elem` configs-    then do-    error' $ newfile ++ " already exists!"-    else do-    let mcurrentconfig = find (ver <=) (delete Nightly configs)-    case mcurrentconfig of-      Nothing -> copyFile stackYaml newfile-      Just conf -> do-        let origfile = configFile conf-        copyFile origfile newfile-    whenJustM (latestMajorSnapshot refresh ver) $ \latest ->-      cmd_ "sed" ["-i", "-e", "s/\\(resolver:\\) .*/\\1 " ++ latest ++ "/", newfile]--configFile :: MajorVer -> FilePath-configFile ver = "stack-" ++ showCompact ver <.> "yaml"+  case filter (isVersion ver) configs of+    [] -> do+      let newfile = configFile $ Config ver+          mcurrentconfig = find ((ver <) . configVersion) configs+      when multiple $ putStrLn $ "creating" +-+ newfile+      case mcurrentconfig of+        Nothing -> copyFile stackYaml newfile+        Just conf -> do+          let origfile = configFile conf+          copyFile origfile newfile+      whenJustM (latestMajorSnapshot refresh ver) $ \latest ->+        updateResolver latest newfile+    [c] ->+      let msg =+            configFile c +-+ "already" +-++            case c of+              Config _ -> "exists"+              ConfigDefault v -> "has" +-+ showMajor v+      in if multiple+         then putStrLn msg+         else error' $ msg ++ "!"+    cs ->+      (if multiple then putStrLn else error') $ "overlapping major versions:" +-++      unwords (map configFile cs) -runStack :: [MajorVer] -> Bool -> Bool -> Bool -> [String]-           -> MajorVer -> IO ()-runStack configs keepgoing debug refresh command ver = do-  let mcfgver =-        case ver of-          Nightly | Nightly `elem` configs -> Just Nightly-          _ ->-            case sort (filter (ver <=) (delete Nightly configs)) of+runStack :: [ConfigVersion] -> Bool -> Bool -> Bool -> FilePath -> [String]+         -> MajorVer -> IO ()+runStack configs keepgoing debug refresh stack command ver = do+  -- FIXME add --stack or STACK envvar or look for stack-<VERSION>+  when (ver <= LTS 11) $ do+    stackver <- readVersion <$> cmd stack ["--numeric-version"]+    when (stackver >= makeVersion [3]) $+      error' $ "stack-" ++ showVersion stackver +-+ "no longer supports lts < 12"+  let !mconfig =+        case filter (isVersion ver) configs of+          [] ->+            case sort (filter (Config ver <) $ delete (Config Nightly) configs) of               [] -> Nothing-              (cfg:_) -> Just cfg+              (c:_) -> nonDefaultConfig c+          [c] -> nonDefaultConfig c+          cs -> error' $ "overlapping major versions:" +-++                unwords (map configFile cs)   latest <- latestMajorSnapshot refresh ver   case latest of     Nothing -> error' $ "no snapshot not found for " ++ showMajor ver     Just minor -> do       let opts = ["-v" | debug] ++ ["--resolver", minor] ++-                 maybe [] (\f -> ["--stack-yaml", configFile f]) mcfgver+                 maybe [] (\f -> ["--stack-yaml", configFile f]) mconfig       putStrLn $ "# " ++ minor       if debug         then debugBuild $ opts ++ command         else do-        ok <- cmdBool "stack" $ opts ++ command+        ok <- cmdBool stack $ opts ++ command         unless (ok || keepgoing) $ do           putStr "\nsnapshot-pkg-db: "-          cmd_ "stack" $ "--silent" : opts ++ ["path", "--snapshot-pkg-db"]+          cmd_ stack $ "--silent" : opts ++ ["path", "--snapshot-pkg-db"]           error' $ "failed for " ++ showMajor ver       putStrLn ""   where     debugBuild :: [String] -> IO ()     debugBuild args = do-      putStr $ "stack " ++ unwords args-      (ret,out,err) <- readProcessWithExitCode "stack" args ""+      putStr $ stack +-+ unwords args+      (ret,out,err) <- readProcessWithExitCode stack args ""       putStrLn "\n"       unless (null out) $ putStrLn out       unless (ret == ExitSuccess) $ do@@ -249,6 +282,12 @@   #if !MIN_VERSION_simple_cmd(0,2,4)+#if !MIN_VERSION_filepath(1,4,2)+isExtensionOf :: String -> FilePath -> Bool+isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions+isExtensionOf ext         = isSuffixOf ('.':ext) . takeExtensions+#endif+ filesWithExtension :: FilePath -- directory                    -> String   -- file extension                    -> IO [FilePath]@@ -274,9 +313,3 @@   case mf of     Nothing -> return False     Just f -> doesFileExist f--#if !MIN_VERSION_filepath(1,4,2)-isExtensionOf :: String -> FilePath -> Bool-isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions-isExtensionOf ext         = isSuffixOf ('.':ext) . takeExtensions-#endif
src/MajorVer.hs view
@@ -10,23 +10,33 @@   ) where +import Data.Char (isDigit) import Data.List.Extra+import Numeric.Natural (Natural) import SimpleCmd (error') import Text.Read (readMaybe)  -- FIXME allow specific snapshots?-data MajorVer = LTS Int | LTSLatest | Nightly+data MajorVer = LTS Natural | Nightly   deriving (Eq, Ord)  maybeReadMajor :: String -> Maybe MajorVer-maybeReadMajor "nightly" = Just Nightly maybeReadMajor ver+  | "nightly" `isPrefixOf` ver =+      case dropPrefix "-" $ dropPrefix "nightly" ver of+        "" -> Just Nightly+        ds ->+          if all (\d -> isDigit d || d == '-') ds+          then Just Nightly+          else Nothing+maybeReadMajor ver   | "lts" `isPrefixOf` ver =       case readMaybe (dropPrefix "-" (dropPrefix "lts" ver)) of         Just major -> Just (LTS major)         Nothing -> Nothing   | "ghc" `isPrefixOf` ver =       case dropPrefix "-" (dropPrefix "ghc" ver) of+        "9.8" -> Just (LTS 23)         "9.6" -> Just (LTS 22)         "9.4" -> Just (LTS 21)         "9.2" -> Just (LTS 20)@@ -45,15 +55,14 @@ -- readMajor "lts-16" readMajor :: String -> MajorVer readMajor "nightly" = Nightly-readMajor "lts" = LTSLatest readMajor ver =   case maybeReadMajor ver of     Just s -> s     Nothing ->-      error' $! "couldn't parse " ++ ver ++ " (expected lts-XX, ltsXX, ghc-X.Y or ghcX.Y)"+      error' $! "couldn't parse " ++ ver ++ " (expected lts*, nightly*, ghc-X.Y or ghcX.Y)"  -- readCompactMajor "lts16"--- Should we support "stack-lts.yaml"?+-- Should we support stack-lts.yaml or even stack-<minor>.yaml? readCompactMajor :: String -> Maybe MajorVer readCompactMajor "nightly" = Just Nightly readCompactMajor ver =@@ -65,7 +74,6 @@  showMajor :: MajorVer -> String showMajor Nightly = "nightly"-showMajor LTSLatest = "lts" showMajor (LTS ver) = "lts-" ++ show ver  showCompact :: MajorVer -> String
src/StackYaml.hs view
@@ -1,14 +1,88 @@ {-# LANGUAGE OverloadedStrings #-} -module StackYaml (readStackYaml)+module StackYaml (+  readDefaultStackYaml,+  stackYaml,+  readStackConfigs,+  ConfigVersion(..),+  configVersion,+  configFile,+  isVersion,+  nonDefaultConfig+  ) where +import Control.Applicative ((<|>))+import Control.Monad.Extra (mapMaybeM, unless)+import Data.List.Extra+import Data.Maybe (mapMaybe) import Data.Yaml (decodeFileThrow) import Network.HTTP.Query (lookupKey)+import SimpleCmd ((+-+))+import System.Directory (listDirectory)+import System.FilePath ((<.>)) -import MajorVer (MajorVer, snapMajorVer)+import MajorVer (MajorVer, readCompactMajor, showCompact, showMajor,+                 snapMajorVer) -readStackYaml :: FilePath -> IO (Maybe MajorVer)-readStackYaml file = do+stackYaml :: FilePath+stackYaml = "stack.yaml"++data ConfigVersion = Config MajorVer | ConfigDefault MajorVer+  deriving Eq++instance Ord ConfigVersion where+  compare (Config v1) (Config v2) = compare v1 v2+  compare (ConfigDefault v1) (Config v2) = compare v1 v2+  compare (Config v1) (ConfigDefault v2) = compare v1 v2+  compare (ConfigDefault v1) (ConfigDefault v2) = compare v1 v2++isVersion :: MajorVer -> ConfigVersion -> Bool+isVersion v cfg = configVersion cfg == v++nonDefaultConfig :: ConfigVersion -> Maybe ConfigVersion+nonDefaultConfig (ConfigDefault _) = Nothing+nonDefaultConfig c = Just c++configVersion :: ConfigVersion -> MajorVer+configVersion (Config v) = v+configVersion (ConfigDefault v) = v++configFile :: ConfigVersion -> FilePath+configFile (ConfigDefault _) = stackYaml+configFile (Config ver) = "stack-" ++ showCompact ver <.> "yaml"++data ConfigFile = ConfigFileDefault | ConfigFile MajorVer++-- FIXME error "unversioned stack-lts.yaml is unsupported"+readConfigFile :: FilePath -> Maybe ConfigFile+readConfigFile file =+  if file == stackYaml+  then Just ConfigFileDefault+  else+    ConfigFile <$>+    (stripPrefix "stack-" file >>= stripSuffix ".yaml" >>= readCompactMajor)++readStackYamlFile :: FilePath -> IO (Maybe MajorVer)+readStackYamlFile file = do   yaml <- decodeFileThrow file-  return $ snapMajorVer <$> lookupKey "resolver" yaml+  return $ snapMajorVer <$>+    (lookupKey "resolver" yaml <|> lookupKey "snapshot" yaml)++readDefaultStackYaml :: IO (Maybe MajorVer)+readDefaultStackYaml = readStackYamlFile stackYaml++readStackYaml :: ConfigFile -> IO (Maybe ConfigVersion)+readStackYaml ConfigFileDefault =+  fmap ConfigDefault <$> readDefaultStackYaml+readStackYaml (ConfigFile ver) = do+  let file = configFile $ Config ver+  mactual <- readStackYamlFile file+  unless (mactual == Just ver) $+    putStrLn $ configFile (Config ver) +-+ "has" +-+ maybe "undefined" showMajor mactual +-+ "resolver"+  return $ Just $ Config ver++readStackConfigs :: IO [ConfigVersion]+readStackConfigs =+  listDirectory "." >>=+  fmap sort . mapMaybeM readStackYaml . mapMaybe readConfigFile
stack-all.cabal view
@@ -1,5 +1,5 @@ name:                stack-all-version:             0.6.4+version:             0.7 synopsis:            CLI tool for building over Stackage major versions description:         Stack-all is a tool for stack building of a Haskell project@@ -8,7 +8,7 @@ license-file:        LICENSE author:              Jens Petersen <juhpetersen@gmail.com> maintainer:          Jens Petersen <juhpetersen@gmail.com>-copyright:           2020-2024  Jens Petersen <juhpetersen@gmail.com>+copyright:           2020-2025  Jens Petersen <juhpetersen@gmail.com> category:            Distribution homepage:            https://github.com/juhp/stack-all bug-reports:         https://github.com/juhp/stack-all/issues@@ -18,7 +18,7 @@ cabal-version:       1.18 tested-with:         GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5,                      GHC == 8.8.4, GHC == 8.10.7, GHC == 9.0.2, GHC == 9.2.8,-                     GHC == 9.4.8, GHC == 9.6.6, GHC == 9.8.2+                     GHC == 9.4.8, GHC == 9.6.7, GHC == 9.8.4, GHC == 9.10.2  source-repository head   type:                git