Factor out TreeInfo

This commit is contained in:
Eelco Dolstra 2020-02-01 16:41:54 +01:00
parent 5d70b454be
commit 8451298b35
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
13 changed files with 100 additions and 68 deletions

View file

@ -478,7 +478,7 @@ LockedFlake lockFlake(
lockFlags.useRegistries, flakeCache); lockFlags.useRegistries, flakeCache);
newLocks.inputs.insert_or_assign(id, newLocks.inputs.insert_or_assign(id,
LockedInput(inputFlake.resolvedRef, inputFlake.originalRef, inputFlake.sourceInfo->narHash)); LockedInput(inputFlake.resolvedRef, inputFlake.originalRef, inputFlake.sourceInfo->info.narHash));
/* Recursively process the inputs of this /* Recursively process the inputs of this
flake. Also, unless we already have this flake. Also, unless we already have this
@ -497,7 +497,7 @@ LockedFlake lockFlake(
auto [sourceInfo, resolvedRef] = getNonFlake(state, input.ref, auto [sourceInfo, resolvedRef] = getNonFlake(state, input.ref,
lockFlags.useRegistries, flakeCache); lockFlags.useRegistries, flakeCache);
newLocks.inputs.insert_or_assign(id, newLocks.inputs.insert_or_assign(id,
LockedInput(resolvedRef, input.ref, sourceInfo.narHash)); LockedInput(resolvedRef, input.ref, sourceInfo.info.narHash));
} }
} }
} }
@ -573,19 +573,19 @@ static void emitSourceInfoAttrs(EvalState & state, const fetchers::Tree & source
auto pathS = state.store->printStorePath(sourceInfo.storePath); auto pathS = state.store->printStorePath(sourceInfo.storePath);
mkString(*state.allocAttr(vAttrs, state.sOutPath), pathS, {pathS}); mkString(*state.allocAttr(vAttrs, state.sOutPath), pathS, {pathS});
if (sourceInfo.rev) { if (sourceInfo.info.rev) {
mkString(*state.allocAttr(vAttrs, state.symbols.create("rev")), mkString(*state.allocAttr(vAttrs, state.symbols.create("rev")),
sourceInfo.rev->gitRev()); sourceInfo.info.rev->gitRev());
mkString(*state.allocAttr(vAttrs, state.symbols.create("shortRev")), mkString(*state.allocAttr(vAttrs, state.symbols.create("shortRev")),
sourceInfo.rev->gitShortRev()); sourceInfo.info.rev->gitShortRev());
} }
if (sourceInfo.revCount) if (sourceInfo.info.revCount)
mkInt(*state.allocAttr(vAttrs, state.symbols.create("revCount")), *sourceInfo.revCount); mkInt(*state.allocAttr(vAttrs, state.symbols.create("revCount")), *sourceInfo.info.revCount);
if (sourceInfo.lastModified) if (sourceInfo.info.lastModified)
mkString(*state.allocAttr(vAttrs, state.symbols.create("lastModified")), mkString(*state.allocAttr(vAttrs, state.symbols.create("lastModified")),
fmt("%s", std::put_time(std::gmtime(&*sourceInfo.lastModified), "%Y%m%d%H%M%S"))); fmt("%s", std::put_time(std::gmtime(&*sourceInfo.info.lastModified), "%Y%m%d%H%M%S")));
} }
struct LazyInput struct LazyInput
@ -604,7 +604,7 @@ static void prim_callFlake(EvalState & state, const Pos & pos, Value * * args, V
if (lazyInput->isFlake) { if (lazyInput->isFlake) {
auto flake = getFlake(state, lazyInput->lockedInput.ref, false); auto flake = getFlake(state, lazyInput->lockedInput.ref, false);
if (flake.sourceInfo->narHash != lazyInput->lockedInput.narHash) if (flake.sourceInfo->info.narHash != lazyInput->lockedInput.narHash)
throw Error("the content hash of flake '%s' doesn't match the hash recorded in the referring lockfile", throw Error("the content hash of flake '%s' doesn't match the hash recorded in the referring lockfile",
lazyInput->lockedInput.ref); lazyInput->lockedInput.ref);
@ -615,7 +615,7 @@ static void prim_callFlake(EvalState & state, const Pos & pos, Value * * args, V
FlakeCache flakeCache; FlakeCache flakeCache;
auto [sourceInfo, resolvedRef] = getNonFlake(state, lazyInput->lockedInput.ref, false, flakeCache); auto [sourceInfo, resolvedRef] = getNonFlake(state, lazyInput->lockedInput.ref, false, flakeCache);
if (sourceInfo.narHash != lazyInput->lockedInput.narHash) if (sourceInfo.info.narHash != lazyInput->lockedInput.narHash)
throw Error("the content hash of repository '%s' doesn't match the hash recorded in the referring lockfile", throw Error("the content hash of repository '%s' doesn't match the hash recorded in the referring lockfile",
lazyInput->lockedInput.ref); lazyInput->lockedInput.ref);
@ -718,8 +718,8 @@ Fingerprint LockedFlake::getFingerprint() const
return hashString(htSHA256, return hashString(htSHA256,
fmt("%s;%d;%d;%s", fmt("%s;%d;%d;%s",
flake.sourceInfo->storePath.to_string(), flake.sourceInfo->storePath.to_string(),
flake.sourceInfo->revCount.value_or(0), flake.sourceInfo->info.revCount.value_or(0),
flake.sourceInfo->lastModified.value_or(0), flake.sourceInfo->info.lastModified.value_or(0),
lockFile)); lockFile));
} }

View file

@ -64,11 +64,11 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath})); mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
// Backward compatibility: set 'rev' to // Backward compatibility: set 'rev' to
// 0000000000000000000000000000000000000000 for a dirty tree. // 0000000000000000000000000000000000000000 for a dirty tree.
auto rev2 = tree.rev.value_or(Hash(htSHA1)); auto rev2 = tree.info.rev.value_or(Hash(htSHA1));
mkString(*state.allocAttr(v, state.symbols.create("rev")), rev2.gitRev()); mkString(*state.allocAttr(v, state.symbols.create("rev")), rev2.gitRev());
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), rev2.gitShortRev()); mkString(*state.allocAttr(v, state.symbols.create("shortRev")), rev2.gitShortRev());
assert(tree.revCount); assert(tree.info.revCount);
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.revCount); mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.info.revCount);
v.attrs->sort(); v.attrs->sort();
if (state.allowedPaths) if (state.allowedPaths)

View file

@ -73,11 +73,11 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
mkString(*state.allocAttr(v, state.symbols.create("branch")), *input2->getRef()); mkString(*state.allocAttr(v, state.symbols.create("branch")), *input2->getRef());
// Backward compatibility: set 'rev' to // Backward compatibility: set 'rev' to
// 0000000000000000000000000000000000000000 for a dirty tree. // 0000000000000000000000000000000000000000 for a dirty tree.
auto rev2 = tree.rev.value_or(Hash(htSHA1)); auto rev2 = tree.info.rev.value_or(Hash(htSHA1));
mkString(*state.allocAttr(v, state.symbols.create("rev")), rev2.gitRev()); mkString(*state.allocAttr(v, state.symbols.create("rev")), rev2.gitRev());
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), std::string(rev2.gitRev(), 0, 12)); mkString(*state.allocAttr(v, state.symbols.create("shortRev")), std::string(rev2.gitRev(), 0, 12));
if (tree.revCount) if (tree.info.revCount)
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.revCount); mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.info.revCount);
v.attrs->sort(); v.attrs->sort();
if (state.allowedPaths) if (state.allowedPaths)

View file

@ -83,11 +83,11 @@ std::pair<Tree, std::shared_ptr<const Input>> Input::fetchTree(ref<Store> store)
if (tree.actualPath == "") if (tree.actualPath == "")
tree.actualPath = store->toRealPath(store->printStorePath(tree.storePath)); tree.actualPath = store->toRealPath(store->printStorePath(tree.storePath));
if (!tree.narHash) if (!tree.info.narHash)
tree.narHash = store->queryPathInfo(tree.storePath)->narHash; tree.info.narHash = store->queryPathInfo(tree.storePath)->narHash;
if (input->narHash) if (input->narHash)
assert(input->narHash == tree.narHash); assert(input->narHash == tree.info.narHash);
if (narHash && narHash != input->narHash) if (narHash && narHash != input->narHash)
throw Error("NAR hash mismatch in input '%s', expected '%s', got '%s'", throw Error("NAR hash mismatch in input '%s', expected '%s', got '%s'",

View file

@ -3,6 +3,7 @@
#include "types.hh" #include "types.hh"
#include "hash.hh" #include "hash.hh"
#include "path.hh" #include "path.hh"
#include "tree-info.hh"
#include <memory> #include <memory>
#include <variant> #include <variant>
@ -19,10 +20,7 @@ struct Tree
{ {
Path actualPath; Path actualPath;
StorePath storePath; StorePath storePath;
Hash narHash; TreeInfo info;
std::optional<Hash> rev;
std::optional<uint64_t> revCount;
std::optional<time_t> lastModified;
}; };
struct Input : std::enable_shared_from_this<Input> struct Input : std::enable_shared_from_this<Input>

View file

@ -28,11 +28,11 @@ static void cacheGitInfo(Store & store, const std::string & name, const Tree & t
nlohmann::json json; nlohmann::json json;
json["storePath"] = store.printStorePath(tree.storePath); json["storePath"] = store.printStorePath(tree.storePath);
json["name"] = name; json["name"] = name;
json["rev"] = tree.rev->gitRev(); json["rev"] = tree.info.rev->gitRev();
json["revCount"] = *tree.revCount; json["revCount"] = *tree.info.revCount;
json["lastModified"] = *tree.lastModified; json["lastModified"] = *tree.info.lastModified;
auto cacheInfoPath = getCacheInfoPathFor(name, *tree.rev); auto cacheInfoPath = getCacheInfoPathFor(name, *tree.info.rev);
createDirs(dirOf(cacheInfoPath)); createDirs(dirOf(cacheInfoPath));
writeFile(cacheInfoPath, json.dump()); writeFile(cacheInfoPath, json.dump());
} }
@ -53,9 +53,11 @@ static std::optional<Tree> lookupGitInfo(
Tree tree{ Tree tree{
.actualPath = store->toRealPath(store->printStorePath(storePath)), .actualPath = store->toRealPath(store->printStorePath(storePath)),
.storePath = std::move(storePath), .storePath = std::move(storePath),
.rev = rev, .info = TreeInfo {
.revCount = json["revCount"], .rev = rev,
.lastModified = json["lastModified"], .revCount = json["revCount"],
.lastModified = json["lastModified"],
}
}; };
return tree; return tree;
} }
@ -237,10 +239,12 @@ struct GitInput : Input
auto tree = Tree { auto tree = Tree {
.actualPath = store->printStorePath(storePath), .actualPath = store->printStorePath(storePath),
.storePath = std::move(storePath), .storePath = std::move(storePath),
.revCount = haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "rev-list", "--count", "HEAD" })) : 0, .info = TreeInfo {
// FIXME: maybe we should use the timestamp of the last .revCount = haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "rev-list", "--count", "HEAD" })) : 0,
// modified dirty file? // FIXME: maybe we should use the timestamp of the last
.lastModified = haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "log", "-1", "--format=%ct", "HEAD" })) : 0, // modified dirty file?
.lastModified = haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "log", "-1", "--format=%ct", "HEAD" })) : 0,
}
}; };
return {std::move(tree), input}; return {std::move(tree), input};
@ -349,9 +353,11 @@ struct GitInput : Input
auto tree = Tree { auto tree = Tree {
.actualPath = store->toRealPath(store->printStorePath(storePath)), .actualPath = store->toRealPath(store->printStorePath(storePath)),
.storePath = std::move(storePath), .storePath = std::move(storePath),
.rev = input->rev, .info = TreeInfo {
.revCount = revCount, .rev = input->rev,
.lastModified = lastModified, .revCount = revCount,
.lastModified = lastModified
}
}; };
cacheGitInfo(*store, name, tree); cacheGitInfo(*store, name, tree);

View file

@ -113,8 +113,10 @@ struct GitHubInput : Input
Tree result{ Tree result{
.actualPath = dresult.path, .actualPath = dresult.path,
.storePath = store->parseStorePath(dresult.storePath), .storePath = store->parseStorePath(dresult.storePath),
.rev = *rev, .info = TreeInfo {
.lastModified = *dresult.lastModified .rev = *rev,
.lastModified = *dresult.lastModified,
},
}; };
#if 0 #if 0

View file

@ -215,12 +215,17 @@ struct MercurialInput : Input
if (store->isValidPath(storePath)) { if (store->isValidPath(storePath)) {
printTalkative("using cached Mercurial store path '%s'", store->printStorePath(storePath)); printTalkative("using cached Mercurial store path '%s'", store->printStorePath(storePath));
return {Tree { return {
.actualPath = store->printStorePath(storePath), Tree {
.storePath = std::move(storePath), .actualPath = store->printStorePath(storePath),
.rev = input->rev, .storePath = std::move(storePath),
.revCount = revCount, .info = TreeInfo {
}, input}; .rev = input->rev,
.revCount = revCount,
},
},
input
};
} }
} catch (SysError & e) { } catch (SysError & e) {
@ -246,12 +251,17 @@ struct MercurialInput : Input
writeFile(storeLink, json.dump()); writeFile(storeLink, json.dump());
return {Tree { return {
.actualPath = store->printStorePath(storePath), Tree {
.storePath = std::move(storePath), .actualPath = store->printStorePath(storePath),
.rev = input->rev, .storePath = std::move(storePath),
.revCount = revCount, .info = TreeInfo {
}, input}; .rev = input->rev,
.revCount = revCount
}
},
input
};
} }
}; };

View file

@ -72,7 +72,9 @@ struct TarballInput : Input
Tree { Tree {
.actualPath = res.path, .actualPath = res.path,
.storePath = std::move(storePath), .storePath = std::move(storePath),
.lastModified = *res.lastModified .info = TreeInfo {
.lastModified = *res.lastModified,
},
}, },
input input
}; };

View file

@ -0,0 +1,13 @@
#pragma once
namespace nix {
struct TreeInfo
{
Hash narHash;
std::optional<Hash> rev;
std::optional<uint64_t> revCount;
std::optional<time_t> lastModified;
};
}

View file

@ -21,7 +21,7 @@ Logger * logger = makeDefaultLogger();
void Logger::warn(const std::string & msg) void Logger::warn(const std::string & msg)
{ {
log(lvlWarn, ANSI_RED "warning:" ANSI_NORMAL " " + msg); log(lvlWarn, ANSI_YELLOW "warning:" ANSI_NORMAL " " + msg);
} }
class SimpleLogger : public Logger class SimpleLogger : public Logger

View file

@ -455,6 +455,7 @@ void ignoreException();
#define ANSI_FAINT "\e[2m" #define ANSI_FAINT "\e[2m"
#define ANSI_RED "\e[31;1m" #define ANSI_RED "\e[31;1m"
#define ANSI_GREEN "\e[32;1m" #define ANSI_GREEN "\e[32;1m"
#define ANSI_YELLOW "\e[33;1m"
#define ANSI_BLUE "\e[34;1m" #define ANSI_BLUE "\e[34;1m"

View file

@ -84,13 +84,13 @@ static void printFlakeInfo(const Store & store, const Flake & flake)
if (flake.description) if (flake.description)
std::cout << fmt("Description: %s\n", *flake.description); std::cout << fmt("Description: %s\n", *flake.description);
std::cout << fmt("Path: %s\n", store.printStorePath(flake.sourceInfo->storePath)); std::cout << fmt("Path: %s\n", store.printStorePath(flake.sourceInfo->storePath));
if (flake.sourceInfo->rev) if (flake.sourceInfo->info.rev)
std::cout << fmt("Revision: %s\n", flake.sourceInfo->rev->to_string(Base16, false)); std::cout << fmt("Revision: %s\n", flake.sourceInfo->info.rev->to_string(Base16, false));
if (flake.sourceInfo->revCount) if (flake.sourceInfo->info.revCount)
std::cout << fmt("Revisions: %s\n", *flake.sourceInfo->revCount); std::cout << fmt("Revisions: %s\n", *flake.sourceInfo->info.revCount);
if (flake.sourceInfo->lastModified) if (flake.sourceInfo->info.lastModified)
std::cout << fmt("Last modified: %s\n", std::cout << fmt("Last modified: %s\n",
std::put_time(std::localtime(&*flake.sourceInfo->lastModified), "%F %T")); std::put_time(std::localtime(&*flake.sourceInfo->info.lastModified), "%F %T"));
} }
static nlohmann::json flakeToJson(const Store & store, const Flake & flake) static nlohmann::json flakeToJson(const Store & store, const Flake & flake)
@ -100,12 +100,12 @@ static nlohmann::json flakeToJson(const Store & store, const Flake & flake)
j["description"] = *flake.description; j["description"] = *flake.description;
j["edition"] = flake.edition; j["edition"] = flake.edition;
j["url"] = flake.resolvedRef.input->to_string(); j["url"] = flake.resolvedRef.input->to_string();
if (flake.sourceInfo->rev) if (flake.sourceInfo->info.rev)
j["revision"] = flake.sourceInfo->rev->to_string(Base16, false); j["revision"] = flake.sourceInfo->info.rev->to_string(Base16, false);
if (flake.sourceInfo->revCount) if (flake.sourceInfo->info.revCount)
j["revCount"] = *flake.sourceInfo->revCount; j["revCount"] = *flake.sourceInfo->info.revCount;
if (flake.sourceInfo->lastModified) if (flake.sourceInfo->info.lastModified)
j["lastModified"] = *flake.sourceInfo->lastModified; j["lastModified"] = *flake.sourceInfo->info.lastModified;
j["path"] = store.printStorePath(flake.sourceInfo->storePath); j["path"] = store.printStorePath(flake.sourceInfo->storePath);
return j; return j;
} }