mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-08 12:14:16 +00:00
checkout: only consider nsecs when built that way
When examining the working directory and determining whether it's up-to-date, only consider the nanoseconds in the index entry when built with `GIT_USE_NSEC`. This prevents us from believing that the working directory is always dirty when the index was originally written with a git client that uinderstands nsecs (like git 2.x).
This commit is contained in:
parent
66e4e6da59
commit
25e84f959a
@ -200,8 +200,7 @@ static bool checkout_is_workdir_modified(
|
||||
* out.)
|
||||
*/
|
||||
if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) {
|
||||
if (wditem->mtime.seconds == ie->mtime.seconds &&
|
||||
wditem->mtime.nanoseconds == ie->mtime.nanoseconds &&
|
||||
if (git_index_time_eq(&wditem->mtime, &ie->mtime) &&
|
||||
wditem->file_size == ie->file_size)
|
||||
return !is_workdir_base_or_new(&ie->id, baseitem, newitem);
|
||||
}
|
||||
|
49
src/diff.c
49
src/diff.c
@ -494,11 +494,6 @@ static int diff_list_apply_options(
|
||||
|
||||
/* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */
|
||||
|
||||
/* Don't trust nanoseconds; we do not load nanos from disk */
|
||||
#ifdef GIT_USE_NSEC
|
||||
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_NANOSECS;
|
||||
#endif
|
||||
|
||||
/* If not given explicit `opts`, check `diff.xyz` configs */
|
||||
if (!opts) {
|
||||
int context = git_config__get_int_force(cfg, "diff.context", 3);
|
||||
@ -699,38 +694,6 @@ int git_diff__oid_for_entry(
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool diff_time_eq(
|
||||
const git_index_time *a, const git_index_time *b, bool use_nanos)
|
||||
{
|
||||
return a->seconds == b->seconds &&
|
||||
(!use_nanos || a->nanoseconds == b->nanoseconds);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the given index time is newer than the given existing index entry.
|
||||
* If the timestamps are exactly equivalent, then the given index time is
|
||||
* considered "racily newer" than the existing index entry.
|
||||
*/
|
||||
static bool diff_newer_than_index(
|
||||
const git_index_time *a, const git_index *b, bool use_nanos)
|
||||
{
|
||||
bool is_newer = false;
|
||||
|
||||
if(!b)
|
||||
return false;
|
||||
|
||||
is_newer = is_newer || (a->seconds > (int32_t) b->stamp.mtime.tv_sec);
|
||||
is_newer = is_newer || (!use_nanos &&
|
||||
(a->seconds == (int32_t) b->stamp.mtime.tv_sec));
|
||||
if(use_nanos)
|
||||
{
|
||||
is_newer = is_newer || ((a->seconds == (int32_t) b->stamp.mtime.tv_sec) &&
|
||||
(a->nanoseconds >= (uint32_t) b->stamp.mtime.tv_nsec));
|
||||
}
|
||||
|
||||
return is_newer;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
git_repository *repo;
|
||||
git_iterator *old_iter;
|
||||
@ -863,11 +826,6 @@ static int maybe_modified(
|
||||
*/
|
||||
} else if (git_oid_iszero(&nitem->id) && new_is_workdir) {
|
||||
bool use_ctime = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) != 0);
|
||||
#ifdef GIT_USE_NSEC
|
||||
bool use_nanos = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_NANOSECS) != 0);
|
||||
#else
|
||||
bool use_nanos = false;
|
||||
#endif
|
||||
git_index *index;
|
||||
git_iterator_index(&index, info->new_iter);
|
||||
|
||||
@ -886,13 +844,12 @@ static int maybe_modified(
|
||||
modified_uncertain =
|
||||
(oitem->file_size <= 0 && nitem->file_size > 0);
|
||||
}
|
||||
else if (!diff_time_eq(&oitem->mtime, &nitem->mtime, use_nanos) ||
|
||||
(use_ctime &&
|
||||
!diff_time_eq(&oitem->ctime, &nitem->ctime, use_nanos)) ||
|
||||
else if (!git_index_time_eq(&oitem->mtime, &nitem->mtime) ||
|
||||
(use_ctime && !git_index_time_eq(&oitem->ctime, &nitem->ctime)) ||
|
||||
oitem->ino != nitem->ino ||
|
||||
oitem->uid != nitem->uid ||
|
||||
oitem->gid != nitem->gid ||
|
||||
diff_newer_than_index(&nitem->mtime, index, use_nanos))
|
||||
git_index_entry_newer_than_index(nitem, index))
|
||||
{
|
||||
status = GIT_DELTA_MODIFIED;
|
||||
modified_uncertain = true;
|
||||
|
@ -28,7 +28,6 @@ enum {
|
||||
GIT_DIFFCAPS_TRUST_MODE_BITS = (1 << 2), /* use st_mode? */
|
||||
GIT_DIFFCAPS_TRUST_CTIME = (1 << 3), /* use st_ctime? */
|
||||
GIT_DIFFCAPS_USE_DEV = (1 << 4), /* use st_dev? */
|
||||
GIT_DIFFCAPS_TRUST_NANOSECS = (1 << 5), /* use stat time nanoseconds */
|
||||
};
|
||||
|
||||
#define DIFF_FLAGS_KNOWN_BINARY (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)
|
||||
|
20
src/index.c
20
src/index.c
@ -720,27 +720,13 @@ int git_index__changed_relative_to(
|
||||
return !!git_oid_cmp(&index->checksum, checksum);
|
||||
}
|
||||
|
||||
static bool is_racy_timestamp(const struct timespec *stamp, git_index_entry *entry)
|
||||
static bool is_racy_entry(git_index *index, const 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->tv_sec == 0)
|
||||
return false;
|
||||
|
||||
/* If the timestamp is the same or newer than the index, it's racy */
|
||||
#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
|
||||
return git_index_entry_newer_than_index(entry, index);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -768,7 +754,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 ((entry->flags_extended & GIT_IDXENTRY_UPTODATE) == 0 &&
|
||||
is_racy_timestamp(&index->stamp.mtime, entry))
|
||||
is_racy_entry(index, entry))
|
||||
git_vector_insert(&paths, (char *)entry->path);
|
||||
}
|
||||
|
||||
|
39
src/index.h
39
src/index.h
@ -65,6 +65,45 @@ extern int git_index_entry_icmp(const void *a, const void *b);
|
||||
extern int git_index_entry_srch(const void *a, const void *b);
|
||||
extern int git_index_entry_isrch(const void *a, const void *b);
|
||||
|
||||
/* Index time handling functions */
|
||||
GIT_INLINE(bool) git_index_time_eq(const git_index_time *one, const git_index_time *two)
|
||||
{
|
||||
if (one->seconds != two->seconds)
|
||||
return false;
|
||||
|
||||
#ifdef GIT_USE_NSEC
|
||||
if (one->nanoseconds != two->nanoseconds)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the given index time is newer than the given existing index entry.
|
||||
* If the timestamps are exactly equivalent, then the given index time is
|
||||
* considered "racily newer" than the existing index entry.
|
||||
*/
|
||||
GIT_INLINE(bool) git_index_entry_newer_than_index(
|
||||
const git_index_entry *entry, git_index *index)
|
||||
{
|
||||
/* If we never read the index, we can't have this race either */
|
||||
if (!index || index->stamp.mtime.tv_sec == 0)
|
||||
return false;
|
||||
|
||||
/* If the timestamp is the same or newer than the index, it's racy */
|
||||
#if defined(GIT_USE_NSEC)
|
||||
if ((int32_t)index->stamp.tv_sec < entry->mtime.seconds)
|
||||
return true;
|
||||
else if ((int32_t)index->stamp.mtime.tv_sec > entry->mtime.seconds)
|
||||
return false;
|
||||
else
|
||||
return (uint32_t)index->stamp.mtime.tv_nsec <= entry->mtime.nanoseconds;
|
||||
#else
|
||||
return ((int32_t)index->stamp.mtime.tv_sec) <= entry->mtime.seconds;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Search index for `path`, returning GIT_ENOTFOUND if it does not exist
|
||||
* (but not setting an error message).
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user