Allow setting the state directory as a store parameter
E.g. "local?store=/tmp/store&state=/tmp/var".
This commit is contained in:
		
							parent
							
								
									f2682e6e18
								
							
						
					
					
						commit
						812c0dfbe2
					
				
					 13 changed files with 112 additions and 77 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -131,19 +131,23 @@ 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(ref<LocalFSStore>(store2), profile, topLevelOut);
 | 
			
		||||
        switchLink(profile, generation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    debug(format("switching to new user environment"));
 | 
			
		||||
    Path generation = createGeneration(state.store, profile, topLevelOut);
 | 
			
		||||
    switchLink(profile, generation);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 : "");
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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};
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue