From 461b4f75056fc476db6bbdf8bc3ff6e91a8ad08d Mon Sep 17 00:00:00 2001 From: Quentin Casasnovas Date: Sat, 7 Jan 2017 09:26:29 +0100 Subject: [PATCH] git-update-index: add --refresh-stat option. git-update-index --refresh, contrary to what the documentation says, not only will refresh the stat information but will also update the sha1 of the objects in the working tree if the stat information is found to be out-of-date. We add a --refresh-stat option, which like --refresh will update the stat information, but will assume that any file in the working tree that is present in the index matches the index - hence prevents unecessarily reading the files in the working tree. It is different from --assume-unchanged or --skip-worktree in that the new stat information is recorded in the index, hence subsequent git update-index --refresh will not read the files if their mtime hasn't changed. This sounds like a very dangerous option to give to the user, since it could potentially cause changed files to be missed, but can be needed when we are sure the working tree files have not changed and are matching the index. Signed-off-by: Quentin Casasnovas --- builtin/update-index.c | 10 ++++++++++ cache.h | 3 +++ read-cache.c | 7 +++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/builtin/update-index.c b/builtin/update-index.c index f3f07e7f1cb2..1215b6a09687 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -777,6 +777,12 @@ static int really_refresh_callback(const struct option *opt, return refresh(opt->value, REFRESH_REALLY); } +static int refresh_stat_callback(const struct option *opt, + const char *arg, int unset) +{ + return refresh(opt->value, REFRESH_STAT_ONLY); +} + static int chmod_callback(const struct option *opt, const char *arg, int unset) { @@ -934,6 +940,10 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) N_("refresh stat information"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, refresh_callback}, + {OPTION_CALLBACK, 0, "refresh-stat", &refresh_args, NULL, + N_("refresh only stat information (assume content has not changed)"), + PARSE_OPT_NOARG | PARSE_OPT_NONEG, + refresh_stat_callback}, {OPTION_CALLBACK, 0, "really-refresh", &refresh_args, NULL, N_("like --refresh, but ignore assume-unchanged setting"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, diff --git a/cache.h b/cache.h index a50a61a19787..57d0f9fffbe5 100644 --- a/cache.h +++ b/cache.h @@ -611,6 +611,8 @@ extern void *read_blob_data_from_index(struct index_state *, const char *, unsig #define CE_MATCH_IGNORE_MISSING 0x08 /* enable stat refresh */ #define CE_MATCH_REFRESH 0x10 +/* only stat refresh, assume content hasn't changed */ +#define CE_MATCH_REFRESH_STAT_ONLY 0x20 extern int ie_match_stat(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int); extern int ie_modified(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int); @@ -643,6 +645,7 @@ extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); #define REFRESH_IGNORE_MISSING 0x0008 /* ignore non-existent */ #define REFRESH_IGNORE_SUBMODULES 0x0010 /* ignore submodules */ #define REFRESH_IN_PORCELAIN 0x0020 /* user friendly output, not "needs update" */ +#define REFRESH_STAT_ONLY 0x0040 /* do not check content but update stat */ extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg); extern struct cache_entry *refresh_cache_entry(struct cache_entry *, unsigned int); diff --git a/read-cache.c b/read-cache.c index db5d91064266..e9334094c6f0 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1101,6 +1101,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate, int ignore_valid = options & CE_MATCH_IGNORE_VALID; int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE; int ignore_missing = options & CE_MATCH_IGNORE_MISSING; + int assume_content_unchanged = options & CE_MATCH_REFRESH_STAT_ONLY; if (!refresh || ce_uptodate(ce)) return ce; @@ -1161,7 +1162,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate, } } - if (ie_modified(istate, ce, &st, options)) { + if (!assume_content_unchanged && ie_modified(istate, ce, &st, options)) { if (err) *err = EINVAL; return NULL; @@ -1206,11 +1207,13 @@ int refresh_index(struct index_state *istate, unsigned int flags, int quiet = (flags & REFRESH_QUIET) != 0; int not_new = (flags & REFRESH_IGNORE_MISSING) != 0; int ignore_submodules = (flags & REFRESH_IGNORE_SUBMODULES) != 0; + int refresh_stat_only = (flags & REFRESH_STAT_ONLY) != 0; int first = 1; int in_porcelain = (flags & REFRESH_IN_PORCELAIN); unsigned int options = (CE_MATCH_REFRESH | (really ? CE_MATCH_IGNORE_VALID : 0) | - (not_new ? CE_MATCH_IGNORE_MISSING : 0)); + (not_new ? CE_MATCH_IGNORE_MISSING : 0) | + (refresh_stat_only ? CE_MATCH_REFRESH_STAT_ONLY : 0)); const char *modified_fmt; const char *deleted_fmt; const char *typechange_fmt; -- 2.11.0