]> git.ipfire.org Git - thirdparty/git.git/blobdiff - pretty.c
Sync with Git 2.30.7
[thirdparty/git.git] / pretty.c
index e2285572c49b8eb9dcf219d95dc43da1f3f2e5fa..ae0f696d8ec2f4ea3d75df51d2fab8e7b3d83849 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -685,8 +685,8 @@ 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));
-               read_mailmap(mail_map, NULL);
+               CALLOC_ARRAY(mail_map, 1);
+               read_mailmap(mail_map);
        }
        return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
 }
@@ -790,6 +790,7 @@ enum trunc_type {
 };
 
 struct format_commit_context {
+       struct repository *repository;
        const struct commit *commit;
        const struct pretty_print_context *pretty_ctx;
        unsigned commit_header_parsed:1;
@@ -1166,6 +1167,63 @@ 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 format_commit_one(struct strbuf *sb, /* in UTF-8 */
                                const char *placeholder,
                                void *context)
@@ -1401,10 +1459,13 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                return 2;
        }
 
-
        /* For the rest we have to parse the commit header. */
-       if (!c->commit_header_parsed)
+       if (!c->commit_header_parsed) {
+               msg = c->message =
+                       repo_logmsg_reencode(c->repository, commit,
+                                            &c->commit_encoding, "UTF-8");
                parse_commit_header(c);
+       }
 
        switch (placeholder[0]) {
        case 'a':       /* author ... */
@@ -1446,42 +1507,15 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
                struct string_list filter_list = STRING_LIST_INIT_NODUP;
                struct strbuf sepbuf = STRBUF_INIT;
+               struct strbuf kvsepbuf = STRBUF_INIT;
                size_t ret = 0;
 
                opts.no_divider = 1;
 
                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_bool_arg(arg, "only", &arg, &opts.only_trailers) &&
-                                          !match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold) &&
-                                          !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);
@@ -1698,6 +1732,7 @@ void repo_format_commit_message(struct repository *r,
                                const struct pretty_print_context *pretty_ctx)
 {
        struct format_commit_context context = {
+               .repository = r,
                .commit = commit,
                .pretty_ctx = pretty_ctx,
                .wrap_start = sb->len
@@ -1705,18 +1740,14 @@ void repo_format_commit_message(struct repository *r,
        const char *output_enc = pretty_ctx->output_encoding;
        const char *utf8 = "UTF-8";
 
-       /*
-        * convert a commit message to UTF-8 first
-        * as far as 'format_commit_item' assumes it in UTF-8
-        */
-       context.message = repo_logmsg_reencode(r, commit,
-                                              &context.commit_encoding,
-                                              utf8);
-
        strbuf_expand(sb, format, format_commit_item, &context);
        rewrap_message_tail(sb, &context, 0, 0, 0);
 
-       /* then convert a commit message to an actual output encoding */
+       /*
+        * Convert output to an actual output encoding; note that
+        * format_commit_item() will always use UTF-8, so we don't
+        * have to bother if that's what the output wants.
+        */
        if (output_enc) {
                if (same_encoding(utf8, output_enc))
                        output_enc = NULL;