diff --git a/builtin/rebase.c b/builtin/rebase.c index 10a306310c..535db60181 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -762,9 +762,16 @@ static int run_specific_rebase(struct rebase_options *opts) if (opts->dont_finish_rebase) ; /* do nothing */ - else if (opts->type == REBASE_MERGE) - ; /* merge backend cleans up after itself */ - else if (status == 0) { + else if (opts->type == REBASE_MERGE) { + int quiet = !(opts->flags & (REBASE_NO_QUIET|REBASE_VERBOSE)); + + /* + * The sequencer cleans up after itself. Its state directory + * is gone once it is done, and stays while it is stopped. + */ + if (status == 0 && !is_directory(opts->state_dir)) + run_auto_maintenance(the_repository, quiet); + } else if (status == 0) { if (!file_exists(state_dir_path("stopped-sha", opts))) finish_rebase(opts); } else if (status == 2) { diff --git a/builtin/revert.c b/builtin/revert.c index bedc40f368..52100a20cb 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -8,6 +8,7 @@ #include "gettext.h" #include "revision.h" #include "rerere.h" +#include "run-command.h" #include "sequencer.h" #include "branch.h" @@ -116,7 +117,7 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, const char *strategy = &sentinel_value; const char *gpg_sign = &sentinel_value; enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED; - int cmd = 0; + int cmd = 0, ret; struct option base_options[] = { OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'), OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'), @@ -264,18 +265,22 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, free(options); if (cmd == 'q') { - int ret = sequencer_remove_state(opts); + ret = sequencer_remove_state(opts); if (!ret) remove_branch_state(the_repository, 0); return ret; } - if (cmd == 'c') - return sequencer_continue(the_repository, opts); if (cmd == 'a') return sequencer_rollback(the_repository, opts); - if (cmd == 's') - return sequencer_skip(the_repository, opts); - return sequencer_pick_revisions(the_repository, opts); + if (cmd == 'c') + ret = sequencer_continue(the_repository, opts); + else if (cmd == 's') + ret = sequencer_skip(the_repository, opts); + else + ret = sequencer_pick_revisions(the_repository, opts); + if (!ret) + run_auto_maintenance(the_repository, opts->quiet); + return ret; } int cmd_revert(int argc, diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index cb5c3a1cb5..8056b39955 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -395,4 +395,18 @@ test_orig_head () { test_orig_head --apply test_orig_head --merge +test_expect_success 'rebase runs auto maintenance once it is done' ' + # topic and main both add F2, so the pick conflicts and the rebase + # stops before the exec runs, and once more when the exec fails + git checkout -b auto-maintenance topic && + test_must_fail env GIT_TRACE2_EVENT="$(pwd)/stop.txt" \ + git rebase -x false main && + test_subcommand_flex ! git maintenance run --auto F2 && + git add F2 && + test_must_fail git rebase --continue && + GIT_TRACE2_EVENT="$(pwd)/end.txt" git rebase --continue && + test_subcommand_flex git maintenance run --auto maintenance && + test_line_count = 1 maintenance +' + +test_expect_success 'cherry-pick runs auto maintenance once a stopped sequence is done' ' + # both picked and anotherpick conflict on foo, so "--continue" stops + # once more before "--skip" ends the sequence + pristine_detach initial && + test_must_fail env GIT_TRACE2_EVENT="$(pwd)/stop.txt" \ + git cherry-pick base..anotherpick && + test_subcommand_flex ! git maintenance run --auto foo && + git add foo && + test_must_fail git cherry-pick --continue && + GIT_TRACE2_EVENT="$(pwd)/end.txt" git cherry-pick --skip && + test_subcommand_flex git maintenance run --auto