Skip to content

Commit 2dd3944

Browse files
committed
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 NixOS#2409
1 parent 644a033 commit 2dd3944

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

src/libfetchers/git.cc

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,13 @@ struct GitInputScheme : InputScheme
5858
if (maybeGetStrAttr(attrs, "type") != "git") return {};
5959

6060
for (auto & [name, value] : attrs)
61-
if (name != "type" && name != "url" && name != "ref" && name != "rev" && name != "shallow" && name != "submodules" && name != "lastModified" && name != "revCount" && name != "narHash")
61+
if (name != "type" && name != "url" && name != "ref" && name != "rev" && name != "shallow" && name != "submodules" && name != "lastModified" && name != "revCount" && name != "narHash" && name != "allRefs")
6262
throw Error("unsupported Git input attribute '%s'", name);
6363

6464
parseURL(getStrAttr(attrs, "url"));
6565
maybeGetBoolAttr(attrs, "shallow");
6666
maybeGetBoolAttr(attrs, "submodules");
67+
maybeGetBoolAttr(attrs, "allRefs");
6768

6869
if (auto ref = maybeGetStrAttr(attrs, "ref")) {
6970
if (std::regex_search(*ref, badGitRefRegex))
@@ -168,10 +169,12 @@ struct GitInputScheme : InputScheme
168169

169170
bool shallow = maybeGetBoolAttr(input.attrs, "shallow").value_or(false);
170171
bool submodules = maybeGetBoolAttr(input.attrs, "submodules").value_or(false);
172+
bool allRefs = maybeGetBoolAttr(input.attrs, "allRefs").value_or(false);
171173

172174
std::string cacheType = "git";
173175
if (shallow) cacheType += "-shallow";
174176
if (submodules) cacheType += "-submodules";
177+
if (allRefs) cacheType += "-all-refs";
175178

176179
auto getImmutableAttrs = [&]()
177180
{
@@ -337,11 +340,15 @@ struct GitInputScheme : InputScheme
337340
}
338341
}
339342
} else {
340-
/* If the local ref is older than ‘tarball-ttl’ seconds, do a
341-
git fetch to update the local ref to the remote ref. */
342-
struct stat st;
343-
doFetch = stat(localRefFile.c_str(), &st) != 0 ||
344-
(uint64_t) st.st_mtime + settings.tarballTtl <= (uint64_t) now;
343+
if (allRefs) {
344+
doFetch = true;
345+
} else {
346+
/* If the local ref is older than ‘tarball-ttl’ seconds, do a
347+
git fetch to update the local ref to the remote ref. */
348+
struct stat st;
349+
doFetch = stat(localRefFile.c_str(), &st) != 0 ||
350+
(uint64_t) st.st_mtime + settings.tarballTtl <= (uint64_t) now;
351+
}
345352
}
346353

347354
if (doFetch) {
@@ -351,9 +358,11 @@ struct GitInputScheme : InputScheme
351358
// we're using --quiet for now. Should process its stderr.
352359
try {
353360
auto ref = input.getRef();
354-
auto fetchRef = ref->compare(0, 5, "refs/") == 0
355-
? *ref
356-
: "refs/heads/" + *ref;
361+
auto fetchRef = allRefs
362+
? "refs/*"
363+
: ref->compare(0, 5, "refs/") == 0
364+
? *ref
365+
: "refs/heads/" + *ref;
357366
runProgram("git", true, { "-C", repoDir, "fetch", "--quiet", "--force", "--", actualUrl, fmt("%s:%s", fetchRef, fetchRef) });
358367
} catch (Error & e) {
359368
if (!pathExists(localRefFile)) throw;

0 commit comments

Comments
 (0)