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).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
diff --git a/src/checkout.c b/src/checkout.c
index d09357f..a92ad08 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -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);
}
diff --git a/src/diff.c b/src/diff.c
index 0ab3b8d..9402b6e 100644
--- a/src/diff.c
+++ b/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;
diff --git a/src/diff.h b/src/diff.h
index 2dfc2c6..47743f8 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -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)
diff --git a/src/index.c b/src/index.c
index bce1634..ca5b2c4 100644
--- a/src/index.c
+++ b/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);
}
diff --git a/src/index.h b/src/index.h
index 546e677..9baf976 100644
--- a/src/index.h
+++ b/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).
*