grep: support NUL chars in search strings for -F
[gitweb.git] / builtin / grep.c
index 40b9a93127482bebf6dc8c9eb39b2104711a543a..7653d8492a9f26b47cfaeec64f717107ffa204bc 100644 (file)
@@ -96,6 +96,9 @@ static pthread_cond_t cond_write;
 /* Signalled when we are finished with everything. */
 static pthread_cond_t cond_result;
 
+static int print_hunk_marks_between_files;
+static int printed_something;
+
 static void add_work(enum work_type type, char *name, void *id)
 {
        grep_lock();
@@ -159,7 +162,12 @@ static void work_done(struct work_item *w)
        for(; todo[todo_done].done && todo_done != todo_start;
            todo_done = (todo_done+1) % ARRAY_SIZE(todo)) {
                w = &todo[todo_done];
-               write_or_die(1, w->out.buf, w->out.len);
+               if (w->out.len) {
+                       if (print_hunk_marks_between_files && printed_something)
+                               write_or_die(1, "--\n", 3);
+                       write_or_die(1, w->out.buf, w->out.len);
+                       printed_something = 1;
+               }
                free(w->name);
                free(w->identifier);
        }
@@ -289,6 +297,7 @@ static int wait_all(void)
 static int grep_config(const char *var, const char *value, void *cb)
 {
        struct grep_opt *opt = cb;
+       char *color = NULL;
 
        switch (userdiff_config(var, value)) {
        case 0: break;
@@ -296,17 +305,30 @@ static int grep_config(const char *var, const char *value, void *cb)
        default: return 0;
        }
 
-       if (!strcmp(var, "color.grep")) {
+       if (!strcmp(var, "color.grep"))
                opt->color = git_config_colorbool(var, value, -1);
-               return 0;
-       }
-       if (!strcmp(var, "color.grep.match")) {
+       else if (!strcmp(var, "color.grep.context"))
+               color = opt->color_context;
+       else if (!strcmp(var, "color.grep.filename"))
+               color = opt->color_filename;
+       else if (!strcmp(var, "color.grep.function"))
+               color = opt->color_function;
+       else if (!strcmp(var, "color.grep.linenumber"))
+               color = opt->color_lineno;
+       else if (!strcmp(var, "color.grep.match"))
+               color = opt->color_match;
+       else if (!strcmp(var, "color.grep.selected"))
+               color = opt->color_selected;
+       else if (!strcmp(var, "color.grep.separator"))
+               color = opt->color_sep;
+       else
+               return git_color_default_config(var, value, cb);
+       if (color) {
                if (!value)
                        return config_error_nonbool(var);
-               color_parse(value, var, opt->color_match);
-               return 0;
+               color_parse(value, var, color);
        }
-       return git_color_default_config(var, value, cb);
+       return 0;
 }
 
 /*
@@ -702,11 +724,15 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
        if (!patterns)
                die_errno("cannot open '%s'", arg);
        while (strbuf_getline(&sb, patterns, '\n') == 0) {
+               char *s;
+               size_t len;
+
                /* ignore empty line like grep does */
                if (sb.len == 0)
                        continue;
-               append_grep_pattern(grep_opt, strbuf_detach(&sb, NULL), arg,
-                                   ++lno, GREP_PATTERN);
+
+               s = strbuf_detach(&sb, &len);
+               append_grep_pat(grep_opt, s, len, arg, ++lno, GREP_PATTERN);
        }
        fclose(patterns);
        strbuf_release(&sb);
@@ -872,7 +898,13 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        opt.regflags = REG_NEWLINE;
        opt.max_depth = -1;
 
-       strcpy(opt.color_match, GIT_COLOR_RED GIT_COLOR_BOLD);
+       strcpy(opt.color_context, "");
+       strcpy(opt.color_filename, "");
+       strcpy(opt.color_function, "");
+       strcpy(opt.color_lineno, "");
+       strcpy(opt.color_match, GIT_COLOR_BOLD_RED);
+       strcpy(opt.color_selected, "");
+       strcpy(opt.color_sep, GIT_COLOR_CYAN);
        opt.color = -1;
        git_config(grep_config, &opt);
        if (opt.color == -1)
@@ -926,8 +958,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        if (online_cpus() == 1 || !grep_threads_ok(&opt))
                use_threads = 0;
 
-       if (use_threads)
+       if (use_threads) {
+               if (opt.pre_context || opt.post_context)
+                       print_hunk_marks_between_files = 1;
                start_threads(&opt);
+       }
 #else
        use_threads = 0;
 #endif