Only rewrite the lockfile if it changed

This removes spurious warnings about failure to write the lockfile.
This commit is contained in:
Eelco Dolstra 2019-05-21 14:55:43 +02:00
parent 818c8da5b8
commit 20a1a65d37
2 changed files with 37 additions and 12 deletions

View file

@ -465,31 +465,35 @@ ResolvedFlake resolveFlakeFromLockFile(EvalState & state, const FlakeRef & flake
ResolvedFlake resolveFlake(EvalState & state, const FlakeRef & topRef, HandleLockFile handleLockFile) ResolvedFlake resolveFlake(EvalState & state, const FlakeRef & topRef, HandleLockFile handleLockFile)
{ {
Flake flake = getFlake(state, topRef, allowedToUseRegistries(handleLockFile, true)); Flake flake = getFlake(state, topRef, allowedToUseRegistries(handleLockFile, true));
LockFile lockFile; LockFile oldLockFile;
if (!recreateLockFile (handleLockFile)) { if (!recreateLockFile (handleLockFile)) {
// If recreateLockFile, start with an empty lockfile // If recreateLockFile, start with an empty lockfile
lockFile = readLockFile(flake.storePath + "/flake.lock"); // FIXME: symlink attack oldLockFile = readLockFile(flake.storePath + "/flake.lock"); // FIXME: symlink attack
} }
LockFile lockFile(oldLockFile);
ResolvedFlake resFlake = resolveFlakeFromLockFile(state, topRef, handleLockFile, lockFile, true); ResolvedFlake resFlake = resolveFlakeFromLockFile(state, topRef, handleLockFile, lockFile, true);
lockFile = entryToLockFile(dependenciesToFlakeEntry(resFlake)); lockFile = entryToLockFile(dependenciesToFlakeEntry(resFlake));
if (allowedToWrite(handleLockFile)) { if (!(lockFile == oldLockFile)) {
if (auto refData = std::get_if<FlakeRef::IsPath>(&topRef.data)) { if (allowedToWrite(handleLockFile)) {
writeLockFile(lockFile, refData->path + (topRef.subdir == "" ? "" : "/" + topRef.subdir) + "/flake.lock"); if (auto refData = std::get_if<FlakeRef::IsPath>(&topRef.data)) {
writeLockFile(lockFile, refData->path + (topRef.subdir == "" ? "" : "/" + topRef.subdir) + "/flake.lock");
// Hack: Make sure that flake.lock is visible to Git, so it ends up in the Nix store. // Hack: Make sure that flake.lock is visible to Git, so it ends up in the Nix store.
runProgram("git", true, { "-C", refData->path, "add", runProgram("git", true, { "-C", refData->path, "add",
(topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock" }); (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock" });
} else std::cout << "Cannot write lockfile because the FlakeRef isn't of the form IsPath." << std::endl; } else std::cout << "Cannot write lockfile because the FlakeRef isn't of the form IsPath." << std::endl;
} else if (handleLockFile != AllPure && handleLockFile != TopRefUsesRegistries) } else if (handleLockFile != AllPure && handleLockFile != TopRefUsesRegistries)
std::cout << "Using updating lockfile without writing it to file" << std::endl; std::cout << "Using updating lockfile without writing it to file" << std::endl;
}
return resFlake; return resFlake;
} }
void updateLockFile (EvalState & state, const FlakeUri & flakeUri, bool recreateLockFile) void updateLockFile(EvalState & state, const FlakeUri & flakeUri, bool recreateLockFile)
{ {
FlakeRef flakeRef(flakeUri); FlakeRef flakeRef(flakeUri);
resolveFlake(state, flakeRef, recreateLockFile ? RecreateLockFile : UpdateLockFile); resolveFlake(state, flakeRef, recreateLockFile ? RecreateLockFile : UpdateLockFile);

View file

@ -24,6 +24,11 @@ struct LockFile
FlakeRef ref; FlakeRef ref;
Hash contentHash; Hash contentHash;
NonFlakeEntry(const FlakeRef & flakeRef, const Hash & hash) : ref(flakeRef), contentHash(hash) {}; NonFlakeEntry(const FlakeRef & flakeRef, const Hash & hash) : ref(flakeRef), contentHash(hash) {};
bool operator ==(const NonFlakeEntry & other) const
{
return ref == other.ref && contentHash == other.contentHash;
}
}; };
struct FlakeEntry struct FlakeEntry
@ -33,10 +38,26 @@ struct LockFile
std::map<FlakeRef, FlakeEntry> flakeEntries; std::map<FlakeRef, FlakeEntry> flakeEntries;
std::map<FlakeAlias, NonFlakeEntry> nonFlakeEntries; std::map<FlakeAlias, NonFlakeEntry> nonFlakeEntries;
FlakeEntry(const FlakeRef & flakeRef, const Hash & hash) : ref(flakeRef), contentHash(hash) {}; FlakeEntry(const FlakeRef & flakeRef, const Hash & hash) : ref(flakeRef), contentHash(hash) {};
bool operator ==(const FlakeEntry & other) const
{
return
ref == other.ref
&& contentHash == other.contentHash
&& flakeEntries == other.flakeEntries
&& nonFlakeEntries == other.nonFlakeEntries;
}
}; };
std::map<FlakeRef, FlakeEntry> flakeEntries; std::map<FlakeRef, FlakeEntry> flakeEntries;
std::map<FlakeAlias, NonFlakeEntry> nonFlakeEntries; std::map<FlakeAlias, NonFlakeEntry> nonFlakeEntries;
bool operator ==(const LockFile & other) const
{
return
flakeEntries == other.flakeEntries
&& nonFlakeEntries == other.nonFlakeEntries;
}
}; };
typedef std::vector<std::shared_ptr<FlakeRegistry>> Registries; typedef std::vector<std::shared_ptr<FlakeRegistry>> Registries;