@@ -29,9 +29,12 @@ struct add_p_state {
2929
3030 /* parsed diff */
3131 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 ;
3538};
3639
3740static 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)
131134 struct strbuf * plain = & s -> plain , * colored = NULL ;
132135 struct child_process cp = CHILD_PROCESS_INIT ;
133136 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 ;
135139 struct hunk * hunk = NULL ;
136140 int res ;
137141
@@ -171,7 +175,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
171175 }
172176 argv_array_clear (& args );
173177
174- /* parse hunks */
178+ /* parse files and hunks */
175179 p = plain -> buf ;
176180 pend = p + plain -> len ;
177181 while (p != pend ) {
@@ -180,17 +184,23 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
180184 eol = pend ;
181185
182186 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 ;
186196 } else if (p == plain -> buf )
187197 BUG ("diff starts with unexpected line:\n"
188198 "%.*s\n" , (int )(eol - p ), p );
189199 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 ;
194204 memset (hunk , 0 , sizeof (* hunk ));
195205
196206 hunk -> start = p - plain -> buf ;
@@ -262,16 +272,17 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
262272 hunk -> end - hunk -> start );
263273}
264274
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 )
266277{
267278 struct hunk * hunk ;
268279 size_t i ;
269280 ssize_t delta = 0 ;
270281
271- render_hunk (s , & s -> head , 0 , 0 , out );
282+ render_hunk (s , & file_diff -> head , 0 , 0 , out );
272283
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 ;
275286 if (hunk -> use != USE_HUNK )
276287 delta += hunk -> header .old_count
277288 - hunk -> header .new_count ;
@@ -291,7 +302,8 @@ N_("y - stage this hunk\n"
291302 "K - leave this hunk undecided, see previous hunk\n"
292303 "? - print help\n" );
293304
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 )
295307{
296308 size_t hunk_index = 0 ;
297309 ssize_t i , undecided_previous , undecided_next ;
@@ -300,27 +312,27 @@ static int patch_update_file(struct add_p_state *s)
300312 struct child_process cp = CHILD_PROCESS_INIT ;
301313 int colored = !!s -> colored .len ;
302314
303- if (!s -> hunk_nr )
315+ if (!file_diff -> hunk_nr )
304316 return 0 ;
305317
306318 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 );
308320 fputs (s -> buf .buf , stdout );
309321 for (;;) {
310- if (hunk_index >= s -> hunk_nr )
322+ if (hunk_index >= file_diff -> hunk_nr )
311323 hunk_index = 0 ;
312- hunk = s -> hunk + hunk_index ;
324+ hunk = file_diff -> hunk + hunk_index ;
313325
314326 undecided_previous = -1 ;
315327 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 ) {
317329 undecided_previous = i ;
318330 break ;
319331 }
320332
321333 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 ) {
324336 undecided_next = i ;
325337 break ;
326338 }
@@ -341,7 +353,7 @@ static int patch_update_file(struct add_p_state *s)
341353 strbuf_addstr (& s -> buf , ",K" );
342354 if (undecided_next >= 0 )
343355 strbuf_addstr (& s -> buf , ",j" );
344- if (hunk_index + 1 < s -> hunk_nr )
356+ if (hunk_index + 1 < file_diff -> hunk_nr )
345357 strbuf_addstr (& s -> buf , ",J" );
346358 color_fprintf (stdout , s -> s .prompt_color ,
347359 _ ("Stage this hunk [y,n,a,d%s,?]? " ),
@@ -357,22 +369,22 @@ static int patch_update_file(struct add_p_state *s)
357369 if (ch == 'y' ) {
358370 hunk -> use = USE_HUNK ;
359371soft_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
362374 != UNDECIDED_HUNK )
363375 ; /* continue looking */
364376 } else if (ch == 'n' ) {
365377 hunk -> use = SKIP_HUNK ;
366378 goto soft_increment ;
367379 } 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 ;
370382 if (hunk -> use == UNDECIDED_HUNK )
371383 hunk -> use = USE_HUNK ;
372384 }
373385 } 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 ;
376388 if (hunk -> use == UNDECIDED_HUNK )
377389 hunk -> use = SKIP_HUNK ;
378390 }
@@ -382,7 +394,7 @@ static int patch_update_file(struct add_p_state *s)
382394 else
383395 err (s , _ ("No previous hunk" ));
384396 } else if (s -> answer .buf [0 ] == 'J' ) {
385- if (hunk_index + 1 < s -> hunk_nr )
397+ if (hunk_index + 1 < file_diff -> hunk_nr )
386398 hunk_index ++ ;
387399 else
388400 err (s , _ ("No next hunk" ));
@@ -402,14 +414,14 @@ static int patch_update_file(struct add_p_state *s)
402414 }
403415
404416 /* 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 )
407419 break ;
408420
409- if (i < s -> hunk_nr ) {
421+ if (i < file_diff -> hunk_nr ) {
410422 /* At least one hunk selected: apply */
411423 strbuf_reset (& s -> buf );
412- reassemble_patch (s , & s -> buf );
424+ reassemble_patch (s , file_diff , & s -> buf );
413425
414426 setup_child_process (& cp , s , "apply" , "--cached" , NULL );
415427 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)
427439 struct add_p_state s = {
428440 { r }, STRBUF_INIT , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
429441 };
442+ size_t i ;
430443
431444 if (init_add_i_state (r , & s .s ))
432445 return error ("Could not read `add -i` config" );
@@ -438,8 +451,9 @@ int run_add_p(struct repository *r, const struct pathspec *ps)
438451 return -1 ;
439452 }
440453
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 ;
443457
444458 strbuf_release (& s .answer );
445459 strbuf_release (& s .buf );
0 commit comments