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