libexpr: stop lying about DrvInfo's constness

DrvInfo's query methods all use mutable fields to cache, but like.
that's basically the entire interface for DrvInfo. Not only that, but
these formerly-const-marked functions can even throw due to eval errors!
Changing this only required removing some `const` markers in nix-env,
and changing a single inline `queryInstalled()` call to be an lvalue
instead.

Change-Id: I796807118f3b35b0e93668b5e28210d9e521b2ae
This commit is contained in:
Qyriad 2024-07-07 05:47:41 -06:00
parent d461cc1d7b
commit accfd8aa9d
3 changed files with 29 additions and 26 deletions

View file

@ -45,7 +45,7 @@ DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPat
} }
std::string DrvInfo::queryName() const std::string DrvInfo::queryName()
{ {
if (name == "" && attrs) { if (name == "" && attrs) {
auto i = attrs->find(state->sName); auto i = attrs->find(state->sName);
@ -56,7 +56,7 @@ std::string DrvInfo::queryName() const
} }
std::string DrvInfo::querySystem() const std::string DrvInfo::querySystem()
{ {
if (system == "" && attrs) { if (system == "" && attrs) {
auto i = attrs->find(state->sSystem); auto i = attrs->find(state->sSystem);
@ -66,7 +66,7 @@ std::string DrvInfo::querySystem() const
} }
std::optional<StorePath> DrvInfo::queryDrvPath() const std::optional<StorePath> DrvInfo::queryDrvPath()
{ {
if (!drvPath && attrs) { if (!drvPath && attrs) {
Bindings::iterator i = attrs->find(state->sDrvPath); Bindings::iterator i = attrs->find(state->sDrvPath);
@ -80,7 +80,7 @@ std::optional<StorePath> DrvInfo::queryDrvPath() const
} }
StorePath DrvInfo::requireDrvPath() const StorePath DrvInfo::requireDrvPath()
{ {
if (auto drvPath = queryDrvPath()) if (auto drvPath = queryDrvPath())
return *drvPath; return *drvPath;
@ -88,7 +88,7 @@ StorePath DrvInfo::requireDrvPath() const
} }
StorePath DrvInfo::queryOutPath() const StorePath DrvInfo::queryOutPath()
{ {
if (!outPath && attrs) { if (!outPath && attrs) {
Bindings::iterator i = attrs->find(state->sOutPath); Bindings::iterator i = attrs->find(state->sOutPath);
@ -164,7 +164,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool withPaths, bool onlyOutputsToInstall
} }
std::string DrvInfo::queryOutputName() const std::string DrvInfo::queryOutputName()
{ {
if (outputName == "" && attrs) { if (outputName == "" && attrs) {
Bindings::iterator i = attrs->find(state->sOutputName); Bindings::iterator i = attrs->find(state->sOutputName);

View file

@ -19,11 +19,11 @@ public:
private: private:
EvalState * state; EvalState * state;
mutable std::string name; std::string name;
mutable std::string system; std::string system;
mutable std::optional<std::optional<StorePath>> drvPath; std::optional<std::optional<StorePath>> drvPath;
mutable std::optional<StorePath> outPath; std::optional<StorePath> outPath;
mutable std::string outputName; std::string outputName;
Outputs outputs; Outputs outputs;
/** /**
@ -47,12 +47,12 @@ public:
DrvInfo(EvalState & state, std::string attrPath, Bindings * attrs); DrvInfo(EvalState & state, std::string attrPath, Bindings * attrs);
DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs); DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs);
std::string queryName() const; std::string queryName();
std::string querySystem() const; std::string querySystem();
std::optional<StorePath> queryDrvPath() const; std::optional<StorePath> queryDrvPath();
StorePath requireDrvPath() const; StorePath requireDrvPath();
StorePath queryOutPath() const; StorePath queryOutPath();
std::string queryOutputName() const; std::string queryOutputName();
/** /**
* Return the unordered map of output names to (optional) output paths. * Return the unordered map of output names to (optional) output paths.
* The "outputs to install" are determined by `meta.outputsToInstall`. * The "outputs to install" are determined by `meta.outputsToInstall`.

View file

@ -236,10 +236,10 @@ static void checkSelectorUse(DrvNames & selectors)
namespace { namespace {
std::set<std::string> searchByPrefix(const DrvInfos & allElems, std::string_view prefix) { std::set<std::string> searchByPrefix(DrvInfos & allElems, std::string_view prefix) {
constexpr std::size_t maxResults = 3; constexpr std::size_t maxResults = 3;
std::set<std::string> result; std::set<std::string> result;
for (const auto & drvInfo : allElems) { for (auto & drvInfo : allElems) {
const auto drvName = DrvName { drvInfo.queryName() }; const auto drvName = DrvName { drvInfo.queryName() };
if (drvName.name.starts_with(prefix)) { if (drvName.name.starts_with(prefix)) {
result.emplace(drvName.name); result.emplace(drvName.name);
@ -319,7 +319,7 @@ std::vector<Match> pickNewestOnly(EvalState & state, std::vector<Match> matches)
} // end namespace } // end namespace
static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, static DrvInfos filterBySelector(EvalState & state, DrvInfos & allElems,
const Strings & args, bool newestOnly) const Strings & args, bool newestOnly)
{ {
DrvNames selectors = drvNamesFromArgs(args); DrvNames selectors = drvNamesFromArgs(args);
@ -331,7 +331,7 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
for (auto & selector : selectors) { for (auto & selector : selectors) {
std::vector<Match> matches; std::vector<Match> matches;
for (const auto & [index, drvInfo] : enumerate(allElems)) { for (auto && [index, drvInfo] : enumerate(allElems)) {
const auto drvName = DrvName { drvInfo.queryName() }; const auto drvName = DrvName { drvInfo.queryName() };
if (selector.matches(drvName)) { if (selector.matches(drvName)) {
++selector.hits; ++selector.hits;
@ -457,9 +457,12 @@ static void queryInstSources(EvalState & state,
user environment. These are then filtered as in the user environment. These are then filtered as in the
`srcNixExprDrvs' case. */ `srcNixExprDrvs' case. */
case srcProfile: { case srcProfile: {
elems = filterBySelector(state, auto installed = queryInstalled(state, instSource.profile);
queryInstalled(state, instSource.profile), elems = filterBySelector(
args, newestOnly); state,
installed,
args, newestOnly
);
break; break;
} }
@ -838,7 +841,7 @@ static bool cmpChars(char a, char b)
} }
static bool cmpElemByName(const DrvInfo & a, const DrvInfo & b) static bool cmpElemByName(DrvInfo & a, DrvInfo & b)
{ {
auto a_name = a.queryName(); auto a_name = a.queryName();
auto b_name = b.queryName(); auto b_name = b.queryName();
@ -891,7 +894,7 @@ void printTable(Table & table)
typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff; typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff;
static VersionDiff compareVersionAgainstSet( static VersionDiff compareVersionAgainstSet(
const DrvInfo & elem, const DrvInfos & elems, std::string & version) DrvInfo & elem, DrvInfos & elems, std::string & version)
{ {
DrvName name(elem.queryName()); DrvName name(elem.queryName());