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 <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Johannes Schindelin committed
Dec 21, 2019 at 21:57 UTC
36bae1dc0ee777aa529dd955f2e619281265f262
3 files changed
+85
-4
add-interactive.h
+2
@@ -25,6 +25,8 @@ int run_add_i(struct repository *r, const struct pathspec *ps);
25
26
enum add_p_mode {
27
ADD_P_ADD,
28
+ ADD_P_STASH,
29
+ ADD_P_RESET,
30
};
31
32
int run_add_p(struct repository *r, enum add_p_mode mode,
add-patch.c
+79
-4
@@ -19,7 +19,7 @@ struct patch_mode {
19
* trailing `NULL`.
20
*/
21
const char *diff_cmd[4], *apply_args[4], *apply_check_args[4];
22
- unsigned is_reverse:1, apply_for_checkout:1;
22
+ unsigned is_reverse:1, index_only:1, apply_for_checkout:1;
23
const char *prompt_mode[PROMPT_MODE_MAX];
24
const char *edit_hunk_hint, *help_patch_text;
25
};
@@ -45,6 +45,72 @@ static struct patch_mode patch_mode_add = {
45
"the file\n")
46
};
47
48
+static struct patch_mode patch_mode_stash = {
49
+ .diff_cmd = { "diff-index", "HEAD", NULL },
50
+ .apply_args = { "--cached", NULL },
51
+ .apply_check_args = { "--cached", NULL },
52
+ .prompt_mode = {
53
+ N_("Stash mode change [y,n,q,a,d%s,?]? "),
54
+ N_("Stash deletion [y,n,q,a,d%s,?]? "),
55
+ N_("Stash this hunk [y,n,q,a,d%s,?]? "),
56
+ },
57
+ .edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
58
+ "will immediately be marked for stashing."),
59
+ .help_patch_text =
60
+ N_("y - stash this hunk\n"
61
+ "n - do not stash this hunk\n"
62
+ "q - quit; do not stash this hunk or any of the remaining "
63
+ "ones\n"
64
+ "a - stash this hunk and all later hunks in the file\n"
65
+ "d - do not stash this hunk or any of the later hunks in "
66
+ "the file\n"),
67
+};
68
+
69
+static struct patch_mode patch_mode_reset_head = {
70
+ .diff_cmd = { "diff-index", "--cached", NULL },
71
+ .apply_args = { "-R", "--cached", NULL },
72
+ .apply_check_args = { "-R", "--cached", NULL },
73
+ .is_reverse = 1,
74
+ .index_only = 1,
75
+ .prompt_mode = {
76
+ N_("Unstage mode change [y,n,q,a,d%s,?]? "),
77
+ N_("Unstage deletion [y,n,q,a,d%s,?]? "),
78
+ N_("Unstage this hunk [y,n,q,a,d%s,?]? "),
79
+ },
80
+ .edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
81
+ "will immediately be marked for unstaging."),
82
+ .help_patch_text =
83
+ N_("y - unstage this hunk\n"
84
+ "n - do not unstage this hunk\n"
85
+ "q - quit; do not unstage this hunk or any of the remaining "
86
+ "ones\n"
87
+ "a - unstage this hunk and all later hunks in the file\n"
88
+ "d - do not unstage this hunk or any of the later hunks in "
89
+ "the file\n"),
90
+};
91
+
92
+static struct patch_mode patch_mode_reset_nothead = {
93
+ .diff_cmd = { "diff-index", "-R", "--cached", NULL },
94
+ .apply_args = { "--cached", NULL },
95
+ .apply_check_args = { "--cached", NULL },
96
+ .index_only = 1,
97
+ .prompt_mode = {
98
+ N_("Apply mode change to index [y,n,q,a,d%s,?]? "),
99
+ N_("Apply deletion to index [y,n,q,a,d%s,?]? "),
100
+ N_("Apply this hunk to index [y,n,q,a,d%s,?]? "),
101
+ },
102
+ .edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
103
+ "will immediately be marked for applying."),
104
+ .help_patch_text =
105
+ N_("y - apply this hunk to index\n"
106
+ "n - do not apply this hunk to index\n"
107
+ "q - quit; do not apply this hunk or any of the remaining "
108
+ "ones\n"
109
+ "a - apply this hunk and all later hunks in the file\n"
110
+ "d - do not apply this hunk or any of the later hunks in "
111
+ "the file\n"),
112
+};
113
+
114
struct hunk_header {
115
unsigned long old_offset, old_count, new_offset, new_count;
116
/*
@@ -1350,12 +1416,21 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
1416
1417
init_add_i_state(&s.s, r);
1418
1353
- s.mode = &patch_mode_add;
1419
+ if (mode == ADD_P_STASH)
1420
+ s.mode = &patch_mode_stash;
1421
+ else if (mode == ADD_P_RESET) {
1422
+ if (!revision || !strcmp(revision, "HEAD"))
1423
+ s.mode = &patch_mode_reset_head;
1424
+ else
1425
+ s.mode = &patch_mode_reset_nothead;
1426
+ } else
1427
+ s.mode = &patch_mode_add;
1428
s.revision = revision;
1429
1430
if (discard_index(r->index) < 0 || repo_read_index(r) < 0 ||
1357
- repo_refresh_and_write_index(r, REFRESH_QUIET, 0, 1,
1358
- NULL, NULL, NULL) < 0 ||
1431
+ (!s.mode->index_only &&
1432
+ repo_refresh_and_write_index(r, REFRESH_QUIET, 0, 1,
1433
+ NULL, NULL, NULL) < 0) ||
1434
parse_diff(&s, ps) < 0) {
1435
strbuf_release(&s.plain);
1436
strbuf_release(&s.colored);
builtin/add.c
+4
@@ -201,6 +201,10 @@ int run_add_interactive(const char *revision, const char *patch_mode,
201
202
if (!strcmp(patch_mode, "--patch"))
203
mode = ADD_P_ADD;
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;
208
else
209
die("'%s' not yet supported in the built-in add -p",
210
patch_mode);