@@ -29,9 +29,12 @@ struct add_p_state {
29
29
30
30
/* parsed diff */
31
31
struct strbuf plain , colored ;
32
- struct hunk head ;
33
- struct hunk * hunk ;
34
- size_t hunk_nr , hunk_alloc ;
32
+ struct file_diff {
33
+ struct hunk head ;
34
+ struct hunk * hunk ;
35
+ size_t hunk_nr , hunk_alloc ;
36
+ } * file_diff ;
37
+ size_t file_diff_nr ;
35
38
};
36
39
37
40
static void err (struct add_p_state * s , const char * fmt , ...)
@@ -131,7 +134,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
131
134
struct strbuf * plain = & s -> plain , * colored = NULL ;
132
135
struct child_process cp = CHILD_PROCESS_INIT ;
133
136
char * p , * pend , * colored_p = NULL , * colored_pend = NULL ;
134
- size_t i , color_arg_index ;
137
+ size_t file_diff_alloc = 0 , i , color_arg_index ;
138
+ struct file_diff * file_diff = NULL ;
135
139
struct hunk * hunk = NULL ;
136
140
int res ;
137
141
@@ -171,7 +175,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
171
175
}
172
176
argv_array_clear (& args );
173
177
174
- /* parse hunks */
178
+ /* parse files and hunks */
175
179
p = plain -> buf ;
176
180
pend = p + plain -> len ;
177
181
while (p != pend ) {
@@ -180,17 +184,23 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
180
184
eol = pend ;
181
185
182
186
if (starts_with (p , "diff " )) {
183
- if (p != plain -> buf )
184
- BUG ("multi-file diff not yet handled" );
185
- hunk = & s -> head ;
187
+ s -> file_diff_nr ++ ;
188
+ ALLOC_GROW (s -> file_diff , s -> file_diff_nr ,
189
+ file_diff_alloc );
190
+ file_diff = s -> file_diff + s -> file_diff_nr - 1 ;
191
+ memset (file_diff , 0 , sizeof (* file_diff ));
192
+ hunk = & file_diff -> head ;
193
+ hunk -> start = p - plain -> buf ;
194
+ if (colored_p )
195
+ hunk -> colored_start = colored_p - colored -> buf ;
186
196
} else if (p == plain -> buf )
187
197
BUG ("diff starts with unexpected line:\n"
188
198
"%.*s\n" , (int )(eol - p ), p );
189
199
else if (starts_with (p , "@@ " )) {
190
- s -> hunk_nr ++ ;
191
- ALLOC_GROW (s -> hunk , s -> hunk_nr ,
192
- s -> hunk_alloc );
193
- hunk = s -> hunk + s -> hunk_nr - 1 ;
200
+ file_diff -> hunk_nr ++ ;
201
+ ALLOC_GROW (file_diff -> hunk , file_diff -> hunk_nr ,
202
+ file_diff -> hunk_alloc );
203
+ hunk = file_diff -> hunk + file_diff -> hunk_nr - 1 ;
194
204
memset (hunk , 0 , sizeof (* hunk ));
195
205
196
206
hunk -> start = p - plain -> buf ;
@@ -262,16 +272,17 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
262
272
hunk -> end - hunk -> start );
263
273
}
264
274
265
- static void reassemble_patch (struct add_p_state * s , struct strbuf * out )
275
+ static void reassemble_patch (struct add_p_state * s ,
276
+ struct file_diff * file_diff , struct strbuf * out )
266
277
{
267
278
struct hunk * hunk ;
268
279
size_t i ;
269
280
ssize_t delta = 0 ;
270
281
271
- render_hunk (s , & s -> head , 0 , 0 , out );
282
+ render_hunk (s , & file_diff -> head , 0 , 0 , out );
272
283
273
- for (i = 0 ; i < s -> hunk_nr ; i ++ ) {
274
- hunk = s -> hunk + i ;
284
+ for (i = 0 ; i < file_diff -> hunk_nr ; i ++ ) {
285
+ hunk = file_diff -> hunk + i ;
275
286
if (hunk -> use != USE_HUNK )
276
287
delta += hunk -> header .old_count
277
288
- hunk -> header .new_count ;
@@ -291,7 +302,8 @@ N_("y - stage this hunk\n"
291
302
"K - leave this hunk undecided, see previous hunk\n"
292
303
"? - print help\n" );
293
304
294
- static int patch_update_file (struct add_p_state * s )
305
+ static int patch_update_file (struct add_p_state * s ,
306
+ struct file_diff * file_diff )
295
307
{
296
308
size_t hunk_index = 0 ;
297
309
ssize_t i , undecided_previous , undecided_next ;
@@ -300,27 +312,27 @@ static int patch_update_file(struct add_p_state *s)
300
312
struct child_process cp = CHILD_PROCESS_INIT ;
301
313
int colored = !!s -> colored .len ;
302
314
303
- if (!s -> hunk_nr )
315
+ if (!file_diff -> hunk_nr )
304
316
return 0 ;
305
317
306
318
strbuf_reset (& s -> buf );
307
- render_hunk (s , & s -> head , 0 , colored , & s -> buf );
319
+ render_hunk (s , & file_diff -> head , 0 , colored , & s -> buf );
308
320
fputs (s -> buf .buf , stdout );
309
321
for (;;) {
310
- if (hunk_index >= s -> hunk_nr )
322
+ if (hunk_index >= file_diff -> hunk_nr )
311
323
hunk_index = 0 ;
312
- hunk = s -> hunk + hunk_index ;
324
+ hunk = file_diff -> hunk + hunk_index ;
313
325
314
326
undecided_previous = -1 ;
315
327
for (i = hunk_index - 1 ; i >= 0 ; i -- )
316
- if (s -> hunk [i ].use == UNDECIDED_HUNK ) {
328
+ if (file_diff -> hunk [i ].use == UNDECIDED_HUNK ) {
317
329
undecided_previous = i ;
318
330
break ;
319
331
}
320
332
321
333
undecided_next = -1 ;
322
- for (i = hunk_index + 1 ; i < s -> hunk_nr ; i ++ )
323
- if (s -> hunk [i ].use == UNDECIDED_HUNK ) {
334
+ for (i = hunk_index + 1 ; i < file_diff -> hunk_nr ; i ++ )
335
+ if (file_diff -> hunk [i ].use == UNDECIDED_HUNK ) {
324
336
undecided_next = i ;
325
337
break ;
326
338
}
@@ -341,7 +353,7 @@ static int patch_update_file(struct add_p_state *s)
341
353
strbuf_addstr (& s -> buf , ",K" );
342
354
if (undecided_next >= 0 )
343
355
strbuf_addstr (& s -> buf , ",j" );
344
- if (hunk_index + 1 < s -> hunk_nr )
356
+ if (hunk_index + 1 < file_diff -> hunk_nr )
345
357
strbuf_addstr (& s -> buf , ",J" );
346
358
color_fprintf (stdout , s -> s .prompt_color ,
347
359
_ ("Stage this hunk [y,n,a,d%s,?]? " ),
@@ -357,22 +369,22 @@ static int patch_update_file(struct add_p_state *s)
357
369
if (ch == 'y' ) {
358
370
hunk -> use = USE_HUNK ;
359
371
soft_increment :
360
- while (++ hunk_index < s -> hunk_nr &&
361
- s -> hunk [hunk_index ].use
372
+ while (++ hunk_index < file_diff -> hunk_nr &&
373
+ file_diff -> hunk [hunk_index ].use
362
374
!= UNDECIDED_HUNK )
363
375
; /* continue looking */
364
376
} else if (ch == 'n' ) {
365
377
hunk -> use = SKIP_HUNK ;
366
378
goto soft_increment ;
367
379
} else if (ch == 'a' ) {
368
- for (; hunk_index < s -> hunk_nr ; hunk_index ++ ) {
369
- hunk = s -> hunk + hunk_index ;
380
+ for (; hunk_index < file_diff -> hunk_nr ; hunk_index ++ ) {
381
+ hunk = file_diff -> hunk + hunk_index ;
370
382
if (hunk -> use == UNDECIDED_HUNK )
371
383
hunk -> use = USE_HUNK ;
372
384
}
373
385
} else if (ch == 'd' ) {
374
- for (; hunk_index < s -> hunk_nr ; hunk_index ++ ) {
375
- hunk = s -> hunk + hunk_index ;
386
+ for (; hunk_index < file_diff -> hunk_nr ; hunk_index ++ ) {
387
+ hunk = file_diff -> hunk + hunk_index ;
376
388
if (hunk -> use == UNDECIDED_HUNK )
377
389
hunk -> use = SKIP_HUNK ;
378
390
}
@@ -382,7 +394,7 @@ static int patch_update_file(struct add_p_state *s)
382
394
else
383
395
err (s , _ ("No previous hunk" ));
384
396
} else if (s -> answer .buf [0 ] == 'J' ) {
385
- if (hunk_index + 1 < s -> hunk_nr )
397
+ if (hunk_index + 1 < file_diff -> hunk_nr )
386
398
hunk_index ++ ;
387
399
else
388
400
err (s , _ ("No next hunk" ));
@@ -402,14 +414,14 @@ static int patch_update_file(struct add_p_state *s)
402
414
}
403
415
404
416
/* Any hunk to be used? */
405
- for (i = 0 ; i < s -> hunk_nr ; i ++ )
406
- if (s -> hunk [i ].use == USE_HUNK )
417
+ for (i = 0 ; i < file_diff -> hunk_nr ; i ++ )
418
+ if (file_diff -> hunk [i ].use == USE_HUNK )
407
419
break ;
408
420
409
- if (i < s -> hunk_nr ) {
421
+ if (i < file_diff -> hunk_nr ) {
410
422
/* At least one hunk selected: apply */
411
423
strbuf_reset (& s -> buf );
412
- reassemble_patch (s , & s -> buf );
424
+ reassemble_patch (s , file_diff , & s -> buf );
413
425
414
426
setup_child_process (& cp , s , "apply" , "--cached" , NULL );
415
427
if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
@@ -427,6 +439,7 @@ int run_add_p(struct repository *r, const struct pathspec *ps)
427
439
struct add_p_state s = {
428
440
{ r }, STRBUF_INIT , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
429
441
};
442
+ size_t i ;
430
443
431
444
if (init_add_i_state (r , & s .s ))
432
445
return error ("Could not read `add -i` config" );
@@ -438,8 +451,9 @@ int run_add_p(struct repository *r, const struct pathspec *ps)
438
451
return -1 ;
439
452
}
440
453
441
- if (s .hunk_nr )
442
- patch_update_file (& s );
454
+ for (i = 0 ; i < s .file_diff_nr ; i ++ )
455
+ if (patch_update_file (& s , s .file_diff + i ))
456
+ break ;
443
457
444
458
strbuf_release (& s .answer );
445
459
strbuf_release (& s .buf );
0 commit comments