@@ -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
/*
@@ -1007,6 +1073,57 @@ static int edit_hunk_loop(struct add_p_state *s,
1007
1073
}
1008
1074
}
1009
1075
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
+
1010
1127
#define SUMMARY_HEADER_WIDTH 20
1011
1128
#define SUMMARY_LINE_WIDTH 80
1012
1129
static 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,
1327
1444
strbuf_reset (& s -> buf );
1328
1445
reassemble_patch (s , file_diff , 0 , & s -> buf );
1329
1446
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
+ }
1335
1457
repo_refresh_and_write_index (s -> s .r , REFRESH_QUIET , 0 );
1336
1458
}
1337
1459
@@ -1357,6 +1479,13 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
1357
1479
s .mode = & patch_mode_reset_head ;
1358
1480
else
1359
1481
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 ;
1360
1489
} else
1361
1490
s .mode = & patch_mode_stage ;
1362
1491
s .revision = revision ;
0 commit comments