about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-10-03T16·47+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-10-03T19·29+0200
commit104e55bb7f593b1ac3c54ffda48a9d72af7fbe6b (patch)
tree92eea5af2736190ec196a4bc68c16ea5f16dff2f /src
parent3800f441e49af78b95d403014459dbb9bb646e8a (diff)
nix-env: Add regular expression support in selectors
So you can now do things like:

  $ nix-env -qa '.*zip.*'
  $ nix-env -qa '.*(firefox|chromium).*'
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/names.cc6
-rw-r--r--src/libutil/regex.cc33
-rw-r--r--src/libutil/regex.hh22
3 files changed, 60 insertions, 1 deletions
diff --git a/src/libexpr/names.cc b/src/libexpr/names.cc
index 781c2b6468f9..c2b2733347f6 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 000000000000..36c8458cee08
--- /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 000000000000..aa012b721cb7
--- /dev/null
+++ b/src/libutil/regex.hh
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "types.hh"
+
+#include <sys/types.h>
+#include <regex.h>
+
+namespace nix {
+
+class Regex
+{
+public:
+    Regex(const string & pattern);
+    ~Regex();
+    bool matches(const string & s);
+
+private:
+    regex_t preg;
+    string showError(int err);
+};
+
+}