Skip to content

Commit cf3e248

Browse files
artagnongitster
authored andcommitted
revert: Propagate errors upwards from do_pick_commit
Currently, revert_or_cherry_pick can fail in two ways. If it encounters a conflict, it returns a positive number indicating the intended exit status for the git wrapper to pass on; for all other errors, it calls die(). The latter behavior is inconsiderate towards callers, as it denies them the opportunity to recover from errors and do other things. After this patch, revert_or_cherry_pick will still return a positive return value to indicate an exit status for conflicts as before, while for some other errors, it will print an error message and return -1 instead of die()-ing. The cmd_revert and cmd_cherry_pick are adjusted to handle the fatal errors by die()-ing themselves. While the full benefits of this patch will only be seen once all the "die" calls are replaced with calls to "error", its immediate impact is to change some "fatal:" messages to say "error:" and to add a new "fatal: cherry-pick failed" message at the end when the operation fails. Inspired-by: Christian Couder <[email protected]> Mentored-by: Jonathan Nieder <[email protected]> Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Ramkumar Ramachandra <[email protected]> Signed-off-by: Jonathan Nieder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5a5d80f commit cf3e248

File tree

1 file changed

+40
-46
lines changed

1 file changed

+40
-46
lines changed

builtin/revert.c

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,6 @@ struct replay_opts {
6666

6767
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
6868

69-
static void fatal(const char *advice, ...)
70-
{
71-
va_list params;
72-
73-
va_start(params, advice);
74-
vreportf("fatal: ", advice, params);
75-
va_end(params);
76-
}
77-
7869
static const char *action_name(const struct replay_opts *opts)
7970
{
8071
return opts->action == REVERT ? "revert" : "cherry-pick";
@@ -356,25 +347,20 @@ static struct tree *empty_tree(void)
356347
return tree;
357348
}
358349

359-
static NORETURN void die_dirty_index(struct replay_opts *opts)
350+
static int error_dirty_index(struct replay_opts *opts)
360351
{
361-
if (read_cache_unmerged()) {
362-
die_resolve_conflict(action_name(opts));
363-
} else {
364-
if (advice_commit_before_merge) {
365-
if (opts->action == REVERT)
366-
die(_("Your local changes would be overwritten by revert.\n"
367-
"Please, commit your changes or stash them to proceed."));
368-
else
369-
die(_("Your local changes would be overwritten by cherry-pick.\n"
370-
"Please, commit your changes or stash them to proceed."));
371-
} else {
372-
if (opts->action == REVERT)
373-
die(_("Your local changes would be overwritten by revert.\n"));
374-
else
375-
die(_("Your local changes would be overwritten by cherry-pick.\n"));
376-
}
377-
}
352+
if (read_cache_unmerged())
353+
return error_resolve_conflict(action_name(opts));
354+
355+
/* Different translation strings for cherry-pick and revert */
356+
if (opts->action == CHERRY_PICK)
357+
error(_("Your local changes would be overwritten by cherry-pick."));
358+
else
359+
error(_("Your local changes would be overwritten by revert."));
360+
361+
if (advice_commit_before_merge)
362+
advise(_("Commit your changes or stash them to proceed."));
363+
return -1;
378364
}
379365

380366
static int fast_forward_to(const unsigned char *to, const unsigned char *from)
@@ -492,9 +478,9 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
492478
die (_("Your index file is unmerged."));
493479
} else {
494480
if (get_sha1("HEAD", head))
495-
die (_("You do not have a valid HEAD"));
481+
return error(_("You do not have a valid HEAD"));
496482
if (index_differs_from("HEAD", 0))
497-
die_dirty_index(opts);
483+
return error_dirty_index(opts);
498484
}
499485
discard_cache();
500486

@@ -507,20 +493,20 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
507493
struct commit_list *p;
508494

509495
if (!opts->mainline)
510-
die(_("Commit %s is a merge but no -m option was given."),
511-
sha1_to_hex(commit->object.sha1));
496+
return error(_("Commit %s is a merge but no -m option was given."),
497+
sha1_to_hex(commit->object.sha1));
512498

