diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 39fdc776c..5018b460b 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -579,22 +579,23 @@ LockedFlake lockFlake(
newLockFile.write(path);
- // Rewriting the lockfile changed the top-level
- // repo, so we should re-read it.
+ topRef.input->markChangedFile(
+ (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock");
+
+ /* Rewriting the lockfile changed the top-level
+ repo, so we should re-read it. FIXME: we could
+ also just clear the 'rev' field... */
+ auto prevLockedRef = flake.lockedRef;
FlakeCache dummyCache;
flake = getFlake(state, topRef, {}, lockFlags.useRegistries, dummyCache);
- if (flake.lockedRef.input->isImmutable())
+ /* Make sure that we picked up the change,
+ i.e. the tree should usually be dirty
+ now. Corner case: we could have reverted from a
+ dirty to a clean tree! */
+ if (flake.lockedRef.input == prevLockedRef.input
+ && !flake.lockedRef.input->isImmutable())
throw Error("'%s' did not change after I updated its 'flake.lock' file; is 'flake.lock' under version control?", flake.originalRef);
-
- #if 0
- // Hack: Make sure that flake.lock is visible to Git, so it ends up in the Nix store.
- runProgram("git", true,
- { "-C", *sourcePath, "add",
- "--force",
- "--intent-to-add",
- (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock" });
- #endif
}
} else
throw Error("cannot write modified lock file of flake '%s' (use '--no-write-lock-file' to ignore)", topRef);
diff --git a/src/libstore/fetchers/fetchers.hh b/src/libstore/fetchers/fetchers.hh
index 0ef79bc45..64628d1bb 100644
--- a/src/libstore/fetchers/fetchers.hh
+++ b/src/libstore/fetchers/fetchers.hh
@@ -62,6 +62,9 @@ struct Input : std::enable_shared_from_this
virtual std::optional getSourcePath() const { return {}; }
+ // FIXME: should merge with getSourcePath().
+ virtual void markChangedFile(std::string_view file) const { assert(false); }
+
virtual void clone(const Path & destDir) const
{
throw Error("do not know how to clone input '%s'", to_string());
diff --git a/src/libstore/fetchers/git.cc b/src/libstore/fetchers/git.cc
index 0101744bd..1c74d92a4 100644
--- a/src/libstore/fetchers/git.cc
+++ b/src/libstore/fetchers/git.cc
@@ -165,6 +165,18 @@ struct GitInput : Input
return {};
}
+ void markChangedFile(std::string_view file) const override
+ {
+ auto sourcePath = getSourcePath();
+ assert(sourcePath);
+ runProgram("git", true,
+ { "-C", *sourcePath, "add",
+ "--force",
+ "--intent-to-add",
+ std::string(file)
+ });
+ }
+
std::pair getActualUrl() const
{
// Don't clone file:// URIs (but otherwise treat them the
diff --git a/src/libstore/fetchers/mercurial.cc b/src/libstore/fetchers/mercurial.cc
index 9b8c2132c..0825f6b23 100644
--- a/src/libstore/fetchers/mercurial.cc
+++ b/src/libstore/fetchers/mercurial.cc
@@ -84,6 +84,17 @@ struct MercurialInput : Input
return {};
}
+ void markChangedFile(std::string_view file) const override
+ {
+ auto sourcePath = getSourcePath();
+ assert(sourcePath);
+ // FIXME: shut up if file is already tracked.
+ runProgram("hg", true,
+ { "add",
+ *sourcePath + "/" + std::string(file)
+ });
+ }
+
std::pair getActualUrl() const
{
bool isLocal = url.scheme == "file";
diff --git a/tests/flakes.sh b/tests/flakes.sh
index 5a00d8671..63e7f8e87 100644
--- a/tests/flakes.sh
+++ b/tests/flakes.sh
@@ -5,6 +5,11 @@ if [[ -z $(type -p git) ]]; then
exit 99
fi
+if [[ -z $(type -p hg) ]]; then
+ echo "Mercurial not installed; skipping flake tests"
+ exit 99
+fi
+
clearStore
rm -rf $TEST_HOME/.cache $TEST_HOME/.config
@@ -372,7 +377,7 @@ nix flake remove flake1
(cd $flake7Dir && nix flake init)
git -C $flake7Dir add flake.nix
nix flake check $flake7Dir
-git -C $flake7Dir commit -m 'Initial'
+git -C $flake7Dir commit -a -m 'Initial'
# Test 'nix flake clone'.
rm -rf $TEST_ROOT/flake1-v2
@@ -545,11 +550,6 @@ nix flake update $flake3Dir --recreate-lock-file
[[ $(jq .inputs.flake2.inputs.flake1.locked.url $flake3Dir/flake.lock) =~ flake7 ]]
# Test Mercurial flakes.
-if [[ -z $(type -p hg) ]]; then
- echo "Git not installed; skipping Mercurial flake tests"
- exit 99
-fi
-
rm -rf $flake5Dir
hg init $flake5Dir
@@ -571,12 +571,9 @@ hg commit --config ui.username=foobar@example.org $flake5Dir -m 'Initial commit'
nix build -o $TEST_ROOT/result hg+file://$flake5Dir
[[ -e $TEST_ROOT/result/hello ]]
-nix flake info --json hg+file://$flake5Dir | jq -e -r .revision
+(! nix flake info --json hg+file://$flake5Dir | jq -e -r .revision)
-# This will fail because flake.lock is not tracked by Mercurial.
-(! nix eval hg+file://$flake5Dir#expr)
-
-hg add $flake5Dir/flake.lock
+nix eval hg+file://$flake5Dir#expr
nix eval hg+file://$flake5Dir#expr