Don't write lock files if they have dirty inputs

This commit is contained in:
Eelco Dolstra 2019-07-12 13:29:54 +02:00
parent bd62290c23
commit b29cec7697
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
4 changed files with 36 additions and 10 deletions

View file

@ -405,17 +405,22 @@ ResolvedFlake resolveFlake(EvalState & state, const FlakeRef & topRef, HandleLoc
if (!(lockFile == oldLockFile)) { if (!(lockFile == oldLockFile)) {
if (allowedToWrite(handleLockFile)) { if (allowedToWrite(handleLockFile)) {
if (auto refData = std::get_if<FlakeRef::IsPath>(&topRef.data)) { if (auto refData = std::get_if<FlakeRef::IsPath>(&topRef.data)) {
lockFile.write(refData->path + (topRef.subdir == "" ? "" : "/" + topRef.subdir) + "/flake.lock"); if (lockFile.isDirty())
warn("will not write lock file of flake '%s' because it has a dirty input", topRef);
else {
lockFile.write(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,
"--force", { "-C", refData->path, "add",
"--intent-to-add", "--force",
(topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock" }); "--intent-to-add",
(topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock" });
}
} else } else
warn("cannot write lockfile of remote flake '%s'", topRef); warn("cannot write lock file of remote flake '%s'", topRef);
} else if (handleLockFile != AllPure && handleLockFile != TopRefUsesRegistries) } else if (handleLockFile != AllPure && handleLockFile != TopRefUsesRegistries)
warn("using updated lockfile without writing it to file"); warn("using updated lock file without writing it to file");
} }
return ResolvedFlake(std::move(flake), std::move(lockFile)); return ResolvedFlake(std::move(flake), std::move(lockFile));
@ -624,8 +629,8 @@ const Registries EvalState::getFlakeRegistries()
Fingerprint ResolvedFlake::getFingerprint() const Fingerprint ResolvedFlake::getFingerprint() const
{ {
// FIXME: as an optimization, if the flake contains a lockfile and // FIXME: as an optimization, if the flake contains a lock file
// we haven't changed it, then it's sufficient to use // and we haven't changed it, then it's sufficient to use
// flake.sourceInfo.storePath for the fingerprint. // flake.sourceInfo.storePath for the fingerprint.
return hashString(htSHA256, return hashString(htSHA256,
fmt("%s;%s", flake.sourceInfo.storePath, lockFile)); fmt("%s;%s", flake.sourceInfo.storePath, lockFile));

View file

@ -176,6 +176,12 @@ struct FlakeRef
bool isImmutable() const; bool isImmutable() const;
FlakeRef baseRef() const; FlakeRef baseRef() const;
bool isDirty() const
{
return std::get_if<FlakeRef::IsPath>(&data)
&& rev == Hash(rev->type);
}
}; };
std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef); std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef);

View file

@ -66,6 +66,17 @@ nlohmann::json FlakeInputs::toJson() const
return json; return json;
} }
bool FlakeInputs::isDirty() const
{
for (auto & i : flakeInputs)
if (i.second.ref.isDirty() || i.second.isDirty()) return true;
for (auto & i : nonFlakeInputs)
if (i.second.ref.isDirty()) return true;
return false;
}
nlohmann::json LockFile::toJson() const nlohmann::json LockFile::toJson() const
{ {
auto json = FlakeInputs::toJson(); auto json = FlakeInputs::toJson();

View file

@ -53,6 +53,10 @@ struct FlakeInputs
FlakeInputs(const nlohmann::json & json); FlakeInputs(const nlohmann::json & json);
nlohmann::json toJson() const; nlohmann::json toJson() const;
/* A lock file is dirty if it contains a dirty flakeref
(i.e. reference to a dirty working tree). */
bool isDirty() const;
}; };
/* Lock file information about a flake input. */ /* Lock file information about a flake input. */