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); +}; + +}