Skip to content

Commit

Permalink
fixup! builtins.fetchGit: improve error message when git is not avail…
Browse files Browse the repository at this point in the history
…able
  • Loading branch information
LnL7 committed Jul 3, 2019
1 parent 4de5d0d commit 419e211
Showing 1 changed file with 33 additions and 28 deletions.
61 changes: 33 additions & 28 deletions src/libexpr/primops/fetchGit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ struct GitInfo

std::regex revRegex("^[0-9a-fA-F]{40}$");

string runGit(const Strings & args)
{
try {
return runProgram("git", true, args);
} catch (ExecError & e) {
if (WEXITSTATUS(e.status) == 127)
throw ExecError(e.status,
"%s\n"
"The program 'git' is currently not installed. It is required for builtins.fetchGit\n"
"You can install it by running the following:\n"
"nix-env -f '<nixpkgs>' -iA git",
e.what());
throw;
}
}

GitInfo exportGit(ref<Store> store, const std::string & uri,
std::optional<std::string> ref, std::string rev,
const std::string & name)
Expand All @@ -37,7 +53,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
bool clean = true;

try {
runProgram("git", true, { "-C", uri, "diff-index", "--quiet", "HEAD", "--" });
runGit({ "-C", uri, "diff-index", "--quiet", "HEAD", "--" });
} catch (ExecError e) {
if (!WIFEXITED(e.status) || WEXITSTATUS(e.status) != 1) throw;
clean = false;
Expand All @@ -53,7 +69,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
gitInfo.shortRev = std::string(gitInfo.rev, 0, 7);

auto files = tokenizeString<std::set<std::string>>(
runProgram("git", true, { "-C", uri, "ls-files", "-z" }), "\0"s);
runGit({ "-C", uri, "ls-files", "-z" }), "\0"s);

PathFilter filter = [&](const Path & p) -> bool {
assert(hasPrefix(p, uri));
Expand All @@ -76,7 +92,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
}

// clean working tree, but no ref or rev specified. Use 'HEAD'.
rev = chomp(runProgram("git", true, { "-C", uri, "rev-parse", "HEAD" }));
rev = chomp(runGit({ "-C", uri, "rev-parse", "HEAD" }));
ref = "HEAD"s;
}

Expand All @@ -91,7 +107,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,

if (!pathExists(cacheDir)) {
createDirs(dirOf(cacheDir));
runProgram("git", true, { "init", "--bare", cacheDir });
runGit({ "init", "--bare", cacheDir });
}

Path localRefFile = cacheDir + "/refs/heads/" + *ref;
Expand All @@ -102,7 +118,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
repo. */
if (rev != "") {
try {
runProgram("git", true, { "-C", cacheDir, "cat-file", "-e", rev });
runGit({ "-C", cacheDir, "cat-file", "-e", rev });
doFetch = false;
} catch (ExecError & e) {
if (WIFEXITED(e.status)) {
Expand All @@ -124,7 +140,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,

// FIXME: git stderr messes up our progress indicator, so
// we're using --quiet for now. Should process its stderr.
runProgram("git", true, { "-C", cacheDir, "fetch", "--quiet", "--force", "--", uri, fmt("%s:%s", *ref, *ref) });
runGit({ "-C", cacheDir, "fetch", "--quiet", "--force", "--", uri, fmt("%s:%s", *ref, *ref) });

struct timeval times[2];
times[0].tv_sec = now;
Expand Down Expand Up @@ -164,7 +180,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,

// FIXME: should pipe this, or find some better way to extract a
// revision.
auto tar = runProgram("git", true, { "-C", cacheDir, "archive", gitInfo.rev });
auto tar = runGit({ "-C", cacheDir, "archive", gitInfo.rev });

Path tmpDir = createTempDir();
AutoDelete delTmpDir(tmpDir, true);
Expand All @@ -173,7 +189,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,

gitInfo.storePath = store->addToStore(name, tmpDir);

gitInfo.revCount = std::stoull(runProgram("git", true, { "-C", cacheDir, "rev-list", "--count", gitInfo.rev }));
gitInfo.revCount = std::stoull(runGit({ "-C", cacheDir, "rev-list", "--count", gitInfo.rev }));

nlohmann::json json;
json["storePath"] = gitInfo.storePath;
Expand Down Expand Up @@ -225,28 +241,17 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
// whitelist. Ah well.
state.checkURI(url);

try {
auto gitInfo = exportGit(state.store, url, ref, rev, name);
auto gitInfo = exportGit(state.store, url, ref, rev, name);

state.mkAttrs(v, 8);
mkString(*state.allocAttr(v, state.sOutPath), gitInfo.storePath, PathSet({gitInfo.storePath}));
mkString(*state.allocAttr(v, state.symbols.create("rev")), gitInfo.rev);
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), gitInfo.shortRev);
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), gitInfo.revCount);
v.attrs->sort();
state.mkAttrs(v, 8);
mkString(*state.allocAttr(v, state.sOutPath), gitInfo.storePath, PathSet({gitInfo.storePath}));
mkString(*state.allocAttr(v, state.symbols.create("rev")), gitInfo.rev);
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), gitInfo.shortRev);
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), gitInfo.revCount);
v.attrs->sort();

if (state.allowedPaths)
state.allowedPaths->insert(state.store->toRealPath(gitInfo.storePath));
} catch (ExecError & e) {
if (WEXITSTATUS(e.status) == 127)
throw ExecError(e.status,
"%s\n"
"The program 'git' is currently not installed. It is required for builtins.fetchGit\n"
"You can install it by running the following:\n"
"nix-env -f '<nixpkgs>' -iA git",
e.what());
throw;
}
if (state.allowedPaths)
state.allowedPaths->insert(state.store->toRealPath(gitInfo.storePath));
}

static RegisterPrimOp r("fetchGit", 1, prim_fetchGit);
Expand Down

0 comments on commit 419e211

Please sign in to comment.