]> git.ipfire.org Git - thirdparty/git.git/blobdiff - builtin/shortlog.c
post-cocci: adjust comments for recent repo_* migration
[thirdparty/git.git] / builtin / shortlog.c
index 26c5c0cf93545777301c27f02279450347425fde..f287a6acd0325468d0178acbcc97641f7a079957 100644 (file)
@@ -81,8 +81,10 @@ static void insert_one_record(struct shortlog *log,
                format_subject(&subject, oneline, " ");
                buffer = strbuf_detach(&subject, NULL);
 
-               if (item->util == NULL)
-                       item->util = xcalloc(1, sizeof(struct string_list));
+               if (!item->util) {
+                       item->util = xmalloc(sizeof(struct string_list));
+                       string_list_init_nodup(item->util);
+               }
                string_list_append(item->util, buffer);
        }
 }
@@ -130,7 +132,9 @@ static void read_from_stdin(struct shortlog *log)
                match = committer_match;
                break;
        case SHORTLOG_GROUP_TRAILER:
-               die(_("using --group=trailer with stdin is not supported"));
+               die(_("using %s with stdin is not supported"), "--group=trailer");
+       case SHORTLOG_GROUP_FORMAT:
+               die(_("using %s with stdin is not supported"), "--group=format");
        default:
                BUG("unhandled shortlog group");
        }
@@ -168,11 +172,15 @@ static void insert_records_from_trailers(struct shortlog *log,
        const char *commit_buffer, *body;
        struct strbuf ident = STRBUF_INIT;
 
+       if (!log->trailers.nr)
+               return;
+
        /*
-        * Using format_commit_message("%B") would be simpler here, but
+        * Using repo_format_commit_message("%B") would be simpler here, but
         * this saves us copying the message.
         */
-       commit_buffer = logmsg_reencode(commit, NULL, ctx->output_encoding);
+       commit_buffer = repo_logmsg_reencode(the_repository, commit, NULL,
+                                            ctx->output_encoding);
        body = strstr(commit_buffer, "\n\n");
        if (!body)
                return;
@@ -195,12 +203,38 @@ static void insert_records_from_trailers(struct shortlog *log,
        trailer_iterator_release(&iter);
 
        strbuf_release(&ident);
-       unuse_commit_buffer(commit, commit_buffer);
+       repo_unuse_commit_buffer(the_repository, commit, commit_buffer);
+}
+
+static int shortlog_needs_dedup(const struct shortlog *log)
+{
+       return HAS_MULTI_BITS(log->groups) || log->format.nr > 1 || log->trailers.nr;
+}
+
+static void insert_records_from_format(struct shortlog *log,
+                                      struct strset *dups,
+                                      struct commit *commit,
+                                      struct pretty_print_context *ctx,
+                                      const char *oneline)
+{
+       struct strbuf buf = STRBUF_INIT;
+       struct string_list_item *item;
+
+       for_each_string_list_item(item, &log->format) {
+               strbuf_reset(&buf);
+
+               repo_format_commit_message(the_repository, commit,
+                                          item->string, &buf, ctx);
+
+               if (!shortlog_needs_dedup(log) || strset_add(dups, buf.buf))
+                       insert_one_record(log, buf.buf, oneline);
+       }
+
+       strbuf_release(&buf);
 }
 
 void shortlog_add_commit(struct shortlog *log, struct commit *commit)
 {
-       struct strbuf ident = STRBUF_INIT;
        struct strbuf oneline = STRBUF_INIT;
        struct strset dups = STRSET_INIT;
        struct pretty_print_context ctx = {0};
@@ -209,41 +243,22 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
        ctx.fmt = CMIT_FMT_USERFORMAT;
        ctx.abbrev = log->abbrev;
        ctx.print_email_subject = 1;
-       ctx.date_mode.type = DATE_NORMAL;
+       ctx.date_mode = log->date_mode;
        ctx.output_encoding = get_log_output_encoding();
 
        if (!log->summary) {
                if (log->user_format)
                        pretty_print_commit(&ctx, commit, &oneline);
                else
-                       format_commit_message(commit, "%s", &oneline, &ctx);
+                       repo_format_commit_message(the_repository, commit,
+                                                  "%s", &oneline, &ctx);
        }
        oneline_str = oneline.len ? oneline.buf : "<none>";
 
-       if (log->groups & SHORTLOG_GROUP_AUTHOR) {
-               strbuf_reset(&ident);
-               format_commit_message(commit,
-                                     log->email ? "%aN <%aE>" : "%aN",
-                                     &ident, &ctx);
-               if (!HAS_MULTI_BITS(log->groups) ||
-                   strset_add(&dups, ident.buf))
-                       insert_one_record(log, ident.buf, oneline_str);
-       }
-       if (log->groups & SHORTLOG_GROUP_COMMITTER) {
-               strbuf_reset(&ident);
-               format_commit_message(commit,
-                                     log->email ? "%cN <%cE>" : "%cN",
-                                     &ident, &ctx);
-               if (!HAS_MULTI_BITS(log->groups) ||
-                   strset_add(&dups, ident.buf))
-                       insert_one_record(log, ident.buf, oneline_str);
-       }
-       if (log->groups & SHORTLOG_GROUP_TRAILER) {
-               insert_records_from_trailers(log, &dups, commit, &ctx, oneline_str);
-       }
+       insert_records_from_trailers(log, &dups, commit, &ctx, oneline_str);
+       insert_records_from_format(log, &dups, commit, &ctx, oneline_str);
 
        strset_clear(&dups);
-       strbuf_release(&ident);
        strbuf_release(&oneline);
 }
 
@@ -312,6 +327,7 @@ static int parse_group_option(const struct option *opt, const char *arg, int uns
        if (unset) {
                log->groups = 0;
                string_list_clear(&log->trailers, 0);
+               string_list_clear(&log->format, 0);
        } else if (!strcasecmp(arg, "author"))
                log->groups |= SHORTLOG_GROUP_AUTHOR;
        else if (!strcasecmp(arg, "committer"))
@@ -319,8 +335,15 @@ static int parse_group_option(const struct option *opt, const char *arg, int uns
        else if (skip_prefix(arg, "trailer:", &field)) {
                log->groups |= SHORTLOG_GROUP_TRAILER;
                string_list_append(&log->trailers, field);
-       } else
+       } else if (skip_prefix(arg, "format:", &field)) {
+               log->groups |= SHORTLOG_GROUP_FORMAT;
+               string_list_append(&log->format, field);
+       } else if (strchr(arg, '%')) {
+               log->groups |= SHORTLOG_GROUP_FORMAT;
+               string_list_append(&log->format, arg);
+       } else {
                return error(_("unknown group type: %s"), arg);
+       }
 
        return 0;
 }
@@ -338,6 +361,19 @@ void shortlog_init(struct shortlog *log)
        log->in2 = DEFAULT_INDENT2;
        log->trailers.strdup_strings = 1;
        log->trailers.cmp = strcasecmp;
+       log->format.strdup_strings = 1;
+}
+
+void shortlog_finish_setup(struct shortlog *log)
+{
+       if (log->groups & SHORTLOG_GROUP_AUTHOR)
+               string_list_append(&log->format,
+                                  log->email ? "%aN <%aE>" : "%aN");
+       if (log->groups & SHORTLOG_GROUP_COMMITTER)
+               string_list_append(&log->format,
+                                  log->email ? "%cN <%cE>" : "%cN");
+
+       string_list_sort(&log->trailers);
 }
 
 int cmd_shortlog(int argc, const char **argv, const char *prefix)
