index: add a dirty bit reflecting unsaved changes Teach the index when it is "dirty", and has unsaved changes. Consider the index dirty whenever a caller has added or removed an entry from the main index, REUC or NAME section, including when the index is completely cleared. Similarly, consider the index _not_ dirty immediately after it is written, or when it is read from the on-disk index. This allows us to ensure that unsaved changes are not lost when we automatically refresh the index.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
diff --git a/src/index.c b/src/index.c
index 67c844c..0876c22 100644
--- a/src/index.c
+++ b/src/index.c
@@ -516,6 +516,8 @@ static int index_remove_entry(git_index *index, size_t pos)
} else {
index_entry_free(entry);
}
+
+ index->dirty = 1;
}
return error;
@@ -527,6 +529,7 @@ int git_index_clear(git_index *index)
assert(index);
+ index->dirty = 1;
index->tree = NULL;
git_pool_clear(&index->tree_pool);
@@ -637,8 +640,10 @@ int git_index_read(git_index *index, int force)
index->on_disk = git_path_exists(index->index_file_path);
if (!index->on_disk) {
- if (force)
- return git_index_clear(index);
+ if (force && (error = git_index_clear(index)) < 0)
+ return error;
+
+ index->dirty = 0;
return 0;
}
@@ -650,6 +655,7 @@ int git_index_read(git_index *index, int force)
index->index_file_path);
return updated;
}
+
if (!updated && !force)
return 0;
@@ -665,8 +671,10 @@ int git_index_read(git_index *index, int force)
if (!error)
error = parse_index(index, buffer.ptr, buffer.size);
- if (!error)
+ if (!error) {
git_futils_filestamp_set(&index->stamp, &stamp);
+ index->dirty = 0;
+ }
git_buf_dispose(&buffer);
return error;
@@ -735,8 +743,10 @@ static int truncate_racily_clean(git_index *index)
/* Ensure that we have a stage 0 for this file (ie, it's not a
* conflict), otherwise smudging it is quite pointless.
*/
- if (entry)
+ if (entry) {
entry->file_size = 0;
+ index->dirty = 1;
+ }
}
done:
@@ -774,8 +784,9 @@ int git_index_write(git_index *index)
truncate_racily_clean(index);
- if ((error = git_indexwriter_init(&writer, index)) == 0)
- error = git_indexwriter_commit(&writer);
+ if ((error = git_indexwriter_init(&writer, index)) == 0 &&
+ (error = git_indexwriter_commit(&writer)) == 0)
+ index->dirty = 0;
git_indexwriter_cleanup(&writer);
@@ -1389,6 +1400,8 @@ static int index_insert(
if (error < 0) {
index_entry_free(*entry_ptr);
*entry_ptr = NULL;
+ } else {
+ index->dirty = 1;
}
return error;
@@ -1616,6 +1629,8 @@ int git_index__fill(git_index *index, const git_vector *source_entries)
INSERT_IN_MAP(index, entry, &ret);
if (ret < 0)
break;
+
+ index->dirty = 1;
}
if (!ret)
@@ -2053,6 +2068,7 @@ int git_index_name_add(git_index *index,
return -1;
}
+ index->dirty = 1;
return 0;
}
@@ -2067,6 +2083,8 @@ void git_index_name_clear(git_index *index)
index_name_entry_free(conflict_name);
git_vector_clear(&index->names);
+
+ index->dirty = 1;
}
size_t git_index_reuc_entrycount(git_index *index)
@@ -2092,6 +2110,8 @@ static int index_reuc_insert(
assert(git_vector_is_sorted(&index->reuc));
res = git_vector_insert_sorted(&index->reuc, reuc, &index_reuc_on_dup);
+ index->dirty = 1;
+
return res == GIT_EEXISTS ? 0 : res;
}
@@ -2157,6 +2177,7 @@ int git_index_reuc_remove(git_index *index, size_t position)
if (!error)
index_entry_reuc_free(reuc);
+ index->dirty = 1;
return error;
}
@@ -2170,6 +2191,8 @@ void git_index_reuc_clear(git_index *index)
index_entry_reuc_free(git__swap(index->reuc.contents[i], NULL));
git_vector_clear(&index->reuc);
+
+ index->dirty = 1;
}
static int index_error_invalid(const char *message)
@@ -2604,6 +2627,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
git_vector_set_sorted(&index->entries, !index->ignore_case);
git_vector_sort(&index->entries);
+ index->dirty = 0;
done:
return error;
}
@@ -3070,6 +3094,8 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
entries_map = git__swap(index->entries_map, entries_map);
}
+ index->dirty = 1;
+
cleanup:
git_vector_free(&entries);
git_idxmap_free(entries_map);
@@ -3209,6 +3235,7 @@ static int git_index_read_iterator(
clear_uptodate(index);
+ index->dirty = 1;
error = 0;
done:
@@ -3601,6 +3628,7 @@ int git_indexwriter_commit(git_indexwriter *writer)
return -1;
}
+ writer->index->dirty = 0;
writer->index->on_disk = 1;
git_oid_cpy(&writer->index->checksum, &checksum);
diff --git a/src/index.h b/src/index.h
index 0f1c095..8bf1008 100644
--- a/src/index.h
+++ b/src/index.h
@@ -37,6 +37,7 @@ struct git_index {
unsigned int ignore_case:1;
unsigned int distrust_filemode:1;
unsigned int no_symlinks:1;
+ unsigned int dirty:1; /* whether we have unsaved changes */
git_tree_cache *tree;
git_pool tree_pool;
@@ -143,6 +144,11 @@ extern int git_index_snapshot_find(
/* Replace an index with a new index */
int git_index_read_index(git_index *index, const git_index *new_index);
+GIT_INLINE(int) git_index_is_dirty(git_index *index)
+{
+ return index->dirty;
+}
+
typedef struct {
git_index *index;
git_filebuf file;