Enable minimal stat checking

Specifically the fields uid, gid, ctime, ino and dev are set to zero by JGit. Other implementations, eg. Git in cygwin are allegedly also somewhat incompatible with Git For Windows and on *nix platforms the resolution of the timestamps may differ. Any stat checking by git will then need to check content, which may be very slow, particularly on Windows. Since mtime and size is typically enough we should allow the user to tell git to avoid checking these fields if they are set to zero in the index. This change introduces a core.checkstat config option where the the user can select to check all fields (default), or just size and the whole second part of mtime (minimal). Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Robin Rosenberg committed Jan 22, 2013 at 08:49 UTC c08e4d5b5cfa9f692cb8c81e5e9615e330f299c2
5 files changed +28 -10
Documentation/config.txt
+6
@@ -235,6 +235,12 @@ core.trustctime::
235 crawlers and some backup systems).
236 See linkgit:git-update-index[1]. True by default.
237
238 +core.checkstat::
239 + Determines which stat fields to match between the index
240 + and work tree. The user can set this to 'default' or
241 + 'minimal'. Default (or explicitly 'default'), is to check
242 + all fields, including the sub-second part of mtime and ctime.
243 +
244 core.quotepath::
245 The commands that output paths (e.g. 'ls-files',
246 'diff'), when not given the `-z` option, will quote
cache.h
+1
@@ -536,6 +536,7 @@ extern int delete_ref(const char *, const unsigned char *sha1, int delopt);
536 /* Environment bits from configuration mechanism */
537 extern int trust_executable_bit;
538 extern int trust_ctime;
539 +extern int check_stat;
540 extern int quote_path_fully;
541 extern int has_symlinks;
542 extern int minimum_abbrev, default_abbrev;
config.c
+6
@@ -566,6 +566,12 @@ static int git_default_core_config(const char *var, const char *value)
566 trust_ctime = git_config_bool(var, value);
567 return 0;
568 }
569 + if (!strcmp(var, "core.statinfo")) {
570 + if (!strcasecmp(value, "default"))
571 + check_stat = 1;
572 + else if (!strcasecmp(value, "minimal"))
573 + check_stat = 0;
574 + }
575
576 if (!strcmp(var, "core.quotepath")) {
577 quote_path_fully = git_config_bool(var, value);
environment.c
+1
@@ -13,6 +13,7 @@
13
14 int trust_executable_bit = 1;
15 int trust_ctime = 1;
16 +int check_stat = 1;
17 int has_symlinks = 1;
18 int minimum_abbrev = 4, default_abbrev = 7;
19 int ignore_case;
read-cache.c
+14 -10
@@ -197,21 +197,25 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
197 }
198 if (ce->ce_mtime.sec != (unsigned int)st->st_mtime)
199 changed |= MTIME_CHANGED;
200 - if (trust_ctime && ce->ce_ctime.sec != (unsigned int)st->st_ctime)
200 + if (trust_ctime && check_stat &&
201 + ce->ce_ctime.sec != (unsigned int)st->st_ctime)
202 changed |= CTIME_CHANGED;
203
204 #ifdef USE_NSEC
204 - if (ce->ce_mtime.nsec != ST_MTIME_NSEC(*st))
205 + if (check_stat && ce->ce_mtime.nsec != ST_MTIME_NSEC(*st))
206 changed |= MTIME_CHANGED;
206 - if (trust_ctime && ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
207 + if (trust_ctime && check_stat &&
208 + ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
209 changed |= CTIME_CHANGED;
210 #endif
211
210 - if (ce->ce_uid != (unsigned int) st->st_uid ||
211 - ce->ce_gid != (unsigned int) st->st_gid)
212 - changed |= OWNER_CHANGED;
213 - if (ce->ce_ino != (unsigned int) st->st_ino)
214 - changed |= INODE_CHANGED;
212 + if (check_stat) {
213 + if (ce->ce_uid != (unsigned int) st->st_uid ||
214 + ce->ce_gid != (unsigned int) st->st_gid)
215 + changed |= OWNER_CHANGED;
216 + if (ce->ce_ino != (unsigned int) st->st_ino)
217 + changed |= INODE_CHANGED;
218 + }
219
220 #ifdef USE_STDEV
221 /*
@@ -219,8 +223,8 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
223 * clients will have different views of what "device"
224 * the filesystem is on
225 */
222 - if (ce->ce_dev != (unsigned int) st->st_dev)
223 - changed |= INODE_CHANGED;
226 + if (check_stat && ce->ce_dev != (unsigned int) st->st_dev)
227 + changed |= INODE_CHANGED;
228 #endif
229
230 if (ce->ce_size != (unsigned int) st->st_size)