Skip to content

Commit 846cf16

Browse files
committed
built-in add -p: implement the "stash" and "reset" patch modes
The `git stash` and `git reset` commands support a `--patch` option, and both simply hand off to `git add -p` to perform that work. Let's teach the built-in version of that command to be able to perform that work, too. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 8f6139f commit 846cf16

File tree

3 files changed

+87
-4
lines changed

3 files changed

+87
-4
lines changed

add-interactive.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ int run_add_i(struct repository *r, const struct pathspec *ps);
2525

2626
enum add_p_mode {
2727
ADD_P_STAGE,
28+
ADD_P_STASH,
29+
ADD_P_RESET,
2830
};
2931

3032
int run_add_p(struct repository *r, enum add_p_mode mode,

add-patch.c

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ enum prompt_mode_type {
1313

1414
struct patch_mode {
1515
const char *diff[4], *apply[4], *apply_check[4];
16-
unsigned is_reverse:1, apply_for_checkout:1;
16+
unsigned is_reverse:1, index_only:1, apply_for_checkout:1;
1717
const char *prompt_mode[PROMPT_HUNK + 1];
1818
const char *edit_hunk_hint, *help_patch_text;
1919
};
@@ -40,6 +40,74 @@ static struct patch_mode patch_mode_stage = {
4040
"the file\n")
4141
};
4242

43+
static struct patch_mode patch_mode_stash = {
44+
.diff = { "diff-index", "HEAD", NULL },
45+
.apply = { "--cached", NULL },
46+
.apply_check = { "--cached", NULL },
47+
.is_reverse = 0,
48+
.prompt_mode = {
49+
N_("Stash mode change [y,n,q,a,d%s,?]? "),
50+
N_("Stash deletion [y,n,q,a,d%s,?]? "),
51+
N_("Stash this hunk [y,n,q,a,d%s,?]? "),
52+
},
53+
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
54+
"will immediately be marked for stashing."),
55+
.help_patch_text =
56+
N_("y - stash this hunk\n"
57+
"n - do not stash this hunk\n"
58+
"q - quit; do not stash this hunk or any of the remaining "
59+
"ones\n"
60+
"a - stash this hunk and all later hunks in the file\n"
61+
"d - do not stash this hunk or any of the later hunks in "
62+
"the file\n"),
63+
};
64+
65+
static struct patch_mode patch_mode_reset_head = {
66+
.diff = { "diff-index", "--cached", NULL },
67+
.apply = { "-R", "--cached", NULL },
68+
.apply_check = { "-R", "--cached", NULL },
69+
.is_reverse = 1,
70+
.index_only = 1,
71+
.prompt_mode = {
72+
N_("Unstage mode change [y,n,q,a,d%s,?]? "),
73+
N_("Unstage deletion [y,n,q,a,d%s,?]? "),
74+
N_("Unstage this hunk [y,n,q,a,d%s,?]? "),
75+
},
76+
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
77+
"will immediately be marked for unstaging."),
78+
.help_patch_text =
79+
N_("y - unstage this hunk\n"
80+
"n - do not unstage this hunk\n"
81+
"q - quit; do not unstage this hunk or any of the remaining "
82+
"ones\n"
83+
"a - unstage this hunk and all later hunks in the file\n"
84+
"d - do not unstage this hunk or any of the later hunks in "
85+
"the file\n"),
86+
};
87+
88+
static struct patch_mode patch_mode_reset_nothead = {
89+
.diff = { "diff-index", "-R", "--cached", NULL },
90+
.apply = { "--cached", NULL },
91+
.apply_check = { "--cached", NULL },
92+
.is_reverse = 0,
93+
.index_only = 1,
94+
.prompt_mode = {
95+
N_("Apply mode change to index [y,n,q,a,d%s,?]? "),
96+
N_("Apply deletion to index [y,n,q,a,d%s,?]? "),
97+
N_("Apply this hunk to index [y,n,q,a,d%s,?]? "),
98+
},
99+
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
100+
"will immediately be marked for applying."),
101+
.help_patch_text =
102+
N_("y - apply this hunk to index\n"
103+
"n - do not apply this hunk to index\n"
104+
"q - quit; do not apply this hunk or any of the remaining "
105+
"ones\n"
106+
"a - apply this hunk and all later hunks in the file\n"
107+
"d - do not apply this hunk or any of the later hunks in "
108+
"the file\n"),
109+
};
110+
43111
struct hunk_header {
44112
unsigned long old_offset, old_count, new_offset, new_count;
45113
/*
@@ -1345,12 +1413,21 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
13451413

13461414
init_add_i_state(&s.s, r);
13471415

1348-
s.mode = &patch_mode_stage;
1416+
if (mode == ADD_P_STASH)
1417+
s.mode = &patch_mode_stash;
1418+
else if (mode == ADD_P_RESET) {
1419+
if (!revision || !strcmp(revision, "HEAD"))
1420+
s.mode = &patch_mode_reset_head;
1421+
else
1422+
s.mode = &patch_mode_reset_nothead;
1423+
} else
1424+
s.mode = &patch_mode_stage;
13491425
s.revision = revision;
13501426

13511427
if (discard_index(r->index) < 0 || repo_read_index(r) < 0 ||
1352-
repo_refresh_and_write_index(r, REFRESH_QUIET, 0, 1,
1353-
NULL, NULL, NULL) < 0 ||
1428+
(!s.mode->index_only &&
1429+
repo_refresh_and_write_index(r, REFRESH_QUIET, 0, 1,
1430+
NULL, NULL, NULL) < 0) ||
13541431
parse_diff(&s, ps) < 0) {
13551432
strbuf_release(&s.plain);
13561433
strbuf_release(&s.colored);

builtin/add.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ int run_add_interactive(const char *revision, const char *patch_mode,
201201

202202
if (!strcmp(patch_mode, "--patch"))
203203
mode = ADD_P_STAGE;
204+
else if (!strcmp(patch_mode, "--patch=stash"))
205+
mode = ADD_P_STASH;
206+
else if (!strcmp(patch_mode, "--patch=reset"))
207+
mode = ADD_P_RESET;
204208
else
205209
die("'%s' not yet supported in the built-in add -p",
206210
patch_mode);

0 commit comments

Comments
 (0)