Fix GC closure generation

This commit is contained in:
Eelco Dolstra 2019-06-04 19:45:16 +02:00
parent 6dbd5c26e6
commit 278114d559
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
4 changed files with 40 additions and 25 deletions

View file

@ -50,7 +50,7 @@ void writeRegistry(const FlakeRegistry & registry, const Path & path)
writeFile(path, json.dump(4)); // The '4' is the number of spaces used in the indentation in the json file. writeFile(path, json.dump(4)); // The '4' is the number of spaces used in the indentation in the json file.
} }
NonFlakeDep::NonFlakeDep(const nlohmann::json & json) AbstractDep::AbstractDep(const nlohmann::json & json)
: ref(json["uri"]) : ref(json["uri"])
, narHash(Hash((std::string) json["narHash"])) , narHash(Hash((std::string) json["narHash"]))
{ {
@ -58,7 +58,7 @@ NonFlakeDep::NonFlakeDep(const nlohmann::json & json)
throw Error("lockfile contains mutable flakeref '%s'", ref); throw Error("lockfile contains mutable flakeref '%s'", ref);
} }
nlohmann::json NonFlakeDep::toJson() const nlohmann::json AbstractDep::toJson() const
{ {
nlohmann::json json; nlohmann::json json;
json["uri"] = ref.to_string(); json["uri"] = ref.to_string();
@ -66,22 +66,23 @@ nlohmann::json NonFlakeDep::toJson() const
return json; return json;
} }
Path AbstractDep::computeStorePath(Store & store) const
{
return store.makeFixedOutputPath(true, narHash, "source");
}
FlakeDep::FlakeDep(const nlohmann::json & json) FlakeDep::FlakeDep(const nlohmann::json & json)
: FlakeInputs(json) : FlakeInputs(json)
, AbstractDep(json)
, id(json["id"]) , id(json["id"])
, ref(json["uri"])
, narHash(Hash((std::string) json["narHash"]))
{ {
if (!ref.isImmutable())
throw Error("lockfile contains mutable flakeref '%s'", ref);
} }
nlohmann::json FlakeDep::toJson() const nlohmann::json FlakeDep::toJson() const
{ {
auto json = FlakeInputs::toJson(); auto json = FlakeInputs::toJson();
json.update(AbstractDep::toJson());
json["id"] = id; json["id"] = id;
json["uri"] = ref.to_string();
json["narHash"] = narHash.to_string(SRI);
return json; return json;
} }

View file

