@@ -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 ;
@@ -265,16 +275,17 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
265
275
hunk -> end - hunk -> start );
266
276
}
267
277
268
- static void reassemble_patch (struct add_p_state * s , struct strbuf * out )
278
+ static void reassemble_patch (struct add_p_state * s ,
279
+ struct file_diff * file_diff , struct strbuf * out )
269
280
{
270
281
struct hunk * hunk ;
271
282
size_t i ;
272
283
ssize_t delta = 0 ;
273
284
274
- render_hunk (s , & s -> head , 0 , 0 , out );
285
+ render_hunk (s , & file_diff -> head , 0 , 0 , out );
275
286
276
- for (i = 0 ; i < s -> hunk_nr ; i ++ ) {
277
- hunk = s -> hunk + i ;
287
+ for (i = 0 ; i < file_diff -> hunk_nr ; i ++ ) {
288
+ hunk = file_diff -> hunk + i ;
278
289
if (hunk -> use != USE_HUNK )
279
290
delta += hunk -> header .old_count
280
291
- hunk -> header .new_count ;
@@ -294,7 +305,8 @@ N_("y - stage this hunk\n"
294
305
"K - leave this hunk undecided, see previous hunk\n"
295
306
"? - print help\n" );
296
307
297
- static int patch_update_file (struct add_p_state * s )
308
+ static int patch_update_file (struct add_p_state * s ,
309
+ struct file_diff * file_diff )
298
310
{
299
311
size_t hunk_index = 0 ;
300
312
ssize_t i , undecided_previous , undecided_next ;
@@ -303,27 +315,27 @@ static int patch_update_file(struct add_p_state *s)
303
315
struct child_process cp = CHILD_PROCESS_INIT ;
304
316
int colored = !!s -> colored .len ;
305
317
306
- if (!s -> hunk_nr )
318
+ if (!file_diff -> hunk_nr )
307
319
return 0 ;
308
320
309
321
strbuf_reset (& s -> buf );
310
- render_hunk (s , & s -> head , 0 , colored , & s -> buf );
322
+ render_hunk (s , & file_diff -> head , 0 , colored , & s -> buf );
311
323
fputs (s -> buf .buf , stdout );
312
324
for (;;) {
313
- if (hunk_index >= s -> hunk_nr )
325
+ if (hunk_index >= file_diff -> hunk_nr )
314
326
hunk_index = 0 ;
315
- hunk = s -> hunk + hunk_index ;
327
+ hunk = file_diff -> hunk + hunk_index ;
316
328
317
329
undecided_previous = -1 ;
318
330
for (i = hunk_index - 1 ; i >= 0 ; i -- )
319
- if (s -> hunk [i ].use == UNDECIDED_HUNK ) {
331
+ if (file_diff -> hunk [i ].use == UNDECIDED_HUNK ) {
320
332
undecided_previous = i ;
321
333
break ;
322
334
}
323
335
324
336
undecided_next = -1 ;
325
- for (i = hunk_index + 1 ; i < s -> hunk_nr ; i ++ )
326
- if (s -> hunk [i ].use == UNDECIDED_HUNK ) {
337
+ for (i = hunk_index + 1 ; i < file_diff -> hunk_nr ; i ++ )
338
+ if (file_diff -> hunk [i ].use == UNDECIDED_HUNK ) {
327
339
undecided_next = i ;
328
340
break ;
329
341
}
@@ -344,11 +356,12 @@ static int patch_update_file(struct add_p_state *s)
344
356
strbuf_addstr (& s -> buf , ",K" );
345
357
if (undecided_next >= 0 )
346
358
strbuf_addstr (& s -> buf , ",j" );
347
- if (hunk_index + 1 < s -> hunk_nr )
359
+ if (hunk_index + 1 < file_diff -> hunk_nr )
348
360
strbuf_addstr (& s -> buf , ",J" );
349
361
color_fprintf (stdout , s -> s .prompt_color ,
350
362
"(%" PRIuMAX "/%" PRIuMAX ") " ,
351
- (uintmax_t )hunk_index + 1 , (uintmax_t )s -> hunk_nr );
363
+ (uintmax_t )hunk_index + 1 ,
364
+ (uintmax_t )file_diff -> hunk_nr );
352
365
color_fprintf (stdout , s -> s .prompt_color ,
353
366
_ ("Stage this hunk [y,n,a,d%s,?]? " ),
354
367
s -> buf .buf );
@@ -364,19 +377,19 @@ static int patch_update_file(struct add_p_state *s)
364
377
hunk -> use = USE_HUNK ;
365
378
soft_increment :
366
379
hunk_index = undecided_next < 0 ?
367
- s -> hunk_nr : undecided_next ;
380
+ file_diff -> hunk_nr : undecided_next ;
368
381
} else if (ch == 'n' ) {
369
382
hunk -> use = SKIP_HUNK ;
370
383
goto soft_increment ;
371
384
} else if (ch == 'a' ) {
372
- for (; hunk_index < s -> hunk_nr ; hunk_index ++ ) {
373
- hunk = s -> hunk + hunk_index ;
385
+ for (; hunk_index < file_diff -> hunk_nr ; hunk_index ++ ) {
386
+ hunk = file_diff -> hunk + hunk_index ;
374
387
if (hunk -> use == UNDECIDED_HUNK )
375
388
hunk -> use = USE_HUNK ;
376
389
}
377
390
} else if (ch == 'd' ) {
378
- for (; hunk_index < s -> hunk_nr ; hunk_index ++ ) {
379
- hunk = s -> hunk + hunk_index ;
391
+ for (; hunk_index < file_diff -> hunk_nr ; hunk_index ++ ) {
392
+ hunk = file_diff -> hunk + hunk_index ;
380
393
if (hunk -> use == UNDECIDED_HUNK )
381
394
hunk -> use = SKIP_HUNK ;
382
395
}
@@ -386,7 +399,7 @@ static int patch_update_file(struct add_p_state *s)
386
399
else
387
400
err (s , _ ("No previous hunk" ));
388
401
} else if (s -> answer .buf [0 ] == 'J' ) {
389
- if (hunk_index + 1 < s -> hunk_nr )
402
+ if (hunk_index + 1 < file_diff -> hunk_nr )
390
403
hunk_index ++ ;
391
404
else
392
405
err (s , _ ("No next hunk" ));
@@ -406,14 +419,14 @@ static int patch_update_file(struct add_p_state *s)
406
419
}
407
420
408
421
/* Any hunk to be used? */
409
- for (i = 0 ; i < s -> hunk_nr ; i ++ )
410
- if (s -> hunk [i ].use == USE_HUNK )
422
+ for (i = 0 ; i < file_diff -> hunk_nr ; i ++ )
423
+ if (file_diff -> hunk [i ].use == USE_HUNK )
411
424
break ;
412
425
413
- if (i < s -> hunk_nr ) {
426
+ if (i < file_diff -> hunk_nr ) {
414
427
/* At least one hunk selected: apply */
415
428
strbuf_reset (& s -> buf );
416
- reassemble_patch (s , & s -> buf );
429
+ reassemble_patch (s , file_diff , & s -> buf );
417
430
418
431
discard_index (s -> s .r -> index );
419
432
setup_child_process (s , & cp , "apply" , "--cached" , NULL );
@@ -434,6 +447,7 @@ int run_add_p(struct repository *r, const struct pathspec *ps)
434
447
struct add_p_state s = {
435
448
{ r }, STRBUF_INIT , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
436
449
};
450
+ size_t i ;
437
451
438
452
init_add_i_state (& s .s , r );
439
453
@@ -446,8 +460,9 @@ int run_add_p(struct repository *r, const struct pathspec *ps)
446
460
return -1 ;
447
461
}
448
462
449
- if (s .hunk_nr )
450
- patch_update_file (& s );
463
+ for (i = 0 ; i < s .file_diff_nr ; i ++ )
464
+ if (patch_update_file (& s , s .file_diff + i ))
465
+ break ;
451
466
452
467
strbuf_release (& s .answer );
453
468
strbuf_release (& s .buf );
0 commit comments