summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAxel Rasmussen <axelrasmussen@google.com>2015-08-29 13:59:20 -0700
committerAxel Rasmussen <axelrasmussen@google.com>2015-09-18 23:33:56 -0700
commit0226f7dd36c990e9bc1632adbc655fefc797513a (patch)
tree7077e9792dc75e9b7d74813914e2fe08010a8d0d
parent360dd4dafd30bced1dab1d516765e347d09b91ba (diff)
downloadlibgit2-0226f7dd36c990e9bc1632adbc655fefc797513a.tar.gz
diff/index: respect USE_NSEC for racily clean file detection
-rw-r--r--src/diff.c7
-rw-r--r--src/fileops.c12
-rw-r--r--src/fileops.h2
-rw-r--r--src/index.c22
-rw-r--r--tests/checkout/checkout_helpers.c10
-rw-r--r--tests/index/racy.c16
6 files changed, 43 insertions, 26 deletions
diff --git a/src/diff.c b/src/diff.c
index b2259c74d..f8e0c53d3 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -131,7 +131,7 @@ static int diff_delta__from_one(
if (status == GIT_DELTA_UNTRACKED &&
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED))
return 0;
-
+
if (status == GIT_DELTA_UNREADABLE &&
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNREADABLE))
return 0;
@@ -864,7 +864,10 @@ static int maybe_modified(
oitem->ino != nitem->ino ||
oitem->uid != nitem->uid ||
oitem->gid != nitem->gid ||
- (index && nitem->mtime.seconds >= index->stamp.mtime))
+ (index &&
+ ((nitem->mtime.seconds > (int32_t) index->stamp.mtime.tv_sec) ||
+ ((nitem->mtime.seconds == (int32_t) index->stamp.mtime.tv_sec) &&
+ (nitem->mtime.nanoseconds >= (uint32_t) index->stamp.mtime.tv_nsec)))))
{
status = GIT_DELTA_MODIFIED;
modified_uncertain = true;
diff --git a/src/fileops.c b/src/fileops.c
index 57d2ce9c3..da1d8a0bb 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -1035,12 +1035,18 @@ int git_futils_filestamp_check(
if (p_stat(path, &st) < 0)
return GIT_ENOTFOUND;
- if (stamp->mtime == (git_time_t)st.st_mtime &&
+ if (stamp->mtime.tv_sec == st.st_mtim.tv_sec &&
+#if defined(GIT_USE_NSEC)
+ stamp->mtime.tv_nsec == st.st_mtim.tv_nsec &&
+#endif
stamp->size == (git_off_t)st.st_size &&
stamp->ino == (unsigned int)st.st_ino)
return 0;
- stamp->mtime = (git_time_t)st.st_mtime;
+ stamp->mtime.tv_sec = st.st_mtim.tv_sec;
+#if defined(GIT_USE_NSEC)
+ stamp->mtime.tv_nsec = st.st_mtim.tv_nsec;
+#endif
stamp->size = (git_off_t)st.st_size;
stamp->ino = (unsigned int)st.st_ino;
@@ -1063,7 +1069,7 @@ void git_futils_filestamp_set_from_stat(
git_futils_filestamp *stamp, struct stat *st)
{
if (st) {
- stamp->mtime = (git_time_t)st->st_mtime;
+ stamp->mtime = st->st_mtim;
stamp->size = (git_off_t)st->st_size;
stamp->ino = (unsigned int)st->st_ino;
} else {
diff --git a/src/fileops.h b/src/fileops.h
index 572ff01a5..d806e83ba 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -309,7 +309,7 @@ extern int git_futils_fake_symlink(const char *new, const char *old);
* versions could be implemented in the future.
*/
typedef struct {
- git_time_t mtime;
+ struct timespec mtime;
git_off_t size;
unsigned int ino;
} git_futils_filestamp;
diff --git a/src/index.c b/src/index.c
index bd56cc794..5311fe85f 100644
--- a/src/index.c
+++ b/src/index.c
@@ -719,18 +719,27 @@ int git_index__changed_relative_to(
return !!git_oid_cmp(&index->checksum, checksum);
}
-static bool is_racy_timestamp(git_time_t stamp, git_index_entry *entry)
+static bool is_racy_timestamp(const struct timespec *stamp, git_index_entry *entry)
{
/* Git special-cases submodules in the check */
if (S_ISGITLINK(entry->mode))
return false;
/* If we never read the index, we can't have this race either */
- if (stamp == 0)
+ if(stamp->tv_sec == 0)
return false;
/* If the timestamp is the same or newer than the index, it's racy */
- return ((int32_t) stamp) <= entry->mtime.seconds;
+#if defined(GIT_USE_NSEC)
+ if((int32_t) stamp->tv_sec < entry->mtime.seconds)
+ return true;
+ else if((int32_t) stamp->tv_sec > entry->mtime.seconds)
+ return false;
+ else
+ return (uint32_t) stamp->tv_nsec <= entry->mtime.nanoseconds;
+#else
+ return ((int32_t) stamp->tv_sec) <= entry->mtime.seconds;
+#endif
}
/*
@@ -742,7 +751,6 @@ static int truncate_racily_clean(git_index *index)
size_t i;
int error;
git_index_entry *entry;
- git_time_t ts = index->stamp.mtime;
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
git_diff *diff;
@@ -756,7 +764,7 @@ static int truncate_racily_clean(git_index *index)
diff_opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE | GIT_DIFF_IGNORE_SUBMODULES | GIT_DIFF_DISABLE_PATHSPEC_MATCH;
git_vector_foreach(&index->entries, i, entry) {
- if (!is_racy_timestamp(ts, entry))
+ if (!is_racy_timestamp(&index->stamp.mtime, entry))
continue;
/* TODO: use the (non-fnmatching) filelist iterator */
@@ -2875,9 +2883,9 @@ int git_index_read_index(
(error = git_iterator_for_index(&new_iterator, (git_index *)new_index, &opts)) < 0)
goto done;
- if (((error = git_iterator_current(&old_entry, index_iterator)) < 0 &&
+ if (((error = git_iterator_current(&old_entry, index_iterator)) < 0 &&
error != GIT_ITEROVER) ||
- ((error = git_iterator_current(&new_entry, new_iterator)) < 0 &&
+ ((error = git_iterator_current(&new_entry, new_iterator)) < 0 &&
error != GIT_ITEROVER))
goto done;
diff --git a/tests/checkout/checkout_helpers.c b/tests/checkout/checkout_helpers.c
index 92a454d12..fb2f415e7 100644
--- a/tests/checkout/checkout_helpers.c
+++ b/tests/checkout/checkout_helpers.c
@@ -132,7 +132,7 @@ int checkout_count_callback(
void tick_index(git_index *index)
{
- git_time_t ts;
+ struct timespec ts;
struct timeval times[2];
cl_assert(index->on_disk);
@@ -141,10 +141,10 @@ void tick_index(git_index *index)
cl_git_pass(git_index_read(index, true));
ts = index->stamp.mtime;
- times[0].tv_sec = ts;
- times[0].tv_usec = 0;
- times[1].tv_sec = ts + 5;
- times[1].tv_usec = 0;
+ times[0].tv_sec = ts.tv_sec;
+ times[0].tv_usec = ts.tv_nsec / 1000;
+ times[1].tv_sec = ts.tv_sec + 5;
+ times[1].tv_usec = ts.tv_nsec / 1000;
cl_git_pass(p_utimes(git_index_path(index), times));
cl_git_pass(git_index_read(index, true));
diff --git a/tests/index/racy.c b/tests/index/racy.c
index 3b26aabf4..df25c851c 100644
--- a/tests/index/racy.c
+++ b/tests/index/racy.c
@@ -63,10 +63,10 @@ void test_index_racy__write_index_just_after_file(void)
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A"));
cl_git_mkfile(path.ptr, "A");
/* Force the file's timestamp to be a second after we wrote the index */
- times[0].tv_sec = index->stamp.mtime + 1;
- times[0].tv_usec = 0;
- times[1].tv_sec = index->stamp.mtime + 1;
- times[1].tv_usec = 0;
+ times[0].tv_sec = index->stamp.mtime.tv_sec + 1;
+ times[0].tv_usec = index->stamp.mtime.tv_nsec / 1000;
+ times[1].tv_sec = index->stamp.mtime.tv_sec + 1;
+ times[1].tv_usec = index->stamp.mtime.tv_nsec / 1000;
cl_git_pass(p_utimes(path.ptr, times));
/*
@@ -82,10 +82,10 @@ void test_index_racy__write_index_just_after_file(void)
* Pretend this index' modification happend a second after the
* file update, and rewrite the file in that same second.
*/
- times[0].tv_sec = index->stamp.mtime + 2;
- times[0].tv_usec = 0;
- times[1].tv_sec = index->stamp.mtime + 2;
- times[0].tv_usec = 0;
+ times[0].tv_sec = index->stamp.mtime.tv_sec + 2;
+ times[0].tv_usec = index->stamp.mtime.tv_nsec / 1000;
+ times[1].tv_sec = index->stamp.mtime.tv_sec + 2;
+ times[0].tv_usec = index->stamp.mtime.tv_nsec / 1000;
cl_git_pass(p_utimes(git_index_path(index), times));
cl_git_pass(p_utimes(path.ptr, times));