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