diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index d094989af..263792ec9 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -94,7 +94,8 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s) if (isUri(s)) { auto storePath = fetchers::downloadTarball( state.store, resolveUri(s), "source", false).first.storePath; - auto & accessor = state.registerAccessor(makeFSInputAccessor(CanonPath(state.store->toRealPath(storePath)))); + auto accessor = makeFSInputAccessor(CanonPath(state.store->toRealPath(storePath))); + state.registerAccessor(accessor); return {accessor, CanonPath::root}; } else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { Path p(s.substr(1, s.size() - 2)); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 89887823e..497a1e8f5 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1025,7 +1025,7 @@ void Value::mkStringMove(const char * s, const PathSet & context) void Value::mkPath(const SourcePath & path) { - mkPath(&path.accessor, makeImmutableString(path.path.abs())); + mkPath(&*path.accessor, makeImmutableString(path.path.abs())); } @@ -1928,7 +1928,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) Value values[es->size()]; Value * vTmpP = values; - InputAccessor * accessor = nullptr; + std::shared_ptr accessor; for (auto & [i_pos, i] : *es) { Value * vTmp = vTmpP++; @@ -1947,7 +1947,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) if (first) { firstType = vTmp->type(); if (vTmp->type() == nPath) - accessor = &vTmp->path().accessor; + accessor = vTmp->path().accessor; } if (firstType == nInt) { @@ -1984,7 +1984,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) else if (firstType == nPath) { if (!context.empty()) state.throwEvalError(pos, "a string that refers to a store path cannot be appended to a path", env, *this); - v.mkPath({.accessor = *accessor, .path = CanonPath(str())}); + v.mkPath({ref(accessor), CanonPath(str())}); } else v.mkStringMove(c_str(), context); } @@ -2267,7 +2267,7 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & contex auto path = v.str(); if (path == "" || path[0] != '/') throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path); - return {*rootFS, CanonPath(path)}; + return {rootFS, CanonPath(path)}; } if (v.type() == nPath) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 56519573b..f9814b501 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -219,7 +219,7 @@ public: SourcePath rootPath(const Path & path); - InputAccessor & registerAccessor(ref accessor); + void registerAccessor(ref accessor); /* Allow access to a path. */ void allowPath(const Path & path); diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index 933dad35a..a5b91b947 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -266,7 +266,9 @@ static Flake getFlake( auto [accessor, lockedRef] = resolvedRef.lazyFetch(state.store); - return readFlake(state, originalRef, resolvedRef, lockedRef, SourcePath {state.registerAccessor(accessor), CanonPath::root}, lockRootPath); + state.registerAccessor(accessor); + + return readFlake(state, originalRef, resolvedRef, lockedRef, SourcePath {accessor, CanonPath::root}, lockRootPath); } Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistries) diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index 08478455b..13c3e3587 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -11,11 +11,9 @@ namespace nix { struct SourcePathAdapter : AbstractPos { SourcePath path; - ref hack; // FIXME: remove SourcePathAdapter(SourcePath path) : path(std::move(path)) - , hack(path.accessor.shared_from_this()) { } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 7b732995e..a42a916e2 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -193,7 +193,7 @@ struct ExprPath : Expr ExprPath(SourcePath && _path) : path(_path) { - v.mkPath(&path.accessor, path.path.abs().data()); + v.mkPath(&*path.accessor, path.path.abs().data()); } Value * maybeThunk(EvalState & state, Env & env) override; COMMON_METHODS diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 14b712f6f..96ee42528 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -768,7 +768,7 @@ SourcePath EvalState::findFile(SearchPath & searchPath, const std::string_view p } if (hasPrefix(path, "nix/")) - return {*corepkgsFS, CanonPath(path.substr(3))}; + return {corepkgsFS, CanonPath(path.substr(3))}; debugThrowLastTrace(ThrownError({ .msg = hintfmt(evalSettings.pureEval @@ -791,7 +791,8 @@ SourcePath EvalState::findFile(SearchPath & searchPath, const std::string_view p try { auto storePath = fetchers::downloadTarball( store, resolveUri(elem.second), "source", false).first.storePath; - auto & accessor = registerAccessor(makeFSInputAccessor(CanonPath(store->toRealPath(storePath)))); + auto accessor = makeFSInputAccessor(CanonPath(store->toRealPath(storePath))); + registerAccessor(accessor); res.emplace(SourcePath {accessor, CanonPath::root}); } catch (FileTransferError & e) { logWarning({ diff --git a/src/libexpr/paths.cc b/src/libexpr/paths.cc index af5423e84..f366722eb 100644 --- a/src/libexpr/paths.cc +++ b/src/libexpr/paths.cc @@ -5,13 +5,12 @@ namespace nix { SourcePath EvalState::rootPath(const Path & path) { - return {*rootFS, CanonPath(path)}; + return {rootFS, CanonPath(path)}; } -InputAccessor & EvalState::registerAccessor(ref accessor) +void EvalState::registerAccessor(ref accessor) { inputAccessors.emplace(&*accessor, accessor); - return *accessor; } } diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 164e387d5..0fc3a809c 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -186,9 +186,11 @@ static void fetchTree( if (params.returnPath) { auto [accessor, input2] = input.lazyFetch(state.store); + state.registerAccessor(accessor); + emitTreeAttrs( state, - { state.registerAccessor(accessor), CanonPath::root }, + { accessor, CanonPath::root }, input2, v, params.emptyRevFallback, diff --git a/src/libexpr/primops/patch.cc b/src/libexpr/primops/patch.cc index a4c0d451b..3268754b5 100644 --- a/src/libexpr/primops/patch.cc +++ b/src/libexpr/primops/patch.cc @@ -60,9 +60,11 @@ static void prim_patch(EvalState & state, const PosIdx pos, Value * * args, Valu if (!src->path.isRoot()) throw UnimplementedError("applying patches to a non-root path ('%s') is not yet supported", src->path); - auto accessor = makePatchingInputAccessor(ref(src->accessor.shared_from_this()), patches); + auto accessor = makePatchingInputAccessor(src->accessor, patches); - v.mkPath(SourcePath { state.registerAccessor(accessor), src->path }); + state.registerAccessor(accessor); + + v.mkPath(SourcePath{accessor, src->path}); } static RegisterPrimOp primop_patch({ diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 139bfaa5d..5a8d6413b 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -415,7 +415,10 @@ public: SourcePath path() const { assert(internalType == tPath); - return SourcePath { .accessor = *_path.accessor, .path = CanonPath(CanonPath::unchecked_t(), _path.path) }; + return SourcePath { + .accessor = ref(_path.accessor->shared_from_this()), + .path = CanonPath(CanonPath::unchecked_t(), _path.path) + }; } std::string_view str() const diff --git a/src/libfetchers/input-accessor.cc b/src/libfetchers/input-accessor.cc index c9472d9a8..a335f1e10 100644 --- a/src/libfetchers/input-accessor.cc +++ b/src/libfetchers/input-accessor.cc @@ -290,11 +290,11 @@ SourcePath SourcePath::resolveSymlinks() const for (auto & component : path) { res.push(component); while (true) { - if (auto st = accessor.maybeLstat(res)) { + if (auto st = accessor->maybeLstat(res)) { if (!linksAllowed--) throw Error("infinite symlink recursion in path '%s'", path); if (st->type != InputAccessor::tSymlink) break; - auto target = accessor.readLink(res); + auto target = accessor->readLink(res); if (hasPrefix(target, "/")) res = CanonPath(target); else { diff --git a/src/libfetchers/input-accessor.hh b/src/libfetchers/input-accessor.hh index ceac4f356..46ae48b2a 100644 --- a/src/libfetchers/input-accessor.hh +++ b/src/libfetchers/input-accessor.hh @@ -92,7 +92,7 @@ ref makePatchingInputAccessor( struct SourcePath { - InputAccessor & accessor; + ref accessor; CanonPath path; std::string_view baseName() const; @@ -100,30 +100,30 @@ struct SourcePath SourcePath parent() const; std::string readFile() const - { return accessor.readFile(path); } + { return accessor->readFile(path); } bool pathExists() const - { return accessor.pathExists(path); } + { return accessor->pathExists(path); } InputAccessor::Stat lstat() const - { return accessor.lstat(path); } + { return accessor->lstat(path); } std::optional maybeLstat() const - { return accessor.maybeLstat(path); } + { return accessor->maybeLstat(path); } InputAccessor::DirEntries readDirectory() const - { return accessor.readDirectory(path); } + { return accessor->readDirectory(path); } std::string readLink() const - { return accessor.readLink(path); } + { return accessor->readLink(path); } void dumpPath( Sink & sink, PathFilter & filter = defaultPathFilter) const - { return accessor.dumpPath(path, sink, filter); } + { return accessor->dumpPath(path, sink, filter); } std::string to_string() const - { return accessor.showPath(path); } + { return accessor->showPath(path); } SourcePath operator + (const CanonPath & x) const { return {accessor, path + x}; } diff --git a/src/libutil/ref.hh b/src/libutil/ref.hh index bf26321db..7d38b059c 100644 --- a/src/libutil/ref.hh +++ b/src/libutil/ref.hh @@ -83,6 +83,11 @@ public: return p != other.p; } + bool operator < (const ref & other) const + { + return p < other.p; + } + private: template