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

View file

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

View file

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

View file

@ -92,10 +92,10 @@ struct ExprString : Expr
struct ExprPath : Expr
{
ref<InputAccessor> accessor;
ref<SourceAccessor> accessor;
std::string s;
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());
}

View file

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

View file

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

View file

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

View file

@ -7,7 +7,6 @@
#include "symbol-table.hh"
#include "value/context.hh"
#include "input-accessor.hh"
#include "source-path.hh"
#include "print-options.hh"
@ -217,7 +216,7 @@ public:
};
struct Path {
InputAccessor * accessor;
SourceAccessor * accessor;
const char * path;
};
@ -335,7 +334,7 @@ public:
void mkPath(const SourcePath & 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 } });
}

View file

@ -14,7 +14,7 @@ StorePath fetchToStore(
RepairFlag repair)
{
// 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;

View file

@ -1,6 +1,5 @@
#include "fetchers.hh"
#include "store-api.hh"
#include "input-accessor.hh"
#include "source-path.hh"
#include "fetch-to-store.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 {
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

View file

@ -11,7 +11,7 @@
#include <memory>
#include <nlohmann/json_fwd.hpp>
namespace nix { class Store; class StorePath; struct InputAccessor; }
namespace nix { class Store; class StorePath; struct SourceAccessor; }
namespace nix::fetchers {
@ -84,15 +84,15 @@ public:
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
* unlocked input.
*/
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store) const;
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store) const;
private:
std::pair<ref<InputAccessor>, Input> getAccessorUnchecked(ref<Store> store) const;
std::pair<ref<SourceAccessor>, Input> getAccessorUnchecked(ref<Store> store) const;
public:
@ -185,7 +185,7 @@ struct InputScheme
std::string_view contents,
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?

View file

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

View file

@ -1,6 +1,5 @@
#pragma once
#include "input-accessor.hh"
#include "source-path.hh"
namespace nix {
@ -17,9 +16,9 @@ typedef std::function<RestrictedPathError(const CanonPath & path)> MakeNotAllowe
* control. Subclasses should override `isAllowed()` to implement an
* access control policy. The error message is customized at construction.
*/
struct FilteringInputAccessor : InputAccessor
struct FilteringInputAccessor : SourceAccessor
{
ref<InputAccessor> next;
ref<SourceAccessor> next;
CanonPath prefix;
MakeNotAllowedError makeNotAllowedError;
@ -67,7 +66,7 @@ struct AllowListInputAccessor : public FilteringInputAccessor
virtual void allowPrefix(CanonPath prefix) = 0;
static ref<AllowListInputAccessor> create(
ref<InputAccessor> next,
ref<SourceAccessor> next,
std::set<CanonPath> && allowedPrefixes,
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 "fs-input-accessor.hh"
#include "input-accessor.hh"
#include "filtering-input-accessor.hh"
#include "memory-input-accessor.hh"
#include "cache.hh"
#include "finally.hh"
#include "processes.hh"
@ -338,9 +334,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
*/
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;
@ -477,7 +473,7 @@ ref<GitRepo> GitRepo::openRepo(const std::filesystem::path & path, bool create,
/**
* Raw git tree input accessor.
*/
struct GitInputAccessor : InputAccessor
struct GitInputAccessor : SourceAccessor
{
ref<GitRepoImpl> repo;
Tree root;
@ -710,7 +706,7 @@ struct GitExportIgnoreInputAccessor : CachingFilteringInputAccessor {
ref<GitRepoImpl> repo;
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) {
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);
}
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());
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());
/* In case of an empty workdir, return an empty in-memory tree. We
cannot use AllowListInputAccessor because it would return an
error for the root (and we can't add the root to the allow-list
since that would allow access to all its children). */
ref<InputAccessor> fileAccessor =
ref<SourceAccessor> fileAccessor =
wd.files.empty()
? makeEmptyInputAccessor()
? makeEmptySourceAccessor()
: AllowListInputAccessor::create(
makeFSInputAccessor(path),
makeFSSourceAccessor(path),
std::set<CanonPath> { wd.files },
std::move(makeNotAllowedError)).cast<InputAccessor>();
std::move(makeNotAllowedError)).cast<SourceAccessor>();
if (exportIgnore)
return make_ref<GitExportIgnoreInputAccessor>(self, fileAccessor, std::nullopt);
else

View file

@ -1,7 +1,6 @@
#pragma once
#include "filtering-input-accessor.hh"
#include "input-accessor.hh"
#include "fs-sink.hh"
namespace nix {
@ -75,9 +74,9 @@ struct GitRepo
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;

View file

@ -272,7 +272,7 @@ struct GitArchiveInputScheme : InputScheme
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);

View file

@ -97,7 +97,7 @@ struct IndirectInputScheme : InputScheme
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());
}

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 {
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))
{
displayPrefix.clear();
@ -53,7 +53,7 @@ struct MountedInputAccessor : InputAccessor
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.
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));
}