513499
for (cnt = 1, p = commit->parents;
514500
cnt != opts->mainline && p;
515501
cnt++)
516502
p = p->next;
517503
if (cnt != opts->mainline || !p)
518-
die(_("Commit %s does not have parent %d"),
519-
sha1_to_hex(commit->object.sha1), opts->mainline);
504+
return error(_("Commit %s does not have parent %d"),
505+
sha1_to_hex(commit->object.sha1), opts->mainline);
520506
parent = p->item;
521507
} else if (0 < opts->mainline)
522-
die(_("Mainline was specified but commit %s is not a merge."),
523-
sha1_to_hex(commit->object.sha1));
508+
return error(_("Mainline was specified but commit %s is not a merge."),
509+
sha1_to_hex(commit->object.sha1));
524510
else
525511
parent = commit->parents->item;
526512

@@ -530,12 +516,12 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
530516
if (parent && parse_commit(parent) < 0)
531517
/* TRANSLATORS: The first %s will be "revert" or
532518
"cherry-pick", the second %s a SHA1 */
533-
die(_("%s: cannot parse parent commit %s"),
534-
action_name(opts), sha1_to_hex(parent->object.sha1));
519+
return error(_("%s: cannot parse parent commit %s"),
520+
action_name(opts), sha1_to_hex(parent->object.sha1));
535521

536522
if (get_message(commit, &msg) != 0)
537-
die(_("Cannot get commit message for %s"),
538-
sha1_to_hex(commit->object.sha1));
523+
return error(_("Cannot get commit message for %s"),
524+
sha1_to_hex(commit->object.sha1));
539525

540526
/*
541527
* "commit" is an existing commit. We would want to apply
@@ -997,44 +983,52 @@ static int pick_revisions(struct replay_opts *opts)
997983

998984
walk_revs_populate_todo(&todo_list, opts);
999985
if (create_seq_dir() < 0) {
1000-
fatal(_("A cherry-pick or revert is in progress."));
986+
error(_("A cherry-pick or revert is in progress."));
1001987
advise(_("Use --continue to continue the operation"));
1002988
advise(_("or --reset to forget about it"));
1003-
exit(128);
989+
return -1;
1004990
}
1005991
if (get_sha1("HEAD", sha1)) {
1006992
if (opts->action == REVERT)
1007-
die(_("Can't revert as initial commit"));
1008-
die(_("Can't cherry-pick into empty head"));
993+
return error(_("Can't revert as initial commit"));
994+
return error(_("Can't cherry-pick into empty head"));
1009995
}
1010996
save_head(sha1_to_hex(sha1));
1011997
save_opts(opts);
1012998
}
1013999
return pick_commits(todo_list, opts);
10141000
error:
1015-
die(_("No %s in progress"), action_name(opts));
1001+
return error(_("No %s in progress"), action_name(opts));
10161002
}
10171003

10181004
int cmd_revert(int argc, const char **argv, const char *prefix)
10191005
{
10201006
struct replay_opts opts;
1007+
int res;
10211008

10221009
memset(&opts, 0, sizeof(opts));
10231010
if (isatty(0))
10241011
opts.edit = 1;
10251012
opts.action = REVERT;
10261013
git_config(git_default_config, NULL);
10271014
parse_args(argc, argv, &opts);
1028-
return pick_revisions(&opts);
1015+
res = pick_revisions(&opts);
1016+
if (res < 0)
1017+
die(_("revert failed"));
1018+
return res;
10291019
}
10301020

10311021
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
10321022
{
10331023
struct replay_opts opts;
1024+
int res;
10341025

10351026
memset(&opts, 0, sizeof(opts));
10361027
opts.action = CHERRY_PICK;
10371028
git_config(git_default_config, NULL);
10381029
parse_args(argc, argv, &opts);
1039-
return pick_revisions(&opts);
1030+
res = pick_revisions(&opts);
1031+
if (res < 0)
1032+
die(_("cherry-pick failed"));
1033+
return res;
10401034
}

0 commit comments

Comments
 (0)