diff --git a/doc/manual/command-ref/nix-env.xml b/doc/manual/command-ref/nix-env.xml
index 1db71f75e..f8af6e954 100644
--- a/doc/manual/command-ref/nix-env.xml
+++ b/doc/manual/command-ref/nix-env.xml
@@ -66,6 +66,75 @@ be performed. These are documented below.
+
+
+Selectors
+
+Several commands, such as nix-env -q and
+nix-env -i, take a list of arguments that specify
+the packages on which to operate. These are extended regular
+expressions that must match the entire name of the package. (For
+details on regular expressions, see
+regex7.)
+The match is case-sensitive. The regular expression can optionally be
+followed by a dash and a version number; if omitted, any version of
+the package will match. Here are some examples:
+
+
+
+
+ firefox
+ Matches the package name
+ firefox and any version.
+
+
+
+ firefox-32.0
+ Matches the package name
+ firefox and version
+ 32.0.
+
+
+
+ gtk\\+
+ Matches the package name
+ gtk+. The + character must
+ be escaped using a backslash to prevent it from being interpreted
+ as a quantifier, and the backslash must be escaped in turn with
+ another backslash to ensure that the shell passes it
+ on.
+
+
+
+ .\*
+ Matches any package name. This is the default for
+ most commands.
+
+
+
+ '.*zip.*'
+ Matches any package name containing the string
+ zip. Note the dots: '*zip*'
+ does not work, because in a regular expression, the character
+ * is interpreted as a
+ quantifier.
+
+
+
+ '.*(firefox|chromium).*'
+ Matches any package name containing the strings
+ firefox or
+ chromium.
+
+
+
+
+
+
+
+
+
+
Common options
@@ -262,7 +331,7 @@ number of possible ways:
attribute paths that select attributes from the
top-level Nix expression. This is faster than using derivation
names and unambiguous. To find out the attribute paths of available
- packages, use nix-env -qaP '*'.
+ packages, use nix-env -qaP.
If
path is given,
@@ -326,7 +395,7 @@ number of possible ways:
Remove all previously installed packages first.
- This is equivalent to running nix-env -e '*'
+ This is equivalent to running nix-env -e '.*'
first, except that everything happens in a single
transaction.
@@ -369,7 +438,7 @@ $ nix-env -i -A xorg.xorgserver
To install all derivations in the Nix expression foo.nix:
-$ nix-env -f ~/foo.nix -i '*'
+$ nix-env -f ~/foo.nix -i '.*'
@@ -537,7 +606,7 @@ upgrading `gcc-3.4' to `gcc-3.3.2'
$ nix-env --upgrade pan
(no upgrades available, so nothing happens)
-$ nix-env -u '*' (try to upgrade everything)
+$ nix-env -u (try to upgrade everything)
upgrading `hello-2.1.2' to `hello-2.1.3'
upgrading `mozilla-1.2' to `mozilla-1.4'
@@ -624,7 +693,7 @@ paths designated by the symbolic names
$ nix-env --uninstall gcc
-$ nix-env -e '*' (remove everything)
+$ nix-env -e '.*' (remove everything)
@@ -700,7 +769,7 @@ After this, nix-env -u will ignore Firefox.
Firefox while the old remains part of the profile:
-$ nix-env -q \*
+$ nix-env -q
firefox-2.0.0.9 (the current one)
$ nix-env --preserve-installed -i firefox-2.0.0.11
@@ -716,7 +785,7 @@ setting flag on `firefox-2.0.0.9'
$ nix-env --preserve-installed -i firefox-2.0.0.11
installing `firefox-2.0.0.11'
-$ nix-env -q \*
+$ nix-env -q
firefox-2.0.0.11 (the enabled one)
firefox-2.0.0.9 (the disabled one)
@@ -817,8 +886,7 @@ profile (), or the derivations that are
available for installation in the active Nix expression
(). It only prints information about
derivations whose symbolic name matches one of
-names. The wildcard *
-shows all derivations.
+names.
The derivations are sorted by their name
attributes.
@@ -1024,7 +1092,7 @@ user environment elements, etc. -->
Examples
-$ nix-env -q '*' (show installed derivations)
+$ nix-env -q (show installed derivations)
bison-1.875c
docbook-xml-4.2
firefox-1.0.4
@@ -1032,14 +1100,14 @@ MPlayer-1.0pre7
ORBit2-2.8.3
...
-$ nix-env -qa '*' (show available derivations)
+$ nix-env -qa (show available derivations)
firefox-1.0.7
GConf-2.4.0.1
MPlayer-1.0pre7
ORBit2-2.8.3
...
-$ nix-env -qas '*' (show status of available derivations)
+$ nix-env -qas (show status of available derivations)
-P- firefox-1.0.7 (not installed but present)
--S GConf-2.4.0.1 (not present, but there is a substitute for fast installation)
--S MPlayer-1.0pre3 (i.e., this is not the installed MPlayer, even though the version is the same!)
@@ -1047,24 +1115,29 @@ IP- ORBit2-2.8.3 (installed and by definition present)(show available derivations in the Nix expression foo.nix)
-$ nix-env -f ./foo.nix -qa '*'
+$ nix-env -f ./foo.nix -qa
foo-1.2.3
-$ nix-env -qc '*' (compare installed versions to what’s available)
+$ nix-env -qc (compare installed versions to what’s available)...
acrobat-reader-7.0 - ? (package is not available at all)
autoconf-2.59 = 2.59 (same version)
firefox-1.0.4 < 1.0.7 (a more recent version is available)...
-(show info about a specific package, in XML)
-$ nix-env -qa --xml --description firefox
-
-
-
-]]>
+$ nix-env -qa '.*zip.*' (show all packages with “zip” in the name)
+bzip2-1.0.6
+gzip-1.6
+zip-3.0
+...
+
+$ nix-env -qa '.*(firefox|chromium).*' (show all packages with “firefox” or “chromium” in the name)
+chromium-37.0.2062.94
+chromium-beta-38.0.2125.24
+firefox-32.0.3
+firefox-with-plugins-13.0.1
+...
+
diff --git a/doc/manual/release-notes/rl-1.8.xml b/doc/manual/release-notes/rl-1.8.xml
index de6f891ff..0e6150ccf 100644
--- a/doc/manual/release-notes/rl-1.8.xml
+++ b/doc/manual/release-notes/rl-1.8.xml
@@ -8,6 +8,16 @@
+ nix-env selectors are now regular
+ expressions. For instance, you can do
+
+
+$ nix-env -qa '.*zip.*'
+
+
+ to query all packages with a name containing
+ zip.
+
Derivations can specify the new special attribute
allowedRequisites, which has a similar meaning to
allowedReferences. But instead of only enforcing
diff --git a/src/libexpr/names.cc b/src/libexpr/names.cc
index 781c2b646..c2b273334 100644
--- a/src/libexpr/names.cc
+++ b/src/libexpr/names.cc
@@ -1,5 +1,6 @@
#include "names.hh"
#include "util.hh"
+#include "regex.hh"
namespace nix {
@@ -32,7 +33,10 @@ DrvName::DrvName(const string & s) : hits(0)
bool DrvName::matches(DrvName & n)
{
- if (name != "*" && name != n.name) return false;
+ if (name != "*") {
+ Regex regex(name);
+ if (!regex.matches(n.name)) return false;
+ }
if (version != "" && version != n.version) return false;
return true;
}
diff --git a/src/libutil/regex.cc b/src/libutil/regex.cc
new file mode 100644
index 000000000..36c8458ce
--- /dev/null
+++ b/src/libutil/regex.cc
@@ -0,0 +1,33 @@
+#include "regex.hh"
+#include "types.hh"
+
+namespace nix {
+
+Regex::Regex(const string & pattern)
+{
+ /* Patterns must match the entire string. */
+ int err = regcomp(&preg, ("^(" + pattern + ")$").c_str(), REG_NOSUB | REG_EXTENDED);
+ if (err) throw Error(format("compiling pattern ‘%1%’: %2%") % pattern % showError(err));
+}
+
+Regex::~Regex()
+{
+ regfree(&preg);
+}
+
+bool Regex::matches(const string & s)
+{
+ int err = regexec(&preg, s.c_str(), 0, 0, 0);
+ if (err == 0) return true;
+ else if (err == REG_NOMATCH) return false;
+ throw Error(format("matching string ‘%1%’: %2%") % s % showError(err));
+}
+
+string Regex::showError(int err)
+{
+ char buf[256];
+ regerror(err, &preg, buf, sizeof(buf));
+ return string(buf);
+}
+
+}
diff --git a/src/libutil/regex.hh b/src/libutil/regex.hh
new file mode 100644
index 000000000..aa012b721
--- /dev/null
+++ b/src/libutil/regex.hh
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "types.hh"
+
+#include
+#include
+
+namespace nix {
+
+class Regex
+{
+public:
+ Regex(const string & pattern);
+ ~Regex();
+ bool matches(const string & s);
+
+private:
+ regex_t preg;
+ string showError(int err);
+};
+
+}