about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/gc.cc34
-rw-r--r--src/libstore/local-fs-store.cc7
-rw-r--r--src/libstore/local-store.cc27
-rw-r--r--src/libstore/local-store.hh12
-rw-r--r--src/libstore/profiles.cc2
-rw-r--r--src/libstore/profiles.hh4
-rw-r--r--src/libstore/store-api.cc5
-rw-r--r--src/libstore/store-api.hh14
-rw-r--r--src/libutil/ref.hh17
-rw-r--r--src/nix-env/nix-env.cc5
-rw-r--r--src/nix-env/user-env.cc24
-rw-r--r--src/nix-instantiate/nix-instantiate.cc4
-rw-r--r--src/nix-store/nix-store.cc34
13 files changed, 112 insertions, 77 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index df48e8b662..e5be048d8d 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -29,7 +29,7 @@ static string gcRootsDir = "gcroots";
 int LocalStore::openGCLock(LockType lockType)
 {
     Path fnGCLock = (format("%1%/%2%")
-        % settings.nixStateDir % gcLockName).str();
+        % stateDir % gcLockName).str();
 
     debug(format("acquiring global GC lock ‘%1%’") % fnGCLock);
 
@@ -78,12 +78,12 @@ void LocalStore::addIndirectRoot(const Path & path)
 {
     string hash = printHash32(hashString(htSHA1, path));
     Path realRoot = canonPath((format("%1%/%2%/auto/%3%")
-        % settings.nixStateDir % gcRootsDir % hash).str());
+        % stateDir % gcRootsDir % hash).str());
     makeSymlink(realRoot, path);
 }
 
 
