@@ -111,6 +111,71 @@ static struct patch_mode patch_mode_reset_nothead = {
111111 "the file\n" ),
112112};
113113
114+ static struct patch_mode patch_mode_checkout_index = {
115+ .diff_cmd = { "diff-files" , NULL },
116+ .apply_args = { "-R" , NULL },
117+ .apply_check_args = { "-R" , NULL },
118+ .is_reverse = 1 ,
119+ .prompt_mode = {
120+ N_ ("Discard mode change from worktree [y,n,q,a,d%s,?]? " ),
121+ N_ ("Discard deletion from worktree [y,n,q,a,d%s,?]? " ),
122+ N_ ("Discard this hunk from worktree [y,n,q,a,d%s,?]? " ),
123+ },
124+ .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
125+ "will immediately be marked for discarding." ),
126+ .help_patch_text =
127+ N_ ("y - discard this hunk from worktree\n"
128+ "n - do not discard this hunk from worktree\n"
129+ "q - quit; do not discard this hunk or any of the remaining "
130+ "ones\n"
131+ "a - discard this hunk and all later hunks in the file\n"
132+ "d - do not discard this hunk or any of the later hunks in "
133+ "the file\n" ),
134+ };
135+
136+ static struct patch_mode patch_mode_checkout_head = {
137+ .diff_cmd = { "diff-index" , NULL },
138+ .apply_for_checkout = 1 ,
139+ .apply_check_args = { "-R" , NULL },
140+ .is_reverse = 1 ,
141+ .prompt_mode = {
142+ N_ ("Discard mode change from index and worktree [y,n,q,a,d%s,?]? " ),
143+ N_ ("Discard deletion from index and worktree [y,n,q,a,d%s,?]? " ),
144+ N_ ("Discard this hunk from index and worktree [y,n,q,a,d%s,?]? " ),
145+ },
146+ .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
147+ "will immediately be marked for discarding." ),
148+ .help_patch_text =
149+ N_ ("y - discard this hunk from index and worktree\n"
150+ "n - do not discard this hunk from index and worktree\n"
151+ "q - quit; do not discard this hunk or any of the remaining "
152+ "ones\n"
153+ "a - discard this hunk and all later hunks in the file\n"
154+ "d - do not discard this hunk or any of the later hunks in "
155+ "the file\n" ),
156+ };
157+
158+ static struct patch_mode patch_mode_checkout_nothead = {
159+ .diff_cmd = { "diff-index" , "-R" , NULL },
160+ .apply_for_checkout = 1 ,
161+ .apply_check_args = { NULL },
162+ .prompt_mode = {
163+ N_ ("Apply mode change to index and worktree [y,n,q,a,d%s,?]? " ),
164+ N_ ("Apply deletion to index and worktree [y,n,q,a,d%s,?]? " ),
165+ N_ ("Apply this hunk to index and worktree [y,n,q,a,d%s,?]? " ),
166+ },
167+ .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
168+ "will immediately be marked for applying." ),
169+ .help_patch_text =
170+ N_ ("y - apply this hunk to index and worktree\n"
171+ "n - do not apply this hunk to index and worktree\n"
172+ "q - quit; do not apply this hunk or any of the remaining "
173+ "ones\n"
174+ "a - apply this hunk and all later hunks in the file\n"
175+ "d - do not apply this hunk or any of the later hunks in "
176+ "the file\n" ),
177+ };
178+
114179struct hunk_header {
115180 unsigned long old_offset , old_count , new_offset , new_count ;
116181 /*
@@ -1067,6 +1132,57 @@ static int edit_hunk_loop(struct add_p_state *s,
10671132 }
10681133}
10691134
1135+ static int apply_for_checkout (struct add_p_state * s , struct strbuf * diff ,
1136+ int is_reverse )
1137+ {
1138+ const char * reverse = is_reverse ? "-R" : NULL ;
1139+ struct child_process check_index = CHILD_PROCESS_INIT ;
1140+ struct child_process check_worktree = CHILD_PROCESS_INIT ;
1141+ struct child_process apply_index = CHILD_PROCESS_INIT ;
1142+ struct child_process apply_worktree = CHILD_PROCESS_INIT ;
1143+ int applies_index , applies_worktree ;
1144+
1145+ setup_child_process (s , & check_index ,
1146+ "apply" , "--cached" , "--check" , reverse , NULL );
1147+ applies_index = !pipe_command (& check_index , diff -> buf , diff -> len ,
1148+ NULL , 0 , NULL , 0 );
1149+
1150+ setup_child_process (s , & check_worktree ,
1151+ "apply" , "--check" , reverse , NULL );
1152+ applies_worktree = !pipe_command (& check_worktree , diff -> buf , diff -> len ,
1153+ NULL , 0 , NULL , 0 );
1154+
1155+ if (applies_worktree && applies_index ) {
1156+ setup_child_process (s , & apply_index ,
1157+ "apply" , "--cached" , reverse , NULL );
1158+ pipe_command (& apply_index , diff -> buf , diff -> len ,
1159+ NULL , 0 , NULL , 0 );
1160+
1161+ setup_child_process (s , & apply_worktree ,
1162+ "apply" , reverse , NULL );
1163+ pipe_command (& apply_worktree , diff -> buf , diff -> len ,
1164+ NULL , 0 , NULL , 0 );
1165+
1166+ return 1 ;
1167+ }
1168+
1169+ if (!applies_index ) {
1170+ err (s , _ ("The selected hunks do not apply to the index!" ));
1171+ if (prompt_yesno (s , _ ("Apply them to the worktree "
1172+ "anyway? " )) > 0 ) {
1173+ setup_child_process (s , & apply_worktree ,
1174+ "apply" , reverse , NULL );
1175+ return pipe_command (& apply_worktree , diff -> buf ,
1176+ diff -> len , NULL , 0 , NULL , 0 );
1177+ }
1178+ err (s , _ ("Nothing was applied.\n" ));
1179+ } else
1180+ /* As a last resort, show the diff to the user */
1181+ fwrite (diff -> buf , diff -> len , 1 , stderr );
1182+
1183+ return 0 ;
1184+ }
1185+
10701186#define SUMMARY_HEADER_WIDTH 20
10711187#define SUMMARY_LINE_WIDTH 80
10721188static void summarize_hunk (struct add_p_state * s , struct hunk * hunk ,
@@ -1392,11 +1508,16 @@ static int patch_update_file(struct add_p_state *s,
13921508 reassemble_patch (s , file_diff , 0 , & s -> buf );
13931509
13941510 discard_index (s -> s .r -> index );
1395- setup_child_process (s , & cp , "apply" , NULL );
1396- argv_array_pushv (& cp .args , s -> mode -> apply_args );
1397- if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
1398- NULL , 0 , NULL , 0 ))
1399- error (_ ("'git apply' failed" ));
1511+ if (s -> mode -> apply_for_checkout )
1512+ apply_for_checkout (s , & s -> buf ,
1513+ s -> mode -> is_reverse );
1514+ else {
1515+ setup_child_process (s , & cp , "apply" , NULL );
1516+ argv_array_pushv (& cp .args , s -> mode -> apply_args );
1517+ if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
1518+ NULL , 0 , NULL , 0 ))
1519+ error (_ ("'git apply' failed" ));
1520+ }
14001521 if (!repo_read_index (s -> s .r ))
14011522 repo_refresh_and_write_index (s -> s .r , REFRESH_QUIET , 0 ,
14021523 1 , NULL , NULL , NULL );
@@ -1423,6 +1544,13 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
14231544 s .mode = & patch_mode_reset_head ;
14241545 else
14251546 s .mode = & patch_mode_reset_nothead ;
1547+ } else if (mode == ADD_P_CHECKOUT ) {
1548+ if (!revision )
1549+ s .mode = & patch_mode_checkout_index ;
1550+ else if (!strcmp (revision , "HEAD" ))
1551+ s .mode = & patch_mode_checkout_head ;
1552+ else
1553+ s .mode = & patch_mode_checkout_nothead ;
14261554 } else
14271555 s .mode = & patch_mode_add ;
14281556 s .revision = revision ;
0 commit comments