]> git.ipfire.org Git - thirdparty/git.git/blobdiff - pretty.c
Merge branch 'en/ort-perf-batch-9'
[thirdparty/git.git] / pretty.c
index b4ff3f602f9b17068f74b79ad7611e806e0e6c01..e5b33ba034bd600b343ea146b0c38f992d1b462e 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -12,6 +12,7 @@
 #include "reflog-walk.h"
 #include "gpg-interface.h"
 #include "trailer.h"
+#include "run-command.h"
 
 static char *user_format;
 static struct cmt_fmt_map {
@@ -678,7 +679,7 @@ static int mailmap_name(const char **email, size_t *email_len,
 {
        static struct string_list *mail_map;
        if (!mail_map) {
-               mail_map = xcalloc(1, sizeof(*mail_map));
+               CALLOC_ARRAY(mail_map, 1);
                read_mailmap(mail_map);
        }
        return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
@@ -1149,6 +1150,91 @@ static int format_trailer_match_cb(const struct strbuf *key, void *ud)
        return 0;
 }
 
+int format_set_trailers_options(struct process_trailer_options *opts,
+                               struct string_list *filter_list,
+                               struct strbuf *sepbuf,
+                               struct strbuf *kvsepbuf,
+                               const char **arg,
+                               char **invalid_arg)
+{
+       for (;;) {
+               const char *argval;
+               size_t arglen;
+
+               if (**arg == ')')
+                       break;
+
+               if (match_placeholder_arg_value(*arg, "key", arg, &argval, &arglen)) {
+                       uintptr_t len = arglen;
+
+                       if (!argval)
+                               return -1;
+
+                       if (len && argval[len - 1] == ':')
+                               len--;
+                       string_list_append(filter_list, argval)->util = (char *)len;
+
+                       opts->filter = format_trailer_match_cb;
+                       opts->filter_data = filter_list;
+                       opts->only_trailers = 1;
+               } else if (match_placeholder_arg_value(*arg, "separator", arg, &argval, &arglen)) {
+                       char *fmt;
+
+                       strbuf_reset(sepbuf);
+                       fmt = xstrndup(argval, arglen);
+                       strbuf_expand(sepbuf, fmt, strbuf_expand_literal_cb, NULL);
+                       free(fmt);
+                       opts->separator = sepbuf;
+               } else if (match_placeholder_arg_value(*arg, "key_value_separator", arg, &argval, &arglen)) {
+                       char *fmt;
+
+                       strbuf_reset(kvsepbuf);
+                       fmt = xstrndup(argval, arglen);
+                       strbuf_expand(kvsepbuf, fmt, strbuf_expand_literal_cb, NULL);
+                       free(fmt);
+                       opts->key_value_separator = kvsepbuf;
+               } else if (!match_placeholder_bool_arg(*arg, "only", arg, &opts->only_trailers) &&
+                          !match_placeholder_bool_arg(*arg, "unfold", arg, &opts->unfold) &&
+                          !match_placeholder_bool_arg(*arg, "keyonly", arg, &opts->key_only) &&
+                          !match_placeholder_bool_arg(*arg, "valueonly", arg, &opts->value_only)) {
+                       if (invalid_arg) {
+                               size_t len = strcspn(*arg, ",)");
+                               *invalid_arg = xstrndup(*arg, len);
+                       }
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+static size_t parse_describe_args(const char *start, struct strvec *args)
+{
+       const char *options[] = { "match", "exclude" };
+       const char *arg = start;
+
+       for (;;) {
+               const char *matched = NULL;
+               const char *argval;
+               size_t arglen = 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];
+                               break;
+                       }
+               }
+               if (!matched)
+                       break;
+
+               if (!arglen)
+                       return 0;
+               strvec_pushf(args, "--%s=%.*s", matched, (int)arglen, argval);
+       }
+       return arg - start;
+}
+
 static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                                const char *placeholder,
                                void *context)
@@ -1214,6 +1300,41 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                return parse_padding_placeholder(placeholder, c);
        }
 
+       if (skip_prefix(placeholder, "(describe", &arg)) {
+               struct child_process cmd = CHILD_PROCESS_INIT;
+               struct strbuf out = STRBUF_INIT;
+               struct strbuf err = STRBUF_INIT;
+               struct pretty_print_describe_status *describe_status;
+
+               describe_status = c->pretty_ctx->describe_status;
+               if (describe_status) {
+                       if (!describe_status->max_invocations)
+                               return 0;
+                       describe_status->max_invocations--;
+               }
+
+               cmd.git_cmd = 1;
+               strvec_push(&cmd.args, "describe");
+
+               if (*arg == ':') {
+                       arg++;
+                       arg += parse_describe_args(arg, &cmd.args);
+               }
+
+               if (*arg != ')') {
+                       child_process_clear(&cmd);
+                       return 0;
+               }
+
+               strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
+               pipe_command(&cmd, NULL, 0, &out, 0, &err, 0);
+               strbuf_rtrim(&out);
+               strbuf_addbuf(sb, &out);
+               strbuf_release(&out);
+               strbuf_release(&err);
+               return arg - placeholder + 1;
+       }
+
        /* these depend on the commit */
        if (!commit->object.parsed)
                parse_object(the_repository, &commit->object.oid);
@@ -1429,45 +1550,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 
                if (*arg == ':') {
                        arg++;
-                       for (;;) {
-                               const char *argval;
-                               size_t arglen;
-
-                               if (match_placeholder_arg_value(arg, "key", &arg, &argval, &arglen)) {
-                                       uintptr_t len = arglen;
-
-                                       if (!argval)
-                                               goto trailer_out;
-
-                                       if (len && argval[len - 1] == ':')
-                                               len--;
-                                       string_list_append(&filter_list, argval)->util = (char *)len;
-
-                                       opts.filter = format_trailer_match_cb;
-                                       opts.filter_data = &filter_list;
-                                       opts.only_trailers = 1;
-                               } else if (match_placeholder_arg_value(arg, "separator", &arg, &argval, &arglen)) {
-                                       char *fmt;
-
-                                       strbuf_reset(&sepbuf);
-                                       fmt = xstrndup(argval, arglen);
-                                       strbuf_expand(&sepbuf, fmt, strbuf_expand_literal_cb, NULL);
-                                       free(fmt);
-                                       opts.separator = &sepbuf;
-                               } else if (match_placeholder_arg_value(arg, "key_value_separator", &arg, &argval, &arglen)) {
-                                       char *fmt;
-
-                                       strbuf_reset(&kvsepbuf);
-                                       fmt = xstrndup(argval, arglen);
-                                       strbuf_expand(&kvsepbuf, fmt, strbuf_expand_literal_cb, NULL);
-                                       free(fmt);
-                                       opts.key_value_separator = &kvsepbuf;
-                               } else if (!match_placeholder_bool_arg(arg, "only", &arg, &opts.only_trailers) &&
-                                          !match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold) &&
-                                          !match_placeholder_bool_arg(arg, "keyonly", &arg, &opts.key_only) &&
-                                          !match_placeholder_bool_arg(arg, "valueonly", &arg, &opts.value_only))
-                                       break;
-                       }
+                       if (format_set_trailers_options(&opts, &filter_list, &sepbuf, &kvsepbuf, &arg, NULL))
+                               goto trailer_out;
                }
                if (*arg == ')') {
                        format_trailers_from_commit(sb, msg + c->subject_off, &opts);