@@ -106,6 +106,72 @@ static struct patch_mode patch_mode_reset_nothead = {
106
106
"the file\n" ),
107
107
};
108
108
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
+
109
175
struct hunk_header {
110
176
unsigned long old_offset , old_count , new_offset , new_count ;
111
177
/*
@@ -1006,6 +1072,57 @@ static int edit_hunk_loop(struct add_p_state *s,
1006
1072
}
1007
1073
}
1008
1074
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
+
1009
1126
#define SUMMARY_HEADER_WIDTH 20
1010
1127
#define SUMMARY_LINE_WIDTH 80
1011
1128
static 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,
1326
1443
strbuf_reset (& s -> buf );
1327
1444
reassemble_patch (s , file_diff , 0 , & s -> buf );
1328
1445
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
+ }
1334
1456
repo_refresh_and_write_index (s -> s .r , REFRESH_QUIET , 0 );
1335
1457
}
1336
1458
@@ -1356,6 +1478,13 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
1356
1478
s .mode = & patch_mode_reset_head ;
1357
1479
else
1358
1480
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 ;
1359
1488
} else
1360
1489
s .mode = & patch_mode_stage ;
1361
1490
s .revision = revision ;
0 commit comments