revision.c: reduce implicit dependency the_repository
[gitweb.git] / grep.c
diff --git a/grep.c b/grep.c
index 49a744f96b373c6b90cde4d2d090eea2aa18cbc3..f6bd89e40b7f7a8442a6e0a302a1e6080df5afbd 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -1,18 +1,33 @@
 #include "cache.h"
 #include "config.h"
 #include "grep.h"
+#include "object-store.h"
 #include "userdiff.h"
 #include "xdiff-interface.h"
 #include "diff.h"
 #include "diffcore.h"
 #include "commit.h"
 #include "quote.h"
+#include "help.h"
 
 static int grep_source_load(struct grep_source *gs);
-static int grep_source_is_binary(struct grep_source *gs);
+static int grep_source_is_binary(struct grep_source *gs,
+                                struct index_state *istate);
 
 static struct grep_opt grep_defaults;
 
+static const char *color_grep_slots[] = {
+       [GREP_COLOR_CONTEXT]        = "context",
+       [GREP_COLOR_FILENAME]       = "filename",
+       [GREP_COLOR_FUNCTION]       = "function",
+       [GREP_COLOR_LINENO]         = "lineNumber",
+       [GREP_COLOR_COLUMNNO]       = "column",
+       [GREP_COLOR_MATCH_CONTEXT]  = "matchContext",
+       [GREP_COLOR_MATCH_SELECTED] = "matchSelected",
+       [GREP_COLOR_SELECTED]       = "selected",
+       [GREP_COLOR_SEP]            = "separator",
+};
+
 static void std_output(struct grep_opt *opt, const void *buf, size_t size)
 {
        fwrite(buf, size, 1, stdout);
@@ -28,7 +43,7 @@ static void color_set(char *dst, const char *color_bytes)
  * We could let the compiler do this, but without C99 initializers
  * the code gets unwieldy and unreadable, so...
  */
-void init_grep_defaults(void)
+void init_grep_defaults(struct repository *repo)
 {
        struct grep_opt *opt = &grep_defaults;
        static int run_once;
@@ -38,19 +53,20 @@ void init_grep_defaults(void)
        run_once++;
 
        memset(opt, 0, sizeof(*opt));
+       opt->repo = repo;
        opt->relative = 1;
        opt->pathname = 1;
        opt->max_depth = -1;
        opt->pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED;
-       color_set(opt->color_context, "");
-       color_set(opt->color_filename, "");
-       color_set(opt->color_function, "");
-       color_set(opt->color_lineno, "");
-       color_set(opt->color_columnno, "");
-       color_set(opt->color_match_context, GIT_COLOR_BOLD_RED);
-       color_set(opt->color_match_selected, GIT_COLOR_BOLD_RED);
-       color_set(opt->color_selected, "");
-       color_set(opt->color_sep, GIT_COLOR_CYAN);
+       color_set(opt->colors[GREP_COLOR_CONTEXT], "");
+       color_set(opt->colors[GREP_COLOR_FILENAME], "");
+       color_set(opt->colors[GREP_COLOR_FUNCTION], "");
+       color_set(opt->colors[GREP_COLOR_LINENO], "");
+       color_set(opt->colors[GREP_COLOR_COLUMNNO], "");
+       color_set(opt->colors[GREP_COLOR_MATCH_CONTEXT], GIT_COLOR_BOLD_RED);
+       color_set(opt->colors[GREP_COLOR_MATCH_SELECTED], GIT_COLOR_BOLD_RED);
+       color_set(opt->colors[GREP_COLOR_SELECTED], "");
+       color_set(opt->colors[GREP_COLOR_SEP], GIT_COLOR_CYAN);
        opt->only_matching = 0;
        opt->color = -1;
        opt->output = std_output;
@@ -71,6 +87,8 @@ static int parse_pattern_type_arg(const char *opt, const char *arg)
        die("bad %s argument: %s", opt, arg);
 }
 
+define_list_config_array_extra(color_grep_slots, {"match"});
+
 /*
  * Read the configuration file once and store it in
  * the grep_defaults template.
@@ -78,7 +96,7 @@ static int parse_pattern_type_arg(const char *opt, const char *arg)
 int grep_config(const char *var, const char *value, void *cb)
 {
        struct grep_opt *opt = &grep_defaults;
-       char *color = NULL;
+       const char *slot;
 
        if (userdiff_config(var, value) < 0)
                return -1;
@@ -109,34 +127,18 @@ int grep_config(const char *var, const char *value, void *cb)
 
        if (!strcmp(var, "color.grep"))
                opt->color = git_config_colorbool(var, value);
-       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.column"))
-               color = opt->color_columnno;
-       else if (!strcmp(var, "color.grep.matchcontext"))
-               color = opt->color_match_context;
-       else if (!strcmp(var, "color.grep.matchselected"))
-               color = opt->color_match_selected;
-       else if (!strcmp(var, "color.grep.selected"))
-               color = opt->color_selected;
-       else if (!strcmp(var, "color.grep.separator"))
-               color = opt->color_sep;
-       else if (!strcmp(var, "color.grep.match")) {
-               int rc = 0;
-               if (!value)
-                       return config_error_nonbool(var);
-               rc |= color_parse(value, opt->color_match_context);
-               rc |= color_parse(value, opt->color_match_selected);
-               return rc;
-       }
-
-       if (color) {
+       if (!strcmp(var, "color.grep.match")) {
+               if (grep_config("color.grep.matchcontext", value, cb) < 0)
+                       return -1;
+               if (grep_config("color.grep.matchselected", value, cb) < 0)
+                       return -1;
+       } else if (skip_prefix(var, "color.grep.", &slot)) {
+               int i = LOOKUP_CONFIG(color_grep_slots, slot);
+               char *color;
+
+               if (i < 0)
+                       return -1;
+               color = opt->colors[i];
                if (!value)
                        return config_error_nonbool(var);
                return color_parse(value, color);
@@ -149,11 +151,13 @@ int grep_config(const char *var, const char *value, void *cb)
  * default values from the template we read the configuration
  * information in an earlier call to git_config(grep_config).
  */
-void grep_init(struct grep_opt *opt, const char *prefix)
+void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix)
 {
        struct grep_opt *def = &grep_defaults;
+       int i;
 
        memset(opt, 0, sizeof(*opt));
+       opt->repo = repo;
        opt->prefix = prefix;
        opt->prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
        opt->pattern_tail = &opt->pattern_list;
@@ -170,15 +174,8 @@ void grep_init(struct grep_opt *opt, const char *prefix)
        opt->relative = def->relative;
        opt->output = def->output;
 
-       color_set(opt->color_context, def->color_context);
-       color_set(opt->color_filename, def->color_filename);
-       color_set(opt->color_function, def->color_function);
-       color_set(opt->color_lineno, def->color_lineno);
-       color_set(opt->color_columnno, def->color_columnno);
-       color_set(opt->color_match_context, def->color_match_context);
-       color_set(opt->color_match_selected, def->color_match_selected);
-       color_set(opt->color_selected, def->color_selected);
-       color_set(opt->color_sep, def->color_sep);
+       for (i = 0; i < NR_GREP_COLORS; i++)
+               color_set(opt->colors[i], def->colors[i]);
 }
 
 static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt)
