Merge pull request #6237 from obsidiansystems/store-path-string-context
Decode string context straight to using StorePaths
This commit is contained in:
commit
e4ff430866
8 changed files with 42 additions and 26 deletions
|
@ -21,6 +21,8 @@ struct AttrDb
|
||||||
{
|
{
|
||||||
std::atomic_bool failed{false};
|
std::atomic_bool failed{false};
|
||||||
|
|
||||||
|
const Store & cfg;
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
SQLite db;
|
SQLite db;
|
||||||
|
@ -33,8 +35,9 @@ struct AttrDb
|
||||||
|
|
||||||
std::unique_ptr<Sync<State>> _state;
|
std::unique_ptr<Sync<State>> _state;
|
||||||
|
|
||||||
AttrDb(const Hash & fingerprint)
|
AttrDb(const Store & cfg, const Hash & fingerprint)
|
||||||
: _state(std::make_unique<Sync<State>>())
|
: cfg(cfg)
|
||||||
|
, _state(std::make_unique<Sync<State>>())
|
||||||
{
|
{
|
||||||
auto state(_state->lock());
|
auto state(_state->lock());
|
||||||
|
|
||||||
|
@ -254,10 +257,10 @@ struct AttrDb
|
||||||
return {{rowId, attrs}};
|
return {{rowId, attrs}};
|
||||||
}
|
}
|
||||||
case AttrType::String: {
|
case AttrType::String: {
|
||||||
std::vector<std::pair<Path, std::string>> context;
|
NixStringContext context;
|
||||||
if (!queryAttribute.isNull(3))
|
if (!queryAttribute.isNull(3))
|
||||||
for (auto & s : tokenizeString<std::vector<std::string>>(queryAttribute.getStr(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}}};
|
return {{rowId, string_t{queryAttribute.getStr(2), context}}};
|
||||||
}
|
}
|
||||||
case AttrType::Bool:
|
case AttrType::Bool:
|
||||||
|
@ -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 {
|
try {
|
||||||
return std::make_shared<AttrDb>(fingerprint);
|
return std::make_shared<AttrDb>(cfg, fingerprint);
|
||||||
} catch (SQLiteError &) {
|
} catch (SQLiteError &) {
|
||||||
ignoreException();
|
ignoreException();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -288,7 +291,7 @@ EvalCache::EvalCache(
|
||||||
std::optional<std::reference_wrapper<const Hash>> useCache,
|
std::optional<std::reference_wrapper<const Hash>> useCache,
|
||||||
EvalState & state,
|
EvalState & state,
|
||||||
RootLoader rootLoader)
|
RootLoader rootLoader)
|
||||||
: db(useCache ? makeAttrDb(*useCache) : nullptr)
|
: db(useCache ? makeAttrDb(*state.store, *useCache) : nullptr)
|
||||||
, state(state)
|
, state(state)
|
||||||
, rootLoader(rootLoader)
|
, rootLoader(rootLoader)
|
||||||
{
|
{
|
||||||
|
@ -546,7 +549,7 @@ string_t AttrCursor::getStringWithContext()
|
||||||
if (auto s = std::get_if<string_t>(&cachedValue->second)) {
|
if (auto s = std::get_if<string_t>(&cachedValue->second)) {
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
for (auto & c : s->second) {
|
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;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -563,7 +566,7 @@ string_t AttrCursor::getStringWithContext()
|
||||||
auto & v = forceValue();
|
auto & v = forceValue();
|
||||||
|
|
||||||
if (v.type() == nString)
|
if (v.type() == nString)
|
||||||
return {v.string.s, v.getContext()};
|
return {v.string.s, v.getContext(*root->state.store)};
|
||||||
else if (v.type() == nPath)
|
else if (v.type() == nPath)
|
||||||
return {v.path, {}};
|
return {v.path, {}};
|
||||||
else
|
else
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct misc_t {};
|
||||||
struct failed_t {};
|
struct failed_t {};
|
||||||
typedef uint64_t AttrId;
|
typedef uint64_t AttrId;
|
||||||
typedef std::pair<AttrId, Symbol> AttrKey;
|
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<
|
typedef std::variant<
|
||||||
std::vector<Symbol>,
|
std::vector<Symbol>,
|
||||||
|
|
|
@ -1903,13 +1903,22 @@ std::string_view EvalState::forceString(Value & v, const Pos & pos)
|
||||||
|
|
||||||
/* Decode a context string ‘!<name>!<path>’ into a pair <path,
|
/* Decode a context string ‘!<name>!<path>’ into a pair <path,
|
||||||
name>. */
|
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) == '!') {
|
if (s.at(0) == '!') {
|
||||||
size_t index = s.find("!", 1);
|
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
|
} else
|
||||||
return {s.at(0) == '/' ? std::string(s) : std::string(s.substr(1)), ""};
|
return {
|
||||||
|
store.parseStorePath(
|
||||||
|
s.at(0) == '/'
|
||||||
|
? s
|
||||||
|
: s.substr(1)),
|
||||||
|
"",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
assert(internalType == tString);
|
||||||
if (string.context)
|
if (string.context)
|
||||||
for (const char * * p = string.context; *p; ++p)
|
for (const char * * p = string.context; *p; ++p)
|
||||||
res.push_back(decodeContext(*p));
|
res.push_back(decodeContext(store, *p));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
class Store;
|
struct Store;
|
||||||
class EvalState;
|
class EvalState;
|
||||||
class StorePath;
|
class StorePath;
|
||||||
enum RepairFlag : bool;
|
enum RepairFlag : bool;
|
||||||
|
@ -430,7 +430,7 @@ std::string showType(const Value & v);
|
||||||
|
|
||||||
/* Decode a context string ‘!<name>!<path>’ into a pair <path,
|
/* Decode a context string ‘!<name>!<path>’ into a pair <path,
|
||||||
name>. */
|
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". */
|
/* If `path' refers to a directory, then append "/default.nix". */
|
||||||
Path resolveExprPath(Path path);
|
Path resolveExprPath(Path path);
|
||||||
|
|
|
@ -43,8 +43,8 @@ StringMap EvalState::realiseContext(const PathSet & context)
|
||||||
StringMap res;
|
StringMap res;
|
||||||
|
|
||||||
for (auto & i : context) {
|
for (auto & i : context) {
|
||||||
auto [ctxS, outputName] = decodeContext(i);
|
auto [ctx, outputName] = decodeContext(*store, i);
|
||||||
auto ctx = store->parseStorePath(ctxS);
|
auto ctxS = store->printStorePath(ctx);
|
||||||
if (!store->isValidPath(ctx))
|
if (!store->isValidPath(ctx))
|
||||||
throw InvalidPathError(store->printStorePath(ctx));
|
throw InvalidPathError(store->printStorePath(ctx));
|
||||||
if (!outputName.empty() && ctx.isDerivation()) {
|
if (!outputName.empty() && ctx.isDerivation()) {
|
||||||
|
@ -1118,8 +1118,8 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
|
|
||||||
/* Handle derivation outputs of the form ‘!<name>!<path>’. */
|
/* Handle derivation outputs of the form ‘!<name>!<path>’. */
|
||||||
else if (path.at(0) == '!') {
|
else if (path.at(0) == '!') {
|
||||||
auto ctx = decodeContext(path);
|
auto ctx = decodeContext(*state.store, path);
|
||||||
drv.inputDrvs[state.store->parseStorePath(ctx.first)].insert(ctx.second);
|
drv.inputDrvs[ctx.first].insert(ctx.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise it's a source file. */
|
/* Otherwise it's a source file. */
|
||||||
|
|
|
@ -83,8 +83,8 @@ static void prim_getContext(EvalState & state, const Pos & pos, Value * * args,
|
||||||
drv = std::string(p, 1);
|
drv = std::string(p, 1);
|
||||||
path = &drv;
|
path = &drv;
|
||||||
} else if (p.at(0) == '!') {
|
} else if (p.at(0) == '!') {
|
||||||
std::pair<std::string, std::string> ctx = decodeContext(p);
|
NixStringContextElem ctx = decodeContext(*state.store, p);
|
||||||
drv = ctx.first;
|
drv = state.store->printStorePath(ctx.first);
|
||||||
output = ctx.second;
|
output = ctx.second;
|
||||||
path = &drv;
|
path = &drv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,8 @@ struct ExprLambda;
|
||||||
struct PrimOp;
|
struct PrimOp;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
struct Pos;
|
struct Pos;
|
||||||
|
class StorePath;
|
||||||
|
class Store;
|
||||||
class EvalState;
|
class EvalState;
|
||||||
class XMLWriter;
|
class XMLWriter;
|
||||||
class JSONPlaceholder;
|
class JSONPlaceholder;
|
||||||
|
@ -64,6 +66,8 @@ class JSONPlaceholder;
|
||||||
|
|
||||||
typedef int64_t NixInt;
|
typedef int64_t NixInt;
|
||||||
typedef double NixFloat;
|
typedef double NixFloat;
|
||||||
|
typedef std::pair<StorePath, std::string> NixStringContextElem;
|
||||||
|
typedef std::vector<NixStringContextElem> NixStringContext;
|
||||||
|
|
||||||
/* External values must descend from ExternalValueBase, so that
|
/* External values must descend from ExternalValueBase, so that
|
||||||
* type-agnostic nix functions (e.g. showType) can be implemented
|
* type-agnostic nix functions (e.g. showType) can be implemented
|
||||||
|
@ -368,7 +372,7 @@ public:
|
||||||
non-trivial. */
|
non-trivial. */
|
||||||
bool isTrivial() const;
|
bool isTrivial() const;
|
||||||
|
|
||||||
std::vector<std::pair<Path, std::string>> getContext();
|
NixStringContext getContext(const Store &);
|
||||||
|
|
||||||
auto listItems()
|
auto listItems()
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,7 +71,7 @@ UnresolvedApp Installable::toApp(EvalState & state)
|
||||||
|
|
||||||
std::vector<StorePathWithOutputs> context2;
|
std::vector<StorePathWithOutputs> context2;
|
||||||
for (auto & [path, name] : context)
|
for (auto & [path, name] : context)
|
||||||
context2.push_back({state.store->parseStorePath(path), {name}});
|
context2.push_back({path, {name}});
|
||||||
|
|
||||||
return UnresolvedApp{App {
|
return UnresolvedApp{App {
|
||||||
.context = std::move(context2),
|
.context = std::move(context2),
|
||||||
|
|
Loading…
Reference in a new issue