@@ -106,6 +106,72 @@ static struct patch_mode patch_mode_reset_nothead = {
106106 "the file\n" ),
107107};
108108
109+ static struct patch_mode patch_mode_checkout_index = {
110+ .diff = { "diff-files" , NULL },
111+ .apply = { "-R" , NULL },
112+ .apply_check = { "-R" , NULL },
113+ .is_reverse = 1 ,
114+ .prompt_mode = {
115+ N_ ("Discard mode change from worktree [y,n,q,a,d%s,?]? " ),
116+ N_ ("Discard deletion from worktree [y,n,q,a,d%s,?]? " ),
117+ N_ ("Discard this hunk from worktree [y,n,q,a,d%s,?]? " ),
118+ },
119+ .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
120+ "will immediately be marked for discarding." ),
121+ .help_patch_text =
122+ N_ ("y - discard this hunk from worktree\n"
123+ "n - do not discard this hunk from worktree\n"
124+ "q - quit; do not discard this hunk or any of the remaining "
125+ "ones\n"
126+ "a - discard this hunk and all later hunks in the file\n"
127+ "d - do not discard this hunk or any of the later hunks in "
128+ "the file\n" ),
129+ };
130+
131+ static struct patch_mode patch_mode_checkout_head = {
132+ .diff = { "diff-index" , NULL },
133+ .apply_for_checkout = 1 ,
134+ .apply_check = { "-R" , NULL },
135+ .is_reverse = 1 ,
136+ .prompt_mode = {
137+ N_ ("Discard mode change from index and worktree [y,n,q,a,d%s,?]? " ),
138+ N_ ("Discard deletion from index and worktree [y,n,q,a,d%s,?]? " ),
139+ N_ ("Discard this hunk from index and worktree [y,n,q,a,d%s,?]? " ),
140+ },
141+ .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
142+ "will immediately be marked for discarding." ),
143+ .help_patch_text =
144+ N_ ("y - discard this hunk from index and worktree\n"
145+ "n - do not discard this hunk from index and worktree\n"
146+ "q - quit; do not discard this hunk or any of the remaining "
147+ "ones\n"
148+ "a - discard this hunk and all later hunks in the file\n"
149+ "d - do not discard this hunk or any of the later hunks in "
150+ "the file\n" ),
151+ };
152+
153+ static struct patch_mode patch_mode_checkout_nothead = {
154+ .diff = { "diff-index" , "-R" , NULL },
155+ .apply_for_checkout = 1 ,
156+ .apply_check = { NULL },
157+ .is_reverse = 0 ,
158+ .prompt_mode = {
159+ N_ ("Apply mode change to index and worktree [y,n,q,a,d%s,?]? " ),
160+ N_ ("Apply deletion to index and worktree [y,n,q,a,d%s,?]? " ),
161+ N_ ("Apply this hunk to index and worktree [y,n,q,a,d%s,?]? " ),
162+ },
163+ .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
164+ "will immediately be marked for applying." ),
165+ .help_patch_text =
166+ N_ ("y - apply this hunk to index and worktree\n"
167+ "n - do not apply this hunk to index and worktree\n"
168+ "q - quit; do not apply this hunk or any of the remaining "
169+ "ones\n"
170+ "a - apply this hunk and all later hunks in the file\n"
171+ "d - do not apply this hunk or any of the later hunks in "
172+ "the file\n" ),
173+ };
174+
109175struct hunk_header {
110176 unsigned long old_offset , old_count , new_offset , new_count ;
111177 /*
@@ -1006,6 +1072,57 @@ static int edit_hunk_loop(struct add_p_state *s,
10061072 }
10071073}
10081074
1075+ static int apply_for_checkout (struct add_p_state * s , struct strbuf * diff ,
1076+ int is_reverse )
1077+ {
1078+ const char * reverse = is_reverse ? "-R" : NULL ;
1079+ struct child_process check_index = CHILD_PROCESS_INIT ;
1080+ struct child_process check_worktree = CHILD_PROCESS_INIT ;
1081+ struct child_process apply_index = CHILD_PROCESS_INIT ;
1082+ struct child_process apply_worktree = CHILD_PROCESS_INIT ;
1083+ int applies_index , applies_worktree ;
1084+
1085+ setup_child_process (& check_index , s ,
1086+ "apply" , "--cached" , "--check" , reverse , NULL );
1087+ applies_index = !pipe_command (& check_index , diff -> buf , diff -> len ,
1088+ NULL , 0 , NULL , 0 );
1089+
1090+ setup_child_process (& check_worktree , s ,
1091+ "apply" , "--check" , reverse , NULL );
1092+ applies_worktree = !pipe_command (& check_worktree , diff -> buf , diff -> len ,
1093+ NULL , 0 , NULL , 0 );
1094+
1095+ if (applies_worktree && applies_index ) {
1096+ setup_child_process (& apply_index , s ,
1097+ "apply" , "--cached" , reverse , NULL );
1098+ pipe_command (& apply_index , diff -> buf , diff -> len ,
1099+ NULL , 0 , NULL , 0 );
1100+
1101+ setup_child_process (& apply_worktree , s ,
1102+ "apply" , reverse , NULL );
1103+ pipe_command (& apply_worktree , diff -> buf , diff -> len ,
1104+ NULL , 0 , NULL , 0 );
1105+
1106+ return 1 ;
1107+ }
1108+
1109+ if (!applies_index ) {
1110+ err (s , _ ("The selected hunks do not apply to the index!" ));
1111+ if (prompt_yesno (s , _ ("Apply them to the worktree "
1112+ "anyway? " )) > 0 ) {
1113+ setup_child_process (& apply_worktree , s ,
1114+ "apply" , reverse , NULL );
1115+ return pipe_command (& apply_worktree , diff -> buf ,
1116+ diff -> len , NULL , 0 , NULL , 0 );
1117+ }
1118+ err (s , _ ("Nothing was applied.\n" ));
1119+ } else
1120+ /* As a last resort, show the diff to the user */
1121+ fwrite (diff -> buf , diff -> len , 1 , stderr );
1122+
1123+ return 0 ;
1124+ }
1125+
10091126#define SUMMARY_HEADER_WIDTH 20
10101127#define SUMMARY_LINE_WIDTH 80
10111128static void summarize_hunk (struct add_p_state * s , struct hunk * hunk ,
@@ -1326,11 +1443,16 @@ static int patch_update_file(struct add_p_state *s,
13261443 strbuf_reset (& s -> buf );
13271444 reassemble_patch (s , file_diff , 0 , & s -> buf );
13281445
1329- setup_child_process (& cp , s , "apply" , NULL );
1330- argv_array_pushv (& cp .args , s -> mode -> apply );
1331- if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
1332- NULL , 0 , NULL , 0 ))
1333- error (_ ("'git apply' failed" ));
1446+ if (s -> mode -> apply_for_checkout )
1447+ apply_for_checkout (s , & s -> buf ,
1448+ s -> mode -> is_reverse );
1449+ else {
1450+ setup_child_process (& cp , s , "apply" , NULL );
1451+ argv_array_pushv (& cp .args , s -> mode -> apply );
1452+ if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
1453+ NULL , 0 , NULL , 0 ))
1454+ error (_ ("'git apply' failed" ));
1455+ }
13341456 repo_refresh_and_write_index (s -> s .r , REFRESH_QUIET , 0 );
13351457 }
13361458
@@ -1356,6 +1478,13 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
13561478 s .mode = & patch_mode_reset_head ;
13571479 else
13581480 s .mode = & patch_mode_reset_nothead ;
1481+ } else if (mode == ADD_P_CHECKOUT ) {
1482+ if (!revision )
1483+ s .mode = & patch_mode_checkout_index ;
1484+ else if (!strcmp (revision , "HEAD" ))
1485+ s .mode = & patch_mode_checkout_head ;
1486+ else
1487+ s .mode = & patch_mode_checkout_nothead ;
13591488 } else
13601489 s .mode = & patch_mode_stage ;
13611490 s .revision = revision ;
0 commit comments