Created
November 16, 2024 12:35
-
-
Save jkarni/e0a6b6c4c574db25b21e2899508a71a3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
makeNormalizedFlake :: [Build] -> M NormalizedFlake | |
makeNormalizedFlake = foldM go mempty | |
where | |
getStorePath :: Build -> M (Maybe StorePath) | |
getStorePath build = case build ^. drvPath of | |
Nothing -> pure Nothing | |
Just path -> do | |
nixConfig <- view userNixConfig | |
-- We here fetch the drv from the cache. The drv might be private, so | |
-- we need the authentication token. | |
-- Note that there is a small race condition here, since it could be | |
-- that between us fetching the drv and using it, or between checking | |
-- that it exists and using it, garbage collection runs. So we make | |
-- sure the build still succeeds (just not with a cache) if so. | |
drvExistsLocally <- liftIO $ doesFileExist path | |
unless drvExistsLocally $ do | |
(StderrRaw err, exit) <- | |
run | |
$ cmd "nix-store" | |
& addArgs ["--realize", path] | |
& addNixConfigEnvironment nixConfig | |
case exit of | |
ExitSuccess -> | |
log Informational | |
$ "Successfully fetched " | |
<> cs path | |
<> " from the cache for incremental build" | |
ExitFailure c -> | |
log Error | |
$ "'nix-store --realize' failed with exit code " | |
<> show c | |
<> " and stderr " | |
<> cs err | |
(StdoutTrimmed result, StderrRaw err, exit) <- | |
run | |
$ cmd "nix" | |
& addArgs ["derivation", "show", path] | |
& addNixConfigEnvironment nixConfig | |
case exit of | |
ExitSuccess -> | |
pure | |
$ result | |
^? key (fromString $ cs path) | |
. key "outputs" | |
. key "intermediates" | |
. key "path" | |
. _String | |
. to StorePath | |
ExitFailure c -> do | |
log Error | |
$ "'nix derivation show' failed with exit code " | |
<> show c | |
<> " and stderr " | |
<> cs err | |
pure Nothing | |
go :: NormalizedFlake -> Build -> M NormalizedFlake | |
go f build | |
| build ^. packageType == TypeOverall = pure f | |
| otherwise = do | |
storePath <- getStorePath build | |
pure | |
$ f | |
& at | |
( build ^. packageType, | |
build ^. system, | |
build ^. package | |
) | |
.~ storePath | |
renderNormalizedFlakeWithHelpers :: FilePath -> NormalizedFlake -> IO Text | |
renderNormalizedFlakeWithHelpers emptyDir' (NormalizedFlake f) = cs <$> rendered | |
where | |
renderSingle :: (PackageType, MaybeSystem, PackageName) -> StorePath -> Text -> Text | |
renderSingle (typ, sys, PackageName name) (StorePath s) prev = | |
prev | |
<> "\n" | |
<> (typ ^. re asPackageType) | |
<> "s." | |
<> case sys of | |
NoSystem -> "" | |
IsSystem s -> s ^. systemTextIso <> "." | |
<> name | |
<> case typ of | |
TypeNixosConfiguration -> ".config.system.build.toplevel" | |
_ -> "" | |
<> ".intermediates" | |
<> " = builtins.fetchClosure { " | |
<> " inputAddressed = true;" -- Is this worth changing? | |
<> " fromStore = \"https://cache.garnix.io\"; " | |
<> " fromPath = " | |
<> show s | |
<> ";" | |
<> " };" | |
attrs :: Text | |
attrs = Map.foldrWithKey renderSingle "" f | |
helpers = do | |
pure | |
[i| | |
lib.withCaches = args.self.lib.withCachesFor args.self; | |
lib.withCachesFor = prev: outputs: | |
let wantedAttrs = ["packages" "checks" "devShells"]; | |
emptyDir = "${#{emptyDir'}}"; | |
mapAttrsIfSet = fn : s : if builtins.isAttrs s then builtins.mapAttrs fn s else s; | |
in (mapAttrsIfSet (type: | |
mapAttrsIfSet (sys: | |
mapAttrsIfSet (pkg: def: | |
if builtins.elem type wantedAttrs && builtins.isFunction def | |
then (def (prev.${type}.${sys}.${pkg}.intermediates or emptyDir)) | |
else def | |
)))) outputs; | |
|] | |
rendered = do | |
h <- helpers | |
pure | |
[i| | |
{ | |
outputs = args : { | |
#{attrs} | |
#{h} | |
}; | |
} | |
|] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment