libexpr: extract eval path handling into new type

Change-Id: Icf38113076a4dd0f8515a27b501f405033aec73b
This commit is contained in:
eldritch horrors 2024-12-03 20:38:41 +01:00
parent a65e9e5828
commit 32f7a93f71
15 changed files with 183 additions and 161 deletions

View file

@ -252,7 +252,7 @@ static void main_nix_build(std::string programName, Strings argv)
else else
/* If we're in a #! script, interpret filenames /* If we're in a #! script, interpret filenames
relative to the script. */ relative to the script. */
exprs.push_back(state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, exprs.push_back(state->parseExprFromFile(resolveExprPath(state->paths.checkSourcePath(lookupFileArg(*state,
inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i))))); inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i)))));
} }
} }

View file

@ -166,7 +166,7 @@ static int main_nix_instantiate(std::string programName, Strings argv)
if (findFile) { if (findFile) {
for (auto & i : files) { for (auto & i : files) {
auto p = state->findFile(i); auto p = state->paths.findFile(i);
if (auto fn = p.getPhysicalPath()) if (auto fn = p.getPhysicalPath())
std::cout << fn->abs() << std::endl; std::cout << fn->abs() << std::endl;
else else
@ -185,7 +185,7 @@ static int main_nix_instantiate(std::string programName, Strings argv)
for (auto & i : files) { for (auto & i : files) {
Expr & e = fromArgs Expr & e = fromArgs
? state->parseExprFromString(i, CanonPath::fromCwd()) ? state->parseExprFromString(i, CanonPath::fromCwd())
: state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, i)))); : state->parseExprFromFile(resolveExprPath(state->paths.checkSourcePath(lookupFileArg(*state, i))));
processExpr(*state, attrPaths, parseOnly, strict, autoArgs, processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
evalOnly, outputKind, xmlOutputSourceLocation, e); evalOnly, outputKind, xmlOutputSourceLocation, e);
} }

View file

@ -104,7 +104,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Construct a Nix expression that calls the user environment /* Construct a Nix expression that calls the user environment
builder with the manifest as argument. */ builder with the manifest as argument. */
auto attrs = state.buildBindings(3); auto attrs = state.buildBindings(3);
state.mkStorePathString(manifestFile, attrs.alloc("manifest")); state.paths.mkStorePathString(manifestFile, attrs.alloc("manifest"));
attrs.insert(state.symbols.create("derivations"), &manifest); attrs.insert(state.symbols.create("derivations"), &manifest);
Value args; Value args;
args.mkAttrs(attrs); args.mkAttrs(attrs);

View file

@ -162,8 +162,8 @@ ProfileManifest::ProfileManifest(EvalState & state, const Path & profile)
} }
} else if (pathExists(profile + "/manifest.nix")) { } else if (pathExists(profile + "/manifest.nix")) {
// FIXME: needed because of pure mode; ugly. // FIXME: needed because of pure mode; ugly.
state.allowPath(state.store->followLinksToStore(profile)); state.paths.allowPath(state.store->followLinksToStore(profile));
state.allowPath(state.store->followLinksToStore(profile + "/manifest.nix")); state.paths.allowPath(state.store->followLinksToStore(profile + "/manifest.nix"));
auto drvInfos = queryInstalled(state, state.store->followLinksToStore(profile)); auto drvInfos = queryInstalled(state, state.store->followLinksToStore(profile));

View file

@ -205,7 +205,7 @@ SourcePath lookupFileArg(EvalState & state, std::string_view fileArg)
return CanonPath(state.store->toRealPath(storePath)); return CanonPath(state.store->toRealPath(storePath));
} else if (fileArg.size() > 2 && fileArg.at(0) == '<' && fileArg.at(fileArg.size() - 1) == '>') { } else if (fileArg.size() > 2 && fileArg.at(0) == '<' && fileArg.at(fileArg.size() - 1) == '>') {
Path p(fileArg.substr(1, fileArg.size() - 2)); Path p(fileArg.substr(1, fileArg.size() - 2));
return state.findFile(p); return state.paths.findFile(p);
} else { } else {
return CanonPath::fromCwd(fileArg); return CanonPath::fromCwd(fileArg);
} }

