summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaximilian Bosch <maximilian@mbosch.me>2020-07-17 20:34:57 +0200
committerMaximilian Bosch <maximilian@mbosch.me>2020-12-22 10:46:00 +0100
commit2857b1baaf78bbadeec01adfae8a50fc0f2a254f (patch)
treec424d8bf474da2fe22b80289c0c3d3f7f9f9d906
parent629af83b2d86d77305dc994b83f176a377106c3e (diff)
Add explicit `allRefs = true;` argument to `fetchGit`
Sometimes it's necessary to fetch a git repository at a revision and it's unknown which ref contains the revision in question. An example would be a Cargo.lock which only provides the URL and the revision when using a git repository as build input. However it's considered a bad practice to perform a full checkout of a repository since this may take a lot of time and can eat up a lot of disk space. This patch makes a full checkout explicit by adding an `allRefs` argument to `builtins.fetchGit` which fetches all refs if explicitly set to true. Closes #2409
-rw-r--r--src/libfetchers/git.cc27
1 files changed, 18 insertions, 9 deletions
diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc
index 1f298c2d6..81c647f89 100644
--- a/src/libfetchers/git.cc
+++ b/src/libfetchers/git.cc
@@ -59,12 +59,13 @@ struct GitInputScheme : InputScheme
if (maybeGetStrAttr(attrs, "type") != "git") return {};
for (auto & [name, value] : attrs)
- if (name != "type" && name != "url" && name != "ref" && name != "rev" && name != "shallow" && name != "submodules" && name != "lastModified" && name != "revCount" && name != "narHash")
+ if (name != "type" && name != "url" && name != "ref" && name != "rev" && name != "shallow" && name != "submodules" && name != "lastModified" && name != "revCount" && name != "narHash" && name != "allRefs")
throw Error("unsupported Git input attribute '%s'", name);
parseURL(getStrAttr(attrs, "url"));
maybeGetBoolAttr(attrs, "shallow");
maybeGetBoolAttr(attrs, "submodules");
+ maybeGetBoolAttr(attrs, "allRefs");
if (auto ref = maybeGetStrAttr(attrs, "ref")) {
if (std::regex_search(*ref, badGitRefRegex))
@@ -169,10 +170,12 @@ struct GitInputScheme : InputScheme
bool shallow = maybeGetBoolAttr(input.attrs, "shallow").value_or(false);
bool submodules = maybeGetBoolAttr(input.attrs, "submodules").value_or(false);
+ bool allRefs = maybeGetBoolAttr(input.attrs, "allRefs").value_or(false);
std::string cacheType = "git";
if (shallow) cacheType += "-shallow";
if (submodules) cacheType += "-submodules";
+ if (allRefs) cacheType += "-all-refs";
auto getImmutableAttrs = [&]()
{
@@ -338,11 +341,15 @@ struct GitInputScheme : InputScheme
}
}
} else {
- /* If the local ref is older than ‘tarball-ttl’ seconds, do a
- git fetch to update the local ref to the remote ref. */
- struct stat st;
- doFetch = stat(localRefFile.c_str(), &st) != 0 ||
- (uint64_t) st.st_mtime + settings.tarballTtl <= (uint64_t) now;
+ if (allRefs) {
+ doFetch = true;
+ } else {
+ /* If the local ref is older than ‘tarball-ttl’ seconds, do a
+ git fetch to update the local ref to the remote ref. */
+ struct stat st;
+ doFetch = stat(localRefFile.c_str(), &st) != 0 ||
+ (uint64_t) st.st_mtime + settings.tarballTtl <= (uint64_t) now;
+ }
}
if (doFetch) {
@@ -352,9 +359,11 @@ struct GitInputScheme : InputScheme
// we're using --quiet for now. Should process its stderr.
try {
auto ref = input.getRef();
- auto fetchRef = ref->compare(0, 5, "refs/") == 0
- ? *ref
- : "refs/heads/" + *ref;
+ auto fetchRef = allRefs
+ ? "refs/*"
+ : ref->compare(0, 5, "refs/") == 0
+ ? *ref
+ : "refs/heads/" + *ref;
runProgram("git", true, { "-C", repoDir, "fetch", "--quiet", "--force", "--", actualUrl, fmt("%s:%s", fetchRef, fetchRef) });
} catch (Error & e) {
if (!pathExists(localRefFile)) throw;