mirror of
https://github.com/NixOS/nix.git
synced 2025-11-14 22:42:41 +01:00
Register flake source trees as GC roots
This ensures that flakes don't get garbage-collected, which is important to get nix-channel-like behaviour. For example, running $ nix build hydra: will create a GC root ~/.cache/nix/flake-closures/hydra -> /nix/store/xarfiqcwa4w8r4qpz1a769xxs8c3phgn-flake-closure where the contents/references of the linked file in the store are the flake source trees used by the 'hydra' flake: /nix/store/n6d5f5lkpfjbmkyby0nlg8y1wbkmbc7i-source /nix/store/vbkg4zy1qd29fnhflsv9k2j9jnbqd5m2-source /nix/store/z46xni7d47s5wk694359mq9ay353ar94-source Note that this in itself is not enough to allow offline use; the fetcher for the flakeref (e.g. fetchGit or downloadCached) must not fail if it cannot fetch the latest version of the file, so long as it knows a cached version. Issue #2868.
This commit is contained in:
parent
6b77bfc28d
commit
90fe1dfd2f
3 changed files with 63 additions and 3 deletions
|
|
@ -132,6 +132,8 @@ struct ResolvedFlake
|
|||
|
||||
ResolvedFlake resolveFlake(EvalState &, const FlakeRef &, HandleLockFile);
|
||||
|
||||
void callFlake(EvalState & state, const ResolvedFlake & resFlake, Value & v);
|
||||
|
||||
void updateLockFile(EvalState &, const FlakeRef & flakeRef, bool recreateLockFile);
|
||||
|
||||
void gitCloneFlake(FlakeRef flakeRef, EvalState &, Registries, const Path & destDir);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "primops/flake.hh"
|
||||
|
||||
#include <regex>
|
||||
#include <queue>
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
@ -162,6 +163,44 @@ struct InstallableAttrPath : InstallableValue
|
|||
}
|
||||
};
|
||||
|
||||
void makeFlakeClosureGCRoot(Store & store, const FlakeRef & origFlakeRef, const ResolvedFlake & resFlake)
|
||||
{
|
||||
if (std::get_if<FlakeRef::IsPath>(&origFlakeRef.data)) return;
|
||||
|
||||
/* Get the store paths of all non-local flakes. */
|
||||
PathSet closure;
|
||||
|
||||
std::queue<std::reference_wrapper<const ResolvedFlake>> queue;
|
||||
queue.push(resFlake);
|
||||
|
||||
while (!queue.empty()) {
|
||||
const ResolvedFlake & flake = queue.front();
|
||||
queue.pop();
|
||||
if (!std::get_if<FlakeRef::IsPath>(&flake.flake.resolvedRef.data))
|
||||
closure.insert(flake.flake.storePath);
|
||||
for (const auto & dep : flake.flakeDeps)
|
||||
queue.push(dep.second);
|
||||
}
|
||||
|
||||
if (closure.empty()) return;
|
||||
|
||||
/* Write the closure to a file in the store. */
|
||||
auto closurePath = store.addTextToStore("flake-closure", concatStringsSep(" ", closure), closure);
|
||||
|
||||
Path cacheDir = getCacheDir() + "/nix/flake-closures";
|
||||
createDirs(cacheDir);
|
||||
|
||||
auto s = origFlakeRef.to_string();
|
||||
assert(s[0] != '.');
|
||||
s = replaceStrings(s, "%", "%25");
|
||||
s = replaceStrings(s, "/", "%2f");
|
||||
s = replaceStrings(s, ":", "%3a");
|
||||
Path symlink = cacheDir + "/" + s;
|
||||
debug("writing GC root '%s' for flake closure of '%s'", symlink, origFlakeRef);
|
||||
replaceSymlink(closurePath, symlink);
|
||||
store.addIndirectRoot(symlink);
|
||||
}
|
||||
|
||||
struct InstallableFlake : InstallableValue
|
||||
{
|
||||
FlakeRef flakeRef;
|
||||
|
|
@ -182,7 +221,11 @@ struct InstallableFlake : InstallableValue
|
|||
{
|
||||
auto vFlake = state.allocValue();
|
||||
|
||||
makeFlakeValue(state, flakeRef, cmd.getLockFileMode(), *vFlake);
|
||||
auto resFlake = resolveFlake(state, flakeRef, cmd.getLockFileMode());
|
||||
|
||||
callFlake(state, resFlake, *vFlake);
|
||||
|
||||
makeFlakeClosureGCRoot(*state.store, flakeRef, resFlake);
|
||||
|
||||
auto vProvides = (*vFlake->attrs->get(state.symbols.create("provides")))->value;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue