]> git.ipfire.org Git - thirdparty/git.git/blame - builtin/log.c
The fifth batch
[thirdparty/git.git] / builtin / log.c
CommitLineData
70827b15
LT
1/*
2 * Builtin "git log" and related commands (show, whatchanged)
3 *
4 * (C) Copyright 2006 Linus Torvalds
5 * 2006 Junio Hamano
6 */
41f43b82 7
03eae9af 8#define USE_THE_REPOSITORY_VARIABLE
41f43b82 9
e7da9385 10#include "builtin.h"
0b027f6c 11#include "abspath.h"
b2141fc1 12#include "config.h"
32a8f510 13#include "environment.h"
f394e093 14#include "gettext.h"
41771fa4 15#include "hex.h"
fb58c8d5 16#include "refs.h"
dabab1d6 17#include "object-name.h"
68cd492a 18#include "object-store.h"
ca4eed70 19#include "pager.h"
6b2f2d98 20#include "color.h"
70827b15
LT
21#include "commit.h"
22#include "diff.h"
a37eec63 23#include "diff-merges.h"
70827b15
LT
24#include "revision.h"
25#include "log-tree.h"
91efcf60 26#include "builtin.h"
6f2d7430 27#include "oid-array.h"
5d7eeee2 28#include "tag.h"
cf39f54e 29#include "reflog-walk.h"
5d23e133 30#include "patch-ids.h"
1a99fe80 31#include "path.h"
2bda2cf4 32#include "shortlog.h"
f2968022 33#include "remote.h"
b079c50e 34#include "string-list.h"
fff02ee6 35#include "parse-options.h"
12da1d1f 36#include "line-log.h"
739453a3 37#include "branch.h"
74775a09 38#include "streaming.h"
816fb46b 39#include "version.h"
ea57bc0d 40#include "mailmap.h"
738e88a2 41#include "progress.h"
7b680d32 42#include "commit-slab.h"
03eae9af 43
64043556 44#include "commit-reach.h"
31e2617a 45#include "range-diff.h"
db757e8b 46#include "tmp-objdir.h"
d4a4f929 47#include "tree.h"
d48be35c 48#include "write-or-die.h"
70827b15 49
43662b23 50#define MAIL_DEFAULT_WRAP 72
bf8e65b3 51#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
3baf58bf 52#define FORMAT_PATCH_NAME_MAX_DEFAULT 64
43662b23 53
34bc1b10 54static unsigned int force_in_body_from;
4810946f 55static int stdout_mboxrd;
8d5213de 56static int format_no_prefix;
0f03ca94 57
1c40c36b 58static const char * const builtin_log_usage[] = {
ce41720c 59 N_("git log [<options>] [<revision-range>] [[--] <path>...]"),
bb831db6 60 N_("git show [<options>] <object>..."),
1c40c36b
CMN
61 NULL
62};
1c370ea4 63
12da1d1f
TR
64struct line_opt_callback_data {
65 struct rev_info *rev;
66 const char *prefix;
67 struct string_list args;
68};
69
f0596ecc
AC
70static int session_is_interactive(void)
71{
72 return isatty(1) || pager_in_use();
73}
74
940a911f
AH
75static int auto_decoration_style(void)
76{
f0596ecc 77 return session_is_interactive() ? DECORATE_SHORT_REFS : 0;
940a911f
AH
78}
79
f094b89a 80static int parse_decoration_style(const char *value)
8a3d203b 81{
89576613 82 switch (git_parse_maybe_bool(value)) {
8a3d203b
JH
83 case 1:
84 return DECORATE_SHORT_REFS;
85 case 0:
86 return 0;
87 default:
88 break;
89 }
90 if (!strcmp(value, "full"))
91 return DECORATE_FULL_REFS;
92 else if (!strcmp(value, "short"))
93 return DECORATE_SHORT_REFS;
15715866 94 else if (!strcmp(value, "auto"))
940a911f 95 return auto_decoration_style();
5a59a230
NTND
96 /*
97 * Please update _git_log() in git-completion.bash when you
98 * add new decoration styles.
99 */
8a3d203b
JH
100 return -1;
101}
102
106a54ae
PS
103struct log_config {
104 int default_abbrev_commit;
105 int default_show_root;
106 int default_follow;
107 int default_show_signature;
108 int default_encode_email_headers;
109 int decoration_style;
110 int decoration_given;
111 int use_mailmap_config;
112 char *fmt_patch_subject_prefix;
113 int fmt_patch_name_max;
114 char *fmt_pretty;
115 char *default_date_mode;
731a2c7d 116
07572f22 117#ifndef WITH_BREAKING_CHANGES
731a2c7d
JH
118 /*
119 * Note: git_log_config() does not touch this member and that
120 * is very deliberate. This member is only to be used to
121 * resurrect whatchanged that is deprecated.
122 */
123 int i_still_use_this;
07572f22 124#endif
106a54ae
PS
125};
126
127static void log_config_init(struct log_config *cfg)
128{
129 memset(cfg, 0, sizeof(*cfg));
130 cfg->default_show_root = 1;
131 cfg->default_encode_email_headers = 1;
132 cfg->use_mailmap_config = 1;
133 cfg->fmt_patch_subject_prefix = xstrdup("PATCH");
134 cfg->fmt_patch_name_max = FORMAT_PATCH_NAME_MAX_DEFAULT;
135 cfg->decoration_style = auto_decoration_style();
136}
137
138static void log_config_release(struct log_config *cfg)
139{
140 free(cfg->default_date_mode);
141 free(cfg->fmt_pretty);
142 free(cfg->fmt_patch_subject_prefix);
143}
144
748706d7
DS
145static int use_default_decoration_filter = 1;
146static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
147static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
148static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
149
34bf44f2
JK
150static int clear_decorations_callback(const struct option *opt UNUSED,
151 const char *arg, int unset)
748706d7 152{
abf2952f
JK
153 BUG_ON_OPT_NEG(unset);
154 BUG_ON_OPT_ARG(arg);
748706d7
DS
155 string_list_clear(&decorate_refs_include, 0);
156 string_list_clear(&decorate_refs_exclude, 0);
157 use_default_decoration_filter = 0;
158 return 0;
159}
160
106a54ae 161static int decorate_callback(const struct option *opt, const char *arg,
34bf44f2 162 int unset)
1c40c36b 163{
106a54ae
PS
164 struct log_config *cfg = opt->value;
165
1c40c36b 166 if (unset)
106a54ae 167 cfg->decoration_style = 0;
1c40c36b 168 else if (arg)
106a54ae 169 cfg->decoration_style = parse_decoration_style(arg);
1c40c36b 170 else
106a54ae 171 cfg->decoration_style = DECORATE_SHORT_REFS;
1c40c36b 172
106a54ae 173 if (cfg->decoration_style < 0)
e4a590ef 174 die(_("invalid --decorate option: %s"), arg);
1c40c36b 175
106a54ae 176 cfg->decoration_given = 1;
1c40c36b
CMN
177
178 return 0;
179}
180
12da1d1f
TR
181static int log_line_range_callback(const struct option *option, const char *arg, int unset)
182{
183 struct line_opt_callback_data *data = option->value;
184
517fe807
JK
185 BUG_ON_OPT_NEG(unset);
186
12da1d1f
TR
187 if (!arg)
188 return -1;
189
190 data->rev->line_level_traverse = 1;
191 string_list_append(&data->args, arg);
192
193 return 0;
194}
195
106a54ae
PS
196static void cmd_log_init_defaults(struct rev_info *rev,
197 struct log_config *cfg)
9501d191 198{
106a54ae
PS
199 if (cfg->fmt_pretty)
200 get_commit_format(cfg->fmt_pretty, rev);
201 if (cfg->default_follow)
0d1e0e78 202 rev->diffopt.flags.default_follow_renames = 1;
70827b15 203 rev->verbose_header = 1;
4ca7a3fd 204 init_diffstat_widths(&rev->diffopt);
0d1e0e78 205 rev->diffopt.flags.recursive = 1;
4ca7a3fd 206 rev->diffopt.flags.allow_textconv = 1;
106a54ae
PS
207 rev->abbrev_commit = cfg->default_abbrev_commit;
208 rev->show_root_diff = cfg->default_show_root;
209 rev->subject_prefix = cfg->fmt_patch_subject_prefix;
210 rev->patch_name_max = cfg->fmt_patch_name_max;
211 rev->show_signature = cfg->default_show_signature;
212 rev->encode_email_headers = cfg->default_encode_email_headers;
dd0ffd5b 213
106a54ae
PS
214 if (cfg->default_date_mode)
215 parse_date_format(cfg->default_date_mode, &rev->date_mode);
ef803fd4 216}
dd0ffd5b 217
92156291
DS
218static void set_default_decoration_filter(struct decoration_filter *decoration_filter)
219{
3e103ed2 220 char *value = NULL;
92156291 221 struct string_list *include = decoration_filter->include_ref_pattern;
a4286193 222 const struct string_list *config_exclude;
92156291 223
9e2d884d
ÆAB
224 if (!git_config_get_string_multi("log.excludeDecoration",
225 &config_exclude)) {
92156291
DS
226 struct string_list_item *item;
227 for_each_string_list_item(item, config_exclude)
228 string_list_append(decoration_filter->exclude_ref_config_pattern,
229 item->string);
230 }
231
3e103ed2
DS
232 /*
233 * By default, decorate_all is disabled. Enable it if
234 * log.initialDecorationSet=all. Don't ever disable it by config,
235 * since the command-line takes precedent.
236 */
237 if (use_default_decoration_filter &&
238 !git_config_get_string("log.initialdecorationset", &value) &&
239 !strcmp("all", value))
240 use_default_decoration_filter = 0;
241 free(value);
242
748706d7
DS
243 if (!use_default_decoration_filter ||
244 decoration_filter->exclude_ref_pattern->nr ||
92156291
DS
245 decoration_filter->include_ref_pattern->nr ||
246 decoration_filter->exclude_ref_config_pattern->nr)
247 return;
248
249 /*
250 * No command-line or config options were given, so
251 * populate with sensible defaults.
252 */
1ab59481 253 for (size_t i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
92156291
DS
254 if (!ref_namespace[i].decoration)
255 continue;
256
257 string_list_append(include, ref_namespace[i].ref);
258 }
259}
260
ef803fd4 261static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
106a54ae
PS
262 struct rev_info *rev, struct setup_revision_opt *opt,
263 struct log_config *cfg)
ef803fd4 264{
ef803fd4 265 struct userformat_want w;
f3eda90f 266 int quiet = 0, source = 0, mailmap;
12da1d1f 267 static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};
92156291
DS
268 struct decoration_filter decoration_filter = {
269 .exclude_ref_pattern = &decorate_refs_exclude,
270 .include_ref_pattern = &decorate_refs_include,
271 .exclude_ref_config_pattern = &decorate_refs_exclude_config,
272 };
87be2523 273 static struct revision_sources revision_sources;
1c40c36b
CMN
274
275 const struct option builtin_log_options[] = {
b7df098c 276 OPT__QUIET(&quiet, N_("suppress diff output")),
aa089cd9 277 OPT_BOOL(0, "source", &source, N_("show source")),
e73fe3dd 278 OPT_BOOL(0, "use-mailmap", &mailmap, N_("use mail map file")),
07572f22 279#ifndef WITH_BREAKING_CHANGES
731a2c7d
JH
280 OPT_HIDDEN_BOOL(0, "i-still-use-this", &cfg->i_still_use_this,
281 "<use this deprecated command>"),
07572f22 282#endif
88acccda 283 OPT_ALIAS(0, "mailmap", "use-mailmap"),
748706d7
DS
284 OPT_CALLBACK_F(0, "clear-decorations", NULL, NULL,
285 N_("clear all previously-defined decoration filters"),
286 PARSE_OPT_NOARG | PARSE_OPT_NONEG,
287 clear_decorations_callback),
65516f58
RA
288 OPT_STRING_LIST(0, "decorate-refs", &decorate_refs_include,
289 N_("pattern"), N_("only decorate refs that match <pattern>")),
290 OPT_STRING_LIST(0, "decorate-refs-exclude", &decorate_refs_exclude,
291 N_("pattern"), N_("do not decorate refs that match <pattern>")),
106a54ae 292 OPT_CALLBACK_F(0, "decorate", cfg, NULL, N_("decorate options"),
203c8533 293 PARSE_OPT_OPTARG, decorate_callback),
180d641d 294 OPT_CALLBACK('L', NULL, &line_cb, "range:file",
e73fe3dd 295 N_("trace the evolution of line range <start>,<end> or function :<funcname> in <file>"),
12da1d1f 296 log_line_range_callback),
1c40c36b
CMN
297 OPT_END()
298 };
299
12da1d1f
TR
300 line_cb.rev = rev;
301 line_cb.prefix = prefix;
302
106a54ae 303 mailmap = cfg->use_mailmap_config;
1c40c36b
CMN
304 argc = parse_options(argc, argv, prefix,
305 builtin_log_options, builtin_log_usage,
99d86d60 306 PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT |
1c40c36b 307 PARSE_OPT_KEEP_DASHDASH);
52883fbd 308
01771a8e
JH
309 if (quiet)
310 rev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;
f9c75d85 311 argc = setup_revisions(argc, argv, rev, opt);
dd0ffd5b 312
1c40c36b
CMN
313 /* Any arguments at this point are not recognized */
314 if (argc > 1)
e4a590ef 315 die(_("unrecognized argument: %s"), argv[1]);
1c40c36b 316
39664cb0
JH
317 if (rev->line_level_traverse && rev->prune_data.nr)
318 die(_("-L<range>:<file> cannot be used with pathspec"));
319
5b163603
JG
320 memset(&w, 0, sizeof(w));
321 userformat_find_requirements(NULL, &w);
322
323 if (!rev->show_notes_given && (!rev->pretty_given || w.notes))
66b2ed09 324 rev->show_notes = 1;
894a9d33 325 if (rev->show_notes)
1e6ed544 326 load_display_notes(&rev->notes_opt);
66b2ed09 327
cf63051a
SB
328 if ((rev->diffopt.pickaxe_opts & DIFF_PICKAXE_KINDS_MASK) ||
329 rev->diffopt.filter || rev->diffopt.flags.follow_renames)
9dafea26 330 rev->always_show_header = 0;
1c40c36b 331
ad6f028f 332 if (source || w.source) {
87be2523
NTND
333 init_revision_sources(&revision_sources);
334 rev->sources = &revision_sources;
335 }
635530a2 336
ea57bc0d 337 if (mailmap) {
f2605051
ÆAB
338 rev->mailmap = xmalloc(sizeof(struct string_list));
339 string_list_init_nodup(rev->mailmap);
4e168333 340 read_mailmap(rev->mailmap);
ea57bc0d
AP
341 }
342
0c47695a
JS
343 if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
344 /*
345 * "log --pretty=raw" is special; ignore UI oriented
346 * configuration variables such as decoration.
347 */
106a54ae
PS
348 if (!cfg->decoration_given)
349 cfg->decoration_style = 0;
0c47695a
JS
350 if (!rev->abbrev_commit_given)
351 rev->abbrev_commit = 0;
352 }
635530a2 353
14b9c2b3
JK
354 if (rev->commit_format == CMIT_FMT_USERFORMAT) {
355 if (!w.decorate) {
356 /*
357 * Disable decoration loading if the format will not
358 * show them anyway.
359 */
106a54ae
PS
360 cfg->decoration_style = 0;
361 } else if (!cfg->decoration_style) {
14b9c2b3
JK
362 /*
363 * If we are going to show them, make sure we do load
364 * them here, but taking care not to override a
365 * specific style set by config or --decorate.
366 */
106a54ae 367 cfg->decoration_style = DECORATE_SHORT_REFS;
14b9c2b3
JK
368 }
369 }
b2086b51 370
106a54ae 371 if (cfg->decoration_style || rev->simplify_by_decoration) {
92156291 372 set_default_decoration_filter(&decoration_filter);
a6be5e67 373
106a54ae 374 if (cfg->decoration_style)
be738607 375 rev->show_decorations = 1;
a6be5e67 376
106a54ae 377 load_ref_decorations(&decoration_filter, cfg->decoration_style);
33e7018c 378 }
12da1d1f
TR
379
380 if (rev->line_level_traverse)
381 line_log_init(rev, line_cb.prefix, &line_cb.args);
382
59b6131a 383 setup_pager(the_repository);
9dafea26
TH
384}
385
ef803fd4 386static void cmd_log_init(int argc, const char **argv, const char *prefix,
106a54ae
PS
387 struct rev_info *rev, struct setup_revision_opt *opt,
388 struct log_config *cfg)
f6bfea0a 389{
106a54ae
PS
390 cmd_log_init_defaults(rev, cfg);
391 cmd_log_init_finish(argc, argv, prefix, rev, opt, cfg);
f6bfea0a
ÆAB
392}
393
252a7c02
LT
394/*
395 * This gives a rough estimate for how many commits we
396 * will print out in the list.
397 */
7954d365 398static int estimate_commit_count(struct commit_list *list)
252a7c02
LT
399{
400 int n = 0;
401
402 while (list) {
403 struct commit *commit = list->item;
404 unsigned int flags = commit->object.flags;
252a7c02 405 list = list->next;
7dc0fe3b 406 if (!(flags & (TREESAME | UNINTERESTING)))
53b2c823 407 n++;
252a7c02
LT
408 }
409 return n;
410}
411
412static void show_early_header(struct rev_info *rev, const char *stage, int nr)
413{
414 if (rev->shown_one) {
415 rev->shown_one = 0;
416 if (rev->commit_format != CMIT_FMT_ONELINE)
417 putchar(rev->diffopt.line_termination);
418 }
95235f5b 419 fprintf(rev->diffopt.file, _("Final output: %d %s\n"), nr, stage);
252a7c02
LT
420}
421
2af202be 422static struct itimerval early_output_timer;
252a7c02 423
cdcefbc9
LT
424static void log_show_early(struct rev_info *revs, struct commit_list *list)
425{
e900d494 426 int i = revs->early_output;
252a7c02 427 int show_header = 1;
e900d494 428 int no_free = revs->diffopt.no_free;
cdcefbc9 429
e900d494 430 revs->diffopt.no_free = 0;
08f704f2 431 sort_in_topological_order(&list, revs->sort_order);
cdcefbc9
LT
432 while (list && i) {
433 struct commit *commit = list->item;
252a7c02
LT
434 switch (simplify_commit(revs, commit)) {
435 case commit_show:
436 if (show_header) {
7954d365 437 int n = estimate_commit_count(list);
252a7c02
LT
438 show_early_header(revs, "incomplete", n);
439 show_header = 0;
440 }
441 log_tree_commit(revs, commit);
442 i--;
443 break;
444 case commit_ignore:
445 break;
446 case commit_error:
e900d494
ÆAB
447 revs->diffopt.no_free = no_free;
448 diff_free(&revs->diffopt);
252a7c02
LT
449 return;
450 }
cdcefbc9 451 list = list->next;
cdcefbc9 452 }
252a7c02
LT
453
454 /* Did we already get enough commits for the early output? */
6ea57703 455 if (!i) {
e900d494
ÆAB
456 revs->diffopt.no_free = 0;
457 diff_free(&revs->diffopt);
252a7c02 458 return;
6ea57703 459 }
252a7c02
LT
460
461 /*
462 * ..if no, then repeat it twice a second until we
463 * do.
464 *
465 * NOTE! We don't use "it_interval", because if the
466 * reader isn't listening, we want our output to be
467 * throttled by the writing, and not have the timer
468 * trigger every second even if we're blocked on a
469 * reader!
470 */
471 early_output_timer.it_value.tv_sec = 0;
472 early_output_timer.it_value.tv_usec = 500000;
473 setitimer(ITIMER_REAL, &early_output_timer, NULL);
cdcefbc9
LT
474}
475
9ec03b59 476static void early_output(int signal UNUSED)
cdcefbc9
LT
477{
478 show_early_output = log_show_early;
479}
480
7954d365 481static void setup_early_output(void)
cdcefbc9
LT
482{
483 struct sigaction sa;
cdcefbc9
LT
484
485 /*
486 * Set up the signal handler, minimally intrusively:
487 * we only set a single volatile integer word (not
488 * using sigatomic_t - trying to avoid unnecessary
489 * system dependencies and headers), and using
490 * SA_RESTART.
491 */
492 memset(&sa, 0, sizeof(sa));
493 sa.sa_handler = early_output;
494 sigemptyset(&sa.sa_mask);
495 sa.sa_flags = SA_RESTART;
496 sigaction(SIGALRM, &sa, NULL);
497
498 /*
499 * If we can get the whole output in less than a
500 * tenth of a second, don't even bother doing the
501 * early-output thing..
502 *
503 * This is a one-time-only trigger.
504 */
252a7c02
LT
505 early_output_timer.it_value.tv_sec = 0;
506 early_output_timer.it_value.tv_usec = 100000;
507 setitimer(ITIMER_REAL, &early_output_timer, NULL);
cdcefbc9
LT
508}
509
510static void finish_early_output(struct rev_info *rev)
511{
7954d365 512 int n = estimate_commit_count(rev->commits);
cdcefbc9 513 signal(SIGALRM, SIG_IGN);
252a7c02 514 show_early_header(rev, "done", n);
cdcefbc9
LT
515}
516
5cdb3845 517static int cmd_log_walk_no_free(struct rev_info *rev)
9dafea26
TH
518{
519 struct commit *commit;
f31027c9 520 int saved_nrl = 0;
e900d494 521 int saved_dcctc = 0;
4460e052 522 int result;
70827b15 523
cdcefbc9 524 if (rev->early_output)
7954d365 525 setup_early_output();
cdcefbc9 526
3d51e1b5 527 if (prepare_revision_walk(rev))
5c5f1d7c 528 die(_("revision walk setup failed"));
cdcefbc9
LT
529
530 if (rev->early_output)
531 finish_early_output(rev);
532
036d17fe 533 /*
84102a33
PVM
534 * For --check and --exit-code, the exit code is based on CHECK_FAILED
535 * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
536 * retain that state information if replacing rev->diffopt in this loop
036d17fe 537 */
70827b15 538 while ((commit = get_revision(rev)) != NULL) {
3acf8dd8 539 if (!log_tree_commit(rev, commit) && rev->max_count >= 0)
251df09b
MM
540 /*
541 * We decremented max_count in get_revision,
542 * but we didn't actually show the commit.
543 */
544 rev->max_count++;
f94bfa15 545 if (!rev->reflog_info && !rev->remerge_diff) {
822601e8
JK
546 /*
547 * We may show a given commit multiple times when
f94bfa15
JS
548 * walking the reflogs. Therefore we still need it.
549 *
550 * Likewise, we potentially still need the parents
551 * of * already shown commits to determine merge
552 * bases when showing remerge diffs.
822601e8 553 */
6a7895fd
SB
554 free_commit_buffer(the_repository->parsed_objects,
555 commit);
f35650df
JK
556 free_commit_list(commit->parents);
557 commit->parents = NULL;
a6c73064 558 }
f31027c9
JH
559 if (saved_nrl < rev->diffopt.needed_rename_limit)
560 saved_nrl = rev->diffopt.needed_rename_limit;
561 if (rev->diffopt.degraded_cc_to_c)
562 saved_dcctc = 1;
70827b15 563 }
f31027c9
JH
564 rev->diffopt.degraded_cc_to_c = saved_dcctc;
565 rev->diffopt.needed_rename_limit = saved_nrl;
566
4460e052 567 result = diff_result_code(rev);
036d17fe 568 if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
0d1e0e78 569 rev->diffopt.flags.check_failed) {
4460e052 570 result = 02;
036d17fe 571 }
4460e052 572 return result;
70827b15
LT
573}
574
5cdb3845
JH
575static int cmd_log_walk(struct rev_info *rev)
576{
577 int retval;
578
579 rev->diffopt.no_free = 1;
580 retval = cmd_log_walk_no_free(rev);
581 rev->diffopt.no_free = 0;
582 diff_free(&rev->diffopt);
583 return retval;
584}
585
a4e7e317
GC
586static int git_log_config(const char *var, const char *value,
587 const struct config_context *ctx, void *cb)
0f03ca94 588{
106a54ae 589 struct log_config *cfg = cb;
e3f1da98
RS
590 const char *slot_name;
591
106a54ae
PS
592 if (!strcmp(var, "format.pretty")) {
593 FREE_AND_NULL(cfg->fmt_pretty);
1b261c20 594 return git_config_string(&cfg->fmt_pretty, var, value);
106a54ae
PS
595 }
596 if (!strcmp(var, "format.subjectprefix")) {
597 FREE_AND_NULL(cfg->fmt_patch_subject_prefix);
1b261c20 598 return git_config_string(&cfg->fmt_patch_subject_prefix, var, value);
106a54ae 599 }
3baf58bf 600 if (!strcmp(var, "format.filenamemaxlength")) {
106a54ae 601 cfg->fmt_patch_name_max = git_config_int(var, value, ctx->kvi);
3baf58bf
JH
602 return 0;
603 }
19d097e3 604 if (!strcmp(var, "format.encodeemailheaders")) {
106a54ae 605 cfg->default_encode_email_headers = git_config_bool(var, value);
19d097e3
EB
606 return 0;
607 }
0c47695a 608 if (!strcmp(var, "log.abbrevcommit")) {
106a54ae 609 cfg->default_abbrev_commit = git_config_bool(var, value);
0c47695a
JS
610 return 0;
611 }
106a54ae
PS
612 if (!strcmp(var, "log.date")) {
613 FREE_AND_NULL(cfg->default_date_mode);
1b261c20 614 return git_config_string(&cfg->default_date_mode, var, value);
106a54ae 615 }
eb734454 616 if (!strcmp(var, "log.decorate")) {
106a54ae
PS
617 cfg->decoration_style = parse_decoration_style(value);
618 if (cfg->decoration_style < 0)
619 cfg->decoration_style = 0; /* maybe warn? */
eb734454
SD
620 return 0;
621 }
ba176db5
JK
622 if (!strcmp(var, "log.diffmerges")) {
623 if (!value)
624 return config_error_nonbool(var);
17c13e60 625 return diff_merges_config(value);
ba176db5 626 }
0f03ca94 627 if (!strcmp(var, "log.showroot")) {
106a54ae 628 cfg->default_show_root = git_config_bool(var, value);
0f03ca94
PB
629 return 0;
630 }
076c9837 631 if (!strcmp(var, "log.follow")) {
106a54ae 632 cfg->default_follow = git_config_bool(var, value);
076c9837
DT
633 return 0;
634 }
e3f1da98 635 if (skip_prefix(var, "color.decorate.", &slot_name))
b9465768 636 return parse_decorate_color_config(var, slot_name, value);
e6bb5f78 637 if (!strcmp(var, "log.mailmap")) {
106a54ae 638 cfg->use_mailmap_config = git_config_bool(var, value);
e6bb5f78
AP
639 return 0;
640 }
fce04c3c 641 if (!strcmp(var, "log.showsignature")) {
106a54ae 642 cfg->default_show_signature = git_config_bool(var, value);
fce04c3c
MJ
643 return 0;
644 }
e6bb5f78 645
a4e7e317 646 return git_diff_ui_config(var, value, ctx, cb);
0f03ca94
PB
647}
648
07572f22 649#ifndef WITH_BREAKING_CHANGES
9b1cb507
JC
650int cmd_whatchanged(int argc,
651 const char **argv,
652 const char *prefix,
653 struct repository *repo UNUSED)
70827b15 654{
106a54ae 655 struct log_config cfg;
70827b15 656 struct rev_info rev;
32962c9b 657 struct setup_revision_opt opt;
106a54ae 658 int ret;
70827b15 659
106a54ae
PS
660 log_config_init(&cfg);
661 init_diff_ui_defaults();
662 git_config(git_log_config, &cfg);
6b2f2d98 663
2abf3503 664 repo_init_revisions(the_repository, &rev, prefix);
72365bb4
ÆAB
665 git_config(grep_config, &rev.grep_filter);
666
70827b15 667 rev.diff = 1;
9202434c 668 rev.simplify_history = 0;
32962c9b
JH
669 memset(&opt, 0, sizeof(opt));
670 opt.def = "HEAD";
d5f6b1d7 671 opt.revarg_opt = REVARG_COMMITTISH;
106a54ae 672 cmd_log_init(argc, argv, prefix, &rev, &opt, &cfg);
731a2c7d
JH
673
674 if (!cfg.i_still_use_this)
675 you_still_use_that("git whatchanged");
676
9dafea26
TH
677 if (!rev.diffopt.output_format)
678 rev.diffopt.output_format = DIFF_FORMAT_RAW;
106a54ae
PS
679
680 ret = cmd_log_walk(&rev);
681
682 release_revisions(&rev);
683 log_config_release(&cfg);
684 return ret;
70827b15 685}
07572f22 686#endif
70827b15 687
af117077 688static void show_tagger(const char *buf, struct rev_info *rev)
56122ed8 689{
ea718e65 690 struct strbuf out = STRBUF_INIT;
6bf13944 691 struct pretty_print_context pp = {0};
56122ed8 692
6bf13944
JK
693 pp.fmt = rev->commit_format;
694 pp.date_mode = rev->date_mode;
695 pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding());
95235f5b 696 fprintf(rev->diffopt.file, "%s", out.buf);
ea718e65 697 strbuf_release(&out);
56122ed8
JS
698}
699
d801627b 700static int show_blob_object(const struct object_id *oid, struct rev_info *rev, const char *obj_name)
74775a09 701{
d801627b 702 struct object_id oidc;
f87c55c2 703 struct object_context obj_context = {0};
083b9931
MG
704 char *buf;
705 unsigned long size;
706
95235f5b 707 fflush(rev->diffopt.file);
0d1e0e78
BW
708 if (!rev->diffopt.flags.textconv_set_via_cmdline ||
709 !rev->diffopt.flags.allow_textconv)
7eda0e4f 710 return stream_blob_to_fd(1, oid, NULL, 0);
083b9931 711
3a7a698e
NTND
712 if (get_oid_with_context(the_repository, obj_name,
713 GET_OID_RECORD_PATH,
e82caf38 714 &oidc, &obj_context))
bc208ae3 715 die(_("not a valid object name %s"), obj_name);
dc944b65 716 if (!obj_context.path ||
6afaf807
NTND
717 !textconv_object(the_repository, obj_context.path,
718 obj_context.mode, &oidc, 1, &buf, &size)) {
f87c55c2 719 object_context_release(&obj_context);
7eda0e4f 720 return stream_blob_to_fd(1, oid, NULL, 0);
dc944b65 721 }
083b9931
MG
722
723 if (!buf)
e4a590ef 724 die(_("git show %s: bad file"), obj_name);
083b9931
MG
725
726 write_or_die(1, buf, size);
f87c55c2 727 object_context_release(&obj_context);
0aaca0ec 728 free(buf);
083b9931 729 return 0;
74775a09
NTND
730}
731
d801627b 732static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
5d7eeee2
JS
733{
734 unsigned long size;
21666f1a 735 enum object_type type;
bc726bd0 736 char *buf = repo_read_object_file(the_repository, oid, &type, &size);
1ab59481 737 unsigned long offset = 0;
5d7eeee2
JS
738
739 if (!buf)
bc208ae3 740 return error(_("could not read object %s"), oid_to_hex(oid));
5d7eeee2 741
74775a09
NTND
742 assert(type == OBJ_TAG);
743 while (offset < size && buf[offset] != '\n') {
1ab59481 744 unsigned long new_offset = offset + 1;
af117077 745 const char *ident;
74775a09
NTND
746 while (new_offset < size && buf[new_offset++] != '\n')
747 ; /* do nothing */
af117077
JK
748 if (skip_prefix(buf + offset, "tagger ", &ident))
749 show_tagger(ident, rev);
74775a09
NTND
750 offset = new_offset;
751 }
5d7eeee2
JS
752
753 if (offset < size)
95235f5b 754 fwrite(buf + offset, size - offset, 1, rev->diffopt.file);
5d7eeee2
JS
755 free(buf);
756 return 0;
757}
758
5cf88fd8
ÆAB
759static int show_tree_object(const struct object_id *oid UNUSED,
760 struct strbuf *base UNUSED,
555ff1c8
JK
761 const char *pathname, unsigned mode,
762 void *context)
5d7eeee2 763{
95235f5b
JS
764 FILE *file = context;
765 fprintf(file, "%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
5d7eeee2
JS
766 return 0;
767}
768
cc88afad 769static void show_setup_revisions_tweak(struct rev_info *rev)
b4490059 770{
7acf0d06 771 if (rev->first_parent_only)
4f54544d 772 diff_merges_default_to_first_parent(rev);
7acf0d06
SO
773 else
774 diff_merges_default_to_dense_combined(rev);
b4490059
JH
775 if (!rev->diffopt.output_format)
776 rev->diffopt.output_format = DIFF_FORMAT_PATCH;
777}
778
9b1cb507
JC
779int cmd_show(int argc,
780 const char **argv,
781 const char *prefix,
782 struct repository *repo UNUSED)
70827b15 783{
106a54ae 784 struct log_config cfg;
70827b15 785 struct rev_info rev;
f89d085b 786 unsigned int i;
32962c9b 787 struct setup_revision_opt opt;
f0096c06 788 struct pathspec match_all;
f89d085b 789 int ret = 0;
70827b15 790
106a54ae
PS
791 log_config_init(&cfg);
792 init_diff_ui_defaults();
793 git_config(git_log_config, &cfg);
6b2f2d98 794
a37d1442
DS
795 if (the_repository->gitdir) {
796 prepare_repo_settings(the_repository);
797 the_repository->settings.command_requires_full_index = 0;
798 }
799
9a087274 800 memset(&match_all, 0, sizeof(match_all));
2abf3503 801 repo_init_revisions(the_repository, &rev, prefix);
72365bb4
ÆAB
802 git_config(grep_config, &rev.grep_filter);
803
70827b15 804 rev.diff = 1;
70827b15 805 rev.always_show_header = 1;
29ef1f27 806 rev.no_walk = 1;
666c92a2
ZJS
807 rev.diffopt.stat_width = -1; /* Scale to real terminal size */
808
32962c9b
JH
809 memset(&opt, 0, sizeof(opt));
810 opt.def = "HEAD";
b130c706 811 opt.tweak = show_setup_revisions_tweak;
106a54ae 812 cmd_log_init(argc, argv, prefix, &rev, &opt, &cfg);
5d7eeee2 813
106a54ae
PS
814 if (!rev.no_walk) {
815 ret = cmd_log_walk(&rev);
816 release_revisions(&rev);
817 log_config_release(&cfg);
818 return ret;
819 }
c5941f1a 820
5cdb3845 821 rev.diffopt.no_free = 1;
f89d085b
ÆAB
822 for (i = 0; i < rev.pending.nr && !ret; i++) {
823 struct object *o = rev.pending.objects[i].item;
824 const char *name = rev.pending.objects[i].name;
5d7eeee2
JS
825 switch (o->type) {
826 case OBJ_BLOB:
d801627b 827 ret = show_blob_object(&o->oid, &rev, name);
5d7eeee2
JS
828 break;
829 case OBJ_TAG: {
830 struct tag *t = (struct tag *)o;
c77722b3 831 struct object_id *oid = get_tagged_oid(t);
5d7eeee2 832
ae03ee64
JK
833 if (rev.shown_one)
834 putchar('\n');
95235f5b 835 fprintf(rev.diffopt.file, "%stag %s%s\n",
8f67f8ae 836 diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
5d7eeee2 837 t->tag,
8f67f8ae 838 diff_get_color_opt(&rev.diffopt, DIFF_RESET));
d801627b 839 ret = show_tag_object(&o->oid, &rev);
ae03ee64 840 rev.shown_one = 1;
d2dadfe8
JH
841 if (ret)
842 break;
c77722b3 843 o = parse_object(the_repository, oid);
d2dadfe8 844 if (!o)
bc208ae3 845 ret = error(_("could not read object %s"),
c77722b3 846 oid_to_hex(oid));
f89d085b 847 rev.pending.objects[i].item = o;
5d7eeee2
JS
848 i--;
849 break;
850 }
851 case OBJ_TREE:
ae03ee64
JK
852 if (rev.shown_one)
853 putchar('\n');
95235f5b 854 fprintf(rev.diffopt.file, "%stree %s%s\n\n",
8f67f8ae 855 diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
5d7eeee2 856 name,
8f67f8ae 857 diff_get_color_opt(&rev.diffopt, DIFF_RESET));
47957485
ÆAB
858 read_tree(the_repository, (struct tree *)o,
859 &match_all, show_tree_object,
860 rev.diffopt.file);
ae03ee64 861 rev.shown_one = 1;
5d7eeee2
JS
862 break;
863 case OBJ_COMMIT:
055e57b7
ÆAB
864 {
865 struct object_array old;
f89d085b 866 struct object_array blank = OBJECT_ARRAY_INIT;
055e57b7
ÆAB
867
868 memcpy(&old, &rev.pending, sizeof(old));
f89d085b
ÆAB
869 memcpy(&rev.pending, &blank, sizeof(rev.pending));
870
5d7eeee2 871 add_object_array(o, name, &rev.pending);
5cdb3845 872 ret = cmd_log_walk_no_free(&rev);
f89d085b
ÆAB
873
874 /*
875 * No need for
876 * object_array_clear(&pending). It was
877 * cleared already in prepare_revision_walk()
878 */
055e57b7 879 memcpy(&rev.pending, &old, sizeof(rev.pending));
5d7eeee2 880 break;
055e57b7 881 }
5d7eeee2 882 default:
bc208ae3 883 ret = error(_("unknown type: %d"), o->type);
5d7eeee2
JS
884 }
885 }
5cdb3845
JH
886
887 rev.diffopt.no_free = 0;
888 diff_free(&rev.diffopt);
106a54ae
PS
889 release_revisions(&rev);
890 log_config_release(&cfg);
5cdb3845 891
106a54ae 892 return ret;
70827b15
LT
893}
894
cf39f54e
LT
895/*
896 * This is equivalent to "git log -g --abbrev-commit --pretty=oneline"
897 */
9b1cb507
JC
898int cmd_log_reflog(int argc,
899 const char **argv,
900 const char *prefix,
901 struct repository *repo UNUSED)
cf39f54e 902{
106a54ae 903 struct log_config cfg;
cf39f54e 904 struct rev_info rev;
32962c9b 905 struct setup_revision_opt opt;
106a54ae 906 int ret;
cf39f54e 907
106a54ae
PS
908 log_config_init(&cfg);
909 init_diff_ui_defaults();
910 git_config(git_log_config, &cfg);
6b2f2d98 911
2abf3503 912 repo_init_revisions(the_repository, &rev, prefix);
cf39f54e 913 init_reflog_walk(&rev.reflog_info);
72365bb4
ÆAB
914 git_config(grep_config, &rev.grep_filter);
915
cf39f54e 916 rev.verbose_header = 1;
32962c9b
JH
917 memset(&opt, 0, sizeof(opt));
918 opt.def = "HEAD";
106a54ae 919 cmd_log_init_defaults(&rev, &cfg);
0c47695a 920 rev.abbrev_commit = 1;
cf39f54e 921 rev.commit_format = CMIT_FMT_ONELINE;
4da45bef 922 rev.use_terminator = 1;
cf39f54e 923 rev.always_show_header = 1;
106a54ae 924 cmd_log_init_finish(argc, argv, prefix, &rev, &opt, &cfg);
cf39f54e 925
106a54ae 926 ret = cmd_log_walk(&rev);
cf39f54e 927
106a54ae
PS
928 release_revisions(&rev);
929 log_config_release(&cfg);
930 return ret;
cf39f54e
LT
931}
932
cc88afad 933static void log_setup_revisions_tweak(struct rev_info *rev)
076c9837 934{
0d1e0e78 935 if (rev->diffopt.flags.default_follow_renames &&
9eac5954 936 diff_check_follow_pathspec(&rev->prune_data, 0))
0d1e0e78 937 rev->diffopt.flags.follow_renames = 1;
c7eaf8b4 938
7acf0d06 939 if (rev->first_parent_only)
4f54544d 940 diff_merges_default_to_first_parent(rev);
076c9837
DT
941}
942
9b1cb507
JC
943int cmd_log(int argc,
944 const char **argv,
945 const char *prefix,
946 struct repository *repo UNUSED)
70827b15 947{
106a54ae 948 struct log_config cfg;
70827b15 949 struct rev_info rev;
32962c9b 950 struct setup_revision_opt opt;
106a54ae 951 int ret;
70827b15 952
106a54ae
PS
953 log_config_init(&cfg);
954 init_diff_ui_defaults();
955 git_config(git_log_config, &cfg);
6b2f2d98 956
2abf3503 957 repo_init_revisions(the_repository, &rev, prefix);
72365bb4
ÆAB
958 git_config(grep_config, &rev.grep_filter);
959
70827b15 960 rev.always_show_header = 1;
32962c9b
JH
961 memset(&opt, 0, sizeof(opt));
962 opt.def = "HEAD";
d5f6b1d7 963 opt.revarg_opt = REVARG_COMMITTISH;
b130c706 964 opt.tweak = log_setup_revisions_tweak;
106a54ae 965 cmd_log_init(argc, argv, prefix, &rev, &opt, &cfg);
3ee79d9f 966
106a54ae 967 ret = cmd_log_walk(&rev);
ca9e0a1b 968
106a54ae
PS
969 release_revisions(&rev);
970 log_config_release(&cfg);
971 return ret;
3ee79d9f
DB
972}
973
c06d2daa 974/* format-patch */
0377db77 975
a92331df
DL
976enum cover_setting {
977 COVER_UNSET,
978 COVER_OFF,
979 COVER_ON,
980 COVER_AUTO
981};
982
983enum thread_level {
984 THREAD_UNSET,
985 THREAD_SHALLOW,
986 THREAD_DEEP
987};
988
bf8e65b3
DL
989enum cover_from_description {
990 COVER_FROM_NONE,
991 COVER_FROM_MESSAGE,
992 COVER_FROM_SUBJECT,
993 COVER_FROM_AUTO
994};
995
7efba5fa
JK
996enum auto_base_setting {
997 AUTO_BASE_NEVER,
998 AUTO_BASE_ALWAYS,
999 AUTO_BASE_WHEN_ABLE
1000};
1001
83024d98
PS
1002struct format_config {
1003 struct log_config log;
1004 enum thread_level thread;
1005 int do_signoff;
1006 enum auto_base_setting auto_base;
1007 char *base_commit;
1008 char *from;
1009 char *signature;
1010 char *signature_file;
1011 enum cover_setting config_cover_letter;
1012 char *config_output_directory;
1013 enum cover_from_description cover_from_description_mode;
1014 int show_notes;
1015 struct display_notes_opt notes_opt;
1016 int numbered_cmdline_opt;
1017 int numbered;
1018 int auto_number;
1019 char *default_attach;
1020 struct string_list extra_hdr;
1021 struct string_list extra_to;
1022 struct string_list extra_cc;
1023 int keep_subject;
1024 int subject_prefix;
1025 struct strbuf sprefix;
1026 char *fmt_patch_suffix;
1027};
1028
1029static void format_config_init(struct format_config *cfg)
1030{
1031 memset(cfg, 0, sizeof(*cfg));
1032 log_config_init(&cfg->log);
1033 cfg->cover_from_description_mode = COVER_FROM_MESSAGE;
1034 cfg->auto_number = 1;
1035 string_list_init_dup(&cfg->extra_hdr);
1036 string_list_init_dup(&cfg->extra_to);
1037 string_list_init_dup(&cfg->extra_cc);
1038 strbuf_init(&cfg->sprefix, 0);
1039 cfg->fmt_patch_suffix = xstrdup(".patch");
1040}
1041
1042static void format_config_release(struct format_config *cfg)
1043{
1044 log_config_release(&cfg->log);
1045 free(cfg->base_commit);
1046 free(cfg->from);
1047 free(cfg->signature);
1048 free(cfg->signature_file);
1049 free(cfg->config_output_directory);
1050 free(cfg->default_attach);
1051 string_list_clear(&cfg->extra_hdr, 0);
1052 string_list_clear(&cfg->extra_to, 0);
1053 string_list_clear(&cfg->extra_cc, 0);
1054 strbuf_release(&cfg->sprefix);
1055 free(cfg->fmt_patch_suffix);
1056}
2a4c2607 1057
bf8e65b3
DL
1058static enum cover_from_description parse_cover_from_description(const char *arg)
1059{
1060 if (!arg || !strcmp(arg, "default"))
1061 return COVER_FROM_MESSAGE;
1062 else if (!strcmp(arg, "none"))
1063 return COVER_FROM_NONE;
1064 else if (!strcmp(arg, "message"))
1065 return COVER_FROM_MESSAGE;
1066 else if (!strcmp(arg, "subject"))
1067 return COVER_FROM_SUBJECT;
1068 else if (!strcmp(arg, "auto"))
1069 return COVER_FROM_AUTO;
1070 else
1071 die(_("%s: invalid cover from description mode"), arg);
1072}
30984ed2 1073
83024d98
PS
1074static void add_header(struct format_config *cfg, const char *value)
1075{
1076 struct string_list_item *item;
1077 int len = strlen(value);
1078 while (len && value[len - 1] == '\n')
1079 len--;
1080
1081 if (!strncasecmp(value, "to: ", 4)) {
1082 item = string_list_append(&cfg->extra_to, value + 4);
1083 len -= 4;
1084 } else if (!strncasecmp(value, "cc: ", 4)) {
1085 item = string_list_append(&cfg->extra_cc, value + 4);
1086 len -= 4;
1087 } else {
1088 item = string_list_append(&cfg->extra_hdr, value);
1089 }
1090
1091 item->string[len] = '\0';
1092}
1093
a4e7e317
GC
1094static int git_format_config(const char *var, const char *value,
1095 const struct config_context *ctx, void *cb)
20ff0680 1096{
83024d98
PS
1097 struct format_config *cfg = cb;
1098
20ff0680 1099 if (!strcmp(var, "format.headers")) {
d7fb91c6 1100 if (!value)
5c5f1d7c 1101 die(_("format.headers without value"));
83024d98 1102 add_header(cfg, value);
20ff0680
JS
1103 return 0;
1104 }
83024d98
PS
1105 if (!strcmp(var, "format.suffix")) {
1106 FREE_AND_NULL(cfg->fmt_patch_suffix);
1b261c20 1107 return git_config_string(&cfg->fmt_patch_suffix, var, value);
83024d98 1108 }
ae6c098f
SD
1109 if (!strcmp(var, "format.to")) {
1110 if (!value)
1111 return config_error_nonbool(var);
83024d98 1112 string_list_append(&cfg->extra_to, value);
ae6c098f
SD
1113 return 0;
1114 }
fe8928e6
MV
1115 if (!strcmp(var, "format.cc")) {
1116 if (!value)
1117 return config_error_nonbool(var);
83024d98 1118 string_list_append(&cfg->extra_cc, value);
fe8928e6
MV
1119 return 0;
1120 }
787570c7 1121 if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff") ||
339de508 1122 !strcmp(var, "color.ui") || !strcmp(var, "diff.submodule")) {
f3aafa4d
RA
1123 return 0;
1124 }
49604a4d 1125 if (!strcmp(var, "format.numbered")) {
90f5c186 1126 if (value && !strcasecmp(value, "auto")) {
83024d98 1127 cfg->auto_number = 1;
49604a4d
BG
1128 return 0;
1129 }
83024d98
PS
1130 cfg->numbered = git_config_bool(var, value);
1131 cfg->auto_number = cfg->auto_number && cfg->numbered;
49604a4d
BG
1132 return 0;
1133 }
0db5260b 1134 if (!strcmp(var, "format.attach")) {
83024d98
PS
1135 if (value && *value) {
1136 FREE_AND_NULL(cfg->default_attach);
1137 cfg->default_attach = xstrdup(value);
1138 } else if (value && !*value) {
1139 FREE_AND_NULL(cfg->default_attach);
1140 } else {
1141 FREE_AND_NULL(cfg->default_attach);
1142 cfg->default_attach = xstrdup(git_version_string);
1143 }
0db5260b
JW
1144 return 0;
1145 }
30984ed2
TR
1146 if (!strcmp(var, "format.thread")) {
1147 if (value && !strcasecmp(value, "deep")) {
83024d98 1148 cfg->thread = THREAD_DEEP;
30984ed2
TR
1149 return 0;
1150 }
1151 if (value && !strcasecmp(value, "shallow")) {
83024d98 1152 cfg->thread = THREAD_SHALLOW;
30984ed2
TR
1153 return 0;
1154 }
83024d98 1155 cfg->thread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;
30984ed2
TR
1156 return 0;
1157 }
1d1876e9 1158 if (!strcmp(var, "format.signoff")) {
83024d98 1159 cfg->do_signoff = git_config_bool(var, value);
1d1876e9
HV
1160 return 0;
1161 }
83024d98
PS
1162 if (!strcmp(var, "format.signature")) {
1163 FREE_AND_NULL(cfg->signature);
1b261c20 1164 return git_config_string(&cfg->signature, var, value);
83024d98
PS
1165 }
1166 if (!strcmp(var, "format.signaturefile")) {
1167 FREE_AND_NULL(cfg->signature_file);
1168 return git_config_pathname(&cfg->signature_file, var, value);
1169 }
2a4c2607
FC
1170 if (!strcmp(var, "format.coverletter")) {
1171 if (value && !strcasecmp(value, "auto")) {
83024d98 1172 cfg->config_cover_letter = COVER_AUTO;
2a4c2607
FC
1173 return 0;
1174 }
83024d98 1175 cfg->config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;
2a4c2607
FC
1176 return 0;
1177 }
83024d98
PS
1178 if (!strcmp(var, "format.outputdirectory")) {
1179 FREE_AND_NULL(cfg->config_output_directory);
1b261c20 1180 return git_config_string(&cfg->config_output_directory, var, value);
83024d98 1181 }
bb52995f 1182 if (!strcmp(var, "format.useautobase")) {
7efba5fa 1183 if (value && !strcasecmp(value, "whenAble")) {
83024d98 1184 cfg->auto_base = AUTO_BASE_WHEN_ABLE;
7efba5fa
JK
1185 return 0;
1186 }
83024d98 1187 cfg->auto_base = git_config_bool(var, value) ? AUTO_BASE_ALWAYS : AUTO_BASE_NEVER;
bb52995f
XY
1188 return 0;
1189 }
6bc6b6c0 1190 if (!strcmp(var, "format.from")) {
89576613 1191 int b = git_parse_maybe_bool(value);
83024d98 1192 FREE_AND_NULL(cfg->from);
6bc6b6c0 1193 if (b < 0)
83024d98 1194 cfg->from = xstrdup(value);
6bc6b6c0 1195 else if (b)
83024d98 1196 cfg->from = xstrdup(git_committer_info(IDENT_NO_DATE));
6bc6b6c0
JT
1197 return 0;
1198 }
d5fc07df
JH
1199 if (!strcmp(var, "format.forceinbodyfrom")) {
1200 force_in_body_from = git_config_bool(var, value);
1201 return 0;
1202 }
13cdf780 1203 if (!strcmp(var, "format.notes")) {
13cdf780 1204 int b = git_parse_maybe_bool(value);
1d729751 1205 if (b < 0)
83024d98 1206 enable_ref_display_notes(&cfg->notes_opt, &cfg->show_notes, value);
1d729751 1207 else if (b)
83024d98 1208 enable_default_display_notes(&cfg->notes_opt, &cfg->show_notes);
1d729751 1209 else
83024d98 1210 disable_display_notes(&cfg->notes_opt, &cfg->show_notes);
13cdf780
DL
1211 return 0;
1212 }
bf8e65b3 1213 if (!strcmp(var, "format.coverfromdescription")) {
83024d98 1214 cfg->cover_from_description_mode = parse_cover_from_description(value);
bf8e65b3
DL
1215 return 0;
1216 }
4810946f
EW
1217 if (!strcmp(var, "format.mboxrd")) {
1218 stdout_mboxrd = git_config_bool(var, value);
1219 return 0;
1220 }
8d5213de
JK
1221 if (!strcmp(var, "format.noprefix")) {
1222 format_no_prefix = 1;
1223 return 0;
1224 }
dbd21447 1225
c169af8f
JK
1226 /*
1227 * ignore some porcelain config which would otherwise be parsed by
1228 * git_diff_ui_config(), via git_log_config(); we can't just avoid
1229 * diff_ui_config completely, because we do care about some ui options
1230 * like color.
1231 */
1232 if (!strcmp(var, "diff.noprefix"))
1233 return 0;
dbd21447 1234
83024d98 1235 return git_log_config(var, value, ctx, &cfg->log);
20ff0680
JS
1236}
1237
efd02016 1238static const char *output_directory = NULL;
9800a754 1239static int outdir_offset;
81f3a188 1240
95235f5b 1241static int open_next_file(struct commit *commit, const char *subject,
a21c2f94 1242 struct rev_info *rev, int quiet)
0377db77 1243{
cd2ef591 1244 struct strbuf filename = STRBUF_INIT;
0377db77 1245
2448482b 1246 if (output_directory) {
cd2ef591 1247 strbuf_addstr(&filename, output_directory);
00b6c178 1248 strbuf_complete(&filename, '/');
2448482b 1249 }
0377db77 1250
38ec23ac
JH
1251 if (rev->numbered_files)
1252 strbuf_addf(&filename, "%d", rev->nr);
d28b5d47
JH
1253 else if (commit)
1254 fmt_output_commit(&filename, commit, rev);
38ec23ac 1255 else
d28b5d47 1256 fmt_output_subject(&filename, subject, rev);
e6ff0f42 1257
250087f2 1258 if (!quiet)
36a4d905 1259 printf("%s\n", filename.buf + outdir_offset);
ec2956df 1260
afe8a907 1261 if (!(rev->diffopt.file = fopen(filename.buf, "w"))) {
bc208ae3 1262 error_errno(_("cannot open patch file %s"), filename.buf);
15d980a7
NTND
1263 strbuf_release(&filename);
1264 return -1;
1265 }
c06d2daa 1266
cd2ef591 1267 strbuf_release(&filename);
e6ff0f42 1268 return 0;
0377db77
JS
1269}
1270
811929f1 1271static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
9c6efa36
JS
1272{
1273 struct rev_info check_rev;
9b7a61d7 1274 struct commit *commit, *c1, *c2;
9c6efa36
JS
1275 struct object *o1, *o2;
1276 unsigned flags1, flags2;
9c6efa36
JS
1277
1278 if (rev->pending.nr != 2)
bc208ae3 1279 die(_("need exactly one range"));
9c6efa36
JS
1280
1281 o1 = rev->pending.objects[0].item;
9c6efa36 1282 o2 = rev->pending.objects[1].item;
9b7a61d7 1283 flags1 = o1->flags;
9c6efa36 1284 flags2 = o2->flags;
2122f675
SB
1285 c1 = lookup_commit_reference(the_repository, &o1->oid);
1286 c2 = lookup_commit_reference(the_repository, &o2->oid);
9c6efa36
JS
1287
1288 if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
bc208ae3 1289 die(_("not a range"));
9c6efa36 1290
a7edadda 1291 init_patch_ids(the_repository, ids);
9c6efa36
JS
1292
1293 /* given a range a..b get all patch ids for b..a */
2abf3503 1294 repo_init_revisions(the_repository, &check_rev, rev->prefix);
51f4de3a 1295 check_rev.max_parents = 1;
9c6efa36
JS
1296 o1->flags ^= UNINTERESTING;
1297 o2->flags ^= UNINTERESTING;
1298 add_pending_object(&check_rev, o1, "o1");
1299 add_pending_object(&check_rev, o2, "o2");
3d51e1b5 1300 if (prepare_revision_walk(&check_rev))
5c5f1d7c 1301 die(_("revision walk setup failed"));
9c6efa36
JS
1302
1303 while ((commit = get_revision(&check_rev)) != NULL) {
5d23e133 1304 add_commit_patch_id(commit, ids);
9c6efa36
JS
1305 }
1306
1307 /* reset for next revision walk */
9b7a61d7
JH
1308 clear_commit_marks(c1, SEEN | UNINTERESTING | SHOWN | ADDED);
1309 clear_commit_marks(c2, SEEN | UNINTERESTING | SHOWN | ADDED);
9c6efa36
JS
1310 o1->flags = flags1;
1311 o2->flags = flags2;
1312}
1313
b567004b 1314static void gen_message_id(struct rev_info *info, const char *base)
d1566f78 1315{
f285a2d7 1316 struct strbuf buf = STRBUF_INIT;
cb71f8bd 1317 strbuf_addf(&buf, "%s.%"PRItime".git.%s", base,
dddbad72 1318 (timestamp_t) time(NULL),
59f9b8a9 1319 git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT));
e1a37346 1320 info->message_id = strbuf_detach(&buf, NULL);
d1566f78
JT
1321}
1322
83024d98 1323static void print_signature(const char *signature, FILE *file)
6622d9c7 1324{
c6076e2b
JK
1325 if (!signature || !*signature)
1326 return;
1327
95235f5b 1328 fprintf(file, "-- \n%s", signature);
c6076e2b 1329 if (signature[strlen(signature)-1] != '\n')
95235f5b
JS
1330 putc('\n', file);
1331 putc('\n', file);
6622d9c7
SB
1332}
1333
d7ddad01
FC
1334static char *find_branch_name(struct rev_info *rev)
1335{
f2fd0760 1336 struct object_id branch_oid;
1337 const struct object_id *tip_oid;
95b567c7 1338 const char *ref, *v;
d7ddad01 1339 char *full_ref, *branch = NULL;
1ab59481
PS
1340 int interesting_found = 0;
1341 size_t idx;
d7ddad01 1342
1ab59481 1343 for (size_t i = 0; i < rev->cmdline.nr; i++) {
d7ddad01
FC
1344 if (rev->cmdline.rev[i].flags & UNINTERESTING)
1345 continue;
1ab59481 1346 if (interesting_found)
d7ddad01 1347 return NULL;
1ab59481
PS
1348 interesting_found = 1;
1349 idx = i;
d7ddad01 1350 }
1ab59481 1351 if (!interesting_found)
d7ddad01 1352 return NULL;
1ab59481
PS
1353 ref = rev->cmdline.rev[idx].name;
1354 tip_oid = &rev->cmdline.rev[idx].item->oid;
12cb1c10
ÆAB
1355 if (repo_dwim_ref(the_repository, ref, strlen(ref), &branch_oid,
1356 &full_ref, 0) &&
95b567c7 1357 skip_prefix(full_ref, "refs/heads/", &v) &&
4a7e27e9 1358 oideq(tip_oid, &branch_oid))
95b567c7 1359 branch = xstrdup(v);
d7ddad01
FC
1360 free(full_ref);
1361 return branch;
1362}
1363
fa5b7ea6
ES
1364static void show_diffstat(struct rev_info *rev,
1365 struct commit *origin, struct commit *head)
1366{
1367 struct diff_options opts;
1368
1369 memcpy(&opts, &rev->diffopt, sizeof(opts));
1370 opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
fa5b7ea6
ES
1371 diff_setup_done(&opts);
1372
1373 diff_tree_oid(get_commit_tree_oid(origin),
1374 get_commit_tree_oid(head),
1375 "", &opts);
1376 diffcore_std(&opts);
1377 diff_flush(&opts);
1378
1379 fprintf(rev->diffopt.file, "\n");
1380}
1381
67f4b36e
OB
1382static void read_desc_file(struct strbuf *buf, const char *desc_file)
1383{
1384 if (strbuf_read_file(buf, desc_file, 0) < 0)
1385 die_errno(_("unable to read branch description file '%s'"),
1386 desc_file);
1387}
1388
bf8e65b3 1389static void prepare_cover_text(struct pretty_print_context *pp,
67f4b36e 1390 const char *description_file,
bf8e65b3
DL
1391 const char *branch_name,
1392 struct strbuf *sb,
1393 const char *encoding,
83024d98
PS
1394 int need_8bit_cte,
1395 const struct format_config *cfg)
bf8e65b3
DL
1396{
1397 const char *subject = "*** SUBJECT HERE ***";
1398 const char *body = "*** BLURB HERE ***";
1399 struct strbuf description_sb = STRBUF_INIT;
1400 struct strbuf subject_sb = STRBUF_INIT;
1401
83024d98 1402 if (cfg->cover_from_description_mode == COVER_FROM_NONE)
bf8e65b3
DL
1403 goto do_pp;
1404
67f4b36e
OB
1405 if (description_file && *description_file)
1406 read_desc_file(&description_sb, description_file);
1407 else if (branch_name && *branch_name)
bf8e65b3
DL
1408 read_branch_desc(&description_sb, branch_name);
1409 if (!description_sb.len)
1410 goto do_pp;
1411
83024d98
PS
1412 if (cfg->cover_from_description_mode == COVER_FROM_SUBJECT ||
1413 cfg->cover_from_description_mode == COVER_FROM_AUTO)
bf8e65b3
DL
1414 body = format_subject(&subject_sb, description_sb.buf, " ");
1415
83024d98
PS
1416 if (cfg->cover_from_description_mode == COVER_FROM_MESSAGE ||
1417 (cfg->cover_from_description_mode == COVER_FROM_AUTO &&
1418 subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))
bf8e65b3
DL
1419 body = description_sb.buf;
1420 else
1421 subject = subject_sb.buf;
1422
1423do_pp:
69aff620 1424 pp_email_subject(pp, &subject, sb, encoding, need_8bit_cte);
bf8e65b3
DL
1425 pp_remainder(pp, &body, sb, 0);
1426
1427 strbuf_release(&description_sb);
1428 strbuf_release(&subject_sb);
1429}
1430
5b583e6a
DL
1431static int get_notes_refs(struct string_list_item *item, void *arg)
1432{
22f9b7f3 1433 strvec_pushf(arg, "--notes=%s", item->string);
5b583e6a
DL
1434 return 0;
1435}
1436
22f9b7f3 1437static void get_notes_args(struct strvec *arg, struct rev_info *rev)
5b583e6a
DL
1438{
1439 if (!rev->show_notes) {
22f9b7f3 1440 strvec_push(arg, "--no-notes");
5b583e6a
DL
1441 } else if (rev->notes_opt.use_default_notes > 0 ||
1442 (rev->notes_opt.use_default_notes == -1 &&
1443 !rev->notes_opt.extra_notes_refs.nr)) {
22f9b7f3 1444 strvec_push(arg, "--notes");
5b583e6a
DL
1445 } else {
1446 for_each_string_list(&rev->notes_opt.extra_notes_refs, get_notes_refs, arg);
1447 }
1448}
1449
1e1693b2 1450static void make_cover_letter(struct rev_info *rev, int use_separate_file,
2bda2cf4 1451 struct commit *origin,
d7ddad01 1452 int nr, struct commit **list,
67f4b36e 1453 const char *description_file,
739453a3 1454 const char *branch_name,
83024d98
PS
1455 int quiet,
1456 const struct format_config *cfg)
a5a27c79
DB
1457{
1458 const char *committer;
2bda2cf4 1459 struct shortlog log;
f285a2d7 1460 struct strbuf sb = STRBUF_INIT;
2bda2cf4 1461 int i;
330db18c 1462 const char *encoding = "UTF-8";
267123b4 1463 int need_8bit_cte = 0;
6bf13944 1464 struct pretty_print_context pp = {0};
d7ddad01 1465 struct commit *head = list[0];
7935a026 1466 char *to_free = NULL;
a5a27c79 1467
9f23e040 1468 if (!cmit_fmt_is_mail(rev->commit_format))
bc208ae3 1469 die(_("cover letter needs email format"));
a5a27c79 1470
cd2ef591 1471 committer = git_committer_info(0);
6df514af 1472
1e1693b2 1473 if (use_separate_file &&
95235f5b 1474 open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
2fe95f49 1475 die(_("failed to create cover-letter file"));
a5a27c79 1476
50cd54ef 1477 log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
a5a27c79 1478
bc6b8fc1 1479 for (i = 0; !need_8bit_cte && i < nr; i++) {
ecb5091f
ÆAB
1480 const char *buf = repo_get_commit_buffer(the_repository,
1481 list[i], NULL);
bc6b8fc1 1482 if (has_non_ascii(buf))
0a7f4483 1483 need_8bit_cte = 1;
ecb5091f 1484 repo_unuse_commit_buffer(the_repository, list[i], buf);
bc6b8fc1 1485 }
0a7f4483 1486
d7ddad01 1487 if (!branch_name)
7935a026 1488 branch_name = to_free = find_branch_name(rev);
d7ddad01 1489
6bf13944 1490 pp.fmt = CMIT_FMT_EMAIL;
a5481a6c 1491 pp.date_mode.type = DATE_RFC2822;
6d167fd7 1492 pp.rev = rev;
219d54ae 1493 pp.encode_email_headers = rev->encode_email_headers;
6bf13944 1494 pp_user_info(&pp, NULL, &sb, committer, encoding);
67f4b36e 1495 prepare_cover_text(&pp, description_file, branch_name, &sb,
83024d98 1496 encoding, need_8bit_cte, cfg);
95235f5b 1497 fprintf(rev->diffopt.file, "%s\n", sb.buf);
a5a27c79 1498
7935a026 1499 free(to_free);
305a6814 1500 free(pp.after_subject);
a5a27c79
DB
1501 strbuf_release(&sb);
1502
2bda2cf4 1503 shortlog_init(&log);
859c4fbe 1504 log.wrap_lines = 1;
43662b23 1505 log.wrap = MAIL_DEFAULT_WRAP;
859c4fbe
JS
1506 log.in1 = 2;
1507 log.in2 = 4;
95235f5b 1508 log.file = rev->diffopt.file;
63d24fa0 1509 log.groups = SHORTLOG_GROUP_AUTHOR;
10538e2a 1510 shortlog_finish_setup(&log);
2bda2cf4
DB
1511 for (i = 0; i < nr; i++)
1512 shortlog_add_commit(&log, list[i]);
1513
1514 shortlog_output(&log);
1515
fa5b7ea6
ES
1516 /* We can only do diffstat with a unique reference point */
1517 if (origin)
1518 show_diffstat(rev, origin, head);
a5a27c79 1519
126facf8 1520 if (rev->idiff_oid1) {
5ac290f9 1521 fprintf_ln(rev->diffopt.file, "%s", rev->idiff_title);
72a72390
ES
1522 show_interdiff(rev->idiff_oid1, rev->idiff_oid2, 0,
1523 &rev->diffopt);
126facf8 1524 }
31e2617a
ES
1525
1526 if (rev->rdiff1) {
ac0edf1f
1527 /*
1528 * Pass minimum required diff-options to range-diff; others
1529 * can be added later if deemed desirable.
1530 */
1531 struct diff_options opts;
22f9b7f3 1532 struct strvec other_arg = STRVEC_INIT;
f1ce6c19
JS
1533 struct range_diff_options range_diff_opts = {
1534 .creation_factor = rev->creation_factor,
1535 .dual_color = 1,
1536 .diffopt = &opts,
1537 .other_arg = &other_arg
1538 };
1539
08539032 1540 repo_diff_setup(the_repository, &opts);
ac0edf1f
1541 opts.file = rev->diffopt.file;
1542 opts.use_color = rev->diffopt.use_color;
1543 diff_setup_done(&opts);
4ee99689 1544 fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title);
5b583e6a 1545 get_notes_args(&other_arg, rev);
f1ce6c19 1546 show_range_diff(rev->rdiff1, rev->rdiff2, &range_diff_opts);
22f9b7f3 1547 strvec_clear(&other_arg);
31e2617a 1548 }
d1566f78
JT
1549}
1550
c6d26a9d 1551static char *clean_message_id(const char *msg_id)
8419d2ee
JH
1552{
1553 char ch;
1554 const char *a, *z, *m;
8419d2ee
JH
1555
1556 m = msg_id;
1557 while ((ch = *m) && (isspace(ch) || (ch == '<')))
1558 m++;
1559 a = m;
1560 z = NULL;
1561 while ((ch = *m)) {
1562 if (!isspace(ch) && (ch != '>'))
1563 z = m;
1564 m++;
1565 }
1566 if (!z)
5c5f1d7c 1567 die(_("insane in-reply-to: %s"), msg_id);
8419d2ee 1568 if (++z == m)
c6d26a9d 1569 return xstrdup(a);
182af834 1570 return xmemdupz(a, z - a);
8419d2ee
JH
1571}
1572
9800a754
JH
1573static const char *set_outdir(const char *prefix, const char *output_directory)
1574{
1575 if (output_directory && is_absolute_path(output_directory))
1576 return output_directory;
1577
1578 if (!prefix || !*prefix) {
1579 if (output_directory)
1580 return output_directory;
1581 /* The user did not explicitly ask for "./" */
1582 outdir_offset = 2;
1583 return "./";
1584 }
1585
1586 outdir_offset = strlen(prefix);
1587 if (!output_directory)
1588 return prefix;
1589
e4da43b1 1590 return prefix_filename(prefix, output_directory);
9800a754
JH
1591}
1592
fff02ee6 1593static const char * const builtin_format_patch_usage[] = {
9c9b4f2f 1594 N_("git format-patch [<options>] [<since> | <revision-range>]"),
fff02ee6
SB
1595 NULL
1596};
1597
83024d98
PS
1598struct keep_callback_data {
1599 struct format_config *cfg;
1600 struct rev_info *revs;
1601};
fff02ee6
SB
1602
1603static int keep_callback(const struct option *opt, const char *arg, int unset)
1604{
83024d98 1605 struct keep_callback_data *data = opt->value;
517fe807
JK
1606 BUG_ON_OPT_NEG(unset);
1607 BUG_ON_OPT_ARG(arg);
83024d98
PS
1608 data->revs->total = -1;
1609 data->cfg->keep_subject = 1;
fff02ee6
SB
1610 return 0;
1611}
1612
fff02ee6
SB
1613static int subject_prefix_callback(const struct option *opt, const char *arg,
1614 int unset)
1615{
83024d98 1616 struct format_config *cfg = opt->value;
e0d7db74 1617
517fe807 1618 BUG_ON_OPT_NEG(unset);
83024d98
PS
1619 cfg->subject_prefix = 1;
1620 strbuf_reset(&cfg->sprefix);
1621 strbuf_addstr(&cfg->sprefix, arg);
fff02ee6
SB
1622 return 0;
1623}
1624
ce48fb2e
JH
1625static int rfc_callback(const struct option *opt, const char *arg,
1626 int unset)
1627{
1628 const char **rfc = opt->value;
1629
1630 *rfc = opt->value;
1631 if (unset)
1632 *rfc = NULL;
1633 else
1634 *rfc = arg ? arg : "RFC";
1635 return 0;
1636}
1637
fff02ee6
SB
1638static int numbered_callback(const struct option *opt, const char *arg,
1639 int unset)
1640{
83024d98 1641 struct format_config *cfg = opt->value;
517fe807 1642 BUG_ON_OPT_ARG(arg);
83024d98 1643 cfg->numbered = cfg->numbered_cmdline_opt = unset ? 0 : 1;
fff02ee6 1644 if (unset)
83024d98 1645 cfg->auto_number = 0;
fff02ee6
SB
1646 return 0;
1647}
1648
1649static int no_numbered_callback(const struct option *opt, const char *arg,
1650 int unset)
1651{
517fe807 1652 BUG_ON_OPT_NEG(unset);
fff02ee6
SB
1653 return numbered_callback(opt, arg, 1);
1654}
1655
1656static int output_directory_callback(const struct option *opt, const char *arg,
1657 int unset)
1658{
1659 const char **dir = (const char **)opt->value;
517fe807 1660 BUG_ON_OPT_NEG(unset);
fff02ee6 1661 if (*dir)
bc208ae3 1662 die(_("two output directories?"));
fff02ee6
SB
1663 *dir = arg;
1664 return 0;
1665}
1666
1667static int thread_callback(const struct option *opt, const char *arg, int unset)
1668{
83024d98
PS
1669 struct format_config *cfg = opt->value;
1670
fff02ee6 1671 if (unset)
83024d98 1672 cfg->thread = THREAD_UNSET;
fff02ee6 1673 else if (!arg || !strcmp(arg, "shallow"))
83024d98 1674 cfg->thread = THREAD_SHALLOW;
fff02ee6 1675 else if (!strcmp(arg, "deep"))
83024d98 1676 cfg->thread = THREAD_DEEP;
5a59a230
NTND
1677 /*
1678 * Please update _git_formatpatch() in git-completion.bash
1679 * when you add new options.
1680 */
fff02ee6
SB
1681 else
1682 return 1;
1683 return 0;
1684}
1685
1686static int attach_callback(const struct option *opt, const char *arg, int unset)
1687{
1688 struct rev_info *rev = (struct rev_info *)opt->value;
1689 if (unset)
1690 rev->mime_boundary = NULL;
1691 else if (arg)
1692 rev->mime_boundary = arg;
1693 else
1694 rev->mime_boundary = git_version_string;
1695 rev->no_inline = unset ? 0 : 1;
1696 return 0;
1697}
1698
1699static int inline_callback(const struct option *opt, const char *arg, int unset)
1700{
1701 struct rev_info *rev = (struct rev_info *)opt->value;
1702 if (unset)
1703 rev->mime_boundary = NULL;
1704 else if (arg)
1705 rev->mime_boundary = arg;
1706 else
1707 rev->mime_boundary = git_version_string;
1708 rev->no_inline = 0;
1709 return 0;
1710}
1711
83024d98 1712static int header_callback(const struct option *opt, const char *arg,
34bf44f2 1713 int unset)
fff02ee6 1714{
83024d98
PS
1715 struct format_config *cfg = opt->value;
1716
c4260034 1717 if (unset) {
83024d98
PS
1718 string_list_clear(&cfg->extra_hdr, 0);
1719 string_list_clear(&cfg->extra_to, 0);
1720 string_list_clear(&cfg->extra_cc, 0);
c4260034 1721 } else {
83024d98 1722 add_header(cfg, arg);
c4260034 1723 }
fff02ee6
SB
1724 return 0;
1725}
1726
a9080475
JK
1727static int from_callback(const struct option *opt, const char *arg, int unset)
1728{
1729 char **from = opt->value;
1730
1731 free(*from);
1732
1733 if (unset)
1734 *from = NULL;
1735 else if (arg)
1736 *from = xstrdup(arg);
1737 else
1738 *from = xstrdup(git_committer_info(IDENT_NO_DATE));
1739 return 0;
1740}
1741
7efba5fa
JK
1742static int base_callback(const struct option *opt, const char *arg, int unset)
1743{
83024d98 1744 struct format_config *cfg = opt->value;
7efba5fa
JK
1745
1746 if (unset) {
83024d98
PS
1747 cfg->auto_base = AUTO_BASE_NEVER;
1748 FREE_AND_NULL(cfg->base_commit);
7efba5fa 1749 } else if (!strcmp(arg, "auto")) {
83024d98
PS
1750 cfg->auto_base = AUTO_BASE_ALWAYS;
1751 FREE_AND_NULL(cfg->base_commit);
7efba5fa 1752 } else {
83024d98
PS
1753 cfg->auto_base = AUTO_BASE_NEVER;
1754 cfg->base_commit = xstrdup(arg);
7efba5fa
JK
1755 }
1756 return 0;
1757}
1758
fa2ab86d
XY
1759struct base_tree_info {
1760 struct object_id base_commit;
1761 int nr_patch_id, alloc_patch_id;
1762 struct object_id *patch_id;
1763};
1764
83024d98 1765static struct commit *get_base_commit(const struct format_config *cfg,
fa2ab86d 1766 struct commit **list,
0905ed20 1767 size_t total)
fa2ab86d
XY
1768{
1769 struct commit *base = NULL;
1770 struct commit **rev;
0905ed20
PS
1771 int auto_select, die_on_failure, ret;
1772 size_t i = 0, rev_nr = 0;
7efba5fa 1773
83024d98 1774 switch (cfg->auto_base) {
7efba5fa 1775 case AUTO_BASE_NEVER:
83024d98 1776 if (cfg->base_commit) {
7efba5fa
JK
1777 auto_select = 0;
1778 die_on_failure = 1;
1779 } else {
1780 /* no base information is requested */
1781 return NULL;
1782 }
1783 break;
1784 case AUTO_BASE_ALWAYS:
1785 case AUTO_BASE_WHEN_ABLE:
83024d98 1786 if (cfg->base_commit) {
7efba5fa
JK
1787 BUG("requested automatic base selection but a commit was provided");
1788 } else {
1789 auto_select = 1;
83024d98 1790 die_on_failure = cfg->auto_base == AUTO_BASE_ALWAYS;
7efba5fa
JK
1791 }
1792 break;
1793 default:
1794 BUG("unexpected automatic base selection method");
1795 }
fa2ab86d 1796
7efba5fa 1797 if (!auto_select) {
83024d98 1798 base = lookup_commit_reference_by_name(cfg->base_commit);
bb52995f 1799 if (!base)
83024d98 1800 die(_("unknown commit %s"), cfg->base_commit);
7efba5fa 1801 } else {
3de66517
XY
1802 struct branch *curr_branch = branch_get(NULL);
1803 const char *upstream = branch_get_upstream(curr_branch, NULL);
1804 if (upstream) {
53173805 1805 struct commit_list *base_list = NULL;
3de66517 1806 struct commit *commit;
d801627b 1807 struct object_id oid;
3de66517 1808
d850b7a5 1809 if (repo_get_oid(the_repository, upstream, &oid)) {
7efba5fa
JK
1810 if (die_on_failure)
1811 die(_("failed to resolve '%s' as a valid ref"), upstream);
1812 else
1813 return NULL;
1814 }
bc83266a 1815 commit = lookup_commit_or_die(&oid, "upstream base");
53173805
JS
1816 if (repo_get_merge_bases_many(the_repository,
1817 commit, total,
1818 list,
1819 &base_list) < 0 ||
1820 /* There should be one and only one merge base. */
1821 !base_list || base_list->next) {
7efba5fa
JK
1822 if (die_on_failure) {
1823 die(_("could not find exact merge base"));
1824 } else {
1825 free_commit_list(base_list);
1826 return NULL;
1827 }
1828 }
3de66517
XY
1829 base = base_list->item;
1830 free_commit_list(base_list);
1831 } else {
7efba5fa
JK
1832 if (die_on_failure)
1833 die(_("failed to get upstream, if you want to record base commit automatically,\n"
1834 "please use git branch --set-upstream-to to track a remote branch.\n"
1835 "Or you could specify base commit by --base=<base-commit-id> manually"));
1836 else
1837 return NULL;
3de66517 1838 }
3de66517 1839 }
fa2ab86d
XY
1840
1841 ALLOC_ARRAY(rev, total);
1842 for (i = 0; i < total; i++)
1843 rev[i] = list[i];
1844
1845 rev_nr = total;
1846 /*
1847 * Get merge base through pair-wise computations
1848 * and store it in rev[0].
1849 */
1850 while (rev_nr > 1) {
1851 for (i = 0; i < rev_nr / 2; i++) {
76e2a099
JS
1852 struct commit_list *merge_base = NULL;
1853 if (repo_get_merge_bases(the_repository,
1854 rev[2 * i],
1855 rev[2 * i + 1], &merge_base) < 0 ||
1856 !merge_base || merge_base->next) {
7efba5fa
JK
1857 if (die_on_failure) {
1858 die(_("failed to find exact merge base"));
1859 } else {
1bc158e7 1860 free_commit_list(merge_base);
7efba5fa
JK
1861 free(rev);
1862 return NULL;
1863 }
1864 }
fa2ab86d
XY
1865
1866 rev[i] = merge_base->item;
1bc158e7 1867 free_commit_list(merge_base);
fa2ab86d
XY
1868 }
1869
1870 if (rev_nr % 2)
1871 rev[i] = rev[2 * i];
42c78a21 1872 rev_nr = DIV_ROUND_UP(rev_nr, 2);
fa2ab86d
XY
1873 }
1874
24876ebf
JS
1875 ret = repo_in_merge_bases(the_repository, base, rev[0]);
1876 if (ret < 0)
1877 exit(128);
1878 if (!ret) {
7efba5fa
JK
1879 if (die_on_failure) {
1880 die(_("base commit should be the ancestor of revision list"));
1881 } else {
1882 free(rev);
1883 return NULL;
1884 }
1885 }
fa2ab86d
XY
1886
1887 for (i = 0; i < total; i++) {
7efba5fa
JK
1888 if (base == list[i]) {
1889 if (die_on_failure) {
1890 die(_("base commit shouldn't be in revision list"));
1891 } else {
1892 free(rev);
1893 return NULL;
1894 }
1895 }
fa2ab86d
XY
1896 }
1897
1898 free(rev);
1899 return base;
1900}
1901
7b680d32
NTND
1902define_commit_slab(commit_base, int);
1903
fa2ab86d
XY
1904static void prepare_bases(struct base_tree_info *bases,
1905 struct commit *base,
1906 struct commit **list,
0905ed20 1907 size_t total)
fa2ab86d
XY
1908{
1909 struct commit *commit;
1910 struct rev_info revs;
1911 struct diff_options diffopt;
7b680d32 1912 struct commit_base commit_base;
fa2ab86d
XY
1913
1914 if (!base)
1915 return;
1916
7b680d32 1917 init_commit_base(&commit_base);
e6757652 1918 repo_diff_setup(the_repository, &diffopt);
0d1e0e78 1919 diffopt.flags.recursive = 1;
fa2ab86d
XY
1920 diff_setup_done(&diffopt);
1921
1922 oidcpy(&bases->base_commit, &base->object.oid);
1923
2abf3503 1924 repo_init_revisions(the_repository, &revs, NULL);
fa2ab86d
XY
1925 revs.max_parents = 1;
1926 revs.topo_order = 1;
0905ed20 1927 for (size_t i = 0; i < total; i++) {
fa2ab86d
XY
1928 list[i]->object.flags &= ~UNINTERESTING;
1929 add_pending_object(&revs, &list[i]->object, "rev_list");
7b680d32 1930 *commit_base_at(&commit_base, list[i]) = 1;
fa2ab86d
XY
1931 }
1932 base->object.flags |= UNINTERESTING;
1933 add_pending_object(&revs, &base->object, "base");
1934
1935 if (prepare_revision_walk(&revs))
1936 die(_("revision walk setup failed"));
1937 /*
1938 * Traverse the commits list, get prerequisite patch ids
1939 * and stuff them in bases structure.
1940 */
1941 while ((commit = get_revision(&revs)) != NULL) {
d801627b 1942 struct object_id oid;
fa2ab86d 1943 struct object_id *patch_id;
7b680d32 1944 if (*commit_base_at(&commit_base, commit))
fa2ab86d 1945 continue;
51276c18 1946 if (commit_patch_id(commit, &diffopt, &oid, 0))
fa2ab86d
XY
1947 die(_("cannot get patch id"));
1948 ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
1949 patch_id = bases->patch_id + bases->nr_patch_id;
d801627b 1950 oidcpy(patch_id, &oid);
fa2ab86d
XY
1951 bases->nr_patch_id++;
1952 }
7b680d32 1953 clear_commit_base(&commit_base);
fa2ab86d
XY
1954}
1955
95235f5b 1956static void print_bases(struct base_tree_info *bases, FILE *file)
fa2ab86d
XY
1957{
1958 int i;
1959
1960 /* Only do this once, either for the cover or for the first one */
1961 if (is_null_oid(&bases->base_commit))
1962 return;
1963
1964 /* Show the base commit */
480871e0 1965 fprintf(file, "\nbase-commit: %s\n", oid_to_hex(&bases->base_commit));
fa2ab86d
XY
1966
1967 /* Show the prerequisite patches */
1968 for (i = bases->nr_patch_id - 1; i >= 0; i--)
95235f5b 1969 fprintf(file, "prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
fa2ab86d
XY
1970
1971 free(bases->patch_id);
1972 bases->nr_patch_id = 0;
1973 bases->alloc_patch_id = 0;
9da95bda 1974 oidclr(&bases->base_commit, the_repository->hash_algo);
fa2ab86d
XY
1975}
1976
db91988a
ZH
1977static const char *diff_title(struct strbuf *sb,
1978 const char *reroll_count,
1979 const char *generic,
1980 const char *rerolled)
5ac290f9 1981{
db91988a
ZH
1982 int v;
1983
1984 /* RFC may be v0, so allow -v1 to diff against v0 */
1985 if (reroll_count && !strtol_i(reroll_count, 10, &v) &&
1986 v >= 1)
1987 strbuf_addf(sb, rerolled, v - 1);
1988 else
5ac290f9 1989 strbuf_addstr(sb, generic);
5ac290f9
ES
1990 return sb->buf;
1991}
1992
31e2617a
ES
1993static void infer_range_diff_ranges(struct strbuf *r1,
1994 struct strbuf *r2,
1995 const char *prev,
2e6fd71a 1996 struct commit *origin,
31e2617a
ES
1997 struct commit *head)
1998{
1999 const char *head_oid = oid_to_hex(&head->object.oid);
679b5916 2000 int prev_is_range = is_range_diff_range(prev);
31e2617a 2001
07a7f8de
ES
2002 if (prev_is_range)
2003 strbuf_addstr(r1, prev);
2004 else
2e6fd71a 2005 strbuf_addf(r1, "%s..%s", head_oid, prev);
07a7f8de
ES
2006
2007 if (origin)
2008 strbuf_addf(r2, "%s..%s", oid_to_hex(&origin->object.oid), head_oid);
2009 else if (prev_is_range)
2010 die(_("failed to infer range-diff origin of current series"));
2011 else {
2012 warning(_("using '%s' as range-diff origin of current series"), prev);
2e6fd71a 2013 strbuf_addf(r2, "%s..%s", prev, head_oid);
2e6fd71a 2014 }
31e2617a
ES
2015}
2016
9b1cb507
JC
2017int cmd_format_patch(int argc,
2018 const char **argv,
2019 const char *prefix,
2020 struct repository *repo UNUSED)
91efcf60 2021{
83024d98 2022 struct format_config cfg;
91efcf60
JH
2023 struct commit *commit;
2024 struct commit **list = NULL;
2025 struct rev_info rev;
89f45cf4 2026 char *to_free = NULL;
32962c9b 2027 struct setup_revision_opt s_r_opt;
0905ed20 2028 size_t nr = 0, total, i;
0377db77 2029 int use_stdout = 0;
fa0f02df 2030 int start_number = -1;
ce37596c 2031 int just_numbers = 0;
9c6efa36 2032 int ignore_if_in_upstream = 0;
2a4c2607 2033 int cover_letter = -1;
2bda2cf4 2034 int boundary_count = 0;
37c22a4b 2035 int no_binary_diff = 0;
3a30aa17 2036 int zero_commit = 0;
d7ddad01 2037 struct commit *origin = NULL;
76af0734 2038 const char *in_reply_to = NULL;
5d23e133 2039 struct patch_ids ids;
f285a2d7 2040 struct strbuf buf = STRBUF_INIT;
1d46f2ea 2041 int use_patch_format = 0;
250087f2 2042 int quiet = 0;
db91988a 2043 const char *reroll_count = NULL;
bf8e65b3 2044 char *cover_from_description_arg = NULL;
67f4b36e 2045 char *description_file = NULL;
739453a3 2046 char *branch_name = NULL;
fa2ab86d 2047 struct base_tree_info bases;
7efba5fa 2048 struct commit *base;
738e88a2
KW
2049 int show_progress = 0;
2050 struct progress *progress = NULL;
126facf8 2051 struct oid_array idiff_prev = OID_ARRAY_INIT;
5ac290f9 2052 struct strbuf idiff_title = STRBUF_INIT;
31e2617a
ES
2053 const char *rdiff_prev = NULL;
2054 struct strbuf rdiff1 = STRBUF_INIT;
2055 struct strbuf rdiff2 = STRBUF_INIT;
4ee99689 2056 struct strbuf rdiff_title = STRBUF_INIT;
ce48fb2e 2057 const char *rfc = NULL;
8631bf1c 2058 int creation_factor = -1;
83024d98 2059 const char *signature = git_version_string;
1bc158e7 2060 char *signature_to_free = NULL;
14da2623 2061 char *signature_file_arg = NULL;
83024d98
PS
2062 struct keep_callback_data keep_callback_data = {
2063 .cfg = &cfg,
2064 .revs = &rev,
2065 };
2066 const char *fmt_patch_suffix = NULL;
fa2ab86d 2067
fff02ee6 2068 const struct option builtin_format_patch_options[] = {
83024d98 2069 OPT_CALLBACK_F('n', "numbered", &cfg, NULL,
61007a58 2070 N_("use [PATCH n/m] even with a single patch"),
203c8533 2071 PARSE_OPT_NOARG, numbered_callback),
83024d98 2072 OPT_CALLBACK_F('N', "no-numbered", &cfg, NULL,
61007a58 2073 N_("use [PATCH] even with multiple patches"),
203c8533 2074 PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback),
83024d98 2075 OPT_BOOL('s', "signoff", &cfg.do_signoff, N_("add a Signed-off-by trailer")),
aa089cd9 2076 OPT_BOOL(0, "stdout", &use_stdout,
61007a58 2077 N_("print patches to standard out")),
aa089cd9 2078 OPT_BOOL(0, "cover-letter", &cover_letter,
61007a58 2079 N_("generate a cover letter")),
aa089cd9 2080 OPT_BOOL(0, "numbered-files", &just_numbers,
61007a58
NTND
2081 N_("use simple number sequence for output file names")),
2082 OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"),
2083 N_("use <sfx> instead of '.patch'")),
fff02ee6 2084 OPT_INTEGER(0, "start-number", &start_number,
61007a58 2085 N_("start numbering patches at <n> instead of 1")),
db91988a 2086 OPT_STRING('v', "reroll-count", &reroll_count, N_("reroll-count"),
5fe10fe8 2087 N_("mark the series as Nth re-roll")),
83024d98 2088 OPT_INTEGER(0, "filename-max-length", &cfg.log.fmt_patch_name_max,
3baf58bf 2089 N_("max length of output filename")),
ce48fb2e
JH
2090 OPT_CALLBACK_F(0, "rfc", &rfc, N_("rfc"),
2091 N_("add <rfc> (default 'RFC') before 'PATCH'"),
2092 PARSE_OPT_OPTARG, rfc_callback),
bf8e65b3
DL
2093 OPT_STRING(0, "cover-from-description", &cover_from_description_arg,
2094 N_("cover-from-description-mode"),
2095 N_("generate parts of a cover letter based on a branch's description")),
67f4b36e
OB
2096 OPT_FILENAME(0, "description-file", &description_file,
2097 N_("use branch description from file")),
83024d98 2098 OPT_CALLBACK_F(0, "subject-prefix", &cfg, N_("prefix"),
e73fe3dd 2099 N_("use [<prefix>] instead of [PATCH]"),
203c8533
DL
2100 PARSE_OPT_NONEG, subject_prefix_callback),
2101 OPT_CALLBACK_F('o', "output-directory", &output_directory,
61007a58 2102 N_("dir"), N_("store resulting files in <dir>"),
203c8533 2103 PARSE_OPT_NONEG, output_directory_callback),
83024d98 2104 OPT_CALLBACK_F('k', "keep-subject", &keep_callback_data, NULL,
61007a58 2105 N_("don't strip/add [PATCH]"),
203c8533 2106 PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback),
d5d09d47
SB
2107 OPT_BOOL(0, "no-binary", &no_binary_diff,
2108 N_("don't output binary diffs")),
3a30aa17 2109 OPT_BOOL(0, "zero-commit", &zero_commit,
2110 N_("output all-zero hash in From header")),
d5d09d47
SB
2111 OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
2112 N_("don't include a patch matching a commit upstream")),
3e4a67b4
NTND
2113 OPT_SET_INT_F('p', "no-stat", &use_patch_format,
2114 N_("show patch format instead of default (patch + stat)"),
2115 1, PARSE_OPT_NONEG),
61007a58 2116 OPT_GROUP(N_("Messaging")),
83024d98 2117 OPT_CALLBACK(0, "add-header", &cfg, N_("header"),
203c8533 2118 N_("add email header"), header_callback),
83024d98
PS
2119 OPT_STRING_LIST(0, "to", &cfg.extra_to, N_("email"), N_("add To: header")),
2120 OPT_STRING_LIST(0, "cc", &cfg.extra_cc, N_("email"), N_("add Cc: header")),
2121 OPT_CALLBACK_F(0, "from", &cfg.from, N_("ident"),
a9080475 2122 N_("set From address to <ident> (or committer ident if absent)"),
203c8533 2123 PARSE_OPT_OPTARG, from_callback),
61007a58
NTND
2124 OPT_STRING(0, "in-reply-to", &in_reply_to, N_("message-id"),
2125 N_("make first mail a reply to <message-id>")),
203c8533 2126 OPT_CALLBACK_F(0, "attach", &rev, N_("boundary"),
61007a58 2127 N_("attach the patch"), PARSE_OPT_OPTARG,
203c8533
DL
2128 attach_callback),
2129 OPT_CALLBACK_F(0, "inline", &rev, N_("boundary"),
61007a58 2130 N_("inline the patch"),
fff02ee6 2131 PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
203c8533 2132 inline_callback),
83024d98 2133 OPT_CALLBACK_F(0, "thread", &cfg, N_("style"),
61007a58 2134 N_("enable message threading, styles: shallow, deep"),
203c8533 2135 PARSE_OPT_OPTARG, thread_callback),
61007a58
NTND
2136 OPT_STRING(0, "signature", &signature, N_("signature"),
2137 N_("add a signature")),
83024d98 2138 OPT_CALLBACK_F(0, "base", &cfg, N_("base-commit"),
7efba5fa
JK
2139 N_("add prerequisite tree info to the patch series"),
2140 0, base_callback),
83024d98 2141 OPT_FILENAME(0, "signature-file", &signature_file_arg,
7022650f 2142 N_("add a signature from a file")),
b7df098c 2143 OPT__QUIET(&quiet, N_("don't print the patch filenames")),
738e88a2
KW
2144 OPT_BOOL(0, "progress", &show_progress,
2145 N_("show progress while generating patches")),
126facf8 2146 OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"),
ee6cbf71 2147 N_("show changes against <rev> in cover letter or single patch"),
126facf8 2148 parse_opt_object_name),
31e2617a 2149 OPT_STRING(0, "range-diff", &rdiff_prev, N_("refspec"),
40ce4160 2150 N_("show changes against <refspec> in cover letter or single patch")),
8631bf1c
ES
2151 OPT_INTEGER(0, "creation-factor", &creation_factor,
2152 N_("percentage by which creation is weighted")),
34bc1b10
JH
2153 OPT_BOOL(0, "force-in-body-from", &force_in_body_from,
2154 N_("show in-body From: even if identical to the e-mail header")),
fff02ee6
SB
2155 OPT_END()
2156 };
91efcf60 2157
83024d98 2158 format_config_init(&cfg);
106a54ae 2159 init_diff_ui_defaults();
83024d98 2160 init_display_notes(&cfg.notes_opt);
106a54ae 2161 git_config(git_format_config, &cfg);
2abf3503 2162 repo_init_revisions(the_repository, &rev, prefix);
72365bb4
ÆAB
2163 git_config(grep_config, &rev.grep_filter);
2164
83024d98
PS
2165 rev.show_notes = cfg.show_notes;
2166 memcpy(&rev.notes_opt, &cfg.notes_opt, sizeof(cfg.notes_opt));
91efcf60 2167 rev.commit_format = CMIT_FMT_EMAIL;
83024d98 2168 rev.encode_email_headers = cfg.log.default_encode_email_headers;
0893eec8 2169 rev.expand_tabs_in_log_default = 0;
91efcf60
JH
2170 rev.verbose_header = 1;
2171 rev.diff = 1;
ad5aeede 2172 rev.max_parents = 1;
0d1e0e78 2173 rev.diffopt.flags.recursive = 1;
91f8f7e4 2174 rev.diffopt.no_free = 1;
32962c9b
JH
2175 memset(&s_r_opt, 0, sizeof(s_r_opt));
2176 s_r_opt.def = "HEAD";
d5f6b1d7 2177 s_r_opt.revarg_opt = REVARG_COMMITTISH;
20ff0680 2178
83024d98 2179 strbuf_addstr(&cfg.sprefix, cfg.log.fmt_patch_subject_prefix);
8d5213de
JK
2180 if (format_no_prefix)
2181 diff_set_noprefix(&rev.diffopt);
2182
83024d98
PS
2183 if (cfg.default_attach) {
2184 rev.mime_boundary = cfg.default_attach;
0db5260b
JW
2185 rev.no_inline = 1;
2186 }
2187
2448482b
JS
2188 /*
2189 * Parse the arguments before setup_revisions(), or something
2dc189a3 2190 * like "git format-patch -o a123 HEAD^.." may fail; a123 is
2448482b
JS
2191 * possibly a valid SHA1.
2192 */
37782920 2193 argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
fff02ee6 2194 builtin_format_patch_usage,
99d86d60 2195 PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT |
382da402 2196 PARSE_OPT_KEEP_DASHDASH);
2448482b 2197
34bc1b10
JH
2198 rev.force_in_body_from = force_in_body_from;
2199
83024d98
PS
2200 if (!fmt_patch_suffix)
2201 fmt_patch_suffix = cfg.fmt_patch_suffix;
2202
3baf58bf 2203 /* Make sure "0000-$sub.patch" gives non-negative length for $sub */
1ab59481 2204 if (cfg.log.fmt_patch_name_max <= cast_size_t_to_int(strlen("0000-") + strlen(fmt_patch_suffix)))
83024d98 2205 cfg.log.fmt_patch_name_max = strlen("0000-") + strlen(fmt_patch_suffix);
3baf58bf 2206
bf8e65b3 2207 if (cover_from_description_arg)
83024d98 2208 cfg.cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
bf8e65b3 2209
ce368945 2210 if (rfc && rfc[0]) {
83024d98 2211 cfg.subject_prefix = 1;
ce368945 2212 if (rfc[0] == '-')
83024d98 2213 strbuf_addf(&cfg.sprefix, " %s", rfc + 1);
ce368945 2214 else
83024d98 2215 strbuf_insertf(&cfg.sprefix, 0, "%s ", rfc);
cadcf580 2216 }
e0d7db74 2217
db91988a 2218 if (reroll_count) {
83024d98 2219 strbuf_addf(&cfg.sprefix, " v%s", reroll_count);
5fe10fe8 2220 rev.reroll_count = reroll_count;
5fe10fe8
JH
2221 }
2222
83024d98 2223 rev.subject_prefix = cfg.sprefix.buf;
e0d7db74 2224
83024d98
PS
2225 for (i = 0; i < cfg.extra_hdr.nr; i++) {
2226 strbuf_addstr(&buf, cfg.extra_hdr.items[i].string);
3ee79d9f
DB
2227 strbuf_addch(&buf, '\n');
2228 }
2229
83024d98 2230 if (cfg.extra_to.nr)
3ee79d9f 2231 strbuf_addstr(&buf, "To: ");
83024d98 2232 for (i = 0; i < cfg.extra_to.nr; i++) {
3ee79d9f
DB
2233 if (i)
2234 strbuf_addstr(&buf, " ");
83024d98
PS
2235 strbuf_addstr(&buf, cfg.extra_to.items[i].string);
2236 if (i + 1 < cfg.extra_to.nr)
3ee79d9f
DB
2237 strbuf_addch(&buf, ',');
2238 strbuf_addch(&buf, '\n');
2239 }
2240
83024d98 2241 if (cfg.extra_cc.nr)
3ee79d9f 2242 strbuf_addstr(&buf, "Cc: ");
83024d98 2243 for (i = 0; i < cfg.extra_cc.nr; i++) {
3ee79d9f
DB
2244 if (i)
2245 strbuf_addstr(&buf, " ");
83024d98
PS
2246 strbuf_addstr(&buf, cfg.extra_cc.items[i].string);
2247 if (i + 1 < cfg.extra_cc.nr)
3ee79d9f
DB
2248 strbuf_addch(&buf, ',');
2249 strbuf_addch(&buf, '\n');
2250 }
2251
89f45cf4 2252 rev.extra_headers = to_free = strbuf_detach(&buf, NULL);
3ee79d9f 2253
83024d98
PS
2254 if (cfg.from) {
2255 if (split_ident_line(&rev.from_ident, cfg.from, strlen(cfg.from)))
2256 die(_("invalid ident line: %s"), cfg.from);
a9080475
JK
2257 }
2258
add5c8a5 2259 if (start_number < 0)
fa0f02df 2260 start_number = 1;
ca6b91d2
JM
2261
2262 /*
2263 * If numbered is set solely due to format.numbered in config,
2264 * and it would conflict with --keep-subject (-k) from the
2265 * command line, reset "numbered".
2266 */
83024d98
PS
2267 if (cfg.numbered && cfg.keep_subject && !cfg.numbered_cmdline_opt)
2268 cfg.numbered = 0;
ca6b91d2 2269
83024d98 2270 if (cfg.numbered && cfg.keep_subject)
43ea635c 2271 die(_("options '%s' and '%s' cannot be used together"), "-n", "-k");
83024d98 2272 if (cfg.keep_subject && cfg.subject_prefix)
43ea635c 2273 die(_("options '%s' and '%s' cannot be used together"), "--subject-prefix/--rfc", "-k");
83024d98 2274 rev.preserve_subject = cfg.keep_subject;
8ac80a57 2275
32962c9b 2276 argc = setup_revisions(argc, argv, &rev, &s_r_opt);
2448482b 2277 if (argc > 1)
1a07e59c 2278 die(_("unrecognized argument: %s"), argv[1]);
0377db77 2279
02bc5b03 2280 if (rev.diffopt.output_format & DIFF_FORMAT_NAME)
f338cb83 2281 die(_("--name-only does not make sense"));
02bc5b03 2282 if (rev.diffopt.output_format & DIFF_FORMAT_NAME_STATUS)
f338cb83 2283 die(_("--name-status does not make sense"));
02bc5b03 2284 if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF)
f338cb83 2285 die(_("--check does not make sense"));
db757e8b
EN
2286 if (rev.remerge_diff)
2287 die(_("--remerge-diff does not make sense"));
02bc5b03
BG
2288
2289 if (!use_patch_format &&
2290 (!rev.diffopt.output_format ||
2291 rev.diffopt.output_format == DIFF_FORMAT_PATCH))
2292 rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY;
071dd0ba
NTND
2293 if (!rev.diffopt.stat_width)
2294 rev.diffopt.stat_width = MAIL_DEFAULT_WRAP;
02bc5b03
BG
2295
2296 /* Always generate a patch */
2297 rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
94c42894 2298 rev.always_show_header = 1;
c9b5ef99 2299
3a30aa17 2300 rev.zero_commit = zero_commit;
83024d98 2301 rev.patch_name_max = cfg.log.fmt_patch_name_max;
3a30aa17 2302
0d1e0e78
BW
2303 if (!rev.diffopt.flags.text && !no_binary_diff)
2304 rev.diffopt.flags.binary = 1;
e47f306d 2305
894a9d33 2306 if (rev.show_notes)
1e6ed544 2307 load_display_notes(&rev.notes_opt);
894a9d33 2308
a699367b
JNA
2309 die_for_incompatible_opt3(use_stdout, "--stdout",
2310 rev.diffopt.close_file, "--output",
2311 !!output_directory, "--output-directory");
bc6bf2d7 2312
4810946f
EW
2313 if (use_stdout && stdout_mboxrd)
2314 rev.commit_format = CMIT_FMT_MBOXRD;
2315
4c6f781f 2316 if (use_stdout) {
59b6131a 2317 setup_pager(the_repository);
91f8f7e4 2318 } else if (!rev.diffopt.close_file) {
edefc318 2319 int saved;
4c6f781f
JK
2320
2321 if (!output_directory)
83024d98 2322 output_directory = cfg.config_output_directory;
4c6f781f
JK
2323 output_directory = set_outdir(prefix, output_directory);
2324
11f4eb19
JS
2325 if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
2326 rev.diffopt.use_color = GIT_COLOR_NEVER;
edefc318
BW
2327 /*
2328 * We consider <outdir> as 'outside of gitdir', therefore avoid
2329 * applying adjust_shared_perm in s-c-l-d.
2330 */
f1ce861c
PS
2331 saved = repo_settings_get_shared_repository(the_repository);
2332 repo_settings_set_shared_repository(the_repository, 0);
1a99fe80 2333 switch (safe_create_leading_directories_const(the_repository, output_directory)) {
edefc318
BW
2334 case SCLD_OK:
2335 case SCLD_EXISTS:
2336 break;
2337 default:
2338 die(_("could not create leading directories "
2339 "of '%s'"), output_directory);
2340 }
f1ce861c 2341 repo_settings_set_shared_repository(the_repository, saved);
efd02016 2342 if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
bc208ae3 2343 die_errno(_("could not create directory '%s'"),
0721c314 2344 output_directory);
efd02016
JH
2345 }
2346
1f1e895f 2347 if (rev.pending.nr == 1) {
427a8ec5
FC
2348 int check_head = 0;
2349
8a1d076e
JH
2350 if (rev.max_count < 0 && !rev.show_root_diff) {
2351 /*
2352 * This is traditional behaviour of "git format-patch
2353 * origin" that prepares what the origin side still
2354 * does not have.
2355 */
7c496280 2356 rev.pending.objects[0].item->flags |= UNINTERESTING;
3384a2df 2357 add_head_to_pending(&rev);
427a8ec5 2358 check_head = 1;
7c496280 2359 }
8a1d076e
JH
2360 /*
2361 * Otherwise, it is "format-patch -22 HEAD", and/or
2362 * "format-patch --root HEAD". The user wants
2363 * get_revision() to do the usual traversal.
7c496280 2364 */
427a8ec5
FC
2365
2366 if (!strcmp(rev.pending.objects[0].name, "HEAD"))
2367 check_head = 1;
2368
2369 if (check_head) {
95b567c7 2370 const char *ref, *v;
2e5c4758
PS
2371 ref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
2372 "HEAD",
2373 RESOLVE_REF_READING,
2374 NULL, NULL);
95b567c7
JK
2375 if (ref && skip_prefix(ref, "refs/heads/", &v))
2376 branch_name = xstrdup(v);
427a8ec5
FC
2377 else
2378 branch_name = xstrdup(""); /* no branch */
2379 }
e686eb98 2380 }
68c2ec7f
JH
2381
2382 /*
2383 * We cannot move this anywhere earlier because we do want to
9517e6b8 2384 * know if --root was given explicitly from the command line.
68c2ec7f
JH
2385 */
2386 rev.show_root_diff = 1;
2387
657ab61e
KB
2388 if (ignore_if_in_upstream) {
2389 /* Don't say anything if head and upstream are the same. */
2390 if (rev.pending.nr == 2) {
2391 struct object_array_entry *o = rev.pending.objects;
4a7e27e9 2392 if (oideq(&o[0].item->oid, &o[1].item->oid))
126facf8 2393 goto done;
657ab61e 2394 }
811929f1 2395 get_patch_ids(&rev, &ids);
657ab61e 2396 }
9c6efa36 2397
3d51e1b5 2398 if (prepare_revision_walk(&rev))
5c5f1d7c 2399 die(_("revision walk setup failed"));
2bda2cf4 2400 rev.boundary = 1;
91efcf60 2401 while ((commit = get_revision(&rev)) != NULL) {
2bda2cf4 2402 if (commit->object.flags & BOUNDARY) {
2bda2cf4
DB
2403 boundary_count++;
2404 origin = (boundary_count == 1) ? commit : NULL;
2405 continue;
2406 }
2407
3acf8dd8 2408 if (ignore_if_in_upstream && has_commit_patch_id(commit, &ids))
9c6efa36
JS
2409 continue;
2410
91efcf60 2411 nr++;
2756ca43 2412 REALLOC_ARRAY(list, nr);
91efcf60
JH
2413 list[nr - 1] = commit;
2414 }
80d35ca0
FC
2415 if (nr == 0)
2416 /* nothing to do */
126facf8 2417 goto done;
0377db77 2418 total = nr;
2a4c2607 2419 if (cover_letter == -1) {
83024d98 2420 if (cfg.config_cover_letter == COVER_AUTO)
2a4c2607 2421 cover_letter = (total > 1);
f96c3854 2422 else if ((idiff_prev.nr || rdiff_prev) && (total > 1))
9071453e 2423 cover_letter = (cfg.config_cover_letter != COVER_OFF);
2a4c2607 2424 else
83024d98 2425 cover_letter = (cfg.config_cover_letter == COVER_ON);
2a4c2607 2426 }
83024d98
PS
2427 if (!cfg.keep_subject && cfg.auto_number && (total > 1 || cover_letter))
2428 cfg.numbered = 1;
2429 if (cfg.numbered)
957ed3a5 2430 rev.total = total + start_number - 1;
2a4c2607 2431
126facf8 2432 if (idiff_prev.nr) {
ee6cbf71
ES
2433 if (!cover_letter && total != 1)
2434 die(_("--interdiff requires --cover-letter or single patch"));
126facf8
ES
2435 rev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1];
2436 rev.idiff_oid2 = get_commit_tree_oid(list[0]);
5ac290f9
ES
2437 rev.idiff_title = diff_title(&idiff_title, reroll_count,
2438 _("Interdiff:"),
2439 _("Interdiff against v%d:"));
126facf8
ES
2440 }
2441
8631bf1c 2442 if (creation_factor < 0)
c22d41d6 2443 creation_factor = CREATION_FACTOR_FOR_THE_SAME_SERIES;
8631bf1c 2444 else if (!rdiff_prev)
6fa00ee8 2445 die(_("the option '%s' requires '%s'"), "--creation-factor", "--range-diff");
8631bf1c 2446
31e2617a 2447 if (rdiff_prev) {
40ce4160
ES
2448 if (!cover_letter && total != 1)
2449 die(_("--range-diff requires --cover-letter or single patch"));
31e2617a 2450
2e6fd71a
ES
2451 infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev,
2452 origin, list[0]);
31e2617a
ES
2453 rev.rdiff1 = rdiff1.buf;
2454 rev.rdiff2 = rdiff2.buf;
8631bf1c 2455 rev.creation_factor = creation_factor;
4ee99689
ES
2456 rev.rdiff_title = diff_title(&rdiff_title, reroll_count,
2457 _("Range-diff:"),
2458 _("Range-diff against v%d:"));
31e2617a
ES
2459 }
2460
83024d98
PS
2461 /*
2462 * The order of precedence is:
2463 *
2464 * 1. The `--signature` and `--no-signature` options.
2465 * 2. The `--signature-file` option.
2466 * 3. The `format.signature` config.
2467 * 4. The `format.signatureFile` config.
2468 * 5. Default `git_version_string`.
2469 */
7022650f
JM
2470 if (!signature) {
2471 ; /* --no-signature inhibits all signatures */
2472 } else if (signature && signature != git_version_string) {
2473 ; /* non-default signature already set */
83024d98 2474 } else if (signature_file_arg || (cfg.signature_file && !cfg.signature)) {
7022650f 2475 struct strbuf buf = STRBUF_INIT;
83024d98
PS
2476 const char *signature_file = signature_file_arg ?
2477 signature_file_arg : cfg.signature_file;
7022650f
JM
2478
2479 if (strbuf_read_file(&buf, signature_file, 128) < 0)
2480 die_errno(_("unable to read signature file '%s'"), signature_file);
1bc158e7 2481 signature = signature_to_free = strbuf_detach(&buf, NULL);
83024d98
PS
2482 } else if (cfg.signature) {
2483 signature = cfg.signature;
7022650f
JM
2484 }
2485
fa2ab86d 2486 memset(&bases, 0, sizeof(bases));
83024d98 2487 base = get_base_commit(&cfg, list, nr);
7efba5fa 2488 if (base) {
fa2ab86d 2489 reset_revision_walk();
74d414c9 2490 clear_object_flags(the_repository, UNINTERESTING);
fa2ab86d
XY
2491 prepare_bases(&bases, base, list, nr);
2492 }
2493
83024d98 2494 if (in_reply_to || cfg.thread || cover_letter) {
f2605051 2495 rev.ref_message_ids = xmalloc(sizeof(*rev.ref_message_ids));
c6d26a9d 2496 string_list_init_dup(rev.ref_message_ids);
f2605051 2497 }
b079c50e 2498 if (in_reply_to) {
c6d26a9d
JK
2499 char *msgid = clean_message_id(in_reply_to);
2500 string_list_append_nodup(rev.ref_message_ids, msgid);
b079c50e 2501 }
ce37596c 2502 rev.numbered_files = just_numbers;
108dab28 2503 rev.patch_suffix = fmt_patch_suffix;
a5a27c79 2504 if (cover_letter) {
83024d98 2505 if (cfg.thread)
a5a27c79 2506 gen_message_id(&rev, "cover");
1e1693b2 2507 make_cover_letter(&rev, !!output_directory,
83024d98 2508 origin, nr, list, description_file, branch_name, quiet, &cfg);
95235f5b 2509 print_bases(&bases, rev.diffopt.file);
83024d98 2510 print_signature(signature, rev.diffopt.file);
a5a27c79
DB
2511 total++;
2512 start_number--;
40ce4160 2513 /* interdiff/range-diff in cover-letter; omit from patches */
ee6cbf71 2514 rev.idiff_oid1 = NULL;
40ce4160 2515 rev.rdiff1 = NULL;
a5a27c79 2516 }
83024d98 2517 rev.add_signoff = cfg.do_signoff;
738e88a2
KW
2518
2519 if (show_progress)
1f7e6478
PS
2520 progress = start_delayed_progress(the_repository,
2521 _("Generating patches"), total);
0905ed20
PS
2522 for (i = 0; i < nr; i++) {
2523 size_t idx = nr - i - 1;
91efcf60 2524 int shown;
0905ed20
PS
2525
2526 display_progress(progress, total - idx);
2527 commit = list[idx];
2528 rev.nr = total - idx + (start_number - 1);
2529
d1566f78 2530 /* Make the second and subsequent mails replies to the first */
83024d98 2531 if (cfg.thread) {
a5a27c79 2532 /* Have we already had a message ID? */
e1a37346 2533 if (rev.message_id) {
a5a27c79 2534 /*
30984ed2
TR
2535 * For deep threading: make every mail
2536 * a reply to the previous one, no
2537 * matter what other options are set.
2538 *
2539 * For shallow threading:
2540 *
2175c10d
TR
2541 * Without --cover-letter and
2542 * --in-reply-to, make every mail a
2543 * reply to the one before.
2544 *
2545 * With --in-reply-to but no
2546 * --cover-letter, make every mail a
2547 * reply to the <reply-to>.
2548 *
2549 * With --cover-letter, make every
2550 * mail but the cover letter a reply
2551 * to the cover letter. The cover
2552 * letter is a reply to the
2553 * --in-reply-to, if specified.
a5a27c79 2554 */
83024d98 2555 if (cfg.thread == THREAD_SHALLOW
30984ed2 2556 && rev.ref_message_ids->nr > 0
2175c10d 2557 && (!cover_letter || rev.nr > 1))
e1a37346
DB
2558 free(rev.message_id);
2559 else
c6d26a9d
JK
2560 string_list_append_nodup(rev.ref_message_ids,
2561 rev.message_id);
cc35de84 2562 }
f2fd0760 2563 gen_message_id(&rev, oid_to_hex(&commit->object.oid));
d1566f78 2564 }
6df514af 2565
1e1693b2 2566 if (output_directory &&
95235f5b 2567 open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
bc208ae3 2568 die(_("failed to create output files"));
91efcf60 2569 shown = log_tree_commit(&rev, commit);
6a7895fd
SB
2570 free_commit_buffer(the_repository->parsed_objects,
2571 commit);
add5c8a5
JH
2572
2573 /* We put one extra blank line between formatted
2574 * patches and this flag is used by log-tree code
2575 * to see if it needs to emit a LF before showing
2576 * the log; when using one file per patch, we do
2577 * not want the extra blank line.
2578 */
1e1693b2 2579 if (output_directory)
add5c8a5 2580 rev.shown_one = 0;
698ce6f8 2581 if (shown) {
480871e0 2582 print_bases(&bases, rev.diffopt.file);
698ce6f8 2583 if (rev.mime_boundary)
95235f5b 2584 fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n",
698ce6f8
JS
2585 mime_boundary_leader,
2586 rev.mime_boundary);
2587 else
83024d98 2588 print_signature(signature, rev.diffopt.file);
698ce6f8 2589 }
1bc158e7 2590 if (output_directory) {
95235f5b 2591 fclose(rev.diffopt.file);
1bc158e7
PS
2592 rev.diffopt.file = NULL;
2593 }
91efcf60 2594 }
738e88a2 2595 stop_progress(&progress);
91efcf60 2596 free(list);
5d23e133
JH
2597 if (ignore_if_in_upstream)
2598 free_patch_ids(&ids);
126facf8
ES
2599
2600done:
2601 oid_array_clear(&idiff_prev);
5ac290f9 2602 strbuf_release(&idiff_title);
31e2617a
ES
2603 strbuf_release(&rdiff1);
2604 strbuf_release(&rdiff2);
4ee99689 2605 strbuf_release(&rdiff_title);
14da2623
PS
2606 free(description_file);
2607 free(signature_file_arg);
1bc158e7
PS
2608 free(signature_to_free);
2609 free(branch_name);
89f45cf4 2610 free(to_free);
cfa12094 2611 free(rev.message_id);
89f45cf4
ÆAB
2612 if (rev.ref_message_ids)
2613 string_list_clear(rev.ref_message_ids, 0);
2614 free(rev.ref_message_ids);
1bc158e7 2615 rev.diffopt.no_free = 0;
106a54ae 2616 release_revisions(&rev);
83024d98 2617 format_config_release(&cfg);
106a54ae 2618 return 0;
91efcf60
JH
2619}
2620
e827633a
RS
2621static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
2622{
d801627b 2623 struct object_id oid;
d850b7a5 2624 if (repo_get_oid(the_repository, arg, &oid) == 0) {
2122f675
SB
2625 struct commit *commit = lookup_commit_reference(the_repository,
2626 &oid);
e827633a
RS
2627 if (commit) {
2628 commit->object.flags |= flags;
2629 add_pending_object(revs, &commit->object, arg);
2630 return 0;
2631 }
2632 }
2633 return -1;
2634}
2635
28a53178 2636static const char * const cherry_usage[] = {
986d1bb8 2637 N_("git cherry [-v] [<upstream> [<head> [<limit>]]]"),
28a53178
EFL
2638 NULL
2639};
2640
a3a32e7f 2641static void print_commit(char sign, struct commit *commit, int verbose,
95235f5b 2642 int abbrev, FILE *file)
a3a32e7f
JN
2643{
2644 if (!verbose) {
95235f5b 2645 fprintf(file, "%c %s\n", sign,
d850b7a5 2646 repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev));
a3a32e7f
JN
2647 } else {
2648 struct strbuf buf = STRBUF_INIT;
f67d2e82 2649 pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
95235f5b 2650 fprintf(file, "%c %s %s\n", sign,
d850b7a5 2651 repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev),
a3a32e7f
JN
2652 buf.buf);
2653 strbuf_release(&buf);
2654 }
2655}
2656
9b1cb507
JC
2657int cmd_cherry(int argc,
2658 const char **argv,
2659 const char *prefix,
2660 struct repository *repo UNUSED)
e827633a
RS
2661{
2662 struct rev_info revs;
5d23e133 2663 struct patch_ids ids;
e827633a
RS
2664 struct commit *commit;
2665 struct commit_list *list = NULL;
f2968022 2666 struct branch *current_branch;
e827633a
RS
2667 const char *upstream;
2668 const char *head = "HEAD";
2669 const char *limit = NULL;
28a53178 2670 int verbose = 0, abbrev = 0;
e827633a 2671
28a53178
EFL
2672 struct option options[] = {
2673 OPT__ABBREV(&abbrev),
986d1bb8 2674 OPT__VERBOSE(&verbose, N_("be verbose")),
28a53178
EFL
2675 OPT_END()
2676 };
e827633a 2677
28a53178 2678 argc = parse_options(argc, argv, prefix, options, cherry_usage, 0);
fef34270 2679
e827633a 2680 switch (argc) {
e827633a 2681 case 3:
28a53178 2682 limit = argv[2];
e827633a
RS
2683 /* FALLTHROUGH */
2684 case 2:
28a53178
EFL
2685 head = argv[1];
2686 /* FALLTHROUGH */
2687 case 1:
2688 upstream = argv[0];
e827633a
RS
2689 break;
2690 default:
f2968022 2691 current_branch = branch_get(NULL);
3a429d0a 2692 upstream = branch_get_upstream(current_branch, NULL);
a9f9f8cc 2693 if (!upstream) {
5c5f1d7c 2694 fprintf(stderr, _("Could not find a tracked"
f2968022 2695 " remote branch, please"
5c5f1d7c 2696 " specify <upstream> manually.\n"));
28a53178 2697 usage_with_options(cherry_usage, options);
f2968022 2698 }
e827633a
RS
2699 }
2700
2abf3503 2701 repo_init_revisions(the_repository, &revs, prefix);
51f4de3a 2702 revs.max_parents = 1;
e827633a
RS
2703
2704 if (add_pending_commit(head, &revs, 0))
bc208ae3 2705 die(_("unknown commit %s"), head);
e827633a 2706 if (add_pending_commit(upstream, &revs, UNINTERESTING))
bc208ae3 2707 die(_("unknown commit %s"), upstream);
e827633a
RS
2708
2709 /* Don't say anything if head and upstream are the same. */
2710 if (revs.pending.nr == 2) {
2711 struct object_array_entry *o = revs.pending.objects;
4a7e27e9 2712 if (oideq(&o[0].item->oid, &o[1].item->oid))
e827633a
RS
2713 return 0;
2714 }
2715
811929f1 2716 get_patch_ids(&revs, &ids);
e827633a
RS
2717
2718 if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
bc208ae3 2719 die(_("unknown commit %s"), limit);
e827633a
RS
2720
2721 /* reverse the list of commits */
3d51e1b5 2722 if (prepare_revision_walk(&revs))
5c5f1d7c 2723 die(_("revision walk setup failed"));
e827633a 2724 while ((commit = get_revision(&revs)) != NULL) {
e827633a
RS
2725 commit_list_insert(commit, &list);
2726 }
2727
a282dbeb 2728 for (struct commit_list *l = list; l; l = l->next) {
e827633a
RS
2729 char sign = '+';
2730
a282dbeb 2731 commit = l->item;
5d23e133 2732 if (has_commit_patch_id(commit, &ids))
e827633a 2733 sign = '-';
95235f5b 2734 print_commit(sign, commit, verbose, abbrev, revs.diffopt.file);
e827633a
RS
2735 }
2736
a282dbeb 2737 free_commit_list(list);
5d23e133 2738 free_patch_ids(&ids);
e827633a
RS
2739 return 0;
2740}