name-hash: properly fold directory names in adjust_dirname_case()
[gitweb.git] / diffcore-pickaxe.c
index 7715c13ec4780a755ec2a6552c0aec9994691087..9795ca1c159a5177b1b7031a87c8f8bd5e5be3d5 100644 (file)
@@ -7,6 +7,8 @@
 #include "diffcore.h"
 #include "xdiff-interface.h"
 #include "kwset.h"
+#include "commit.h"
+#include "quote.h"
 
 typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two,
                          struct diff_options *o,
@@ -21,7 +23,6 @@ static void diffgrep_consume(void *priv, char *line, unsigned long len)
 {
        struct diffgrep_cb *data = priv;
        regmatch_t regmatch;
-       int hold;
 
        if (line[0] != '+' && line[0] != '-')
                return;
@@ -31,11 +32,8 @@ static void diffgrep_consume(void *priv, char *line, unsigned long len)
                 * caller early.
                 */
                return;
-       /* Yuck -- line ought to be "const char *"! */
-       hold = line[len];
-       line[len] = '\0';
-       data->hit = !regexec(data->regexp, line + 1, 1, &regmatch, 0);
-       line[len] = hold;
+       data->hit = !regexec_buf(data->regexp, line + 1, len - 1, 1,
+                                &regmatch, 0);
 }
 
 static int diff_grep(mmfile_t *one, mmfile_t *two,
@@ -48,9 +46,11 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
        xdemitconf_t xecfg;
 
        if (!one)
-               return !regexec(regexp, two->ptr, 1, &regmatch, 0);
+               return !regexec_buf(regexp, two->ptr, two->size,
+                                   1, &regmatch, 0);
        if (!two)
-               return !regexec(regexp, one->ptr, 1, &regmatch, 0);
+               return !regexec_buf(regexp, one->ptr, one->size,
+                                   1, &regmatch, 0);
 
        /*
         * We have both sides; need to run textual diff and see if
@@ -81,8 +81,8 @@ static unsigned int contains(mmfile_t *mf, regex_t *regexp, kwset_t kws)
                regmatch_t regmatch;
                int flags = 0;
 
-               assert(data[sz] == '\0');
-               while (*data && !regexec(regexp, data, 1, &regmatch, flags)) {
+               while (*data &&
+                      !regexec_buf(regexp, data, sz, 1, &regmatch, flags)) {
                        flags |= REG_NOTBOL;
                        data += regmatch.rm_eo;
                        if (*data && regmatch.rm_so == regmatch.rm_eo)
@@ -198,6 +198,18 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
        *q = outq;
 }
 
+static void regcomp_or_die(regex_t *regex, const char *needle, int cflags)
+{
+       int err = regcomp(regex, needle, cflags);
+       if (err) {
+               /* The POSIX.2 people are surely sick */
+               char errbuf[1024];
+               regerror(err, regex, errbuf, 1024);
+               regfree(regex);
+               die("invalid regex: %s", errbuf);
+       }
+}
+
 void diffcore_pickaxe(struct diff_options *o)
 {
        const char *needle = o->pickaxe;
@@ -206,18 +218,19 @@ void diffcore_pickaxe(struct diff_options *o)
        kwset_t kws = NULL;
 
        if (opts & (DIFF_PICKAXE_REGEX | DIFF_PICKAXE_KIND_G)) {
-               int err;
                int cflags = REG_EXTENDED | REG_NEWLINE;
                if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
                        cflags |= REG_ICASE;
-               err = regcomp(&regex, needle, cflags);
-               if (err) {
-                       /* The POSIX.2 people are surely sick */
-                       char errbuf[1024];
-                       regerror(err, &regex, errbuf, 1024);
-                       regfree(&regex);
-                       die("invalid regex: %s", errbuf);
-               }
+               regcomp_or_die(&regex, needle, cflags);
+               regexp = &regex;
+       } else if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE) &&
+                  has_non_ascii(needle)) {
+               struct strbuf sb = STRBUF_INIT;
+               int cflags = REG_NEWLINE | REG_ICASE;
+
+               basic_regex_quote_buf(&sb, needle);
+               regcomp_or_die(&regex, sb.buf, cflags);
+               strbuf_release(&sb);
                regexp = &regex;
        } else {
                kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)