Skip to content

Commit 9e7e41b

Browse files
aleen42gitster
authored andcommitted
am: support --allow-empty to record specific empty patches
This option helps to record specific empty patches in the middle of an am session, which does create empty commits only when: 1. the index has not changed 2. lacking a branch When the index has changed, "--allow-empty" will create a non-empty commit like passing "--continue" or "--resolved". Signed-off-by: 徐沛文 (Aleen) <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7c096b8 commit 9e7e41b

File tree

5 files changed

+95
-10
lines changed

5 files changed

+95
-10
lines changed

Documentation/git-am.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ SYNOPSIS
1818
[--quoted-cr=<action>]
1919
[--empty=(stop|drop|keep)]
2020
[(<mbox> | <Maildir>)...]
21-
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)])
21+
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)] | --allow-empty)
2222

2323
DESCRIPTION
2424
-----------
@@ -200,6 +200,11 @@ default. You can use `--no-utf8` to override this.
200200
the e-mail message; if `diff`, show the diff portion only.
201201
Defaults to `raw`.
202202

203+
--allow-empty::
204+
After a patch failure on an input e-mail message lacking a patch,
205+
create an empty commit with the contents of the e-mail message
206+
as its log message.
207+
203208
DISCUSSION
204209
----------
205210

builtin/am.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,12 @@ static void NORETURN die_user_resolve(const struct am_state *state)
11521152

