Store a ref to InputAccessor in SourcePath

This commit is contained in:
Eelco Dolstra 2022-07-06 17:25:15 +02:00
parent 72dffd6c6c
commit a18b3c665a
14 changed files with 44 additions and 31 deletions

View file

@ -94,7 +94,8 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s)
if (isUri(s)) { if (isUri(s)) {
auto storePath = fetchers::downloadTarball( auto storePath = fetchers::downloadTarball(
state.store, resolveUri(s), "source", false).first.storePath; 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}; return {accessor, CanonPath::root};
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { } else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p(s.substr(1, s.size() - 2)); Path p(s.substr(1, s.size() - 2));

View file

@ -1025,7 +1025,7 @@ void Value::mkStringMove(const char * s, const PathSet & context)
void Value::mkPath(const SourcePath & path) 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 values[es->size()];
Value * vTmpP = values; Value * vTmpP = values;
InputAccessor * accessor = nullptr; std::shared_ptr<InputAccessor> accessor;
for (auto & [i_pos, i] : *es) { for (auto & [i_pos, i] : *es) {
Value * vTmp = vTmpP++; Value * vTmp = vTmpP++;
@ -1947,7 +1947,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
if (first) { if (first) {
firstType = vTmp->type(); firstType = vTmp->type();
if (vTmp->type() == nPath) if (vTmp->type() == nPath)
accessor = &vTmp->path().accessor; accessor = vTmp->path().accessor;
} }
if (firstType == nInt) { if (firstType == nInt) {
@ -1984,7 +1984,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
else if (firstType == nPath) { else if (firstType == nPath) {
if (!context.empty()) if (!context.empty())
state.throwEvalError(pos, "a string that refers to a store path cannot be appended to a path", env, *this); 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 } else
v.mkStringMove(c_str(), context); v.mkStringMove(c_str(), context);
} }
@ -2267,7 +2267,7 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & contex
auto path = v.str(); auto path = v.str();
if (path == "" || path[0] != '/') if (path == "" || path[0] != '/')
throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path); throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path);
return {*rootFS, CanonPath(path)}; return {rootFS, CanonPath(path)};
} }
if (v.type() == nPath) if (v.type() == nPath)

View file

@ -219,7 +219,7 @@ public:
SourcePath rootPath(const Path & path); SourcePath rootPath(const Path & path);
InputAccessor & registerAccessor(ref<InputAccessor> accessor); void registerAccessor(ref<InputAccessor> accessor);
/* Allow access to a path. */ /* Allow access to a path. */
void allowPath(const Path & path); void allowPath(const Path & path);

View file

@ -266,7 +266,9 @@ static Flake getFlake(
auto [accessor, lockedRef] = resolvedRef.lazyFetch(state.store); 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) Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistries)

View file