@ -1,3 +1,5 @@
#pragma once
#include "types.hh" #include "types.hh"
#include "flakeref.hh" #include "flakeref.hh"
@ -8,6 +10,7 @@ namespace nix {
struct Value; struct Value;
class EvalState; class EvalState;
class Store;
namespace flake { namespace flake {
@ -37,22 +40,29 @@ enum HandleLockFile : unsigned int
, UseNewLockFile // `RecreateLockFile` without writing to file , UseNewLockFile // `RecreateLockFile` without writing to file
}; };
struct NonFlakeDep struct AbstractDep
{ {
FlakeRef ref; FlakeRef ref;
Hash narHash; Hash narHash;
NonFlakeDep(const FlakeRef & flakeRef, const Hash & narHash) AbstractDep(const FlakeRef & flakeRef, const Hash & narHash)
: ref(flakeRef), narHash(narHash) {}; : ref(flakeRef), narHash(narHash) {};
NonFlakeDep(const nlohmann::json & json); AbstractDep(const nlohmann::json & json);
nlohmann::json toJson() const;
Path computeStorePath(Store & store) const;
};
struct NonFlakeDep : AbstractDep
{
using AbstractDep::AbstractDep;
bool operator ==(const NonFlakeDep & other) const bool operator ==(const NonFlakeDep & other) const
{ {
return ref == other.ref && narHash == other.narHash; return ref == other.ref && narHash == other.narHash;
} }
nlohmann::json toJson() const;
}; };
struct FlakeDep; struct FlakeDep;
@ -68,14 +78,12 @@ struct FlakeInputs
nlohmann::json toJson() const; nlohmann::json toJson() const;
}; };
struct FlakeDep : FlakeInputs struct FlakeDep : FlakeInputs, AbstractDep
{ {
FlakeId id; FlakeId id;
FlakeRef ref;
Hash narHash;
FlakeDep(const FlakeId & id, const FlakeRef & flakeRef, const Hash & narHash) FlakeDep(const FlakeId & id, const FlakeRef & flakeRef, const Hash & narHash)
: id(id), ref(flakeRef), narHash(narHash) {}; : AbstractDep(flakeRef, narHash), id(id) {};
FlakeDep(const nlohmann::json & json); FlakeDep(const nlohmann::json & json);

View file

@ -190,22 +190,28 @@ void makeFlakeClosureGCRoot(Store & store,
const FlakeRef & origFlakeRef, const FlakeRef & origFlakeRef,
const flake::ResolvedFlake & resFlake) const flake::ResolvedFlake & resFlake)
{ {
#if 0
if (std::get_if<FlakeRef::IsPath>(&origFlakeRef.data)) return; if (std::get_if<FlakeRef::IsPath>(&origFlakeRef.data)) return;
/* Get the store paths of all non-local flakes. */ /* Get the store paths of all non-local flakes. */
PathSet closure; PathSet closure;
std::queue<std::reference_wrapper<const flake::ResolvedFlake>> queue; assert(store.isValidPath(resFlake.flake.sourceInfo.storePath));
queue.push(resFlake); closure.insert(resFlake.flake.sourceInfo.storePath);
std::queue<std::reference_wrapper<const flake::FlakeInputs>> queue;
queue.push(resFlake.lockFile);
while (!queue.empty()) { while (!queue.empty()) {
const flake::ResolvedFlake & flake = queue.front(); const flake::FlakeInputs & flake = queue.front();
queue.pop(); queue.pop();
if (!std::get_if<FlakeRef::IsPath>(&flake.flake.sourceInfo.resolvedRef.data)) /* Note: due to lazy fetching, these paths might not exist
closure.insert(flake.flake.sourceInfo.storePath); yet. */
for (const auto & dep : flake.flakeDeps) for (auto & dep : flake.flakeDeps) {
closure.insert(dep.second.computeStorePath(store));
queue.push(dep.second); queue.push(dep.second);
}
for (auto & dep : flake.nonFlakeDeps)
closure.insert(dep.second.computeStorePath(store));
} }
if (closure.empty()) return; if (closure.empty()) return;
@ -225,7 +231,6 @@ void makeFlakeClosureGCRoot(Store & store,
debug("writing GC root '%s' for flake closure of '%s'", symlink, origFlakeRef); debug("writing GC root '%s' for flake closure of '%s'", symlink, origFlakeRef);
replaceSymlink(closurePath, symlink); replaceSymlink(closurePath, symlink);
store.addIndirectRoot(symlink); store.addIndirectRoot(symlink);
#endif
} }
struct InstallableFlake : InstallableValue struct InstallableFlake : InstallableValue

View file

@ -204,6 +204,7 @@ nix flake list --flake-registry file://$registry --tarball-ttl 0 | grep -q flake
mv $registry.tmp $registry mv $registry.tmp $registry
# Test whether flakes are registered as GC roots for offline use. # Test whether flakes are registered as GC roots for offline use.
# FIXME: use tarballs rather than git.
rm -rf $TEST_HOME/.cache rm -rf $TEST_HOME/.cache
nix build -o $TEST_ROOT/result --flake-registry file://$registry file://$flake2Dir:bar nix build -o $TEST_ROOT/result --flake-registry file://$registry file://$flake2Dir:bar
mv $flake1Dir $flake1Dir.tmp mv $flake1Dir $flake1Dir.tmp