Merge branch 'jk/ref-filter-colors'
authorJunio C Hamano <gitster@pobox.com>
Fri, 11 Aug 2017 20:26:58 +0000 (13:26 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 11 Aug 2017 20:26:58 +0000 (13:26 -0700)
"%C(color name)" in the pretty print format always produced ANSI
color escape codes, which was an early design mistake. They now
honor the configuration (e.g. "color.ui = never") and also tty-ness
of the output medium.

* jk/ref-filter-colors:
ref-filter: consult want_color() before emitting colors
pretty: respect color settings for %C placeholders
rev-list: pass diffopt->use_colors through to pretty-print
for-each-ref: load config earlier
color: check color.ui in git_default_config()
ref-filter: pass ref_format struct to atom parsers
ref-filter: factor out the parsing of sorting atoms
ref-filter: make parse_ref_filter_atom a private function
ref-filter: provide a function for parsing sort options
ref-filter: move need_color_reset_at_eol into ref_format
ref-filter: abstract ref format into its own struct
ref-filter: simplify automatic color reset
t: use test_decode_color rather than literal ANSI codes
docs/for-each-ref: update pointer to color syntax
check return value of verify_ref_format()

1  2 
builtin/grep.c
builtin/show-branch.c
builtin/tag.c
builtin/verify-tag.c
config.c
t/test-lib-functions.sh
diff --combined builtin/grep.c
index b10062902373590e0ebba0fc960b640b418a07dc,a7157f56327c0a9b2d4cccbdb2ee47666902392d..3cbee04dc4164255148b7f4b0c6f8f6dcd86a8fe
@@@ -284,7 -284,7 +284,7 @@@ static int wait_all(void
  static int grep_cmd_config(const char *var, const char *value, void *cb)
  {
        int st = grep_config(var, value, cb);
-       if (git_color_default_config(var, value, cb) < 0)
+       if (git_default_config(var, value, cb) < 0)
                st = -1;
  
        if (!strcmp(var, "grep.threads")) {
@@@ -653,7 -653,7 +653,7 @@@ static int grep_submodule(struct grep_o
                 */
                if (oid) {
                        const struct submodule *sub =
 -                                      submodule_from_path(null_sha1, path);
 +                                      submodule_from_path(&null_oid, path);
                        if (sub)
                                path = git_path("modules/%s", sub->name);
  
@@@ -862,7 -862,7 +862,7 @@@ static int grep_objects(struct grep_op
                /* load the gitmodules file for this rev */
                if (recurse_submodules) {
                        submodule_free();
 -                      gitmodules_config_sha1(real_obj->oid.hash);
 +                      gitmodules_config_oid(&real_obj->oid);
                }
                if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path)) {
                        hit = 1;
@@@ -1170,6 -1170,8 +1170,6 @@@ int cmd_grep(int argc, const char **arg
  
        if (!opt.pattern_list)
                die(_("no pattern given."));
 -      if (!opt.fixed && opt.ignore_case)
 -              opt.regflags |= REG_ICASE;
  
        /*
         * We have to find "--" in a separate pass, because its presence
                        break;
                }
  
 -              if (get_sha1_with_context(arg, GET_SHA1_RECORD_PATH,
 -                                        oid.hash, &oc)) {
 +              if (get_oid_with_context(arg, GET_OID_RECORD_PATH,
 +                                       &oid, &oc)) {
                        if (seen_dashdash)
                                die(_("unable to resolve revision: %s"), arg);
                        break;
diff --combined builtin/show-branch.c
index 6fa1f62a88ac2704abc6f274ed7a6170bd3a2f4c,28f245c8cccbc20c96a189516e9df77d238c7e96..84547d6fba07cb7770d94e80cda170c391d04a21
@@@ -393,7 -393,7 +393,7 @@@ static int append_head_ref(const char *
        /* If both heads/foo and tags/foo exists, get_sha1 would
         * get confused.
         */
 -      if (get_sha1(refname + ofs, tmp.hash) || oidcmp(&tmp, oid))
 +      if (get_oid(refname + ofs, &tmp) || oidcmp(&tmp, oid))
                ofs = 5;
        return append_ref(refname + ofs, oid, 0);
  }
@@@ -408,7 -408,7 +408,7 @@@ static int append_remote_ref(const cha
        /* If both heads/foo and tags/foo exists, get_sha1 would
         * get confused.
         */
 -      if (get_sha1(refname + ofs, tmp.hash) || oidcmp(&tmp, oid))
 +      if (get_oid(refname + ofs, &tmp) || oidcmp(&tmp, oid))
                ofs = 5;
        return append_ref(refname + ofs, oid, 0);
  }
@@@ -514,7 -514,7 +514,7 @@@ static int show_independent(struct comm
  static void append_one_rev(const char *av)
  {
        struct object_id revkey;
 -      if (!get_sha1(av, revkey.hash)) {
 +      if (!get_oid(av, &revkey)) {
                append_ref(av, &revkey, 0);
                return;
        }
@@@ -554,7 -554,7 +554,7 @@@ static int git_show_branch_config(cons
                return 0;
        }
  
-       return git_color_default_config(var, value, cb);
+       return git_default_config(var, value, cb);
  }
  
  static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
@@@ -808,7 -808,7 +808,7 @@@ int cmd_show_branch(int ac, const char 
                        die(Q_("cannot handle more than %d rev.",
                               "cannot handle more than %d revs.",
                               MAX_REVS), MAX_REVS);
 -              if (get_sha1(ref_name[num_rev], revkey.hash))
 +              if (get_oid(ref_name[num_rev], &revkey))
                        die(_("'%s' is not a valid ref."), ref_name[num_rev]);
                commit = lookup_commit_reference(&revkey);
                if (!commit)
diff --combined builtin/tag.c
index b25bf8daa289d75af023fd5f14034eccdb2a9d37,66e35b823b6e0a3e732fb84e402dd0af6830a471..e8a30e6110f9782d72a4fd2592bd82af9842ef19
@@@ -32,7 -32,8 +32,8 @@@ static const char * const git_tag_usage
  static unsigned int colopts;
  static int force_sign_annotate;
  
- static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, const char *format)
+ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
+                    struct ref_format *format)
  {
        struct ref_array array;
        char *to_free = NULL;
        if (filter->lines == -1)
                filter->lines = 0;
  
-       if (!format) {
+       if (!format->format) {
                if (filter->lines) {
                        to_free = xstrfmt("%s %%(contents:lines=%d)",
                                          "%(align:15)%(refname:lstrip=2)%(end)",
                                          filter->lines);
-                       format = to_free;
+                       format->format = to_free;
                } else
-                       format = "%(refname:lstrip=2)";
+                       format->format = "%(refname:lstrip=2)";
        }
  
-       verify_ref_format(format);
+       if (verify_ref_format(format))
+               die(_("unable to parse format string"));
        filter->with_commit_tag_algo = 1;
        filter_refs(&array, filter, FILTER_REFS_TAGS);
        ref_array_sort(sorting, &array);
  
        for (i = 0; i < array.nr; i++)
-               show_ref_array_item(array.items[i], format, 0);
+               show_ref_array_item(array.items[i], format);
        ref_array_clear(&array);
        free(to_free);
  
@@@ -105,17 -107,17 +107,17 @@@ static int verify_tag(const char *name
                      const struct object_id *oid, const void *cb_data)
  {
        int flags;
-       const char *fmt_pretty = cb_data;
+       const struct ref_format *format = cb_data;
        flags = GPG_VERIFY_VERBOSE;
  
-       if (fmt_pretty)
+       if (format->format)
                flags = GPG_VERIFY_OMIT_STATUS;
  
 -      if (gpg_verify_tag(oid->hash, name, flags))
 +      if (gpg_verify_tag(oid, name, flags))
                return -1;
  
-       if (fmt_pretty)
-               pretty_print_ref(name, oid->hash, fmt_pretty);
+       if (format->format)
+               pretty_print_ref(name, oid->hash, format);
  
        return 0;
  }
@@@ -134,30 -136,6 +136,6 @@@ static const char tag_template_nocleanu
        "Lines starting with '%c' will be kept; you may remove them"
        " yourself if you want to.\n");
  
- /* Parse arg given and add it the ref_sorting array */
- static int parse_sorting_string(const char *arg, struct ref_sorting **sorting_tail)
- {
-       struct ref_sorting *s;
-       int len;
-       s = xcalloc(1, sizeof(*s));
-       s->next = *sorting_tail;
-       *sorting_tail = s;
-       if (*arg == '-') {
-               s->reverse = 1;
-               arg++;
-       }
-       if (skip_prefix(arg, "version:", &arg) ||
-           skip_prefix(arg, "v:", &arg))
-               s->version = 1;
-       len = strlen(arg);
-       s->atom = parse_ref_filter_atom(arg, arg+len);
-       return 0;
- }
  static int git_tag_config(const char *var, const char *value, void *cb)
  {
        int status;
        if (!strcmp(var, "tag.sort")) {
                if (!value)
                        return config_error_nonbool(var);
-               parse_sorting_string(value, sorting_tail);
+               parse_ref_sorting(sorting_tail, value);
                return 0;
        }
  
@@@ -392,7 -370,7 +370,7 @@@ int cmd_tag(int argc, const char **argv
        struct strbuf err = STRBUF_INIT;
        struct ref_filter filter;
        static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
-       const char *format = NULL;
+       struct ref_format format = REF_FORMAT_INIT;
        int icase = 0;
        struct option options[] = {
                OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'),
                        N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
                        parse_opt_object_name, (intptr_t) "HEAD"
                },
-               OPT_STRING(  0 , "format", &format, N_("format"), N_("format to use for the output")),
+               OPT_STRING(  0 , "format", &format.format, N_("format"),
+                          N_("format to use for the output")),
                OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
                OPT_END()
        };
                        run_column_filter(colopts, &copts);
                }
                filter.name_patterns = argv;
-               ret = list_tags(&filter, sorting, format);
+               ret = list_tags(&filter, sorting, &format);
                if (column_active(colopts))
                        stop_column_filter();
                return ret;
        if (cmdmode == 'd')
                return for_each_tag_name(argv, delete_tag, NULL);
        if (cmdmode == 'v') {
-               if (format)
-                       verify_ref_format(format);
-               return for_each_tag_name(argv, verify_tag, format);
+               if (format.format && verify_ref_format(&format))
+                       usage_with_options(git_tag_usage, options);
+               return for_each_tag_name(argv, verify_tag, &format);
        }
  
        if (msg.given || msgfile) {
diff --combined builtin/verify-tag.c
index ed8329340f73482c18b295a2733fcb11c4198859,87d73e856a13e4abaa67ee8cad3e520f1bd9f779..ad7b79fa5cd718daf3be5f1a46a1fbb2bed41ad5
@@@ -32,11 -32,11 +32,11 @@@ int cmd_verify_tag(int argc, const cha
  {
        int i = 1, verbose = 0, had_error = 0;
        unsigned flags = 0;
-       char *fmt_pretty = NULL;
+       struct ref_format format = REF_FORMAT_INIT;
        const struct option verify_tag_options[] = {
                OPT__VERBOSE(&verbose, N_("print tag contents")),
                OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW),
-               OPT_STRING(  0 , "format", &fmt_pretty, N_("format"), N_("format to use for the output")),
+               OPT_STRING(0, "format", &format.format, N_("format"), N_("format to use for the output")),
                OPT_END()
        };
  
        if (verbose)
                flags |= GPG_VERIFY_VERBOSE;
  
-       if (fmt_pretty) {
-               verify_ref_format(fmt_pretty);
+       if (format.format) {
+               if (verify_ref_format(&format))
+                       usage_with_options(verify_tag_usage,
+                                          verify_tag_options);
                flags |= GPG_VERIFY_OMIT_STATUS;
        }
  
        while (i < argc) {
 -              unsigned char sha1[20];
 +              struct object_id oid;
                const char *name = argv[i++];
 -              if (get_sha1(name, sha1)) {
 +
 +              if (get_oid(name, &oid)) {
                        had_error = !!error("tag '%s' not found.", name);
                        continue;
                }
  
 -              if (gpg_verify_tag(sha1, name, flags)) {
 +              if (gpg_verify_tag(&oid, name, flags)) {
                        had_error = 1;
                        continue;
                }
  
-               if (fmt_pretty)
-                       pretty_print_ref(name, oid.hash, fmt_pretty);
+               if (format.format)
 -                      pretty_print_ref(name, sha1, &format);
++                      pretty_print_ref(name, oid.hash, &format);
        }
        return had_error;
  }
diff --combined config.c
index a1b66fe764e66e5c57bb984dd1514c01022cae22,bc290e7563dc5be4c70a5660358e03da180351e9..e04500d13ba256e1c2a1a15e1b71718d0298900a
+++ b/config.c
@@@ -16,6 -16,7 +16,7 @@@
  #include "string-list.h"
  #include "utf8.h"
  #include "dir.h"
+ #include "color.h"
  
  struct config_source {
        struct config_source *prev;
@@@ -1350,6 -1351,9 +1351,9 @@@ int git_default_config(const char *var
        if (starts_with(var, "advice."))
                return git_default_advice_config(var, value);
  
+       if (git_color_config(var, value, dummy) < 0)
+               return -1;
        if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
                pager_use_color = git_config_bool(var,value);
                return 0;
@@@ -1460,9 -1464,9 +1464,9 @@@ int git_config_from_mem(config_fn_t fn
        return do_config_from(&top, fn, data);
  }
  
 -int git_config_from_blob_sha1(config_fn_t fn,
 +int git_config_from_blob_oid(config_fn_t fn,
                              const char *name,
 -                            const unsigned char *sha1,
 +                            const struct object_id *oid,
                              void *data)
  {
        enum object_type type;
        unsigned long size;
        int ret;
  
 -      buf = read_sha1_file(sha1, &type, &size);
 +      buf = read_sha1_file(oid->hash, &type, &size);
        if (!buf)
                return error("unable to load config blob object '%s'", name);
        if (type != OBJ_BLOB) {
@@@ -1488,11 -1492,11 +1492,11 @@@ static int git_config_from_blob_ref(con
                                    const char *name,
                                    void *data)
  {
 -      unsigned char sha1[20];
 +      struct object_id oid;
  
 -      if (get_sha1(name, sha1) < 0)
 +      if (get_oid(name, &oid) < 0)
                return error("unable to resolve config blob '%s'", name);
 -      return git_config_from_blob_sha1(fn, name, sha1, data);
 +      return git_config_from_blob_oid(fn, name, &oid, data);
  }
  
  const char *git_etc_gitconfig(void)
@@@ -1714,18 -1718,15 +1718,18 @@@ static int configset_add_value(struct c
        return 0;
  }
  
 -static int config_set_element_cmp(const struct config_set_element *e1,
 -                               const struct config_set_element *e2, const void *unused)
 +static int config_set_element_cmp(const void *unused_cmp_data,
 +                                const struct config_set_element *e1,
 +                                const struct config_set_element *e2,
 +                                const void *unused_keydata)
  {
        return strcmp(e1->key, e2->key);
  }
  
  void git_configset_init(struct config_set *cs)
  {
 -      hashmap_init(&cs->config_hash, (hashmap_cmp_fn)config_set_element_cmp, 0);
 +      hashmap_init(&cs->config_hash, (hashmap_cmp_fn)config_set_element_cmp,
 +                   NULL, 0);
        cs->hash_initialized = 1;
        cs->list.nr = 0;
        cs->list.alloc = 0;
diff --combined t/test-lib-functions.sh
index 50a9a1d1c49e719d0ee65435b05171747e065259,e09e93b38f869b1d2238b927966125b8c2daab6d..1701fe2a06057530d845b91b4fd4cce99b4521a2
@@@ -42,6 -42,7 +42,7 @@@ test_decode_color () 
                function name(n) {
                        if (n == 0) return "RESET";
                        if (n == 1) return "BOLD";
+                       if (n == 7) return "REVERSE";
                        if (n == 30) return "BLACK";
                        if (n == 31) return "RED";
                        if (n == 32) return "GREEN";
@@@ -999,7 -1000,6 +1000,7 @@@ test_copy_bytes () 
                        my $s;
                        my $nread = sysread(STDIN, $s, $len);
                        die "cannot read: $!" unless defined($nread);
 +                      last unless $nread;
                        print $s;
                        $len -= $nread;
                }