-Path Store::addPermRoot(const Path & _storePath,
+Path LocalFSStore::addPermRoot(const Path & _storePath,
     const Path & _gcRoot, bool indirect, bool allowOutsideRootsDir)
 {
     Path storePath(canonPath(_storePath));
@@ -106,7 +106,7 @@ Path Store::addPermRoot(const Path & _storePath,
 
     else {
         if (!allowOutsideRootsDir) {
-            Path rootsDir = canonPath((format("%1%/%2%") % settings.nixStateDir % gcRootsDir).str());
+            Path rootsDir = canonPath((format("%1%/%2%") % stateDir % gcRootsDir).str());
 
             if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
                 throw Error(format(
@@ -153,7 +153,7 @@ void LocalStore::addTempRoot(const Path & path)
     if (state->fdTempRoots == -1) {
 
         while (1) {
-            Path dir = (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str();
+            Path dir = (format("%1%/%2%") % stateDir % tempRootsDir).str();
             createDirs(dir);
 
             state->fnTempRoots = (format("%1%/%2%") % dir % getpid()).str();
@@ -200,19 +200,15 @@ void LocalStore::addTempRoot(const Path & path)
 }
 
 
-typedef std::shared_ptr<AutoCloseFD> FDPtr;
-typedef list<FDPtr> FDs;
-
-
-static void readTempRoots(Store & store, PathSet & tempRoots, FDs & fds)
+void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
 {
     /* Read the `temproots' directory for per-process temporary root
        files. */
     DirEntries tempRootFiles = readDirectory(
-        (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str());
+        (format("%1%/%2%") % stateDir % tempRootsDir).str());
 
     for (auto & i : tempRootFiles) {
-        Path path = (format("%1%/%2%/%3%") % settings.nixStateDir % tempRootsDir % i.name).str();
+        Path path = (format("%1%/%2%/%3%") % stateDir % tempRootsDir % i.name).str();
 
         debug(format("reading temporary root file ‘%1%’") % path);
         FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666)));
@@ -251,7 +247,7 @@ static void readTempRoots(Store & store, PathSet & tempRoots, FDs & fds)
         while ((end = contents.find((char) 0, pos)) != string::npos) {
             Path root(contents, pos, end - pos);
             debug(format("got temporary root ‘%1%’") % root);
-            store.assertStorePath(root);
+            assertStorePath(root);
             tempRoots.insert(root);
             pos = end + 1;
         }
@@ -290,7 +286,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
             else {
                 target = absPath(target, dirOf(path));
                 if (!pathExists(target)) {
-                    if (isInDir(path, settings.nixStateDir + "/" + gcRootsDir + "/auto")) {
+                    if (isInDir(path, stateDir + "/" + gcRootsDir + "/auto")) {
                         printMsg(lvlInfo, format("removing stale link from ‘%1%’ to ‘%2%’") % path % target);
                         unlink(path.c_str());
                     }
@@ -326,10 +322,10 @@ Roots LocalStore::findRoots()
     Roots roots;
 
     /* Process direct roots in {gcroots,manifests,profiles}. */
-    findRoots(settings.nixStateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
-    if (pathExists(settings.nixStateDir + "/manifests"))
-        findRoots(settings.nixStateDir + "/manifests", DT_UNKNOWN, roots);
-    findRoots(settings.nixStateDir + "/profiles", DT_UNKNOWN, roots);
+    findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
+    if (pathExists(stateDir + "/manifests"))
+        findRoots(stateDir + "/manifests", DT_UNKNOWN, roots);
+    findRoots(stateDir + "/profiles", DT_UNKNOWN, roots);
 
     return roots;
 }
@@ -635,7 +631,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
        per-process temporary root files.  So after this point no paths
        can be added to the set of temporary roots. */
     FDs fds;
-    readTempRoots(*this, state.tempRoots, fds);
+    readTempRoots(state.tempRoots, fds);
     state.roots.insert(state.tempRoots.begin(), state.tempRoots.end());
 
     /* After this point the set of roots or temporary roots cannot
diff --git a/src/libstore/local-fs-store.cc b/src/libstore/local-fs-store.cc
index ea9c6b541a..a19e4ce5db 100644
--- a/src/libstore/local-fs-store.cc
+++ b/src/libstore/local-fs-store.cc
@@ -1,9 +1,16 @@
 #include "archive.hh"
 #include "fs-accessor.hh"
 #include "store-api.hh"
+#include "globals.hh"
 
 namespace nix {
 
+LocalFSStore::LocalFSStore(const Params & params)
+    : Store(params)
+    , stateDir(get(params, "state", settings.nixStateDir))
+{
+}
+
 struct LocalStoreAccessor : public FSAccessor
 {
     ref<Store> store;
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 7588d4b073..e1ff94d2ce 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -38,9 +38,10 @@ namespace nix {
 
 LocalStore::LocalStore(const Params & params)
     : LocalFSStore(params)
+    , dbDir(get(params, "state", "") != "" ? get(params, "state", "") + "/db" : settings.nixDBPath)
     , linksDir(storeDir + "/.links")
-    , reservedPath(settings.nixDBPath + "/reserved")
-    , schemaPath(settings.nixDBPath + "/schema")
+    , reservedPath(dbDir + "/reserved")
+    , schemaPath(dbDir + "/schema")
     , requireSigs(settings.get("signed-binary-caches", std::string("")) != "") // FIXME: rename option
     , publicKeys(getDefaultPublicKeys())
 {
@@ -55,11 +56,11 @@ LocalStore::LocalStore(const Params & params)
     createDirs(storeDir);
     makeStoreWritable();
     createDirs(linksDir);
-    Path profilesDir = settings.nixStateDir + "/profiles";
+    Path profilesDir = stateDir + "/profiles";
     createDirs(profilesDir);
-    createDirs(settings.nixStateDir + "/temproots");
-    createDirs(settings.nixDBPath);
-    Path gcRootsDir = settings.nixStateDir + "/gcroots";
+    createDirs(stateDir + "/temproots");
+    createDirs(dbDir);
+    Path gcRootsDir = stateDir + "/gcroots";
     if (!pathExists(gcRootsDir)) {
         createDirs(gcRootsDir);
         createSymlink(profilesDir, gcRootsDir + "/profiles");
@@ -135,7 +136,7 @@ LocalStore::LocalStore(const Params & params)
     /* Acquire the big fat lock in shared mode to make sure that no
        schema upgrade is in progress. */
     try {
-        Path globalLockPath = settings.nixDBPath + "/big-lock";
+        Path globalLockPath = dbDir + "/big-lock";
         globalLock = openLockFile(globalLockPath.c_str(), true);
     } catch (SysError & e) {
         if (e.errNo != EACCES) throw;
@@ -246,19 +247,13 @@ int LocalStore::getSchema()
 }
 
 
-bool LocalStore::haveWriteAccess()
-{
-    return access(settings.nixDBPath.c_str(), R_OK | W_OK) == 0;
-}
-
-
 void LocalStore::openDB(State & state, bool create)
 {
-    if (!haveWriteAccess())
-        throw SysError(format("Nix database directory ‘%1%’ is not writable") % settings.nixDBPath);
+    if (access(dbDir.c_str(), R_OK | W_OK))
+        throw SysError(format("Nix database directory ‘%1%’ is not writable") % dbDir);
 
     /* Open the Nix database. */
-    string dbPath = settings.nixDBPath + "/db.sqlite";
+    string dbPath = dbDir + "/db.sqlite";
     auto & db(state.db);
     if (sqlite3_open_v2(dbPath.c_str(), &db.db,
             SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK)
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index eb5fcf8336..5166c04e53 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -73,6 +73,7 @@ private:
 
     Sync<State, std::recursive_mutex> _state;
 
+    const Path dbDir;
     const Path linksDir;
     const Path reservedPath;
     const Path schemaPath;
@@ -146,6 +147,15 @@ public:
 
     void syncWithGC() override;
 
+private:
+
+    typedef std::shared_ptr<AutoCloseFD> FDPtr;
+    typedef list<FDPtr> FDs;
+
+    void readTempRoots(PathSet & tempRoots, FDs & fds);
+
+public:
+
     Roots findRoots() override;
 
     void collectGarbage(const GCOptions & options, GCResults & results) override;
@@ -179,8 +189,6 @@ public:
 
     void addSignatures(const Path & storePath, const StringSet & sigs) override;
 
-    static bool haveWriteAccess();
-
 private:
 
     int getSchema();
diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc
index 18e3bcbec4..449c88b576 100644
--- a/src/libstore/profiles.cc
+++ b/src/libstore/profiles.cc
@@ -74,7 +74,7 @@ static void makeName(const Path & profile, unsigned int num,
 }
 
 
-Path createGeneration(ref<Store> store, Path profile, Path outPath)
+Path createGeneration(ref<LocalFSStore> store, Path profile, Path outPath)
 {
     /* The new generation number should be higher than old the
        previous ones. */
diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh
index d758d94b60..1d4e6d3037 100644
--- a/src/libstore/profiles.hh
+++ b/src/libstore/profiles.hh
@@ -31,9 +31,9 @@ typedef list<Generation> Generations;
    profile, sorted by generation number. */
 Generations findGenerations(Path profile, int & curGen);
 
-class Store;
+class LocalFSStore;
 
-Path createGeneration(ref<Store> store, Path profile, Path outPath);
+Path createGeneration(ref<LocalFSStore> store, Path profile, Path outPath);
 
 void deleteGeneration(const Path & profile, unsigned int gen);
 
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index cea4b4b6eb..c6616a43d7 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -230,7 +230,7 @@ Path Store::computeStorePathForText(const string & name, const string & s,
 
 
 Store::Store(const Params & params)
-    : storeDir(settings.nixStore)
+    : storeDir(get(params, "store", settings.nixStore))
 {
 }
 
@@ -508,7 +508,8 @@ static RegisterStoreImplementation regStore([](
     else return 0;
 
     if (mode == mAuto) {
-        if (LocalStore::haveWriteAccess())
+        auto stateDir = get(params, "state", settings.nixStateDir);
+        if (access(stateDir.c_str(), R_OK | W_OK) == 0)
             mode = mLocal;
         else if (pathExists(settings.nixDaemonSocketFile))
             mode = mDaemon;
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 45cf7e7819..b665babc08 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -372,10 +372,6 @@ public:
        `path' has disappeared. */
     virtual void addIndirectRoot(const Path & path) = 0;
 
-    /* Register a permanent GC root. */
-    Path addPermRoot(const Path & storePath,
-        const Path & gcRoot, bool indirect, bool allowOutsideRootsDir = false);
-
     /* Acquire the global GC lock, then immediately release it.  This
        function must be called after registering a new permanent root,
        but before exiting.  Otherwise, it is possible that a running
@@ -494,11 +490,17 @@ protected:
 
 class LocalFSStore : public Store
 {
-protected:
-    using Store::Store;
 public:
+    const Path stateDir;
+
+    LocalFSStore(const Params & params);
+
     void narFromPath(const Path & path, Sink & sink) override;
     ref<FSAccessor> getFSAccessor() override;
+
+    /* Register a permanent GC root. */
+    Path addPermRoot(const Path & storePath,
+        const Path & gcRoot, bool indirect, bool allowOutsideRootsDir = false);
 };
 
 
diff --git a/src/libutil/ref.hh b/src/libutil/ref.hh
index 85afa28119..0be2a7e74a 100644
--- a/src/libutil/ref.hh
+++ b/src/libutil/ref.hh
@@ -45,19 +45,30 @@ public:
         return *p;
     }
 
-    operator std::shared_ptr<T> ()
+    operator std::shared_ptr<T> () const
+    {
+        return p;
+    }
+
+    std::shared_ptr<T> get_ptr() const
     {
         return p;
     }
 
     template<typename T2>
-    ref<T2> cast()
+    ref<T2> cast() const
     {
         return ref<T2>(std::dynamic_pointer_cast<T2>(p));
     }
 
     template<typename T2>
-    operator ref<T2> ()
+    std::shared_ptr<T2> dynamic_pointer_cast() const
+    {
+        return std::dynamic_pointer_cast<T2>(p);
+    }
+
+    template<typename T2>
+    operator ref<T2> () const
     {
         return ref<T2>((std::shared_ptr<T2>) p);
     }
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index fbb0f61a19..3f0486bb65 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -692,6 +692,9 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs)
 
 static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
 {
+    auto store2 = globals.state->store.dynamic_pointer_cast<LocalFSStore>();
+    if (!store2) throw Error("--set is not supported for this Nix store");
+
     for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) {
         string arg = *i++;
         if (parseInstallSourceOptions(globals, i, opFlags, arg)) ;
@@ -722,7 +725,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
     }
 
     debug(format("switching to new user environment"));
-    Path generation = createGeneration(globals.state->store, globals.profile, drv.queryOutPath());
+    Path generation = createGeneration(ref<LocalFSStore>(store2), globals.profile, drv.queryOutPath());
     switchLink(globals.profile, generation);
 }
 
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index ca27a72481..f239f63776 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -131,18 +131,22 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
     state.store->buildPaths({topLevelDrv}, state.repair ? bmRepair : bmNormal);
 
     /* Switch the current user environment to the output path. */
-    PathLocks lock;
-    lockProfile(lock, profile);
+    auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>();
 
-    Path lockTokenCur = optimisticLockProfile(profile);
-    if (lockToken != lockTokenCur) {
-        printMsg(lvlError, format("profile ‘%1%’ changed while we were busy; restarting") % profile);
-        return false;
-    }
+    if (store2) {
+        PathLocks lock;
+        lockProfile(lock, profile);
+
+        Path lockTokenCur = optimisticLockProfile(profile);
+        if (lockToken != lockTokenCur) {
+            printMsg(lvlError, format("profile ‘%1%’ changed while we were busy; restarting") % profile);
+            return false;
+        }
 
-    debug(format("switching to new user environment"));
-    Path generation = createGeneration(state.store, profile, topLevelOut);
-    switchLink(profile, generation);
+        debug(format("switching to new user environment"));
+        Path generation = createGeneration(ref<LocalFSStore>(store2), profile, topLevelOut);
+        switchLink(profile, generation);
+    }
 
     return true;
 }
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index 7dce08400e..c1b0b0ea09 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -79,7 +79,9 @@ void processExpr(EvalState & state, const Strings & attrPaths,
                 else {
                     Path rootName = gcRoot;
                     if (++rootNr > 1) rootName += "-" + std::to_string(rootNr);
-                    drvPath = state.store->addPermRoot(drvPath, rootName, indirectRoot);
+                    auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>();
+                    if (store2)
+                        drvPath = store2->addPermRoot(drvPath, rootName, indirectRoot);
                 }
                 std::cout << format("%1%%2%\n") % drvPath % (outputName != "out" ? "!" + outputName : "");
             }
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index cd00412a8a..78b2aa1027 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -63,6 +63,8 @@ static PathSet realisePath(Path path, bool build = true)
 {
     DrvPathWithOutputs p = parseDrvPathWithOutputs(path);
 
+    auto store2 = std::dynamic_pointer_cast<LocalFSStore>(store);
+
     if (isDerivation(p.first)) {
         if (build) store->buildPaths({path});
         Derivation drv = store->derivationFromPath(p.first);
@@ -77,13 +79,15 @@ static PathSet realisePath(Path path, bool build = true)
             if (i == drv.outputs.end())
                 throw Error(format("derivation ‘%1%’ does not have an output named ‘%2%’") % p.first % j);
             Path outPath = i->second.path;
-            if (gcRoot == "")
-                printGCWarning();
-            else {
-                Path rootName = gcRoot;
-                if (rootNr > 1) rootName += "-" + std::to_string(rootNr);
-                if (i->first != "out") rootName += "-" + i->first;
-                outPath = store->addPermRoot(outPath, rootName, indirectRoot);
+            if (store2) {
+                if (gcRoot == "")
+                    printGCWarning();
+                else {
+                    Path rootName = gcRoot;
+                    if (rootNr > 1) rootName += "-" + std::to_string(rootNr);
+                    if (i->first != "out") rootName += "-" + i->first;
+                    outPath = store2->addPermRoot(outPath, rootName, indirectRoot);
+                }
             }
             outputs.insert(outPath);
         }
@@ -93,13 +97,15 @@ static PathSet realisePath(Path path, bool build = true)
     else {
         if (build) store->ensurePath(path);
         else if (!store->isValidPath(path)) throw Error(format("path ‘%1%’ does not exist and cannot be created") % path);
-        if (gcRoot == "")
-            printGCWarning();
-        else {
-            Path rootName = gcRoot;
-            rootNr++;
-            if (rootNr > 1) rootName += "-" + std::to_string(rootNr);
-            path = store->addPermRoot(path, rootName, indirectRoot);
+        if (store2) {
+            if (gcRoot == "")
+                printGCWarning();
+            else {
+                Path rootName = gcRoot;
+                rootNr++;
+                if (rootNr > 1) rootName += "-" + std::to_string(rootNr);
+                path = store2->addPermRoot(path, rootName, indirectRoot);
+            }
         }
         return {path};
     }