From 9504445cab095fe3869c5a68342fb2cf23ac0f28 Mon Sep 17 00:00:00 2001 From: Martin Schwaighofer Date: Sat, 1 Jan 2022 21:26:41 +0100 Subject: [PATCH] git fetcher: distinguish errors more precisely --- src/libfetchers/git.cc | 26 +++++++++++++++++--------- tests/fetchGit.sh | 8 ++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index d241eb67a..ad877eacc 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -222,17 +222,25 @@ struct GitInputScheme : InputScheme /* Check whether HEAD points to something that looks like a commit, since that is the refrence we want to use later on. */ - bool hasHead = false; - try { - runProgram("git", true, { "-C", actualUrl, "rev-parse", "--verify", "--no-revs", "HEAD^{commit}" }); - hasHead = true; - } catch (ExecError & e) { - // git exits with status 128 here if it does not detect a repository. - if (!WIFEXITED(e.status) || WEXITSTATUS(e.status) != 128) { - throw Error("Git tree '%s' is broken.\n'git rev-parse --verify HEAD' failed with exit code %d.", actualUrl, WEXITSTATUS(e.status)); - } + auto result = runProgram(RunOptions { + .program = "git", + .args = { "-C", actualUrl, "--git-dir=.git", "rev-parse", "--verify", "--no-revs", "HEAD^{commit}" }, + .mergeStderrToStdout = true + }); + auto exitCode = WEXITSTATUS(result.first); + auto errorMessage = result.second; + + if (errorMessage.find("fatal: not a git repository") != std::string::npos) { + throw Error("'%s' is not a git repository.", actualUrl); + } else if (errorMessage.find("fatal: Needed a single revision") != std::string::npos) { + // indicates that the repo does not have any commits + // we want to proceed and will consider it dirty later + } else if (exitCode != 0) { + // any other errors should lead to a failure + throw Error("Getting the HEAD of the git tree '%s' failed with exit code %d:\n%s", actualUrl, exitCode, errorMessage); } + bool hasHead = exitCode == 0; try { if (hasHead) { // Using git diff is preferrable over lower-level operations here, diff --git a/tests/fetchGit.sh b/tests/fetchGit.sh index 628d96924..ac23be5c0 100644 --- a/tests/fetchGit.sh +++ b/tests/fetchGit.sh @@ -206,3 +206,11 @@ rev4_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$ # The name argument should be handled path9=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; name = \"foo\"; }).outPath") [[ $path9 =~ -foo$ ]] + +# should fail if there is no repo +rm -rf $repo/.git +(! nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath") + +# should succeed for a repo without commits +git init $repo +path10=$(nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath")