libfetchers/git: hardcode --git-dir
To demonstrate the problem: * You need a `git` at 2.33.3 in your $PATH * An expression like this in a git repository: ``` nix { outputs = { self, nixpkgs }: { packages.foo.x86_64-linux = with nixpkgs.legacyPackages.x86_64-linux; runCommand "snens" { } '' echo ${(builtins.fetchGit ./.).lastModifiedDate} > $out ''; }; } ``` Now, when instantiating the package via `builtins.getFlake`, it fails on Nix 2.7 like this: $ nix-instantiate -E '(builtins.getFlake "'"$(pwd)"'").packages.foo.x86_64-linux' fatal: unsafe repository ('/nix/store/a7j3125km4h8l0p71q6ssfkxamfh5d61-source' is owned by someone else) To add an exception for this directory, call: git config --global --add safe.directory /nix/store/a7j3125km4h8l0p71q6ssfkxamfh5d61-source error: program 'git' failed with exit code 128 (use '--show-trace' to show detailed location information) This breaks e.g. `nixops`-deployments using flakes with similar expressions as shown above. The cause for this is that `git(1)` tries to find the highest `.git`-directory in the directory tree and if it finds a such a directory, but with another owning user (root vs. the user who evaluates the expression), it fails as above. This was changed recently to fix CVE-2022-24765[1]. By explicitly specifying `--git-dir`, Git assumes to be in the top-level directory and doesn't attempt to look for a `.git`-directory in the parent directories and thus the code-path leading to said error is never reached. [1] https://lore.kernel.org/git/xmqqv8veb5i6.fsf@gitster.g/
This commit is contained in:
parent
7f814d6d9a
commit
0256e5578e
|
@ -23,7 +23,7 @@ const std::string gitInitialBranch = "__nix_dummy_branch";
|
||||||
|
|
||||||
static std::string readHead(const Path & path)
|
static std::string readHead(const Path & path)
|
||||||
{
|
{
|
||||||
return chomp(runProgram("git", true, { "-C", path, "rev-parse", "--abbrev-ref", "HEAD" }));
|
return chomp(runProgram("git", true, { "-C", path, "--git-dir", ".git", "rev-parse", "--abbrev-ref", "HEAD" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isNotDotGitDirectory(const Path & path)
|
static bool isNotDotGitDirectory(const Path & path)
|
||||||
|
@ -152,11 +152,11 @@ struct GitInputScheme : InputScheme
|
||||||
assert(sourcePath);
|
assert(sourcePath);
|
||||||
|
|
||||||
runProgram("git", true,
|
runProgram("git", true,
|
||||||
{ "-C", *sourcePath, "add", "--force", "--intent-to-add", "--", std::string(file) });
|
{ "-C", *sourcePath, "--git-dir", ".git", "add", "--force", "--intent-to-add", "--", std::string(file) });
|
||||||
|
|
||||||
if (commitMsg)
|
if (commitMsg)
|
||||||
runProgram("git", true,
|
runProgram("git", true,
|
||||||
{ "-C", *sourcePath, "commit", std::string(file), "-m", *commitMsg });
|
{ "-C", *sourcePath, "--git-dir", ".git", "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
|
||||||
|
@ -259,7 +259,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, "diff", "HEAD", "--quiet"});
|
auto gitDiffOpts = Strings({ "-C", actualUrl, "--git-dir", ".git", "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 +284,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, "ls-files", "-z" });
|
auto gitOpts = Strings({ "-C", actualUrl, "--git-dir", ".git", "ls-files", "-z" });
|
||||||
if (submodules)
|
if (submodules)
|
||||||
gitOpts.emplace_back("--recurse-submodules");
|
gitOpts.emplace_back("--recurse-submodules");
|
||||||
|
|
||||||
|
@ -314,7 +314,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, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
|
hasHead ? std::stoull(runProgram("git", true, { "-C", actualPath, "--git-dir", ".git", "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
|
||||||
|
|
||||||
return {std::move(storePath), input};
|
return {std::move(storePath), input};
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,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, "rev-parse", *input.getRef() })), htSHA1).gitRev());
|
Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "--git-dir", ".git", "rev-parse", *input.getRef() })), htSHA1).gitRev());
|
||||||
|
|
||||||
repoDir = actualUrl;
|
repoDir = actualUrl;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue