Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions src/libexpr/eval-cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ struct AttrDb
{
std::atomic_bool failed{false};

const Store & cfg;

struct State
{
SQLite db;
Expand All @@ -33,8 +35,9 @@ struct AttrDb

std::unique_ptr<Sync<State>> _state;

AttrDb(const Hash & fingerprint)
: _state(std::make_unique<Sync<State>>())
AttrDb(const Store & cfg, const Hash & fingerprint)
: cfg(cfg)
, _state(std::make_unique<Sync<State>>())
{
auto state(_state->lock());

Expand Down Expand Up @@ -254,10 +257,10 @@ struct AttrDb
return {{rowId, attrs}};
}
case AttrType::String: {
std::vector<std::pair<Path, std::string>> context;
NixStringContext context;
if (!queryAttribute.isNull(3))
for (auto & s : tokenizeString<std::vector<std::string>>(queryAttribute.getStr(3), ";"))
context.push_back(decodeContext(s));
context.push_back(decodeContext(cfg, s));
return {{rowId, string_t{queryAttribute.getStr(2), context}}};
}
case AttrType::Bool:
Expand All @@ -274,10 +277,10 @@ struct AttrDb
}
};

static std::shared_ptr<AttrDb> makeAttrDb(const Hash & fingerprint)
static std::shared_ptr<AttrDb> makeAttrDb(const Store & cfg, const Hash & fingerprint)
{
try {
return std::make_shared<AttrDb>(fingerprint);
return std::make_shared<AttrDb>(cfg, fingerprint);
} catch (SQLiteError &) {
ignoreException();
return nullptr;
Expand All @@ -288,7 +291,7 @@ EvalCache::EvalCache(
std::optional<std::reference_wrapper<const Hash>> useCache,
EvalState & state,
RootLoader rootLoader)
: db(useCache ? makeAttrDb(*useCache) : nullptr)
: db(useCache ? makeAttrDb(*state.store, *useCache) : nullptr)
, state(state)
, rootLoader(rootLoader)
{
Expand Down Expand Up @@ -546,7 +549,7 @@ string_t AttrCursor::getStringWithContext()
if (auto s = std::get_if<string_t>(&cachedValue->second)) {
bool valid = true;
for (auto & c : s->second) {
if (!root->state.store->isValidPath(root->state.store->parseStorePath(c.first))) {
if (!root->state.store->isValidPath(c.first)) {
valid = false;
break;
}
Expand All @@ -563,7 +566,7 @@ string_t AttrCursor::getStringWithContext()
auto & v = forceValue();

if (v.type() == nString)
return {v.string.s, v.getContext()};
return {v.string.s, v.getContext(*root->state.store)};
else if (v.type() == nPath)
return {v.path, {}};
else
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/eval-cache.hh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct misc_t {};
struct failed_t {};
typedef uint64_t AttrId;
typedef std::pair<AttrId, Symbol> AttrKey;
typedef std::pair<std::string, std::vector<std::pair<Path, std::string>>> string_t;
typedef std::pair<std::string, NixStringContext> string_t;

typedef std::variant<
std::vector<Symbol>,
Expand Down
21 changes: 15 additions & 6 deletions src/libexpr/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1903,13 +1903,22 @@ std::string_view EvalState::forceString(Value & v, const Pos & pos)

/* Decode a context string ‘!<name>!<path>’ into a pair <path,
name>. */
std::pair<std::string, std::string> decodeContext(std::string_view s)
NixStringContextElem decodeContext(const Store & store, std::string_view s)
{
if (s.at(0) == '!') {
size_t index = s.find("!", 1);
return {std::string(s.substr(index + 1)), std::string(s.substr(1, index - 1))};
return {
store.parseStorePath(s.substr(index + 1)),
std::string(s.substr(1, index - 1)),
};
} else
return {s.at(0) == '/' ? std::string(s) : std::string(s.substr(1)), ""};
return {
store.parseStorePath(
s.at(0) == '/'
? s
: s.substr(1)),
"",
};
}


Expand All @@ -1921,13 +1930,13 @@ void copyContext(const Value & v, PathSet & context)
}


std::vector<std::pair<Path, std::string>> Value::getContext()
NixStringContext Value::getContext(const Store & store)
{
std::vector<std::pair<Path, std::string>> res;
NixStringContext res;
assert(internalType == tString);
if (string.context)
for (const char * * p = string.context; *p; ++p)
res.push_back(decodeContext(*p));
res.push_back(decodeContext(store, *p));
return res;
}

Expand Down
4 changes: 2 additions & 2 deletions src/libexpr/eval.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace nix {


class Store;
struct Store;
class EvalState;
class StorePath;
enum RepairFlag : bool;
Expand Down Expand Up @@ -430,7 +430,7 @@ std::string showType(const Value & v);

/* Decode a context string ‘!<name>!<path>’ into a pair <path,
name>. */
std::pair<std::string, std::string> decodeContext(std::string_view s);
NixStringContextElem decodeContext(const Store & store, std::string_view s);

/* If `path' refers to a directory, then append "/default.nix". */
Path resolveExprPath(Path path);
Expand Down
8 changes: 4 additions & 4 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ StringMap EvalState::realiseContext(const PathSet & context)
StringMap res;

for (auto & i : context) {
auto [ctxS, outputName] = decodeContext(i);
auto ctx = store->parseStorePath(ctxS);
auto [ctx, outputName] = decodeContext(*store, i);
auto ctxS = store->printStorePath(ctx);
if (!store->isValidPath(ctx))
throw InvalidPathError(store->printStorePath(ctx));
if (!outputName.empty() && ctx.isDerivation()) {
Expand Down Expand Up @@ -1118,8 +1118,8 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *

/* Handle derivation outputs of the form ‘!<name>!<path>’. */
else if (path.at(0) == '!') {
auto ctx = decodeContext(path);
drv.inputDrvs[state.store->parseStorePath(ctx.first)].insert(ctx.second);
auto ctx = decodeContext(*state.store, path);
drv.inputDrvs[ctx.first].insert(ctx.second);
}

/* Otherwise it's a source file. */
Expand Down
4 changes: 2 additions & 2 deletions src/libexpr/primops/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ static void prim_getContext(EvalState & state, const Pos & pos, Value * * args,
drv = std::string(p, 1);
path = &drv;
} else if (p.at(0) == '!') {
std::pair<std::string, std::string> ctx = decodeContext(p);
drv = ctx.first;
NixStringContextElem ctx = decodeContext(*state.store, p);
drv = state.store->printStorePath(ctx.first);
output = ctx.second;
path = &drv;
}
Expand Down
6 changes: 5 additions & 1 deletion src/libexpr/value.hh
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,17 @@ struct ExprLambda;
struct PrimOp;
class Symbol;
struct Pos;
class StorePath;
class Store;
class EvalState;
class XMLWriter;
class JSONPlaceholder;


typedef int64_t NixInt;
typedef double NixFloat;
typedef std::pair<StorePath, std::string> NixStringContextElem;
typedef std::vector<NixStringContextElem> NixStringContext;

/* External values must descend from ExternalValueBase, so that
* type-agnostic nix functions (e.g. showType) can be implemented
Expand Down Expand Up @@ -368,7 +372,7 @@ public:
non-trivial. */
bool isTrivial() const;

std::vector<std::pair<Path, std::string>> getContext();
NixStringContext getContext(const Store &);

auto listItems()
{
Expand Down
2 changes: 1 addition & 1 deletion src/nix/app.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ UnresolvedApp Installable::toApp(EvalState & state)

std::vector<StorePathWithOutputs> context2;
for (auto & [path, name] : context)
context2.push_back({state.store->parseStorePath(path), {name}});
context2.push_back({path, {name}});

return UnresolvedApp{App {
.context = std::move(context2),
Expand Down