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)) {
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));

View file

@ -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<InputAccessor> 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)

View file

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

View file

@ -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)

View file

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

View file

@ -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

View file

@ -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({

View file

@ -5,13 +5,12 @@ namespace nix {
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);
return *accessor;
}
}

View file

@ -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,

View file

@ -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({

View file

@ -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

View file

@ -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 {

View file

@ -92,7 +92,7 @@ ref<InputAccessor> makePatchingInputAccessor(
struct SourcePath
{
InputAccessor & accessor;
ref<InputAccessor> 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<InputAccessor::Stat> 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}; }

View file

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