@@ -1109,12 +1106,12 @@ static void output_sep(struct grep_opt *opt, char sign)
        if (opt->null_following_name)
                opt->output(opt, "\0", 1);
        else
-               output_color(opt, &sign, 1, opt->color_sep);
+               output_color(opt, &sign, 1, opt->colors[GREP_COLOR_SEP]);
 }
 
 static void show_name(struct grep_opt *opt, const char *name)
 {
-       output_color(opt, name, strlen(name), opt->color_filename);
+       output_color(opt, name, strlen(name), opt->colors[GREP_COLOR_FILENAME]);
        opt->output(opt, opt->null_following_name ? "\0" : "\n", 1);
 }
 
@@ -1416,19 +1413,19 @@ static void show_line_header(struct grep_opt *opt, const char *name,
                             unsigned lno, ssize_t cno, char sign)
 {
        if (opt->heading && opt->last_shown == 0) {
-               output_color(opt, name, strlen(name), opt->color_filename);
+               output_color(opt, name, strlen(name), opt->colors[GREP_COLOR_FILENAME]);
                opt->output(opt, "\n", 1);
        }
        opt->last_shown = lno;
 
        if (!opt->heading && opt->pathname) {
-               output_color(opt, name, strlen(name), opt->color_filename);
+               output_color(opt, name, strlen(name), opt->colors[GREP_COLOR_FILENAME]);
                output_sep(opt, sign);
        }
        if (opt->linenum) {
                char buf[32];
                xsnprintf(buf, sizeof(buf), "%d", lno);
-               output_color(opt, buf, strlen(buf), opt->color_lineno);
+               output_color(opt, buf, strlen(buf), opt->colors[GREP_COLOR_LINENO]);
                output_sep(opt, sign);
        }
        /*
@@ -1439,7 +1436,7 @@ static void show_line_header(struct grep_opt *opt, const char *name,
        if (opt->columnnum && cno) {
                char buf[32];
                xsnprintf(buf, sizeof(buf), "%"PRIuMAX, (uintmax_t)cno);
-               output_color(opt, buf, strlen(buf), opt->color_columnno);
+               output_color(opt, buf, strlen(buf), opt->colors[GREP_COLOR_COLUMNNO]);
                output_sep(opt, sign);
        }
 }
@@ -1457,11 +1454,11 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
        } else if (opt->pre_context || opt->post_context || opt->funcbody) {
                if (opt->last_shown == 0) {
                        if (opt->show_hunk_mark) {
-                               output_color(opt, "--", 2, opt->color_sep);
+                               output_color(opt, "--", 2, opt->colors[GREP_COLOR_SEP]);
                                opt->output(opt, "\n", 1);
                        }
                } else if (lno > opt->last_shown + 1) {
-                       output_color(opt, "--", 2, opt->color_sep);
+                       output_color(opt, "--", 2, opt->colors[GREP_COLOR_SEP]);
                        opt->output(opt, "\n", 1);
                }
        }
@@ -1480,15 +1477,15 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
 
                if (opt->color) {
                        if (sign == ':')
-                               match_color = opt->color_match_selected;
+                               match_color = opt->colors[GREP_COLOR_MATCH_SELECTED];
                        else
-                               match_color = opt->color_match_context;
+                               match_color = opt->colors[GREP_COLOR_MATCH_CONTEXT];
                        if (sign == ':')
-                               line_color = opt->color_selected;
+                               line_color = opt->colors[GREP_COLOR_SELECTED];
                        else if (sign == '-')
-                               line_color = opt->color_context;
+                               line_color = opt->colors[GREP_COLOR_CONTEXT];
                        else if (sign == '=')
-                               line_color = opt->color_function;
+                               line_color = opt->colors[GREP_COLOR_FUNCTION];
                }
                *eol = '\0';
                while (next_match(opt, bol, eol, ctx, &match, eflags)) {
@@ -1551,7 +1548,7 @@ static int match_funcname(struct grep_opt *opt, struct grep_source *gs, char *bo
 {
        xdemitconf_t *xecfg = opt->priv;
        if (xecfg && !xecfg->find_func) {
-               grep_source_load_driver(gs);
+               grep_source_load_driver(gs, opt->repo->index);
                if (gs->driver->funcname.pattern) {
                        const struct userdiff_funcname *pe = &gs->driver->funcname;
                        xdiff_set_find_func(xecfg, pe->pattern, pe->cflags);
@@ -1714,7 +1711,8 @@ static int look_ahead(struct grep_opt *opt,
        return 0;
 }
 
-static int fill_textconv_grep(struct userdiff_driver *driver,
+static int fill_textconv_grep(struct repository *r,
+                             struct userdiff_driver *driver,
                              struct grep_source *gs)
 {
        struct diff_filespec *df;
@@ -1747,7 +1745,7 @@ static int fill_textconv_grep(struct userdiff_driver *driver,
         * structure.
         */
        grep_read_lock();
-       size = fill_textconv(driver, df, &buf);
+       size = fill_textconv(r, driver, df, &buf);
        grep_read_unlock();
        free_filespec(df);
 
@@ -1807,7 +1805,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
        opt->last_shown = 0;
 
        if (opt->allow_textconv) {
-               grep_source_load_driver(gs);
+               grep_source_load_driver(gs, opt->repo->index);
                /*
                 * We might set up the shared textconv cache data here, which
                 * is not thread-safe.
@@ -1824,11 +1822,11 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
        if (!textconv) {
                switch (opt->binary) {
                case GREP_BINARY_DEFAULT:
-                       if (grep_source_is_binary(gs))
+                       if (grep_source_is_binary(gs, opt->repo->index))
                                binary_match_only = 1;
                        break;
                case GREP_BINARY_NOMATCH:
-                       if (grep_source_is_binary(gs))
+                       if (grep_source_is_binary(gs, opt->repo->index))
                                return 0; /* Assume unmatch */
                        break;
                case GREP_BINARY_TEXT:
@@ -1843,7 +1841,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
 
        try_lookahead = should_lookahead(opt);
 
-       if (fill_textconv_grep(textconv, gs) < 0)
+       if (fill_textconv_grep(opt->repo, textconv, gs) < 0)
                return 0;
 
        bol = gs->buf;
@@ -1906,7 +1904,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
                        if (binary_match_only) {
                                opt->output(opt, "Binary file ", 12);
                                output_color(opt, gs->name, strlen(gs->name),
-                                            opt->color_filename);
+                                            opt->colors[GREP_COLOR_FILENAME]);
                                opt->output(opt, " matches\n", 9);
                                return 1;
                        }
@@ -1991,7 +1989,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
                char buf[32];
                if (opt->pathname) {
                        output_color(opt, gs->name, strlen(gs->name),
-                                    opt->color_filename);
+                                    opt->colors[GREP_COLOR_FILENAME]);
                        output_sep(opt, ':');
                }
                xsnprintf(buf, sizeof(buf), "%u\n", count);
@@ -2174,22 +2172,24 @@ static int grep_source_load(struct grep_source *gs)
        BUG("invalid grep_source type to load");
 }
 
-void grep_source_load_driver(struct grep_source *gs)
+void grep_source_load_driver(struct grep_source *gs,
+                            struct index_state *istate)
 {
        if (gs->driver)
                return;
 
        grep_attr_lock();
        if (gs->path)
-               gs->driver = userdiff_find_by_path(gs->path);
+               gs->driver = userdiff_find_by_path(istate, gs->path);
        if (!gs->driver)
                gs->driver = userdiff_find_by_name("default");
        grep_attr_unlock();
 }
 
-static int grep_source_is_binary(struct grep_source *gs)
+static int grep_source_is_binary(struct grep_source *gs,
+                                struct index_state *istate)
 {
-       grep_source_load_driver(gs);
+       grep_source_load_driver(gs, istate);
        if (gs->driver->binary != -1)
                return gs->driver->binary;