Make the store directory a member variable of Store

This commit is contained in:
Eelco Dolstra 2016-06-01 14:49:12 +02:00
parent 1b5b654fe2
commit 7850d3d279
35 changed files with 315 additions and 296 deletions

View file

@ -11,7 +11,6 @@ makefiles = \
src/nix-env/local.mk \ src/nix-env/local.mk \
src/nix-daemon/local.mk \ src/nix-daemon/local.mk \
src/nix-collect-garbage/local.mk \ src/nix-collect-garbage/local.mk \
src/download-via-ssh/local.mk \
src/nix-prefetch-url/local.mk \ src/nix-prefetch-url/local.mk \
perl/local.mk \ perl/local.mk \
scripts/local.mk \ scripts/local.mk \
@ -22,6 +21,7 @@ makefiles = \
misc/emacs/local.mk \ misc/emacs/local.mk \
doc/manual/local.mk \ doc/manual/local.mk \
tests/local.mk tests/local.mk
#src/download-via-ssh/local.mk \
GLOBAL_CXXFLAGS += -std=c++11 -g -Wall GLOBAL_CXXFLAGS += -std=c++11 -g -Wall

View file

@ -161,8 +161,7 @@ SV * topoSortPaths(...)
SV * followLinksToStorePath(char * path) SV * followLinksToStorePath(char * path)
CODE: CODE:
try { try {
store(); RETVAL = newSVpv(store()->followLinksToStorePath(path).c_str(), 0);
RETVAL = newSVpv(followLinksToStorePath(path).c_str(), 0);
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
} }
@ -289,7 +288,7 @@ SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
PPCODE: PPCODE:
try { try {
HashType ht = parseHashType(algo); HashType ht = parseHashType(algo);
Path path = makeFixedOutputPath(recursive, ht, Path path = store()->makeFixedOutputPath(recursive, ht,
parseHash16or32(ht, hash), name); parseHash16or32(ht, hash), name);
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {

View file

@ -341,7 +341,7 @@ Path EvalState::checkSourcePath(const Path & path_)
/* To support import-from-derivation, allow access to anything in /* To support import-from-derivation, allow access to anything in
the store. FIXME: only allow access to paths that have been the store. FIXME: only allow access to paths that have been
constructed by this evaluation. */ constructed by this evaluation. */
if (isInStore(path)) return path; if (store->isInStore(path)) return path;
#if 0 #if 0
/* Hack to support the chroot dependencies of corepkgs (see /* Hack to support the chroot dependencies of corepkgs (see
@ -1517,7 +1517,7 @@ string EvalState::copyPathToStore(PathSet & context, const Path & path)
dstPath = srcToStore[path]; dstPath = srcToStore[path];
else { else {
dstPath = settings.readOnlyMode dstPath = settings.readOnlyMode
? computeStorePathForPath(checkSourcePath(path)).first ? store->computeStorePathForPath(checkSourcePath(path)).first
: store->addToStore(baseNameOf(path), checkSourcePath(path), true, htSHA256, defaultPathFilter, repair); : store->addToStore(baseNameOf(path), checkSourcePath(path), true, htSHA256, defaultPathFilter, repair);
srcToStore[path] = dstPath; srcToStore[path] = dstPath;
printMsg(lvlChatty, format("copied source %1% -> %2%") printMsg(lvlChatty, format("copied source %1% -> %2%")

View file

@ -50,7 +50,7 @@ void EvalState::realiseContext(const PathSet & context)
for (auto & i : context) { for (auto & i : context) {
std::pair<string, string> decoded = decodeContext(i); std::pair<string, string> decoded = decodeContext(i);
Path ctx = decoded.first; Path ctx = decoded.first;
assert(isStorePath(ctx)); assert(store->isStorePath(ctx));
if (!store->isValidPath(ctx)) if (!store->isValidPath(ctx))
throw InvalidPathError(ctx); throw InvalidPathError(ctx);
if (!decoded.second.empty() && nix::isDerivation(ctx)) if (!decoded.second.empty() && nix::isDerivation(ctx))
@ -82,7 +82,7 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
path = state.checkSourcePath(path); path = state.checkSourcePath(path);
if (isStorePath(path) && state.store->isValidPath(path) && isDerivation(path)) { if (state.store->isStorePath(path) && state.store->isValidPath(path) && isDerivation(path)) {
Derivation drv = readDerivation(path); Derivation drv = readDerivation(path);
Value & w = *state.allocValue(); Value & w = *state.allocValue();
state.mkAttrs(w, 3 + drv.outputs.size()); state.mkAttrs(w, 3 + drv.outputs.size());
@ -624,7 +624,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
outputHash = printHash(h); outputHash = printHash(h);
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo; if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
Path outPath = makeFixedOutputPath(outputHashRecursive, ht, h, drvName); Path outPath = state.store->makeFixedOutputPath(outputHashRecursive, ht, h, drvName);
drv.env["out"] = outPath; drv.env["out"] = outPath;
drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, outputHash); drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, outputHash);
} }
@ -646,7 +646,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
for (auto & i : drv.outputs) for (auto & i : drv.outputs)
if (i.second.path == "") { if (i.second.path == "") {
Path outPath = makeOutputPath(i.first, h, drvName); Path outPath = state.store->makeOutputPath(i.first, h, drvName);
drv.env[i.first] = outPath; drv.env[i.first] = outPath;
i.second.path = outPath; i.second.path = outPath;
} }
@ -702,10 +702,10 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
/* Resolve symlinks in path, unless path itself is a symlink /* Resolve symlinks in path, unless path itself is a symlink
directly in the store. The latter condition is necessary so directly in the store. The latter condition is necessary so
e.g. nix-push does the right thing. */ e.g. nix-push does the right thing. */
if (!isStorePath(path)) path = canonPath(path, true); if (!state.store->isStorePath(path)) path = canonPath(path, true);
if (!isInStore(path)) if (!state.store->isInStore(path))
throw EvalError(format("path %1% is not in the Nix store, at %2%") % path % pos); throw EvalError(format("path %1% is not in the Nix store, at %2%") % path % pos);
Path path2 = toStorePath(path); Path path2 = state.store->toStorePath(path);
if (!settings.readOnlyMode) if (!settings.readOnlyMode)
state.store->ensurePath(path2); state.store->ensurePath(path2);
context.insert(path2); context.insert(path2);
@ -897,7 +897,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
} }
Path storePath = settings.readOnlyMode Path storePath = settings.readOnlyMode
? computeStorePathForText(name, contents, refs) ? state.store->computeStorePathForText(name, contents, refs)
: state.store->addTextToStore(name, contents, refs, state.repair); : state.store->addTextToStore(name, contents, refs, state.repair);
/* Note: we don't need to add `context' to the context of the /* Note: we don't need to add `context' to the context of the
@ -963,7 +963,7 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args
path = state.checkSourcePath(path); path = state.checkSourcePath(path);
Path dstPath = settings.readOnlyMode Path dstPath = settings.readOnlyMode
? computeStorePathForPath(path, true, htSHA256, filter).first ? state.store->computeStorePathForPath(path, true, htSHA256, filter).first
: state.store->addToStore(baseNameOf(path), path, true, htSHA256, filter, state.repair); : state.store->addToStore(baseNameOf(path), path, true, htSHA256, filter, state.repair);
mkString(v, dstPath, {dstPath}); mkString(v, dstPath, {dstPath});
@ -1765,7 +1765,7 @@ void EvalState::createBaseEnv()
mkString(v, nixVersion); mkString(v, nixVersion);
addConstant("__nixVersion", v); addConstant("__nixVersion", v);
mkString(v, settings.nixStore); mkString(v, store->storeDir);
addConstant("__storeDir", v); addConstant("__storeDir", v);
/* Language version. This should be increased every time a new /* Language version. This should be increased every time a new

View file

@ -14,8 +14,9 @@
namespace nix { namespace nix {
BinaryCacheStore::BinaryCacheStore(const StoreParams & params) BinaryCacheStore::BinaryCacheStore(const Params & params)
: compression(get(params, "compression", "xz")) : Store(params)
, compression(get(params, "compression", "xz"))
{ {
auto secretKeyFile = get(params, "secret-key", ""); auto secretKeyFile = get(params, "secret-key", "");
if (secretKeyFile != "") if (secretKeyFile != "")
@ -32,7 +33,7 @@ void BinaryCacheStore::init()
auto cacheInfo = getFile(cacheInfoFile); auto cacheInfo = getFile(cacheInfoFile);
if (!cacheInfo) { if (!cacheInfo) {
upsertFile(cacheInfoFile, "StoreDir: " + settings.nixStore + "\n"); upsertFile(cacheInfoFile, "StoreDir: " + storeDir + "\n");
} else { } else {
for (auto & line : tokenizeString<Strings>(*cacheInfo, "\n")) { for (auto & line : tokenizeString<Strings>(*cacheInfo, "\n")) {
size_t colon = line.find(':'); size_t colon = line.find(':');
@ -40,9 +41,9 @@ void BinaryCacheStore::init()
auto name = line.substr(0, colon); auto name = line.substr(0, colon);
auto value = trim(line.substr(colon + 1, std::string::npos)); auto value = trim(line.substr(colon + 1, std::string::npos));
if (name == "StoreDir") { if (name == "StoreDir") {
if (value != settings.nixStore) if (value != storeDir)
throw Error(format("binary cache %s is for Nix stores with prefix %s, not %s") throw Error(format("binary cache %s is for Nix stores with prefix %s, not %s")
% getUri() % value % settings.nixStore); % getUri() % value % storeDir);
} else if (name == "WantMassQuery") { } else if (name == "WantMassQuery") {
wantMassQuery_ = value == "1"; wantMassQuery_ = value == "1";
} else if (name == "Priority") { } else if (name == "Priority") {
@ -181,7 +182,7 @@ std::shared_ptr<ValidPathInfo> BinaryCacheStore::queryPathInfoUncached(const Pat
auto data = getFile(narInfoFile); auto data = getFile(narInfoFile);
if (!data) return 0; if (!data) return 0;
auto narInfo = make_ref<NarInfo>(*data, narInfoFile); auto narInfo = make_ref<NarInfo>(*this, *data, narInfoFile);
stats.narInfoRead++; stats.narInfoRead++;
@ -249,7 +250,7 @@ struct BinaryCacheStoreAccessor : public FSAccessor
{ {
auto path = canonPath(path_); auto path = canonPath(path_);
auto storePath = toStorePath(path); auto storePath = store->toStorePath(path);
std::string restPath = std::string(path, storePath.size()); std::string restPath = std::string(path, storePath.size());
if (!store->isValidPath(storePath)) if (!store->isValidPath(storePath))

View file

@ -21,7 +21,7 @@ private:
protected: protected:
BinaryCacheStore(const StoreParams & params); BinaryCacheStore(const Params & params);
[[noreturn]] void notImpl(); [[noreturn]] void notImpl();

View file

@ -1442,7 +1442,7 @@ void DerivationGoal::buildDone()
#if HAVE_STATVFS #if HAVE_STATVFS
unsigned long long required = 8ULL * 1024 * 1024; // FIXME: make configurable unsigned long long required = 8ULL * 1024 * 1024; // FIXME: make configurable
struct statvfs st; struct statvfs st;
if (statvfs(settings.nixStore.c_str(), &st) == 0 && if (statvfs(worker.store.storeDir.c_str(), &st) == 0 &&
(unsigned long long) st.f_bavail * st.f_bsize < required) (unsigned long long) st.f_bavail * st.f_bsize < required)
diskFull = true; diskFull = true;
if (statvfs(tmpDir.c_str(), &st) == 0 && if (statvfs(tmpDir.c_str(), &st) == 0 &&
@ -1701,7 +1701,7 @@ void DerivationGoal::startBuilder()
shouldn't care, but this is useful for purity checking (e.g., shouldn't care, but this is useful for purity checking (e.g.,
the compiler or linker might only want to accept paths to files the compiler or linker might only want to accept paths to files
in the store or in the build directory). */ in the store or in the build directory). */
env["NIX_STORE"] = settings.nixStore; env["NIX_STORE"] = worker.store.storeDir;
/* The maximum number of cores to utilize for parallel building. */ /* The maximum number of cores to utilize for parallel building. */
env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str(); env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str();
@ -1784,10 +1784,10 @@ void DerivationGoal::startBuilder()
/* Check that the store path is valid. */ /* Check that the store path is valid. */
Path storePath = *i++; Path storePath = *i++;
if (!isInStore(storePath)) if (!worker.store.isInStore(storePath))
throw BuildError(format("exportReferencesGraph contains a non-store path %1%") throw BuildError(format("exportReferencesGraph contains a non-store path %1%")
% storePath); % storePath);
storePath = toStorePath(storePath); storePath = worker.store.toStorePath(storePath);
if (!worker.store.isValidPath(storePath)) if (!worker.store.isValidPath(storePath))
throw BuildError(format("exportReferencesGraph contains an invalid path %1%") throw BuildError(format("exportReferencesGraph contains an invalid path %1%")
% storePath); % storePath);
@ -1838,7 +1838,7 @@ void DerivationGoal::startBuilder()
string defaultChrootDirs; string defaultChrootDirs;
#if __linux__ #if __linux__
if (isInStore(BASH_PATH)) if (worker.store.isInStore(BASH_PATH))
defaultChrootDirs = "/bin/sh=" BASH_PATH; defaultChrootDirs = "/bin/sh=" BASH_PATH;
#endif #endif
@ -1867,8 +1867,8 @@ void DerivationGoal::startBuilder()
/* Add the closure of store paths to the chroot. */ /* Add the closure of store paths to the chroot. */
PathSet closure; PathSet closure;
for (auto & i : dirsInChroot) for (auto & i : dirsInChroot)
if (isInStore(i.second)) if (worker.store.isInStore(i.second))
worker.store.computeFSClosure(toStorePath(i.second), closure); worker.store.computeFSClosure(worker.store.toStorePath(i.second), closure);
for (auto & i : closure) for (auto & i : closure)
dirsInChroot[i] = i; dirsInChroot[i] = i;
@ -1953,7 +1953,7 @@ void DerivationGoal::startBuilder()
can be bind-mounted). !!! As an extra security can be bind-mounted). !!! As an extra security
precaution, make the fake Nix store only writable by the precaution, make the fake Nix store only writable by the
build user. */ build user. */
Path chrootStoreDir = chrootRootDir + settings.nixStore; Path chrootStoreDir = chrootRootDir + worker.store.storeDir;
createDirs(chrootStoreDir); createDirs(chrootStoreDir);
chmod_(chrootStoreDir, 01775); chmod_(chrootStoreDir, 01775);
@ -2408,7 +2408,7 @@ void DerivationGoal::runChild()
/* And we want the store in there regardless of how empty dirsInChroot. We include the innermost /* And we want the store in there regardless of how empty dirsInChroot. We include the innermost
path component this time, since it's typically /nix/store and we care about that. */ path component this time, since it's typically /nix/store and we care about that. */
Path cur = settings.nixStore; Path cur = worker.store.storeDir;
while (cur.compare("/") != 0) { while (cur.compare("/") != 0) {
ancestry.insert(cur); ancestry.insert(cur);
cur = dirOf(cur); cur = dirOf(cur);
@ -2532,12 +2532,12 @@ void DerivationGoal::runChild()
/* Parse a list of reference specifiers. Each element must either be /* Parse a list of reference specifiers. Each element must either be
a store path, or the symbolic name of the output of the derivation a store path, or the symbolic name of the output of the derivation
(such as `out'). */ (such as `out'). */
PathSet parseReferenceSpecifiers(const BasicDerivation & drv, string attr) PathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv, string attr)
{ {
PathSet result; PathSet result;
Paths paths = tokenizeString<Paths>(attr); Paths paths = tokenizeString<Paths>(attr);
for (auto & i : paths) { for (auto & i : paths) {
if (isStorePath(i)) if (store.isStorePath(i))
result.insert(i); result.insert(i);
else if (drv.outputs.find(i) != drv.outputs.end()) else if (drv.outputs.find(i) != drv.outputs.end())
result.insert(drv.outputs.find(i)->second.path); result.insert(drv.outputs.find(i)->second.path);
@ -2660,7 +2660,7 @@ void DerivationGoal::registerOutputs()
the derivation to its content-addressed location. */ the derivation to its content-addressed location. */
Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath); Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath);
if (buildMode == bmHash) { if (buildMode == bmHash) {
Path dest = makeFixedOutputPath(recursive, ht, h2, drv->env["name"]); Path dest = worker.store.makeFixedOutputPath(recursive, ht, h2, drv->env["name"]);
printMsg(lvlError, format("build produced path %1% with %2% hash %3%") printMsg(lvlError, format("build produced path %1% with %2% hash %3%")
% dest % printHashType(ht) % printHash16or32(h2)); % dest % printHashType(ht) % printHash16or32(h2));
if (worker.store.isValidPath(dest)) if (worker.store.isValidPath(dest))
@ -2733,7 +2733,7 @@ void DerivationGoal::registerOutputs()
auto checkRefs = [&](const string & attrName, bool allowed, bool recursive) { auto checkRefs = [&](const string & attrName, bool allowed, bool recursive) {
if (drv->env.find(attrName) == drv->env.end()) return; if (drv->env.find(attrName) == drv->env.end()) return;
PathSet spec = parseReferenceSpecifiers(*drv, get(drv->env, attrName)); PathSet spec = parseReferenceSpecifiers(worker.store, *drv, get(drv->env, attrName));
PathSet used; PathSet used;
if (recursive) { if (recursive) {
@ -2965,9 +2965,9 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
Path DerivationGoal::addHashRewrite(const Path & path) Path DerivationGoal::addHashRewrite(const Path & path)
{ {
string h1 = string(path, settings.nixStore.size() + 1, 32); string h1 = string(path, worker.store.storeDir.size() + 1, 32);
string h2 = string(printHash32(hashString(htSHA256, "rewrite:" + drvPath + ":" + path)), 0, 32); string h2 = string(printHash32(hashString(htSHA256, "rewrite:" + drvPath + ":" + path)), 0, 32);
Path p = settings.nixStore + "/" + h2 + string(path, settings.nixStore.size() + 33); Path p = worker.store.storeDir + "/" + h2 + string(path, worker.store.storeDir.size() + 33);
deletePath(p); deletePath(p);
assert(path.size() == p.size()); assert(path.size() == p.size());
rewritesToTmp[h1] = h2; rewritesToTmp[h1] = h2;

View file

@ -26,7 +26,6 @@ void builtinFetchurl(const BasicDerivation & drv)
if (out == drv.env.end()) throw Error("attribute url missing"); if (out == drv.env.end()) throw Error("attribute url missing");
Path storePath = out->second; Path storePath = out->second;
assertStorePath(storePath);
auto unpack = drv.env.find("unpack"); auto unpack = drv.env.find("unpack");
if (unpack != drv.env.end() && unpack->second == "1") { if (unpack != drv.env.end() && unpack->second == "1") {

View file

@ -81,7 +81,7 @@ Path writeDerivation(ref<Store> store,
string suffix = name + drvExtension; string suffix = name + drvExtension;
string contents = drv.unparse(); string contents = drv.unparse();
return settings.readOnlyMode return settings.readOnlyMode
? computeStorePathForText(suffix, contents, references) ? store->computeStorePathForText(suffix, contents, references)
: store->addTextToStore(suffix, contents, references, repair); : store->addTextToStore(suffix, contents, references, repair);
} }
@ -336,7 +336,7 @@ PathSet BasicDerivation::outputPaths() const
} }
Source & operator >> (Source & in, BasicDerivation & drv) Source & readDerivation(Source & in, Store & store, BasicDerivation & drv)
{ {
drv.outputs.clear(); drv.outputs.clear();
auto nr = readInt(in); auto nr = readInt(in);
@ -344,11 +344,11 @@ Source & operator >> (Source & in, BasicDerivation & drv)
auto name = readString(in); auto name = readString(in);
DerivationOutput o; DerivationOutput o;
in >> o.path >> o.hashAlgo >> o.hash; in >> o.path >> o.hashAlgo >> o.hash;
assertStorePath(o.path); store.assertStorePath(o.path);
drv.outputs[name] = o; drv.outputs[name] = o;
} }
drv.inputSrcs = readStorePaths<PathSet>(in); drv.inputSrcs = readStorePaths<PathSet>(store, in);
in >> drv.platform >> drv.builder; in >> drv.platform >> drv.builder;
drv.args = readStrings<Strings>(in); drv.args = readStrings<Strings>(in);

View file

@ -114,7 +114,7 @@ bool wantOutput(const string & output, const std::set<string> & wanted);
struct Source; struct Source;
struct Sink; struct Sink;
Source & operator >> (Source & in, BasicDerivation & drv); Source & readDerivation(Source & in, Store & store, BasicDerivation & drv);
Sink & operator << (Sink & out, const BasicDerivation & drv); Sink & operator << (Sink & out, const BasicDerivation & drv);
} }

View file

@ -101,11 +101,11 @@ Paths Store::importPaths(Source & source, std::shared_ptr<FSAccessor> accessor,
ValidPathInfo info; ValidPathInfo info;
info.path = readStorePath(source); info.path = readStorePath(*this, source);
Activity act(*logger, lvlInfo, format("importing path %s") % info.path); Activity act(*logger, lvlInfo, format("importing path %s") % info.path);
info.references = readStorePaths<PathSet>(source); info.references = readStorePaths<PathSet>(*this, source);
info.deriver = readString(source); info.deriver = readString(source);
if (info.deriver != "") assertStorePath(info.deriver); if (info.deriver != "") assertStorePath(info.deriver);

View file

@ -204,7 +204,7 @@ typedef std::shared_ptr<AutoCloseFD> FDPtr;
typedef list<FDPtr> FDs; typedef list<FDPtr> FDs;
static void readTempRoots(PathSet & tempRoots, FDs & fds) static void readTempRoots(Store & store, PathSet & tempRoots, FDs & fds)
{ {
/* Read the `temproots' directory for per-process temporary root /* Read the `temproots' directory for per-process temporary root
files. */ files. */
@ -251,7 +251,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
while ((end = contents.find((char) 0, pos)) != string::npos) { while ((end = contents.find((char) 0, pos)) != string::npos) {
Path root(contents, pos, end - pos); Path root(contents, pos, end - pos);
debug(format("got temporary root %1%") % root); debug(format("got temporary root %1%") % root);
assertStorePath(root); store.assertStorePath(root);
tempRoots.insert(root); tempRoots.insert(root);
pos = end + 1; pos = end + 1;
} }
@ -304,7 +304,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
} }
else if (type == DT_REG) { else if (type == DT_REG) {
Path storePath = settings.nixStore + "/" + baseNameOf(path); Path storePath = storeDir + "/" + baseNameOf(path);
if (isStorePath(storePath) && isValidPath(storePath)) if (isStorePath(storePath) && isValidPath(storePath))
roots[path] = storePath; roots[path] = storePath;
} }
@ -594,7 +594,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
{ {
GCState state(results); GCState state(results);
state.options = options; state.options = options;
state.trashDir = settings.nixStore + "/trash"; state.trashDir = storeDir + "/trash";
state.gcKeepOutputs = settings.gcKeepOutputs; state.gcKeepOutputs = settings.gcKeepOutputs;
state.gcKeepDerivations = settings.gcKeepDerivations; state.gcKeepDerivations = settings.gcKeepDerivations;
@ -635,7 +635,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
per-process temporary root files. So after this point no paths per-process temporary root files. So after this point no paths
can be added to the set of temporary roots. */ can be added to the set of temporary roots. */
FDs fds; FDs fds;
readTempRoots(state.tempRoots, fds); readTempRoots(*this, state.tempRoots, fds);
state.roots.insert(state.tempRoots.begin(), state.tempRoots.end()); state.roots.insert(state.tempRoots.begin(), state.tempRoots.end());
/* After this point the set of roots or temporary roots cannot /* After this point the set of roots or temporary roots cannot
@ -675,8 +675,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
try { try {
AutoCloseDir dir = opendir(settings.nixStore.c_str()); AutoCloseDir dir = opendir(storeDir.c_str());
if (!dir) throw SysError(format("opening directory %1%") % settings.nixStore); if (!dir) throw SysError(format("opening directory %1%") % storeDir);
/* Read the store and immediately delete all paths that /* Read the store and immediately delete all paths that
aren't valid. When using --max-freed etc., deleting aren't valid. When using --max-freed etc., deleting
@ -690,7 +690,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
checkInterrupt(); checkInterrupt();
string name = dirent->d_name; string name = dirent->d_name;
if (name == "." || name == "..") continue; if (name == "." || name == "..") continue;
Path path = settings.nixStore + "/" + name; Path path = storeDir + "/" + name;
if (isStorePath(path) && isValidPath(path)) if (isStorePath(path) && isValidPath(path))
entries.push_back(path); entries.push_back(path);
else else

View file

@ -18,7 +18,7 @@ private:
public: public:
HttpBinaryCacheStore( HttpBinaryCacheStore(
const StoreParams & params, const Path & _cacheUri) const Params & params, const Path & _cacheUri)
: BinaryCacheStore(params) : BinaryCacheStore(params)
, cacheUri(_cacheUri) , cacheUri(_cacheUri)
, downloaders( , downloaders(
@ -45,7 +45,7 @@ public:
} catch (UploadToHTTP &) { } catch (UploadToHTTP &) {
throw Error(format("%s does not appear to be a binary cache") % cacheUri); throw Error(format("%s does not appear to be a binary cache") % cacheUri);
} }
diskCache->createCache(cacheUri, wantMassQuery_, priority); diskCache->createCache(cacheUri, storeDir, wantMassQuery_, priority);
} }
} }
@ -91,7 +91,7 @@ protected:
}; };
static RegisterStoreImplementation regStore([]( static RegisterStoreImplementation regStore([](
const std::string & uri, const StoreParams & params) const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store> -> std::shared_ptr<Store>
{ {
if (std::string(uri, 0, 7) != "http://" && if (std::string(uri, 0, 7) != "http://" &&

View file

@ -13,7 +13,7 @@ private:
public: public:
LocalBinaryCacheStore( LocalBinaryCacheStore(
const StoreParams & params, const Path & binaryCacheDir) const Params & params, const Path & binaryCacheDir)
: BinaryCacheStore(params) : BinaryCacheStore(params)
, binaryCacheDir(binaryCacheDir) , binaryCacheDir(binaryCacheDir)
{ {
@ -45,7 +45,7 @@ protected:
if (entry.name.size() != 40 || if (entry.name.size() != 40 ||
!hasSuffix(entry.name, ".narinfo")) !hasSuffix(entry.name, ".narinfo"))
continue; continue;
paths.insert(settings.nixStore + "/" + entry.name.substr(0, entry.name.size() - 8)); paths.insert(storeDir + "/" + entry.name.substr(0, entry.name.size() - 8));
} }
return paths; return paths;
@ -59,7 +59,7 @@ void LocalBinaryCacheStore::init()
BinaryCacheStore::init(); BinaryCacheStore::init();
if (diskCache && !diskCache->cacheExists(getUri())) if (diskCache && !diskCache->cacheExists(getUri()))
diskCache->createCache(getUri(), wantMassQuery_, priority); diskCache->createCache(getUri(), storeDir, wantMassQuery_, priority);
} }
static void atomicWrite(const Path & path, const std::string & s) static void atomicWrite(const Path & path, const std::string & s)
@ -93,7 +93,7 @@ std::shared_ptr<std::string> LocalBinaryCacheStore::getFile(const std::string &
} }
static RegisterStoreImplementation regStore([]( static RegisterStoreImplementation regStore([](
const std::string & uri, const StoreParams & params) const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store> -> std::shared_ptr<Store>
{ {
if (std::string(uri, 0, 7) != "file://") return 0; if (std::string(uri, 0, 7) != "file://") return 0;

View file

@ -12,7 +12,7 @@ struct LocalStoreAccessor : public FSAccessor
void assertStore(const Path & path) void assertStore(const Path & path)
{ {
Path storePath = toStorePath(path); Path storePath = store->toStorePath(path);
if (!store->isValidPath(storePath)) if (!store->isValidPath(storePath))
throw Error(format("path %1% is not a valid store path") % storePath); throw Error(format("path %1% is not a valid store path") % storePath);
} }

View file

@ -36,26 +36,9 @@
namespace nix { namespace nix {
void checkStoreNotSymlink() LocalStore::LocalStore(const Params & params)
{ : LocalFSStore(params)
if (getEnv("NIX_IGNORE_SYMLINK_STORE") == "1") return; , linksDir(storeDir + "/.links")
Path path = settings.nixStore;
struct stat st;
while (path != "/") {
if (lstat(path.c_str(), &st))
throw SysError(format("getting status of %1%") % path);
if (S_ISLNK(st.st_mode))
throw Error(format(
"the path %1% is a symlink; "
"this is not allowed for the Nix store and its parent directories")
% path);
path = dirOf(path);
}
}
LocalStore::LocalStore()
: linksDir(settings.nixStore + "/.links")
, reservedPath(settings.nixDBPath + "/reserved") , reservedPath(settings.nixDBPath + "/reserved")
, schemaPath(settings.nixDBPath + "/schema") , schemaPath(settings.nixDBPath + "/schema")
, requireSigs(settings.get("signed-binary-caches", std::string("")) != "") // FIXME: rename option , requireSigs(settings.get("signed-binary-caches", std::string("")) != "") // FIXME: rename option
@ -69,7 +52,7 @@ LocalStore::LocalStore()
} }
/* Create missing state directories if they don't already exist. */ /* Create missing state directories if they don't already exist. */
createDirs(settings.nixStore); createDirs(storeDir);
makeStoreWritable(); makeStoreWritable();
createDirs(linksDir); createDirs(linksDir);
Path profilesDir = settings.nixStateDir + "/profiles"; Path profilesDir = settings.nixStateDir + "/profiles";
@ -99,19 +82,33 @@ LocalStore::LocalStore()
% settings.buildUsersGroup); % settings.buildUsersGroup);
else { else {
struct stat st; struct stat st;
if (stat(settings.nixStore.c_str(), &st)) if (stat(storeDir.c_str(), &st))
throw SysError(format("getting attributes of path %1%") % settings.nixStore); throw SysError(format("getting attributes of path %1%") % storeDir);
if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) { if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
if (chown(settings.nixStore.c_str(), 0, gr->gr_gid) == -1) if (chown(storeDir.c_str(), 0, gr->gr_gid) == -1)
throw SysError(format("changing ownership of path %1%") % settings.nixStore); throw SysError(format("changing ownership of path %1%") % storeDir);
if (chmod(settings.nixStore.c_str(), perm) == -1) if (chmod(storeDir.c_str(), perm) == -1)
throw SysError(format("changing permissions on path %1%") % settings.nixStore); throw SysError(format("changing permissions on path %1%") % storeDir);
} }
} }
} }
checkStoreNotSymlink(); /* Ensure that the store and its parents are not symlinks. */
if (getEnv("NIX_IGNORE_SYMLINK_STORE") != "1") {
Path path = storeDir;
struct stat st;
while (path != "/") {
if (lstat(path.c_str(), &st))
throw SysError(format("getting status of %1%") % path);
if (S_ISLNK(st.st_mode))
throw Error(format(
"the path %1% is a symlink; "
"this is not allowed for the Nix store and its parent directories")
% path);
path = dirOf(path);
}
}
/* We can't open a SQLite database if the disk is full. Since /* We can't open a SQLite database if the disk is full. Since
this prevents the garbage collector from running when it's most this prevents the garbage collector from running when it's most
@ -351,15 +348,15 @@ void LocalStore::makeStoreWritable()
if (getuid() != 0) return; if (getuid() != 0) return;
/* Check if /nix/store is on a read-only mount. */ /* Check if /nix/store is on a read-only mount. */
struct statvfs stat; struct statvfs stat;
if (statvfs(settings.nixStore.c_str(), &stat) != 0) if (statvfs(storeDir.c_str(), &stat) != 0)
throw SysError("getting info about the Nix store mount point"); throw SysError("getting info about the Nix store mount point");
if (stat.f_flag & ST_RDONLY) { if (stat.f_flag & ST_RDONLY) {
if (unshare(CLONE_NEWNS) == -1) if (unshare(CLONE_NEWNS) == -1)
throw SysError("setting up a private mount namespace"); throw SysError("setting up a private mount namespace");
if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) if (mount(0, storeDir.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
throw SysError(format("remounting %1% writable") % settings.nixStore); throw SysError(format("remounting %1% writable") % storeDir);
} }
#endif #endif
} }
@ -771,7 +768,7 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
{ {
if (hashPart.size() != storePathHashLen) throw Error("invalid hash part"); if (hashPart.size() != storePathHashLen) throw Error("invalid hash part");
Path prefix = settings.nixStore + "/" + hashPart; Path prefix = storeDir + "/" + hashPart;
return retrySQLite<Path>([&]() { return retrySQLite<Path>([&]() {
auto state(_state.lock()); auto state(_state.lock());
@ -1071,7 +1068,7 @@ Path LocalStore::createTempDirInStore()
/* There is a slight possibility that `tmpDir' gets deleted by /* There is a slight possibility that `tmpDir' gets deleted by
the GC between createTempDir() and addTempRoot(), so repeat the GC between createTempDir() and addTempRoot(), so repeat
until `tmpDir' exists. */ until `tmpDir' exists. */
tmpDir = createTempDir(settings.nixStore); tmpDir = createTempDir(storeDir);
addTempRoot(tmpDir); addTempRoot(tmpDir);
} while (!pathExists(tmpDir)); } while (!pathExists(tmpDir));
return tmpDir; return tmpDir;
@ -1111,7 +1108,7 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
AutoCloseFD fdGCLock = openGCLock(ltWrite); AutoCloseFD fdGCLock = openGCLock(ltWrite);
PathSet store; PathSet store;
for (auto & i : readDirectory(settings.nixStore)) store.insert(i.name); for (auto & i : readDirectory(storeDir)) store.insert(i.name);
/* Check whether all valid paths actually exist. */ /* Check whether all valid paths actually exist. */
printMsg(lvlInfo, "checking path existence..."); printMsg(lvlInfo, "checking path existence...");
@ -1275,7 +1272,7 @@ void LocalStore::upgradeStore7()
{ {
if (getuid() != 0) return; if (getuid() != 0) return;
printMsg(lvlError, "removing immutable bits from the Nix store (this may take a while)..."); printMsg(lvlError, "removing immutable bits from the Nix store (this may take a while)...");
makeMutable(settings.nixStore); makeMutable(storeDir);
} }
#else #else

View file

@ -85,7 +85,7 @@ public:
/* Initialise the local store, upgrading the schema if /* Initialise the local store, upgrading the schema if
necessary. */ necessary. */
LocalStore(); LocalStore(const Params & params);
~LocalStore(); ~LocalStore();

View file

@ -1,7 +1,6 @@
#include "nar-info-disk-cache.hh" #include "nar-info-disk-cache.hh"
#include "sync.hh" #include "sync.hh"
#include "sqlite.hh" #include "sqlite.hh"
#include "globals.hh"
#include <sqlite3.h> #include <sqlite3.h>
@ -54,11 +53,17 @@ public:
/* How long negative lookups are valid. */ /* How long negative lookups are valid. */
const int ttlNegative = 3600; const int ttlNegative = 3600;
struct Cache
{
int id;
Path storeDir;
};
struct State struct State
{ {
SQLite db; SQLite db;
SQLiteStmt insertCache, queryCache, insertNAR, queryNAR, insertNARExistence, queryNARExistence; SQLiteStmt insertCache, queryCache, insertNAR, queryNAR, insertNARExistence, queryNARExistence;
std::map<std::string, int> caches; std::map<std::string, Cache> caches;
}; };
Sync<State> _state; Sync<State> _state;
@ -106,22 +111,22 @@ public:
"select exist, timestamp from NARExistence where cache = ? and storePath = ?"); "select exist, timestamp from NARExistence where cache = ? and storePath = ?");
} }
int uriToInt(State & state, const std::string & uri) Cache & getCache(State & state, const std::string & uri)
{ {
auto i = state.caches.find(uri); auto i = state.caches.find(uri);
if (i == state.caches.end()) abort(); if (i == state.caches.end()) abort();
return i->second; return i->second;
} }
void createCache(const std::string & uri, bool wantMassQuery, int priority) override void createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) override
{ {
auto state(_state.lock()); auto state(_state.lock());
// FIXME: race // FIXME: race
state->insertCache.use()(uri)(time(0))(settings.nixStore)(wantMassQuery)(priority).exec(); state->insertCache.use()(uri)(time(0))(storeDir)(wantMassQuery)(priority).exec();
assert(sqlite3_changes(state->db) == 1); assert(sqlite3_changes(state->db) == 1);
state->caches[uri] = sqlite3_last_insert_rowid(state->db); state->caches[uri] = Cache{(int) sqlite3_last_insert_rowid(state->db), storeDir};
} }
bool cacheExists(const std::string & uri) override bool cacheExists(const std::string & uri) override
@ -134,7 +139,7 @@ public:
auto queryCache(state->queryCache.use()(uri)); auto queryCache(state->queryCache.use()(uri));
if (queryCache.next()) { if (queryCache.next()) {
state->caches[uri] = queryCache.getInt(0); state->caches[uri] = Cache{(int) queryCache.getInt(0), queryCache.getStr(1)};
return true; return true;
} }
@ -146,9 +151,9 @@ public:
{ {
auto state(_state.lock()); auto state(_state.lock());
auto queryNAR(state->queryNAR.use() auto & cache(getCache(*state, uri));
(uriToInt(*state, uri))
(hashPart)); auto queryNAR(state->queryNAR.use()(cache.id)(hashPart));
if (!queryNAR.next()) if (!queryNAR.next())
// FIXME: check NARExistence // FIXME: check NARExistence
@ -159,7 +164,7 @@ public:
// FIXME: implement TTL. // FIXME: implement TTL.
auto namePart = queryNAR.getStr(2); auto namePart = queryNAR.getStr(2);
narInfo->path = settings.nixStore + "/" + narInfo->path = cache.storeDir + "/" +
hashPart + (namePart.empty() ? "" : "-" + namePart); hashPart + (namePart.empty() ? "" : "-" + namePart);
narInfo->url = queryNAR.getStr(3); narInfo->url = queryNAR.getStr(3);
narInfo->compression = queryNAR.getStr(4); narInfo->compression = queryNAR.getStr(4);
@ -169,9 +174,9 @@ public:
narInfo->narHash = parseHash(queryNAR.getStr(7)); narInfo->narHash = parseHash(queryNAR.getStr(7));
narInfo->narSize = queryNAR.getInt(8); narInfo->narSize = queryNAR.getInt(8);
for (auto & r : tokenizeString<Strings>(queryNAR.getStr(9), " ")) for (auto & r : tokenizeString<Strings>(queryNAR.getStr(9), " "))
narInfo->references.insert(settings.nixStore + "/" + r); narInfo->references.insert(cache.storeDir + "/" + r);
if (!queryNAR.isNull(10)) if (!queryNAR.isNull(10))
narInfo->deriver = settings.nixStore + "/" + queryNAR.getStr(10); narInfo->deriver = cache.storeDir + "/" + queryNAR.getStr(10);
for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(11), " ")) for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(11), " "))
narInfo->sigs.insert(sig); narInfo->sigs.insert(sig);
@ -184,6 +189,8 @@ public:
{ {
auto state(_state.lock()); auto state(_state.lock());
auto & cache(getCache(*state, uri));
if (info) { if (info) {
auto narInfo = std::dynamic_pointer_cast<NarInfo>(info); auto narInfo = std::dynamic_pointer_cast<NarInfo>(info);
@ -191,7 +198,7 @@ public:
assert(hashPart == storePathToHash(info->path)); assert(hashPart == storePathToHash(info->path));
state->insertNAR.use() state->insertNAR.use()
(uriToInt(*state, uri)) (cache.id)
(hashPart) (hashPart)
(storePathToName(info->path)) (storePathToName(info->path))
(narInfo ? narInfo->url : "", narInfo != 0) (narInfo ? narInfo->url : "", narInfo != 0)

View file

@ -10,7 +10,8 @@ class NarInfoDiskCache
public: public:
typedef enum { oValid, oInvalid, oUnknown } Outcome; typedef enum { oValid, oInvalid, oUnknown } Outcome;
virtual void createCache(const std::string & uri, bool wantMassQuery, int priority) = 0; virtual void createCache(const std::string & uri, const Path & storeDir,
bool wantMassQuery, int priority) = 0;
virtual bool cacheExists(const std::string & uri) = 0; virtual bool cacheExists(const std::string & uri) = 0;

View file

@ -3,7 +3,7 @@
namespace nix { namespace nix {
NarInfo::NarInfo(const std::string & s, const std::string & whence) NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & whence)
{ {
auto corrupt = [&]() { auto corrupt = [&]() {
throw Error("NAR info file %1% is corrupt"); throw Error("NAR info file %1% is corrupt");
@ -32,7 +32,7 @@ NarInfo::NarInfo(const std::string & s, const std::string & whence)
std::string value(s, colon + 2, eol - colon - 2); std::string value(s, colon + 2, eol - colon - 2);
if (name == "StorePath") { if (name == "StorePath") {
if (!isStorePath(value)) corrupt(); if (!store.isStorePath(value)) corrupt();
path = value; path = value;
} }
else if (name == "URL") else if (name == "URL")
@ -53,14 +53,14 @@ NarInfo::NarInfo(const std::string & s, const std::string & whence)
auto refs = tokenizeString<Strings>(value, " "); auto refs = tokenizeString<Strings>(value, " ");
if (!references.empty()) corrupt(); if (!references.empty()) corrupt();
for (auto & r : refs) { for (auto & r : refs) {
auto r2 = settings.nixStore + "/" + r; auto r2 = store.storeDir + "/" + r;
if (!isStorePath(r2)) corrupt(); if (!store.isStorePath(r2)) corrupt();
references.insert(r2); references.insert(r2);
} }
} }
else if (name == "Deriver") { else if (name == "Deriver") {
auto p = settings.nixStore + "/" + value; auto p = store.storeDir + "/" + value;
if (!isStorePath(p)) corrupt(); if (!store.isStorePath(p)) corrupt();
deriver = p; deriver = p;
} }
else if (name == "System") else if (name == "System")

View file

@ -16,7 +16,7 @@ struct NarInfo : ValidPathInfo
NarInfo() { } NarInfo() { }
NarInfo(const ValidPathInfo & info) : ValidPathInfo(info) { } NarInfo(const ValidPathInfo & info) : ValidPathInfo(info) { }
NarInfo(const std::string & s, const std::string & whence); NarInfo(const Store & store, const std::string & s, const std::string & whence);
std::string to_string() const; std::string to_string() const;
}; };

View file

@ -184,7 +184,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : ""); MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : "");
Path tempLink = (format("%1%/.tmp-link-%2%-%3%") Path tempLink = (format("%1%/.tmp-link-%2%-%3%")
% settings.nixStore % getpid() % rand()).str(); % storeDir % getpid() % rand()).str();
if (link(linkPath.c_str(), tempLink.c_str()) == -1) { if (link(linkPath.c_str(), tempLink.c_str()) == -1) {
if (errno == EMLINK) { if (errno == EMLINK) {

View file

@ -21,26 +21,27 @@
namespace nix { namespace nix {
Path readStorePath(Source & from) Path readStorePath(Store & store, Source & from)
{ {
Path path = readString(from); Path path = readString(from);
assertStorePath(path); store.assertStorePath(path);
return path; return path;
} }
template<class T> T readStorePaths(Source & from) template<class T> T readStorePaths(Store & store, Source & from)
{ {
T paths = readStrings<T>(from); T paths = readStrings<T>(from);
for (auto & i : paths) assertStorePath(i); for (auto & i : paths) store.assertStorePath(i);
return paths; return paths;
} }
template PathSet readStorePaths(Source & from); template PathSet readStorePaths(Store & store, Source & from);
RemoteStore::RemoteStore(size_t maxConnections) RemoteStore::RemoteStore(const Params & params, size_t maxConnections)
: connections(make_ref<Pool<Connection>>( : LocalFSStore(params)
, connections(make_ref<Pool<Connection>>(
maxConnections, maxConnections,
[this]() { return openConnection(); }, [this]() { return openConnection(); },
[](const ref<Connection> & r) { return r->to.good() && r->from.good(); } [](const ref<Connection> & r) { return r->to.good() && r->from.good(); }
@ -168,7 +169,7 @@ PathSet RemoteStore::queryValidPaths(const PathSet & paths)
} else { } else {
conn->to << wopQueryValidPaths << paths; conn->to << wopQueryValidPaths << paths;
conn->processStderr(); conn->processStderr();
return readStorePaths<PathSet>(conn->from); return readStorePaths<PathSet>(*this, conn->from);
} }
} }
@ -178,7 +179,7 @@ PathSet RemoteStore::queryAllValidPaths()
auto conn(connections->get()); auto conn(connections->get());
conn->to << wopQueryAllValidPaths; conn->to << wopQueryAllValidPaths;
conn->processStderr(); conn->processStderr();
return readStorePaths<PathSet>(conn->from); return readStorePaths<PathSet>(*this, conn->from);
} }
@ -196,7 +197,7 @@ PathSet RemoteStore::querySubstitutablePaths(const PathSet & paths)
} else { } else {
conn->to << wopQuerySubstitutablePaths << paths; conn->to << wopQuerySubstitutablePaths << paths;
conn->processStderr(); conn->processStderr();
return readStorePaths<PathSet>(conn->from); return readStorePaths<PathSet>(*this, conn->from);
} }
} }
@ -220,7 +221,7 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
if (reply == 0) continue; if (reply == 0) continue;
info.deriver = readString(conn->from); info.deriver = readString(conn->from);
if (info.deriver != "") assertStorePath(info.deriver); if (info.deriver != "") assertStorePath(info.deriver);
info.references = readStorePaths<PathSet>(conn->from); info.references = readStorePaths<PathSet>(*this, conn->from);
info.downloadSize = readLongLong(conn->from); info.downloadSize = readLongLong(conn->from);
info.narSize = GET_PROTOCOL_MINOR(conn->daemonVersion) >= 7 ? readLongLong(conn->from) : 0; info.narSize = GET_PROTOCOL_MINOR(conn->daemonVersion) >= 7 ? readLongLong(conn->from) : 0;
infos[i] = info; infos[i] = info;
@ -232,11 +233,11 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
conn->processStderr(); conn->processStderr();
unsigned int count = readInt(conn->from); unsigned int count = readInt(conn->from);
for (unsigned int n = 0; n < count; n++) { for (unsigned int n = 0; n < count; n++) {
Path path = readStorePath(conn->from); Path path = readStorePath(*this, conn->from);
SubstitutablePathInfo & info(infos[path]); SubstitutablePathInfo & info(infos[path]);
info.deriver = readString(conn->from); info.deriver = readString(conn->from);
if (info.deriver != "") assertStorePath(info.deriver); if (info.deriver != "") assertStorePath(info.deriver);
info.references = readStorePaths<PathSet>(conn->from); info.references = readStorePaths<PathSet>(*this, conn->from);
info.downloadSize = readLongLong(conn->from); info.downloadSize = readLongLong(conn->from);
info.narSize = readLongLong(conn->from); info.narSize = readLongLong(conn->from);
} }
@ -266,7 +267,7 @@ std::shared_ptr<ValidPathInfo> RemoteStore::queryPathInfoUncached(const Path & p
info->deriver = readString(conn->from); info->deriver = readString(conn->from);
if (info->deriver != "") assertStorePath(info->deriver); if (info->deriver != "") assertStorePath(info->deriver);
info->narHash = parseHash(htSHA256, readString(conn->from)); info->narHash = parseHash(htSHA256, readString(conn->from));
info->references = readStorePaths<PathSet>(conn->from); info->references = readStorePaths<PathSet>(*this, conn->from);
info->registrationTime = readInt(conn->from); info->registrationTime = readInt(conn->from);
info->narSize = readLongLong(conn->from); info->narSize = readLongLong(conn->from);
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 16) { if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 16) {
@ -283,7 +284,7 @@ void RemoteStore::queryReferrers(const Path & path,
auto conn(connections->get()); auto conn(connections->get());
conn->to << wopQueryReferrers << path; conn->to << wopQueryReferrers << path;
conn->processStderr(); conn->processStderr();
PathSet referrers2 = readStorePaths<PathSet>(conn->from); PathSet referrers2 = readStorePaths<PathSet>(*this, conn->from);
referrers.insert(referrers2.begin(), referrers2.end()); referrers.insert(referrers2.begin(), referrers2.end());
} }
@ -293,7 +294,7 @@ PathSet RemoteStore::queryValidDerivers(const Path & path)
auto conn(connections->get()); auto conn(connections->get());
conn->to << wopQueryValidDerivers << path; conn->to << wopQueryValidDerivers << path;
conn->processStderr(); conn->processStderr();
return readStorePaths<PathSet>(conn->from); return readStorePaths<PathSet>(*this, conn->from);
} }
@ -302,7 +303,7 @@ PathSet RemoteStore::queryDerivationOutputs(const Path & path)
auto conn(connections->get()); auto conn(connections->get());
conn->to << wopQueryDerivationOutputs << path; conn->to << wopQueryDerivationOutputs << path;
conn->processStderr(); conn->processStderr();
return readStorePaths<PathSet>(conn->from); return readStorePaths<PathSet>(*this, conn->from);
} }
@ -363,7 +364,7 @@ Path RemoteStore::addToStore(const string & name, const Path & _srcPath,
throw; throw;
} }
return readStorePath(conn->from); return readStorePath(*this, conn->from);
} }
@ -376,7 +377,7 @@ Path RemoteStore::addTextToStore(const string & name, const string & s,
conn->to << wopAddTextToStore << name << s << references; conn->to << wopAddTextToStore << name << s << references;
conn->processStderr(); conn->processStderr();
return readStorePath(conn->from); return readStorePath(*this, conn->from);
} }
@ -465,7 +466,7 @@ Roots RemoteStore::findRoots()
Roots result; Roots result;
while (count--) { while (count--) {
Path link = readString(conn->from); Path link = readString(conn->from);
Path target = readStorePath(conn->from); Path target = readStorePath(*this, conn->from);
result[link] = target; result[link] = target;
} }
return result; return result;

View file

@ -22,7 +22,7 @@ class RemoteStore : public LocalFSStore
{ {
public: public:
RemoteStore(size_t maxConnections = std::numeric_limits<size_t>::max()); RemoteStore(const Params & params, size_t maxConnections = std::numeric_limits<size_t>::max());
/* Implementations of abstract store API methods. */ /* Implementations of abstract store API methods. */

View file

@ -47,7 +47,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
Stats stats; Stats stats;
S3BinaryCacheStoreImpl( S3BinaryCacheStoreImpl(
const StoreParams & params, const std::string & bucketName) const Params & params, const std::string & bucketName)
: S3BinaryCacheStore(params) : S3BinaryCacheStore(params)
, bucketName(bucketName) , bucketName(bucketName)
, config(makeConfig()) , config(makeConfig())
@ -95,7 +95,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
BinaryCacheStore::init(); BinaryCacheStore::init();
diskCache->createCache(getUri(), wantMassQuery_, priority); diskCache->createCache(getUri(), storeDir, wantMassQuery_, priority);
} }
} }
@ -232,7 +232,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
for (auto object : contents) { for (auto object : contents) {
auto & key = object.GetKey(); auto & key = object.GetKey();
if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue; if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue;
paths.insert(settings.nixStore + "/" + key.substr(0, key.size() - 8)); paths.insert(storeDir + "/" + key.substr(0, key.size() - 8));
} }
marker = res.GetNextMarker(); marker = res.GetNextMarker();
@ -244,7 +244,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
}; };
static RegisterStoreImplementation regStore([]( static RegisterStoreImplementation regStore([](
const std::string & uri, const StoreParams & params) const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store> -> std::shared_ptr<Store>
{ {
if (std::string(uri, 0, 5) != "s3://") return 0; if (std::string(uri, 0, 5) != "s3://") return 0;

View file

@ -10,7 +10,7 @@ class S3BinaryCacheStore : public BinaryCacheStore
{ {
protected: protected:
S3BinaryCacheStore(const StoreParams & params) S3BinaryCacheStore(const Params & params)
: BinaryCacheStore(params) : BinaryCacheStore(params)
{ } { }

View file

@ -8,32 +8,32 @@
namespace nix { namespace nix {
bool isInStore(const Path & path) bool Store::isInStore(const Path & path) const
{ {
return isInDir(path, settings.nixStore); return isInDir(path, storeDir);
} }
bool isStorePath(const Path & path) bool Store::isStorePath(const Path & path) const
{ {
return isInStore(path) return isInStore(path)
&& path.size() >= settings.nixStore.size() + 1 + storePathHashLen && path.size() >= storeDir.size() + 1 + storePathHashLen
&& path.find('/', settings.nixStore.size() + 1) == Path::npos; && path.find('/', storeDir.size() + 1) == Path::npos;
} }
void assertStorePath(const Path & path) void Store::assertStorePath(const Path & path) const
{ {
if (!isStorePath(path)) if (!isStorePath(path))
throw Error(format("path %1% is not in the Nix store") % path); throw Error(format("path %1% is not in the Nix store") % path);
} }
Path toStorePath(const Path & path) Path Store::toStorePath(const Path & path) const
{ {
if (!isInStore(path)) if (!isInStore(path))
throw Error(format("path %1% is not in the Nix store") % path); throw Error(format("path %1% is not in the Nix store") % path);
Path::size_type slash = path.find('/', settings.nixStore.size() + 1); Path::size_type slash = path.find('/', storeDir.size() + 1);
if (slash == Path::npos) if (slash == Path::npos)
return path; return path;
else else
@ -41,7 +41,7 @@ Path toStorePath(const Path & path)
} }
Path followLinksToStore(const Path & _path) Path Store::followLinksToStore(const Path & _path) const
{ {
Path path = absPath(_path); Path path = absPath(_path);
while (!isInStore(path)) { while (!isInStore(path)) {
@ -55,7 +55,7 @@ Path followLinksToStore(const Path & _path)
} }
Path followLinksToStorePath(const Path & path) Path Store::followLinksToStorePath(const Path & path) const
{ {
return toStorePath(followLinksToStore(path)); return toStorePath(followLinksToStore(path));
} }
@ -63,18 +63,17 @@ Path followLinksToStorePath(const Path & path)
string storePathToName(const Path & path) string storePathToName(const Path & path)
{ {
assertStorePath(path); auto base = baseNameOf(path);
auto l = settings.nixStore.size() + 1 + storePathHashLen; assert(base.size() == storePathHashLen || (base.size() > storePathHashLen && base[storePathHashLen] == '-'));
assert(path.size() >= l); return base.size() == storePathHashLen ? "" : string(base, storePathHashLen + 1);
return path.size() == l ? "" : string(path, l + 1);
} }
string storePathToHash(const Path & path) string storePathToHash(const Path & path)
{ {
assertStorePath(path); auto base = baseNameOf(path);
assert(path.size() >= settings.nixStore.size() + 1 + storePathHashLen); assert(base.size() >= storePathHashLen);
return string(path, settings.nixStore.size() + 1, storePathHashLen); return string(base, 0, storePathHashLen);
} }
@ -168,31 +167,31 @@ void checkStoreName(const string & name)
*/ */
Path makeStorePath(const string & type, Path Store::makeStorePath(const string & type,
const Hash & hash, const string & name) const Hash & hash, const string & name) const
{ {
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
string s = type + ":sha256:" + printHash(hash) + ":" string s = type + ":sha256:" + printHash(hash) + ":"
+ settings.nixStore + ":" + name; + storeDir + ":" + name;
checkStoreName(name); checkStoreName(name);
return settings.nixStore + "/" return storeDir + "/"
+ printHash32(compressHash(hashString(htSHA256, s), 20)) + printHash32(compressHash(hashString(htSHA256, s), 20))
+ "-" + name; + "-" + name;
} }
Path makeOutputPath(const string & id, Path Store::makeOutputPath(const string & id,
const Hash & hash, const string & name) const Hash & hash, const string & name) const
{ {
return makeStorePath("output:" + id, hash, return makeStorePath("output:" + id, hash,
name + (id == "out" ? "" : "-" + id)); name + (id == "out" ? "" : "-" + id));
} }
Path makeFixedOutputPath(bool recursive, Path Store::makeFixedOutputPath(bool recursive,
HashType hashAlgo, Hash hash, string name) HashType hashAlgo, Hash hash, string name) const
{ {
return hashAlgo == htSHA256 && recursive return hashAlgo == htSHA256 && recursive
? makeStorePath("source", hash, name) ? makeStorePath("source", hash, name)
@ -203,8 +202,8 @@ Path makeFixedOutputPath(bool recursive,
} }
std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath, std::pair<Path, Hash> Store::computeStorePathForPath(const Path & srcPath,
bool recursive, HashType hashAlgo, PathFilter & filter) bool recursive, HashType hashAlgo, PathFilter & filter) const
{ {
HashType ht(hashAlgo); HashType ht(hashAlgo);
Hash h = recursive ? hashPath(ht, srcPath, filter).first : hashFile(ht, srcPath); Hash h = recursive ? hashPath(ht, srcPath, filter).first : hashFile(ht, srcPath);
@ -214,8 +213,8 @@ std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
} }
Path computeStorePathForText(const string & name, const string & s, Path Store::computeStorePathForText(const string & name, const string & s,
const PathSet & references) const PathSet & references) const
{ {
Hash hash = hashString(htSHA256, s); Hash hash = hashString(htSHA256, s);
/* Stuff the references (if any) into the type. This is a bit /* Stuff the references (if any) into the type. This is a bit
@ -230,6 +229,12 @@ Path computeStorePathForText(const string & name, const string & s,
} }
Store::Store(const Params & params)
: storeDir(settings.nixStore)
{
}
std::string Store::getUri() std::string Store::getUri()
{ {
return ""; return "";
@ -465,7 +470,7 @@ RegisterStoreImplementation::Implementations * RegisterStoreImplementation::impl
ref<Store> openStoreAt(const std::string & uri_) ref<Store> openStoreAt(const std::string & uri_)
{ {
auto uri(uri_); auto uri(uri_);
StoreParams params; Store::Params params;
auto q = uri.find('?'); auto q = uri.find('?');
if (q != std::string::npos) { if (q != std::string::npos) {
for (auto s : tokenizeString<Strings>(uri.substr(q + 1), "&")) { for (auto s : tokenizeString<Strings>(uri.substr(q + 1), "&")) {
@ -492,7 +497,7 @@ ref<Store> openStore()
static RegisterStoreImplementation regStore([]( static RegisterStoreImplementation regStore([](
const std::string & uri, const StoreParams & params) const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store> -> std::shared_ptr<Store>
{ {
enum { mDaemon, mLocal, mAuto } mode; enum { mDaemon, mLocal, mAuto } mode;
@ -512,8 +517,8 @@ static RegisterStoreImplementation regStore([](
} }
return mode == mDaemon return mode == mDaemon
? std::shared_ptr<Store>(std::make_shared<RemoteStore>()) ? std::shared_ptr<Store>(std::make_shared<RemoteStore>(params))
: std::shared_ptr<Store>(std::make_shared<LocalStore>()); : std::shared_ptr<Store>(std::make_shared<LocalStore>(params));
}); });

View file

@ -177,6 +177,12 @@ class NarInfoDiskCache;
class Store : public std::enable_shared_from_this<Store> class Store : public std::enable_shared_from_this<Store>
{ {
public:
typedef std::map<std::string, std::string> Params;
const Path storeDir;
protected: protected:
struct State struct State
@ -188,12 +194,71 @@ protected:
std::shared_ptr<NarInfoDiskCache> diskCache; std::shared_ptr<NarInfoDiskCache> diskCache;
Store(const Params & params);
public: public:
virtual ~Store() { } virtual ~Store() { }
virtual std::string getUri() = 0; virtual std::string getUri() = 0;
/* Return true if path is in the Nix store (but not the Nix
store itself). */
bool isInStore(const Path & path) const;
/* Return true if path is a store path, i.e. a direct child of
the Nix store. */
bool isStorePath(const Path & path) const;
/* Throw an exception if path is not a store path. */
void assertStorePath(const Path & path) const;
/* Chop off the parts after the top-level store name, e.g.,
/nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
Path toStorePath(const Path & path) const;
/* Follow symlinks until we end up with a path in the Nix store. */
Path followLinksToStore(const Path & path) const;
/* Same as followLinksToStore(), but apply toStorePath() to the
result. */
Path followLinksToStorePath(const Path & path) const;
/* Constructs a unique store path name. */
Path makeStorePath(const string & type,
const Hash & hash, const string & name) const;
Path makeOutputPath(const string & id,
const Hash & hash, const string & name) const;
Path makeFixedOutputPath(bool recursive,
HashType hashAlgo, Hash hash, string name) const;
/* This is the preparatory part of addToStore() and
addToStoreFixed(); it computes the store path to which srcPath
is to be copied. Returns the store path and the cryptographic
hash of the contents of srcPath. */
std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
bool recursive = true, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter) const;
/* Preparatory part of addTextToStore().
!!! Computation of the path should take the references given to
addTextToStore() into account, otherwise we have a (relatively
minor) security hole: a caller can register a source file with
bogus references. If there are too many references, the path may
not be garbage collected when it has to be (not really a problem,
the caller could create a root anyway), or it may be garbage
collected when it shouldn't be (more serious).
Hashing the references would solve this (bogus references would
simply yield a different store path, so other users wouldn't be
affected), but it has some backwards compatibility issues (the
hashing scheme changes), so I'm not doing that for now. */
Path computeStorePathForText(const string & name, const string & s,
const PathSet & references) const;
/* Check whether a path is valid. */ /* Check whether a path is valid. */
bool isValidPath(const Path & path); bool isValidPath(const Path & path);
@ -429,80 +494,26 @@ protected:
class LocalFSStore : public Store class LocalFSStore : public Store
{ {
protected:
using Store::Store;
public: public:
void narFromPath(const Path & path, Sink & sink) override; void narFromPath(const Path & path, Sink & sink) override;
ref<FSAccessor> getFSAccessor() override; ref<FSAccessor> getFSAccessor() override;
}; };
/* !!! These should be part of the store API, I guess. */
/* Throw an exception if `path' is not directly in the Nix store. */
void assertStorePath(const Path & path);
bool isInStore(const Path & path);
bool isStorePath(const Path & path);
/* Extract the name part of the given store path. */ /* Extract the name part of the given store path. */
string storePathToName(const Path & path); string storePathToName(const Path & path);
/* Extract the hash part of the given store path. */ /* Extract the hash part of the given store path. */
string storePathToHash(const Path & path); string storePathToHash(const Path & path);
/* Check whether name is a valid store path name part, i.e. contains
only the characters [a-zA-Z0-9\+\-\.\_\?\=] and doesn't start with
a dot. */
void checkStoreName(const string & name); void checkStoreName(const string & name);
/* Chop off the parts after the top-level store name, e.g.,
/nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
Path toStorePath(const Path & path);
/* Follow symlinks until we end up with a path in the Nix store. */
Path followLinksToStore(const Path & path);
/* Same as followLinksToStore(), but apply toStorePath() to the
result. */
Path followLinksToStorePath(const Path & path);
/* Constructs a unique store path name. */
Path makeStorePath(const string & type,
const Hash & hash, const string & name);
Path makeOutputPath(const string & id,
const Hash & hash, const string & name);
Path makeFixedOutputPath(bool recursive,
HashType hashAlgo, Hash hash, string name);
/* This is the preparatory part of addToStore() and addToStoreFixed();
it computes the store path to which srcPath is to be copied.
Returns the store path and the cryptographic hash of the
contents of srcPath. */
std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
bool recursive = true, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter);
/* Preparatory part of addTextToStore().
!!! Computation of the path should take the references given to
addTextToStore() into account, otherwise we have a (relatively
minor) security hole: a caller can register a source file with
bogus references. If there are too many references, the path may
not be garbage collected when it has to be (not really a problem,
the caller could create a root anyway), or it may be garbage
collected when it shouldn't be (more serious).
Hashing the references would solve this (bogus references would
simply yield a different store path, so other users wouldn't be
affected), but it has some backwards compatibility issues (the
hashing scheme changes), so I'm not doing that for now. */
Path computeStorePathForText(const string & name, const string & s,
const PathSet & references);
/* Copy a path from one store to another. */ /* Copy a path from one store to another. */
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore, void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
const Path & storePath, bool repair = false); const Path & storePath, bool repair = false);
@ -542,10 +553,8 @@ std::list<ref<Store>> getDefaultSubstituters();
/* Store implementation registration. */ /* Store implementation registration. */
typedef std::map<std::string, std::string> StoreParams;
typedef std::function<std::shared_ptr<Store>( typedef std::function<std::shared_ptr<Store>(
const std::string & uri, const StoreParams & params)> OpenStore; const std::string & uri, const Store::Params & params)> OpenStore;
struct RegisterStoreImplementation struct RegisterStoreImplementation
{ {

View file

@ -56,8 +56,8 @@ typedef enum {
#define STDERR_ERROR 0x63787470 #define STDERR_ERROR 0x63787470
Path readStorePath(Source & from); Path readStorePath(Store & store, Source & from);
template<class T> T readStorePaths(Source & from); template<class T> T readStorePaths(Store & store, Source & from);
} }

View file

@ -176,7 +176,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
connection. */ connection. */
Path path = readString(from); Path path = readString(from);
startWork(); startWork();
assertStorePath(path); store->assertStorePath(path);
bool result = store->isValidPath(path); bool result = store->isValidPath(path);
stopWork(); stopWork();
to << result; to << result;
@ -184,7 +184,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopQueryValidPaths: { case wopQueryValidPaths: {
PathSet paths = readStorePaths<PathSet>(from); PathSet paths = readStorePaths<PathSet>(*store, from);
startWork(); startWork();
PathSet res = store->queryValidPaths(paths); PathSet res = store->queryValidPaths(paths);
stopWork(); stopWork();
@ -193,7 +193,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopHasSubstitutes: { case wopHasSubstitutes: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
startWork(); startWork();
PathSet res = store->querySubstitutablePaths({path}); PathSet res = store->querySubstitutablePaths({path});
stopWork(); stopWork();
@ -202,7 +202,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopQuerySubstitutablePaths: { case wopQuerySubstitutablePaths: {
PathSet paths = readStorePaths<PathSet>(from); PathSet paths = readStorePaths<PathSet>(*store, from);
startWork(); startWork();
PathSet res = store->querySubstitutablePaths(paths); PathSet res = store->querySubstitutablePaths(paths);
stopWork(); stopWork();
@ -211,7 +211,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopQueryPathHash: { case wopQueryPathHash: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
startWork(); startWork();
auto hash = store->queryPathInfo(path)->narHash; auto hash = store->queryPathInfo(path)->narHash;
stopWork(); stopWork();
@ -223,7 +223,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
case wopQueryReferrers: case wopQueryReferrers:
case wopQueryValidDerivers: case wopQueryValidDerivers:
case wopQueryDerivationOutputs: { case wopQueryDerivationOutputs: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
startWork(); startWork();
PathSet paths; PathSet paths;
if (op == wopQueryReferences) if (op == wopQueryReferences)
@ -239,7 +239,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopQueryDerivationOutputNames: { case wopQueryDerivationOutputNames: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
startWork(); startWork();
StringSet names; StringSet names;
names = store->queryDerivationOutputNames(path); names = store->queryDerivationOutputNames(path);
@ -249,7 +249,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopQueryDeriver: { case wopQueryDeriver: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
startWork(); startWork();
auto deriver = store->queryPathInfo(path)->deriver; auto deriver = store->queryPathInfo(path)->deriver;
stopWork(); stopWork();
@ -302,7 +302,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
case wopAddTextToStore: { case wopAddTextToStore: {
string suffix = readString(from); string suffix = readString(from);
string s = readString(from); string s = readString(from);
PathSet refs = readStorePaths<PathSet>(from); PathSet refs = readStorePaths<PathSet>(*store, from);
startWork(); startWork();
Path path = store->addTextToStore(suffix, s, refs); Path path = store->addTextToStore(suffix, s, refs);
stopWork(); stopWork();
@ -311,7 +311,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopExportPath: { case wopExportPath: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
readInt(from); // obsolete readInt(from); // obsolete
startWork(); startWork();
TunnelSink sink(to); TunnelSink sink(to);
@ -331,7 +331,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopBuildPaths: { case wopBuildPaths: {
PathSet drvs = readStorePaths<PathSet>(from); PathSet drvs = readStorePaths<PathSet>(*store, from);
BuildMode mode = bmNormal; BuildMode mode = bmNormal;
if (GET_PROTOCOL_MINOR(clientVersion) >= 15) { if (GET_PROTOCOL_MINOR(clientVersion) >= 15) {
mode = (BuildMode)readInt(from); mode = (BuildMode)readInt(from);
@ -349,9 +349,9 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopBuildDerivation: { case wopBuildDerivation: {
Path drvPath = readStorePath(from); Path drvPath = readStorePath(*store, from);
BasicDerivation drv; BasicDerivation drv;
from >> drv; readDerivation(from, *store, drv);
BuildMode buildMode = (BuildMode) readInt(from); BuildMode buildMode = (BuildMode) readInt(from);
startWork(); startWork();
if (!trusted) if (!trusted)
@ -363,7 +363,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopEnsurePath: { case wopEnsurePath: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
startWork(); startWork();
store->ensurePath(path); store->ensurePath(path);
stopWork(); stopWork();
@ -372,7 +372,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopAddTempRoot: { case wopAddTempRoot: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
startWork(); startWork();
store->addTempRoot(path); store->addTempRoot(path);
stopWork(); stopWork();
@ -410,7 +410,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
case wopCollectGarbage: { case wopCollectGarbage: {
GCOptions options; GCOptions options;
options.action = (GCOptions::GCAction) readInt(from); options.action = (GCOptions::GCAction) readInt(from);
options.pathsToDelete = readStorePaths<PathSet>(from); options.pathsToDelete = readStorePaths<PathSet>(*store, from);
options.ignoreLiveness = readInt(from); options.ignoreLiveness = readInt(from);
options.maxFreed = readLongLong(from); options.maxFreed = readLongLong(from);
readInt(from); // obsolete field readInt(from); // obsolete field
@ -486,7 +486,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopQuerySubstitutablePathInfos: { case wopQuerySubstitutablePathInfos: {
PathSet paths = readStorePaths<PathSet>(from); PathSet paths = readStorePaths<PathSet>(*store, from);
startWork(); startWork();
SubstitutablePathInfos infos; SubstitutablePathInfos infos;
store->querySubstitutablePathInfos(paths, infos); store->querySubstitutablePathInfos(paths, infos);
@ -508,7 +508,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopQueryPathInfo: { case wopQueryPathInfo: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
std::shared_ptr<const ValidPathInfo> info; std::shared_ptr<const ValidPathInfo> info;
startWork(); startWork();
try { try {
@ -553,7 +553,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
} }
case wopAddSignatures: { case wopAddSignatures: {
Path path = readStorePath(from); Path path = readStorePath(*store, from);
StringSet sigs = readStrings<StringSet>(from); StringSet sigs = readStrings<StringSet>(from);
startWork(); startWork();
if (!trusted) if (!trusted)
@ -607,7 +607,7 @@ static void processConnection(bool trusted)
#endif #endif
/* Open the store. */ /* Open the store. */
auto store = make_ref<LocalStore>(); auto store = make_ref<LocalStore>(Store::Params()); // FIXME: get params from somewhere
stopWork(); stopWork();
to.flush(); to.flush();

View file

@ -387,7 +387,7 @@ static void queryInstSources(EvalState & state,
case srcStorePaths: { case srcStorePaths: {
for (auto & i : args) { for (auto & i : args) {
Path path = followLinksToStorePath(i); Path path = state.store->followLinksToStorePath(i);
string name = baseNameOf(path); string name = baseNameOf(path);
string::size_type dash = name.find('-'); string::size_type dash = name.find('-');
@ -742,7 +742,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
for (auto & j : selectors) for (auto & j : selectors)
/* !!! the repeated calls to followLinksToStorePath() /* !!! the repeated calls to followLinksToStorePath()
are expensive, should pre-compute them. */ are expensive, should pre-compute them. */
if ((isPath(j) && i.queryOutPath() == followLinksToStorePath(j)) if ((isPath(j) && i.queryOutPath() == globals.state->store->followLinksToStorePath(j))
|| DrvName(j).matches(drvName)) || DrvName(j).matches(drvName))
{ {
printMsg(lvlInfo, format("uninstalling %1%") % i.name); printMsg(lvlInfo, format("uninstalling %1%") % i.name);

View file

@ -146,7 +146,7 @@ int main(int argc, char * * argv)
Path storePath; Path storePath;
if (args.size() == 2) { if (args.size() == 2) {
expectedHash = parseHash16or32(ht, args[1]); expectedHash = parseHash16or32(ht, args[1]);
storePath = makeFixedOutputPath(unpack, ht, expectedHash, name); storePath = store->makeFixedOutputPath(unpack, ht, expectedHash, name);
if (store->isValidPath(storePath)) if (store->isValidPath(storePath))
hash = expectedHash; hash = expectedHash;
else else
@ -197,7 +197,7 @@ int main(int argc, char * * argv)
into the Nix store. */ into the Nix store. */
storePath = store->addToStore(name, tmpFile, unpack, ht); storePath = store->addToStore(name, tmpFile, unpack, ht);
assert(storePath == makeFixedOutputPath(unpack, ht, hash, name)); assert(storePath == store->makeFixedOutputPath(unpack, ht, hash, name));
} }
if (!printPath) if (!printPath)

View file

@ -124,7 +124,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
Paths paths; Paths paths;
for (auto & i : opArgs) { for (auto & i : opArgs) {
DrvPathWithOutputs p = parseDrvPathWithOutputs(i); DrvPathWithOutputs p = parseDrvPathWithOutputs(i);
paths.push_back(makeDrvPathWithOutputs(followLinksToStorePath(p.first), p.second)); paths.push_back(makeDrvPathWithOutputs(store->followLinksToStorePath(p.first), p.second));
} }
unsigned long long downloadSize, narSize; unsigned long long downloadSize, narSize;
@ -207,7 +207,7 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs)
string name = *i++; string name = *i++;
cout << format("%1%\n") % cout << format("%1%\n") %
makeFixedOutputPath(recursive, hashAlgo, store->makeFixedOutputPath(recursive, hashAlgo,
parseHash16or32(hashAlgo, hash), name); parseHash16or32(hashAlgo, hash), name);
} }
@ -315,7 +315,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qOutputs: { case qOutputs: {
for (auto & i : opArgs) { for (auto & i : opArgs) {
i = followLinksToStorePath(i); i = store->followLinksToStorePath(i);
if (forceRealise) realisePath(i); if (forceRealise) realisePath(i);
Derivation drv = store->derivationFromPath(i); Derivation drv = store->derivationFromPath(i);
for (auto & j : drv.outputs) for (auto & j : drv.outputs)
@ -330,7 +330,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qReferrersClosure: { case qReferrersClosure: {
PathSet paths; PathSet paths;
for (auto & i : opArgs) { for (auto & i : opArgs) {
PathSet ps = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise); PathSet ps = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
for (auto & j : ps) { for (auto & j : ps) {
if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs); if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs);
else if (query == qReferences) { else if (query == qReferences) {
@ -350,7 +350,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qDeriver: case qDeriver:
for (auto & i : opArgs) { for (auto & i : opArgs) {
Path deriver = store->queryPathInfo(followLinksToStorePath(i))->deriver; Path deriver = store->queryPathInfo(store->followLinksToStorePath(i))->deriver;
cout << format("%1%\n") % cout << format("%1%\n") %
(deriver == "" ? "unknown-deriver" : deriver); (deriver == "" ? "unknown-deriver" : deriver);
} }
@ -358,7 +358,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qBinding: case qBinding:
for (auto & i : opArgs) { for (auto & i : opArgs) {
Path path = useDeriver(followLinksToStorePath(i)); Path path = useDeriver(store->followLinksToStorePath(i));
Derivation drv = store->derivationFromPath(path); Derivation drv = store->derivationFromPath(path);
StringPairs::iterator j = drv.env.find(bindingName); StringPairs::iterator j = drv.env.find(bindingName);
if (j == drv.env.end()) if (j == drv.env.end())
@ -371,7 +371,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qHash: case qHash:
case qSize: case qSize:
for (auto & i : opArgs) { for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise); PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
for (auto & j : paths) { for (auto & j : paths) {
auto info = store->queryPathInfo(j); auto info = store->queryPathInfo(j);
if (query == qHash) { if (query == qHash) {
@ -386,14 +386,14 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qTree: { case qTree: {
PathSet done; PathSet done;
for (auto & i : opArgs) for (auto & i : opArgs)
printTree(followLinksToStorePath(i), "", "", done); printTree(store->followLinksToStorePath(i), "", "", done);
break; break;
} }
case qGraph: { case qGraph: {
PathSet roots; PathSet roots;
for (auto & i : opArgs) { for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise); PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end()); roots.insert(paths.begin(), paths.end());
} }
printDotGraph(ref<Store>(store), roots); printDotGraph(ref<Store>(store), roots);
@ -403,7 +403,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qXml: { case qXml: {
PathSet roots; PathSet roots;
for (auto & i : opArgs) { for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise); PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end()); roots.insert(paths.begin(), paths.end());
} }
printXmlGraph(ref<Store>(store), roots); printXmlGraph(ref<Store>(store), roots);
@ -412,14 +412,14 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qResolve: { case qResolve: {
for (auto & i : opArgs) for (auto & i : opArgs)
cout << format("%1%\n") % followLinksToStorePath(i); cout << format("%1%\n") % store->followLinksToStorePath(i);
break; break;
} }
case qRoots: { case qRoots: {
PathSet referrers; PathSet referrers;
for (auto & i : opArgs) { for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise); PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
for (auto & j : paths) for (auto & j : paths)
store->computeFSClosure(j, referrers, true, store->computeFSClosure(j, referrers, true,
settings.gcKeepOutputs, settings.gcKeepDerivations); settings.gcKeepOutputs, settings.gcKeepDerivations);
@ -479,7 +479,7 @@ static void opReadLog(Strings opFlags, Strings opArgs)
RunPager pager; RunPager pager;
for (auto & i : opArgs) { for (auto & i : opArgs) {
Path path = useDeriver(followLinksToStorePath(i)); Path path = useDeriver(store->followLinksToStorePath(i));
string baseName = baseNameOf(path); string baseName = baseNameOf(path);
bool found = false; bool found = false;
@ -599,7 +599,7 @@ static void opCheckValidity(Strings opFlags, Strings opArgs)
else throw UsageError(format("unknown flag %1%") % i); else throw UsageError(format("unknown flag %1%") % i);
for (auto & i : opArgs) { for (auto & i : opArgs) {
Path path = followLinksToStorePath(i); Path path = store->followLinksToStorePath(i);
if (!store->isValidPath(path)) { if (!store->isValidPath(path)) {
if (printInvalid) if (printInvalid)
cout << format("%1%\n") % path; cout << format("%1%\n") % path;
@ -662,7 +662,7 @@ static void opDelete(Strings opFlags, Strings opArgs)
else throw UsageError(format("unknown flag %1%") % i); else throw UsageError(format("unknown flag %1%") % i);
for (auto & i : opArgs) for (auto & i : opArgs)
options.pathsToDelete.insert(followLinksToStorePath(i)); options.pathsToDelete.insert(store->followLinksToStorePath(i));
GCResults results; GCResults results;
PrintFreed freed(true, results); PrintFreed freed(true, results);
@ -761,7 +761,7 @@ static void opVerifyPath(Strings opFlags, Strings opArgs)
int status = 0; int status = 0;
for (auto & i : opArgs) { for (auto & i : opArgs) {
Path path = followLinksToStorePath(i); Path path = store->followLinksToStorePath(i);
printMsg(lvlTalkative, format("checking path %1%...") % path); printMsg(lvlTalkative, format("checking path %1%...") % path);
auto info = store->queryPathInfo(path); auto info = store->queryPathInfo(path);
HashSink sink(info->narHash.type); HashSink sink(info->narHash.type);
@ -787,7 +787,7 @@ static void opRepairPath(Strings opFlags, Strings opArgs)
throw UsageError("no flags expected"); throw UsageError("no flags expected");
for (auto & i : opArgs) { for (auto & i : opArgs) {
Path path = followLinksToStorePath(i); Path path = store->followLinksToStorePath(i);
ensureLocalStore()->repairPath(path); ensureLocalStore()->repairPath(path);
} }
} }
@ -847,7 +847,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdQueryValidPaths: { case cmdQueryValidPaths: {
bool lock = readInt(in); bool lock = readInt(in);
bool substitute = readInt(in); bool substitute = readInt(in);
PathSet paths = readStorePaths<PathSet>(in); PathSet paths = readStorePaths<PathSet>(*store, in);
if (lock && writeAllowed) if (lock && writeAllowed)
for (auto & path : paths) for (auto & path : paths)
store->addTempRoot(path); store->addTempRoot(path);
@ -879,7 +879,7 @@ static void opServe(Strings opFlags, Strings opArgs)
} }
case cmdQueryPathInfos: { case cmdQueryPathInfos: {
PathSet paths = readStorePaths<PathSet>(in); PathSet paths = readStorePaths<PathSet>(*store, in);
// !!! Maybe we want a queryPathInfos? // !!! Maybe we want a queryPathInfos?
for (auto & i : paths) { for (auto & i : paths) {
try { try {
@ -896,7 +896,7 @@ static void opServe(Strings opFlags, Strings opArgs)
} }
case cmdDumpStorePath: case cmdDumpStorePath:
dumpPath(readStorePath(in), out); dumpPath(readStorePath(*store, in), out);
break; break;
case cmdImportPaths: { case cmdImportPaths: {
@ -908,7 +908,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdExportPaths: { case cmdExportPaths: {
readInt(in); // obsolete readInt(in); // obsolete
Paths sorted = store->topoSortPaths(readStorePaths<PathSet>(in)); Paths sorted = store->topoSortPaths(readStorePaths<PathSet>(*store, in));
reverse(sorted.begin(), sorted.end()); reverse(sorted.begin(), sorted.end());
store->exportPaths(sorted, out); store->exportPaths(sorted, out);
break; break;
@ -917,7 +917,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdBuildPaths: { /* Used by build-remote.pl. */ case cmdBuildPaths: { /* Used by build-remote.pl. */
if (!writeAllowed) throw Error("building paths is not allowed"); if (!writeAllowed) throw Error("building paths is not allowed");
PathSet paths = readStorePaths<PathSet>(in); PathSet paths = readStorePaths<PathSet>(*store, in);
getBuildSettings(); getBuildSettings();
@ -936,9 +936,9 @@ static void opServe(Strings opFlags, Strings opArgs)
if (!writeAllowed) throw Error("building paths is not allowed"); if (!writeAllowed) throw Error("building paths is not allowed");
Path drvPath = readStorePath(in); // informational only Path drvPath = readStorePath(*store, in); // informational only
BasicDerivation drv; BasicDerivation drv;
in >> drv; readDerivation(in, *store, drv);
getBuildSettings(); getBuildSettings();
@ -952,7 +952,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdQueryClosure: { case cmdQueryClosure: {
bool includeOutputs = readInt(in); bool includeOutputs = readInt(in);
PathSet paths = readStorePaths<PathSet>(in); PathSet paths = readStorePaths<PathSet>(*store, in);
PathSet closure; PathSet closure;
for (auto & i : paths) for (auto & i : paths)
store->computeFSClosure(i, closure, false, includeOutputs); store->computeFSClosure(i, closure, false, includeOutputs);

View file

@ -102,7 +102,7 @@ void StorePathsCommand::run(ref<Store> store)
else { else {
for (auto & storePath : storePaths) for (auto & storePath : storePaths)
storePath = followLinksToStorePath(storePath); storePath = store->followLinksToStorePath(storePath);
if (recursive) { if (recursive) {
PathSet closure; PathSet closure;

View file

@ -17,7 +17,7 @@ UserEnvElems MixInstallables::evalInstallables(ref<Store> store)
if (std::string(installable, 0, 1) == "/") { if (std::string(installable, 0, 1) == "/") {
if (isStorePath(installable)) { if (store->isStorePath(installable)) {
if (isDerivation(installable)) { if (isDerivation(installable)) {
UserEnvElem elem; UserEnvElem elem;