11531153
printf_ln(_("When you have resolved this problem, run \"%s --continue\"."), cmdline);
11541154
printf_ln(_("If you prefer to skip this patch, run \"%s --skip\" instead."), cmdline);
1155+
1156+
if (advice_enabled(ADVICE_AM_WORK_DIR) &&
1157+
is_empty_or_missing_file(am_path(state, "patch")) &&
1158+
!repo_index_has_changes(the_repository, NULL, NULL))
1159+
printf_ln(_("To record the empty patch as an empty commit, run \"%s --allow-empty\"."), cmdline);
1160+
11551161
printf_ln(_("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline);
11561162
}
11571163

@@ -1900,19 +1906,24 @@ static void am_run(struct am_state *state, int resume)
19001906
/**
19011907
* Resume the current am session after patch application failure. The user did
19021908
* all the hard work, and we do not have to do any patch application. Just
1903-
* trust and commit what the user has in the index and working tree.
1909+
* trust and commit what the user has in the index and working tree. If `allow_empty`
1910+
* is true, commit as an empty commit when index has not changed and lacking a patch.
19041911
*/
1905-
static void am_resolve(struct am_state *state)
1912+
static void am_resolve(struct am_state *state, int allow_empty)
19061913
{
19071914
validate_resume_state(state);
19081915

19091916
say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg);
19101917

19111918
if (!repo_index_has_changes(the_repository, NULL, NULL)) {
1912-
printf_ln(_("No changes - did you forget to use 'git add'?\n"
1913-
"If there is nothing left to stage, chances are that something else\n"
1914-
"already introduced the same changes; you might want to skip this patch."));
1915-
die_user_resolve(state);
1919+
if (allow_empty && is_empty_or_missing_file(am_path(state, "patch"))) {
1920+
printf_ln(_("No changes - recorded it as an empty commit."));
1921+
} else {
1922+
printf_ln(_("No changes - did you forget to use 'git add'?\n"
1923+
"If there is nothing left to stage, chances are that something else\n"
1924+
"already introduced the same changes; you might want to skip this patch."));
1925+
die_user_resolve(state);
1926+
}
19161927
}
19171928

19181929
if (unmerged_cache()) {
@@ -2239,7 +2250,8 @@ enum resume_type {
22392250
RESUME_SKIP,
22402251
RESUME_ABORT,
22412252
RESUME_QUIT,
2242-
RESUME_SHOW_PATCH
2253+
RESUME_SHOW_PATCH,
2254+
RESUME_ALLOW_EMPTY,
22432255
};
22442256

22452257
struct resume_mode {
@@ -2392,6 +2404,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
23922404
N_("show the patch being applied"),
23932405
PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
23942406
parse_opt_show_current_patch, RESUME_SHOW_PATCH },
2407+
OPT_CMDMODE(0, "allow-empty", &resume.mode,
2408+
N_("record the empty patch as an empty commit"),
2409+
RESUME_ALLOW_EMPTY),
23952410
OPT_BOOL(0, "committer-date-is-author-date",
23962411
&state.committer_date_is_author_date,
23972412
N_("lie about committer date")),
@@ -2500,7 +2515,8 @@ int cmd_am(int argc, const char **argv, const char *prefix)
25002515
am_run(&state, 1);
25012516
break;
25022517
case RESUME_RESOLVED:
2503-
am_resolve(&state);
2518+
case RESUME_ALLOW_EMPTY:
2519+
am_resolve(&state, resume.mode == RESUME_ALLOW_EMPTY ? 1 : 0);
25042520
break;
25052521
case RESUME_SKIP:
25062522
am_skip(&state);

t/t4150-am.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,4 +1202,61 @@ test_expect_success 'record as an empty commit when meeting e-mail message that
12021202
grep "Creating an empty commit: empty commit" output
12031203
'
12041204

1205+
test_expect_success 'skip an empty patch in the middle of an am session' '
1206+
git checkout empty-commit^ &&
1207+
test_must_fail git am empty-commit.patch >err &&
1208+
grep "Patch is empty." err &&
1209+
grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err &&
1210+
git am --skip &&
1211+
test_path_is_missing .git/rebase-apply &&
1212+
git rev-parse empty-commit^ >expected &&
1213+
git rev-parse HEAD >actual &&
1214+
test_cmp expected actual
1215+
'
1216+
1217+
test_expect_success 'record an empty patch as an empty commit in the middle of an am session' '
1218+
git checkout empty-commit^ &&
1219+
test_must_fail git am empty-commit.patch >err &&
1220+
grep "Patch is empty." err &&
1221+
grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err &&
1222+
git am --allow-empty >output &&
1223+
grep "No changes - recorded it as an empty commit." output &&
1224+
test_path_is_missing .git/rebase-apply &&
1225+
git show empty-commit --format="%B" >expected &&
1226+
git show HEAD --format="%B" >actual &&
1227+
grep -f actual expected
1228+
'
1229+
1230+
test_expect_success 'create an non-empty commit when the index IS changed though "--allow-empty" is given' '
1231+
git checkout empty-commit^ &&
1232+
test_must_fail git am empty-commit.patch >err &&
1233+
: >empty-file &&
1234+
git add empty-file &&
1235+
git am --allow-empty &&
1236+
git show empty-commit --format="%B" >expected &&
1237+
git show HEAD --format="%B" >actual &&
1238+
grep -f actual expected &&
1239+
git diff HEAD^..HEAD --name-only
1240+
'
1241+
1242+
test_expect_success 'cannot create empty commits when there is a clean index due to merge conflicts' '
1243+
test_when_finished "git am --abort || :" &&
1244+
git rev-parse HEAD >expected &&
1245+
test_must_fail git am seq.patch &&
1246+
test_must_fail git am --allow-empty >err &&
1247+
! grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err &&
1248+
git rev-parse HEAD >actual &&
1249+
test_cmp actual expected
1250+
'
1251+
1252+
test_expect_success 'cannot create empty commits when there is unmerged index due to merge conflicts' '
1253+
test_when_finished "git am --abort || :" &&
1254+
git rev-parse HEAD >expected &&
1255+
test_must_fail git am -3 seq.patch &&
1256+
test_must_fail git am --allow-empty >err &&
1257+
! grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err &&
1258+
git rev-parse HEAD >actual &&
1259+
test_cmp actual expected
1260+
'
1261+
12051262
test_done

t/t7512-status-help.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ On branch am_empty
659659
You are in the middle of an am session.
660660
The current patch is empty.
661661
(use "git am --skip" to skip this patch)
662+
(use "git am --allow-empty" to record this patch as an empty commit)
662663
(use "git am --abort" to restore the original branch)
663664
664665
nothing to commit (use -u to show untracked files)

wt-status.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1212,17 +1212,23 @@ static void show_merge_in_progress(struct wt_status *s,
12121212
static void show_am_in_progress(struct wt_status *s,
12131213
const char *color)
12141214
{
1215+
int am_empty_patch;
1216+
12151217
status_printf_ln(s, color,
12161218
_("You are in the middle of an am session."));
12171219
if (s->state.am_empty_patch)
12181220
status_printf_ln(s, color,
12191221
_("The current patch is empty."));
12201222
if (s->hints) {
1221-
if (!s->state.am_empty_patch)
1223+
am_empty_patch = s->state.am_empty_patch;
1224+
if (!am_empty_patch)
12221225
status_printf_ln(s, color,
12231226
_(" (fix conflicts and then run \"git am --continue\")"));
12241227
status_printf_ln(s, color,
12251228
_(" (use \"git am --skip\" to skip this patch)"));
1229+
if (am_empty_patch)
1230+
status_printf_ln(s, color,
1231+
_(" (use \"git am --allow-empty\" to record this patch as an empty commit)"));
12261232
status_printf_ln(s, color,
12271233
_(" (use \"git am --abort\" to restore the original branch)"));
12281234
}

0 commit comments

Comments
 (0)