|
9 | 9 | #include "mailmap.h"
|
10 | 10 | #include "shortlog.h"
|
11 | 11 | #include "parse-options.h"
|
| 12 | +#include "trailer.h" |
12 | 13 |
|
13 | 14 | static char const * const shortlog_usage[] = {
|
14 | 15 | N_("git shortlog [<options>] [<revision-range>] [[--] <path>...]"),
|
@@ -136,6 +137,8 @@ static void read_from_stdin(struct shortlog *log)
|
136 | 137 | case SHORTLOG_GROUP_COMMITTER:
|
137 | 138 | match = committer_match;
|
138 | 139 | break;
|
| 140 | + case SHORTLOG_GROUP_TRAILER: |
| 141 | + die(_("using --group=trailer with stdin is not supported")); |
139 | 142 | default:
|
140 | 143 | BUG("unhandled shortlog group");
|
141 | 144 | }
|
@@ -163,6 +166,37 @@ static void read_from_stdin(struct shortlog *log)
|
163 | 166 | strbuf_release(&oneline);
|
164 | 167 | }
|
165 | 168 |
|
| 169 | +static void insert_records_from_trailers(struct shortlog *log, |
| 170 | + struct commit *commit, |
| 171 | + struct pretty_print_context *ctx, |
| 172 | + const char *oneline) |
| 173 | +{ |
| 174 | + struct trailer_iterator iter; |
| 175 | + const char *commit_buffer, *body; |
| 176 | + |
| 177 | + /* |
| 178 | + * Using format_commit_message("%B") would be simpler here, but |
| 179 | + * this saves us copying the message. |
| 180 | + */ |
| 181 | + commit_buffer = logmsg_reencode(commit, NULL, ctx->output_encoding); |
| 182 | + body = strstr(commit_buffer, "\n\n"); |
| 183 | + if (!body) |
| 184 | + return; |
| 185 | + |
| 186 | + trailer_iterator_init(&iter, body); |
| 187 | + while (trailer_iterator_advance(&iter)) { |
| 188 | + const char *value = iter.val.buf; |
| 189 | + |
| 190 | + if (strcasecmp(iter.key.buf, log->trailer)) |
| 191 | + continue; |
| 192 | + |
| 193 | + insert_one_record(log, value, oneline); |
| 194 | + } |
| 195 | + trailer_iterator_release(&iter); |
| 196 | + |
| 197 | + unuse_commit_buffer(commit, commit_buffer); |
| 198 | +} |
| 199 | + |
166 | 200 | void shortlog_add_commit(struct shortlog *log, struct commit *commit)
|
167 | 201 | {
|
168 | 202 | struct strbuf ident = STRBUF_INIT;
|
@@ -197,6 +231,9 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
|
197 | 231 | &ident, &ctx);
|
198 | 232 | insert_one_record(log, ident.buf, oneline_str);
|
199 | 233 | break;
|
| 234 | + case SHORTLOG_GROUP_TRAILER: |
| 235 | + insert_records_from_trailers(log, commit, &ctx, oneline_str); |
| 236 | + break; |
200 | 237 | }
|
201 | 238 |
|
202 | 239 | strbuf_release(&ident);
|
@@ -263,12 +300,17 @@ static int parse_wrap_args(const struct option *opt, const char *arg, int unset)
|
263 | 300 | static int parse_group_option(const struct option *opt, const char *arg, int unset)
|
264 | 301 | {
|
265 | 302 | struct shortlog *log = opt->value;
|
| 303 | + const char *field; |
266 | 304 |
|
267 | 305 | if (unset || !strcasecmp(arg, "author"))
|
268 | 306 | log->group = SHORTLOG_GROUP_AUTHOR;
|
269 | 307 | else if (!strcasecmp(arg, "committer"))
|
270 | 308 | log->group = SHORTLOG_GROUP_COMMITTER;
|
271 |
| - else |
| 309 | + else if (skip_prefix(arg, "trailer:", &field)) { |
| 310 | + log->group = SHORTLOG_GROUP_TRAILER; |
| 311 | + free(log->trailer); |
| 312 | + log->trailer = xstrdup(field); |
| 313 | + } else |
272 | 314 | return error(_("unknown group type: %s"), arg);
|
273 | 315 |
|
274 | 316 | return 0;
|
|
0 commit comments