aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2023-04-24 13:20:36 +0200
committerEelco Dolstra <edolstra@gmail.com>2023-04-24 13:20:36 +0200
commit01232358ffd78600d170ca5c1526a7031f6f2762 (patch)
treebabf00196894ec8b79fb963419fe4a6d44e56db4 /src/libexpr
parentcb2615cf4735cf28a6e538544c9abbf40cdd24a9 (diff)
parent7474a90db69813d051ab1bef35c7d0ab958d9ccd (diff)
Merge remote-tracking branch 'origin/master' into source-path
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/attr-path.cc2
-rw-r--r--src/libexpr/eval-cache.cc12
-rw-r--r--src/libexpr/eval.cc58
-rw-r--r--src/libexpr/eval.hh24
-rw-r--r--src/libexpr/flake/config.cc2
-rw-r--r--src/libexpr/flake/flake.cc2
-rw-r--r--src/libexpr/get-drvs.cc6
-rw-r--r--src/libexpr/primops.cc118
-rw-r--r--src/libexpr/primops/context.cc54
-rw-r--r--src/libexpr/primops/fetchClosure.cc7
-rw-r--r--src/libexpr/primops/fetchMercurial.cc5
-rw-r--r--src/libexpr/primops/fetchTree.cc18
-rw-r--r--src/libexpr/tests/json.cc2
-rw-r--r--src/libexpr/tests/value/context.cc61
-rw-r--r--src/libexpr/value-to-json.cc6
-rw-r--r--src/libexpr/value-to-json.hh4
-rw-r--r--src/libexpr/value-to-xml.cc10
-rw-r--r--src/libexpr/value-to-xml.hh2
-rw-r--r--src/libexpr/value.hh12
-rw-r--r--src/libexpr/value/context.cc17
-rw-r--r--src/libexpr/value/context.hh15
21 files changed, 235 insertions, 202 deletions
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index 8ae4270e6..ab654c1b0 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -118,7 +118,7 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
// FIXME: is it possible to extract the Pos object instead of doing this
// toString + parsing?
- PathSet context;
+ NixStringContext context;
auto path = state.coerceToPath(noPos, *v2, context, "while evaluating the 'meta.position' attribute of a derivation");
auto fn = path.path.abs();
diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc
index ec4ad2f5e..ac646af8a 100644
--- a/src/libexpr/eval-cache.cc
+++ b/src/libexpr/eval-cache.cc
@@ -47,7 +47,7 @@ struct AttrDb
{
auto state(_state->lock());
- Path cacheDir = getCacheDir() + "/nix/eval-cache-v4";
+ Path cacheDir = getCacheDir() + "/nix/eval-cache-v5";
createDirs(cacheDir);
Path dbPath = cacheDir + "/" + fingerprint.to_string(Base16, false) + ".sqlite";
@@ -300,7 +300,7 @@ struct AttrDb
NixStringContext context;
if (!queryAttribute.isNull(3))
for (auto & s : tokenizeString<std::vector<std::string>>(queryAttribute.getStr(3), ";"))
- context.push_back(NixStringContextElem::parse(cfg, s));
+ context.insert(NixStringContextElem::parse(s));
return {{rowId, string_t{queryAttribute.getStr(2), context}}};
}
case AttrType::Bool:
@@ -621,9 +621,11 @@ string_t AttrCursor::getStringWithContext()
auto & v = forceValue();
- if (v.type() == nString)
- return {v.string.s, v.getContext(*root->state.store)};
- else if (v.type() == nPath)
+ if (v.type() == nString) {
+ NixStringContext context;
+ copyContext(v, context);
+ return {v.string.s, std::move(context)};
+ } else if (v.type() == nPath)
return {v.path().to_string(), {}};
else
root->state.error("'%s' is not a string but %s", getAttrPathStr()).debugThrow<TypeError>();
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index d6daf2727..e2b455b91 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -610,8 +610,7 @@ void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value &
{
allowPath(storePath);
- auto path = store->printStorePath(storePath);
- v.mkString(path, PathSet({path}));
+ mkStorePathString(storePath, v);
}
SourcePath EvalState::checkSourcePath(const SourcePath & path_)
@@ -693,7 +692,7 @@ void EvalState::checkURI(const std::string & uri)
}
-Path EvalState::toRealPath(const Path & path, const PathSet & context)
+Path EvalState::toRealPath(const Path & path, const NixStringContext & context)
{
// FIXME: check whether 'path' is in 'context'.
return
@@ -945,25 +944,25 @@ void Value::mkString(std::string_view s)
}
-static void copyContextToValue(Value & v, const PathSet & context)
+static void copyContextToValue(Value & v, const NixStringContext & context)
{
if (!context.empty()) {
size_t n = 0;
v.string.context = (const char * *)
allocBytes((context.size() + 1) * sizeof(char *));
for (auto & i : context)
- v.string.context[n++] = dupString(i.c_str());
+ v.string.context[n++] = dupString(i.to_string().c_str());
v.string.context[n] = 0;
}
}
-void Value::mkString(std::string_view s, const PathSet & context)
+void Value::mkString(std::string_view s, const NixStringContext & context)
{
mkString(s);
copyContextToValue(*this, context);
}
-void Value::mkStringMove(const char * s, const PathSet & context)
+void Value::mkStringMove(const char * s, const NixStringContext & context)
{
mkString(s);
copyContextToValue(*this, context);
@@ -1039,6 +1038,16 @@ void EvalState::mkPos(Value & v, PosIdx p)
}
+void EvalState::mkStorePathString(const StorePath & p, Value & v)
+{
+ v.mkString(
+ store->printStorePath(p),
+ NixStringContext {
+ NixStringContextElem::Opaque { .path = p },
+ });
+}
+
+
/* Create a thunk for the delayed computation of the given expression
in the given environment. But if the expression is a variable,
then look it up right away. This significantly reduces the number
@@ -1901,7 +1910,7 @@ void EvalState::concatLists(Value & v, size_t nrLists, Value * * lists, const Po
void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
{
- PathSet context;
+ NixStringContext context;
std::vector<BackedStringView> s;
size_t sSize = 0;
NixInt n = 0;
@@ -2110,26 +2119,15 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string
}
-void copyContext(const Value & v, PathSet & context)
+void copyContext(const Value & v, NixStringContext & context)
{
if (v.string.context)
for (const char * * p = v.string.context; *p; ++p)
- context.insert(*p);
+ context.insert(NixStringContextElem::parse(*p));
}
-NixStringContext Value::getContext(const Store & store)
-{
- NixStringContext res;
- assert(internalType == tString);
- if (string.context)
- for (const char * * p = string.context; *p; ++p)
- res.push_back(NixStringContextElem::parse(store, *p));
- return res;
-}
-
-
-std::string_view EvalState::forceString(Value & v, PathSet & context, const PosIdx pos, std::string_view errorCtx)
+std::string_view EvalState::forceString(Value & v, NixStringContext & context, const PosIdx pos, std::string_view errorCtx)
{
auto s = forceString(v, pos, errorCtx);
copyContext(v, context);
@@ -2159,7 +2157,7 @@ bool EvalState::isDerivation(Value & v)
std::optional<std::string> EvalState::tryAttrsToString(const PosIdx pos, Value & v,
- PathSet & context, bool coerceMore, bool copyToStore)
+ NixStringContext & context, bool coerceMore, bool copyToStore)
{
auto i = v.attrs->find(sToString);
if (i != v.attrs->end()) {
@@ -2176,7 +2174,7 @@ std::optional<std::string> EvalState::tryAttrsToString(const PosIdx pos, Value &
BackedStringView EvalState::coerceToString(
const PosIdx pos,
Value & v,
- PathSet & context,
+ NixStringContext & context,
std::string_view errorCtx,
bool coerceMore,
bool copyToStore,
@@ -2258,7 +2256,7 @@ BackedStringView EvalState::coerceToString(
}
-StorePath EvalState::copyPathToStore(PathSet & context, const SourcePath & path)
+StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePath & path)
{
if (nix::isDerivation(path.path.abs()))
error("file names are not allowed to end in '%1%'", drvExtension).debugThrow<EvalError>();
@@ -2275,12 +2273,14 @@ StorePath EvalState::copyPathToStore(PathSet & context, const SourcePath & path)
return dstPath;
}();
- context.insert(store->printStorePath(dstPath));
+ context.insert(NixStringContextElem::Opaque {
+ .path = dstPath
+ });
return dstPath;
}
-SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & context, std::string_view errorCtx)
+SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx)
{
auto path = coerceToString(pos, v, context, errorCtx, false, false, true).toOwned();
if (path == "" || path[0] != '/')
@@ -2289,7 +2289,7 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & contex
}
-StorePath EvalState::coerceToStorePath(const PosIdx pos, Value & v, PathSet & context, std::string_view errorCtx)
+StorePath EvalState::coerceToStorePath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx)
{
auto path = coerceToString(pos, v, context, errorCtx, false, false, true).toOwned();
if (auto storePath = store->maybeParseStorePath(path))
@@ -2496,7 +2496,7 @@ void EvalState::printStats()
}
-std::string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const
+std::string ExternalValueBase::coerceToString(const Pos & pos, NixStringContext & context, bool copyMore, bool copyToStore) const
{
throw TypeError({
.msg = hintfmt("cannot coerce %1% to a string", showType())
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index dea8b4a3a..bb3ac2b22 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -57,7 +57,7 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env &
std::unique_ptr<ValMap> mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env);
-void copyContext(const Value & v, PathSet & context);
+void copyContext(const Value & v, NixStringContext & context);
std::string printValue(const EvalState & state, const Value & v);
@@ -330,7 +330,7 @@ public:
* intended to distinguish between import-from-derivation and
* sources stored in the actual /nix/store.
*/
- Path toRealPath(const Path & path, const PathSet & context);
+ Path toRealPath(const Path & path, const NixStringContext & context);
/**
* Parse a Nix expression from the specified file.
@@ -426,7 +426,7 @@ public:
*/
void forceFunction(Value & v, const PosIdx pos, std::string_view errorCtx);
std::string_view forceString(Value & v, const PosIdx pos, std::string_view errorCtx);
- std::string_view forceString(Value & v, PathSet & context, const PosIdx pos, std::string_view errorCtx);
+ std::string_view forceString(Value & v, NixStringContext & context, const PosIdx pos, std::string_view errorCtx);
std::string_view forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx);
[[gnu::noinline]]
@@ -442,7 +442,7 @@ public:
bool isDerivation(Value & v);
std::optional<std::string> tryAttrsToString(const PosIdx pos, Value & v,
- PathSet & context, bool coerceMore = false, bool copyToStore = true);
+ NixStringContext & context, bool coerceMore = false, bool copyToStore = true);
/**
* String coercion.
@@ -452,12 +452,12 @@ public:
* booleans and lists to a string. If `copyToStore` is set,
* referenced paths are copied to the Nix store as a side effect.
*/
- BackedStringView coerceToString(const PosIdx pos, Value & v, PathSet & context,
+ BackedStringView coerceToString(const PosIdx pos, Value & v, NixStringContext & context,
std::string_view errorCtx,
bool coerceMore = false, bool copyToStore = true,
bool canonicalizePath = true);
- StorePath copyPathToStore(PathSet & context, const SourcePath & path);
+ StorePath copyPathToStore(NixStringContext & context, const SourcePath & path);
/**
* Path coercion.
@@ -466,12 +466,12 @@ public:
* path. The result is guaranteed to be a canonicalised, absolute
* path. Nothing is copied to the store.
*/
- SourcePath coerceToPath(const PosIdx pos, Value & v, PathSet & context, std::string_view errorCtx);
+ SourcePath coerceToPath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx);
/**
* Like coerceToPath, but the result must be a store path.
*/
- StorePath coerceToStorePath(const PosIdx pos, Value & v, PathSet & context, std::string_view errorCtx);
+ StorePath coerceToStorePath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx);
public:
@@ -576,6 +576,12 @@ public:
void mkThunk_(Value & v, Expr * expr);
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
+ `Opaque` element of that store path. */
+ void mkStorePathString(const StorePath & storePath, Value & v);
+
void concatLists(Value & v, size_t nrLists, Value * * lists, const PosIdx pos, std::string_view errorCtx);
/**
@@ -587,7 +593,7 @@ public:
* 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 PathSet & context);
+ [[nodiscard]] StringMap realiseContext(const NixStringContext & context);
private:
diff --git a/src/libexpr/flake/config.cc b/src/libexpr/flake/config.cc
index 89ddbde7e..e89014862 100644
--- a/src/libexpr/flake/config.cc
+++ b/src/libexpr/flake/config.cc
@@ -31,7 +31,7 @@ static void writeTrustedList(const TrustedList & trustedList)
void ConfigFile::apply()
{
- std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry"};
+ std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lockfile-summary"};
for (auto & [name, value] : settings) {
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index ccf868361..60bb6a71e 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -265,7 +265,7 @@ static Flake getFlake(
state.symbols[setting.name],
std::string(state.forceStringNoCtx(*setting.value, setting.pos, "")));
else if (setting.value->type() == nPath) {
- PathSet emptyContext = {};
+ NixStringContext emptyContext = {};
flake.config.settings.emplace(
state.symbols[setting.name],
state.coerceToString(setting.pos, *setting.value, emptyContext, "", false, true, true) .toOwned());
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 1602fbffb..506a63677 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -71,7 +71,7 @@ std::optional<StorePath> DrvInfo::queryDrvPath() const
{
if (!drvPath && attrs) {
Bindings::iterator i = attrs->find(state->sDrvPath);
- PathSet context;
+ NixStringContext context;
if (i == attrs->end())
drvPath = {std::nullopt};
else
@@ -93,7 +93,7 @@ StorePath DrvInfo::queryOutPath() const
{
if (!outPath && attrs) {
Bindings::iterator i = attrs->find(state->sOutPath);
- PathSet context;
+ NixStringContext context;
if (i != attrs->end())
outPath = state->coerceToStorePath(i->pos, *i->value, context, "while evaluating the output path of a derivation");
}
@@ -124,7 +124,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool withPaths, bool onlyOutputsToInstall
/* And evaluate its ‘outPath’ attribute. */
Bindings::iterator outPath = out->value->attrs->find(state->sOutPath);
if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
- PathSet context;
+ NixStringContext context;
outputs.emplace(output, state->coerceToStorePath(outPath->pos, *outPath->value, context, "while evaluating an output path of a derivation"));
} else
outputs.emplace(output, std::nullopt);
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 60bf45147..cea5b4202 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -38,17 +38,16 @@ namespace nix {
InvalidPathError::InvalidPathError(const Path & path) :
EvalError("path '%s' is not valid", path), path(path) {}
-StringMap EvalState::realiseContext(const PathSet & context)
+StringMap EvalState::realiseContext(const NixStringContext & context)
{
std::vector<DerivedPath::Built> drvs;
StringMap res;
- for (auto & c_ : context) {
+ for (auto & c : context) {
auto ensureValid = [&](const StorePath & p) {
if (!store->isValidPath(p))
debugThrowLastTrace(InvalidPathError(store->printStorePath(p)));
};
- auto c = NixStringContextElem::parse(*store, c_);
std::visit(overloaded {
[&](const NixStringContextElem::Built & b) {
drvs.push_back(DerivedPath::Built {
@@ -112,7 +111,7 @@ struct RealisePathFlags {
static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, const RealisePathFlags flags = {})
{
- PathSet context;
+ NixStringContext context;
auto path = state.coerceToPath(noPos, v, context, "while realising the context of a path");
@@ -158,7 +157,12 @@ static void mkOutputString(
/* FIXME: we need to depend on the basic derivation, not
derivation */
: downstreamPlaceholder(*state.store, drvPath, o.first),
- {"!" + o.first + "!" + state.store->printStorePath(drvPath)});
+ NixStringContext {
+ NixStringContextElem::Built {
+ .drvPath = drvPath,
+ .output = o.first,
+ }
+ });
}
/* Load and evaluate an expression from path specified by the
@@ -178,17 +182,18 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v
return storePath;
};
- if (auto optStorePath = isValidDerivationInStore()) {
- auto storePath = *optStorePath;
- Derivation drv = state.store->readDerivation(storePath);
+ if (auto storePath = isValidDerivationInStore()) {
+ Derivation drv = state.store->readDerivation(*storePath);
auto attrs = state.buildBindings(3 + drv.outputs.size());
- attrs.alloc(state.sDrvPath).mkString(path2, {"=" + path2});
+ attrs.alloc(state.sDrvPath).mkString(path2, {
+ NixStringContextElem::DrvDeep { .drvPath = *storePath },
+ });
attrs.alloc(state.sName).mkString(drv.env["name"]);
auto & outputsVal = attrs.alloc(state.sOutputs);
state.mkList(outputsVal, drv.outputs.size());
for (const auto & [i, o] : enumerate(drv.outputs)) {
- mkOutputString(state, attrs, storePath, drv, o);
+ mkOutputString(state, attrs, *storePath, drv, o);
(outputsVal.listElems()[i] = state.allocValue())->mkString(o.first);
}
@@ -359,7 +364,7 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
auto count = args[0]->listSize();
if (count == 0)
state.error("at least one argument to 'exec' required").atPos(pos).debugThrow<EvalError>();
- PathSet context;
+ NixStringContext context;
auto program = state.coerceToString(pos, *elems[0], context,
"while evaluating the first element of the argument passed to builtins.exec",
false, false).toOwned();
@@ -769,7 +774,7 @@ static RegisterPrimOp primop_abort({
)",
.fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context,
"while evaluating the error message passed to builtins.abort").toOwned();
state.debugThrowLastTrace(Abort("evaluation aborted with the following error message: '%1%'", s));
@@ -788,7 +793,7 @@ static RegisterPrimOp primop_throw({
)",
.fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context,
"while evaluating the error message passed to builtin.throw").toOwned();
state.debugThrowLastTrace(ThrownError(s));
@@ -801,7 +806,7 @@ static void prim_addErrorContext(EvalState & state, const PosIdx pos, Value * *
state.forceValue(*args[1], pos);
v = *args[1];
} catch (Error & e) {
- PathSet context;
+ NixStringContext context;
auto message = state.coerceToString(pos, *args[0], context,
"while evaluating the error message passed to builtins.addErrorContext",
false, false).toOwned();
@@ -1087,7 +1092,7 @@ drvName, Bindings * attrs, Value & v)
Derivation drv;
drv.name = drvName;
- PathSet context;
+ NixStringContext context;
bool contentAddressed = false;
bool isImpure = false;
@@ -1233,8 +1238,7 @@ drvName, Bindings * attrs, Value & v)
/* Everything in the context of the strings in the derivation
attributes should be added as dependencies of the resulting
derivation. */
- for (auto & c_ : context) {
- auto c = NixStringContextElem::parse(*state.store, c_);
+ for (auto & c : context) {
std::visit(overloaded {
/* Since this allows the builder to gain access to every
path in the dependency graph of the derivation (including
@@ -1294,7 +1298,13 @@ drvName, Bindings * attrs, Value & v)
auto h = newHashAllowEmpty(*outputHash, parseHashTypeOpt(outputHashAlgo));
auto method = ingestionMethod.value_or(FileIngestionMethod::Flat);
- auto outPath = state.store->makeFixedOutputPath(method, h, drvName);
+ auto outPath = state.store->makeFixedOutputPath(drvName, FixedOutputInfo {
+ .hash = {
+ .method = method,
+ .hash = h,
+ },
+ .references = {},
+ });
drv.env["out"] = state.store->printStorePath(outPath);
drv.outputs.insert_or_assign("out",
DerivationOutput::CAFixed {
@@ -1387,7 +1397,9 @@ drvName, Bindings * attrs, Value & v)
}
auto result = state.buildBindings(1 + drv.outputs.size());
- result.alloc(state.sDrvPath).mkString(drvPathS, {"=" + drvPathS});
+ result.alloc(state.sDrvPath).mkString(drvPathS, {
+ NixStringContextElem::DrvDeep { .drvPath = drvPath },
+ });
for (auto & i : drv.outputs)
mkOutputString(state, result, drvPath, drv, i);
@@ -1432,7 +1444,7 @@ static RegisterPrimOp primop_placeholder({
/* Convert the argument to a path. !!! obsolete? */
static void prim_toPath(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto path = state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to builtins.toPath");
v.mkString(path.path.abs(), context);
}
@@ -1463,7 +1475,7 @@ static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args,
.errPos = state.positions[pos]
}));
- PathSet context;
+ NixStringContext context;
auto path = state.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
directly in the store. The latter condition is necessary so
@@ -1478,7 +1490,7 @@ static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args,
auto path2 = state.store->toStorePath(path.abs()).first;
if (!settings.readOnlyMode)
state.store->ensurePath(path2);
- context.insert(state.store->printStorePath(path2));
+ context.insert(NixStringContextElem::Opaque { .path = path2 });
v.mkString(path.abs(), context);
}
@@ -1534,7 +1546,7 @@ static RegisterPrimOp primop_pathExists({
following the last slash. */
static void prim_baseNameOf(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
v.mkString(baseNameOf(*state.coerceToString(pos, *args[0], context,
"while evaluating the first argument passed to builtins.baseNameOf",
false, false)), context);
@@ -1556,12 +1568,12 @@ static RegisterPrimOp primop_baseNameOf({
of the argument. */
static void prim_dirOf(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
state.forceValue(*args[0], pos);
if (args[0]->type() == nPath) {
auto path = args[0]->path();
v.mkPath(path.path.isRoot() ? path : path.parent());
} else {
+ NixStringContext context;
auto path = state.coerceToString(pos, *args[0], context,
"while evaluating the first argument passed to 'builtins.dirOf'",
false, false);
@@ -1599,7 +1611,12 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V
refsSink << s;
refs = refsSink.getResultPaths();
}
- auto context = state.store->printStorePathSet(refs);
+ NixStringContext context;
+ for (auto && p : std::move(refs)) {
+ context.insert(NixStringContextElem::Opaque {
+ .path = std::move((StorePath &&)p),
+ });
+ }
v.mkString(s, context);
}
@@ -1630,7 +1647,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
i = getAttr(state, state.sPath, v2->attrs, "in an element of the __nixPath");
- PathSet context;
+ NixStringContext context;
auto path = state.coerceToString(pos, *i->value, context,
"while evaluating the `path` attribute of an element of the list passed to builtins.findFile",
false, false).toOwned();
@@ -1781,7 +1798,7 @@ static RegisterPrimOp primop_readDir({
static void prim_toXML(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
std::ostringstream out;
- PathSet context;
+ NixStringContext context;
printValueAsXML(state, true, false, *args[0], out, context, pos);
v.mkString(out.str(), context);
}
@@ -1889,7 +1906,7 @@ static RegisterPrimOp primop_toXML({
static void prim_toJSON(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
std::ostringstream out;
- PathSet context;
+ NixStringContext context;
printValueAsJSON(state, true, *args[0], pos, out, context);
v.mkString(out.str(), context);
}
@@ -1939,22 +1956,23 @@ static RegisterPrimOp primop_fromJSON({
as an input by derivations. */
static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
std::string name(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.toFile"));
std::string contents(state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.toFile"));
StorePathSet refs;
- for (auto path : context) {
- if (path.at(0) != '/')
+ for (auto c : context) {
+ if (auto p = std::get_if<NixStringContextElem::Opaque>(&c))
+ refs.insert(p->path);
+ else
state.debugThrowLastTrace(EvalError({
.msg = hintfmt(
"in 'toFile': the file named '%1%' must not contain a reference "
"to a derivation but contains (%2%)",
- name, path),
+ name, c.to_string()),
.errPos = state.positions[pos]
}));
- refs.insert(state.store->parseStorePath(path));
}
auto storePath = settings.readOnlyMode
@@ -2055,7 +2073,7 @@ static void addPath(
FileIngestionMethod method,
const std::optional<Hash> expectedHash,
Value & v,
- const PathSet & context)
+ const NixStringContext & context)
{
try {
// FIXME: handle CA derivation outputs (where path needs to
@@ -2103,7 +2121,13 @@ static void addPath(
std::optional<StorePath> expectedStorePath;
if (expectedHash)
- expectedStorePath = state.store->makeFixedOutputPath(method, *expectedHash, name);
+ expectedStorePath = state.store->makeFixedOutputPath(name, FixedOutputInfo {
+ .hash = {
+ .method = method,
+ .hash = *expectedHash,
+ },
+ .references = {},
+ });
if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) {
StorePath dstPath = settings.readOnlyMode
@@ -2123,7 +2147,7 @@ static void addPath(
static void prim_filterSource(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto path = state.coerceToPath(pos, *args[1], context,
"while evaluating the second argument (the path to filter) passed to builtins.filterSource");
state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.filterSource");
@@ -2192,7 +2216,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
Value * filterFun = nullptr;
auto method = FileIngestionMethod::Recursive;
std::optional<Hash> expectedHash;
- PathSet context;
+ NixStringContext context;
state.forceAttrs(*args[0], pos, "while evaluating the argument passed to 'builtins.path'");
@@ -3528,7 +3552,7 @@ static RegisterPrimOp primop_lessThan({
`"/nix/store/whatever..."'. */
static void prim_toString(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context,
"while evaluating the first argument passed to builtins.toString",
true, false);
@@ -3567,7 +3591,7 @@ static void prim_substring(EvalState & state, const PosIdx pos, Value * * args,
{
int start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring");
int len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring");
- PathSet context;
+ NixStringContext context;
auto s = state.coerceToString(pos, *args[2], context, "while evaluating the third argument (the string) passed to builtins.substring");
if (start < 0)
@@ -3601,7 +3625,7 @@ static RegisterPrimOp primop_substring({
static void prim_stringLength(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.stringLength");
v.mkInt(s->size());
}
@@ -3627,7 +3651,7 @@ static void prim_hashString(EvalState & state, const PosIdx pos, Value * * args,
.errPos = state.positions[pos]
}));
- PathSet context; // discarded
+ NixStringContext context; // discarded
auto s = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.hashString");
v.mkString(hashString(*ht, s).to_string(Base16, false));
@@ -3673,7 +3697,7 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v)
auto regex = state.regexCache->get(re);
- PathSet context;
+ NixStringContext context;
const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.match");
std::cmatch match;
@@ -3753,7 +3777,7 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)
auto regex = state.regexCache->get(re);
- PathSet context;
+ NixStringContext context;
const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.split");
auto begin = std::cregex_iterator(str.begin(), str.end(), regex);
@@ -3850,7 +3874,7 @@ static RegisterPrimOp primop_split({
static void prim_concatStringsSep(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto sep = state.forceString(*args[0], context, pos, "while evaluating the first argument (the separator string) passed to builtins.concatStringsSep");
state.forceList(*args[1], pos, "while evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep");
@@ -3890,15 +3914,15 @@ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * a
for (auto elem : args[0]->listItems())
from.emplace_back(state.forceString(*elem, pos, "while evaluating one of the strings to replace passed to builtins.replaceStrings"));
- std::vector<std::pair<std::string, PathSet>> to;
+ std::vector<std::pair<std::string, NixStringContext>> to;
to.reserve(args[1]->listSize());
for (auto elem : args[1]->listItems()) {
- PathSet ctx;
+ NixStringContext ctx;
auto s = state.forceString(*elem, ctx, pos, "while evaluating one of the replacement strings passed to builtins.replaceStrings");
to.emplace_back(s, std::move(ctx));
}
- PathSet context;
+ NixStringContext context;
auto s = state.forceString(*args[2], context, pos, "while evaluating the third argument passed to builtins.replaceStrings");
std::string res;
diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc
index db43e5771..07bf400cf 100644
--- a/src/libexpr/primops/context.cc
+++ b/src/libexpr/primops/context.cc
@@ -7,7 +7,7 @@ namespace nix {
static void prim_unsafeDiscardStringContext(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.unsafeDiscardStringContext");
v.mkString(*s);
}
@@ -17,7 +17,7 @@ static RegisterPrimOp primop_unsafeDiscardStringContext("__unsafeDiscardStringCo
static void prim_hasContext(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
state.forceString(*args[0], context, pos, "while evaluating the argument passed to builtins.hasContext");
v.mkBool(!context.empty());
}
@@ -33,17 +33,18 @@ static RegisterPrimOp primop_hasContext("__hasContext", 1, prim_hasContext);
drv.inputDrvs. */
static void prim_unsafeDiscardOutputDependency(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.unsafeDiscardOutputDependency");
- PathSet context2;
- for (auto && p : context) {
- auto c = NixStringContextElem::parse(*state.store, p);
+ NixStringContext context2;
+ for (auto && c : context) {
if (auto * ptr = std::get_if<NixStringContextElem::DrvDeep>(&c)) {
- context2.emplace(state.store->printStorePath(ptr->drvPath));
+ context2.emplace(NixStringContextElem::Opaque {
+ .path = ptr->drvPath
+ });
} else {
/* Can reuse original item */
- context2.emplace(std::move(p));
+ context2.emplace(std::move(c));
}
}
@@ -79,22 +80,21 @@ static void prim_getContext(EvalState & state, const PosIdx pos, Value * * args,
bool allOutputs = false;
Strings outputs;
};
- PathSet context;
+ NixStringContext context;
state.forceString(*args[0], context, pos, "while evaluating the argument passed to builtins.getContext");
auto contextInfos = std::map<StorePath, ContextInfo>();
- for (const auto & p : context) {
- NixStringContextElem ctx = NixStringContextElem::parse(*state.store, p);
+ for (auto && i : context) {
std::visit(overloaded {
- [&](NixStringContextElem::DrvDeep & d) {
- contextInfos[d.drvPath].allOutputs = true;
+ [&](NixStringContextElem::DrvDeep && d) {
+ contextInfos[std::move(d.drvPath)].allOutputs = true;
},
- [&](NixStringContextElem::Built & b) {
- contextInfos[b.drvPath].outputs.emplace_back(std::move(b.output));
+ [&](NixStringContextElem::Built && b) {
+ contextInfos[std::move(b.drvPath)].outputs.emplace_back(std::move(b.output));
},
- [&](NixStringContextElem::Opaque & o) {
- contextInfos[o.path].path = true;
+ [&](NixStringContextElem::Opaque && o) {
+ contextInfos[std::move(o.path)].path = true;
},
- }, ctx.raw());
+ }, ((NixStringContextElem &&) i).raw());
}
auto attrs = state.buildBindings(contextInfos.size());
@@ -129,7 +129,7 @@ static RegisterPrimOp primop_getContext("__getContext", 1, prim_getContext);
*/
static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- PathSet context;
+ NixStringContext context;
auto orig = state.forceString(*args[0], context, noPos, "while evaluating the first argument passed to builtins.appendContext");
state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.appendContext");
@@ -143,13 +143,16 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
.msg = hintfmt("context key '%s' is not a store path", name),
.errPos = state.positions[i.pos]
});
+ auto namePath = state.store->parseStorePath(name);
if (!settings.readOnlyMode)
- state.store->ensurePath(state.store->parseStorePath(name));
+ state.store->ensurePath(namePath);
state.forceAttrs(*i.value, i.pos, "while evaluating the value of a string context");
auto iter = i.value->attrs->find(sPath);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, iter->pos, "while evaluating the `path` attribute of a string context"))
- context.emplace(name);
+ context.emplace(NixStringContextElem::Opaque {
+ .path = namePath,
+ });
}
iter = i.value->attrs->find(sAllOutputs);
@@ -161,7 +164,9 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
.errPos = state.positions[i.pos]
});
}
- context.insert(concatStrings("=", name));
+ context.emplace(NixStringContextElem::DrvDeep {
+ .drvPath = namePath,
+ });
}
}
@@ -176,7 +181,10 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
}
for (auto elem : iter->value->listItems()) {
auto outputName = state.forceStringNoCtx(*elem, iter->pos, "while evaluating an output name within a string context");
- context.insert(concatStrings("!", outputName, "!", name));
+ context.emplace(NixStringContextElem::Built {
+ .drvPath = namePath,
+ .output = std::string { outputName },
+ });
}
}
}
diff --git a/src/libexpr/primops/fetchClosure.cc b/src/libexpr/primops/fetchClosure.cc
index 0dfa97fa3..4cf1f1e0b 100644
--- a/src/libexpr/primops/fetchClosure.cc
+++ b/src/libexpr/primops/fetchClosure.cc
@@ -18,7 +18,7 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg
const auto & attrName = state.symbols[attr.name];
if (attrName == "fromPath") {
- PathSet context;
+ NixStringContext context;
fromPath = state.coerceToStorePath(attr.pos, *attr.value, context,
"while evaluating the 'fromPath' attribute passed to builtins.fetchClosure");
}
@@ -27,7 +27,7 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg
state.forceValue(*attr.value, attr.pos);
toCA = true;
if (attr.value->type() != nString || attr.value->string.s != std::string("")) {
- PathSet context;
+ NixStringContext context;
toPath = state.coerceToStorePath(attr.pos, *attr.value, context,
"while evaluating the 'toPath' attribute passed to builtins.fetchClosure");
}
@@ -114,8 +114,7 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg
});
}
- auto toPathS = state.store->printStorePath(*toPath);
- v.mkString(toPathS, {toPathS});
+ state.mkStorePathString(*toPath, v);
}
static RegisterPrimOp primop_fetchClosure({
diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc
index c41bd60b6..2c0d98e74 100644
--- a/src/libexpr/primops/fetchMercurial.cc
+++ b/src/libexpr/primops/fetchMercurial.cc
@@ -13,7 +13,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
std::optional<Hash> rev;
std::optional<std::string> ref;
std::string_view name = "source";
- PathSet context;
+ NixStringContext context;
state.forceValue(*args[0], pos);
@@ -73,8 +73,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
auto [tree, input2] = input.fetch(state.store);
auto attrs2 = state.buildBindings(8);
- auto storePath = state.store->printStorePath(tree.storePath);
- attrs2.alloc(state.sOutPath).mkString(storePath, {storePath});
+ state.mkStorePathString(tree.storePath, attrs2.alloc(state.sOutPath));
if (input2.getRef())
attrs2.alloc("branch").mkString(*input2.getRef());
// Backward compatibility: set 'rev' to
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index 0d0e00fa5..cd7039025 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -24,9 +24,8 @@ void emitTreeAttrs(
auto attrs = state.buildBindings(8);
- auto storePath = state.store->printStorePath(tree.storePath);
- attrs.alloc(state.sOutPath).mkString(storePath, {storePath});
+ state.mkStorePathString(tree.storePath, attrs.alloc(state.sOutPath));
// FIXME: support arbitrary input attributes.
@@ -107,7 +106,7 @@ static void fetchTree(
const FetchTreeParams & params = FetchTreeParams{}
) {
fetchers::Input input;
- PathSet context;
+ NixStringContext context;
state.forceValue(*args[0], pos);
@@ -243,10 +242,15 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
// early exit if pinned and already in the store
if (expectedHash && expectedHash->type == htSHA256) {
- auto expectedPath =
- unpack
- ? state.store->makeFixedOutputPath(FileIngestionMethod::Recursive, *expectedHash, name, {})
- : state.store->makeFixedOutputPath(FileIngestionMethod::Flat, *expectedHash, name, {});
+ auto expectedPath = state.store->makeFixedOutputPath(
+ name,
+ FixedOutputInfo {
+ .hash = {
+ .method = unpack ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat,
+ .hash = *expectedHash,
+ },
+ .references = {}
+ });
if (state.store->isValidPath(expectedPath)) {
state.allowAndSetStorePathString(expectedPath, v);
diff --git a/src/libexpr/tests/json.cc b/src/libexpr/tests/json.cc
index 411bc0ac3..7586bdd9b 100644
--- a/src/libexpr/tests/json.cc
+++ b/src/libexpr/tests/json.cc
@@ -8,7 +8,7 @@ namespace nix {
protected:
std::string getJSONValue(Value& value) {
std::stringstream ss;
- PathSet ps;
+ NixStringContext ps;
printValueAsJSON(state, true, value, noPos, ss, ps);
return ss.str();
}
diff --git a/src/libexpr/tests/value/context.cc b/src/libexpr/tests/value/context.cc
index 083359b7a..27d6920b0 100644
--- a/src/libexpr/tests/value/context.cc
+++ b/src/libexpr/tests/value/context.cc
@@ -8,69 +8,62 @@
namespace nix {
-// Testing of trivial expressions
-struct NixStringContextElemTest : public LibExprTest {
- const Store & store() const {
- return *LibExprTest::store;
- }
-};
-
-TEST_F(NixStringContextElemTest, empty_invalid) {
+TEST(NixStringContextElemTest, empty_invalid) {
EXPECT_THROW(
- NixStringContextElem::parse(store(), ""),
+ NixStringContextElem::parse(""),
BadNixStringContextElem);
}
-TEST_F(NixStringContextElemTest, single_bang_invalid) {
+TEST(NixStringContextElemTest, single_bang_invalid) {
EXPECT_THROW(
- NixStringContextElem::parse(store(), "!"),
+ NixStringContextElem::parse("!"),
BadNixStringContextElem);
}
-TEST_F(NixStringContextElemTest, double_bang_invalid) {
+TEST(NixStringContextElemTest, double_bang_invalid) {
EXPECT_THROW(
- NixStringContextElem::parse(store(), "!!/"),
+ NixStringContextElem::parse("!!/"),
BadStorePath);
}
-TEST_F(NixStringContextElemTest, eq_slash_invalid) {
+TEST(NixStringContextElemTest, eq_slash_invalid) {
EXPECT_THROW(
- NixStringContextElem::parse(store(), "=/"),
+ NixStringContextElem::parse("=/"),
BadStorePath);
}
-TEST_F(NixStringContextElemTest, slash_invalid) {
+TEST(NixStringContextElemTest, slash_invalid) {
EXPECT_THROW(
- NixStringContextElem::parse(store(), "/"),
+ NixStringContextElem::parse("/"),
BadStorePath);
}
-TEST_F(NixStringContextElemTest, opaque) {
- std::string_view opaque = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x";
- auto elem = NixStringContextElem::parse(store(), opaque);
+TEST(NixStringContextElemTest, opaque) {
+ std::string_view opaque = "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x";
+ auto elem = NixStringContextElem::parse(opaque);
auto * p = std::get_if<NixStringContextElem::Opaque>(&elem);
ASSERT_TRUE(p);
- ASSERT_EQ(p->path, store().parseStorePath(opaque));
- ASSERT_EQ(elem.to_string(store()), opaque);
+ ASSERT_EQ(p->path, StorePath { opaque });
+ ASSERT_EQ(elem.to_string(), opaque);
}
-TEST_F(NixStringContextElemTest, drvDeep) {
- std::string_view drvDeep = "=/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv";
- auto elem = NixStringContextElem::parse(store(), drvDeep);
+TEST(NixStringContextElemTest, drvDeep) {
+ std::string_view drvDeep = "=g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv";
+ auto elem = NixStringContextElem::parse(drvDeep);
auto * p = std::get_if<NixStringContextElem::DrvDeep>(&elem);
ASSERT_TRUE(p);
- ASSERT_EQ(p->drvPath, store().parseStorePath(drvDeep.substr(1)));
- ASSERT_EQ(elem.to_string(store()), drvDeep);
+ ASSERT_EQ(p->drvPath, StorePath { drvDeep.substr(1) });
+ ASSERT_EQ(elem.to_string(), drvDeep);
}
-TEST_F(NixStringContextElemTest, built) {
- std::string_view built = "!foo!/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv";
- auto elem = NixStringContextElem::parse(store(), built);
+TEST(NixStringContextElemTest, built) {
+ std::string_view built = "!foo!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv";
+ auto elem = NixStringContextElem::parse(built);
auto * p = std::get_if<NixStringContextElem::Built>(&elem);
ASSERT_TRUE(p);
ASSERT_EQ(p->output, "foo");
- ASSERT_EQ(p->drvPath, store().parseStorePath(built.substr(5)));
- ASSERT_EQ(elem.to_string(store()), built);
+ ASSERT_EQ(p->drvPath, StorePath { built.substr(5) });
+ ASSERT_EQ(elem.to_string(), built);
}
}
@@ -116,12 +109,12 @@ Gen<NixStringContextElem> Arbitrary<NixStringContextElem>::arbitrary()
namespace nix {
-RC_GTEST_FIXTURE_PROP(
+RC_GTEST_PROP(
NixStringContextElemTest,
prop_round_rip,
(const NixStringContextElem & o))
{
- RC_ASSERT(o == NixStringContextElem::parse(store(), o.to_string(store())));
+ RC_ASSERT(o == NixStringContextElem::parse(o.to_string()));
}
}
diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc
index d40a77302..4996a5bde 100644
--- a/src/libexpr/value-to-json.cc
+++ b/src/libexpr/value-to-json.cc
@@ -11,7 +11,7 @@
namespace nix {
using json = nlohmann::json;
json printValueAsJSON(EvalState & state, bool strict,
- Value & v, const PosIdx pos, PathSet & context, bool copyToStore)
+ Value & v, const PosIdx pos, NixStringContext & context, bool copyToStore)
{
checkInterrupt();
@@ -95,13 +95,13 @@ json printValueAsJSON(EvalState & state, bool strict,
}
void printValueAsJSON(EvalState & state, bool strict,
- Value & v, const PosIdx pos, std::ostream & str, PathSet & context, bool copyToStore)
+ Value & v, const PosIdx pos, std::ostream & str, NixStringContext & context, bool copyToStore)
{
str << printValueAsJSON(state, strict, v, pos, context, copyToStore);
}
json ExternalValueBase::printValueAsJSON(EvalState & state, bool strict,
- PathSet & context, bool copyToStore) const
+ NixStringContext & context, bool copyToStore) const
{
state.debugThrowLastTrace(TypeError("cannot convert %1% to JSON", showType()));
}
diff --git a/src/libexpr/value-to-json.hh b/src/libexpr/value-to-json.hh
index 713356c7f..47ac90313 100644
--- a/src/libexpr/value-to-json.hh
+++ b/src/libexpr/value-to-json.hh
@@ -11,9 +11,9 @@
namespace nix {
nlohmann::json printValueAsJSON(EvalState & state, bool strict,
- Value & v, const PosIdx pos, PathSet & context, bool copyToStore = true);
+ Value & v, const PosIdx pos, NixStringContext & context, bool copyToStore = true);
void printValueAsJSON(EvalState & state, bool strict,
- Value & v, const PosIdx pos, std::ostream & str, PathSet & context, bool copyToStore = true);
+ Value & v, const PosIdx pos, std::ostream & str, NixStringContext & context, bool copyToStore = true);
}
diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc
index 4e87ac4b6..2539ad1c1 100644
--- a/src/libexpr/value-to-xml.cc
+++ b/src/libexpr/value-to-xml.cc
@@ -18,7 +18,7 @@ static XMLAttrs singletonAttrs(const std::string & name, const std::string & val
static void printValueAsXML(EvalState & state, bool strict, bool location,
- Value & v, XMLWriter & doc, PathSet & context, PathSet & drvsSeen,
+ Value & v, XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen,
const PosIdx pos);
@@ -32,7 +32,7 @@ static void posToXML(EvalState & state, XMLAttrs & xmlAttrs, const Pos & pos)
static void showAttrs(EvalState & state, bool strict, bool location,
- Bindings & attrs, XMLWriter & doc, PathSet & context, PathSet & drvsSeen)
+ Bindings & attrs, XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen)
{
StringSet names;
@@ -54,7 +54,7 @@ static void showAttrs(EvalState & state, bool strict, bool location,
static void printValueAsXML(EvalState & state, bool strict, bool location,
- Value & v, XMLWriter & doc, PathSet & context, PathSet & drvsSeen,
+ Value & v, XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen,
const PosIdx pos)
{
checkInterrupt();
@@ -166,7 +166,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
void ExternalValueBase::printValueAsXML(EvalState & state, bool strict,
- bool location, XMLWriter & doc, PathSet & context, PathSet & drvsSeen,
+ bool location, XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen,
const PosIdx pos) const
{
doc.writeEmptyElement("unevaluated");
@@ -174,7 +174,7 @@ void ExternalValueBase::printValueAsXML(EvalState & state, bool strict,
void printValueAsXML(EvalState & state, bool strict, bool location,
- Value & v, std::ostream & out, PathSet & context, const PosIdx pos)
+ Value & v, std::ostream & out, NixStringContext & context, const PosIdx pos)
{
XMLWriter doc(true, out);
XMLOpenElement root(doc, "expr");
diff --git a/src/libexpr/value-to-xml.hh b/src/libexpr/value-to-xml.hh
index ace7ead0f..6d702c0f2 100644
--- a/src/libexpr/value-to-xml.hh
+++ b/src/libexpr/value-to-xml.hh
@@ -10,6 +10,6 @@
namespace nix {
void printValueAsXML(EvalState & state, bool strict, bool location,
- Value & v, std::ostream & out, PathSet & context, const PosIdx pos);
+ Value & v, std::ostream & out, NixStringContext & context, const PosIdx pos);
}
diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh
index d524c4869..89c0c36fd 100644
--- a/src/libexpr/value.hh
+++ b/src/libexpr/value.hh
@@ -101,7 +101,7 @@ class ExternalValueBase
* Coerce the value to a string. Defaults to uncoercable, i.e. throws an
* error.
*/
- virtual std::string coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const;
+ virtual std::string coerceToString(const Pos & pos, NixStringContext & context, bool copyMore, bool copyToStore) const;
/**
* Compare to another value of the same type. Defaults to uncomparable,
@@ -113,13 +113,13 @@ class ExternalValueBase
* Print the value as JSON. Defaults to unconvertable, i.e. throws an error
*/
virtual nlohmann::json printValueAsJSON(EvalState & state, bool strict,
- PathSet & context, bool copyToStore = true) const;
+ NixStringContext & context, bool copyToStore = true) const;
/**
* Print the value as XML. Defaults to unevaluated
*/
virtual void printValueAsXML(EvalState & state, bool strict, bool location,
- XMLWriter & doc, PathSet & context, PathSet & drvsSeen,
+ XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen,
const PosIdx pos) const;
virtual ~ExternalValueBase()
@@ -269,9 +269,9 @@ public:
void mkString(std::string_view s);
- void mkString(std::string_view s, const PathSet & context);
+ void mkString(std::string_view s, const NixStringContext & context);
- void mkStringMove(const char * s, const PathSet & context);
+ void mkStringMove(const char * s, const NixStringContext & context);
inline void mkString(const Symbol & s)
{
@@ -400,8 +400,6 @@ public:
*/
bool isTrivial() const;
- NixStringContext getContext(const Store &);
-
auto listItems()
{
struct ListIterable
diff --git a/src/libexpr/value/context.cc b/src/libexpr/value/context.cc
index 61d9c53df..f76fc76e4 100644
--- a/src/libexpr/value/context.cc
+++ b/src/libexpr/value/context.cc
@@ -1,11 +1,10 @@
#include "value/context.hh"
-#include "store-api.hh"
#include <optional>
namespace nix {
-NixStringContextElem NixStringContextElem::parse(const Store & store, std::string_view s0)
+NixStringContextElem NixStringContextElem::parse(std::string_view s0)
{
std::string_view s = s0;
@@ -25,41 +24,41 @@ NixStringContextElem NixStringContextElem::parse(const Store & store, std::strin
"String content element beginning with '!' should have a second '!'");
}
return NixStringContextElem::Built {
- .drvPath = store.parseStorePath(s.substr(index + 1)),
+ .drvPath = StorePath { s.substr(index + 1) },
.output = std::string(s.substr(0, index)),
};
}
case '=': {
return NixStringContextElem::DrvDeep {
- .drvPath = store.parseStorePath(s.substr(1)),
+ .drvPath = StorePath { s.substr(1) },
};
}
default: {
return NixStringContextElem::Opaque {
- .path = store.parseStorePath(s),
+ .path = StorePath { s },
};
}
}
}
-std::string NixStringContextElem::to_string(const Store & store) const {
+std::string NixStringContextElem::to_string() const {
return std::visit(overloaded {
[&](const NixStringContextElem::Built & b) {
std::string res;
res += '!';
res += b.output;
res += '!';
- res += store.printStorePath(b.drvPath);
+ res += b.drvPath.to_string();
return res;
},
[&](const NixStringContextElem::DrvDeep & d) {
std::string res;
res += '=';
- res += store.printStorePath(d.drvPath);
+ res += d.drvPath.to_string();
return res;
},
[&](const NixStringContextElem::Opaque & o) {
- return store.printStorePath(o.path);
+ return std::string { o.path.to_string() };
},
}, raw());
}
diff --git a/src/libexpr/value/context.hh b/src/libexpr/value/context.hh
index 8719602d8..287ae08a9 100644
--- a/src/libexpr/value/context.hh
+++ b/src/libexpr/value/context.hh
@@ -26,8 +26,6 @@ public:
}
};
-class Store;
-
/**
* Plain opaque path to some store object.
*
@@ -80,12 +78,15 @@ struct NixStringContextElem : _NixStringContextElem_Raw {
using DrvDeep = NixStringContextElem_DrvDeep;
using Built = NixStringContextElem_Built;
- inline const Raw & raw() const {
+ inline const Raw & raw() const & {
return static_cast<const Raw &>(*this);
}
- inline Raw & raw() {
+ inline Raw & raw() & {
return static_cast<Raw &>(*this);
}
+ inline Raw && raw() && {
+ return static_cast<Raw &&>(*this);
+ }
/**
* Decode a context string, one of:
@@ -93,10 +94,10 @@ struct NixStringContextElem : _NixStringContextElem_Raw {
* - ‘=<path>’
* - ‘!<name>!<path>’
*/
- static NixStringContextElem parse(const Store & store, std::string_view s);
- std::string to_string(const Store & store) const;
+ static NixStringContextElem parse(std::string_view s);
+ std::string to_string() const;
};
-typedef std::vector<NixStringContextElem> NixStringContext;
+typedef std::set<NixStringContextElem> NixStringContext;
}