summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-06-15 09:55:40 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2015-06-16 08:40:45 +0200
commit316b820b6fed712d4b6fae886ba1e6c44afc6c81 (patch)
treecce49e5c16dde5ae3bfe3b4c7b488dec639fc519
parent77596fcfd7cd14d0998b333af5f2d11ffea84843 (diff)
downloadlibgit2-316b820b6fed712d4b6fae886ba1e6c44afc6c81.tar.gz
index: zero the size of racily-clean entries
If a file entry has the same timestamp as the index itself, it is considered racily-clean, as it may have been modified after the index was written, but during the same second. We take extra steps to check the contents, but this is just one part of avoiding races. For files which do have changes but have not been updated in the index, updating the on-disk index means updating its timestamp, which means we would no longer recognise these entries as racy and we would trust the timestamp to tell us whether they have changed. In order to work around this, git zeroes out the file-size field in entries with the same timestamp as the index in order to force the next diff to check the contents. Do so in libgit2 as well.
-rw-r--r--src/index.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/index.c b/src/index.c
index 14d8d3684..a931f048a 100644
--- a/src/index.c
+++ b/src/index.c
@@ -658,11 +658,29 @@ int git_index__changed_relative_to(
index->stamp.ino != fs->ino);
}
+/*
+ * Force the next diff to take a look at those entries which have the
+ * same timestamp as the current index.
+ */
+static void truncate_racily_clean(git_index *index)
+{
+ size_t i;
+ git_index_entry *entry;
+ git_time_t ts = index->stamp.mtime;
+
+ git_vector_foreach(&index->entries, i, entry) {
+ if (entry->mtime.seconds == ts || ts == 0)
+ entry->file_size = 0;
+ }
+}
+
int git_index_write(git_index *index)
{
git_indexwriter writer = GIT_INDEXWRITER_INIT;
int error;
+ truncate_racily_clean(index);
+
if ((error = git_indexwriter_init(&writer, index)) == 0)
error = git_indexwriter_commit(&writer);