Skip to content

Commit a7f7baa

Browse files
committed
Allow properly loading custom snapshots in scripts commercialhaskell#3218
1 parent 37f0a1c commit a7f7baa

5 files changed

Lines changed: 48 additions & 30 deletions

File tree

src/Stack/Config.hs

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ loadConfigMaybeProject configArgs mresolver mproject = do
468468

469469
config <-
470470
case mproject of
471-
LCSNoConfig -> configNoLocalConfig stackRoot mresolver configArgs
471+
LCSNoConfig _ -> configNoLocalConfig stackRoot mresolver configArgs
472472
LCSProject project -> loadHelper $ Just project
473473
LCSNoProject -> loadHelper Nothing
474474
unless (fromCabalVersion Meta.version `withinRange` configRequireStackVersion config)
@@ -488,7 +488,7 @@ loadConfigMaybeProject configArgs mresolver mproject = do
488488
case mprojectRoot of
489489
LCSProject fp -> Just fp
490490
LCSNoProject -> Nothing
491-
LCSNoConfig -> Nothing
491+
LCSNoConfig _ -> Nothing
492492
}
493493

494494
-- | Load the configuration, using current directory, environment variables,
@@ -517,9 +517,14 @@ loadBuildConfig mproject mresolver mcompiler = do
517517
(project', stackYamlFP) <- case mproject of
518518
LCSProject (project, fp, _) -> do
519519
forM_ (projectUserMsg project) ($logWarn . T.pack)
520-
return (project, fp)
521-
LCSNoConfig -> do
522-
p <- getEmptyProject
520+
resolver <-
521+
case mresolver of
522+
Nothing -> return $ projectResolver project
523+
Just aresolver ->
524+
runRIO config $ makeConcreteResolver (Just (parent fp)) aresolver
525+
return (project { projectResolver = resolver }, fp)
526+
LCSNoConfig parentDir -> do
527+
p <- getEmptyProject (Just parentDir)
523528
return (p, configUserConfigPath config)
524529
LCSNoProject -> do
525530
$logDebug "Run from outside a project, using implicit global project config"
@@ -552,7 +557,7 @@ loadBuildConfig mproject mresolver mcompiler = do
552557
else do
553558
$logInfo ("Writing implicit global project config file to: " <> T.pack dest')
554559
$logInfo "Note: You can change the snapshot via the resolver field there."
555-
p <- getEmptyProject
560+
p <- getEmptyProject Nothing
556561
liftIO $ do
557562
S.writeFile dest' $ S.concat
558563
[ "# This is the implicit global project's config file, which is only used when\n"
@@ -568,17 +573,11 @@ loadBuildConfig mproject mresolver mcompiler = do
568573
[ "This is the implicit global project, which is used only when 'stack' is run\n"
569574
, "outside of a real project.\n" ]
570575
return (p, dest)
571-
resolver <-
572-
case mresolver of
573-
Nothing -> return $ projectResolver project'
574-
Just aresolver ->
575-
runRIO config $ makeConcreteResolver (Just (parent stackYamlFP)) aresolver
576576
let project = project'
577-
{ projectResolver = resolver
578-
, projectCompiler = mcompiler <|> projectCompiler project'
577+
{ projectCompiler = mcompiler <|> projectCompiler project'
579578
}
580579

581-
sd0 <- runRIO config $ loadResolver resolver
580+
sd0 <- runRIO config $ loadResolver $ projectResolver project
582581
let sd = maybe id setCompilerVersion (projectCompiler project) sd0
583582

584583
extraPackageDBs <- mapM resolveDir' (projectExtraPackageDBs project)
@@ -596,14 +595,15 @@ loadBuildConfig mproject mresolver mcompiler = do
596595
case mproject of
597596
LCSNoProject -> True
598597
LCSProject _ -> False
599-
LCSNoConfig -> False
598+
LCSNoConfig _ -> False
600599
}
601600
where
602-
getEmptyProject :: RIO Config Project
603-
getEmptyProject = do
601+
getEmptyProject :: Maybe (Path Abs Dir) -- ^ directory used for making concrete resolver
602+
-> RIO Config Project
603+
getEmptyProject mparentDir = do
604604
r <- case mresolver of
605605
Just aresolver -> do
606-
r' <- makeConcreteResolver Nothing aresolver
606+
r' <- makeConcreteResolver mparentDir aresolver
607607
$logInfo ("Using resolver: " <> resolverRawName r' <> " specified on command line")
608608
return r'
609609
Nothing -> do
@@ -862,12 +862,13 @@ getProjectConfig SYLDefault = do
862862
if exists
863863
then return $ Just fp
864864
else return Nothing
865-
getProjectConfig SYLNoConfig = return LCSNoConfig
865+
getProjectConfig (SYLNoConfig parentDir) = return (LCSNoConfig parentDir)
866866

867867
data LocalConfigStatus a
868868
= LCSNoProject
869869
| LCSProject a
870-
| LCSNoConfig
870+
| LCSNoConfig !(Path Abs Dir)
871+
-- ^ parent directory for making a concrete resolving
871872
deriving (Show,Functor,Foldable,Traversable)
872873

873874
-- | Find the project config file location, respecting environment variables
@@ -888,9 +889,9 @@ loadProjectConfig mstackYaml = do
888889
LCSNoProject -> do
889890
$logDebug $ "No project config file found, using defaults."
890891
return LCSNoProject
891-
LCSNoConfig -> do
892+
LCSNoConfig mparentDir -> do
892893
$logDebug "Ignoring config files"
893-
return LCSNoConfig
894+
return (LCSNoConfig mparentDir)
894895
where
895896
load fp = do
896897
ProjectAndConfigMonoid project config <- loadConfigYaml (parseProjectAndConfigMonoid (parent fp)) fp
@@ -943,7 +944,13 @@ getFakeConfigPath stackRoot ar = do
943944
case ar of
944945
ARResolver r -> return $ T.unpack $ resolverRawName r
945946
_ -> throwM $ InvalidResolverForNoLocalConfig $ show ar
946-
asDir <- parseRelDir asString
947+
-- This takeWhile is an ugly hack. We don't actually need this
948+
-- path for anything useful. But if we take the raw value for
949+
-- a custom snapshot, it will be unparseable in a PATH.
950+
-- Therefore, we add in this silly "strip up to :".
951+
-- Better would be to defer figuring out this value until
952+
-- after we have a fully loaded snapshot with a hash.
953+
asDir <- parseRelDir $ takeWhile (/= ':') asString
947954
let full = stackRoot </> $(mkRelDir "script") </> asDir </> $(mkRelFile "config.yaml")
948955
ensureDir (parent full)
949956
return full

src/Stack/ConfigCmd.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ cfgCmdSet go cmd = do
6161
case mstackYaml of
6262
LCSProject stackYaml -> return stackYaml
6363
LCSNoProject -> liftM (</> stackDotYaml) (getImplicitGlobalProjectDir conf)
64-
LCSNoConfig -> throwString "config command used when no local configuration available"
64+
LCSNoConfig _ -> throwString "config command used when no local configuration available"
6565
CommandScopeGlobal -> return (configUserConfigPath conf)
6666
-- We don't need to worry about checking for a valid yaml here
6767
(config :: Yaml.Object) <-

src/Stack/Script.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ import System.Process.Read
3030
-- | Run a Stack Script
3131
scriptCmd :: ScriptOpts -> GlobalOpts -> IO ()
3232
scriptCmd opts go' = do
33+
file <- resolveFile' $ soFile opts
3334
let go = go'
3435
{ globalConfigMonoid = (globalConfigMonoid go')
3536
{ configMonoidInstallGHC = First $ Just True
3637
}
37-
, globalStackYaml = SYLNoConfig
38+
, globalStackYaml = SYLNoConfig $ parent file
3839
}
3940
withBuildConfigAndLock go $ \lk -> do
4041
-- Some warnings in case the user somehow tries to set a
@@ -46,7 +47,7 @@ scriptCmd opts go' = do
4647
SYLOverride fp -> $logError $ T.pack
4748
$ "Ignoring override stack.yaml file for script command: " ++ fp
4849
SYLDefault -> return ()
49-
SYLNoConfig -> assert False (return ())
50+
SYLNoConfig _ -> assert False (return ())
5051

5152
config <- view configL
5253
menv <- liftIO $ configEnvOverride config defaultEnvSettings
@@ -100,7 +101,6 @@ scriptCmd opts go' = do
100101
SEInterpret -> exec menv ("run" ++ compilerExeName wc)
101102
(ghcArgs ++ soFile opts : soArgs opts)
102103
_ -> do
103-
file <- resolveFile' $ soFile opts
104104
let dir = parent file
105105
-- use sinkProcessStdout to ensure a ProcessFailed
106106
-- exception is generated for better error messages

src/Stack/Snapshot.hs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ data SnapshotException
7777
| FilepathInCustomSnapshot !Text
7878
| NeedResolverOrCompiler !Text
7979
| MissingPackages !(Set PackageName)
80+
| CustomResolverException !Text !(Either Request FilePath) !ParseException
8081
deriving Typeable
8182
instance Exception SnapshotException
8283
instance Show SnapshotException where
@@ -123,6 +124,14 @@ instance Show SnapshotException where
123124
show (MissingPackages names) =
124125
"The following packages specified by flags or options are not found: " ++
125126
unwords (map packageNameString (Set.toList names))
127+
show (CustomResolverException url loc e) = concat
128+
[ "Unable to load custom resolver "
129+
, T.unpack url
130+
, " from location\n"
131+
, show loc
132+
, "\nException: "
133+
, show e
134+
]
126135

127136
-- | Convert a 'Resolver' into a 'SnapshotDef'
128137
loadResolver
@@ -233,7 +242,7 @@ loadResolver (ResolverCompiler compiler) = return SnapshotDef
233242
, sdGlobalHints = Map.empty
234243
}
235244
loadResolver (ResolverCustom url loc) = do
236-
$logDebug $ "Loading " <> url <> " build plan"
245+
$logDebug $ "Loading " <> url <> " build plan from " <> T.pack (show loc)
237246
case loc of
238247
Left req -> download' req >>= load . toFilePath
239248
Right fp -> load fp
@@ -255,7 +264,7 @@ loadResolver (ResolverCustom url loc) = do
255264
load fp = do
256265
WithJSONWarnings (sd0, mparentResolver, mcompiler) warnings <-
257266
liftIO (decodeFileEither fp) >>= either
258-
throwM
267+
(throwM . CustomResolverException url loc)
259268
(either (throwM . AesonException) return . parseEither parseCustom)
260269
logJSONWarnings (T.unpack url) warnings
261270

src/Stack/Types/Config.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,9 @@ data GlobalOpts = GlobalOpts
444444
data StackYamlLoc filepath
445445
= SYLDefault
446446
| SYLOverride !filepath
447-
| SYLNoConfig
447+
| SYLNoConfig !(Path Abs Dir)
448+
-- ^ FilePath is the directory containing the script file, used
449+
-- for resolving custom snapshot files.
448450
deriving (Show,Functor,Foldable,Traversable)
449451

450452
-- | Parsed global command-line options monoid.

0 commit comments

Comments
 (0)