]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'es/pretty-describe-more'
authorJunio C Hamano <gitster@pobox.com>
Wed, 15 Dec 2021 17:39:48 +0000 (09:39 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 15 Dec 2021 17:39:48 +0000 (09:39 -0800)
Extend "git log --format=%(describe)" placeholder to allow passing
selected command-line options to the underlying "git describe"
command.

* es/pretty-describe-more:
  pretty: add abbrev option to %(describe)
  pretty: add tag option to %(describe)
  pretty.c: rework describe options parsing for better extensibility

1  2 
Documentation/pretty-formats.txt
pretty.c

index 23f63358871ad3732f8c4716678318237bc94870,9e943fb74bb5cf15a5c85f3486e279ee17d13067..0b4c1c8d98a4acf01c19722941095da2c2c6525d
@@@ -20,7 -20,7 +20,7 @@@ built-in formats
  
  * 'oneline'
  
 -        <hash> <title line>
 +        <hash> <title-line>
  +
  This is designed to be as compact as possible.
  
          commit <hash>
          Author: <author>
  
 -            <title line>
 +            <title-line>
  
  * 'medium'
  
          commit <hash>
          Author: <author>
 -        Date:   <author date>
 +        Date:   <author-date>
  
 -            <title line>
 +            <title-line>
  
 -            <full commit message>
 +            <full-commit-message>
  
  * 'full'
  
          Author: <author>
          Commit: <committer>
  
 -            <title line>
 +            <title-line>
  
 -            <full commit message>
 +            <full-commit-message>
  
  * 'fuller'
  
          commit <hash>
          Author:     <author>
 -        AuthorDate: <author date>
 +        AuthorDate: <author-date>
          Commit:     <committer>
 -        CommitDate: <committer date>
 +        CommitDate: <committer-date>
  
 -             <title line>
 +             <title-line>
  
 -             <full commit message>
 +             <full-commit-message>
  
  * 'reference'
  
 -        <abbrev hash> (<title line>, <short author date>)
 +        <abbrev-hash> (<title-line>, <short-author-date>)
  +
  This format is used to refer to another commit in a commit message and
  is the same as `--pretty='format:%C(auto)%h (%s, %ad)'`.  By default,
@@@ -78,10 -78,10 +78,10 @@@ placeholders, its output is not affecte
  
          From <hash> <date>
          From: <author>
 -        Date: <author date>
 -        Subject: [PATCH] <title line>
 +        Date: <author-date>
 +        Subject: [PATCH] <title-line>
  
 -        <full commit message>
 +        <full-commit-message>
  
  * 'mboxrd'
  +
@@@ -101,9 -101,9 +101,9 @@@ commits are displayed, but not the way 
  `git log --raw`. To get full object names in a raw diff format,
  use `--no-abbrev`.
  
 -* 'format:<string>'
 +* 'format:<format-string>'
  +
 -The 'format:<string>' format allows you to specify which information
 +The 'format:<format-string>' format allows you to specify which information
  you want to show. It works a little bit like printf format,
  with the notable exception that you get a newline with '%n'
  instead of '\n'.
@@@ -220,6 -220,12 +220,12 @@@ The placeholders are
                          inconsistent when tags are added or removed at
                          the same time.
  +
 -** 'tags[=<bool>]': Instead of only considering annotated tags,
++** 'tags[=<bool-value>]': Instead of only considering annotated tags,
+    consider lightweight tags as well.
+ ** 'abbrev=<number>': Instead of using the default number of hexadecimal digits
+    (which will vary according to the number of objects in the repository with a
+    default of 7) of the abbreviated object name, use <number> digits, or as many
+    digits as needed to form a unique object name.
  ** 'match=<pattern>': Only consider tags matching the given
     `glob(7)` pattern, excluding the "refs/tags/" prefix.
  ** 'exclude=<pattern>': Do not consider tags matching the given
@@@ -273,12 -279,7 +279,7 @@@ endif::git-rev-list[
                          If any option is provided multiple times the
                          last occurrence wins.
  +
- The boolean options accept an optional value `[=<value>]`. The values
- `true`, `false`, `on`, `off` etc. are all accepted. See the "boolean"
- sub-section in "EXAMPLES" in linkgit:git-config[1]. If a boolean
- option is given with no value, it's enabled.
- +
 -** 'key=<K>': only show trailers with specified key. Matching is done
 +** 'key=<key>': only show trailers with specified <key>. Matching is done
     case-insensitively and trailing colon is optional. If option is
     given multiple times trailer lines matching any of the keys are
     shown. This option automatically enables the `only` option so that
     desired it can be disabled with `only=false`.  E.g.,
     `%(trailers:key=Reviewed-by)` shows trailer lines with key
     `Reviewed-by`.
 -** 'only[=<BOOL>]': select whether non-trailer lines from the trailer
 +** 'only[=<bool>]': select whether non-trailer lines from the trailer
     block should be included.
 -** 'separator=<SEP>': specify a separator inserted between trailer
 +** 'separator=<sep>': specify a separator inserted between trailer
     lines. When this option is not given each trailer line is
 -   terminated with a line feed character. The string SEP may contain
 +   terminated with a line feed character. The string <sep> may contain
     the literal formatting codes described above. To use comma as
     separator one must use `%x2C` as it would otherwise be parsed as
     next option. E.g., `%(trailers:key=Ticket,separator=%x2C )`
     shows all trailer lines whose key is "Ticket" separated by a comma
     and a space.
 -** 'unfold[=<BOOL>]': make it behave as if interpret-trailer's `--unfold`
 +** 'unfold[=<bool>]': make it behave as if interpret-trailer's `--unfold`
     option was given. E.g.,
     `%(trailers:only,unfold=true)` unfolds and shows all trailer lines.
 -** 'keyonly[=<BOOL>]': only show the key part of the trailer.
 -** 'valueonly[=<BOOL>]': only show the value part of the trailer.
 -** 'key_value_separator=<SEP>': specify a separator inserted between
 +** 'keyonly[=<bool>]': only show the key part of the trailer.
 +** 'valueonly[=<bool>]': only show the value part of the trailer.
 +** 'key_value_separator=<sep>': specify a separator inserted between
     trailer lines. When this option is not given each trailer key-value
     pair is separated by ": ". Otherwise it shares the same semantics
 -   as 'separator=<SEP>' above.
 +   as 'separator=<sep>' above.
  
  NOTE: Some placeholders may depend on other options given to the
  revision traversal engine. For example, the `%g*` reflog options will
@@@ -313,6 -314,11 +314,11 @@@ insert an empty string unless we are tr
  decoration format if `--decorate` was not already provided on the command
  line.
  
 -The boolean options accept an optional value `[=<bool>]`. The values
++The boolean options accept an optional value `[=<bool-value>]`. The values
+ `true`, `false`, `on`, `off` etc. are all accepted. See the "boolean"
+ sub-section in "EXAMPLES" in linkgit:git-config[1]. If a boolean
+ option is given with no value, it's enabled.
  If you add a `+` (plus sign) after '%' of a placeholder, a line-feed
  is inserted immediately before the expansion if and only if the
  placeholder expands to a non-empty string.
diff --combined pretty.c
index 1af5b093ae8a91ec8906b0ebac9f505d7df4b075,d5a34eff9138170d925cad3a47affd7aacf18496..ee6114e3f0aa1dcf8737794bbe8dc8f6e23f5f7b
+++ b/pretty.c
@@@ -431,52 -431,6 +431,52 @@@ const char *show_ident_date(const struc
        return show_date(date, tz, mode);
  }
  
 +static inline void strbuf_add_with_color(struct strbuf *sb, const char *color,
 +                                       const char *buf, size_t buflen)
 +{
 +      strbuf_addstr(sb, color);
 +      strbuf_add(sb, buf, buflen);
 +      if (*color)
 +              strbuf_addstr(sb, GIT_COLOR_RESET);
 +}
 +
 +static void append_line_with_color(struct strbuf *sb, struct grep_opt *opt,
 +                                 const char *line, size_t linelen,
 +                                 int color, enum grep_context ctx,
 +                                 enum grep_header_field field)
 +{
 +      const char *buf, *eol, *line_color, *match_color;
 +      regmatch_t match;
 +      int eflags = 0;
 +
 +      buf = line;
 +      eol = buf + linelen;
 +
 +      if (!opt || !want_color(color) || opt->invert)
 +              goto end;
 +
 +      line_color = opt->colors[GREP_COLOR_SELECTED];
 +      match_color = opt->colors[GREP_COLOR_MATCH_SELECTED];
 +
 +      while (grep_next_match(opt, buf, eol, ctx, &match, field, eflags)) {
 +              if (match.rm_so == match.rm_eo)
 +                      break;
 +
 +              strbuf_add_with_color(sb, line_color, buf, match.rm_so);
 +              strbuf_add_with_color(sb, match_color, buf + match.rm_so,
 +                                    match.rm_eo - match.rm_so);
 +              buf += match.rm_eo;
 +              eflags = REG_NOTBOL;
 +      }
 +
 +      if (eflags)
 +              strbuf_add_with_color(sb, line_color, buf, eol - buf);
 +      else {
 +end:
 +              strbuf_add(sb, buf, eol - buf);
 +      }
 +}
 +
  void pp_user_info(struct pretty_print_context *pp,
                  const char *what, struct strbuf *sb,
                  const char *line, const char *encoding)
                        strbuf_addch(sb, '\n');
                strbuf_addf(sb, " <%.*s>\n", (int)maillen, mailbuf);
        } else {
 -              strbuf_addf(sb, "%s: %.*s%.*s <%.*s>\n", what,
 -                          (pp->fmt == CMIT_FMT_FULLER) ? 4 : 0, "    ",
 -                          (int)namelen, namebuf, (int)maillen, mailbuf);
 +              struct strbuf id = STRBUF_INIT;
 +              enum grep_header_field field = GREP_HEADER_FIELD_MAX;
 +              struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
 +
 +              if (!strcmp(what, "Author"))
 +                      field = GREP_HEADER_AUTHOR;
 +              else if (!strcmp(what, "Commit"))
 +                      field = GREP_HEADER_COMMITTER;
 +
 +              strbuf_addf(sb, "%s: ", what);
 +              if (pp->fmt == CMIT_FMT_FULLER)
 +                      strbuf_addchars(sb, ' ', 4);
 +
 +              strbuf_addf(&id, "%.*s <%.*s>", (int)namelen, namebuf,
 +                          (int)maillen, mailbuf);
 +
 +              append_line_with_color(sb, opt, id.buf, id.len, pp->color,
 +                                     GREP_CONTEXT_HEAD, field);
 +              strbuf_addch(sb, '\n');
 +              strbuf_release(&id);
        }
  
        switch (pp->fmt) {
@@@ -734,7 -671,11 +734,7 @@@ const char *repo_logmsg_reencode(struc
         * If the re-encoding failed, out might be NULL here; in that
         * case we just return the commit message verbatim.
         */
 -      if (!out) {
 -              warning("unable to reencode commit to '%s'", output_encoding);
 -              return msg;
 -      }
 -      return out;
 +      return out ? out : msg;
  }
  
  static int mailmap_name(const char **email, size_t *email_len,
@@@ -1275,28 -1216,66 +1275,66 @@@ int format_set_trailers_options(struct 
  
  static size_t parse_describe_args(const char *start, struct strvec *args)
  {
-       const char *options[] = { "match", "exclude" };
+       struct {
+               char *name;
+               enum {
+                       DESCRIBE_ARG_BOOL,
+                       DESCRIBE_ARG_INTEGER,
+                       DESCRIBE_ARG_STRING,
+               } type;
+       }  option[] = {
+               { "tags", DESCRIBE_ARG_BOOL},
+               { "abbrev", DESCRIBE_ARG_INTEGER },
+               { "exclude", DESCRIBE_ARG_STRING },
+               { "match", DESCRIBE_ARG_STRING },
+       };
        const char *arg = start;
  
        for (;;) {
-               const char *matched = NULL;
+               int found = 0;
                const char *argval;
                size_t arglen = 0;
+               int optval = 0;
                int i;
  
-               for (i = 0; i < ARRAY_SIZE(options); i++) {
-                       if (match_placeholder_arg_value(arg, options[i], &arg,
-                                                       &argval, &arglen)) {
-                               matched = options[i];
+               for (i = 0; !found && i < ARRAY_SIZE(option); i++) {
+                       switch (option[i].type) {
+                       case DESCRIBE_ARG_BOOL:
+                               if (match_placeholder_bool_arg(arg, option[i].name, &arg, &optval)) {
+                                       if (optval)
+                                               strvec_pushf(args, "--%s", option[i].name);
+                                       else
+                                               strvec_pushf(args, "--no-%s", option[i].name);
+                                       found = 1;
+                               }
+                               break;
+                       case DESCRIBE_ARG_INTEGER:
+                               if (match_placeholder_arg_value(arg, option[i].name, &arg,
+                                                               &argval, &arglen)) {
+                                       char *endptr;
+                                       if (!arglen)
+                                               return 0;
+                                       strtol(argval, &endptr, 10);
+                                       if (endptr - argval != arglen)
+                                               return 0;
+                                       strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
+                                       found = 1;
+                               }
+                               break;
+                       case DESCRIBE_ARG_STRING:
+                               if (match_placeholder_arg_value(arg, option[i].name, &arg,
+                                                               &argval, &arglen)) {
+                                       if (!arglen)
+                                               return 0;
+                                       strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
+                                       found = 1;
+                               }
                                break;
                        }
                }
-               if (!matched)
+               if (!found)
                        break;
  
-               if (!arglen)
-                       return 0;
-               strvec_pushf(args, "--%s=%.*s", matched, (int)arglen, argval);
        }
        return arg - start;
  }
@@@ -1495,8 -1474,8 +1533,8 @@@ static size_t format_commit_one(struct 
                        check_commit_signature(c->commit, &(c->signature_check));
                switch (placeholder[1]) {
                case 'G':
 -                      if (c->signature_check.gpg_output)
 -                              strbuf_addstr(sb, c->signature_check.gpg_output);
 +                      if (c->signature_check.output)
 +                              strbuf_addstr(sb, c->signature_check.output);
                        break;
                case '?':
                        switch (c->signature_check.result) {
@@@ -1998,9 -1977,8 +2036,9 @@@ static int pp_utf8_width(const char *st
        return width;
  }
  
 -static void strbuf_add_tabexpand(struct strbuf *sb, int tabwidth,
 -                               const char *line, int linelen)
 +static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt,
 +                               int color, int tabwidth, const char *line,
 +                               int linelen)
  {
        const char *tab;
  
                        break;
  
                /* Output the data .. */
 -              strbuf_add(sb, line, tab - line);
 +              append_line_with_color(sb, opt, line, tab - line, color,
 +                                     GREP_CONTEXT_BODY,
 +                                     GREP_HEADER_FIELD_MAX);
  
                /* .. and the de-tabified tab */
                strbuf_addchars(sb, ' ', tabwidth - (width % tabwidth));
         * worrying about width - there's nothing more to
         * align.
         */
 -      strbuf_add(sb, line, linelen);
 +      append_line_with_color(sb, opt, line, linelen, color, GREP_CONTEXT_BODY,
 +                             GREP_HEADER_FIELD_MAX);
  }
  
  /*
@@@ -2047,16 -2022,11 +2085,16 @@@ static void pp_handle_indent(struct pre
                             struct strbuf *sb, int indent,
                             const char *line, int linelen)
  {
 +      struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
 +
        strbuf_addchars(sb, ' ', indent);
        if (pp->expand_tabs_in_log)
 -              strbuf_add_tabexpand(sb, pp->expand_tabs_in_log, line, linelen);
 +              strbuf_add_tabexpand(sb, opt, pp->color, pp->expand_tabs_in_log,
 +                                   line, linelen);
        else
 -              strbuf_add(sb, line, linelen);
 +              append_line_with_color(sb, opt, line, linelen, pp->color,
 +                                     GREP_CONTEXT_BODY,
 +                                     GREP_HEADER_FIELD_MAX);
  }
  
  static int is_mboxrd_from(const char *line, int len)
@@@ -2074,9 -2044,7 +2112,9 @@@ void pp_remainder(struct pretty_print_c
                  struct strbuf *sb,
                  int indent)
  {
 +      struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
        int first = 1;
 +
        for (;;) {
                const char *line = *msg_p;
                int linelen = get_one_line(line);
                if (indent)
                        pp_handle_indent(pp, sb, indent, line, linelen);
                else if (pp->expand_tabs_in_log)
 -                      strbuf_add_tabexpand(sb, pp->expand_tabs_in_log,
 -                                           line, linelen);
 +                      strbuf_add_tabexpand(sb, opt, pp->color,
 +                                           pp->expand_tabs_in_log, line,
 +                                           linelen);
                else {
                        if (pp->fmt == CMIT_FMT_MBOXRD &&
                                        is_mboxrd_from(line, linelen))
                                strbuf_addch(sb, '>');
  
 -                      strbuf_add(sb, line, linelen);
 +                      append_line_with_color(sb, opt, line, linelen,
 +                                             pp->color, GREP_CONTEXT_BODY,
 +                                             GREP_HEADER_FIELD_MAX);
                }
                strbuf_addch(sb, '\n');
        }