View file

@ -215,7 +215,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s
evalSettings.pureEval.override(false); evalSettings.pureEval.override(false);
auto state = getEvalState(); auto state = getEvalState();
Expr & e = state->parseExprFromFile( Expr & e = state->parseExprFromFile(
resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file))) resolveExprPath(state->paths.checkSourcePath(lookupFileArg(*state, *file)))
); );
Value root; Value root;

View file

@ -271,44 +271,21 @@ EvalBuiltins::EvalBuiltins(
createBaseEnv(searchPath, storeDir); createBaseEnv(searchPath, storeDir);
} }
EvalState::EvalState( EvalPaths::EvalPaths(
const SearchPath & _searchPath, const ref<Store> & store,
ref<Store> store, const ref<Store> buildStore,
std::shared_ptr<Store> buildStore, SearchPath searchPath,
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl) EvalErrorContext & errors
: s(symbols) )
, searchPath([&] { : store(store)
SearchPath searchPath; , buildStore(buildStore)
if (!evalSettings.pureEval) { , searchPath_(std::move(searchPath))
for (auto & i : _searchPath.elements) , errors(errors)
searchPath.elements.emplace_back(SearchPath::Elem {i});
for (auto & i : evalSettings.nixPath.get())
searchPath.elements.emplace_back(SearchPath::Elem::parse(i));
}
return searchPath;
}())
, builtins(mem, symbols, searchPath, store->config().storeDir)
, repair(NoRepair)
, store(store)
, buildStore(buildStore ? buildStore : store)
, debug{
debugRepl ? std::make_unique<DebugState>(
positions,
symbols,
[this, debugRepl](const ValMap & extraEnv) { return debugRepl(*this, extraEnv); }
)
: nullptr
}
, errors{positions, debug.get()}
{ {
countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0";
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
if (evalSettings.restrictEval || evalSettings.pureEval) { if (evalSettings.restrictEval || evalSettings.pureEval) {
allowedPaths = std::optional(PathSet()); allowedPaths = std::optional(PathSet());
for (auto & i : searchPath.elements) { for (auto & i : searchPath_.elements) {
auto r = resolveSearchPathPath(i.path); auto r = resolveSearchPathPath(i.path);
if (!r) continue; if (!r) continue;
@ -329,32 +306,66 @@ EvalState::EvalState(
} }
} }
EvalState::EvalState(
const SearchPath & _searchPath,
ref<Store> store,
std::shared_ptr<Store> buildStore,
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl)
: s(symbols)
, paths(store, buildStore ? ref(buildStore) : store, [&] {
SearchPath searchPath;
if (!evalSettings.pureEval) {
for (auto & i : _searchPath.elements)
searchPath.elements.emplace_back(SearchPath::Elem {i});
for (auto & i : evalSettings.nixPath.get())
searchPath.elements.emplace_back(SearchPath::Elem::parse(i));
}
return searchPath;
}(), errors)
, builtins(mem, symbols, paths.searchPath(), store->config().storeDir)
, repair(NoRepair)
, store(store)
, debug{
debugRepl ? std::make_unique<DebugState>(
positions,
symbols,
[this, debugRepl](const ValMap & extraEnv) { return debugRepl(*this, extraEnv); }
)
: nullptr
}
, errors{positions, debug.get()}
{
countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0";
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
}
EvalState::~EvalState() EvalState::~EvalState()
{ {
} }
void EvalState::allowPath(const Path & path) void EvalPaths::allowPath(const Path & path)
{ {
if (allowedPaths) if (allowedPaths)
allowedPaths->insert(path); allowedPaths->insert(path);
} }
void EvalState::allowPath(const StorePath & storePath) void EvalPaths::allowPath(const StorePath & storePath)
{ {
if (allowedPaths) if (allowedPaths)
allowedPaths->insert(store->toRealPath(storePath)); allowedPaths->insert(store->toRealPath(storePath));
} }
void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & v) void EvalPaths::allowAndSetStorePathString(const StorePath & storePath, Value & v)
{ {
allowPath(storePath); allowPath(storePath);
mkStorePathString(storePath, v); mkStorePathString(storePath, v);
} }
SourcePath EvalState::checkSourcePath(const SourcePath & path_) SourcePath EvalPaths::checkSourcePath(const SourcePath & path_)
{ {
if (!allowedPaths) return path_; if (!allowedPaths) return path_;
@ -401,7 +412,7 @@ SourcePath EvalState::checkSourcePath(const SourcePath & path_)
} }
void EvalState::checkURI(const std::string & uri) void EvalPaths::checkURI(const std::string & uri)
{ {
if (!evalSettings.restrictEval) return; if (!evalSettings.restrictEval) return;
@ -433,7 +444,7 @@ void EvalState::checkURI(const std::string & uri)
} }
Path EvalState::toRealPath(const Path & path, const NixStringContext & context) Path EvalPaths::toRealPath(const Path & path, const NixStringContext & context)
{ {
// FIXME: check whether 'path' is in 'context'. // FIXME: check whether 'path' is in 'context'.
return return
@ -796,7 +807,7 @@ void EvalState::mkPos(Value & v, PosIdx p)
} }
void EvalState::mkStorePathString(const StorePath & p, Value & v) void EvalPaths::mkStorePathString(const StorePath & p, Value & v)
{ {
v.mkString( v.mkString(
store->printStorePath(p), store->printStorePath(p),
@ -926,7 +937,7 @@ struct CachedEvalFile
void EvalState::evalFile(const SourcePath & path_, Value & v) void EvalState::evalFile(const SourcePath & path_, Value & v)
{ {
auto path = checkSourcePath(path_); auto path = paths.checkSourcePath(path_);
if (auto i = caches.fileEval.find(path); i != caches.fileEval.end()) { if (auto i = caches.fileEval.find(path); i != caches.fileEval.end()) {
v = i->second->result; v = i->second->result;
@ -940,7 +951,7 @@ void EvalState::evalFile(const SourcePath & path_, Value & v)
} }
debug("evaluating file '%1%'", resolvedPath); debug("evaluating file '%1%'", resolvedPath);
Expr & e = parseExprFromFile(checkSourcePath(resolvedPath)); Expr & e = parseExprFromFile(paths.checkSourcePath(resolvedPath));
try { try {
auto dts = debug auto dts = debug
@ -2271,7 +2282,7 @@ BackedStringView EvalState::coerceToString(
// slash, as in /foo/${x}. // slash, as in /foo/${x}.
v._path v._path
: copyToStore : copyToStore
? store->printStorePath(copyPathToStore(context, v.path())) ? store->printStorePath(paths.copyPathToStore(context, v.path(), repair))
: std::string(v.path().path.abs()); : std::string(v.path().path.abs());
} }
@ -2340,7 +2351,7 @@ BackedStringView EvalState::coerceToString(
} }
StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePath & path) StorePath EvalPaths::copyPathToStore(NixStringContext & context, const SourcePath & path, RepairFlag repair)
{ {
if (nix::isDerivation(path.path.abs())) if (nix::isDerivation(path.path.abs()))
errors.make<EvalError>("file names are not allowed to end in '%1%'", drvExtension).debugThrow(); errors.make<EvalError>("file names are not allowed to end in '%1%'", drvExtension).debugThrow();
@ -2731,13 +2742,13 @@ Expr & EvalState::parseStdin()
} }
SourcePath EvalState::findFile(const std::string_view path) SourcePath EvalPaths::findFile(const std::string_view path)
{ {
return findFile(searchPath, path); return findFile(searchPath_, path);
} }
SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos) SourcePath EvalPaths::findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos)
{ {
for (auto & i : searchPath.elements) { for (auto & i : searchPath.elements) {
auto suffixOpt = i.prefix.suffixIfPotentialMatch(path); auto suffixOpt = i.prefix.suffixIfPotentialMatch(path);
@ -2765,7 +2776,7 @@ SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_
} }
std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Path & value0) std::optional<std::string> EvalPaths::resolveSearchPathPath(const SearchPath::Path & value0)
{ {
auto & value = value0.s; auto & value = value0.s;
auto i = searchPathResolved.find(value); auto i = searchPathResolved.find(value);

View file

@ -360,29 +360,20 @@ struct EvalErrorContext
} }
}; };
class EvalPaths
class EvalState
{ {
friend class EvalBuiltins; ref<Store> store;
public:
SymbolTable symbols;
PosTable positions;
const StaticSymbols s;
EvalMemory mem;
EvalRuntimeCaches caches;
private:
SearchPath searchPath;
public:
EvalBuiltins builtins;
/** /**
* If set, force copying files to the Nix store even if they * Store used to build stuff.
* already exist there.
*/ */
RepairFlag repair; ref<Store> buildStore;
SearchPath searchPath_;
EvalErrorContext & errors;
public:
EvalPaths(const ref<Store> & store, const ref<Store> buildStore, SearchPath searchPath, EvalErrorContext & errors);
const SearchPath & searchPath() const { return searchPath_; }
/** /**
* The allowed filesystem paths in restricted or pure evaluation * The allowed filesystem paths in restricted or pure evaluation
@ -390,19 +381,6 @@ public:
*/ */
std::optional<PathSet> allowedPaths; std::optional<PathSet> allowedPaths;
/**
* Store used to materialise .drv files.
*/
const ref<Store> store;
/**
* Store used to build stuff.
*/
const ref<Store> buildStore;
std::unique_ptr<DebugState> debug;
EvalErrorContext errors;
private: private:
/* Cache for calls to addToStore(); maps source paths to the store /* Cache for calls to addToStore(); maps source paths to the store
@ -417,15 +395,6 @@ private:
std::unordered_map<Path, SourcePath> resolvedPaths; std::unordered_map<Path, SourcePath> resolvedPaths;
public: public:
EvalState(
const SearchPath & _searchPath,
ref<Store> store,
std::shared_ptr<Store> buildStore = nullptr,
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl = nullptr
);
~EvalState();
/** /**
* Allow access to a path. * Allow access to a path.
*/ */
@ -461,6 +430,78 @@ public:
*/ */
Path toRealPath(const Path & path, const NixStringContext & context); Path toRealPath(const Path & path, const NixStringContext & context);
/**
* Look up a file in the search path.
*/
SourcePath findFile(const std::string_view path);
SourcePath findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos = noPos);
/**
* Try to resolve a search path value (not the optinal key part)
*
* If the specified search path element is a URI, download it.
*
* If it is not found, return `std::nullopt`
*/
std::optional<std::string> resolveSearchPathPath(const SearchPath::Path & path);
StorePath copyPathToStore(
NixStringContext & context, const SourcePath & path, RepairFlag repair = NoRepair
);
/**
* Create a string representing a store path.
*
* The string is the printed store path with a context containing a
* single `NixStringContextElem::Opaque` element of that store path.
*/
void mkStorePathString(const StorePath & storePath, Value & v);
/**
* Realise the given context, and return a mapping from the placeholders
* used to construct the associated value to their final store path
*/
[[nodiscard]] StringMap realiseContext(const NixStringContext & context);
};
class EvalState
{
friend class EvalBuiltins;
public:
SymbolTable symbols;
PosTable positions;
const StaticSymbols s;
EvalMemory mem;
EvalRuntimeCaches caches;
EvalPaths paths;
EvalBuiltins builtins;
/**
* If set, force copying files to the Nix store even if they
* already exist there.
*/
RepairFlag repair;
/**
* Store used to materialise .drv files.
*/
const ref<Store> store;
std::unique_ptr<DebugState> debug;
EvalErrorContext errors;
public:
EvalState(
const SearchPath & _searchPath,
ref<Store> store,
std::shared_ptr<Store> buildStore = nullptr,
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl = nullptr
);
~EvalState();
/** /**
* Parse a Nix expression from the specified file. * Parse a Nix expression from the specified file.
*/ */
@ -491,21 +532,6 @@ public:
void resetFileCache(); void resetFileCache();
/**
* Look up a file in the search path.
*/
SourcePath findFile(const std::string_view path);
SourcePath findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos = noPos);
/**
* Try to resolve a search path value (not the optinal key part)
*
* If the specified search path element is a URI, download it.
*
* If it is not found, return `std::nullopt`
*/
std::optional<std::string> resolveSearchPathPath(const SearchPath::Path & path);
/** /**
* Evaluate an expression to normal form * Evaluate an expression to normal form
* *
@ -577,8 +603,6 @@ public:
bool coerceMore = false, bool copyToStore = true, bool coerceMore = false, bool copyToStore = true,
bool canonicalizePath = true); bool canonicalizePath = true);
StorePath copyPathToStore(NixStringContext & context, const SourcePath & path);
/** /**
* Path coercion. * Path coercion.
* *
@ -669,14 +693,6 @@ public:
void mkThunk_(Value & v, Expr & expr); void mkThunk_(Value & v, Expr & expr);
void mkPos(Value & v, PosIdx pos); void mkPos(Value & v, PosIdx pos);
/**
* Create a string representing a store path.
*
* The string is the printed store path with a context containing a
* single `NixStringContextElem::Opaque` element of that store path.
*/
void mkStorePathString(const StorePath & storePath, Value & v);
/** /**
* Create a string representing a `SingleDerivedPath::Built`. * Create a string representing a `SingleDerivedPath::Built`.
* *
@ -735,12 +751,6 @@ public:
*/ */
bool fullGC(); bool fullGC();
/**
* Realise the given context, and return a mapping from the placeholders
* used to construct the associated value to their final store path
*/
[[nodiscard]] StringMap realiseContext(const NixStringContext & context);
private: private:
/** /**

View file

@ -68,7 +68,7 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
debug("got tree '%s' from '%s'", debug("got tree '%s' from '%s'",
state.store->printStorePath(tree.storePath), lockedRef); state.store->printStorePath(tree.storePath), lockedRef);
state.allowPath(tree.storePath); state.paths.allowPath(tree.storePath);
assert(!originalRef.input.getNarHash() || tree.storePath == originalRef.input.computeStorePath(*state.store)); assert(!originalRef.input.getNarHash() || tree.storePath == originalRef.input.computeStorePath(*state.store));
@ -242,8 +242,8 @@ static Flake getFlake(
}; };
// FIXME: symlink attack // FIXME: symlink attack
auto resolvedFlakeFile = resolveExprPath(state.checkSourcePath(CanonPath(flakeFile))); auto resolvedFlakeFile = resolveExprPath(state.paths.checkSourcePath(CanonPath(flakeFile)));
Expr & flakeExpr = state.parseExprFromFile(state.checkSourcePath(resolvedFlakeFile)); Expr & flakeExpr = state.parseExprFromFile(state.paths.checkSourcePath(resolvedFlakeFile));
// Enforce that 'flake.nix' is a direct attrset, not a computation. // Enforce that 'flake.nix' is a direct attrset, not a computation.
if (!(dynamic_cast<ExprAttrs *>(&flakeExpr))) { if (!(dynamic_cast<ExprAttrs *>(&flakeExpr))) {

View file

@ -39,7 +39,7 @@ namespace nix {
* Miscellaneous * Miscellaneous
*************************************************************/ *************************************************************/
StringMap EvalState::realiseContext(const NixStringContext & context) StringMap EvalPaths::realiseContext(const NixStringContext & context)
{ {
std::vector<DerivedPath::Built> drvs; std::vector<DerivedPath::Built> drvs;
StringMap res; StringMap res;
@ -129,12 +129,12 @@ static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, co
auto path = state.coerceToPath(noPos, v, context, "while realising the context of a path"); auto path = state.coerceToPath(noPos, v, context, "while realising the context of a path");
try { try {
StringMap rewrites = state.realiseContext(context); StringMap rewrites = state.paths.realiseContext(context);
auto realPath = CanonPath(state.toRealPath(rewriteStrings(path.path.abs(), rewrites), context)); auto realPath = CanonPath(state.paths.toRealPath(rewriteStrings(path.path.abs(), rewrites), context));
return flags.checkForPureEval return flags.checkForPureEval
? state.checkSourcePath(realPath) ? state.paths.checkSourcePath(realPath)
: realPath; : realPath;
} catch (Error & e) { } catch (Error & e) {
e.addTrace(state.positions[pos], "while realising the context of path '%s'", path); e.addTrace(state.positions[pos], "while realising the context of path '%s'", path);
@ -323,7 +323,7 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
false, false).toOwned()); false, false).toOwned());
} }
try { try {
auto _ = state.realiseContext(context); // FIXME: Handle CA derivations auto _ = state.paths.realiseContext(context); // FIXME: Handle CA derivations
} catch (InvalidPathError & e) { } catch (InvalidPathError & e) {
e.addTrace(state.positions[pos], "while realising the context for builtins.exec"); e.addTrace(state.positions[pos], "while realising the context for builtins.exec");
throw; throw;
@ -1173,7 +1173,7 @@ static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args,
).atPos(pos).debugThrow(); ).atPos(pos).debugThrow();
NixStringContext context; NixStringContext context;
auto path = state.checkSourcePath(state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to builtins.storePath")).path; auto path = state.paths.checkSourcePath(state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to builtins.storePath")).path;
/* Resolve symlinks in path, unless path itself is a symlink /* Resolve symlinks in path, unless path itself is a symlink
directly in the store. The latter condition is necessary so directly in the store. The latter condition is necessary so
e.g. nix-push does the right thing. */ e.g. nix-push does the right thing. */
@ -1207,6 +1207,7 @@ static void prim_pathExists(EvalState & state, const PosIdx pos, Value * * args,
try { try {
auto checked = state auto checked = state
.paths
.checkSourcePath(path) .checkSourcePath(path)
.resolveSymlinks(mustBeDir ? SymlinkResolution::Full : SymlinkResolution::Ancestors); .resolveSymlinks(mustBeDir ? SymlinkResolution::Full : SymlinkResolution::Ancestors);
@ -1305,7 +1306,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
false, false).toOwned(); false, false).toOwned();
try { try {
auto rewrites = state.realiseContext(context); auto rewrites = state.paths.realiseContext(context);
path = rewriteStrings(path, rewrites); path = rewriteStrings(path, rewrites);
} catch (InvalidPathError & e) { } catch (InvalidPathError & e) {
state.errors.make<EvalError>( state.errors.make<EvalError>(
@ -1323,7 +1324,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
auto path = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.findFile"); auto path = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.findFile");
v.mkPath(state.checkSourcePath(state.findFile(searchPath, path, pos))); v.mkPath(state.paths.checkSourcePath(state.paths.findFile(searchPath, path, pos)));
} }
/* Return the cryptographic hash of a file in base-16. */ /* Return the cryptographic hash of a file in base-16. */
@ -1478,7 +1479,7 @@ static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Val
used in args[1]. */ used in args[1]. */
/* Add the output of this to the allowed paths. */ /* Add the output of this to the allowed paths. */
state.allowAndSetStorePathString(storePath, v); state.paths.allowAndSetStorePathString(storePath, v);
} }
static void addPath( static void addPath(
@ -1495,8 +1496,8 @@ static void addPath(
try { try {
// FIXME: handle CA derivation outputs (where path needs to // FIXME: handle CA derivation outputs (where path needs to
// be rewritten to the actual output). // be rewritten to the actual output).
auto rewrites = state.realiseContext(context); auto rewrites = state.paths.realiseContext(context);
path = state.toRealPath(rewriteStrings(path, rewrites), context); path = state.paths.toRealPath(rewriteStrings(path, rewrites), context);
StorePathSet refs; StorePathSet refs;
@ -1512,7 +1513,7 @@ static void addPath(
path = evalSettings.pureEval && expectedHash path = evalSettings.pureEval && expectedHash
? path ? path
: state.checkSourcePath(CanonPath(path)).path.abs(); : state.paths.checkSourcePath(CanonPath(path)).path.abs();
PathFilter filter = filterFun ? ([&](const Path & path) { PathFilter filter = filterFun ? ([&](const Path & path) {
auto st = lstat(path); auto st = lstat(path);
@ -1552,9 +1553,9 @@ static void addPath(
"store path mismatch in (possibly filtered) path added from '%s'", "store path mismatch in (possibly filtered) path added from '%s'",
path path
).atPos(pos).debugThrow(); ).atPos(pos).debugThrow();
state.allowAndSetStorePathString(dstPath, v); state.paths.allowAndSetStorePathString(dstPath, v);
} else } else
state.allowAndSetStorePathString(*expectedStorePath, v); state.paths.allowAndSetStorePathString(*expectedStorePath, v);
} catch (Error & e) { } catch (Error & e) {
e.addTrace(state.positions[pos], "while adding path '%s'", path); e.addTrace(state.positions[pos], "while adding path '%s'", path);
throw; throw;

View file

@ -58,7 +58,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor
}); });
} }
state.mkStorePathString(toPath, v); state.paths.mkStorePathString(toPath, v);
} }
/** /**
@ -84,7 +84,7 @@ static void runFetchClosureWithContentAddressedPath(EvalState & state, const Pos
}); });
} }
state.mkStorePathString(fromPath, v); state.paths.mkStorePathString(fromPath, v);
} }
/** /**
@ -107,7 +107,7 @@ static void runFetchClosureWithInputAddressedPath(EvalState & state, const PosId
}); });
} }
state.mkStorePathString(fromPath, v); state.paths.mkStorePathString(fromPath, v);
} }
typedef std::optional<StorePath> StorePathOrGap; typedef std::optional<StorePath> StorePathOrGap;

View file

@ -51,7 +51,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
// FIXME: git externals probably can be used to bypass the URI // FIXME: git externals probably can be used to bypass the URI
// whitelist. Ah well. // whitelist. Ah well.
state.checkURI(url); state.paths.checkURI(url);
if (evalSettings.pureEval && !rev) if (evalSettings.pureEval && !rev)
throw Error("in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision"); throw Error("in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision");
@ -68,7 +68,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
auto [tree, input2] = input.fetch(state.store); auto [tree, input2] = input.fetch(state.store);
auto attrs2 = state.buildBindings(8); auto attrs2 = state.buildBindings(8);
state.mkStorePathString(tree.storePath, attrs2.alloc(state.s.outPath)); state.paths.mkStorePathString(tree.storePath, attrs2.alloc(state.s.outPath));
if (input2.getRef()) if (input2.getRef())
attrs2.alloc("branch").mkString(*input2.getRef()); attrs2.alloc("branch").mkString(*input2.getRef());
// Backward compatibility: set 'rev' to // Backward compatibility: set 'rev' to
@ -80,7 +80,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
attrs2.alloc("revCount").mkInt(*revCount); attrs2.alloc("revCount").mkInt(*revCount);
v.mkAttrs(attrs2); v.mkAttrs(attrs2);
state.allowPath(tree.storePath); state.paths.allowPath(tree.storePath);
} }
static RegisterPrimOp r_fetchMercurial({ static RegisterPrimOp r_fetchMercurial({

View file

@ -27,7 +27,7 @@ void emitTreeAttrs(
auto attrs = state.buildBindings(10); auto attrs = state.buildBindings(10);
state.mkStorePathString(tree.storePath, attrs.alloc(state.s.outPath)); state.paths.mkStorePathString(tree.storePath, attrs.alloc(state.s.outPath));
// FIXME: support arbitrary input attributes. // FIXME: support arbitrary input attributes.
@ -74,7 +74,7 @@ void emitTreeAttrs(
std::string fixURI(std::string uri, EvalState & state, const std::string & defaultScheme = "file") std::string fixURI(std::string uri, EvalState & state, const std::string & defaultScheme = "file")
{ {
state.checkURI(uri); state.paths.checkURI(uri);
if (uri.find("://") == std::string::npos) { if (uri.find("://") == std::string::npos) {
const auto p = ParsedURL { const auto p = ParsedURL {
.scheme = defaultScheme, .scheme = defaultScheme,
@ -194,7 +194,7 @@ static void fetchTree(
auto [tree, input2] = input.fetch(state.store); auto [tree, input2] = input.fetch(state.store);
state.allowPath(tree.storePath); state.paths.allowPath(tree.storePath);
emitTreeAttrs(state, tree, input2, v, params.emptyRevFallback, false); emitTreeAttrs(state, tree, input2, v, params.emptyRevFallback, false);
} }
@ -244,7 +244,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
if (who == "fetchTarball") if (who == "fetchTarball")
url = evalSettings.resolvePseudoUrl(*url); url = evalSettings.resolvePseudoUrl(*url);
state.checkURI(*url); state.paths.checkURI(*url);
if (name == "") if (name == "")
name = baseNameOf(*url); name = baseNameOf(*url);
@ -263,7 +263,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
}); });
if (state.store->isValidPath(expectedPath)) { if (state.store->isValidPath(expectedPath)) {
state.allowAndSetStorePathString(expectedPath, v); state.paths.allowAndSetStorePathString(expectedPath, v);
return; return;
} }
} }
@ -290,7 +290,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
} }
} }
state.allowAndSetStorePathString(storePath, v); state.paths.allowAndSetStorePathString(storePath, v);
} }
void prim_fetchurl(EvalState & state, const PosIdx pos, Value * * args, Value & v) void prim_fetchurl(EvalState & state, const PosIdx pos, Value * * args, Value & v)

View file

@ -37,7 +37,7 @@ json printValueAsJSON(EvalState & state, bool strict,
case nPath: case nPath:
if (copyToStore) if (copyToStore)
out = state.store->printStorePath( out = state.store->printStorePath(
state.copyPathToStore(context, v.path())); state.paths.copyPathToStore(context, v.path(), state.repair));
else else
out = v.path().path.abs(); out = v.path().path.abs();
break; break;

View file

@ -26,7 +26,7 @@ RC_GTEST_FIXTURE_PROP(
(const SingleDerivedPath::Opaque & o)) (const SingleDerivedPath::Opaque & o))
{ {
auto * v = state.mem.allocValue(); auto * v = state.mem.allocValue();
state.mkStorePathString(o.path, *v); state.paths.mkStorePathString(o.path, *v);
auto d = state.coerceToSingleDerivedPath(noPos, *v, ""); auto d = state.coerceToSingleDerivedPath(noPos, *v, "");
RC_ASSERT(SingleDerivedPath { o } == d); RC_ASSERT(SingleDerivedPath { o } == d);
} }