Merge pull request #10642 from edolstra/remove-input-accessor

Merge InputAccessor into SourceAccessor
This commit is contained in:
Eelco Dolstra 2024-05-06 15:48:25 +02:00 committed by GitHub
commit ee2fa87a7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 181 additions and 253 deletions

View File

@ -21,7 +21,6 @@
#include "url.hh" #include "url.hh"
#include "registry.hh" #include "registry.hh"
#include "build-result.hh" #include "build-result.hh"
#include "fs-input-accessor.hh"
#include <regex> #include <regex>
#include <queue> #include <queue>
@ -147,7 +146,7 @@ MixFlakeOptions::MixFlakeOptions()
.category = category, .category = category,
.labels = {"flake-lock-path"}, .labels = {"flake-lock-path"},
.handler = {[&](std::string lockFilePath) { .handler = {[&](std::string lockFilePath) {
lockFlags.referenceLockFilePath = getUnfilteredRootPath(CanonPath(absPath(lockFilePath))); lockFlags.referenceLockFilePath = {makeFSSourceAccessor(), CanonPath(absPath(lockFilePath))};
}}, }},
.completer = completePath .completer = completePath
}); });

View File

@ -15,9 +15,8 @@
#include "function-trace.hh" #include "function-trace.hh"
#include "profiles.hh" #include "profiles.hh"
#include "print.hh" #include "print.hh"
#include "fs-input-accessor.hh"
#include "filtering-input-accessor.hh" #include "filtering-input-accessor.hh"
#include "memory-input-accessor.hh" #include "memory-source-accessor.hh"
#include "signals.hh" #include "signals.hh"
#include "gc-small-vector.hh" #include "gc-small-vector.hh"
#include "url.hh" #include "url.hh"
@ -400,16 +399,16 @@ EvalState::EvalState(
, emptyBindings(0) , emptyBindings(0)
, rootFS( , rootFS(
evalSettings.restrictEval || evalSettings.pureEval evalSettings.restrictEval || evalSettings.pureEval
? ref<InputAccessor>(AllowListInputAccessor::create(makeFSInputAccessor(), {}, ? ref<SourceAccessor>(AllowListInputAccessor::create(makeFSSourceAccessor(), {},
[](const CanonPath & path) -> RestrictedPathError { [](const CanonPath & path) -> RestrictedPathError {
auto modeInformation = evalSettings.pureEval auto modeInformation = evalSettings.pureEval
? "in pure evaluation mode (use '--impure' to override)" ? "in pure evaluation mode (use '--impure' to override)"
: "in restricted mode"; : "in restricted mode";
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation); throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
})) }))
: makeFSInputAccessor()) : makeFSSourceAccessor())
, corepkgsFS(makeMemoryInputAccessor()) , corepkgsFS(make_ref<MemorySourceAccessor>())
, internalFS(makeMemoryInputAccessor()) , internalFS(make_ref<MemorySourceAccessor>())
, derivationInternal{corepkgsFS->addFile( , derivationInternal{corepkgsFS->addFile(
CanonPath("derivation-internal.nix"), CanonPath("derivation-internal.nix"),
#include "primops/derivation.nix.gen.hh" #include "primops/derivation.nix.gen.hh"
@ -2766,12 +2765,12 @@ SourcePath resolveExprPath(SourcePath path)
if (++followCount >= maxFollow) if (++followCount >= maxFollow)
throw Error("too many symbolic links encountered while traversing the path '%s'", path); throw Error("too many symbolic links encountered while traversing the path '%s'", path);
auto p = path.parent().resolveSymlinks() / path.baseName(); auto p = path.parent().resolveSymlinks() / path.baseName();
if (p.lstat().type != InputAccessor::tSymlink) break; if (p.lstat().type != SourceAccessor::tSymlink) break;
path = {path.accessor, CanonPath(p.readLink(), path.path.parent().value_or(CanonPath::root))}; path = {path.accessor, CanonPath(p.readLink(), path.path.parent().value_or(CanonPath::root))};
} }
/* If `path' refers to a directory, append `/default.nix'. */ /* If `path' refers to a directory, append `/default.nix'. */
if (path.resolveSymlinks().lstat().type == InputAccessor::tDirectory) if (path.resolveSymlinks().lstat().type == SourceAccessor::tDirectory)
return path / "default.nix"; return path / "default.nix";
return path; return path;

View File

@ -9,7 +9,7 @@
#include "symbol-table.hh" #include "symbol-table.hh"
#include "config.hh" #include "config.hh"
#include "experimental-features.hh" #include "experimental-features.hh"
#include "input-accessor.hh" #include "source-accessor.hh"
#include "search-path.hh" #include "search-path.hh"
#include "repl-exit-status.hh" #include "repl-exit-status.hh"
@ -33,7 +33,7 @@ class EvalState;
class StorePath; class StorePath;
struct SingleDerivedPath; struct SingleDerivedPath;
enum RepairFlag : bool; enum RepairFlag : bool;
struct MemoryInputAccessor; struct MemorySourceAccessor;
namespace eval_cache { namespace eval_cache {
class EvalCache; class EvalCache;
} }
@ -229,18 +229,18 @@ public:
/** /**
* The accessor for the root filesystem. * The accessor for the root filesystem.
*/ */
const ref<InputAccessor> rootFS; const ref<SourceAccessor> rootFS;
/** /**
* The in-memory filesystem for <nix/...> paths. * The in-memory filesystem for <nix/...> paths.
*/ */
const ref<MemoryInputAccessor> corepkgsFS; const ref<MemorySourceAccessor> corepkgsFS;
/** /**
* In-memory filesystem for internal, non-user-callable Nix * In-memory filesystem for internal, non-user-callable Nix
* expressions like call-flake.nix. * expressions like call-flake.nix.
*/ */
const ref<MemoryInputAccessor> internalFS; const ref<MemorySourceAccessor> internalFS;
const SourcePath derivationInternal; const SourcePath derivationInternal;

View File

@ -92,10 +92,10 @@ struct ExprString : Expr
struct ExprPath : Expr struct ExprPath : Expr
{ {
ref<InputAccessor> accessor; ref<SourceAccessor> accessor;
std::string s; std::string s;
Value v; Value v;
ExprPath(ref<InputAccessor> accessor, std::string s) : accessor(accessor), s(std::move(s)) ExprPath(ref<SourceAccessor> accessor, std::string s) : accessor(accessor), s(std::move(s))
{ {
v.mkPath(&*accessor, this->s.c_str()); v.mkPath(&*accessor, this->s.c_str());
} }

View File

@ -44,7 +44,7 @@ struct ParserState
Expr * result; Expr * result;
SourcePath basePath; SourcePath basePath;
PosTable::Origin origin; PosTable::Origin origin;
const ref<InputAccessor> rootFS; const ref<SourceAccessor> rootFS;
const Expr::AstSymbols & s; const Expr::AstSymbols & s;
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos); void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);

View File

@ -41,7 +41,7 @@ Expr * parseExprFromBuf(
const SourcePath & basePath, const SourcePath & basePath,
SymbolTable & symbols, SymbolTable & symbols,
PosTable & positions, PosTable & positions,
const ref<InputAccessor> rootFS, const ref<SourceAccessor> rootFS,
const Expr::AstSymbols & astSymbols); const Expr::AstSymbols & astSymbols);
} }
@ -291,7 +291,7 @@ path_start
/* add back in the trailing '/' to the first segment */ /* add back in the trailing '/' to the first segment */
if ($1.p[$1.l-1] == '/' && $1.l > 1) if ($1.p[$1.l-1] == '/' && $1.l > 1)
path += "/"; path += "/";
$$ = new ExprPath(ref<InputAccessor>(state->rootFS), std::move(path)); $$ = new ExprPath(ref<SourceAccessor>(state->rootFS), std::move(path));
} }
| HPATH { | HPATH {
if (evalSettings.pureEval) { if (evalSettings.pureEval) {
@ -301,7 +301,7 @@ path_start
); );
} }
Path path(getHome() + std::string($1.p + 1, $1.l - 1)); Path path(getHome() + std::string($1.p + 1, $1.l - 1));
$$ = new ExprPath(ref<InputAccessor>(state->rootFS), std::move(path)); $$ = new ExprPath(ref<SourceAccessor>(state->rootFS), std::move(path));
} }
; ;
@ -430,7 +430,7 @@ Expr * parseExprFromBuf(
const SourcePath & basePath, const SourcePath & basePath,
SymbolTable & symbols, SymbolTable & symbols,
PosTable & positions, PosTable & positions,
const ref<InputAccessor> rootFS, const ref<SourceAccessor> rootFS,
const Expr::AstSymbols & astSymbols) const Expr::AstSymbols & astSymbols)
{ {
yyscan_t scanner; yyscan_t scanner;

View File

@ -15,7 +15,6 @@
#include "value-to-json.hh" #include "value-to-json.hh"
#include "value-to-xml.hh" #include "value-to-xml.hh"
#include "primops.hh" #include "primops.hh"
#include "fs-input-accessor.hh"
#include "fetch-to-store.hh" #include "fetch-to-store.hh"
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
@ -1828,12 +1827,12 @@ static RegisterPrimOp primop_hashFile({
.fun = prim_hashFile, .fun = prim_hashFile,
}); });
static Value * fileTypeToString(EvalState & state, InputAccessor::Type type) static Value * fileTypeToString(EvalState & state, SourceAccessor::Type type)
{ {
return return
type == InputAccessor::Type::tRegular ? &state.vStringRegular : type == SourceAccessor::Type::tRegular ? &state.vStringRegular :
type == InputAccessor::Type::tDirectory ? &state.vStringDirectory : type == SourceAccessor::Type::tDirectory ? &state.vStringDirectory :
type == InputAccessor::Type::tSymlink ? &state.vStringSymlink : type == SourceAccessor::Type::tSymlink ? &state.vStringSymlink :
&state.vStringUnknown; &state.vStringUnknown;
} }