View file

@ -1,9 +1,9 @@
#pragma once
#include "input-accessor.hh"
#include "source-accessor.hh"
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 "store-api.hh"
#include "archive.hh"
#include "fs-input-accessor.hh"
#include "posix-source-accessor.hh"
#include "store-path-accessor.hh"
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());
}
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);
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 "types.hh"
#include "split.hh"
#include "posix-source-accessor.hh"
#include "fs-input-accessor.hh"
#include "store-path-accessor.hh"
#include "store-api.hh"
#include "git-utils.hh"
@ -297,7 +296,7 @@ struct FileInputScheme : CurlInputScheme
: (!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);
@ -332,7 +331,7 @@ struct TarballInputScheme : CurlInputScheme
: (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);

View file

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

View file

@ -9,7 +9,6 @@
#include "pathlocks.hh"
#include "processes.hh"
#include "git.hh"
#include "fs-input-accessor.hh"
#include "mounted-input-accessor.hh"
#include "git-utils.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,
RepoInfo & repoInfo,
Input && input) const
@ -629,7 +628,7 @@ struct GitInputScheme : InputScheme
input accessor consisting of the accessor for the top-level
repo and the accessors for the submodules. */
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)) {
auto resolved = repo->resolveSubmoduleUrl(submodule.url);
@ -665,7 +664,7 @@ struct GitInputScheme : InputScheme
return {accessor, std::move(input)};
}
std::pair<ref<InputAccessor>, Input> getAccessorFromWorkdir(
std::pair<ref<SourceAccessor>, Input> getAccessorFromWorkdir(
ref<Store> store,
RepoInfo & repoInfo,
Input && input) const
@ -679,7 +678,7 @@ struct GitInputScheme : InputScheme
auto exportIgnore = getExportIgnoreAttr(input);
ref<InputAccessor> accessor =
ref<SourceAccessor> accessor =
repo->getAccessor(repoInfo.workdirInfo,
exportIgnore,
makeNotAllowedError(repoInfo.url));
@ -690,7 +689,7 @@ struct GitInputScheme : InputScheme
consisting of the accessor for the top-level repo and the
accessors for the submodule workdirs. */
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) {
auto submodulePath = CanonPath(repoInfo.url) / submodule.path;
@ -755,7 +754,7 @@ struct GitInputScheme : InputScheme
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);

View file

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

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);
}
CanonPath MemorySourceAccessor::addFile(CanonPath path, std::string && contents)
SourcePath MemorySourceAccessor::addFile(CanonPath path, std::string && contents)
{
auto * f = open(path, File { File::Regular {} });
if (!f)
@ -118,7 +118,7 @@ CanonPath MemorySourceAccessor::addFile(CanonPath path, std::string && contents)
else
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);
}
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 "variant-wrapper.hh"
@ -69,7 +69,7 @@ struct MemorySourceAccessor : virtual SourceAccessor
*/
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
* Git repositories).
*/
struct SourceAccessor
struct SourceAccessor : std::enable_shared_from_this<SourceAccessor>
{
const size_t number;
@ -168,6 +168,40 @@ struct SourceAccessor
CanonPath resolveSymlinks(
const CanonPath & path,
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
{ return accessor->pathExists(path); }
InputAccessor::Stat SourcePath::lstat() const
SourceAccessor::Stat SourcePath::lstat() const
{ return accessor->lstat(path); }
std::optional<InputAccessor::Stat> SourcePath::maybeLstat() const
std::optional<SourceAccessor::Stat> SourcePath::maybeLstat() const
{ return accessor->maybeLstat(path); }
InputAccessor::DirEntries SourcePath::readDirectory() const
SourceAccessor::DirEntries SourcePath::readDirectory() const
{ return accessor->readDirectory(path); }
std::string SourcePath::readLink() const

View file

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

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
st.type == InputAccessor::tRegular
|| (st.type == InputAccessor::tDirectory && (path / "default.nix").resolveSymlinks().pathExists());
st.type == SourceAccessor::tRegular
|| (st.type == SourceAccessor::tDirectory && (path / "default.nix").resolveSymlinks().pathExists());
}
@ -119,14 +119,14 @@ static void getAllExprs(EvalState & state,
auto path2 = (path / i).resolveSymlinks();
InputAccessor::Stat st;
SourceAccessor::Stat st;
try {
st = path2.lstat();
} catch (Error &) {
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),
otherwise the attribute cannot be selected with the
`-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);
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);
recurse into it. */
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
~/.nix-defexpr directory that includes some system-wide
directory). */
else if (st.type == InputAccessor::tDirectory) {
else if (st.type == SourceAccessor::tDirectory) {
auto attrs = state.buildBindings(maxAttrs);
attrs.insert(state.symbols.create("_combineChannels"), &state.vEmptyList);
StringSet seen;

View file

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

View file

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