@@ -359,22 +359,25 @@ void git_index_free(git_index *index)
359359 GIT_REFCOUNT_DEC (index , index_free );
360360}
361361
362- void git_index_clear ( git_index * index )
362+ static void index_entries_free ( git_vector * entries )
363363{
364364 size_t i ;
365365
366- assert (index );
367-
368- for (i = 0 ; i < index -> entries .length ; ++ i ) {
369- git_index_entry * e ;
370- e = git_vector_get (& index -> entries , i );
366+ for (i = 0 ; i < entries -> length ; ++ i ) {
367+ git_index_entry * e = git_vector_get (entries , i );
371368 git__free (e -> path );
372369 git__free (e );
373370 }
374- git_vector_clear (& index -> entries );
375371
376- git_index_reuc_clear (index );
372+ git_vector_clear (entries );
373+ }
377374
375+ void git_index_clear (git_index * index )
376+ {
377+ assert (index );
378+
379+ index_entries_free (& index -> entries );
380+ git_index_reuc_clear (index );
378381 git_index_name_clear (index );
379382
380383 git_futils_filestamp_set (& index -> stamp , NULL );
@@ -1951,13 +1954,14 @@ int git_index_entry_stage(const git_index_entry *entry)
19511954
19521955typedef struct read_tree_data {
19531956 git_index * index ;
1954- git_transfer_progress * stats ;
1957+ git_vector * old_entries ;
19551958} read_tree_data ;
19561959
1957- static int read_tree_cb (const char * root , const git_tree_entry * tentry , void * data )
1960+ static int read_tree_cb (
1961+ const char * root , const git_tree_entry * tentry , void * payload )
19581962{
1959- git_index * index = ( git_index * ) data ;
1960- git_index_entry * entry = NULL ;
1963+ read_tree_data * data = payload ;
1964+ git_index_entry * entry = NULL , * old_entry ;
19611965 git_buf path = GIT_BUF_INIT ;
19621966
19631967 if (git_tree_entry__is_tree (tentry ))
@@ -1972,6 +1976,25 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
19721976 entry -> mode = tentry -> attr ;
19731977 entry -> oid = tentry -> oid ;
19741978
1979+ /* look for corresponding old entry and copy data to new entry */
1980+ if (data -> old_entries ) {
1981+ size_t pos ;
1982+ struct entry_srch_key skey ;
1983+
1984+ skey .path = path .ptr ;
1985+ skey .stage = 0 ;
1986+
1987+ if (!git_vector_bsearch2 (
1988+ & pos , data -> old_entries , data -> index -> entries_search , & skey ) &&
1989+ (old_entry = git_vector_get (data -> old_entries , pos )) != NULL &&
1990+ entry -> mode == old_entry -> mode &&
1991+ git_oid_equal (& entry -> oid , & old_entry -> oid ))
1992+ {
1993+ memcpy (entry , old_entry , sizeof (* entry ));
1994+ entry -> flags_extended = 0 ;
1995+ }
1996+ }
1997+
19751998 if (path .size < GIT_IDXENTRY_NAMEMASK )
19761999 entry -> flags = path .size & GIT_IDXENTRY_NAMEMASK ;
19772000 else
@@ -1980,7 +2003,7 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
19802003 entry -> path = git_buf_detach (& path );
19812004 git_buf_free (& path );
19822005
1983- if (git_vector_insert (& index -> entries , entry ) < 0 ) {
2006+ if (git_vector_insert (& data -> index -> entries , entry ) < 0 ) {
19842007 index_entry_free (entry );
19852008 return -1 ;
19862009 }
@@ -1990,9 +2013,26 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
19902013
19912014int git_index_read_tree (git_index * index , const git_tree * tree )
19922015{
2016+ int error = 0 ;
2017+ git_vector entries = GIT_VECTOR_INIT ;
2018+ read_tree_data data ;
2019+
2020+ git_vector_sort (& index -> entries );
2021+
2022+ entries ._cmp = index -> entries ._cmp ;
2023+ git_vector_swap (& entries , & index -> entries );
2024+
19932025 git_index_clear (index );
19942026
1995- return git_tree_walk (tree , GIT_TREEWALK_POST , read_tree_cb , index );
2027+ data .index = index ;
2028+ data .old_entries = & entries ;
2029+
2030+ error = git_tree_walk (tree , GIT_TREEWALK_POST , read_tree_cb , & data );
2031+
2032+ index_entries_free (& entries );
2033+ git_vector_sort (& index -> entries );
2034+
2035+ return error ;
19962036}
19972037
19982038git_repository * git_index_owner (const git_index * index )
0 commit comments