aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2021-09-15 20:18:23 +0200
committerGitHub <noreply@github.com>2021-09-15 20:18:23 +0200
commit1ec4efa6c82fb6d90887c21aa7c7c6f3c644dd65 (patch)
treebb672e0f7cf93cf6412041a88e2f396b4417042d /src
parentc17f3c5e699a8332acc536b985dcd710f3ce0a23 (diff)
parent027344ce7e88bfcb6f8ed890299f286cc8e4156e (diff)
Merge pull request #5257 from edolstra/dirty-lock-file
If we can't write a lock file, pretend the top-level flake is dirty
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/flake/flake.cc12
-rw-r--r--src/libexpr/flake/flake.hh11
-rw-r--r--src/libexpr/primops.cc5
-rw-r--r--src/libexpr/primops/fetchTree.cc37
4 files changed, 38 insertions, 27 deletions
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 010d97285..c1a099613 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -635,8 +635,10 @@ LockedFlake lockFlake(
}
} else
throw Error("cannot write modified lock file of flake '%s' (use '--no-write-lock-file' to ignore)", topRef);
- } else
+ } else {
warn("not writing modified lock file of flake '%s':\n%s", topRef, chomp(diff));
+ flake.forceDirty = true;
+ }
}
return LockedFlake { .flake = std::move(flake), .lockFile = std::move(newLockFile) };
@@ -659,7 +661,13 @@ void callFlake(EvalState & state,
mkString(*vLocks, lockedFlake.lockFile.to_string());
- emitTreeAttrs(state, *lockedFlake.flake.sourceInfo, lockedFlake.flake.lockedRef.input, *vRootSrc);
+ emitTreeAttrs(
+ state,
+ *lockedFlake.flake.sourceInfo,
+ lockedFlake.flake.lockedRef.input,
+ *vRootSrc,
+ false,
+ lockedFlake.flake.forceDirty);
mkString(*vRootSubdir, lockedFlake.flake.lockedRef.subdir);
diff --git a/src/libexpr/flake/flake.hh b/src/libexpr/flake/flake.hh
index d46da9d68..524b18af1 100644
--- a/src/libexpr/flake/flake.hh
+++ b/src/libexpr/flake/flake.hh
@@ -58,9 +58,10 @@ struct ConfigFile
/* The contents of a flake.nix file. */
struct Flake
{
- FlakeRef originalRef; // the original flake specification (by the user)
- FlakeRef resolvedRef; // registry references and caching resolved to the specific underlying flake
- FlakeRef lockedRef; // the specific local store result of invoking the fetcher
+ FlakeRef originalRef; // the original flake specification (by the user)
+ FlakeRef resolvedRef; // registry references and caching resolved to the specific underlying flake
+ FlakeRef lockedRef; // the specific local store result of invoking the fetcher
+ bool forceDirty = false; // pretend that 'lockedRef' is dirty
std::optional<std::string> description;
std::shared_ptr<const fetchers::Tree> sourceInfo;
FlakeInputs inputs;
@@ -140,6 +141,8 @@ void emitTreeAttrs(
EvalState & state,
const fetchers::Tree & tree,
const fetchers::Input & input,
- Value & v, bool emptyRevFallback = false);
+ Value & v,
+ bool emptyRevFallback = false,
+ bool forceDirty = false);
}
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 1de86ad04..8a087a781 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1412,11 +1412,6 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va
{
PathSet context;
Path path = state.coerceToPath(pos, *args[0], context);
- if (baseNameOf(path) == "flake.lock")
- throw Error({
- .msg = hintfmt("cannot read '%s' because flake lock files can be out of sync", path),
- .errPos = pos
- });
try {
state.realiseContext(context);
} catch (InvalidPathError & e) {
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index 9c791db31..d004b701b 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -16,7 +16,8 @@ void emitTreeAttrs(
const fetchers::Tree & tree,
const fetchers::Input & input,
Value & v,
- bool emptyRevFallback)
+ bool emptyRevFallback,
+ bool forceDirty)
{
assert(input.isImmutable());
@@ -33,24 +34,28 @@ void emitTreeAttrs(
mkString(*state.allocAttr(v, state.symbols.create("narHash")),
narHash->to_string(SRI, true));
- if (auto rev = input.getRev()) {
- mkString(*state.allocAttr(v, state.symbols.create("rev")), rev->gitRev());
- mkString(*state.allocAttr(v, state.symbols.create("shortRev")), rev->gitShortRev());
- } else if (emptyRevFallback) {
- // Backwards compat for `builtins.fetchGit`: dirty repos return an empty sha1 as rev
- auto emptyHash = Hash(htSHA1);
- mkString(*state.allocAttr(v, state.symbols.create("rev")), emptyHash.gitRev());
- mkString(*state.allocAttr(v, state.symbols.create("shortRev")), emptyHash.gitShortRev());
- }
-
if (input.getType() == "git")
mkBool(*state.allocAttr(v, state.symbols.create("submodules")),
fetchers::maybeGetBoolAttr(input.attrs, "submodules").value_or(true));
- if (auto revCount = input.getRevCount())
- mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *revCount);
- else if (emptyRevFallback)
- mkInt(*state.allocAttr(v, state.symbols.create("revCount")), 0);
+ if (!forceDirty) {
+
+ if (auto rev = input.getRev()) {
+ mkString(*state.allocAttr(v, state.symbols.create("rev")), rev->gitRev());
+ mkString(*state.allocAttr(v, state.symbols.create("shortRev")), rev->gitShortRev());
+ } else if (emptyRevFallback) {
+ // Backwards compat for `builtins.fetchGit`: dirty repos return an empty sha1 as rev
+ auto emptyHash = Hash(htSHA1);
+ mkString(*state.allocAttr(v, state.symbols.create("rev")), emptyHash.gitRev());
+ mkString(*state.allocAttr(v, state.symbols.create("shortRev")), emptyHash.gitShortRev());
+ }
+
+ if (auto revCount = input.getRevCount())
+ mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *revCount);
+ else if (emptyRevFallback)
+ mkInt(*state.allocAttr(v, state.symbols.create("revCount")), 0);
+
+ }
if (auto lastModified = input.getLastModified()) {
mkInt(*state.allocAttr(v, state.symbols.create("lastModified")), *lastModified);
@@ -167,7 +172,7 @@ static void fetchTree(
if (state.allowedPaths)
state.allowedPaths->insert(tree.actualPath);
- emitTreeAttrs(state, tree, input2, v, params.emptyRevFallback);
+ emitTreeAttrs(state, tree, input2, v, params.emptyRevFallback, false);
}
static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, Value & v)