Make the Store API more type-safe

Most functions now take a StorePath argument rather than a Path (which
is just an alias for std::string). The StorePath constructor ensures
that the path is syntactically correct (i.e. it looks like
<store-dir>/<base32-hash>-<name>). Similarly, functions like
buildPaths() now take a StorePathWithOutputs, rather than abusing Path
by adding a '!<outputs>' suffix.

Note that the StorePath type is implemented in Rust. This involves
some hackery to allow Rust values to be used directly in C++, via a
helper type whose destructor calls the Rust type's drop()
function. The main issue is the dynamic nature of C++ move semantics:
after we have moved a Rust value, we should not call the drop function
on the original value. So when we move a value, we set the original
value to bitwise zero, and the destructor only calls drop() if the
value is not bitwise zero. This should be sufficient for most types.

Also lots of minor cleanups to the C++ API to make it more modern
(e.g. using std::optional and std::string_view in some places).
This commit is contained in:
Eelco Dolstra
2019-12-10 22:06:05 +01:00
parent ebd89999c2
commit bbe97dff8b
98 changed files with 2628 additions and 2870 deletions
+5 -4
View File
@@ -40,16 +40,17 @@ struct CmdAddToStore : MixDryRun, StoreCommand
StringSink sink;
dumpPath(path, sink);
ValidPathInfo info;
info.narHash = hashString(htSHA256, *sink.s);
auto narHash = hashString(htSHA256, *sink.s);
ValidPathInfo info(store->makeFixedOutputPath(true, narHash, *namePart));
info.narHash = narHash;
info.narSize = sink.s->size();
info.path = store->makeFixedOutputPath(true, info.narHash, *namePart);
info.ca = makeFixedOutputCA(true, info.narHash);
if (!dryRun)
store->addToStore(info, sink.s);
std::cout << fmt("%s\n", info.path);
std::cout << fmt("%s\n", store->printStorePath(info.path));
}
};
+9 -8
View File
@@ -48,28 +48,29 @@ StorePathsCommand::StorePathsCommand(bool recursive)
void StorePathsCommand::run(ref<Store> store)
{
Paths storePaths;
StorePaths storePaths;
if (all) {
if (installables.size())
throw UsageError("'--all' does not expect arguments");
for (auto & p : store->queryAllValidPaths())
storePaths.push_back(p);
storePaths.push_back(p.clone());
}
else {
for (auto & p : toStorePaths(store, realiseMode, installables))
storePaths.push_back(p);
storePaths.push_back(p.clone());
if (recursive) {
PathSet closure;
store->computeFSClosure(PathSet(storePaths.begin(), storePaths.end()),
closure, false, false);
storePaths = Paths(closure.begin(), closure.end());
StorePathSet closure;
store->computeFSClosure(storePathsToSet(storePaths), closure, false, false);
storePaths.clear();
for (auto & p : closure)
storePaths.push_back(p.clone());
}
}
run(store, storePaths);
run(store, std::move(storePaths));
}
void StorePathCommand::run(ref<Store> store)
+8 -7
View File
@@ -2,6 +2,7 @@
#include "args.hh"
#include "common-eval-args.hh"
#include "path.hh"
namespace nix {
@@ -28,8 +29,8 @@ private:
struct Buildable
{
Path drvPath; // may be empty
std::map<std::string, Path> outputs;
std::optional<StorePath> drvPath;
std::map<std::string, StorePath> outputs;
};
typedef std::vector<Buildable> Buildables;
@@ -131,7 +132,7 @@ public:
using StoreCommand::run;
virtual void run(ref<Store> store, Paths storePaths) = 0;
virtual void run(ref<Store> store, std::vector<StorePath> storePaths) = 0;
void run(ref<Store> store) override;
@@ -143,7 +144,7 @@ struct StorePathCommand : public InstallablesCommand
{
using StoreCommand::run;
virtual void run(ref<Store> store, const Path & storePath) = 0;
virtual void run(ref<Store> store, const StorePath & storePath) = 0;
void run(ref<Store> store) override;
};
@@ -174,13 +175,13 @@ std::shared_ptr<Installable> parseInstallable(
Buildables build(ref<Store> store, RealiseMode mode,
std::vector<std::shared_ptr<Installable>> installables);
PathSet toStorePaths(ref<Store> store, RealiseMode mode,
std::set<StorePath> toStorePaths(ref<Store> store, RealiseMode mode,
std::vector<std::shared_ptr<Installable>> installables);
Path toStorePath(ref<Store> store, RealiseMode mode,
StorePath toStorePath(ref<Store> store, RealiseMode mode,
std::shared_ptr<Installable> installable);
PathSet toDerivations(ref<Store> store,
std::set<StorePath> toDerivations(ref<Store> store,
std::vector<std::shared_ptr<Installable>> installables,
bool useDeriver = false);
+2 -2
View File
@@ -80,14 +80,14 @@ struct CmdCopy : StorePathsCommand
return srcUri.empty() ? StoreCommand::createStore() : openStore(srcUri);
}
void run(ref<Store> srcStore, Paths storePaths) override
void run(ref<Store> srcStore, StorePaths storePaths) override
{
if (srcUri.empty() && dstUri.empty())
throw UsageError("you must pass '--from' and/or '--to'");
ref<Store> dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
copyPaths(srcStore, dstStore, PathSet(storePaths.begin(), storePaths.end()),
copyPaths(srcStore, dstStore, storePathsToSet(storePaths),
NoRepair, checkSigs, substitute);
}
};
+1 -1
View File
@@ -20,7 +20,7 @@ struct CmdDumpPath : StorePathCommand
};
}
void run(ref<Store> store, const Path & storePath) override
void run(ref<Store> store, const StorePath & storePath) override
{
FdSink sink(STDOUT_FILENO);
store->narFromPath(storePath, sink);
+40 -28
View File
@@ -89,15 +89,25 @@ Buildable Installable::toBuildable()
struct InstallableStorePath : Installable
{
Path storePath;
ref<Store> store;
StorePath storePath;
InstallableStorePath(const Path & storePath) : storePath(storePath) { }
InstallableStorePath(ref<Store> store, const Path & storePath)
: store(store), storePath(store->parseStorePath(storePath)) { }
std::string what() override { return storePath; }
std::string what() override { return store->printStorePath(storePath); }
Buildables toBuildables() override
{
return {{isDerivation(storePath) ? storePath : "", {{"out", storePath}}}};
std::map<std::string, StorePath> outputs;
outputs.insert_or_assign("out", storePath.clone());
Buildable b{
.drvPath = storePath.isDerivation() ? storePath.clone() : std::optional<StorePath>(),
.outputs = std::move(outputs)
};
Buildables bs;
bs.push_back(std::move(b));
return bs;
}
};
@@ -120,17 +130,17 @@ struct InstallableValue : Installable
Buildables res;
PathSet drvPaths;
StorePathSet drvPaths;
for (auto & drv : drvs) {
Buildable b{drv.queryDrvPath()};
drvPaths.insert(b.drvPath);
Buildable b{.drvPath = state->store->parseStorePath(drv.queryDrvPath())};
drvPaths.insert(b.drvPath->clone());
auto outputName = drv.queryOutputName();
if (outputName == "")
throw Error("derivation '%s' lacks an 'outputName' attribute", b.drvPath);
throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(*b.drvPath));
b.outputs.emplace(outputName, drv.queryOutPath());
b.outputs.emplace(outputName, state->store->parseStorePath(drv.queryOutPath()));
res.push_back(std::move(b));
}
@@ -138,10 +148,13 @@ struct InstallableValue : Installable
// Hack to recognize .all: if all drvs have the same drvPath,
// merge the buildables.
if (drvPaths.size() == 1) {
Buildable b{*drvPaths.begin()};
Buildable b{.drvPath = drvPaths.begin()->clone()};
for (auto & b2 : res)
b.outputs.insert(b2.outputs.begin(), b2.outputs.end());
return {b};
for (auto & output : b2.outputs)
b.outputs.insert_or_assign(output.first, output.second.clone());
Buildables bs;
bs.push_back(std::move(b));
return bs;
} else
return res;
}
@@ -212,7 +225,7 @@ static std::vector<std::shared_ptr<Installable>> parseInstallables(
auto path = store->toStorePath(store->followLinksToStore(s));
if (store->isStorePath(path))
result.push_back(std::make_shared<InstallableStorePath>(path));
result.push_back(std::make_shared<InstallableStorePath>(store, path));
}
else if (s == "" || std::regex_match(s, attrPathRegex))
@@ -242,19 +255,18 @@ Buildables build(ref<Store> store, RealiseMode mode,
Buildables buildables;
PathSet pathsToBuild;
std::vector<StorePathWithOutputs> pathsToBuild;
for (auto & i : installables) {
for (auto & b : i->toBuildables()) {
if (b.drvPath != "") {
if (b.drvPath) {
StringSet outputNames;
for (auto & output : b.outputs)
outputNames.insert(output.first);
pathsToBuild.insert(
b.drvPath + "!" + concatStringsSep(",", outputNames));
pathsToBuild.push_back({*b.drvPath, outputNames});
} else
for (auto & output : b.outputs)
pathsToBuild.insert(output.second);
pathsToBuild.push_back({output.second.clone()});
buildables.push_back(std::move(b));
}
}
@@ -267,19 +279,19 @@ Buildables build(ref<Store> store, RealiseMode mode,
return buildables;
}
PathSet toStorePaths(ref<Store> store, RealiseMode mode,
StorePathSet toStorePaths(ref<Store> store, RealiseMode mode,
std::vector<std::shared_ptr<Installable>> installables)
{
PathSet outPaths;
StorePathSet outPaths;
for (auto & b : build(store, mode, installables))
for (auto & output : b.outputs)
outPaths.insert(output.second);
outPaths.insert(output.second.clone());
return outPaths;
}
Path toStorePath(ref<Store> store, RealiseMode mode,
StorePath toStorePath(ref<Store> store, RealiseMode mode,
std::shared_ptr<Installable> installable)
{
auto paths = toStorePaths(store, mode, {installable});
@@ -287,17 +299,17 @@ Path toStorePath(ref<Store> store, RealiseMode mode,
if (paths.size() != 1)
throw Error("argument '%s' should evaluate to one store path", installable->what());
return *paths.begin();
return paths.begin()->clone();
}
PathSet toDerivations(ref<Store> store,
StorePathSet toDerivations(ref<Store> store,
std::vector<std::shared_ptr<Installable>> installables, bool useDeriver)
{
PathSet drvPaths;
StorePathSet drvPaths;
for (auto & i : installables)
for (auto & b : i->toBuildables()) {
if (b.drvPath.empty()) {
if (!b.drvPath) {
if (!useDeriver)
throw Error("argument '%s' did not evaluate to a derivation", i->what());
for (auto & output : b.outputs) {
@@ -305,10 +317,10 @@ PathSet toDerivations(ref<Store> store,
if (derivers.empty())
throw Error("'%s' does not have a known deriver", i->what());
// FIXME: use all derivers?
drvPaths.insert(*derivers.begin());
drvPaths.insert(derivers.begin()->clone());
}
} else
drvPaths.insert(b.drvPath);
drvPaths.insert(b.drvPath->clone());
}
return drvPaths;
+1 -1
View File
@@ -15,7 +15,7 @@ nix_SOURCES := \
$(wildcard src/nix-prefetch-url/*.cc) \
$(wildcard src/nix-store/*.cc) \
nix_LIBS = libexpr libmain libstore libutil
nix_LIBS = libexpr libmain libstore libutil libnixrust
nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system
+1 -1
View File
@@ -43,7 +43,7 @@ struct CmdLog : InstallableCommand
RunPager pager;
for (auto & sub : subs) {
auto log = b.drvPath != "" ? sub->getBuildLog(b.drvPath) : nullptr;
auto log = b.drvPath ? sub->getBuildLog(*b.drvPath) : nullptr;
for (auto & output : b.outputs) {
if (log) break;
log = sub->getBuildLog(output.second);
+1 -1
View File
@@ -67,7 +67,7 @@ struct MixLs : virtual Args, MixJSON
if (st.type == FSAccessor::Type::tMissing)
throw Error(format("path '%1%' does not exist") % path);
doPath(st, path,
st.type == FSAccessor::Type::tDirectory ? "." : baseNameOf(path),
st.type == FSAccessor::Type::tDirectory ? "." : std::string(baseNameOf(path)),
showDirectory);
}
+1 -1
View File
@@ -135,7 +135,7 @@ void mainWrapped(int argc, char * * argv)
initGC();
programPath = argv[0];
string programName = baseNameOf(programPath);
auto programName = std::string(baseNameOf(programPath));
{
auto legacy = (*RegisterLegacyCommand::commands)[programName];
+22 -18
View File
@@ -29,34 +29,36 @@ struct CmdMakeContentAddressable : StorePathsCommand
},
};
}
void run(ref<Store> store, Paths storePaths) override
void run(ref<Store> store, StorePaths storePaths) override
{
auto paths = store->topoSortPaths(PathSet(storePaths.begin(), storePaths.end()));
auto paths = store->topoSortPaths(storePathsToSet(storePaths));
paths.reverse();
std::reverse(paths.begin(), paths.end());
std::map<Path, Path> remappings;
std::map<StorePath, StorePath> remappings;
for (auto & path : paths) {
auto pathS = store->printStorePath(path);
auto oldInfo = store->queryPathInfo(path);
auto oldHashPart = storePathToHash(path);
auto name = storePathToName(path);
auto oldHashPart = storePathToHash(pathS);
StringSink sink;
store->narFromPath(path, sink);
StringMap rewrites;
ValidPathInfo info;
StorePathSet references;
bool hasSelfReference = false;
for (auto & ref : oldInfo->references) {
if (ref == path)
info.references.insert("self");
hasSelfReference = true;
else {
auto replacement = get(remappings, ref, ref);
auto i = remappings.find(ref);
auto replacement = i != remappings.end() ? i->second.clone() : ref.clone();
// FIXME: warn about unremapped paths?
info.references.insert(replacement);
if (replacement != ref)
rewrites[storePathToHash(ref)] = storePathToHash(replacement);
rewrites.insert_or_assign(store->printStorePath(ref), store->printStorePath(replacement));
references.insert(std::move(replacement));
}
}
@@ -65,24 +67,26 @@ struct CmdMakeContentAddressable : StorePathsCommand
HashModuloSink hashModuloSink(htSHA256, oldHashPart);
hashModuloSink((unsigned char *) sink.s->data(), sink.s->size());
info.narHash = hashModuloSink.finish().first;
auto narHash = hashModuloSink.finish().first;
ValidPathInfo info(store->makeFixedOutputPath(true, narHash, path.name(), references, hasSelfReference));
info.references = std::move(references);
if (hasSelfReference) info.references.insert(info.path.clone());
info.narHash = narHash;
info.narSize = sink.s->size();
replaceInSet(info.references, path, std::string("self"));
info.path = store->makeFixedOutputPath(true, info.narHash, name, info.references);
replaceInSet(info.references, std::string("self"), info.path);
info.ca = makeFixedOutputCA(true, info.narHash);
printError("rewrote '%s' to '%s'", path, info.path);
printError("rewrote '%s' to '%s'", pathS, store->printStorePath(info.path));
auto source = sinkToSource([&](Sink & nextSink) {
RewritingSink rsink2(oldHashPart, storePathToHash(info.path), nextSink);
RewritingSink rsink2(oldHashPart, storePathToHash(store->printStorePath(info.path)), nextSink);
rsink2((unsigned char *) sink.s->data(), sink.s->size());
rsink2.flush();
});
store->addToStore(info, *source);
remappings[path] = info.path;
remappings.insert_or_assign(std::move(path), std::move(info.path));
}
}
};
+8 -8
View File
@@ -78,36 +78,36 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
std::cout << fmt("\t%6.1f%c", res, idents.at(power));
}
void run(ref<Store> store, Paths storePaths) override
void run(ref<Store> store, StorePaths storePaths) override
{
size_t pathLen = 0;
for (auto & storePath : storePaths)
pathLen = std::max(pathLen, storePath.size());
pathLen = std::max(pathLen, store->printStorePath(storePath).size());
if (json) {
JSONPlaceholder jsonRoot(std::cout);
store->pathInfoToJSON(jsonRoot,
// FIXME: preserve order?
PathSet(storePaths.begin(), storePaths.end()),
storePathsToSet(storePaths),
true, showClosureSize, AllowInvalid);
}
else {
for (auto storePath : storePaths) {
for (auto & storePath : storePaths) {
auto info = store->queryPathInfo(storePath);
storePath = info->path; // FIXME: screws up padding
auto storePathS = store->printStorePath(storePath);
std::cout << storePath;
std::cout << storePathS;
if (showSize || showClosureSize || showSigs)
std::cout << std::string(std::max(0, (int) pathLen - (int) storePath.size()), ' ');
std::cout << std::string(std::max(0, (int) pathLen - (int) storePathS.size()), ' ');
if (showSize)
printSize(info->narSize);
if (showClosureSize)
printSize(store->getClosureSize(storePath).first);
printSize(store->getClosureSize(info->path).first);
if (showSigs) {
std::cout << '\t';
+9 -2
View File
@@ -24,6 +24,13 @@ static uint64_t getI(const std::vector<Logger::Field> & fields, size_t n)
return fields[n].i;
}
static std::string_view storePathToName(std::string_view path)
{
auto base = baseNameOf(path);
auto i = base.find('-');
return i == std::string::npos ? base.substr(0, 0) : base.substr(i + 1);
}
class ProgressBar : public Logger
{
private:
@@ -148,7 +155,7 @@ public:
if (type == actBuild) {
auto name = storePathToName(getS(fields, 0));
if (hasSuffix(name, ".drv"))
name.resize(name.size() - 4);
name = name.substr(name.size() - 4);
i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name);
auto machineName = getS(fields, 1);
if (machineName != "")
@@ -173,7 +180,7 @@ public:
if (type == actPostBuildHook) {
auto name = storePathToName(getS(fields, 0));
if (hasSuffix(name, ".drv"))
name.resize(name.size() - 4);
name = name.substr(name.size() - 4);
i->s = fmt("post-build " ANSI_BOLD "%s" ANSI_NORMAL, name);
i->name = DrvName(name).name;
}
+3 -3
View File
@@ -413,7 +413,7 @@ Path NixRepl::getDerivationPath(Value & v) {
if (!drvInfo)
throw Error("expression does not evaluate to a derivation, so I can't build it");
Path drvPath = drvInfo->queryDrvPath();
if (drvPath == "" || !state.store->isValidPath(drvPath))
if (drvPath == "" || !state.store->isValidPath(state.store->parseStorePath(drvPath)))
throw Error("expression did not evaluate to a valid derivation");
return drvPath;
}
@@ -521,10 +521,10 @@ bool NixRepl::processLine(string line)
but doing it in a child makes it easier to recover from
problems / SIGINT. */
if (runProgram(settings.nixBinDir + "/nix", Strings{"build", "--no-link", drvPath}) == 0) {
Derivation drv = readDerivation(drvPath);
auto drv = readDerivation(*state.store, drvPath);
std::cout << std::endl << "this derivation produced the following outputs:" << std::endl;
for (auto & i : drv.outputs)
std::cout << format(" %1% -> %2%") % i.first % i.second.path << std::endl;
std::cout << fmt(" %s -> %s\n", i.first, state.store->printStorePath(i.second.path));
}
} else if (command == ":i") {
runProgram(settings.nixBinDir + "/nix-env", Strings{"-i", drvPath});
+8 -8
View File
@@ -119,24 +119,24 @@ struct CmdRun : InstallablesCommand
unsetenv(var.c_str());
}
std::unordered_set<Path> done;
std::queue<Path> todo;
for (auto & path : outPaths) todo.push(path);
std::unordered_set<StorePath> done;
std::queue<StorePath> todo;
for (auto & path : outPaths) todo.push(path.clone());
auto unixPath = tokenizeString<Strings>(getEnv("PATH").value_or(""), ":");
while (!todo.empty()) {
Path path = todo.front();
auto path = todo.front().clone();
todo.pop();
if (!done.insert(path).second) continue;
if (!done.insert(path.clone()).second) continue;
if (true)
unixPath.push_front(path + "/bin");
unixPath.push_front(store->printStorePath(path) + "/bin");
auto propPath = path + "/nix-support/propagated-user-env-packages";
auto propPath = store->printStorePath(path) + "/nix-support/propagated-user-env-packages";
if (accessor->stat(propPath).type == FSAccessor::tRegular) {
for (auto & p : tokenizeString<Paths>(readFile(propPath)))
todo.push(p);
todo.push(store->parseStorePath(p));
}
}
+10 -8
View File
@@ -46,9 +46,9 @@ struct CmdShowDerivation : InstallablesCommand
auto drvPaths = toDerivations(store, installables, true);
if (recursive) {
PathSet closure;
StorePathSet closure;
store->computeFSClosure(drvPaths, closure);
drvPaths = closure;
drvPaths = std::move(closure);
}
{
@@ -56,17 +56,19 @@ struct CmdShowDerivation : InstallablesCommand
JSONObject jsonRoot(std::cout, true);
for (auto & drvPath : drvPaths) {
if (!isDerivation(drvPath)) continue;
if (!drvPath.isDerivation()) continue;
auto drvObj(jsonRoot.object(drvPath));
auto drvPathS = store->printStorePath(drvPath);
auto drv = readDerivation(drvPath);
auto drvObj(jsonRoot.object(drvPathS));
auto drv = readDerivation(*store, drvPathS);
{
auto outputsObj(drvObj.object("outputs"));
for (auto & output : drv.outputs) {
auto outputObj(outputsObj.object(output.first));
outputObj.attr("path", output.second.path);
outputObj.attr("path", store->printStorePath(output.second.path));
if (output.second.hash != "") {
outputObj.attr("hashAlgo", output.second.hashAlgo);
outputObj.attr("hash", output.second.hash);
@@ -77,13 +79,13 @@ struct CmdShowDerivation : InstallablesCommand
{
auto inputsList(drvObj.list("inputSrcs"));
for (auto & input : drv.inputSrcs)
inputsList.elem(input);
inputsList.elem(store->printStorePath(input));
}
{
auto inputDrvsObj(drvObj.object("inputDrvs"));
for (auto & input : drv.inputDrvs) {
auto inputList(inputDrvsObj.list(input.first));
auto inputList(inputDrvsObj.list(store->printStorePath(input.first)));
for (auto & outputId : input.second)
inputList.elem(outputId);
}
+10 -8
View File
@@ -27,7 +27,7 @@ struct CmdCopySigs : StorePathsCommand
return "copy path signatures from substituters (like binary caches)";
}
void run(ref<Store> store, Paths storePaths) override
void run(ref<Store> store, StorePaths storePaths) override
{
if (substituterUris.empty())
throw UsageError("you must specify at least one substituter using '-s'");
@@ -44,18 +44,20 @@ struct CmdCopySigs : StorePathsCommand
//logger->setExpected(doneLabel, storePaths.size());
auto doPath = [&](const Path & storePath) {
auto doPath = [&](const Path & storePathS) {
//Activity act(*logger, lvlInfo, format("getting signatures for '%s'") % storePath);
checkInterrupt();
auto storePath = store->parseStorePath(storePathS);
auto info = store->queryPathInfo(storePath);
StringSet newSigs;
for (auto & store2 : substituters) {
try {
auto info2 = store2->queryPathInfo(storePath);
auto info2 = store2->queryPathInfo(info->path);
/* Don't import signatures that don't match this
binary. */
@@ -80,11 +82,11 @@ struct CmdCopySigs : StorePathsCommand
};
for (auto & storePath : storePaths)
pool.enqueue(std::bind(doPath, storePath));
pool.enqueue(std::bind(doPath, store->printStorePath(storePath)));
pool.process();
printInfo(format("imported %d signatures") % added);
printInfo("imported %d signatures", added);
}
};
@@ -109,7 +111,7 @@ struct CmdSignPaths : StorePathsCommand
return "sign the specified paths";
}
void run(ref<Store> store, Paths storePaths) override
void run(ref<Store> store, StorePaths storePaths) override
{
if (secretKeyFile.empty())
throw UsageError("you must specify a secret key file using '-k'");
@@ -123,7 +125,7 @@ struct CmdSignPaths : StorePathsCommand
auto info2(*info);
info2.sigs.clear();
info2.sign(secretKey);
info2.sign(*store, secretKey);
assert(!info2.sigs.empty());
if (!info->sigs.count(*info2.sigs.begin())) {
@@ -132,7 +134,7 @@ struct CmdSignPaths : StorePathsCommand
}
}
printInfo(format("added %d signatures") % added);
printInfo("added %d signatures", added);
}
};
+13 -14
View File
@@ -58,13 +58,9 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
printInfo("upgrading Nix in profile '%s'", profileDir);
Path storePath;
{
Activity act(*logger, lvlInfo, actUnknown, "querying latest Nix version");
storePath = getLatestNix(store);
}
auto storePath = getLatestNix(store);
auto version = DrvName(storePathToName(storePath)).version;
auto version = DrvName(storePath.name()).version;
if (dryRun) {
stopProgressBar();
@@ -73,13 +69,13 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
}
{
Activity act(*logger, lvlInfo, actUnknown, fmt("downloading '%s'...", storePath));
Activity act(*logger, lvlInfo, actUnknown, fmt("downloading '%s'...", store->printStorePath(storePath)));
store->ensurePath(storePath);
}
{
Activity act(*logger, lvlInfo, actUnknown, fmt("verifying that '%s' works...", storePath));
auto program = storePath + "/bin/nix-env";
Activity act(*logger, lvlInfo, actUnknown, fmt("verifying that '%s' works...", store->printStorePath(storePath)));
auto program = store->printStorePath(storePath) + "/bin/nix-env";
auto s = runProgram(program, false, {"--version"});
if (s.find("Nix") == std::string::npos)
throw Error("could not verify that '%s' works", program);
@@ -88,9 +84,10 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
stopProgressBar();
{
Activity act(*logger, lvlInfo, actUnknown, fmt("installing '%s' into profile '%s'...", storePath, profileDir));
Activity act(*logger, lvlInfo, actUnknown,
fmt("installing '%s' into profile '%s'...", store->printStorePath(storePath), profileDir));
runProgram(settings.nixBinDir + "/nix-env", false,
{"--profile", profileDir, "-i", storePath, "--no-sandbox"});
{"--profile", profileDir, "-i", store->printStorePath(storePath), "--no-sandbox"});
}
printError(ANSI_GREEN "upgrade to version %s done" ANSI_NORMAL, version);
@@ -129,15 +126,17 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
!hasSuffix(userEnv, "user-environment"))
throw Error("directory '%s' does not appear to be part of a Nix profile", where);
if (!store->isValidPath(userEnv))
if (!store->isValidPath(store->parseStorePath(userEnv)))
throw Error("directory '%s' is not in the Nix store", userEnv);
return profileDir;
}
/* Return the store path of the latest stable Nix. */
Path getLatestNix(ref<Store> store)
StorePath getLatestNix(ref<Store> store)
{
Activity act(*logger, lvlInfo, actUnknown, "querying latest Nix version");
// FIXME: use nixos.org?
auto req = DownloadRequest(storePathsUrl);
auto res = getDownloader()->download(req);
@@ -148,7 +147,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
Bindings & bindings(*state->allocBindings(0));
auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v);
return state->forceString(*v2);
return store->parseStorePath(state->forceString(*v2));
}
};
+10 -10
View File
@@ -49,7 +49,7 @@ struct CmdVerify : StorePathsCommand
};
}
void run(ref<Store> store, Paths storePaths) override
void run(ref<Store> store, StorePaths storePaths) override
{
std::vector<ref<Store>> substituters;
for (auto & s : substituterUris)
@@ -80,7 +80,7 @@ struct CmdVerify : StorePathsCommand
MaintainCount<std::atomic<size_t>> mcActive(active);
update();
auto info = store->queryPathInfo(storePath);
auto info = store->queryPathInfo(store->parseStorePath(storePath));
if (!noContents) {
@@ -88,7 +88,7 @@ struct CmdVerify : StorePathsCommand
if (info->ca == "")
hashSink = std::make_unique<HashSink>(info->narHash.type);
else
hashSink = std::make_unique<HashModuloSink>(info->narHash.type, storePathToHash(info->path));
hashSink = std::make_unique<HashModuloSink>(info->narHash.type, storePathToHash(store->printStorePath(info->path)));
store->narFromPath(info->path, *hashSink);
@@ -96,10 +96,10 @@ struct CmdVerify : StorePathsCommand
if (hash.first != info->narHash) {
corrupted++;
act2.result(resCorruptedPath, info->path);
act2.result(resCorruptedPath, store->printStorePath(info->path));
printError(
format("path '%s' was modified! expected hash '%s', got '%s'")
% info->path % info->narHash.to_string() % hash.first.to_string());
"path '%s' was modified! expected hash '%s', got '%s'",
store->printStorePath(info->path), info->narHash.to_string(), hash.first.to_string());
}
}
@@ -120,7 +120,7 @@ struct CmdVerify : StorePathsCommand
auto doSigs = [&](StringSet sigs) {
for (auto sig : sigs) {
if (!sigsSeen.insert(sig).second) continue;
if (validSigs < ValidPathInfo::maxSigs && info->checkSignature(publicKeys, sig))
if (validSigs < ValidPathInfo::maxSigs && info->checkSignature(*store, publicKeys, sig))
validSigs++;
}
};
@@ -147,8 +147,8 @@ struct CmdVerify : StorePathsCommand
if (!good) {
untrusted++;
act2.result(resUntrustedPath, info->path);
printError(format("path '%s' is untrusted") % info->path);
act2.result(resUntrustedPath, store->printStorePath(info->path));
printError("path '%s' is untrusted", store->printStorePath(info->path));
}
}
@@ -164,7 +164,7 @@ struct CmdVerify : StorePathsCommand
};
for (auto & storePath : storePaths)
pool.enqueue(std::bind(doPath, storePath));
pool.enqueue(std::bind(doPath, store->printStorePath(storePath)));
pool.process();
+16 -14
View File
@@ -73,9 +73,9 @@ struct CmdWhyDepends : SourceExprCommand
auto packagePath = toStorePath(store, Build, package);
auto dependency = parseInstallable(*this, store, _dependency, false);
auto dependencyPath = toStorePath(store, NoBuild, dependency);
auto dependencyPathHash = storePathToHash(dependencyPath);
auto dependencyPathHash = storePathToHash(store->printStorePath(dependencyPath));
PathSet closure;
StorePathSet closure;
store->computeFSClosure({packagePath}, closure, false, false);
if (!closure.count(dependencyPath)) {
@@ -91,28 +91,28 @@ struct CmdWhyDepends : SourceExprCommand
struct Node
{
Path path;
PathSet refs;
PathSet rrefs;
StorePath path;
StorePathSet refs;
StorePathSet rrefs;
size_t dist = inf;
Node * prev = nullptr;
bool queued = false;
bool visited = false;
};
std::map<Path, Node> graph;
std::map<StorePath, Node> graph;
for (auto & path : closure)
graph.emplace(path, Node{path, store->queryPathInfo(path)->references});
graph.emplace(path.clone(), Node{path.clone(), cloneStorePathSet(store->queryPathInfo(path)->references)});
// Transpose the graph.
for (auto & node : graph)
for (auto & ref : node.second.refs)
graph[ref].rrefs.insert(node.first);
graph.find(ref)->second.rrefs.insert(node.first.clone());
/* Run Dijkstra's shortest path algorithm to get the distance
of every path in the closure to 'dependency'. */
graph[dependencyPath].dist = 0;
graph[dependencyPath.clone()].dist = 0;
std::priority_queue<Node *> queue;
@@ -151,12 +151,14 @@ struct CmdWhyDepends : SourceExprCommand
struct BailOut { };
printNode = [&](Node & node, const string & firstPad, const string & tailPad) {
auto pathS = store->printStorePath(node.path);
assert(node.dist != inf);
std::cout << fmt("%s%s%s%s" ANSI_NORMAL "\n",
firstPad,
node.visited ? "\e[38;5;244m" : "",
firstPad != "" ? "=> " : "",
node.path);
pathS);
if (node.path == dependencyPath && !all
&& packagePath != dependencyPath)
@@ -175,7 +177,7 @@ struct CmdWhyDepends : SourceExprCommand
auto & node2 = graph.at(ref);
if (node2.dist == inf) continue;
refs.emplace(node2.dist, &node2);
hashes.insert(storePathToHash(node2.path));
hashes.insert(storePathToHash(store->printStorePath(node2.path)));
}
/* For each reference, find the files and symlinks that
@@ -187,7 +189,7 @@ struct CmdWhyDepends : SourceExprCommand
visitPath = [&](const Path & p) {
auto st = accessor->stat(p);
auto p2 = p == node.path ? "/" : std::string(p, node.path.size() + 1);
auto p2 = p == pathS ? "/" : std::string(p, pathS.size() + 1);
auto getColour = [&](const std::string & hash) {
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
@@ -231,11 +233,11 @@ struct CmdWhyDepends : SourceExprCommand
// FIXME: should use scanForReferences().
visitPath(node.path);
visitPath(pathS);
RunPager pager;
for (auto & ref : refs) {
auto hash = storePathToHash(ref.second->path);
auto hash = storePathToHash(store->printStorePath(ref.second->path));
bool last = all ? ref == *refs.rbegin() : true;