Add "nix search" command
This commit is contained in:
parent
3162ad5ff4
commit
90825dea51
9 changed files with 263 additions and 102 deletions
|
@ -9,7 +9,34 @@
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
string DrvInfo::queryDrvPath()
|
DrvInfo::DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs)
|
||||||
|
: state(&state), attrs(attrs), attrPath(attrPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string DrvInfo::queryName() const
|
||||||
|
{
|
||||||
|
if (name == "" && attrs) {
|
||||||
|
auto i = attrs->find(state->sName);
|
||||||
|
if (i == attrs->end()) throw TypeError("derivation name missing");
|
||||||
|
name = state->forceStringNoCtx(*i->value);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string DrvInfo::querySystem() const
|
||||||
|
{
|
||||||
|
if (system == "" && attrs) {
|
||||||
|
auto i = attrs->find(state->sSystem);
|
||||||
|
system = i == attrs->end() ? "unknown" : state->forceStringNoCtx(*i->value, *i->pos);
|
||||||
|
}
|
||||||
|
return system;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string DrvInfo::queryDrvPath() const
|
||||||
{
|
{
|
||||||
if (drvPath == "" && attrs) {
|
if (drvPath == "" && attrs) {
|
||||||
Bindings::iterator i = attrs->find(state->sDrvPath);
|
Bindings::iterator i = attrs->find(state->sDrvPath);
|
||||||
|
@ -20,7 +47,7 @@ string DrvInfo::queryDrvPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string DrvInfo::queryOutPath()
|
string DrvInfo::queryOutPath() const
|
||||||
{
|
{
|
||||||
if (outPath == "" && attrs) {
|
if (outPath == "" && attrs) {
|
||||||
Bindings::iterator i = attrs->find(state->sOutPath);
|
Bindings::iterator i = attrs->find(state->sOutPath);
|
||||||
|
@ -76,7 +103,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string DrvInfo::queryOutputName()
|
string DrvInfo::queryOutputName() const
|
||||||
{
|
{
|
||||||
if (outputName == "" && attrs) {
|
if (outputName == "" && attrs) {
|
||||||
Bindings::iterator i = attrs->find(state->sOutputName);
|
Bindings::iterator i = attrs->find(state->sOutputName);
|
||||||
|
@ -225,17 +252,12 @@ static bool getDerivation(EvalState & state, Value & v,
|
||||||
if (done.find(v.attrs) != done.end()) return false;
|
if (done.find(v.attrs) != done.end()) return false;
|
||||||
done.insert(v.attrs);
|
done.insert(v.attrs);
|
||||||
|
|
||||||
Bindings::iterator i = v.attrs->find(state.sName);
|
DrvInfo drv(state, attrPath, v.attrs);
|
||||||
/* !!! We really would like to have a decent back trace here. */
|
|
||||||
if (i == v.attrs->end()) throw TypeError("derivation name missing");
|
|
||||||
|
|
||||||
Bindings::iterator i2 = v.attrs->find(state.sSystem);
|
drv.queryName();
|
||||||
|
|
||||||
DrvInfo drv(state, state.forceStringNoCtx(*i->value), attrPath,
|
|
||||||
i2 == v.attrs->end() ? "unknown" : state.forceStringNoCtx(*i2->value, *i2->pos),
|
|
||||||
v.attrs);
|
|
||||||
|
|
||||||
drvs.push_back(drv);
|
drvs.push_back(drv);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
} catch (AssertionError & e) {
|
} catch (AssertionError & e) {
|
||||||
|
|
|
@ -17,31 +17,32 @@ public:
|
||||||
private:
|
private:
|
||||||
EvalState * state;
|
EvalState * state;
|
||||||
|
|
||||||
string drvPath;
|
mutable string name;
|
||||||
string outPath;
|
mutable string system;
|
||||||
string outputName;
|
mutable string drvPath;
|
||||||
|
mutable string outPath;
|
||||||
|
mutable string outputName;
|
||||||
Outputs outputs;
|
Outputs outputs;
|
||||||
|
|
||||||
bool failed; // set if we get an AssertionError
|
bool failed = false; // set if we get an AssertionError
|
||||||
|
|
||||||
Bindings * attrs, * meta;
|
Bindings * attrs = nullptr, * meta = nullptr;
|
||||||
|
|
||||||
Bindings * getMeta();
|
Bindings * getMeta();
|
||||||
|
|
||||||
bool checkMeta(Value & v);
|
bool checkMeta(Value & v);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
string name;
|
|
||||||
string attrPath; /* path towards the derivation */
|
string attrPath; /* path towards the derivation */
|
||||||
string system;
|
|
||||||
|
|
||||||
DrvInfo(EvalState & state) : state(&state), failed(false), attrs(0), meta(0) { };
|
DrvInfo(EvalState & state) : state(&state) { };
|
||||||
DrvInfo(EvalState & state, const string & name, const string & attrPath, const string & system, Bindings * attrs)
|
DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs);
|
||||||
: state(&state), failed(false), attrs(attrs), meta(0), name(name), attrPath(attrPath), system(system) { };
|
|
||||||
|
|
||||||
string queryDrvPath();
|
string queryName() const;
|
||||||
string queryOutPath();
|
string querySystem() const;
|
||||||
string queryOutputName();
|
string queryDrvPath() const;
|
||||||
|
string queryOutPath() const;
|
||||||
|
string queryOutputName() const;
|
||||||
/** Return the list of outputs. The "outputs to install" are determined by `mesa.outputsToInstall`. */
|
/** Return the list of outputs. The "outputs to install" are determined by `mesa.outputsToInstall`. */
|
||||||
Outputs queryOutputs(bool onlyOutputsToInstall = false);
|
Outputs queryOutputs(bool onlyOutputsToInstall = false);
|
||||||
|
|
||||||
|
@ -58,15 +59,9 @@ public:
|
||||||
MetaValue queryMetaInfo(EvalState & state, const string & name) const;
|
MetaValue queryMetaInfo(EvalState & state, const string & name) const;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void setDrvPath(const string & s)
|
void setName(const string & s) { name = s; }
|
||||||
{
|
void setDrvPath(const string & s) { drvPath = s; }
|
||||||
drvPath = s;
|
void setOutPath(const string & s) { outPath = s; }
|
||||||
}
|
|
||||||
|
|
||||||
void setOutPath(const string & s)
|
|
||||||
{
|
|
||||||
outPath = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFailed() { failed = true; };
|
void setFailed() { failed = true; };
|
||||||
bool hasFailed() { return failed; };
|
bool hasFailed() { return failed; };
|
||||||
|
|
|
@ -66,6 +66,7 @@ void Args::printHelp(const string & programName, std::ostream & out)
|
||||||
std::cout << renderLabels({exp.label});
|
std::cout << renderLabels({exp.label});
|
||||||
// FIXME: handle arity > 1
|
// FIXME: handle arity > 1
|
||||||
if (exp.arity == 0) std::cout << "...";
|
if (exp.arity == 0) std::cout << "...";
|
||||||
|
if (exp.optional) std::cout << "?";
|
||||||
}
|
}
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
|
|
||||||
|
|
|
@ -164,9 +164,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expect a string argument. */
|
/* Expect a string argument. */
|
||||||
void expectArg(const std::string & label, string * dest)
|
void expectArg(const std::string & label, string * dest, bool optional = false)
|
||||||
{
|
{
|
||||||
expectedArgs.push_back(ExpectedArg{label, 1, false, [=](Strings ss) {
|
expectedArgs.push_back(ExpectedArg{label, 1, optional, [=](Strings ss) {
|
||||||
*dest = ss.front();
|
*dest = ss.front();
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ static void loadDerivations(EvalState & state, Path nixExprPath,
|
||||||
system. */
|
system. */
|
||||||
for (DrvInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) {
|
for (DrvInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) {
|
||||||
j = i; j++;
|
j = i; j++;
|
||||||
if (systemFilter != "*" && i->system != systemFilter)
|
if (systemFilter != "*" && i->querySystem() != systemFilter)
|
||||||
elems.erase(i);
|
elems.erase(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
|
||||||
for (DrvInfos::const_iterator j = allElems.begin();
|
for (DrvInfos::const_iterator j = allElems.begin();
|
||||||
j != allElems.end(); ++j, ++n)
|
j != allElems.end(); ++j, ++n)
|
||||||
{
|
{
|
||||||
DrvName drvName(j->name);
|
DrvName drvName(j->queryName());
|
||||||
if (i.matches(drvName)) {
|
if (i.matches(drvName)) {
|
||||||
i.hits++;
|
i.hits++;
|
||||||
matches.push_back(std::pair<DrvInfo, unsigned int>(*j, n));
|
matches.push_back(std::pair<DrvInfo, unsigned int>(*j, n));
|
||||||
|
@ -269,36 +269,36 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
|
||||||
StringSet multiple;
|
StringSet multiple;
|
||||||
|
|
||||||
for (auto & j : matches) {
|
for (auto & j : matches) {
|
||||||
DrvName drvName(j.first.name);
|
DrvName drvName(j.first.queryName());
|
||||||
int d = 1;
|
int d = 1;
|
||||||
|
|
||||||
Newest::iterator k = newest.find(drvName.name);
|
Newest::iterator k = newest.find(drvName.name);
|
||||||
|
|
||||||
if (k != newest.end()) {
|
if (k != newest.end()) {
|
||||||
d = j.first.system == k->second.first.system ? 0 :
|
d = j.first.querySystem() == k->second.first.querySystem() ? 0 :
|
||||||
j.first.system == settings.thisSystem ? 1 :
|
j.first.querySystem() == settings.thisSystem ? 1 :
|
||||||
k->second.first.system == settings.thisSystem ? -1 : 0;
|
k->second.first.querySystem() == settings.thisSystem ? -1 : 0;
|
||||||
if (d == 0)
|
if (d == 0)
|
||||||
d = comparePriorities(state, j.first, k->second.first);
|
d = comparePriorities(state, j.first, k->second.first);
|
||||||
if (d == 0)
|
if (d == 0)
|
||||||
d = compareVersions(drvName.version, DrvName(k->second.first.name).version);
|
d = compareVersions(drvName.version, DrvName(k->second.first.queryName()).version);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d > 0) {
|
if (d > 0) {
|
||||||
newest.erase(drvName.name);
|
newest.erase(drvName.name);
|
||||||
newest.insert(Newest::value_type(drvName.name, j));
|
newest.insert(Newest::value_type(drvName.name, j));
|
||||||
multiple.erase(j.first.name);
|
multiple.erase(j.first.queryName());
|
||||||
} else if (d == 0) {
|
} else if (d == 0) {
|
||||||
multiple.insert(j.first.name);
|
multiple.insert(j.first.queryName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matches.clear();
|
matches.clear();
|
||||||
for (auto & j : newest) {
|
for (auto & j : newest) {
|
||||||
if (multiple.find(j.second.first.name) != multiple.end())
|
if (multiple.find(j.second.first.queryName()) != multiple.end())
|
||||||
printInfo(
|
printInfo(
|
||||||
format("warning: there are multiple derivations named ‘%1%’; using the first one")
|
"warning: there are multiple derivations named ‘%1%’; using the first one",
|
||||||
% j.second.first.name);
|
j.second.first.queryName());
|
||||||
matches.push_back(j.second);
|
matches.push_back(j.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,7 +386,8 @@ static void queryInstSources(EvalState & state,
|
||||||
if (dash != string::npos)
|
if (dash != string::npos)
|
||||||
name = string(name, dash + 1);
|
name = string(name, dash + 1);
|
||||||
|
|
||||||
DrvInfo elem(state, name, "", "", 0);
|
DrvInfo elem(state, "", nullptr);
|
||||||
|
elem.setName(name);
|
||||||
|
|
||||||
if (isDerivation(path)) {
|
if (isDerivation(path)) {
|
||||||
elem.setDrvPath(path);
|
elem.setDrvPath(path);
|
||||||
|
@ -468,8 +469,8 @@ static void installDerivations(Globals & globals,
|
||||||
path is not the one we want (e.g., `java-front' versus
|
path is not the one we want (e.g., `java-front' versus
|
||||||
`java-front-0.9pre15899'). */
|
`java-front-0.9pre15899'). */
|
||||||
if (globals.forceName != "")
|
if (globals.forceName != "")
|
||||||
i.name = globals.forceName;
|
i.setName(globals.forceName);
|
||||||
newNames.insert(DrvName(i.name).name);
|
newNames.insert(DrvName(i.queryName()).name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -484,17 +485,17 @@ static void installDerivations(Globals & globals,
|
||||||
DrvInfos installedElems = queryInstalled(*globals.state, profile);
|
DrvInfos installedElems = queryInstalled(*globals.state, profile);
|
||||||
|
|
||||||
for (auto & i : installedElems) {
|
for (auto & i : installedElems) {
|
||||||
DrvName drvName(i.name);
|
DrvName drvName(i.queryName());
|
||||||
if (!globals.preserveInstalled &&
|
if (!globals.preserveInstalled &&
|
||||||
newNames.find(drvName.name) != newNames.end() &&
|
newNames.find(drvName.name) != newNames.end() &&
|
||||||
!keep(i))
|
!keep(i))
|
||||||
printInfo(format("replacing old ‘%1%’") % i.name);
|
printInfo("replacing old ‘%s’", i.queryName());
|
||||||
else
|
else
|
||||||
allElems.push_back(i);
|
allElems.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & i : newElems)
|
for (auto & i : newElems)
|
||||||
printInfo(format("installing ‘%1%’") % i.name);
|
printInfo("installing ‘%s’", i.queryName());
|
||||||
}
|
}
|
||||||
|
|
||||||
printMissing(*globals.state, newElems);
|
printMissing(*globals.state, newElems);
|
||||||
|
@ -548,7 +549,7 @@ static void upgradeDerivations(Globals & globals,
|
||||||
/* Go through all installed derivations. */
|
/* Go through all installed derivations. */
|
||||||
DrvInfos newElems;
|
DrvInfos newElems;
|
||||||
for (auto & i : installedElems) {
|
for (auto & i : installedElems) {
|
||||||
DrvName drvName(i.name);
|
DrvName drvName(i.queryName());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -569,7 +570,7 @@ static void upgradeDerivations(Globals & globals,
|
||||||
for (auto j = availElems.begin(); j != availElems.end(); ++j) {
|
for (auto j = availElems.begin(); j != availElems.end(); ++j) {
|
||||||
if (comparePriorities(*globals.state, i, *j) > 0)
|
if (comparePriorities(*globals.state, i, *j) > 0)
|
||||||
continue;
|
continue;
|
||||||
DrvName newName(j->name);
|
DrvName newName(j->queryName());
|
||||||
if (newName.name == drvName.name) {
|
if (newName.name == drvName.name) {
|
||||||
int d = compareVersions(drvName.version, newName.version);
|
int d = compareVersions(drvName.version, newName.version);
|
||||||
if ((upgradeType == utLt && d < 0) ||
|
if ((upgradeType == utLt && d < 0) ||
|
||||||
|
@ -596,14 +597,13 @@ static void upgradeDerivations(Globals & globals,
|
||||||
{
|
{
|
||||||
const char * action = compareVersions(drvName.version, bestVersion) <= 0
|
const char * action = compareVersions(drvName.version, bestVersion) <= 0
|
||||||
? "upgrading" : "downgrading";
|
? "upgrading" : "downgrading";
|
||||||
printInfo(
|
printInfo("%1% ‘%2%’ to ‘%3%’",
|
||||||
format("%1% ‘%2%’ to ‘%3%’")
|
action, i.queryName(), bestElem->queryName());
|
||||||
% action % i.name % bestElem->name);
|
|
||||||
newElems.push_back(*bestElem);
|
newElems.push_back(*bestElem);
|
||||||
} else newElems.push_back(i);
|
} else newElems.push_back(i);
|
||||||
|
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addPrefix(format("while trying to find an upgrade for ‘%1%’:\n") % i.name);
|
e.addPrefix(fmt("while trying to find an upgrade for ‘%s’:\n", i.queryName()));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -663,10 +663,10 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
|
|
||||||
/* Update all matching derivations. */
|
/* Update all matching derivations. */
|
||||||
for (auto & i : installedElems) {
|
for (auto & i : installedElems) {
|
||||||
DrvName drvName(i.name);
|
DrvName drvName(i.queryName());
|
||||||
for (auto & j : selectors)
|
for (auto & j : selectors)
|
||||||
if (j.matches(drvName)) {
|
if (j.matches(drvName)) {
|
||||||
printInfo(format("setting flag on ‘%1%’") % i.name);
|
printInfo("setting flag on ‘%1%’", i.queryName());
|
||||||
j.hits++;
|
j.hits++;
|
||||||
setMetaFlag(*globals.state, i, flagName, flagValue);
|
setMetaFlag(*globals.state, i, flagName, flagValue);
|
||||||
break;
|
break;
|
||||||
|
@ -702,7 +702,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
DrvInfo & drv(elems.front());
|
DrvInfo & drv(elems.front());
|
||||||
|
|
||||||
if (globals.forceName != "")
|
if (globals.forceName != "")
|
||||||
drv.name = globals.forceName;
|
drv.setName(globals.forceName);
|
||||||
|
|
||||||
if (drv.queryDrvPath() != "") {
|
if (drv.queryDrvPath() != "") {
|
||||||
PathSet paths = {drv.queryDrvPath()};
|
PathSet paths = {drv.queryDrvPath()};
|
||||||
|
@ -732,7 +732,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
|
||||||
DrvInfos newElems;
|
DrvInfos newElems;
|
||||||
|
|
||||||
for (auto & i : installedElems) {
|
for (auto & i : installedElems) {
|
||||||
DrvName drvName(i.name);
|
DrvName drvName(i.queryName());
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto & j : selectors)
|
for (auto & j : selectors)
|
||||||
/* !!! the repeated calls to followLinksToStorePath()
|
/* !!! the repeated calls to followLinksToStorePath()
|
||||||
|
@ -740,7 +740,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
|
||||||
if ((isPath(j) && i.queryOutPath() == globals.state->store->followLinksToStorePath(j))
|
if ((isPath(j) && i.queryOutPath() == globals.state->store->followLinksToStorePath(j))
|
||||||
|| DrvName(j).matches(drvName))
|
|| DrvName(j).matches(drvName))
|
||||||
{
|
{
|
||||||
printInfo(format("uninstalling ‘%1%’") % i.name);
|
printInfo("uninstalling ‘%s’", i.queryName());
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -771,9 +771,11 @@ static bool cmpChars(char a, char b)
|
||||||
|
|
||||||
static bool cmpElemByName(const DrvInfo & a, const DrvInfo & b)
|
static bool cmpElemByName(const DrvInfo & a, const DrvInfo & b)
|
||||||
{
|
{
|
||||||
|
auto a_name = a.queryName();
|
||||||
|
auto b_name = b.queryName();
|
||||||
return lexicographical_compare(
|
return lexicographical_compare(
|
||||||
a.name.begin(), a.name.end(),
|
a_name.begin(), a_name.end(),
|
||||||
b.name.begin(), b.name.end(), cmpChars);
|
b_name.begin(), b_name.end(), cmpChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -822,13 +824,13 @@ typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff;
|
||||||
static VersionDiff compareVersionAgainstSet(
|
static VersionDiff compareVersionAgainstSet(
|
||||||
const DrvInfo & elem, const DrvInfos & elems, string & version)
|
const DrvInfo & elem, const DrvInfos & elems, string & version)
|
||||||
{
|
{
|
||||||
DrvName name(elem.name);
|
DrvName name(elem.queryName());
|
||||||
|
|
||||||
VersionDiff diff = cvUnavail;
|
VersionDiff diff = cvUnavail;
|
||||||
version = "?";
|
version = "?";
|
||||||
|
|
||||||
for (auto & i : elems) {
|
for (auto & i : elems) {
|
||||||
DrvName name2(i.name);
|
DrvName name2(i.queryName());
|
||||||
if (name.name == name2.name) {
|
if (name.name == name2.name) {
|
||||||
int d = compareVersions(name.version, name2.version);
|
int d = compareVersions(name.version, name2.version);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
|
@ -857,8 +859,8 @@ static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
|
||||||
for (auto & i : elems) {
|
for (auto & i : elems) {
|
||||||
JSONObject pkgObj = topObj.object(i.attrPath);
|
JSONObject pkgObj = topObj.object(i.attrPath);
|
||||||
|
|
||||||
pkgObj.attr("name", i.name);
|
pkgObj.attr("name", i.queryName());
|
||||||
pkgObj.attr("system", i.system);
|
pkgObj.attr("system", i.querySystem());
|
||||||
|
|
||||||
JSONObject metaObj = pkgObj.object("meta");
|
JSONObject metaObj = pkgObj.object("meta");
|
||||||
StringSet metaNames = i.queryMetaNames();
|
StringSet metaNames = i.queryMetaNames();
|
||||||
|
@ -866,7 +868,7 @@ static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
|
||||||
auto placeholder = metaObj.placeholder(j);
|
auto placeholder = metaObj.placeholder(j);
|
||||||
Value * v = i.queryMeta(j);
|
Value * v = i.queryMeta(j);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
printError(format("derivation ‘%1%’ has invalid meta attribute ‘%2%’") % i.name % j);
|
printError("derivation ‘%s’ has invalid meta attribute ‘%s’", i.queryName(), j);
|
||||||
placeholder.write(nullptr);
|
placeholder.write(nullptr);
|
||||||
} else {
|
} else {
|
||||||
PathSet context;
|
PathSet context;
|
||||||
|
@ -963,7 +965,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
try {
|
try {
|
||||||
paths.insert(i.queryOutPath());
|
paths.insert(i.queryOutPath());
|
||||||
} catch (AssertionError & e) {
|
} catch (AssertionError & e) {
|
||||||
printMsg(lvlTalkative, format("skipping derivation named ‘%1%’ which gives an assertion failure") % i.name);
|
printMsg(lvlTalkative, "skipping derivation named ‘%s’ which gives an assertion failure", i.queryName());
|
||||||
i.setFailed();
|
i.setFailed();
|
||||||
}
|
}
|
||||||
validPaths = globals.state->store->queryValidPaths(paths);
|
validPaths = globals.state->store->queryValidPaths(paths);
|
||||||
|
@ -1024,9 +1026,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
columns.push_back(i.attrPath);
|
columns.push_back(i.attrPath);
|
||||||
|
|
||||||
if (xmlOutput)
|
if (xmlOutput)
|
||||||
attrs["name"] = i.name;
|
attrs["name"] = i.queryName();
|
||||||
else if (printName)
|
else if (printName)
|
||||||
columns.push_back(i.name);
|
columns.push_back(i.queryName());
|
||||||
|
|
||||||
if (compareVersions) {
|
if (compareVersions) {
|
||||||
/* Compare this element against the versions of the
|
/* Compare this element against the versions of the
|
||||||
|
@ -1059,10 +1061,10 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlOutput) {
|
if (xmlOutput) {
|
||||||
if (i.system != "") attrs["system"] = i.system;
|
if (i.querySystem() != "") attrs["system"] = i.querySystem();
|
||||||
}
|
}
|
||||||
else if (printSystem)
|
else if (printSystem)
|
||||||
columns.push_back(i.system);
|
columns.push_back(i.querySystem());
|
||||||
|
|
||||||
if (printDrvPath) {
|
if (printDrvPath) {
|
||||||
string drvPath = i.queryDrvPath();
|
string drvPath = i.queryDrvPath();
|
||||||
|
@ -1110,7 +1112,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
attrs2["name"] = j;
|
attrs2["name"] = j;
|
||||||
Value * v = i.queryMeta(j);
|
Value * v = i.queryMeta(j);
|
||||||
if (!v)
|
if (!v)
|
||||||
printError(format("derivation ‘%1%’ has invalid meta attribute ‘%2%’") % i.name % j);
|
printError("derivation ‘%s’ has invalid meta attribute ‘%s’", i.queryName(), j);
|
||||||
else {
|
else {
|
||||||
if (v->type == tString) {
|
if (v->type == tString) {
|
||||||
attrs2["type"] = "string";
|
attrs2["type"] = "string";
|
||||||
|
@ -1161,9 +1163,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
cout.flush();
|
cout.flush();
|
||||||
|
|
||||||
} catch (AssertionError & e) {
|
} catch (AssertionError & e) {
|
||||||
printMsg(lvlTalkative, format("skipping derivation named ‘%1%’ which gives an assertion failure") % i.name);
|
printMsg(lvlTalkative, "skipping derivation named ‘%1%’ which gives an assertion failure", i.queryName());
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addPrefix(format("while querying the derivation named ‘%1%’:\n") % i.name);
|
e.addPrefix(fmt("while querying the derivation named ‘%1%’:\n", i.queryName()));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,9 +56,10 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
state.mkAttrs(v, 16);
|
state.mkAttrs(v, 16);
|
||||||
|
|
||||||
mkString(*state.allocAttr(v, state.sType), "derivation");
|
mkString(*state.allocAttr(v, state.sType), "derivation");
|
||||||
mkString(*state.allocAttr(v, state.sName), i.name);
|
mkString(*state.allocAttr(v, state.sName), i.queryName());
|
||||||
if (!i.system.empty())
|
auto system = i.querySystem();
|
||||||
mkString(*state.allocAttr(v, state.sSystem), i.system);
|
if (!system.empty())
|
||||||
|
mkString(*state.allocAttr(v, state.sSystem), system);
|
||||||
mkString(*state.allocAttr(v, state.sOutPath), i.queryOutPath());
|
mkString(*state.allocAttr(v, state.sOutPath), i.queryOutPath());
|
||||||
if (drvPath != "")
|
if (drvPath != "")
|
||||||
mkString(*state.allocAttr(v, state.sDrvPath), i.queryDrvPath());
|
mkString(*state.allocAttr(v, state.sDrvPath), i.queryDrvPath());
|
||||||
|
|
|
@ -62,17 +62,13 @@ struct Installable
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A command that operates on a list of "installables", which can be
|
struct SourceExprCommand : virtual Args, StoreCommand
|
||||||
store paths, attribute paths, Nix expressions, etc. */
|
|
||||||
struct InstallablesCommand : virtual Args, StoreCommand
|
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<Installable>> installables;
|
|
||||||
Path file;
|
Path file;
|
||||||
|
|
||||||
InstallablesCommand()
|
SourceExprCommand()
|
||||||
{
|
{
|
||||||
mkFlag('f', "file", "file", "evaluate FILE rather than the default", &file);
|
mkFlag('f', "file", "file", "evaluate FILE rather than the default", &file);
|
||||||
expectArgs("installables", &_installables);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a value representing the Nix expression from which we
|
/* Return a value representing the Nix expression from which we
|
||||||
|
@ -81,14 +77,32 @@ struct InstallablesCommand : virtual Args, StoreCommand
|
||||||
= import ...; bla = import ...; }’. */
|
= import ...; bla = import ...; }’. */
|
||||||
Value * getSourceExpr(EvalState & state);
|
Value * getSourceExpr(EvalState & state);
|
||||||
|
|
||||||
|
ref<EvalState> getEvalState();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::shared_ptr<EvalState> evalState;
|
||||||
|
|
||||||
|
Value * vSourceExpr = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A command that operates on a list of "installables", which can be
|
||||||
|
store paths, attribute paths, Nix expressions, etc. */
|
||||||
|
struct InstallablesCommand : virtual Args, SourceExprCommand
|
||||||
|
{
|
||||||
|
std::vector<std::shared_ptr<Installable>> installables;
|
||||||
|
|
||||||
|
InstallablesCommand()
|
||||||
|
{
|
||||||
|
expectArgs("installables", &_installables);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Installable>> parseInstallables(ref<Store> store, Strings ss);
|
std::vector<std::shared_ptr<Installable>> parseInstallables(ref<Store> store, Strings ss);
|
||||||
|
|
||||||
enum ToStorePathsMode { Build, NoBuild, DryRun };
|
enum ToStorePathsMode { Build, NoBuild, DryRun };
|
||||||
|
|
||||||
PathSet toStorePaths(ref<Store> store, ToStorePathsMode mode);
|
PathSet toStorePaths(ref<Store> store, ToStorePathsMode mode);
|
||||||
|
|
||||||
ref<EvalState> getEvalState();
|
|
||||||
|
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
|
||||||
virtual bool useDefaultInstallables() { return true; }
|
virtual bool useDefaultInstallables() { return true; }
|
||||||
|
@ -96,10 +110,6 @@ struct InstallablesCommand : virtual Args, StoreCommand
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Strings _installables;
|
Strings _installables;
|
||||||
|
|
||||||
std::shared_ptr<EvalState> evalState;
|
|
||||||
|
|
||||||
Value * vSourceExpr = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A command that operates on zero or more store paths. */
|
/* A command that operates on zero or more store paths. */
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
Value * InstallablesCommand::getSourceExpr(EvalState & state)
|
Value * SourceExprCommand::getSourceExpr(EvalState & state)
|
||||||
{
|
{
|
||||||
if (vSourceExpr) return vSourceExpr;
|
if (vSourceExpr) return vSourceExpr;
|
||||||
|
|
||||||
|
@ -59,6 +59,13 @@ Value * InstallablesCommand::getSourceExpr(EvalState & state)
|
||||||
return vSourceExpr;
|
return vSourceExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ref<EvalState> SourceExprCommand::getEvalState()
|
||||||
|
{
|
||||||
|
if (!evalState)
|
||||||
|
evalState = std::make_shared<EvalState>(Strings{}, getStore());
|
||||||
|
return ref<EvalState>(evalState);
|
||||||
|
}
|
||||||
|
|
||||||
struct InstallableStoreDrv : Installable
|
struct InstallableStoreDrv : Installable
|
||||||
{
|
{
|
||||||
Path storePath;
|
Path storePath;
|
||||||
|
@ -237,13 +244,6 @@ PathSet InstallablesCommand::toStorePaths(ref<Store> store, ToStorePathsMode mod
|
||||||
return outPaths;
|
return outPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<EvalState> InstallablesCommand::getEvalState()
|
|
||||||
{
|
|
||||||
if (!evalState)
|
|
||||||
evalState = std::make_shared<EvalState>(Strings{}, getStore());
|
|
||||||
return ref<EvalState>(evalState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstallablesCommand::prepare()
|
void InstallablesCommand::prepare()
|
||||||
{
|
{
|
||||||
installables = parseInstallables(getStore(), _installables);
|
installables = parseInstallables(getStore(), _installables);
|
||||||
|
|
130
src/nix/search.cc
Normal file
130
src/nix/search.cc
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
#include "command.hh"
|
||||||
|
#include "globals.hh"
|
||||||
|
#include "eval.hh"
|
||||||
|
#include "eval-inline.hh"
|
||||||
|
#include "names.hh"
|
||||||
|
#include "get-drvs.hh"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
using namespace nix;
|
||||||
|
|
||||||
|
std::string hilite(const std::string & s, const std::smatch & m)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
m.empty()
|
||||||
|
? s
|
||||||
|
: std::string(m.prefix())
|
||||||
|
+ ANSI_RED + std::string(m.str()) + ANSI_NORMAL
|
||||||
|
+ std::string(m.suffix());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CmdSearch : SourceExprCommand
|
||||||
|
{
|
||||||
|
std::string re;
|
||||||
|
|
||||||
|
CmdSearch()
|
||||||
|
{
|
||||||
|
expectArg("regex", &re, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name() override
|
||||||
|
{
|
||||||
|
return "search";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description() override
|
||||||
|
{
|
||||||
|
return "query available packages";
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(ref<Store> store) override
|
||||||
|
{
|
||||||
|
settings.readOnlyMode = true;
|
||||||
|
|
||||||
|
std::regex regex(re, std::regex::extended | std::regex::icase);
|
||||||
|
|
||||||
|
auto state = getEvalState();
|
||||||
|
|
||||||
|
std::function<void(Value *, std::string, bool)> doExpr;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
doExpr = [&](Value * v, std::string attrPath, bool toplevel) {
|
||||||
|
debug("at attribute ‘%s’", attrPath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
state->forceValue(*v);
|
||||||
|
|
||||||
|
if (v->type == tLambda && toplevel) {
|
||||||
|
Value * v2 = state->allocValue();
|
||||||
|
state->autoCallFunction(*state->allocBindings(1), *v, *v2);
|
||||||
|
v = v2;
|
||||||
|
state->forceValue(*v);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->isDerivation(*v)) {
|
||||||
|
|
||||||
|
DrvInfo drv(*state, attrPath, v->attrs);
|
||||||
|
|
||||||
|
DrvName parsed(drv.queryName());
|
||||||
|
|
||||||
|
std::smatch attrPathMatch;
|
||||||
|
std::regex_search(attrPath, attrPathMatch, regex);
|
||||||
|
|
||||||
|
auto name = parsed.name;
|
||||||
|
std::smatch nameMatch;
|
||||||
|
std::regex_search(name, nameMatch, regex);
|
||||||
|
|
||||||
|
std::string description = drv.queryMetaString("description");
|
||||||
|
std::replace(description.begin(), description.end(), '\n', ' ');
|
||||||
|
std::smatch descriptionMatch;
|
||||||
|
std::regex_search(description, descriptionMatch, regex);
|
||||||
|
|
||||||
|
if (!attrPathMatch.empty()
|
||||||
|
|| !nameMatch.empty()
|
||||||
|
|| !descriptionMatch.empty())
|
||||||
|
{
|
||||||
|
if (!first) std::cout << "\n";
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
std::cout << fmt(
|
||||||
|
"Attribute name: %s\n"
|
||||||
|
"Package name: %s\n"
|
||||||
|
"Version: %s\n"
|
||||||
|
"Description: %s\n",
|
||||||
|
hilite(attrPath, attrPathMatch),
|
||||||
|
hilite(name, nameMatch),
|
||||||
|
parsed.version,
|
||||||
|
hilite(description, descriptionMatch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (v->type == tAttrs) {
|
||||||
|
|
||||||
|
if (!toplevel) {
|
||||||
|
auto attrs = v->attrs;
|
||||||
|
Bindings::iterator j = attrs->find(state->symbols.create("recurseForDerivations"));
|
||||||
|
if (j == attrs->end() || !state->forceBool(*j->value, *j->pos)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bindings::iterator j = v->attrs->find(state->symbols.create("_toplevel"));
|
||||||
|
bool toplevel2 = j != v->attrs->end() && state->forceBool(*j->value, *j->pos);
|
||||||
|
|
||||||
|
for (auto & i : *v->attrs) {
|
||||||
|
doExpr(i.value,
|
||||||
|
attrPath == "" ? (std::string) i.name : attrPath + "." + (std::string) i.name,
|
||||||
|
toplevel2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (AssertionError & e) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
doExpr(getSourceExpr(*state), "", true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static RegisterCommand r1(make_ref<CmdSearch>());
|
Loading…
Reference in a new issue