View File

@ -7,7 +7,6 @@
#include "symbol-table.hh" #include "symbol-table.hh"
#include "value/context.hh" #include "value/context.hh"
#include "input-accessor.hh"
#include "source-path.hh" #include "source-path.hh"
#include "print-options.hh" #include "print-options.hh"
@ -217,7 +216,7 @@ public:
}; };
struct Path { struct Path {
InputAccessor * accessor; SourceAccessor * accessor;
const char * path; const char * path;
}; };
@ -335,7 +334,7 @@ public:
void mkPath(const SourcePath & path); void mkPath(const SourcePath & path);
void mkPath(std::string_view path); void mkPath(std::string_view path);
inline void mkPath(InputAccessor * accessor, const char * path) inline void mkPath(SourceAccessor * accessor, const char * path)
{ {
finishValue(tPath, { .path = { .accessor = accessor, .path = path } }); finishValue(tPath, { .path = { .accessor = accessor, .path = path } });
} }

View File

@ -14,7 +14,7 @@ StorePath fetchToStore(
RepairFlag repair) RepairFlag repair)
{ {
// FIXME: add an optimisation for the case where the accessor is // FIXME: add an optimisation for the case where the accessor is
// an FSInputAccessor pointing to a store path. // a `PosixSourceAccessor` pointing to a store path.
std::optional<fetchers::Attrs> cacheKey; std::optional<fetchers::Attrs> cacheKey;

View File

@ -1,6 +1,5 @@
#include "fetchers.hh" #include "fetchers.hh"
#include "store-api.hh" #include "store-api.hh"
#include "input-accessor.hh"
#include "source-path.hh" #include "source-path.hh"
#include "fetch-to-store.hh" #include "fetch-to-store.hh"
#include "json-utils.hh" #include "json-utils.hh"
@ -238,7 +237,7 @@ void InputScheme::checkLocks(const Input & specified, const Input & final) const
} }
} }
std::pair<ref<InputAccessor>, Input> Input::getAccessor(ref<Store> store) const std::pair<ref<SourceAccessor>, Input> Input::getAccessor(ref<Store> store) const
{ {
try { try {
auto [accessor, final] = getAccessorUnchecked(store); auto [accessor, final] = getAccessorUnchecked(store);
@ -252,7 +251,7 @@ std::pair<ref<InputAccessor>, Input> Input::getAccessor(ref<Store> store) const
} }
} }
std::pair<ref<InputAccessor>, Input> Input::getAccessorUnchecked(ref<Store> store) const std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> store) const
{ {
// FIXME: cache the accessor // FIXME: cache the accessor

View File

@ -11,7 +11,7 @@
#include <memory> #include <memory>
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
namespace nix { class Store; class StorePath; struct InputAccessor; } namespace nix { class Store; class StorePath; struct SourceAccessor; }
namespace nix::fetchers { namespace nix::fetchers {
@ -84,15 +84,15 @@ public:
std::pair<StorePath, Input> fetchToStore(ref<Store> store) const; std::pair<StorePath, Input> fetchToStore(ref<Store> store) const;
/** /**
* Return an InputAccessor that allows access to files in the * Return a `SourceAccessor` that allows access to files in the
* input without copying it to the store. Also return a possibly * input without copying it to the store. Also return a possibly
* unlocked input. * unlocked input.
*/ */
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store) const; std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store) const;
private: private:
std::pair<ref<InputAccessor>, Input> getAccessorUnchecked(ref<Store> store) const; std::pair<ref<SourceAccessor>, Input> getAccessorUnchecked(ref<Store> store) const;
public: public:
@ -185,7 +185,7 @@ struct InputScheme
std::string_view contents, std::string_view contents,
std::optional<std::string> commitMsg) const; std::optional<std::string> commitMsg) const;
virtual std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const = 0; virtual std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const = 0;
/** /**
* Is this `InputScheme` part of an experimental feature? * Is this `InputScheme` part of an experimental feature?

View File

@ -13,13 +13,13 @@ bool FilteringInputAccessor::pathExists(const CanonPath & path)
return isAllowed(path) && next->pathExists(prefix / path); return isAllowed(path) && next->pathExists(prefix / path);
} }
std::optional<InputAccessor::Stat> FilteringInputAccessor::maybeLstat(const CanonPath & path) std::optional<SourceAccessor::Stat> FilteringInputAccessor::maybeLstat(const CanonPath & path)
{ {
checkAccess(path); checkAccess(path);
return next->maybeLstat(prefix / path); return next->maybeLstat(prefix / path);
} }
InputAccessor::DirEntries FilteringInputAccessor::readDirectory(const CanonPath & path) SourceAccessor::DirEntries FilteringInputAccessor::readDirectory(const CanonPath & path)
{ {
checkAccess(path); checkAccess(path);
DirEntries entries; DirEntries entries;
@ -54,7 +54,7 @@ struct AllowListInputAccessorImpl : AllowListInputAccessor
std::set<CanonPath> allowedPrefixes; std::set<CanonPath> allowedPrefixes;
AllowListInputAccessorImpl( AllowListInputAccessorImpl(
ref<InputAccessor> next, ref<SourceAccessor> next,
std::set<CanonPath> && allowedPrefixes, std::set<CanonPath> && allowedPrefixes,
MakeNotAllowedError && makeNotAllowedError) MakeNotAllowedError && makeNotAllowedError)
: AllowListInputAccessor(SourcePath(next), std::move(makeNotAllowedError)) : AllowListInputAccessor(SourcePath(next), std::move(makeNotAllowedError))
@ -73,7 +73,7 @@ struct AllowListInputAccessorImpl : AllowListInputAccessor
}; };
ref<AllowListInputAccessor> AllowListInputAccessor::create( ref<AllowListInputAccessor> AllowListInputAccessor::create(
ref<InputAccessor> next, ref<SourceAccessor> next,
std::set<CanonPath> && allowedPrefixes, std::set<CanonPath> && allowedPrefixes,
MakeNotAllowedError && makeNotAllowedError) MakeNotAllowedError && makeNotAllowedError)
{ {

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "input-accessor.hh"
#include "source-path.hh" #include "source-path.hh"
namespace nix { namespace nix {
@ -17,9 +16,9 @@ typedef std::function<RestrictedPathError(const CanonPath & path)> MakeNotAllowe
* control. Subclasses should override `isAllowed()` to implement an * control. Subclasses should override `isAllowed()` to implement an
* access control policy. The error message is customized at construction. * access control policy. The error message is customized at construction.
*/ */
struct FilteringInputAccessor : InputAccessor struct FilteringInputAccessor : SourceAccessor
{ {
ref<InputAccessor> next; ref<SourceAccessor> next;
CanonPath prefix; CanonPath prefix;
MakeNotAllowedError makeNotAllowedError; MakeNotAllowedError makeNotAllowedError;
@ -67,7 +66,7 @@ struct AllowListInputAccessor : public FilteringInputAccessor
virtual void allowPrefix(CanonPath prefix) = 0; virtual void allowPrefix(CanonPath prefix) = 0;
static ref<AllowListInputAccessor> create( static ref<AllowListInputAccessor> create(
ref<InputAccessor> next, ref<SourceAccessor> next,
std::set<CanonPath> && allowedPrefixes, std::set<CanonPath> && allowedPrefixes,
MakeNotAllowedError && makeNotAllowedError); MakeNotAllowedError && makeNotAllowedError);

View File

@ -1,39 +0,0 @@
#include "fs-input-accessor.hh"
#include "posix-source-accessor.hh"
#include "store-api.hh"
namespace nix {
struct FSInputAccessor : InputAccessor, PosixSourceAccessor
{
using PosixSourceAccessor::PosixSourceAccessor;
};
ref<InputAccessor> makeFSInputAccessor()
{
return make_ref<FSInputAccessor>();
}
ref<InputAccessor> makeFSInputAccessor(std::filesystem::path root)
{
return make_ref<FSInputAccessor>(std::move(root));
}
ref<InputAccessor> makeStorePathAccessor(
ref<Store> store,
const StorePath & storePath)
{
// FIXME: should use `store->getFSAccessor()`
auto root = std::filesystem::path { store->toRealPath(storePath) };
auto accessor = makeFSInputAccessor(root);
accessor->setPathDisplay(root.string());
return accessor;
}
SourcePath getUnfilteredRootPath(CanonPath path)
{
static auto rootFS = makeFSInputAccessor();
return {rootFS, path};
}
}

View File

@ -1,21 +0,0 @@
#pragma once
#include "input-accessor.hh"
#include "source-path.hh"
namespace nix {
class StorePath;
class Store;
ref<InputAccessor> makeFSInputAccessor();
ref<InputAccessor> makeFSInputAccessor(std::filesystem::path root);
ref<InputAccessor> makeStorePathAccessor(
ref<Store> store,
const StorePath & storePath);
SourcePath getUnfilteredRootPath(CanonPath path);
}

View File

@ -1,8 +1,4 @@
#include "git-utils.hh" #include "git-utils.hh"
#include "fs-input-accessor.hh"
#include "input-accessor.hh"
#include "filtering-input-accessor.hh"
#include "memory-input-accessor.hh"
#include "cache.hh" #include "cache.hh"
#include "finally.hh" #include "finally.hh"
#include "processes.hh" #include "processes.hh"
@ -338,9 +334,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
*/ */
ref<GitInputAccessor> getRawAccessor(const Hash & rev); ref<GitInputAccessor> getRawAccessor(const Hash & rev);
ref<InputAccessor> getAccessor(const Hash & rev, bool exportIgnore) override; ref<SourceAccessor> getAccessor(const Hash & rev, bool exportIgnore) override;
ref<InputAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError e) override; ref<SourceAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError e) override;
ref<GitFileSystemObjectSink> getFileSystemObjectSink() override; ref<GitFileSystemObjectSink> getFileSystemObjectSink() override;
@ -477,7 +473,7 @@ ref<GitRepo> GitRepo::openRepo(const std::filesystem::path & path, bool create,
/** /**
* Raw git tree input accessor. * Raw git tree input accessor.
*/ */
struct GitInputAccessor : InputAccessor struct GitInputAccessor : SourceAccessor
{ {
ref<GitRepoImpl> repo; ref<GitRepoImpl> repo;
Tree root; Tree root;
@ -710,7 +706,7 @@ struct GitExportIgnoreInputAccessor : CachingFilteringInputAccessor {
ref<GitRepoImpl> repo; ref<GitRepoImpl> repo;
std::optional<Hash> rev; std::optional<Hash> rev;
GitExportIgnoreInputAccessor(ref<GitRepoImpl> repo, ref<InputAccessor> next, std::optional<Hash> rev) GitExportIgnoreInputAccessor(ref<GitRepoImpl> repo, ref<SourceAccessor> next, std::optional<Hash> rev)
: CachingFilteringInputAccessor(next, [&](const CanonPath & path) { : CachingFilteringInputAccessor(next, [&](const CanonPath & path) {
return RestrictedPathError(fmt("'%s' does not exist because it was fetched with exportIgnore enabled", path)); return RestrictedPathError(fmt("'%s' does not exist because it was fetched with exportIgnore enabled", path));
}) })
@ -928,7 +924,7 @@ ref<GitInputAccessor> GitRepoImpl::getRawAccessor(const Hash & rev)
return make_ref<GitInputAccessor>(self, rev); return make_ref<GitInputAccessor>(self, rev);
} }
ref<InputAccessor> GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore) ref<SourceAccessor> GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore)
{ {
auto self = ref<GitRepoImpl>(shared_from_this()); auto self = ref<GitRepoImpl>(shared_from_this());
ref<GitInputAccessor> rawGitAccessor = getRawAccessor(rev); ref<GitInputAccessor> rawGitAccessor = getRawAccessor(rev);
@ -940,20 +936,20 @@ ref<InputAccessor> GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore)
} }
} }
ref<InputAccessor> GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) ref<SourceAccessor> GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError)
{ {
auto self = ref<GitRepoImpl>(shared_from_this()); auto self = ref<GitRepoImpl>(shared_from_this());
/* In case of an empty workdir, return an empty in-memory tree. We /* In case of an empty workdir, return an empty in-memory tree. We
cannot use AllowListInputAccessor because it would return an cannot use AllowListInputAccessor because it would return an
error for the root (and we can't add the root to the allow-list error for the root (and we can't add the root to the allow-list
since that would allow access to all its children). */ since that would allow access to all its children). */
ref<InputAccessor> fileAccessor = ref<SourceAccessor> fileAccessor =
wd.files.empty() wd.files.empty()
? makeEmptyInputAccessor() ? makeEmptySourceAccessor()
: AllowListInputAccessor::create( : AllowListInputAccessor::create(
makeFSInputAccessor(path), makeFSSourceAccessor(path),
std::set<CanonPath> { wd.files }, std::set<CanonPath> { wd.files },
std::move(makeNotAllowedError)).cast<InputAccessor>(); std::move(makeNotAllowedError)).cast<SourceAccessor>();
if (exportIgnore) if (exportIgnore)
return make_ref<GitExportIgnoreInputAccessor>(self, fileAccessor, std::nullopt); return make_ref<GitExportIgnoreInputAccessor>(self, fileAccessor, std::nullopt);
else else

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "filtering-input-accessor.hh" #include "filtering-input-accessor.hh"
#include "input-accessor.hh"
#include "fs-sink.hh" #include "fs-sink.hh"
namespace nix { namespace nix {
@ -75,9 +74,9 @@ struct GitRepo
virtual bool hasObject(const Hash & oid) = 0; virtual bool hasObject(const Hash & oid) = 0;
virtual ref<InputAccessor> getAccessor(const Hash & rev, bool exportIgnore) = 0; virtual ref<SourceAccessor> getAccessor(const Hash & rev, bool exportIgnore) = 0;
virtual ref<InputAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0; virtual ref<SourceAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0;
virtual ref<GitFileSystemObjectSink> getFileSystemObjectSink() = 0; virtual ref<GitFileSystemObjectSink> getFileSystemObjectSink() = 0;

View File

@ -272,7 +272,7 @@ struct GitArchiveInputScheme : InputScheme
return {std::move(input), tarballInfo}; return {std::move(input), tarballInfo};
} }
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
{ {
auto [input, tarballInfo] = downloadArchive(store, _input); auto [input, tarballInfo] = downloadArchive(store, _input);

View File

@ -97,7 +97,7 @@ struct IndirectInputScheme : InputScheme
return input; return input;
} }
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const override std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const override
{ {
throw Error("indirect input '%s' cannot be fetched directly", input.to_string()); throw Error("indirect input '%s' cannot be fetched directly", input.to_string());
} }

View File

@ -1,29 +0,0 @@
#include "memory-input-accessor.hh"
#include "memory-source-accessor.hh"
#include "source-path.hh"
namespace nix {
struct MemoryInputAccessorImpl : MemoryInputAccessor, MemorySourceAccessor
{
SourcePath addFile(CanonPath path, std::string && contents) override
{
return {
ref(shared_from_this()),
MemorySourceAccessor::addFile(path, std::move(contents))
};
}
};
ref<MemoryInputAccessor> makeMemoryInputAccessor()
{
return make_ref<MemoryInputAccessorImpl>();
}
ref<InputAccessor> makeEmptyInputAccessor()
{
static auto empty = makeMemoryInputAccessor().cast<InputAccessor>();
return empty;
}
}

View File

@ -1,18 +0,0 @@
#include "input-accessor.hh"
#include "source-path.hh"
namespace nix {
/**
* An input accessor for an in-memory file system.
*/
struct MemoryInputAccessor : InputAccessor
{
virtual SourcePath addFile(CanonPath path, std::string && contents) = 0;
};
ref<MemoryInputAccessor> makeMemoryInputAccessor();
ref<InputAccessor> makeEmptyInputAccessor();
}

View File

@ -2,11 +2,11 @@
namespace nix { namespace nix {
struct MountedInputAccessor : InputAccessor struct MountedInputAccessor : SourceAccessor
{ {
std::map<CanonPath, ref<InputAccessor>> mounts; std::map<CanonPath, ref<SourceAccessor>> mounts;
MountedInputAccessor(std::map<CanonPath, ref<InputAccessor>> _mounts) MountedInputAccessor(std::map<CanonPath, ref<SourceAccessor>> _mounts)
: mounts(std::move(_mounts)) : mounts(std::move(_mounts))
{ {
displayPrefix.clear(); displayPrefix.clear();
@ -53,7 +53,7 @@ struct MountedInputAccessor : InputAccessor
return displayPrefix + accessor->showPath(subpath) + displaySuffix; return displayPrefix + accessor->showPath(subpath) + displaySuffix;
} }
std::pair<ref<InputAccessor>, CanonPath> resolve(CanonPath path) std::pair<ref<SourceAccessor>, CanonPath> resolve(CanonPath path)
{ {
// Find the nearest parent of `path` that is a mount point. // Find the nearest parent of `path` that is a mount point.
std::vector<std::string> subpath; std::vector<std::string> subpath;
@ -71,7 +71,7 @@ struct MountedInputAccessor : InputAccessor
} }
}; };
ref<InputAccessor> makeMountedInputAccessor(std::map<CanonPath, ref<InputAccessor>> mounts) ref<SourceAccessor> makeMountedInputAccessor(std::map<CanonPath, ref<SourceAccessor>> mounts)
{ {
return make_ref<MountedInputAccessor>(std::move(mounts)); return make_ref<MountedInputAccessor>(std::move(mounts));
} }

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include "input-accessor.hh" #include "source-accessor.hh"
namespace nix { namespace nix {
ref<InputAccessor> makeMountedInputAccessor(std::map<CanonPath, ref<InputAccessor>> mounts); ref<SourceAccessor> makeMountedInputAccessor(std::map<CanonPath, ref<SourceAccessor>> mounts);
} }

View File

@ -1,8 +1,7 @@
#include "fetchers.hh" #include "fetchers.hh"
#include "store-api.hh" #include "store-api.hh"
#include "archive.hh" #include "archive.hh"
#include "fs-input-accessor.hh" #include "store-path-accessor.hh"
#include "posix-source-accessor.hh"
namespace nix::fetchers { namespace nix::fetchers {
@ -114,7 +113,7 @@ struct PathInputScheme : InputScheme
throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string()); throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string());
} }
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
{ {
Input input(_input); Input input(_input);
std::string absPath; std::string absPath;

View File

@ -0,0 +1,15 @@
#include "store-path-accessor.hh"
#include "store-api.hh"
namespace nix {
ref<SourceAccessor> makeStorePathAccessor(ref<Store> store, const StorePath & storePath)
{
// FIXME: should use `store->getFSAccessor()`
auto root = std::filesystem::path{store->toRealPath(storePath)};
auto accessor = makeFSSourceAccessor(root);
accessor->setPathDisplay(root.string());
return accessor;
}
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "source-path.hh"
namespace nix {
class StorePath;
class Store;
ref<SourceAccessor> makeStorePathAccessor(ref<Store> store, const StorePath & storePath);
SourcePath getUnfilteredRootPath(CanonPath path);
}

View File

@ -8,8 +8,7 @@
#include "tarfile.hh" #include "tarfile.hh"
#include "types.hh" #include "types.hh"
#include "split.hh" #include "split.hh"
#include "posix-source-accessor.hh" #include "store-path-accessor.hh"
#include "fs-input-accessor.hh"
#include "store-api.hh" #include "store-api.hh"
#include "git-utils.hh" #include "git-utils.hh"
@ -297,7 +296,7 @@ struct FileInputScheme : CurlInputScheme
: (!requireTree && !hasTarballExtension(url.path))); : (!requireTree && !hasTarballExtension(url.path)));
} }
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
{ {
auto input(_input); auto input(_input);
@ -332,7 +331,7 @@ struct TarballInputScheme : CurlInputScheme
: (requireTree || hasTarballExtension(url.path))); : (requireTree || hasTarballExtension(url.path)));
} }
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
{ {
auto input(_input); auto input(_input);

View File

@ -8,7 +8,7 @@
namespace nix { namespace nix {
class Store; class Store;
struct InputAccessor; struct SourceAccessor;
} }
namespace nix::fetchers { namespace nix::fetchers {
@ -32,7 +32,7 @@ struct DownloadTarballResult
Hash treeHash; Hash treeHash;
time_t lastModified; time_t lastModified;
std::optional<std::string> immutableUrl; std::optional<std::string> immutableUrl;
ref<InputAccessor> accessor; ref<SourceAccessor> accessor;
}; };
/** /**

View File

@ -9,7 +9,6 @@
#include "pathlocks.hh" #include "pathlocks.hh"
#include "processes.hh" #include "processes.hh"
#include "git.hh" #include "git.hh"
#include "fs-input-accessor.hh"
#include "mounted-input-accessor.hh" #include "mounted-input-accessor.hh"
#include "git-utils.hh" #include "git-utils.hh"
#include "logging.hh" #include "logging.hh"
@ -495,7 +494,7 @@ struct GitInputScheme : InputScheme
} }
} }
std::pair<ref<InputAccessor>, Input> getAccessorFromCommit( std::pair<ref<SourceAccessor>, Input> getAccessorFromCommit(
ref<Store> store, ref<Store> store,
RepoInfo & repoInfo, RepoInfo & repoInfo,
Input && input) const Input && input) const
@ -629,7 +628,7 @@ struct GitInputScheme : InputScheme
input accessor consisting of the accessor for the top-level input accessor consisting of the accessor for the top-level
repo and the accessors for the submodules. */ repo and the accessors for the submodules. */
if (getSubmodulesAttr(input)) { if (getSubmodulesAttr(input)) {
std::map<CanonPath, nix::ref<InputAccessor>> mounts; std::map<CanonPath, nix::ref<SourceAccessor>> mounts;
for (auto & [submodule, submoduleRev] : repo->getSubmodules(rev, exportIgnore)) { for (auto & [submodule, submoduleRev] : repo->getSubmodules(rev, exportIgnore)) {
auto resolved = repo->resolveSubmoduleUrl(submodule.url); auto resolved = repo->resolveSubmoduleUrl(submodule.url);
@ -665,7 +664,7 @@ struct GitInputScheme : InputScheme
return {accessor, std::move(input)}; return {accessor, std::move(input)};
} }
std::pair<ref<InputAccessor>, Input> getAccessorFromWorkdir( std::pair<ref<SourceAccessor>, Input> getAccessorFromWorkdir(
ref<Store> store, ref<Store> store,
RepoInfo & repoInfo, RepoInfo & repoInfo,
Input && input) const Input && input) const
@ -679,7 +678,7 @@ struct GitInputScheme : InputScheme
auto exportIgnore = getExportIgnoreAttr(input); auto exportIgnore = getExportIgnoreAttr(input);
ref<InputAccessor> accessor = ref<SourceAccessor> accessor =
repo->getAccessor(repoInfo.workdirInfo, repo->getAccessor(repoInfo.workdirInfo,
exportIgnore, exportIgnore,
makeNotAllowedError(repoInfo.url)); makeNotAllowedError(repoInfo.url));
@ -690,7 +689,7 @@ struct GitInputScheme : InputScheme
consisting of the accessor for the top-level repo and the consisting of the accessor for the top-level repo and the
accessors for the submodule workdirs. */ accessors for the submodule workdirs. */
if (getSubmodulesAttr(input) && !repoInfo.workdirInfo.submodules.empty()) { if (getSubmodulesAttr(input) && !repoInfo.workdirInfo.submodules.empty()) {
std::map<CanonPath, nix::ref<InputAccessor>> mounts; std::map<CanonPath, nix::ref<SourceAccessor>> mounts;
for (auto & submodule : repoInfo.workdirInfo.submodules) { for (auto & submodule : repoInfo.workdirInfo.submodules) {
auto submodulePath = CanonPath(repoInfo.url) / submodule.path; auto submodulePath = CanonPath(repoInfo.url) / submodule.path;
@ -755,7 +754,7 @@ struct GitInputScheme : InputScheme
return {accessor, std::move(input)}; return {accessor, std::move(input)};
} }
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
{ {
Input input(_input); Input input(_input);

View File

@ -6,8 +6,7 @@
#include "tarfile.hh" #include "tarfile.hh"
#include "store-api.hh" #include "store-api.hh"
#include "url-parts.hh" #include "url-parts.hh"
#include "fs-input-accessor.hh" #include "store-path-accessor.hh"
#include "posix-source-accessor.hh"
#include "fetch-settings.hh" #include "fetch-settings.hh"
#include <sys/time.h> #include <sys/time.h>
@ -211,10 +210,9 @@ struct MercurialInputScheme : InputScheme
return files.count(file); return files.count(file);
}; };
PosixSourceAccessor accessor;
auto storePath = store->addToStore( auto storePath = store->addToStore(
input.getName(), input.getName(),
accessor, CanonPath { actualPath }, *makeFSSourceAccessor(), CanonPath { actualPath },
FileIngestionMethod::Recursive, HashAlgorithm::SHA256, {}, FileIngestionMethod::Recursive, HashAlgorithm::SHA256, {},
filter); filter);
@ -320,8 +318,7 @@ struct MercurialInputScheme : InputScheme
deletePath(tmpDir + "/.hg_archival.txt"); deletePath(tmpDir + "/.hg_archival.txt");
PosixSourceAccessor accessor; auto storePath = store->addToStore(name, *makeFSSourceAccessor(), CanonPath { tmpDir });
auto storePath = store->addToStore(name, accessor, CanonPath { tmpDir });
Attrs infoAttrs({ Attrs infoAttrs({
{"rev", input.getRev()->gitRev()}, {"rev", input.getRev()->gitRev()},
@ -346,7 +343,7 @@ struct MercurialInputScheme : InputScheme
return makeResult(infoAttrs, std::move(storePath)); return makeResult(infoAttrs, std::move(storePath));
} }
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
{ {
Input input(_input); Input input(_input);

View File

@ -1,27 +0,0 @@
#pragma once
///@file
#include "source-accessor.hh"
#include "ref.hh"
#include "repair-flag.hh"
namespace nix {
MakeError(RestrictedPathError, Error);
struct InputAccessor : virtual SourceAccessor, std::enable_shared_from_this<InputAccessor>
{
std::optional<std::string> fingerprint;
/**
* Return the maximum last-modified time of the files in this
* tree, if available.
*/
virtual std::optional<time_t> getLastModified()
{
return std::nullopt;
}
};
}

View File

@ -108,7 +108,7 @@ std::string MemorySourceAccessor::readLink(const CanonPath & path)
throw Error("file '%s' is not a symbolic link", path); throw Error("file '%s' is not a symbolic link", path);
} }
CanonPath MemorySourceAccessor::addFile(CanonPath path, std::string && contents) SourcePath MemorySourceAccessor::addFile(CanonPath path, std::string && contents)
{ {
auto * f = open(path, File { File::Regular {} }); auto * f = open(path, File { File::Regular {} });
if (!f) if (!f)
@ -118,7 +118,7 @@ CanonPath MemorySourceAccessor::addFile(CanonPath path, std::string && contents)
else else
throw Error("file '%s' is not a regular file", path); throw Error("file '%s' is not a regular file", path);
return path; return SourcePath{ref(shared_from_this()), path};
} }
@ -184,4 +184,10 @@ void MemorySink::createSymlink(const Path & path, const std::string & target)
throw Error("file '%s' is not a symbolic link", path); throw Error("file '%s' is not a symbolic link", path);
} }
ref<SourceAccessor> makeEmptySourceAccessor()
{
static auto empty = make_ref<MemorySourceAccessor>().cast<SourceAccessor>();
return empty;
}
} }

View File

@ -1,4 +1,4 @@
#include "source-accessor.hh" #include "source-path.hh"
#include "fs-sink.hh" #include "fs-sink.hh"
#include "variant-wrapper.hh" #include "variant-wrapper.hh"
@ -69,7 +69,7 @@ struct MemorySourceAccessor : virtual SourceAccessor
*/ */
File * open(const CanonPath & path, std::optional<File> create); File * open(const CanonPath & path, std::optional<File> create);
CanonPath addFile(CanonPath path, std::string && contents); SourcePath addFile(CanonPath path, std::string && contents);
}; };
/** /**

View File

@ -166,4 +166,14 @@ void PosixSourceAccessor::assertNoSymlinks(CanonPath path)
} }
} }
ref<SourceAccessor> makeFSSourceAccessor()
{
static auto rootFS = make_ref<PosixSourceAccessor>();
return rootFS;
}
ref<SourceAccessor> makeFSSourceAccessor(std::filesystem::path root)
{
return make_ref<PosixSourceAccessor>(std::move(root));
}
} }

View File

@ -35,7 +35,7 @@ enum class SymlinkResolution {
* filesystem-like entities (such as the real filesystem, tarballs or * filesystem-like entities (such as the real filesystem, tarballs or
* Git repositories). * Git repositories).
*/ */
struct SourceAccessor struct SourceAccessor : std::enable_shared_from_this<SourceAccessor>
{ {
const size_t number; const size_t number;
@ -168,6 +168,40 @@ struct SourceAccessor
CanonPath resolveSymlinks( CanonPath resolveSymlinks(
const CanonPath & path, const CanonPath & path,
SymlinkResolution mode = SymlinkResolution::Full); SymlinkResolution mode = SymlinkResolution::Full);
/**
* A string that uniquely represents the contents of this
* accessor. This is used for caching lookups (see `fetchToStore()`).
*/
std::optional<std::string> fingerprint;
/**
* Return the maximum last-modified time of the files in this
* tree, if available.
*/
virtual std::optional<time_t> getLastModified()
{ return std::nullopt; }
}; };
/**
* Return a source accessor that contains only an empty root directory.
*/
ref<SourceAccessor> makeEmptySourceAccessor();
/**
* Exception thrown when accessing a filtered path (see
* `FilteringInputAccessor`).
*/
MakeError(RestrictedPathError, Error);
/**
* Return an accessor for the root filesystem.
*/
ref<SourceAccessor> makeFSSourceAccessor();
/**
* Return an accessor for the filesystem rooted at `root`.
*/
ref<SourceAccessor> makeFSSourceAccessor(std::filesystem::path root);
} }

