35
NULL
36
};
37
38
-static int edit, record_origin, no_commit, mainline, signoff, allow_ff;
39
-static enum { REVERT, CHERRY_PICK } action;
40
-static int commit_argc;
41
-static const char **commit_argv;
42
-static int allow_rerere_auto;
43
-
44
-static const char *me;
45
-
46
-/* Merge strategy. */
47
-static const char *strategy;
48
-static const char **xopts;
49
-static size_t xopts_nr, xopts_alloc;
38
+enum replay_action { REVERT, CHERRY_PICK };
39
+
40
+struct replay_opts {
41
+ enum replay_action action;
42
+
43
+ /* Boolean options */
44
+ int edit;
45
+ int record_origin;
46
+ int no_commit;
47
+ int signoff;
48
+ int allow_ff;
49
+ int allow_rerere_auto;
50
+
51
+ int mainline;
52
+ int commit_argc;
53
+ const char **commit_argv;
54
+
55
+ /* Merge strategy */
56
+ const char *strategy;
57
+ const char **xopts;
58
+ size_t xopts_nr, xopts_alloc;
59
+};
60
61
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
62
63
+static const char *action_name(const struct replay_opts *opts)
64
+{
65
+ return opts->action == REVERT ? "revert" : "cherry-pick";
66
+}
67
+
68
static char *get_encoding(const char *message);
69
55
-static const char * const *revert_or_cherry_pick_usage(void)
70
+static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts)
71
{
57
- return action == REVERT ? revert_usage : cherry_pick_usage;
72
+ return opts->action == REVERT ? revert_usage : cherry_pick_usage;
73
}
74
75
static int option_parse_x(const struct option *opt,
76
const char *arg, int unset)
77
{
78
+ struct replay_opts **opts_ptr = opt->value;
79
+ struct replay_opts *opts = *opts_ptr;
80
+
81
if (unset)
82
return 0;
83
66
- ALLOC_GROW(xopts, xopts_nr + 1, xopts_alloc);
67
- xopts[xopts_nr++] = xstrdup(arg);
84
+ ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
85
+ opts->xopts[opts->xopts_nr++] = xstrdup(arg);
86
return 0;
87
}
88
71
-static void parse_args(int argc, const char **argv)
89
+static void parse_args(int argc, const char **argv, struct replay_opts *opts)
90
{
73
- const char * const * usage_str = revert_or_cherry_pick_usage();
91
+ const char * const * usage_str = revert_or_cherry_pick_usage(opts);
92
int noop;
93
struct option options[] = {
76
- OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
77
- OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
94
+ OPT_BOOLEAN('n', "no-commit", &opts->no_commit, "don't automatically commit"),
95
+ OPT_BOOLEAN('e', "edit", &opts->edit, "edit the commit message"),
96
{ OPTION_BOOLEAN, 'r', NULL, &noop, NULL, "no-op (backward compatibility)",
97
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 0 },
80
- OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
81
- OPT_INTEGER('m', "mainline", &mainline, "parent number"),
82
- OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
83
- OPT_STRING(0, "strategy", &strategy, "strategy", "merge strategy"),
84
- OPT_CALLBACK('X', "strategy-option", &xopts, "option",
98
+ OPT_BOOLEAN('s', "signoff", &opts->signoff, "add Signed-off-by:"),
99
+ OPT_INTEGER('m', "mainline", &opts->mainline, "parent number"),
100
+ OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
101
+ OPT_STRING(0, "strategy", &opts->strategy, "strategy", "merge strategy"),
102
+ OPT_CALLBACK('X', "strategy-option", &opts, "option",
103
"option for merge strategy", option_parse_x),
104
OPT_END(),
105
OPT_END(),
106
OPT_END(),
107
};
108
91
- if (action == CHERRY_PICK) {
109
+ if (opts->action == CHERRY_PICK) {
110
struct option cp_extra[] = {
93
- OPT_BOOLEAN('x', NULL, &record_origin, "append commit name"),
94
- OPT_BOOLEAN(0, "ff", &allow_ff, "allow fast-forward"),
111
+ OPT_BOOLEAN('x', NULL, &opts->record_origin, "append commit name"),
112
+ OPT_BOOLEAN(0, "ff", &opts->allow_ff, "allow fast-forward"),
113
OPT_END(),
114
};
115
if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra))
116
die(_("program error"));
117
}
118
101
- commit_argc = parse_options(argc, argv, NULL, options, usage_str,
102
- PARSE_OPT_KEEP_ARGV0 |
103
- PARSE_OPT_KEEP_UNKNOWN);
104
- if (commit_argc < 2)
119
+ opts->commit_argc = parse_options(argc, argv, NULL, options, usage_str,
120
+ PARSE_OPT_KEEP_ARGV0 |
121
+ PARSE_OPT_KEEP_UNKNOWN);
122
+ if (opts->commit_argc < 2)
123
usage_with_options(usage_str, options);
124
107
- commit_argv = argv;
125
+ opts->commit_argv = argv;
126
}
127
128
struct commit_message {
258
return tree;
259
}
260
243
-static NORETURN void die_dirty_index(const char *me)
261
+static NORETURN void die_dirty_index(struct replay_opts *opts)
262
{
263
if (read_cache_unmerged()) {
246
- die_resolve_conflict(me);
264
+ die_resolve_conflict(action_name(opts));
265
} else {
266
if (advice_commit_before_merge) {
249
- if (action == REVERT)
267
+ if (opts->action == REVERT)
268
die(_("Your local changes would be overwritten by revert.\n"
269
"Please, commit your changes or stash them to proceed."));
270
else
271
die(_("Your local changes would be overwritten by cherry-pick.\n"
272
"Please, commit your changes or stash them to proceed."));
273
} else {
256
- if (action == REVERT)
274
+ if (opts->action == REVERT)
275
die(_("Your local changes would be overwritten by revert.\n"));
276
else
277
die(_("Your local changes would be overwritten by cherry-pick.\n"));
292
293
static int do_recursive_merge(struct commit *base, struct commit *next,
294
const char *base_label, const char *next_label,
277
- unsigned char *head, struct strbuf *msgbuf)
295
+ unsigned char *head, struct strbuf *msgbuf,
296
+ struct replay_opts *opts)
297
{
298
struct merge_options o;
299
struct tree *result, *next_tree, *base_tree, *head_tree;
314
next_tree = next ? next->tree : empty_tree();
315
base_tree = base ? base->tree : empty_tree();
316
298
- for (xopt = xopts; xopt != xopts + xopts_nr; xopt++)
317
+ for (xopt = opts->xopts; xopt != opts->xopts + opts->xopts_nr; xopt++)
318
parse_merge_opt(&o, *xopt);
319
320
clean = merge_trees(&o,
325
(write_cache(index_fd, active_cache, active_nr) ||
326
commit_locked_index(&index_lock)))
327
/* TRANSLATORS: %s will be "revert" or "cherry-pick" */
309
- die(_("%s: Unable to write new index file"), me);
328
+ die(_("%s: Unable to write new index file"), action_name(opts));
329
rollback_lock_file(&index_lock);
330
331
if (!clean) {
354
* If we are revert, or if our cherry-pick results in a hand merge,
355
* we had better say that the current user is responsible for that.
356
*/
338
-static int run_git_commit(const char *defmsg)
357
+static int run_git_commit(const char *defmsg, struct replay_opts *opts)
358
{
359
/* 6 is max possible length of our args array including NULL */
360
const char *args[6];
362
363
args[i++] = "commit";
364
args[i++] = "-n";
346
- if (signoff)
365
+ if (opts->signoff)
366
args[i++] = "-s";
348
- if (!edit) {
367
+ if (!opts->edit) {
368
args[i++] = "-F";
369
args[i++] = defmsg;
370
}
373
return run_command_v_opt(args, RUN_GIT_CMD);
374
}
375
357
-static int do_pick_commit(struct commit *commit)
376
+static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
377
{
378
unsigned char head[20];
379
struct commit *base, *next, *parent;
383
struct strbuf msgbuf = STRBUF_INIT;
384
int res;
385
367
- if (no_commit) {
386
+ if (opts->no_commit) {
387
/*
388
* We do not intend to commit immediately. We just want to
389
* merge the differences in, so let's compute the tree
396
if (get_sha1("HEAD", head))
397
die (_("You do not have a valid HEAD"));
398
if (index_differs_from("HEAD", 0))
380
- die_dirty_index(me);
399
+ die_dirty_index(opts);
400
}
401
discard_cache();
402
408
int cnt;
409
struct commit_list *p;
410
392
- if (!mainline)
411
+ if (!opts->mainline)
412
die(_("Commit %s is a merge but no -m option was given."),
413
sha1_to_hex(commit->object.sha1));
414
415
for (cnt = 1, p = commit->parents;
397
- cnt != mainline && p;
416
+ cnt != opts->mainline && p;
417
cnt++)
418
p = p->next;
400
- if (cnt != mainline || !p)
419
+ if (cnt != opts->mainline || !p)
420
die(_("Commit %s does not have parent %d"),
402
- sha1_to_hex(commit->object.sha1), mainline);
421
+ sha1_to_hex(commit->object.sha1), opts->mainline);
422
parent = p->item;
404
- } else if (0 < mainline)
423
+ } else if (0 < opts->mainline)
424
die(_("Mainline was specified but commit %s is not a merge."),
425
sha1_to_hex(commit->object.sha1));
426
else
427
parent = commit->parents->item;
428
410
- if (allow_ff && parent && !hashcmp(parent->object.sha1, head))
429
+ if (opts->allow_ff && parent && !hashcmp(parent->object.sha1, head))
430
return fast_forward_to(commit->object.sha1, head);
431
432
if (parent && parse_commit(parent) < 0)
433
/* TRANSLATORS: The first %s will be "revert" or
434
"cherry-pick", the second %s a SHA1 */
435
die(_("%s: cannot parse parent commit %s"),
417
- me, sha1_to_hex(parent->object.sha1));
436
+ action_name(opts), sha1_to_hex(parent->object.sha1));
437
438
if (get_message(commit, &msg) != 0)
439
die(_("Cannot get commit message for %s"),
448
449
defmsg = git_pathdup("MERGE_MSG");
450
432
- if (action == REVERT) {
451
+ if (opts->action == REVERT) {
452
base = commit;
453
base_label = msg.label;
454
next = parent;
482
strbuf_addstr(&msgbuf, p);
483
}
484
466
- if (record_origin) {
485
+ if (opts->record_origin) {
486
strbuf_addstr(&msgbuf, "(cherry picked from commit ");
487
strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));
488
strbuf_addstr(&msgbuf, ")\n");
489
}
471
- if (!no_commit)
490
+ if (!opts->no_commit)
491
write_cherry_pick_head(commit);
492
}
493
475
- if (!strategy || !strcmp(strategy, "recursive") || action == REVERT) {
494
+ if (!opts->strategy || !strcmp(opts->strategy, "recursive") || opts->action == REVERT) {
495
res = do_recursive_merge(base, next, base_label, next_label,
477
- head, &msgbuf);
496
+ head, &msgbuf, opts);
497
write_message(&msgbuf, defmsg);
498
} else {
499
struct commit_list *common = NULL;
503
504
commit_list_insert(base, &common);
505
commit_list_insert(next, &remotes);
487
- res = try_merge_command(strategy, xopts_nr, xopts, common,
488
- sha1_to_hex(head), remotes);
506
+ res = try_merge_command(opts->strategy, opts->xopts_nr, opts->xopts,
507
+ common, sha1_to_hex(head), remotes);
508
free_commit_list(common);
509
free_commit_list(remotes);
510
}
511
512
if (res) {
494
- error(action == REVERT
513
+ error(opts->action == REVERT
514
? _("could not revert %s... %s")
515
: _("could not apply %s... %s"),
516
find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV),
517
msg.subject);
518
print_advice();
500
- rerere(allow_rerere_auto);
519
+ rerere(opts->allow_rerere_auto);
520
} else {
502
- if (!no_commit)
503
- res = run_git_commit(defmsg);
521
+ if (!opts->no_commit)
522
+ res = run_git_commit(defmsg, opts);
523
}
524
525
free_message(&msg);
528
return res;
529
}
530
512
-static void prepare_revs(struct rev_info *revs)
531
+static void prepare_revs(struct rev_info *revs, struct replay_opts *opts)
532
{
533
int argc;
534
535
init_revisions(revs, NULL);
536
revs->no_walk = 1;
518
- if (action != REVERT)
537
+ if (opts->action != REVERT)
538
revs->reverse = 1;
539
521
- argc = setup_revisions(commit_argc, commit_argv, revs, NULL);
540
+ argc = setup_revisions(opts->commit_argc, opts->commit_argv, revs, NULL);
541
if (argc > 1)
523
- usage(*revert_or_cherry_pick_usage());
542
+ usage(*revert_or_cherry_pick_usage(opts));
543
544
if (prepare_revision_walk(revs))
545
die(_("revision walk setup failed"));
548
die(_("empty commit set passed"));
549
}
550
532
-static void read_and_refresh_cache(const char *me)
551
+static void read_and_refresh_cache(struct replay_opts *opts)
552
{
553
static struct lock_file index_lock;
554
int index_fd = hold_locked_index(&index_lock, 0);
555
if (read_index_preload(&the_index, NULL) < 0)
537
- die(_("git %s: failed to read the index"), me);
556
+ die(_("git %s: failed to read the index"), action_name(opts));
557
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
558
if (the_index.cache_changed) {
559
if (write_index(&the_index, index_fd) ||
560
commit_locked_index(&index_lock))
542
- die(_("git %s: failed to refresh the index"), me);
561
+ die(_("git %s: failed to refresh the index"), action_name(opts));
562
}
563
rollback_lock_file(&index_lock);
564
}
565
547
-static int revert_or_cherry_pick(int argc, const char **argv)
566
+static int revert_or_cherry_pick(int argc, const char **argv,
567
+ struct replay_opts *opts)
568
{
569
struct rev_info revs;
570
struct commit *commit;
571
572
git_config(git_default_config, NULL);
553
- me = action == REVERT ? "revert" : "cherry-pick";
554
- setenv(GIT_REFLOG_ACTION, me, 0);
555
- parse_args(argc, argv);
573
+ setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
574
+ parse_args(argc, argv, opts);
575
557
- if (allow_ff) {
558
- if (signoff)
576
+ if (opts->allow_ff) {
577
+ if (opts->signoff)
578
die(_("cherry-pick --ff cannot be used with --signoff"));
560
- if (no_commit)
579
+ if (opts->no_commit)
580
die(_("cherry-pick --ff cannot be used with --no-commit"));
562
- if (record_origin)
581
+ if (opts->record_origin)
582
die(_("cherry-pick --ff cannot be used with -x"));
564
- if (edit)
583
+ if (opts->edit)
584
die(_("cherry-pick --ff cannot be used with --edit"));
585
}
586
568
- read_and_refresh_cache(me);
587
+ read_and_refresh_cache(opts);
588
570
- prepare_revs(&revs);
589
+ prepare_revs(&revs, opts);
590
591
while ((commit = get_revision(&revs))) {
573
- int res = do_pick_commit(commit);
592
+ int res = do_pick_commit(commit, opts);
593
if (res)
594
return res;
595
}
599
600
int cmd_revert(int argc, const char **argv, const char *prefix)
601
{
602
+ struct replay_opts opts;
603
+
604
+ memset(&opts, 0, sizeof(opts));
605
if (isatty(0))
584
- edit = 1;
585
- action = REVERT;
586
- return revert_or_cherry_pick(argc, argv);
606
+ opts.edit = 1;
607
+ opts.action = REVERT;
608
+ return revert_or_cherry_pick(argc, argv, &opts);
609
}
610
611
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
612
{
591
- action = CHERRY_PICK;
592
- return revert_or_cherry_pick(argc, argv);
613
+ struct replay_opts opts;
614
+
615
+ memset(&opts, 0, sizeof(opts));
616
+ opts.action = CHERRY_PICK;
617
+ return revert_or_cherry_pick(argc, argv, &opts);
618
}