@@ -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 /*
@@ -1007,6 +1073,57 @@ static int edit_hunk_loop(struct add_p_state *s,
10071073 }
10081074}
10091075
1076+ static int apply_for_checkout (struct add_p_state * s , struct strbuf * diff ,
1077+ int is_reverse )
1078+ {
1079+ const char * reverse = is_reverse ? "-R" : NULL ;
1080+ struct child_process check_index = CHILD_PROCESS_INIT ;
1081+ struct child_process check_worktree = CHILD_PROCESS_INIT ;
1082+ struct child_process apply_index = CHILD_PROCESS_INIT ;
1083+ struct child_process apply_worktree = CHILD_PROCESS_INIT ;
1084+ int applies_index , applies_worktree ;
1085+
1086+ setup_child_process (& check_index , s ,
1087+ "apply" , "--cached" , "--check" , reverse , NULL );
1088+ applies_index = !pipe_command (& check_index , diff -> buf , diff -> len ,
1089+ NULL , 0 , NULL , 0 );
1090+
1091+ setup_child_process (& check_worktree , s ,
1092+ "apply" , "--check" , reverse , NULL );
1093+ applies_worktree = !pipe_command (& check_worktree , diff -> buf , diff -> len ,
1094+ NULL , 0 , NULL , 0 );
1095+
1096+ if (applies_worktree && applies_index ) {
1097+ setup_child_process (& apply_index , s ,
1098+ "apply" , "--cached" , reverse , NULL );
1099+ pipe_command (& apply_index , diff -> buf , diff -> len ,
1100+ NULL , 0 , NULL , 0 );
1101+
1102+ setup_child_process (& apply_worktree , s ,
1103+ "apply" , reverse , NULL );
1104+ pipe_command (& apply_worktree , diff -> buf , diff -> len ,
1105+ NULL , 0 , NULL , 0 );
1106+
1107+ return 1 ;
1108+ }
1109+
1110+ if (!applies_index ) {
1111+ err (s , _ ("The selected hunks do not apply to the index!" ));
1112+ if (prompt_yesno (s , _ ("Apply them to the worktree "
1113+ "anyway? " )) > 0 ) {
1114+ setup_child_process (& apply_worktree , s ,
1115+ "apply" , reverse , NULL );
1116+ return pipe_command (& apply_worktree , diff -> buf ,
1117+ diff -> len , NULL , 0 , NULL , 0 );
1118+ }
1119+ err (s , _ ("Nothing was applied.\n" ));
1120+ } else
1121+ /* As a last resort, show the diff to the user */
1122+ fwrite (diff -> buf , diff -> len , 1 , stderr );
1123+
1124+ return 0 ;
1125+ }
1126+
10101127#define SUMMARY_HEADER_WIDTH 20
10111128#define SUMMARY_LINE_WIDTH 80
10121129static void summarize_hunk (struct add_p_state * s , struct hunk * hunk ,
@@ -1327,11 +1444,16 @@ static int patch_update_file(struct add_p_state *s,
13271444 strbuf_reset (& s -> buf );
13281445 reassemble_patch (s , file_diff , 0 , & s -> buf );
13291446
1330- setup_child_process (& cp , s , "apply" , NULL );
1331- argv_array_pushv (& cp .args , s -> mode -> apply );
1332- if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
1333- NULL , 0 , NULL , 0 ))
1334- error (_ ("'git apply' failed" ));
1447+ if (s -> mode -> apply_for_checkout )
1448+ apply_for_checkout (s , & s -> buf ,
1449+ s -> mode -> is_reverse );
1450+ else {
1451+ setup_child_process (& cp , s , "apply" , NULL );
1452+ argv_array_pushv (& cp .args , s -> mode -> apply );
1453+ if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
1454+ NULL , 0 , NULL , 0 ))
1455+ error (_ ("'git apply' failed" ));
1456+ }
13351457 repo_refresh_and_write_index (s -> s .r , REFRESH_QUIET , 0 );
13361458 }
13371459
@@ -1357,6 +1479,13 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
13571479 s .mode = & patch_mode_reset_head ;
13581480 else
13591481 s .mode = & patch_mode_reset_nothead ;
1482+ } else if (mode == ADD_P_CHECKOUT ) {
1483+ if (!revision )
1484+ s .mode = & patch_mode_checkout_index ;
1485+ else if (!strcmp (revision , "HEAD" ))
1486+ s .mode = & patch_mode_checkout_head ;
1487+ else
1488+ s .mode = & patch_mode_checkout_nothead ;
13601489 } else
13611490 s .mode = & patch_mode_stage ;
13621491 s .revision = revision ;
0 commit comments