Skip to content

Commit

Permalink
GitInputScheme::lazyFetch(): Return rev/revCount/ref/lastModified
Browse files Browse the repository at this point in the history
  • Loading branch information
edolstra committed May 20, 2022
1 parent ad4b766 commit e6cf987
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 31 deletions.
83 changes: 61 additions & 22 deletions src/libfetchers/git.cc
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ struct GitInputScheme : InputScheme
warn("Git tree '%s' is dirty", url);
}
}

std::string gitDir = getGitDir();
};

RepoInfo getRepoInfo(const Input & input)
Expand Down Expand Up @@ -411,6 +413,34 @@ struct GitInputScheme : InputScheme
return res;
}

void updateRev(Input & input, const RepoInfo & repoInfo, const std::string & ref)
{
if (!input.getRev())
input.attrs.insert_or_assign("rev",
Hash::parseAny(chomp(runProgram("git", true, { "-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "rev-parse", ref })), htSHA1).gitRev());
}

uint64_t getLastModified(const RepoInfo & repoInfo, const std::string & repoDir, const std::string & ref)
{
return
repoInfo.hasHead
? std::stoull(
runProgram("git", true,
{ "-C", repoDir, "--git-dir", repoInfo.gitDir, "log", "-1", "--format=%ct", "--no-show-signature", ref }))
: 0;
}

uint64_t getRevCount(const RepoInfo & repoInfo, const std::string & repoDir, const Hash & rev)
{
// FIXME: cache this.
return
repoInfo.hasHead
? std::stoull(
runProgram("git", true,
{ "-C", repoDir, "--git-dir", repoInfo.gitDir, "rev-list", "--count", rev.gitRev() }))
: 0;
}

std::string getDefaultRef(const RepoInfo & repoInfo)
{
auto head = repoInfo.isLocal
Expand All @@ -426,7 +456,6 @@ struct GitInputScheme : InputScheme
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
{
Input input(_input);
auto gitDir = getGitDir(); // FIXME: move into RepoInfo

auto repoInfo = getRepoInfo(input);

Expand Down Expand Up @@ -474,13 +503,8 @@ struct GitInputScheme : InputScheme
Path repoDir;

if (repoInfo.isLocal) {

if (!input.getRev())
input.attrs.insert_or_assign("rev",
Hash::parseAny(chomp(runProgram("git", true, { "-C", repoInfo.url, "--git-dir", getGitDir(), "rev-parse", ref })), htSHA1).gitRev());

updateRev(input, repoInfo, ref);
repoDir = repoInfo.url;

} else {
if (auto res = getCache()->lookup(store, unlockedAttrs)) {
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1);
Expand All @@ -492,7 +516,7 @@ struct GitInputScheme : InputScheme

Path cacheDir = getCachePath(repoInfo.url);
repoDir = cacheDir;
gitDir = ".";
repoInfo.gitDir = ".";

createDirs(dirOf(cacheDir));
PathLocks cacheDirLock({cacheDir + ".lock"});
Expand All @@ -513,7 +537,7 @@ struct GitInputScheme : InputScheme
repo. */
if (input.getRev()) {
try {
runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "cat-file", "-e", input.getRev()->gitRev() });
runProgram("git", true, { "-C", repoDir, "--git-dir", repoInfo.gitDir, "cat-file", "-e", input.getRev()->gitRev() });
doFetch = false;
} catch (ExecError & e) {
if (WIFEXITED(e.status)) {
Expand Down Expand Up @@ -549,7 +573,7 @@ struct GitInputScheme : InputScheme
: "refs/heads/" + ref;
runProgram("git", true,
{ "-C", repoDir,
"--git-dir", gitDir,
"--git-dir", repoInfo.gitDir,
"fetch",
"--quiet",
"--force",
Expand All @@ -574,7 +598,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
}

bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "rev-parse", "--is-shallow-repository" })) == "true";
bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "--git-dir", repoInfo.gitDir, "rev-parse", "--is-shallow-repository" })) == "true";

if (isShallow && !repoInfo.shallow)
throw Error("'%s' is a shallow Git repository, but a non-shallow repository is needed", repoInfo.url);
Expand All @@ -594,7 +618,7 @@ struct GitInputScheme : InputScheme

auto result = runProgram(RunOptions {
.program = "git",
.args = { "-C", repoDir, "--git-dir", gitDir, "cat-file", "commit", input.getRev()->gitRev() },
.args = { "-C", repoDir, "--git-dir", repoInfo.gitDir, "cat-file", "commit", input.getRev()->gitRev() },
.mergeStderrToStdout = true
});
if (WEXITSTATUS(result.first) == 128
Expand Down Expand Up @@ -633,7 +657,7 @@ struct GitInputScheme : InputScheme
auto source = sinkToSource([&](Sink & sink) {
runProgram2({
.program = "git",
.args = { "-C", repoDir, "--git-dir", gitDir, "archive", input.getRev()->gitRev() },
.args = { "-C", repoDir, "--git-dir", repoInfo.gitDir, "archive", input.getRev()->gitRev() },
.standardOut = &sink
});
});
Expand All @@ -643,16 +667,16 @@ struct GitInputScheme : InputScheme

auto storePath = store->addToStore(name, tmpDir, FileIngestionMethod::Recursive, htSHA256, filter);

auto lastModified = std::stoull(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "log", "-1", "--format=%ct", "--no-show-signature", input.getRev()->gitRev() }));
auto rev = *input.getRev();

Attrs infoAttrs({
{"rev", input.getRev()->gitRev()},
{"lastModified", lastModified},
{"rev", rev.gitRev()},
{"lastModified", getLastModified(repoInfo, repoDir, rev.gitRev())},
});

if (!repoInfo.shallow)
infoAttrs.insert_or_assign("revCount",
std::stoull(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "rev-list", "--count", input.getRev()->gitRev() })));
getRevCount(repoInfo, repoDir, rev));

