130
static const char *committer_match[2] = { "Commit: ", "committer " };
131
const char **match;
132
133
- switch (log->group) {
133
+ if (HAS_MULTI_BITS(log->groups))
134
+ die(_("using multiple --group options with stdin is not supported"));
135
+
136
+ switch (log->groups) {
137
case SHORTLOG_GROUP_AUTHOR:
138
match = author_match;
139
break;
224
}
225
226
static void insert_records_from_trailers(struct shortlog *log,
227
+ struct strset *dups,
228
struct commit *commit,
229
struct pretty_print_context *ctx,
230
const char *oneline)
231
{
232
struct trailer_iterator iter;
233
const char *commit_buffer, *body;
230
- struct strset dups = STRSET_INIT;
234
struct strbuf ident = STRBUF_INIT;
235
236
/*
246
while (trailer_iterator_advance(&iter)) {
247
const char *value = iter.val.buf;
248
246
- if (strcasecmp(iter.key.buf, log->trailer))
249
+ if (!string_list_has_string(&log->trailers, iter.key.buf))
250
continue;
251
252
strbuf_reset(&ident);
253
if (!parse_ident(log, &ident, value))
254
value = ident.buf;
255
253
- if (strset_check_and_add(&dups, value))
256
+ if (strset_check_and_add(dups, value))
257
continue;
258
insert_one_record(log, value, oneline);
259
}
260
trailer_iterator_release(&iter);
261
262
strbuf_release(&ident);
260
- strset_clear(&dups);
263
unuse_commit_buffer(commit, commit_buffer);
264
}
265
267
{
268
struct strbuf ident = STRBUF_INIT;
269
struct strbuf oneline = STRBUF_INIT;
270
+ struct strset dups = STRSET_INIT;
271
struct pretty_print_context ctx = {0};
272
const char *oneline_str;
273
285
}
286
oneline_str = oneline.len ? oneline.buf : "<none>";
287
285
- switch (log->group) {
286
- case SHORTLOG_GROUP_AUTHOR:
288
+ if (log->groups & SHORTLOG_GROUP_AUTHOR) {
289
+ strbuf_reset(&ident);
290
format_commit_message(commit,
291
log->email ? "%aN <%aE>" : "%aN",
292
&ident, &ctx);
290
- insert_one_record(log, ident.buf, oneline_str);
291
- break;
292
- case SHORTLOG_GROUP_COMMITTER:
293
+ if (!HAS_MULTI_BITS(log->groups) ||
294
+ !strset_check_and_add(&dups, ident.buf))
295
+ insert_one_record(log, ident.buf, oneline_str);
296
+ }
297
+ if (log->groups & SHORTLOG_GROUP_COMMITTER) {
298
+ strbuf_reset(&ident);
299
format_commit_message(commit,
300
log->email ? "%cN <%cE>" : "%cN",
301
&ident, &ctx);
296
- insert_one_record(log, ident.buf, oneline_str);
297
- break;
298
- case SHORTLOG_GROUP_TRAILER:
299
- insert_records_from_trailers(log, commit, &ctx, oneline_str);
300
- break;
302
+ if (!HAS_MULTI_BITS(log->groups) ||
303
+ !strset_check_and_add(&dups, ident.buf))
304
+ insert_one_record(log, ident.buf, oneline_str);
305
+ }
306
+ if (log->groups & SHORTLOG_GROUP_TRAILER) {
307
+ insert_records_from_trailers(log, &dups, commit, &ctx, oneline_str);
308
}
309
310
+ strset_clear(&dups);
311
strbuf_release(&ident);
312
strbuf_release(&oneline);
313
}
374
struct shortlog *log = opt->value;
375
const char *field;
376
369
- if (unset || !strcasecmp(arg, "author"))
370
- log->group = SHORTLOG_GROUP_AUTHOR;
377
+ if (unset) {
378
+ log->groups = 0;
379
+ string_list_clear(&log->trailers, 0);
380
+ } else if (!strcasecmp(arg, "author"))
381
+ log->groups |= SHORTLOG_GROUP_AUTHOR;
382
else if (!strcasecmp(arg, "committer"))
372
- log->group = SHORTLOG_GROUP_COMMITTER;
383
+ log->groups |= SHORTLOG_GROUP_COMMITTER;
384
else if (skip_prefix(arg, "trailer:", &field)) {
374
- log->group = SHORTLOG_GROUP_TRAILER;
375
- free(log->trailer);
376
- log->trailer = xstrdup(field);
385
+ log->groups |= SHORTLOG_GROUP_TRAILER;
386
+ string_list_append(&log->trailers, field);
387
} else
388
return error(_("unknown group type: %s"), arg);
389
401
log->wrap = DEFAULT_WRAPLEN;
402
log->in1 = DEFAULT_INDENT1;
403
log->in2 = DEFAULT_INDENT2;
404
+ log->trailers.strdup_strings = 1;
405
+ log->trailers.cmp = strcasecmp;
406
}
407
408
int cmd_shortlog(int argc, const char **argv, const char *prefix)
412
int nongit = !startup_info->have_repository;
413
414
const struct option options[] = {
403
- OPT_SET_INT('c', "committer", &log.group,
404
- N_("Group by committer rather than author"),
405
- SHORTLOG_GROUP_COMMITTER),
415
+ OPT_BIT('c', "committer", &log.groups,
416
+ N_("Group by committer rather than author"),
417
+ SHORTLOG_GROUP_COMMITTER),
418
OPT_BOOL('n', "numbered", &log.sort_by_number,
419
N_("sort output according to the number of commits per author")),
420
OPT_BOOL('s', "summary", &log.summary,
466
log.abbrev = rev.abbrev;
467
log.file = rev.diffopt.file;
468
469
+ if (!log.groups)
470
+ log.groups = SHORTLOG_GROUP_AUTHOR;
471
+ string_list_sort(&log.trailers);
472
+
473
/* assume HEAD if from a tty */
474
if (!nongit && !rev.pending.nr && isatty(0))
475
add_head_to_pending(&rev);