@@ -422,6 +422,7 @@ static int apply_one(
422422 git_repository * repo ,
423423 git_reader * preimage_reader ,
424424 git_index * preimage ,
425+ git_reader * postimage_reader ,
425426 git_index * postimage ,
426427 git_diff * diff ,
427428 size_t i ,
@@ -435,6 +436,7 @@ static int apply_one(
435436 git_oid pre_id , post_id ;
436437 git_filemode_t pre_filemode ;
437438 git_index_entry pre_entry , post_entry ;
439+ bool skip_preimage = false;
438440 int error ;
439441
440442 if ((error = git_patch_from_diff (& patch , diff , i )) < 0 )
@@ -453,7 +455,26 @@ static int apply_one(
453455 }
454456 }
455457
456- if (delta -> status != GIT_DELTA_ADDED ) {
458+ /*
459+ * We may be applying a second delta to an already seen file. If so,
460+ * use the already modified data in the postimage instead of the
461+ * content from the index or working directory. (Renames must be
462+ * specified before additional deltas since we are applying deltas
463+ * to the _target_ filename.)
464+ */
465+ if (delta -> status != GIT_DELTA_RENAMED ) {
466+ if ((error = git_reader_read (& pre_contents , & pre_id , & pre_filemode ,
467+ postimage_reader , delta -> old_file .path )) == 0 ) {
468+ skip_preimage = true;
469+ } else if (error == GIT_ENOTFOUND ) {
470+ giterr_clear ();
471+ error = 0 ;
472+ } else {
473+ goto done ;
474+ }
475+ }
476+
477+ if (!skip_preimage && delta -> status != GIT_DELTA_ADDED ) {
457478 error = git_reader_read (& pre_contents , & pre_id , & pre_filemode ,
458479 preimage_reader , delta -> old_file .path );
459480
@@ -527,7 +548,7 @@ int git_apply_to_tree(
527548 const git_apply_options * given_opts )
528549{
529550 git_index * postimage = NULL ;
530- git_reader * pre_reader = NULL ;
551+ git_reader * pre_reader = NULL , * post_reader = NULL ;
531552 git_apply_options opts = GIT_APPLY_OPTIONS_INIT ;
532553 const git_diff_delta * delta ;
533554 size_t i ;
@@ -548,7 +569,8 @@ int git_apply_to_tree(
548569 * replace any entries contained therein
549570 */
550571 if ((error = git_index_new (& postimage )) < 0 ||
551- (error = git_index_read_tree (postimage , preimage )) < 0 )
572+ (error = git_index_read_tree (postimage , preimage )) < 0 ||
573+ (error = git_reader_for_index (& post_reader , repo , postimage )) < 0 )
552574 goto done ;
553575
554576 /*
@@ -565,7 +587,7 @@ int git_apply_to_tree(
565587 }
566588
567589 for (i = 0 ; i < git_diff_num_deltas (diff ); i ++ ) {
568- if ((error = apply_one (repo , pre_reader , NULL , postimage , diff , i , & opts )) < 0 )
590+ if ((error = apply_one (repo , pre_reader , NULL , post_reader , postimage , diff , i , & opts )) < 0 )
569591 goto done ;
570592 }
571593
@@ -576,6 +598,7 @@ int git_apply_to_tree(
576598 git_index_free (postimage );
577599
578600 git_reader_free (pre_reader );
601+ git_reader_free (post_reader );
579602
580603 return error ;
581604}
@@ -700,7 +723,7 @@ int git_apply(
700723{
701724 git_indexwriter indexwriter = GIT_INDEXWRITER_INIT ;
702725 git_index * index = NULL , * preimage = NULL , * postimage = NULL ;
703- git_reader * pre_reader = NULL ;
726+ git_reader * pre_reader = NULL , * post_reader = NULL ;
704727 git_apply_options opts = GIT_APPLY_OPTIONS_INIT ;
705728 size_t i ;
706729 int error = GIT_EINVALID ;
@@ -743,15 +766,16 @@ int git_apply(
743766 * to only write these files that were affected by the diff.
744767 */
745768 if ((error = git_index_new (& preimage )) < 0 ||
746- (error = git_index_new (& postimage )) < 0 )
769+ (error = git_index_new (& postimage )) < 0 ||
770+ (error = git_reader_for_index (& post_reader , repo , postimage )) < 0 )
747771 goto done ;
748772
749773 if ((error = git_repository_index (& index , repo )) < 0 ||
750774 (error = git_indexwriter_init (& indexwriter , index )) < 0 )
751775 goto done ;
752776
753777 for (i = 0 ; i < git_diff_num_deltas (diff ); i ++ ) {
754- if ((error = apply_one (repo , pre_reader , preimage , postimage , diff , i , & opts )) < 0 )
778+ if ((error = apply_one (repo , pre_reader , preimage , post_reader , postimage , diff , i , & opts )) < 0 )
755779 goto done ;
756780 }
757781
@@ -780,6 +804,7 @@ int git_apply(
780804 git_index_free (preimage );
781805 git_index_free (index );
782806 git_reader_free (pre_reader );
807+ git_reader_free (post_reader );
783808
784809 return error ;
785810}
0 commit comments