if (!_input.getRev())
getCache()->add(
Expand Down Expand Up @@ -695,15 +719,15 @@ struct GitInputScheme : InputScheme
// modified dirty file?
input.attrs.insert_or_assign(
"lastModified",
repoInfo.hasHead
? std::stoull(runProgram("git", true, { "-C", repoInfo.url, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" }))
: 0);
getLastModified(repoInfo, repoInfo.url, "HEAD"));

return {std::move(storePath), input};
}

std::pair<ref<InputAccessor>, Input> lazyFetch(ref<Store> store, const Input & input) override
std::pair<ref<InputAccessor>, Input> lazyFetch(ref<Store> store, const Input & _input) override
{
Input input(_input);

auto repoInfo = getRepoInfo(input);

/* Unless we're using the working tree, copy the tree into the
Expand All @@ -714,7 +738,22 @@ struct GitInputScheme : InputScheme

repoInfo.checkDirty();

// FIXME: return updated input.
auto ref = getDefaultRef(repoInfo);
input.attrs.insert_or_assign("ref", ref);

if (!repoInfo.isDirty) {
updateRev(input, repoInfo, ref);

input.attrs.insert_or_assign(
"revCount",
getRevCount(repoInfo, repoInfo.url, *input.getRev()));
}

// FIXME: maybe we should use the timestamp of the last
// modified dirty file?
input.attrs.insert_or_assign(
"lastModified",
getLastModified(repoInfo, repoInfo.url, ref));

auto makeNotAllowedError = [url{repoInfo.url}](const CanonPath & path) -> RestrictedPathError
{
Expand Down
8 changes: 0 additions & 8 deletions src/nix/flake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,6 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
j["revCount"] = *revCount;
if (auto lastModified = flake.lockedRef.input.getLastModified())
j["lastModified"] = *lastModified;
#if 0
j["path"] = store->printStorePath(flake.sourceInfo->storePath);
#endif
j["locks"] = lockedFlake.lockFile.toJSON();
logger->cout("%s", j.dump());
} else {
Expand All @@ -198,11 +195,6 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
logger->cout(
ANSI_BOLD "Description:" ANSI_NORMAL " %s",
*flake.description);
#if 0
logger->cout(
ANSI_BOLD "Path:" ANSI_NORMAL " %s",
store->printStorePath(flake.sourceInfo->storePath));
#endif
if (auto rev = flake.lockedRef.input.getRev())
logger->cout(
ANSI_BOLD "Revision:" ANSI_NORMAL " %s",
Expand Down
2 changes: 1 addition & 1 deletion tests/flakes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ nix flake metadata $flake1Dir | grep -q 'URL:.*flake1.*'
# Test 'nix flake metadata --json'.
json=$(nix flake metadata flake1 --json | jq .)
[[ $(echo "$json" | jq -r .description) = 'Bla bla' ]]
[[ -d $(echo "$json" | jq -r .path) ]]
#[[ -d $(echo "$json" | jq -r .path) ]]
[[ $(echo "$json" | jq -r .lastModified) = $(git -C $flake1Dir log -n1 --format=%ct) ]]
hash1=$(echo "$json" | jq -r .revision)

Expand Down

0 comments on commit e6cf987

Please sign in to comment.