@@ -135,6 +135,8 @@ struct reuc_entry_internal {
135135 char path [GIT_FLEX_ARRAY ];
136136};
137137
138+ bool git_index__enforce_unsaved_safety = false;
139+
138140/* local declarations */
139141static size_t read_extension (git_index * index , const char * buffer , size_t buffer_size );
140142static int read_header (struct index_header * dest , const void * buffer );
@@ -516,6 +518,8 @@ static int index_remove_entry(git_index *index, size_t pos)
516518 } else {
517519 index_entry_free (entry );
518520 }
521+
522+ index -> dirty = 1 ;
519523 }
520524
521525 return error ;
@@ -527,6 +531,7 @@ int git_index_clear(git_index *index)
527531
528532 assert (index );
529533
534+ index -> dirty = 1 ;
530535 index -> tree = NULL ;
531536 git_pool_clear (& index -> tree_pool );
532537
@@ -637,8 +642,10 @@ int git_index_read(git_index *index, int force)
637642 index -> on_disk = git_path_exists (index -> index_file_path );
638643
639644 if (!index -> on_disk ) {
640- if (force )
641- return git_index_clear (index );
645+ if (force && (error = git_index_clear (index )) < 0 )
646+ return error ;
647+
648+ index -> dirty = 0 ;
642649 return 0 ;
643650 }
644651
@@ -650,6 +657,7 @@ int git_index_read(git_index *index, int force)
650657 index -> index_file_path );
651658 return updated ;
652659 }
660+
653661 if (!updated && !force )
654662 return 0 ;
655663
@@ -665,13 +673,26 @@ int git_index_read(git_index *index, int force)
665673 if (!error )
666674 error = parse_index (index , buffer .ptr , buffer .size );
667675
668- if (!error )
676+ if (!error ) {
669677 git_futils_filestamp_set (& index -> stamp , & stamp );
678+ index -> dirty = 0 ;
679+ }
670680
671681 git_buf_dispose (& buffer );
672682 return error ;
673683}
674684
685+ int git_index_read_safely (git_index * index )
686+ {
687+ if (git_index__enforce_unsaved_safety && index -> dirty ) {
688+ giterr_set (GITERR_INDEX ,
689+ "the index has unsaved changes that would be overwritten by this operation" );
690+ return GIT_EINDEXDIRTY ;
691+ }
692+
693+ return git_index_read (index , false);
694+ }
695+
675696int git_index__changed_relative_to (
676697 git_index * index , const git_oid * checksum )
677698{
@@ -735,8 +756,10 @@ static int truncate_racily_clean(git_index *index)
735756 /* Ensure that we have a stage 0 for this file (ie, it's not a
736757 * conflict), otherwise smudging it is quite pointless.
737758 */
738- if (entry )
759+ if (entry ) {
739760 entry -> file_size = 0 ;
761+ index -> dirty = 1 ;
762+ }
740763 }
741764
742765done :
@@ -774,8 +797,9 @@ int git_index_write(git_index *index)
774797
775798 truncate_racily_clean (index );
776799
777- if ((error = git_indexwriter_init (& writer , index )) == 0 )
778- error = git_indexwriter_commit (& writer );
800+ if ((error = git_indexwriter_init (& writer , index )) == 0 &&
801+ (error = git_indexwriter_commit (& writer )) == 0 )
802+ index -> dirty = 0 ;
779803
780804 git_indexwriter_cleanup (& writer );
781805
@@ -1389,6 +1413,8 @@ static int index_insert(
13891413 if (error < 0 ) {
13901414 index_entry_free (* entry_ptr );
13911415 * entry_ptr = NULL ;
1416+ } else {
1417+ index -> dirty = 1 ;
13921418 }
13931419
13941420 return error ;
@@ -1616,6 +1642,8 @@ int git_index__fill(git_index *index, const git_vector *source_entries)
16161642 INSERT_IN_MAP (index , entry , & ret );
16171643 if (ret < 0 )
16181644 break ;
1645+
1646+ index -> dirty = 1 ;
16191647 }
16201648
16211649 if (!ret )
@@ -2053,6 +2081,7 @@ int git_index_name_add(git_index *index,
20532081 return -1 ;
20542082 }
20552083
2084+ index -> dirty = 1 ;
20562085 return 0 ;
20572086}
20582087
@@ -2067,6 +2096,8 @@ void git_index_name_clear(git_index *index)
20672096 index_name_entry_free (conflict_name );
20682097
20692098 git_vector_clear (& index -> names );
2099+
2100+ index -> dirty = 1 ;
20702101}
20712102
20722103size_t git_index_reuc_entrycount (git_index * index )
@@ -2092,6 +2123,8 @@ static int index_reuc_insert(
20922123 assert (git_vector_is_sorted (& index -> reuc ));
20932124
20942125 res = git_vector_insert_sorted (& index -> reuc , reuc , & index_reuc_on_dup );
2126+ index -> dirty = 1 ;
2127+
20952128 return res == GIT_EEXISTS ? 0 : res ;
20962129}
20972130
@@ -2157,6 +2190,7 @@ int git_index_reuc_remove(git_index *index, size_t position)
21572190 if (!error )
21582191 index_entry_reuc_free (reuc );
21592192
2193+ index -> dirty = 1 ;
21602194 return error ;
21612195}
21622196
@@ -2170,6 +2204,8 @@ void git_index_reuc_clear(git_index *index)
21702204 index_entry_reuc_free (git__swap (index -> reuc .contents [i ], NULL ));
21712205
21722206 git_vector_clear (& index -> reuc );
2207+
2208+ index -> dirty = 1 ;
21732209}
21742210
21752211static int index_error_invalid (const char * message )
@@ -2604,6 +2640,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
26042640 git_vector_set_sorted (& index -> entries , !index -> ignore_case );
26052641 git_vector_sort (& index -> entries );
26062642
2643+ index -> dirty = 0 ;
26072644done :
26082645 return error ;
26092646}
@@ -3070,6 +3107,8 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
30703107 entries_map = git__swap (index -> entries_map , entries_map );
30713108 }
30723109
3110+ index -> dirty = 1 ;
3111+
30733112cleanup :
30743113 git_vector_free (& entries );
30753114 git_idxmap_free (entries_map );
@@ -3209,6 +3248,7 @@ static int git_index_read_iterator(
32093248
32103249 clear_uptodate (index );
32113250
3251+ index -> dirty = 1 ;
32123252 error = 0 ;
32133253
32143254done :
@@ -3601,6 +3641,7 @@ int git_indexwriter_commit(git_indexwriter *writer)
36013641 return -1 ;
36023642 }
36033643
3644+ writer -> index -> dirty = 0 ;
36043645 writer -> index -> on_disk = 1 ;
36053646 git_oid_cpy (& writer -> index -> checksum , & checksum );
36063647
0 commit comments