88#include "diff.h"
99
1010enum prompt_mode_type {
11- PROMPT_MODE_CHANGE = 0 , PROMPT_DELETION , PROMPT_HUNK
11+ PROMPT_MODE_CHANGE = 0 , PROMPT_DELETION , PROMPT_HUNK ,
12+ PROMPT_MODE_MAX , /* must be last */
1213};
1314
14- static const char * prompt_mode [] = {
15- N_ ("Stage mode change [y,n,a,q,d%s,?]? " ),
16- N_ ("Stage deletion [y,n,a,q,d%s,?]? " ),
17- N_ ("Stage this hunk [y,n,a,q,d%s,?]? " )
15+ struct patch_mode {
16+ /*
17+ * The magic constant 4 is chosen such that all patch modes
18+ * provide enough space for three command-line arguments followed by a
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 ;
23+ const char * prompt_mode [PROMPT_MODE_MAX ];
24+ const char * edit_hunk_hint , * help_patch_text ;
25+ };
26+
27+ static struct patch_mode patch_mode_add = {
28+ .diff_cmd = { "diff-files" , NULL },
29+ .apply_args = { "--cached" , NULL },
30+ .apply_check_args = { "--cached" , NULL },
31+ .prompt_mode = {
32+ N_ ("Stage mode change [y,n,q,a,d%s,?]? " ),
33+ N_ ("Stage deletion [y,n,q,a,d%s,?]? " ),
34+ N_ ("Stage this hunk [y,n,q,a,d%s,?]? " )
35+ },
36+ .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
37+ "will immediately be marked for staging." ),
38+ .help_patch_text =
39+ N_ ("y - stage this hunk\n"
40+ "n - do not stage this hunk\n"
41+ "q - quit; do not stage this hunk or any of the remaining "
42+ "ones\n"
43+ "a - stage this hunk and all later hunks in the file\n"
44+ "d - do not stage this hunk or any of the later hunks in "
45+ "the file\n" )
1846};
1947
2048struct hunk_header {
@@ -47,6 +75,10 @@ struct add_p_state {
4775 unsigned deleted :1 , mode_change :1 ,binary :1 ;
4876 } * file_diff ;
4977 size_t file_diff_nr ;
78+
79+ /* patch mode */
80+ struct patch_mode * mode ;
81+ const char * revision ;
5082};
5183
5284static void err (struct add_p_state * s , const char * fmt , ...)
@@ -162,9 +194,18 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
162194 struct hunk * hunk = NULL ;
163195 int res ;
164196
197+ argv_array_pushv (& args , s -> mode -> diff_cmd );
198+ if (s -> revision ) {
199+ struct object_id oid ;
200+ argv_array_push (& args ,
201+ /* could be on an unborn branch */
202+ !strcmp ("HEAD" , s -> revision ) &&
203+ get_oid ("HEAD" , & oid ) ?
204+ empty_tree_oid_hex () : s -> revision );
205+ }
206+ color_arg_index = args .argc ;
165207 /* Use `--no-color` explicitly, just in case `diff.color = always`. */
166- argv_array_pushl (& args , "diff-files" , "-p" , "--no-color" , "--" , NULL );
167- color_arg_index = args .argc - 2 ;
208+ argv_array_pushl (& args , "--no-color" , "-p" , "--" , NULL );
168209 for (i = 0 ; i < ps -> nr ; i ++ )
169210 argv_array_push (& args , ps -> items [i ].original );
170211
@@ -382,7 +423,10 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
382423 - header -> colored_extra_start ;
383424 }
384425
385- new_offset += delta ;
426+ if (s -> mode -> is_reverse )
427+ old_offset -= delta ;
428+ else
429+ new_offset += delta ;
386430
387431 strbuf_addf (out , "@@ -%lu,%lu +%lu,%lu @@" ,
388432 old_offset , header -> old_count ,
@@ -805,11 +849,10 @@ static int edit_hunk_manually(struct add_p_state *s, struct hunk *hunk)
805849 "(context).\n"
806850 "To remove '%c' lines, delete them.\n"
807851 "Lines starting with %c will be removed.\n" ),
808- '-' , '+' , comment_line_char );
809- strbuf_commented_addf (& s -> buf ,
810- _ ("If the patch applies cleanly, the edited hunk "
811- "will immediately be\n"
812- "marked for staging.\n" ));
852+ s -> mode -> is_reverse ? '+' : '-' ,
853+ s -> mode -> is_reverse ? '-' : '+' ,
854+ comment_line_char );
855+ strbuf_commented_addf (& s -> buf , "%s" , _ (s -> mode -> edit_hunk_hint ));
813856 /*
814857 * TRANSLATORS: 'it' refers to the patch mentioned in the previous
815858 * messages.
@@ -890,7 +933,8 @@ static int run_apply_check(struct add_p_state *s,
890933 reassemble_patch (s , file_diff , 1 , & s -> buf );
891934
892935 setup_child_process (s , & cp ,
893- "apply" , "--cached" , "--check" , NULL );
936+ "apply" , "--check" , NULL );
937+ argv_array_pushv (& cp .args , s -> mode -> apply_check_args );
894938 if (pipe_command (& cp , s -> buf .buf , s -> buf .len , NULL , 0 , NULL , 0 ))
895939 return error (_ ("'git apply --cached' failed" ));
896940
@@ -1005,13 +1049,6 @@ static size_t display_hunks(struct add_p_state *s,
10051049 return end_index ;
10061050}
10071051
1008- static const char help_patch_text [] =
1009- N_ ("y - stage this hunk\n"
1010- "n - do not stage this hunk\n"
1011- "q - quit; do not stage this hunk or any of the remaining ones\n"
1012- "a - stage this and all the remaining hunks\n"
1013- "d - do not stage this hunk nor any of the remaining hunks\n" );
1014-
10151052static const char help_patch_remainder [] =
10161053N_ ("j - leave this hunk undecided, see next undecided hunk\n"
10171054 "J - leave this hunk undecided, see next hunk\n"
@@ -1097,7 +1134,8 @@ static int patch_update_file(struct add_p_state *s,
10971134 (uintmax_t )hunk_index + 1 ,
10981135 (uintmax_t )file_diff -> hunk_nr );
10991136 color_fprintf (stdout , s -> s .prompt_color ,
1100- _ (prompt_mode [prompt_mode_type ]), s -> buf .buf );
1137+ _ (s -> mode -> prompt_mode [prompt_mode_type ]),
1138+ s -> buf .buf );
11011139 fflush (stdout );
11021140 if (strbuf_getline (& s -> answer , stdin ) == EOF )
11031141 break ;
@@ -1254,7 +1292,7 @@ static int patch_update_file(struct add_p_state *s,
12541292 const char * p = _ (help_patch_remainder ), * eol = p ;
12551293
12561294 color_fprintf (stdout , s -> s .help_color , "%s" ,
1257- _ (help_patch_text ));
1295+ _ (s -> mode -> help_patch_text ));
12581296
12591297 /*
12601298 * Show only those lines of the remainder that are
@@ -1288,10 +1326,11 @@ static int patch_update_file(struct add_p_state *s,
12881326 reassemble_patch (s , file_diff , 0 , & s -> buf );
12891327
12901328 discard_index (s -> s .r -> index );
1291- setup_child_process (s , & cp , "apply" , "--cached" , NULL );
1329+ setup_child_process (s , & cp , "apply" , NULL );
1330+ argv_array_pushv (& cp .args , s -> mode -> apply_args );
12921331 if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
12931332 NULL , 0 , NULL , 0 ))
1294- error (_ ("'git apply --cached ' failed" ));
1333+ error (_ ("'git apply' failed" ));
12951334 if (!repo_read_index (s -> s .r ))
12961335 repo_refresh_and_write_index (s -> s .r , REFRESH_QUIET , 0 ,
12971336 1 , NULL , NULL , NULL );
@@ -1301,7 +1340,8 @@ static int patch_update_file(struct add_p_state *s,
13011340 return quit ;
13021341}
13031342
1304- int run_add_p (struct repository * r , const struct pathspec * ps )
1343+ int run_add_p (struct repository * r , enum add_p_mode mode ,
1344+ const char * revision , const struct pathspec * ps )
13051345{
13061346 struct add_p_state s = {
13071347 { r }, STRBUF_INIT , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
@@ -1310,6 +1350,9 @@ int run_add_p(struct repository *r, const struct pathspec *ps)
13101350
13111351 init_add_i_state (& s .s , r );
13121352
1353+ s .mode = & patch_mode_add ;
1354+ s .revision = revision ;
1355+
13131356 if (discard_index (r -> index ) < 0 || repo_read_index (r ) < 0 ||
13141357 repo_refresh_and_write_index (r , REFRESH_QUIET , 0 , 1 ,
13151358 NULL , NULL , NULL ) < 0 ||
0 commit comments