@@ -671,6 +671,31 @@ static int retrieve_stash_trees(
671
671
return error ;
672
672
}
673
673
674
+ static int merge_indexes (
675
+ git_index * * out ,
676
+ git_repository * repo ,
677
+ git_tree * ancestor_tree ,
678
+ git_index * ours_index ,
679
+ git_index * theirs_index )
680
+ {
681
+ git_iterator * ancestor = NULL , * ours = NULL , * theirs = NULL ;
682
+ const git_iterator_flag_t flags = GIT_ITERATOR_DONT_IGNORE_CASE ;
683
+ int error ;
684
+
685
+ if ((error = git_iterator_for_tree (& ancestor , ancestor_tree , flags , NULL , NULL )) < 0 ||
686
+ (error = git_iterator_for_index (& ours , ours_index , flags , NULL , NULL )) < 0 ||
687
+ (error = git_iterator_for_index (& theirs , theirs_index , flags , NULL , NULL )) < 0 )
688
+ goto done ;
689
+
690
+ error = git_merge__iterators (out , repo , ancestor , ours , theirs , NULL );
691
+
692
+ done :
693
+ git_iterator_free (ancestor );
694
+ git_iterator_free (ours );
695
+ git_iterator_free (theirs );
696
+ return error ;
697
+ }
698
+
674
699
static int merge_index_and_tree (
675
700
git_index * * out ,
676
701
git_repository * repo ,
@@ -733,6 +758,70 @@ int git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int ver
733
758
} \
734
759
} while(false);
735
760
761
+ static int ensure_clean_index (git_repository * repo , git_index * index )
762
+ {
763
+ git_tree * head_tree = NULL ;
764
+ git_diff * index_diff = NULL ;
765
+ int error = 0 ;
766
+
767
+ if ((error = git_repository_head_tree (& head_tree , repo )) < 0 ||
768
+ (error = git_diff_tree_to_index (
769
+ & index_diff , repo , head_tree , index , NULL )) < 0 )
770
+ goto done ;
771
+
772
+ if (git_diff_num_deltas (index_diff ) > 0 ) {
773
+ giterr_set (GITERR_STASH , "%d uncommitted changes exist in the index" ,
774
+ git_diff_num_deltas (index_diff ));
775
+ error = GIT_EUNCOMMITTED ;
776
+ }
777
+
778
+ done :
779
+ git_diff_free (index_diff );
780
+ git_tree_free (head_tree );
781
+ return error ;
782
+ }
783
+
784
+ static int stage_new_file (const git_index_entry * * entries , void * data )
785
+ {
786
+ git_index * index = data ;
787
+
788
+ if (entries [0 ] == NULL )
789
+ return git_index_add (index , entries [1 ]);
790
+ else
791
+ return git_index_add (index , entries [0 ]);
792
+ }
793
+
794
+ static int stage_new_files (
795
+ git_index * * out ,
796
+ git_repository * repo ,
797
+ git_tree * parent_tree ,
798
+ git_tree * tree )
799
+ {
800
+ git_iterator * iterators [2 ] = { NULL , NULL };
801
+ git_index * index = NULL ;
802
+ int error ;
803
+
804
+ if ((error = git_index_new (& index )) < 0 ||
805
+ (error = git_iterator_for_tree (& iterators [0 ], parent_tree ,
806
+ GIT_ITERATOR_DONT_IGNORE_CASE , NULL , NULL )) < 0 ||
807
+ (error = git_iterator_for_tree (& iterators [1 ], tree ,
808
+ GIT_ITERATOR_DONT_IGNORE_CASE , NULL , NULL )) < 0 )
809
+ goto done ;
810
+
811
+ error = git_iterator_walk (iterators , 2 , stage_new_file , index );
812
+
813
+ done :
814
+ if (error < 0 )
815
+ git_index_free (index );
816
+ else
817
+ * out = index ;
818
+
819
+ git_iterator_free (iterators [0 ]);
820
+ git_iterator_free (iterators [1 ]);
821
+
822
+ return error ;
823
+ }
824
+
736
825
int git_stash_apply (
737
826
git_repository * repo ,
738
827
size_t index ,
@@ -746,6 +835,7 @@ int git_stash_apply(
746
835
git_tree * index_tree = NULL ;
747
836
git_tree * index_parent_tree = NULL ;
748
837
git_tree * untracked_tree = NULL ;
838
+ git_index * stash_adds = NULL ;
749
839
git_index * repo_index = NULL ;
750
840
git_index * unstashed_index = NULL ;
751
841
git_index * modified_index = NULL ;
@@ -775,6 +865,9 @@ int git_stash_apply(
775
865
776
866
NOTIFY_PROGRESS (opts , GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX );
777
867
868
+ if ((error = ensure_clean_index (repo , repo_index )) < 0 )
869
+ goto cleanup ;
870
+
778
871
/* Restore index if required */
779
872
if ((opts .flags & GIT_STASH_APPLY_REINSTATE_INDEX ) &&
780
873
git_oid_cmp (git_tree_id (stash_parent_tree ), git_tree_id (index_tree ))) {
@@ -787,6 +880,16 @@ int git_stash_apply(
787
880
error = GIT_ECONFLICT ;
788
881
goto cleanup ;
789
882
}
883
+
884
+ /* Otherwise, stage any new files in the stash tree. (Note: their
885
+ * previously unstaged contents are staged, not the previously staged.)
886
+ */
887
+ } else if ((opts .flags & GIT_STASH_APPLY_REINSTATE_INDEX ) == 0 ) {
888
+ if ((error = stage_new_files (
889
+ & stash_adds , repo , stash_parent_tree , stash_tree )) < 0 ||
890
+ (error = merge_indexes (
891
+ & unstashed_index , repo , stash_parent_tree , repo_index , stash_adds )) < 0 )
892
+ goto cleanup ;
790
893
}
791
894
792
895
NOTIFY_PROGRESS (opts , GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED );
@@ -848,6 +951,7 @@ int git_stash_apply(
848
951
git_index_free (untracked_index );
849
952
git_index_free (modified_index );
850
953
git_index_free (unstashed_index );
954
+ git_index_free (stash_adds );
851
955
git_index_free (repo_index );
852
956
git_tree_free (untracked_tree );
853
957
git_tree_free (index_parent_tree );
0 commit comments