mirror of
https://git.proxmox.com/git/libgit2
synced 2025-11-02 03:01:53 +00:00
diff/index: respect USE_NSEC for racily clean file detection
This commit is contained in:
parent
360dd4dafd
commit
0226f7dd36
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
22
src/index.c
22
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;
|
||||
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user