@@ -95,6 +95,7 @@ data BuildPlanException
95
95
(Map PackageName (Maybe Version , Set PackageName )) -- truly unknown
96
96
(Map PackageName (Set PackageIdentifier )) -- shadowed
97
97
| SnapshotNotFound SnapName
98
+ | FilepathInDownloadedSnapshot T. Text
98
99
deriving (Typeable )
99
100
instance Exception BuildPlanException
100
101
instance Show BuildPlanException where
@@ -174,6 +175,11 @@ instance Show BuildPlanException where
174
175
$ Set. toList
175
176
$ Set. unions
176
177
$ Map. elems shadowed
178
+ show (FilepathInDownloadedSnapshot url) = unlines
179
+ [ " Downloaded snapshot specified a 'resolver: { location: filepath }' "
180
+ , " field, but filepaths are not allowed in downloaded snapshots.\n "
181
+ , " Filepath specified: " ++ T. unpack url
182
+ ]
177
183
178
184
-- | Determine the necessary packages to install to have the given set of
179
185
-- packages available.
@@ -221,8 +227,6 @@ toMiniBuildPlan :: (MonadIO m, MonadLogger m, MonadReader env m, HasHttpManager
221
227
-> Map PackageName (Version , Map FlagName Bool , [Text ]) -- ^ non-core packages
222
228
-> m MiniBuildPlan
223
229
toMiniBuildPlan compilerVersion requireAllowNewer corePackages packages = do
224
- $ logInfo " Caching build plan"
225
-
226
230
-- Determine the dependencies of all of the packages in the build plan. We
227
231
-- handle core packages specially, because some of them will not be in the
228
232
-- package index. For those, we allow missing packages to exist, and then
@@ -404,6 +408,24 @@ getToolMap mbp =
404
408
$ Set. toList
405
409
$ mpiExes mpi
406
410
411
+ loadResolver
412
+ :: (MonadIO m , MonadThrow m , MonadLogger m , MonadReader env m , HasHttpManager env , HasConfig env , HasGHCVariant env , MonadBaseControl IO m , MonadCatch m )
413
+ => Maybe (Path Abs File )
414
+ -> Resolver
415
+ -> m MiniBuildPlan
416
+ loadResolver mconfigPath resolver =
417
+ case resolver of
418
+ ResolverSnapshot snap -> loadMiniBuildPlan snap
419
+ -- TODO(mgsloan): Not sure what this FIXME means
420
+ -- FIXME instead of passing the stackYaml dir we should maintain
421
+ -- the file URL in the custom resolver always relative to stackYaml.
422
+ ResolverCustom _ url -> parseCustomMiniBuildPlan mconfigPath url
423
+ ResolverCompiler compiler -> return MiniBuildPlan
424
+ { mbpCompilerVersion = compiler
425
+ , mbpPackages = mempty
426
+ , mbpAllowNewer = False
427
+ }
428
+
407
429
-- | Load up a 'MiniBuildPlan', preferably from cache
408
430
loadMiniBuildPlan
409
431
:: (MonadIO m , MonadThrow m , MonadLogger m , MonadReader env m , HasHttpManager env , HasConfig env , HasGHCVariant env , MonadBaseControl IO m , MonadCatch m )
@@ -883,11 +905,20 @@ shadowMiniBuildPlan (MiniBuildPlan cv pkgs0 allowNewer) shadowed =
883
905
Just False -> Right
884
906
Nothing -> assert False Right
885
907
886
- parseCustomMiniBuildPlan :: (MonadIO m , MonadCatch m , MonadLogger m , MonadReader env m , HasHttpManager env , HasConfig env , MonadBaseControl IO m )
887
- => Path Abs File -- ^ stack.yaml file location
888
- -> T. Text -> m MiniBuildPlan
889
- parseCustomMiniBuildPlan stackYamlFP url0 = do
890
- yamlFP <- getYamlFP url0
908
+ parseCustomMiniBuildPlan
909
+ :: (MonadIO m , MonadCatch m , MonadLogger m , MonadReader env m , HasHttpManager env , HasConfig env , HasGHCVariant env , MonadBaseControl IO m )
910
+ => Maybe (Path Abs File ) -- ^ Root directory for when url is a filepath
911
+ -> T. Text
912
+ -> m MiniBuildPlan
913
+ parseCustomMiniBuildPlan mconfigPath url0 = do
914
+ $ logDebug $ " Loading " <> url0 <> " build plan"
915
+ eyamlFP <- getYamlFP url0
916
+ let yamlFP = either id id eyamlFP
917
+
918
+ -- FIXME: determine custom snapshot path based on contents. Ideally,
919
+ -- use a hash scheme that ignores formatting differences (works on
920
+ -- the data), so that an implicit snapshot (TBD) will hash to the
921
+ -- same thing as a custom snapshot.
891
922
892
923
yamlBS <- liftIO $ S. readFile $ toFilePath yamlFP
893
924
let yamlHash = S8. unpack $ B16. encode $ SHA256. hash yamlBS
@@ -896,36 +927,33 @@ parseCustomMiniBuildPlan stackYamlFP url0 = do
896
927
let binaryFP = customPlanDir </> $ (mkRelDir " bin" ) </> binaryFilename
897
928
898
929
taggedDecodeOrLoad binaryFP $ do
899
- WithJSONWarnings result warnings <-
930
+ WithJSONWarnings (cs0, mresolver) warnings <-
900
931
either (throwM . ParseCustomSnapshotException url0) return $
901
932
decodeEither' yamlBS
902
- logJSONWarnings (toFilePath yamlFP) warnings
903
- let (CustomSnapshot
904
- mcompilerVersion
905
- packages
906
- (PackageFlags flags)
907
- ghcOptions
908
- allowNewer) = result
909
- let addFlags :: PackageIdentifier -> (PackageName , (Version , Map FlagName Bool , [Text ]))
910
- addFlags (PackageIdentifier name ver) =
911
- ( name
912
- , ( ver
913
- , Map. findWithDefault Map. empty name flags
914
- -- NOTE: similar to 'allGhcOptions' in Stack.Types.Build
915
- , ghcOptionsFor name ghcOptions
916
- )
917
- )
918
- case mcompilerVersion of
919
- Just compilerVersion ->
920
- toMiniBuildPlan
921
- compilerVersion
922
- (fromMaybe False allowNewer)
923
- Map. empty
924
- (Map. fromList $ map addFlags $ Set. toList packages)
925
- Nothing -> do
926
- -- TODO: proper exception type
933
+ logJSONWarnings (T. unpack url0) warnings
934
+ case (mresolver, csCompilerVersion cs0) of
935
+ (Nothing , Nothing ) ->
927
936
fail $ " Failed to load custom snapshot at " ++
928
- T. unpack url0 ++ " , because no compiler is specified."
937
+ T. unpack url0 ++
938
+ " , because no 'compiler' or 'resolver' is specified."
939
+ (Nothing , Just cv) ->
940
+ applyCustomSnapshot cs0 MiniBuildPlan
941
+ { mbpCompilerVersion = cv
942
+ , mbpPackages = mempty
943
+ , mbpAllowNewer = False
944
+ }
945
+ -- Even though we ignore the compiler version here, it gets
946
+ -- used due to applyCustomSnapshot
947
+ (Just resolver, _) -> do
948
+ -- Load referenced resolver. If the custom snapshot is
949
+ -- stored at a user location, then allow relative
950
+ -- filepath custom snapshots.
951
+ mbp <- loadResolver customFile resolver
952
+ applyCustomSnapshot cs0 mbp
953
+ where
954
+ customFile = case eyamlFP of
955
+ Left _ -> Nothing
956
+ Right fp -> Just fp
929
957
where
930
958
getCustomPlanDir = do
931
959
root <- asks $ configStackRoot . getConfig
@@ -944,9 +972,45 @@ parseCustomMiniBuildPlan stackYamlFP url0 = do
944
972
945
973
let cacheFP = customPlanDir </> $ (mkRelDir " yaml" ) </> hashFP
946
974
_ <- download req cacheFP
947
- return cacheFP
948
-
949
- getYamlFPFromFile url = do
950
- fp <- liftIO $ D. canonicalizePath $ toFilePath (parent stackYamlFP) FP. </> T. unpack (fromMaybe url $
951
- T. stripPrefix " file://" url <|> T. stripPrefix " file:" url)
952
- parseAbsFile fp
975
+ return (Left cacheFP)
976
+
977
+ getYamlFPFromFile url =
978
+ case mconfigPath of
979
+ Nothing -> throwM $ FilepathInDownloadedSnapshot url
980
+ Just configPath -> do
981
+ fp <- liftIO $ D. canonicalizePath $ toFilePath (parent configPath) FP. </> T. unpack (fromMaybe url $
982
+ T. stripPrefix " file://" url <|> T. stripPrefix " file:" url)
983
+ Right <$> parseAbsFile fp
984
+
985
+ applyCustomSnapshot
986
+ :: (MonadIO m , MonadLogger m , MonadReader env m , HasHttpManager env , MonadThrow m , HasConfig env , MonadBaseControl IO m , MonadCatch m )
987
+ => CustomSnapshot
988
+ -> MiniBuildPlan
989
+ -> m MiniBuildPlan
990
+ applyCustomSnapshot cs mbp0 = do
991
+ let CustomSnapshot mcompilerVersion
992
+ packages
993
+ dropPackages
994
+ (PackageFlags flags)
995
+ ghcOptions
996
+ mallowNewer
997
+ = cs
998
+ addFlagsAndOpts :: PackageIdentifier -> (PackageName , (Version , Map FlagName Bool , [Text ]))
999
+ addFlagsAndOpts (PackageIdentifier name ver) =
1000
+ ( name
1001
+ , ( ver
1002
+ , Map. findWithDefault Map. empty name flags
1003
+ -- NOTE: similar to 'allGhcOptions' in Stack.Types.Build
1004
+ , ghcOptionsFor name ghcOptions
1005
+ )
1006
+ )
1007
+ packageMap = Map. fromList $ map addFlagsAndOpts $ Set. toList packages
1008
+ cv = fromMaybe (mbpCompilerVersion mbp0) mcompilerVersion
1009
+ packages0 =
1010
+ mbpPackages mbp0 `Map.difference` (Map. fromSet (\ _ -> () ) dropPackages)
1011
+ mbp1 <- toMiniBuildPlan cv False mempty packageMap
1012
+ return $ MiniBuildPlan
1013
+ { mbpCompilerVersion = cv
1014
+ , mbpPackages = Map. union (mbpPackages mbp1) packages0
1015
+ , mbpAllowNewer = fromMaybe (mbpAllowNewer mbp0) mallowNewer
1016
+ }
0 commit comments