@@ -379,6 +415,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
                        break;
                case PARSE_OPT_HELP:
                case PARSE_OPT_ERROR:
+               case PARSE_OPT_SUBCOMMAND:
                        exit(129);
                case PARSE_OPT_COMPLETE:
                        exit(0);
@@ -404,10 +441,11 @@ parse_done:
        log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT;
        log.abbrev = rev.abbrev;
        log.file = rev.diffopt.file;
+       log.date_mode = rev.date_mode;
 
        if (!log.groups)
                log.groups = SHORTLOG_GROUP_AUTHOR;
-       string_list_sort(&log.trailers);
+       shortlog_finish_setup(&log);
 
        /* assume HEAD if from a tty */
        if (!nongit && !rev.pending.nr && isatty(0))
@@ -420,6 +458,8 @@ parse_done:
        else
                get_from_rev(&rev, &log);
 
+       release_revisions(&rev);
+
        shortlog_output(&log);
        if (log.file != stdout)
                fclose(log.file);
@@ -439,7 +479,7 @@ void shortlog_output(struct shortlog *log)
        struct strbuf sb = STRBUF_INIT;
 
        if (log->sort_by_number)
-               QSORT(log->list.items, log->list.nr,
+               STABLE_QSORT(log->list.items, log->list.nr,
                      log->summary ? compare_by_counter : compare_by_list);
        for (i = 0; i < log->list.nr; i++) {
                const struct string_list_item *item = &log->list.items[i];
@@ -474,4 +514,5 @@ void shortlog_output(struct shortlog *log)
        log->list.strdup_strings = 1;
        string_list_clear(&log->list, 1);
        clear_mailmap(&log->mailmap);
+       string_list_clear(&log->format, 0);
 }