View File

@ -18,13 +18,13 @@ std::string SourcePath::readFile() const
bool SourcePath::pathExists() const bool SourcePath::pathExists() const
{ return accessor->pathExists(path); } { return accessor->pathExists(path); }
InputAccessor::Stat SourcePath::lstat() const SourceAccessor::Stat SourcePath::lstat() const
{ return accessor->lstat(path); } { return accessor->lstat(path); }
std::optional<InputAccessor::Stat> SourcePath::maybeLstat() const std::optional<SourceAccessor::Stat> SourcePath::maybeLstat() const
{ return accessor->maybeLstat(path); } { return accessor->maybeLstat(path); }
InputAccessor::DirEntries SourcePath::readDirectory() const SourceAccessor::DirEntries SourcePath::readDirectory() const
{ return accessor->readDirectory(path); } { return accessor->readDirectory(path); }
std::string SourcePath::readLink() const std::string SourcePath::readLink() const

View File

@ -7,7 +7,7 @@
#include "ref.hh" #include "ref.hh"
#include "canon-path.hh" #include "canon-path.hh"
#include "input-accessor.hh" #include "source-accessor.hh"
namespace nix { namespace nix {
@ -19,10 +19,10 @@ namespace nix {
*/ */
struct SourcePath struct SourcePath
{ {
ref<InputAccessor> accessor; ref<SourceAccessor> accessor;
CanonPath path; CanonPath path;
SourcePath(ref<InputAccessor> accessor, CanonPath path = CanonPath::root) SourcePath(ref<SourceAccessor> accessor, CanonPath path = CanonPath::root)
: accessor(std::move(accessor)) : accessor(std::move(accessor))
, path(std::move(path)) , path(std::move(path))
{ } { }
@ -51,19 +51,19 @@ struct SourcePath
* Return stats about this `SourcePath`, or throw an exception if * Return stats about this `SourcePath`, or throw an exception if
* it doesn't exist. * it doesn't exist.
*/ */
InputAccessor::Stat lstat() const; SourceAccessor::Stat lstat() const;
/** /**
* Return stats about this `SourcePath`, or std::nullopt if it * Return stats about this `SourcePath`, or std::nullopt if it
* doesn't exist. * doesn't exist.
*/ */
std::optional<InputAccessor::Stat> maybeLstat() const; std::optional<SourceAccessor::Stat> maybeLstat() const;
/** /**
* If this `SourcePath` denotes a directory (not a symlink), * If this `SourcePath` denotes a directory (not a symlink),
* return its directory entries; otherwise throw an error. * return its directory entries; otherwise throw an error.
*/ */
InputAccessor::DirEntries readDirectory() const; SourceAccessor::DirEntries readDirectory() const;
/** /**
* If this `SourcePath` denotes a symlink, return its target; * If this `SourcePath` denotes a symlink, return its target;

View File

@ -94,11 +94,11 @@ static bool parseInstallSourceOptions(Globals & globals,
} }
static bool isNixExpr(const SourcePath & path, struct InputAccessor::Stat & st) static bool isNixExpr(const SourcePath & path, struct SourceAccessor::Stat & st)
{ {
return return
st.type == InputAccessor::tRegular st.type == SourceAccessor::tRegular
|| (st.type == InputAccessor::tDirectory && (path / "default.nix").resolveSymlinks().pathExists()); || (st.type == SourceAccessor::tDirectory && (path / "default.nix").resolveSymlinks().pathExists());
} }
@ -119,14 +119,14 @@ static void getAllExprs(EvalState & state,
auto path2 = (path / i).resolveSymlinks(); auto path2 = (path / i).resolveSymlinks();
InputAccessor::Stat st; SourceAccessor::Stat st;
try { try {
st = path2.lstat(); st = path2.lstat();
} catch (Error &) { } catch (Error &) {
continue; // ignore dangling symlinks in ~/.nix-defexpr continue; // ignore dangling symlinks in ~/.nix-defexpr
} }
if (isNixExpr(path2, st) && (st.type != InputAccessor::tRegular || hasSuffix(path2.baseName(), ".nix"))) { if (isNixExpr(path2, st) && (st.type != SourceAccessor::tRegular || hasSuffix(path2.baseName(), ".nix"))) {
/* Strip off the `.nix' filename suffix (if applicable), /* Strip off the `.nix' filename suffix (if applicable),
otherwise the attribute cannot be selected with the otherwise the attribute cannot be selected with the
`-A' option. Useful if you want to stick a Nix `-A' option. Useful if you want to stick a Nix
@ -149,7 +149,7 @@ static void getAllExprs(EvalState & state,
throw Error("too many Nix expressions in directory '%1%'", path); throw Error("too many Nix expressions in directory '%1%'", path);
attrs.alloc(attrName).mkApp(&state.getBuiltin("import"), vArg); attrs.alloc(attrName).mkApp(&state.getBuiltin("import"), vArg);
} }
else if (st.type == InputAccessor::tDirectory) else if (st.type == SourceAccessor::tDirectory)
/* `path2' is a directory (with no default.nix in it); /* `path2' is a directory (with no default.nix in it);
recurse into it. */ recurse into it. */
getAllExprs(state, path2, seen, attrs); getAllExprs(state, path2, seen, attrs);
@ -171,7 +171,7 @@ static void loadSourceExpr(EvalState & state, const SourcePath & path, Value & v
set flat, not nested, to make it easier for a user to have a set flat, not nested, to make it easier for a user to have a
~/.nix-defexpr directory that includes some system-wide ~/.nix-defexpr directory that includes some system-wide
directory). */ directory). */
else if (st.type == InputAccessor::tDirectory) { else if (st.type == SourceAccessor::tDirectory) {
auto attrs = state.buildBindings(maxAttrs); auto attrs = state.buildBindings(maxAttrs);
attrs.insert(state.symbols.create("_combineChannels"), &state.vEmptyList); attrs.insert(state.symbols.create("_combineChannels"), &state.vEmptyList);
StringSet seen; StringSet seen;

View File

@ -14,7 +14,7 @@
#include "finally.hh" #include "finally.hh"
#include "loggers.hh" #include "loggers.hh"
#include "markdown.hh" #include "markdown.hh"
#include "memory-input-accessor.hh" #include "memory-source-accessor.hh"
#include "terminal.hh" #include "terminal.hh"
#include "users.hh" #include "users.hh"

View File

@ -2,7 +2,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "eval-settings.hh" #include "eval-settings.hh"
#include "memory-input-accessor.hh" #include "memory-source-accessor.hh"
#include "tests/libexpr.hh" #include "tests/libexpr.hh"