aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-03-16 13:20:32 +0100
committerEelco Dolstra <edolstra@gmail.com>2020-03-16 13:20:32 +0100
commitfbcb897e21e6c7b866a7aed97129141c0e7caa22 (patch)
tree0d44d0e08a8af15432c1563aa4e2deade534c4e1
parent34c7645a586629b7e5f51e74c20dd675794ca117 (diff)
Add a test for shallow Git clones
Also, don't return a revCount anymore for shallow or dirty Git trees, since it's incorrect. Closes #2988.
-rw-r--r--src/libexpr/primops/fetchGit.cc5
-rw-r--r--src/libstore/fetchers/git.cc14
-rw-r--r--tests/fetchGit.sh8
3 files changed, 21 insertions, 6 deletions
diff --git a/src/libexpr/primops/fetchGit.cc b/src/libexpr/primops/fetchGit.cc
index 18774371b..638c14970 100644
--- a/src/libexpr/primops/fetchGit.cc
+++ b/src/libexpr/primops/fetchGit.cc
@@ -67,8 +67,9 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
auto rev2 = input2->getRev().value_or(Hash(htSHA1));
mkString(*state.allocAttr(v, state.symbols.create("rev")), rev2.gitRev());
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), rev2.gitShortRev());
- assert(tree.info.revCount);
- mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.info.revCount);
+ // Backward compatibility: set 'revCount' to 0 for a dirty tree.
+ mkInt(*state.allocAttr(v, state.symbols.create("revCount")),
+ tree.info.revCount.value_or(0));
v.attrs->sort();
if (state.allowedPaths)
diff --git a/src/libstore/fetchers/git.cc b/src/libstore/fetchers/git.cc
index 9276b0993..46ca187fe 100644
--- a/src/libstore/fetchers/git.cc
+++ b/src/libstore/fetchers/git.cc
@@ -34,6 +34,8 @@ static void cacheGitInfo(
const Tree & tree,
const Hash & rev)
{
+ if (!tree.info.revCount || !tree.info.lastModified) return;
+
nlohmann::json json;
json["storePath"] = store.printStorePath(tree.storePath);
json["name"] = name;
@@ -169,6 +171,7 @@ struct GitInput : Input
return url.path;
return {};
}
+
void markChangedFile(std::string_view file, std::optional<std::string> commitMsg) const override
{
auto sourcePath = getSourcePath();
@@ -271,7 +274,6 @@ struct GitInput : Input
.actualPath = store->printStorePath(storePath),
.storePath = std::move(storePath),
.info = TreeInfo {
- .revCount = haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "rev-list", "--count", "HEAD" })) : 0,
// FIXME: maybe we should use the timestamp of the last
// modified dirty file?
.lastModified = haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "log", "-1", "--format=%ct", "HEAD" })) : 0,
@@ -357,8 +359,11 @@ struct GitInput : Input
input->rev = Hash(chomp(readFile(localRefFile)), htSHA1);
}
+ bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "rev-parse", "--is-shallow-repository" })) == "true";
+
if (auto tree = lookupGitInfo(store, name, *input->rev)) {
assert(*input->rev == tree->first);
+ if (isShallow) tree->second.info.revCount.reset();
return {std::move(tree->second), input};
}
@@ -380,14 +385,17 @@ struct GitInput : Input
unpackTarfile(*source, tmpDir);
auto storePath = store->addToStore(name, tmpDir);
- auto revCount = std::stoull(runProgram("git", true, { "-C", repoDir, "rev-list", "--count", input->rev->gitRev() }));
+
auto lastModified = std::stoull(runProgram("git", true, { "-C", repoDir, "log", "-1", "--format=%ct", input->rev->gitRev() }));
auto tree = Tree {
.actualPath = store->toRealPath(storePath),
.storePath = std::move(storePath),
.info = TreeInfo {
- .revCount = revCount,
+ .revCount =
+ !isShallow
+ ? std::optional(std::stoull(runProgram("git", true, { "-C", repoDir, "rev-list", "--count", input->rev->gitRev() })))
+ : std::nullopt,
.lastModified = lastModified
}
};
diff --git a/tests/fetchGit.sh b/tests/fetchGit.sh
index b64f444a5..6e5a4750e 100644
--- a/tests/fetchGit.sh
+++ b/tests/fetchGit.sh
@@ -11,7 +11,7 @@ repo=$TEST_ROOT/git
export _NIX_FORCE_HTTP=1
-rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix/gitv* $TEST_ROOT/worktree
+rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix/git* $TEST_ROOT/worktree $TEST_ROOT/shallow
git init $repo
git -C $repo config user.email "foobar@example.com"
@@ -147,3 +147,9 @@ NIX=$(command -v nix)
# Try again, with 'git' available. This should work.
path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath")
[[ $path3 = $path5 ]]
+
+# Check that shallow clones work and don't return a revcount.
+git clone --depth 1 file://$repo $TEST_ROOT/shallow
+path6=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/shallow; ref = \"dev\"; }).outPath")
+[[ $path3 = $path6 ]]
+[[ $(nix eval --impure --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; }).revCount or 123") == 123 ]]