diff options
author | Axel Rasmussen <axelrasmussen@google.com> | 2015-08-29 13:59:20 -0700 |
---|---|---|
committer | Axel Rasmussen <axelrasmussen@google.com> | 2015-09-18 23:33:56 -0700 |
commit | 0226f7dd36c990e9bc1632adbc655fefc797513a (patch) | |
tree | 7077e9792dc75e9b7d74813914e2fe08010a8d0d | |
parent | 360dd4dafd30bced1dab1d516765e347d09b91ba (diff) | |
download | libgit2-0226f7dd36c990e9bc1632adbc655fefc797513a.tar.gz |
diff/index: respect USE_NSEC for racily clean file detection
-rw-r--r-- | src/diff.c | 7 | ||||
-rw-r--r-- | src/fileops.c | 12 | ||||
-rw-r--r-- | src/fileops.h | 2 | ||||
-rw-r--r-- | src/index.c | 22 | ||||
-rw-r--r-- | tests/checkout/checkout_helpers.c | 10 | ||||
-rw-r--r-- | tests/index/racy.c | 16 |
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)); |