Commit 0226f7dd by Axel Rasmussen

diff/index: respect USE_NSEC for racily clean file detection

parent 360dd4da
...@@ -131,7 +131,7 @@ static int diff_delta__from_one( ...@@ -131,7 +131,7 @@ static int diff_delta__from_one(
if (status == GIT_DELTA_UNTRACKED && if (status == GIT_DELTA_UNTRACKED &&
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED)) DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED))
return 0; return 0;
if (status == GIT_DELTA_UNREADABLE && if (status == GIT_DELTA_UNREADABLE &&
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNREADABLE)) DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNREADABLE))
return 0; return 0;
...@@ -864,7 +864,10 @@ static int maybe_modified( ...@@ -864,7 +864,10 @@ static int maybe_modified(
oitem->ino != nitem->ino || oitem->ino != nitem->ino ||
oitem->uid != nitem->uid || oitem->uid != nitem->uid ||
oitem->gid != nitem->gid || 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; status = GIT_DELTA_MODIFIED;
modified_uncertain = true; modified_uncertain = true;
......
...@@ -1035,12 +1035,18 @@ int git_futils_filestamp_check( ...@@ -1035,12 +1035,18 @@ int git_futils_filestamp_check(
if (p_stat(path, &st) < 0) if (p_stat(path, &st) < 0)
return GIT_ENOTFOUND; 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->size == (git_off_t)st.st_size &&
stamp->ino == (unsigned int)st.st_ino) stamp->ino == (unsigned int)st.st_ino)
return 0; 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->size = (git_off_t)st.st_size;
stamp->ino = (unsigned int)st.st_ino; stamp->ino = (unsigned int)st.st_ino;
...@@ -1063,7 +1069,7 @@ void git_futils_filestamp_set_from_stat( ...@@ -1063,7 +1069,7 @@ void git_futils_filestamp_set_from_stat(
git_futils_filestamp *stamp, struct stat *st) git_futils_filestamp *stamp, struct stat *st)
{ {
if (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->size = (git_off_t)st->st_size;
stamp->ino = (unsigned int)st->st_ino; stamp->ino = (unsigned int)st->st_ino;
} else { } else {
......
...@@ -309,7 +309,7 @@ extern int git_futils_fake_symlink(const char *new, const char *old); ...@@ -309,7 +309,7 @@ extern int git_futils_fake_symlink(const char *new, const char *old);
* versions could be implemented in the future. * versions could be implemented in the future.
*/ */
typedef struct { typedef struct {
git_time_t mtime; struct timespec mtime;
git_off_t size; git_off_t size;
unsigned int ino; unsigned int ino;
} git_futils_filestamp; } git_futils_filestamp;
......
...@@ -719,18 +719,27 @@ int git_index__changed_relative_to( ...@@ -719,18 +719,27 @@ int git_index__changed_relative_to(
return !!git_oid_cmp(&index->checksum, checksum); 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 */ /* Git special-cases submodules in the check */
if (S_ISGITLINK(entry->mode)) if (S_ISGITLINK(entry->mode))
return false; return false;
/* If we never read the index, we can't have this race either */ /* If we never read the index, we can't have this race either */
if (stamp == 0) if(stamp->tv_sec == 0)
return false; return false;
/* If the timestamp is the same or newer than the index, it's racy */ /* 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) ...@@ -742,7 +751,6 @@ static int truncate_racily_clean(git_index *index)
size_t i; size_t i;
int error; int error;
git_index_entry *entry; git_index_entry *entry;
git_time_t ts = index->stamp.mtime;
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
git_diff *diff; git_diff *diff;
...@@ -756,7 +764,7 @@ static int truncate_racily_clean(git_index *index) ...@@ -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; diff_opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE | GIT_DIFF_IGNORE_SUBMODULES | GIT_DIFF_DISABLE_PATHSPEC_MATCH;
git_vector_foreach(&index->entries, i, entry) { git_vector_foreach(&index->entries, i, entry) {
if (!is_racy_timestamp(ts, entry)) if (!is_racy_timestamp(&index->stamp.mtime, entry))
continue; continue;
/* TODO: use the (non-fnmatching) filelist iterator */ /* TODO: use the (non-fnmatching) filelist iterator */
...@@ -2875,9 +2883,9 @@ int git_index_read_index( ...@@ -2875,9 +2883,9 @@ int git_index_read_index(
(error = git_iterator_for_index(&new_iterator, (git_index *)new_index, &opts)) < 0) (error = git_iterator_for_index(&new_iterator, (git_index *)new_index, &opts)) < 0)
goto done; 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_ITEROVER) ||
((error = git_iterator_current(&new_entry, new_iterator)) < 0 && ((error = git_iterator_current(&new_entry, new_iterator)) < 0 &&
error != GIT_ITEROVER)) error != GIT_ITEROVER))
goto done; goto done;
......
...@@ -132,7 +132,7 @@ int checkout_count_callback( ...@@ -132,7 +132,7 @@ int checkout_count_callback(
void tick_index(git_index *index) void tick_index(git_index *index)
{ {
git_time_t ts; struct timespec ts;
struct timeval times[2]; struct timeval times[2];
cl_assert(index->on_disk); cl_assert(index->on_disk);
...@@ -141,10 +141,10 @@ void tick_index(git_index *index) ...@@ -141,10 +141,10 @@ void tick_index(git_index *index)
cl_git_pass(git_index_read(index, true)); cl_git_pass(git_index_read(index, true));
ts = index->stamp.mtime; ts = index->stamp.mtime;
times[0].tv_sec = ts; times[0].tv_sec = ts.tv_sec;
times[0].tv_usec = 0; times[0].tv_usec = ts.tv_nsec / 1000;
times[1].tv_sec = ts + 5; times[1].tv_sec = ts.tv_sec + 5;
times[1].tv_usec = 0; times[1].tv_usec = ts.tv_nsec / 1000;
cl_git_pass(p_utimes(git_index_path(index), times)); cl_git_pass(p_utimes(git_index_path(index), times));
cl_git_pass(git_index_read(index, true)); cl_git_pass(git_index_read(index, true));
......
...@@ -63,10 +63,10 @@ void test_index_racy__write_index_just_after_file(void) ...@@ -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_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A"));
cl_git_mkfile(path.ptr, "A"); cl_git_mkfile(path.ptr, "A");
/* Force the file's timestamp to be a second after we wrote the index */ /* 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_sec = index->stamp.mtime.tv_sec + 1;
times[0].tv_usec = 0; times[0].tv_usec = index->stamp.mtime.tv_nsec / 1000;
times[1].tv_sec = index->stamp.mtime + 1; times[1].tv_sec = index->stamp.mtime.tv_sec + 1;
times[1].tv_usec = 0; times[1].tv_usec = index->stamp.mtime.tv_nsec / 1000;
cl_git_pass(p_utimes(path.ptr, times)); cl_git_pass(p_utimes(path.ptr, times));
/* /*
...@@ -82,10 +82,10 @@ void test_index_racy__write_index_just_after_file(void) ...@@ -82,10 +82,10 @@ void test_index_racy__write_index_just_after_file(void)
* Pretend this index' modification happend a second after the * Pretend this index' modification happend a second after the
* file update, and rewrite the file in that same second. * file update, and rewrite the file in that same second.
*/ */
times[0].tv_sec = index->stamp.mtime + 2; times[0].tv_sec = index->stamp.mtime.tv_sec + 2;
times[0].tv_usec = 0; times[0].tv_usec = index->stamp.mtime.tv_nsec / 1000;
times[1].tv_sec = index->stamp.mtime + 2; times[1].tv_sec = index->stamp.mtime.tv_sec + 2;
times[0].tv_usec = 0; 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(git_index_path(index), times));
cl_git_pass(p_utimes(path.ptr, times)); cl_git_pass(p_utimes(path.ptr, times));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment