aboutsummaryrefslogtreecommitdiff
path: root/src/nix
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-07-17 19:02:56 +0200
committerEelco Dolstra <edolstra@gmail.com>2017-07-20 13:33:13 +0200
commit90825dea518ea078f0783a72cc471a5b3716d198 (patch)
treeb6f6fed6e8c7a96a6769344060409f19a56290b9 /src/nix
parent3162ad5ff497b92fc25cd3f397eaff01d67340cc (diff)
Add "nix search" command
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/command.hh34
-rw-r--r--src/nix/installables.cc16
-rw-r--r--src/nix/search.cc130
3 files changed, 160 insertions, 20 deletions
diff --git a/src/nix/command.hh b/src/nix/command.hh
index ae7709b5d..536802653 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -62,17 +62,13 @@ struct Installable
}
};
-/* A command that operates on a list of "installables", which can be
- store paths, attribute paths, Nix expressions, etc. */
-struct InstallablesCommand : virtual Args, StoreCommand
+struct SourceExprCommand : virtual Args, StoreCommand
{
- std::vector<std::shared_ptr<Installable>> installables;
Path file;
- InstallablesCommand()
+ SourceExprCommand()
{
mkFlag('f', "file", "file", "evaluate FILE rather than the default", &file);
- expectArgs("installables", &_installables);
}
/* Return a value representing the Nix expression from which we
@@ -81,14 +77,32 @@ struct InstallablesCommand : virtual Args, StoreCommand
= import ...; bla = import ...; }ā€™. */
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);
enum ToStorePathsMode { Build, NoBuild, DryRun };
PathSet toStorePaths(ref<Store> store, ToStorePathsMode mode);
- ref<EvalState> getEvalState();
-
void prepare() override;
virtual bool useDefaultInstallables() { return true; }
@@ -96,10 +110,6 @@ struct InstallablesCommand : virtual Args, StoreCommand
private:
Strings _installables;
-
- std::shared_ptr<EvalState> evalState;
-
- Value * vSourceExpr = 0;
};
/* A command that operates on zero or more store paths. */
diff --git a/src/nix/installables.cc b/src/nix/installables.cc
index 7fad8fe41..4da736f4d 100644
--- a/src/nix/installables.cc
+++ b/src/nix/installables.cc
@@ -12,7 +12,7 @@
namespace nix {
-Value * InstallablesCommand::getSourceExpr(EvalState & state)
+Value * SourceExprCommand::getSourceExpr(EvalState & state)
{
if (vSourceExpr) return vSourceExpr;
@@ -59,6 +59,13 @@ Value * InstallablesCommand::getSourceExpr(EvalState & state)
return vSourceExpr;
}
+ref<EvalState> SourceExprCommand::getEvalState()
+{
+ if (!evalState)
+ evalState = std::make_shared<EvalState>(Strings{}, getStore());
+ return ref<EvalState>(evalState);
+}
+
struct InstallableStoreDrv : Installable
{
Path storePath;
@@ -237,13 +244,6 @@ PathSet InstallablesCommand::toStorePaths(ref<Store> store, ToStorePathsMode mod
return outPaths;
}
-ref<EvalState> InstallablesCommand::getEvalState()
-{
- if (!evalState)
- evalState = std::make_shared<EvalState>(Strings{}, getStore());
- return ref<EvalState>(evalState);
-}
-
void InstallablesCommand::prepare()
{
installables = parseInstallables(getStore(), _installables);
diff --git a/src/nix/search.cc b/src/nix/search.cc
new file mode 100644
index 000000000..813f6d0a6
--- /dev/null
+++ b/src/nix/search.cc
@@ -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>());