From d1165d8791f559352ff6aa7348e1293b2873db1c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 17 Mar 2020 21:34:38 +0100 Subject: Require shallow clones to be requested explicitly If you do a fetchTree on a Git repository, whether the result contains a revCount attribute should not depend on whether that repository happens to be a shallow clone or not. That would complicate caching a lot and would be semantically messy. So applying fetchTree/fetchGit to a shallow repository is now an error unless you pass the attribute 'shallow = true'. If 'shallow = true', we don't return revCount, even if the repository is not actually shallow. Note that Nix itself is not doing shallow clones at the moment. But it could do so as an optimisation if the user specifies 'shallow = true'. Issue #2988. --- src/libstore/fetchers/git.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/libstore/fetchers/git.cc') diff --git a/src/libstore/fetchers/git.cc b/src/libstore/fetchers/git.cc index 179a5fb83..c5d4f019c 100644 --- a/src/libstore/fetchers/git.cc +++ b/src/libstore/fetchers/git.cc @@ -83,6 +83,7 @@ struct GitInput : Input ParsedURL url; std::optional ref; std::optional rev; + bool shallow = false; GitInput(const ParsedURL & url) : url(url) { } @@ -114,6 +115,7 @@ struct GitInput : Input if (url2.scheme != "git") url2.scheme = "git+" + url2.scheme; if (rev) url2.query.insert_or_assign("rev", rev->gitRev()); if (ref) url2.query.insert_or_assign("ref", *ref); + if (shallow) url2.query.insert_or_assign("shallow", "1"); return url2.to_string(); } @@ -125,6 +127,8 @@ struct GitInput : Input attrs.emplace("ref", *ref); if (rev) attrs.emplace("rev", rev->gitRev()); + if (shallow) + attrs.emplace("shallow", true); return attrs; } @@ -361,9 +365,12 @@ struct GitInput : Input bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "rev-parse", "--is-shallow-repository" })) == "true"; + if (isShallow && !shallow) + throw Error("'%s' is a shallow Git repository, but a non-shallow repository is needed", actualUrl); + if (auto tree = lookupGitInfo(store, name, *input->rev)) { assert(*input->rev == tree->first); - if (isShallow) tree->second.info.revCount.reset(); + if (shallow) tree->second.info.revCount.reset(); return {std::move(tree->second), input}; } @@ -393,7 +400,7 @@ struct GitInput : Input .storePath = std::move(storePath), .info = TreeInfo { .revCount = - !isShallow + !shallow ? std::optional(std::stoull(runProgram("git", true, { "-C", repoDir, "rev-list", "--count", input->rev->gitRev() }))) : std::nullopt, .lastModified = lastModified @@ -440,7 +447,7 @@ struct GitInputScheme : InputScheme if (maybeGetStrAttr(attrs, "type") != "git") return {}; for (auto & [name, value] : attrs) - if (name != "type" && name != "url" && name != "ref" && name != "rev") + if (name != "type" && name != "url" && name != "ref" && name != "rev" && name != "shallow") throw Error("unsupported Git input attribute '%s'", name); auto input = std::make_unique(parseURL(getStrAttr(attrs, "url"))); @@ -451,6 +458,9 @@ struct GitInputScheme : InputScheme } if (auto rev = maybeGetStrAttr(attrs, "rev")) input->rev = Hash(*rev, htSHA1); + + input->shallow = maybeGetBoolAttr(attrs, "shallow").value_or(false); + return input; } }; -- cgit v1.2.3