@ -11,11 +11,9 @@ namespace nix {
struct SourcePathAdapter : AbstractPos struct SourcePathAdapter : AbstractPos
{ {
SourcePath path; SourcePath path;
ref<InputAccessor> hack; // FIXME: remove
SourcePathAdapter(SourcePath path) SourcePathAdapter(SourcePath path)
: path(std::move(path)) : path(std::move(path))
, hack(path.accessor.shared_from_this())
{ {
} }

View file

@ -193,7 +193,7 @@ struct ExprPath : Expr
ExprPath(SourcePath && _path) ExprPath(SourcePath && _path)
: path(_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; Value * maybeThunk(EvalState & state, Env & env) override;
COMMON_METHODS COMMON_METHODS

View file

@ -768,7 +768,7 @@ SourcePath EvalState::findFile(SearchPath & searchPath, const std::string_view p
} }
if (hasPrefix(path, "nix/")) if (hasPrefix(path, "nix/"))
return {*corepkgsFS, CanonPath(path.substr(3))}; return {corepkgsFS, CanonPath(path.substr(3))};
debugThrowLastTrace(ThrownError({ debugThrowLastTrace(ThrownError({
.msg = hintfmt(evalSettings.pureEval .msg = hintfmt(evalSettings.pureEval
@ -791,7 +791,8 @@ SourcePath EvalState::findFile(SearchPath & searchPath, const std::string_view p
try { try {
auto storePath = fetchers::downloadTarball( auto storePath = fetchers::downloadTarball(
store, resolveUri(elem.second), "source", false).first.storePath; 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}); res.emplace(SourcePath {accessor, CanonPath::root});
} catch (FileTransferError & e) { } catch (FileTransferError & e) {
logWarning({ logWarning({

View file

@ -5,13 +5,12 @@ namespace nix {
SourcePath EvalState::rootPath(const Path & path) SourcePath EvalState::rootPath(const Path & path)
{ {
return {*rootFS, CanonPath(path)}; return {rootFS, CanonPath(path)};
} }
InputAccessor & EvalState::registerAccessor(ref<InputAccessor> accessor) void EvalState::registerAccessor(ref<InputAccessor> accessor)
{ {
inputAccessors.emplace(&*accessor, accessor); inputAccessors.emplace(&*accessor, accessor);
return *accessor;
} }
} }

View file

@ -186,9 +186,11 @@ static void fetchTree(
if (params.returnPath) { if (params.returnPath) {
auto [accessor, input2] = input.lazyFetch(state.store); auto [accessor, input2] = input.lazyFetch(state.store);
state.registerAccessor(accessor);
emitTreeAttrs( emitTreeAttrs(
state, state,
{ state.registerAccessor(accessor), CanonPath::root }, { accessor, CanonPath::root },
input2, input2,
v, v,
params.emptyRevFallback, params.emptyRevFallback,

View file

@ -60,9 +60,11 @@ static void prim_patch(EvalState & state, const PosIdx pos, Value * * args, Valu
if (!src->path.isRoot()) if (!src->path.isRoot())
throw UnimplementedError("applying patches to a non-root path ('%s') is not yet supported", src->path); 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({ static RegisterPrimOp primop_patch({

View file

@ -415,7 +415,10 @@ public:
SourcePath path() const SourcePath path() const
{ {
assert(internalType == tPath); 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 std::string_view str() const

View file

@ -290,11 +290,11 @@ SourcePath SourcePath::resolveSymlinks() const
for (auto & component : path) { for (auto & component : path) {
res.push(component); res.push(component);
while (true) { while (true) {
if (auto st = accessor.maybeLstat(res)) { if (auto st = accessor->maybeLstat(res)) {
if (!linksAllowed--) if (!linksAllowed--)
throw Error("infinite symlink recursion in path '%s'", path); throw Error("infinite symlink recursion in path '%s'", path);
if (st->type != InputAccessor::tSymlink) break; if (st->type != InputAccessor::tSymlink) break;
auto target = accessor.readLink(res); auto target = accessor->readLink(res);
if (hasPrefix(target, "/")) if (hasPrefix(target, "/"))
res = CanonPath(target); res = CanonPath(target);
else { else {

View file

@ -92,7 +92,7 @@ ref<InputAccessor> makePatchingInputAccessor(
struct SourcePath struct SourcePath
{ {
InputAccessor & accessor; ref<InputAccessor> accessor;
CanonPath path; CanonPath path;
std::string_view baseName() const; std::string_view baseName() const;
@ -100,30 +100,30 @@ struct SourcePath
SourcePath parent() const; SourcePath parent() const;
std::string readFile() const std::string readFile() const
{ return accessor.readFile(path); } { return accessor->readFile(path); }
bool pathExists() const bool pathExists() const
{ return accessor.pathExists(path); } { return accessor->pathExists(path); }
InputAccessor::Stat lstat() const InputAccessor::Stat lstat() const
{ return accessor.lstat(path); } { return accessor->lstat(path); }
std::optional<InputAccessor::Stat> maybeLstat() const std::optional<InputAccessor::Stat> maybeLstat() const
{ return accessor.maybeLstat(path); } { return accessor->maybeLstat(path); }
InputAccessor::DirEntries readDirectory() const InputAccessor::DirEntries readDirectory() const
{ return accessor.readDirectory(path); } { return accessor->readDirectory(path); }
std::string readLink() const std::string readLink() const
{ return accessor.readLink(path); } { return accessor->readLink(path); }
void dumpPath( void dumpPath(
Sink & sink, Sink & sink,
PathFilter & filter = defaultPathFilter) const PathFilter & filter = defaultPathFilter) const
{ return accessor.dumpPath(path, sink, filter); } { return accessor->dumpPath(path, sink, filter); }
std::string to_string() const std::string to_string() const
{ return accessor.showPath(path); } { return accessor->showPath(path); }
SourcePath operator + (const CanonPath & x) const SourcePath operator + (const CanonPath & x) const
{ return {accessor, path + x}; } { return {accessor, path + x}; }

View file

@ -83,6 +83,11 @@ public:
return p != other.p; return p != other.p;
} }
bool operator < (const ref<T> & other) const
{
return p < other.p;
}
private: private:
template<typename T2, typename... Args> template<typename T2, typename... Args>