libfetchers/git: fix for nixos-rebuild

The `--git-dir=` must be `.` in some cases (for cached repos that are
"bare" repos in `~/.cache/nix/gitv3`). With this fix we can add
`--git-dir` to each `git`-invokation needed for `nixos-rebuild`.
This commit is contained in:
Maximilian Bosch 2022-04-24 18:06:36 +02:00
parent 0256e5578e
commit d1f5356311
No known key found for this signature in database
GPG key ID: 091DBF4D1FC46B8E

View file

@ -21,6 +21,15 @@ namespace nix::fetchers {
// old version of git, which will ignore unrecognized `-c` options. // old version of git, which will ignore unrecognized `-c` options.
const std::string gitInitialBranch = "__nix_dummy_branch"; const std::string gitInitialBranch = "__nix_dummy_branch";
static std::string getGitDir()
{
auto gitDir = getEnv("GIT_DIR");
if (!gitDir) {
return ".git";
}
return *gitDir;
}
static std::string readHead(const Path & path) static std::string readHead(const Path & path)
{ {
return chomp(runProgram("git", true, { "-C", path, "--git-dir", ".git", "rev-parse", "--abbrev-ref", "HEAD" })); return chomp(runProgram("git", true, { "-C", path, "--git-dir", ".git", "rev-parse", "--abbrev-ref", "HEAD" }));
@ -150,13 +159,14 @@ struct GitInputScheme : InputScheme
{ {
auto sourcePath = getSourcePath(input); auto sourcePath = getSourcePath(input);
assert(sourcePath); assert(sourcePath);
auto gitDir = getGitDir();
runProgram("git", true, runProgram("git", true,
{ "-C", *sourcePath, "--git-dir", ".git", "add", "--force", "--intent-to-add", "--", std::string(file) }); { "-C", *sourcePath, "--git-dir", gitDir, "add", "--force", "--intent-to-add", "--", std::string(file) });
if (commitMsg) if (commitMsg)
runProgram("git", true, runProgram("git", true,
{ "-C", *sourcePath, "--git-dir", ".git", "commit", std::string(file), "-m", *commitMsg }); { "-C", *sourcePath, "--git-dir", gitDir, "commit", std::string(file), "-m", *commitMsg });
} }
std::pair<bool, std::string> getActualUrl(const Input & input) const std::pair<bool, std::string> getActualUrl(const Input & input) const
@ -175,6 +185,7 @@ struct GitInputScheme : InputScheme
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
{ {
Input input(_input); Input input(_input);
auto gitDir = getGitDir();
std::string name = input.getName(); std::string name = input.getName();
@ -237,7 +248,7 @@ struct GitInputScheme : InputScheme
since that is the refrence we want to use later on. */ since that is the refrence we want to use later on. */
auto result = runProgram(RunOptions { auto result = runProgram(RunOptions {
.program = "git", .program = "git",
.args = { "-C", actualUrl, "--git-dir=.git", "rev-parse", "--verify", "--no-revs", "HEAD^{commit}" }, .args = { "-C", actualUrl, "--git-dir", gitDir, "rev-parse", "--verify", "--no-revs", "HEAD^{commit}" },
.environment = env, .environment = env,
.mergeStderrToStdout = true .mergeStderrToStdout = true
}); });
@ -259,7 +270,7 @@ struct GitInputScheme : InputScheme
if (hasHead) { if (hasHead) {
// Using git diff is preferrable over lower-level operations here, // Using git diff is preferrable over lower-level operations here,
// because its conceptually simpler and we only need the exit code anyways. // because its conceptually simpler and we only need the exit code anyways.
auto gitDiffOpts = Strings({ "-C", actualUrl, "--git-dir", ".git", "diff", "HEAD", "--quiet"}); auto gitDiffOpts = Strings({ "-C", actualUrl, "--git-dir", gitDir, "diff", "HEAD", "--quiet"});
if (!submodules) { if (!submodules) {
// Changes in submodules should only make the tree dirty // Changes in submodules should only make the tree dirty
// when those submodules will be copied as well. // when those submodules will be copied as well.
@ -284,7 +295,7 @@ struct GitInputScheme : InputScheme
if (fetchSettings.warnDirty) if (fetchSettings.warnDirty)
warn("Git tree '%s' is dirty", actualUrl); warn("Git tree '%s' is dirty", actualUrl);
auto gitOpts = Strings({ "-C", actualUrl, "--git-dir", ".git", "ls-files", "-z" }); auto gitOpts = Strings({ "-C", actualUrl, "--git-dir", gitDir, "ls-files", "-z" });
if (submodules) if (submodules)
gitOpts.emplace_back("--recurse-submodules"); gitOpts.emplace_back("--recurse-submodules");
@ -314,7 +325,7 @@ struct GitInputScheme : InputScheme
// modified dirty file? // modified dirty file?
input.attrs.insert_or_assign( input.attrs.insert_or_assign(
"lastModified", "lastModified",
hasHead ? std::stoull(runProgram("git", true, { "-C", actualPath, "--git-dir", ".git", "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0); hasHead ? std::stoull(runProgram("git", true, { "-C", actualPath, "--git-dir", gitDir, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
return {std::move(storePath), input}; return {std::move(storePath), input};
} }
@ -335,7 +346,7 @@ struct GitInputScheme : InputScheme
if (!input.getRev()) if (!input.getRev())
input.attrs.insert_or_assign("rev", input.attrs.insert_or_assign("rev",
Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "--git-dir", ".git", "rev-parse", *input.getRef() })), htSHA1).gitRev()); Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "--git-dir", gitDir, "rev-parse", *input.getRef() })), htSHA1).gitRev());
repoDir = actualUrl; repoDir = actualUrl;
@ -351,6 +362,7 @@ struct GitInputScheme : InputScheme
Path cacheDir = getCacheDir() + "/nix/gitv3/" + hashString(htSHA256, actualUrl).to_string(Base32, false); Path cacheDir = getCacheDir() + "/nix/gitv3/" + hashString(htSHA256, actualUrl).to_string(Base32, false);
repoDir = cacheDir; repoDir = cacheDir;
gitDir = ".";
createDirs(dirOf(cacheDir)); createDirs(dirOf(cacheDir));
PathLocks cacheDirLock({cacheDir + ".lock"}); PathLocks cacheDirLock({cacheDir + ".lock"});
@ -427,7 +439,7 @@ struct GitInputScheme : InputScheme
// cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder // cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder
} }
bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "rev-parse", "--is-shallow-repository" })) == "true"; bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "rev-parse", "--is-shallow-repository" })) == "true";
if (isShallow && !shallow) if (isShallow && !shallow)
throw Error("'%s' is a shallow Git repository, but a non-shallow repository is needed", actualUrl); throw Error("'%s' is a shallow Git repository, but a non-shallow repository is needed", actualUrl);