diff options
-rw-r--r-- | Documentation/config.txt | 9 | ||||
-rw-r--r-- | Documentation/git-update-index.txt | 67 | ||||
-rw-r--r-- | builtin/update-index.c | 35 | ||||
-rw-r--r-- | cache.h | 1 | ||||
-rw-r--r-- | config.c | 20 | ||||
-rw-r--r-- | contrib/completion/git-completion.bash | 1 | ||||
-rw-r--r-- | read-cache.c | 27 | ||||
-rwxr-xr-x | t/t7063-status-untracked-cache.sh | 4 |
8 files changed, 133 insertions, 31 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt index 2d06b11f2..e3c8cfe93 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -308,6 +308,15 @@ core.trustctime:: crawlers and some backup systems). See linkgit:git-update-index[1]. True by default. +core.untrackedCache:: + Determines what to do about the untracked cache feature of the + index. It will be kept, if this variable is unset or set to + `keep`. It will automatically be added if set to `true`. And + it will automatically be removed, if set to `false`. Before + setting it to `true`, you should check that mtime is working + properly on your system. + See linkgit:git-update-index[1]. `keep` by default. + core.checkStat:: Determines which stat fields to match between the index and work tree. The user can set this to 'default' or diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index a0afe1745..c6cbed189 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -174,27 +174,30 @@ may not support it yet. --untracked-cache:: --no-untracked-cache:: - Enable or disable untracked cache extension. This could speed - up for commands that involve determining untracked files such - as `git status`. The underlying operating system and file - system must change `st_mtime` field of a directory if files - are added or deleted in that directory. + Enable or disable untracked cache feature. Please use + `--test-untracked-cache` before enabling it. ++ +These options take effect whatever the value of the `core.untrackedCache` +configuration variable (see linkgit:git-config[1]). But a warning is +emitted when the change goes against the configured value, as the +configured value will take effect next time the index is read and this +will remove the intended effect of the option. --test-untracked-cache:: Only perform tests on the working directory to make sure untracked cache can be used. You have to manually enable - untracked cache using `--force-untracked-cache` (or - `--untracked-cache` but this will run the tests again) - afterwards if you really want to use it. If a test fails - the exit code is 1 and a message explains what is not - working as needed, otherwise the exit code is 0 and OK is - printed. + untracked cache using `--untracked-cache` or + `--force-untracked-cache` or the `core.untrackedCache` + configuration variable afterwards if you really want to use + it. If a test fails the exit code is 1 and a message + explains what is not working as needed, otherwise the exit + code is 0 and OK is printed. --force-untracked-cache:: - For safety, `--untracked-cache` performs tests on the working - directory to make sure untracked cache can be used. These - tests can take a few seconds. `--force-untracked-cache` can be - used to skip the tests. + Same as `--untracked-cache`. Provided for backwards + compatibility with older versions of Git where + `--untracked-cache` used to imply `--test-untracked-cache` but + this option would enable the extension unconditionally. \--:: Do not interpret any more arguments as options. @@ -385,6 +388,37 @@ Although this bit looks similar to assume-unchanged bit, its goal is different from assume-unchanged bit's. Skip-worktree also takes precedence over assume-unchanged bit when both are set. +Untracked cache +--------------- + +This cache is meant to speed up commands that involve determining +untracked files such as `git status`. + +This feature works by recording the mtime of the working tree +directories and then omitting reading directories and stat calls +against files in those directories whose mtime hasn't changed. For +this to work the underlying operating system and file system must +change the `st_mtime` field of directories if files in the directory +are added, modified or deleted. + +You can test whether the filesystem supports that with the +`--test-untracked-cache` option. The `--untracked-cache` option used +to implicitly perform that test in older versions of Git, but that's +no longer the case. + +If you want to enable (or disable) this feature, it is easier to use +the `core.untrackedCache` configuration variable (see +linkgit:git-config[1]) than using the `--untracked-cache` option to +`git update-index` in each repository, especially if you want to do so +across all repositories you use, because you can set the configuration +variable to `true` (or `false`) in your `$HOME/.gitconfig` just once +and have it affect all repositories you touch. + +When the `core.untrackedCache` configuration variable is changed, the +untracked cache is added to or removed from the index the next time a +command reads the index; while when `--[no-|force-]untracked-cache` +are used, the untracked cache is immediately added to or removed from +the index. Configuration ------------- @@ -410,6 +444,9 @@ It can be useful when the inode change time is regularly modified by something outside Git (file system crawlers and backup systems use ctime for marking files processed) (see linkgit:git-config[1]). +The untracked cache extension can be enabled by the +`core.untrackedCache` configuration variable (see +linkgit:git-config[1]). SEE ALSO -------- diff --git a/builtin/update-index.c b/builtin/update-index.c index d90154c59..7a5533491 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -1115,19 +1115,32 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) the_index.split_index = NULL; the_index.cache_changed |= SOMETHING_CHANGED; } - if (untracked_cache > UC_DISABLE) { - if (untracked_cache < UC_FORCE) { - setup_work_tree(); - if (!test_if_untracked_cache_is_supported()) - return 1; - if (untracked_cache == UC_TEST) - return 0; - } - add_untracked_cache(&the_index); - report(_("Untracked cache enabled for '%s'"), get_git_work_tree()); - } else if (untracked_cache == UC_DISABLE) { + + switch (untracked_cache) { + case UC_UNSPECIFIED: + break; + case UC_DISABLE: + if (git_config_get_untracked_cache() == 1) + warning("core.untrackedCache is set to true; " + "remove or change it, if you really want to " + "disable the untracked cache"); remove_untracked_cache(&the_index); report(_("Untracked cache disabled")); + break; + case UC_TEST: + setup_work_tree(); + return !test_if_untracked_cache_is_supported(); + case UC_ENABLE: + case UC_FORCE: + if (git_config_get_untracked_cache() == 0) + warning("core.untrackedCache is set to false; " + "remove or change it, if you really want to " + "enable the untracked cache"); + add_untracked_cache(&the_index); + report(_("Untracked cache enabled for '%s'"), get_git_work_tree()); + break; + default: + die("Bug: bad untracked_cache value: %d", untracked_cache); } if (active_cache_changed) { @@ -1602,6 +1602,7 @@ extern int git_config_get_bool(const char *key, int *dest); extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest); extern int git_config_get_maybe_bool(const char *key, int *dest); extern int git_config_get_pathname(const char *key, const char **dest); +extern int git_config_get_untracked_cache(void); struct key_value_info { const char *filename; @@ -1594,6 +1594,26 @@ int git_config_get_pathname(const char *key, const char **dest) return ret; } +int git_config_get_untracked_cache(void) +{ + int val = -1; + const char *v; + + if (!git_config_get_maybe_bool("core.untrackedcache", &val)) + return val; + + if (!git_config_get_value("core.untrackedcache", &v)) { + if (!strcasecmp(v, "keep")) + return -1; + + error("unknown core.untrackedCache value '%s'; " + "using 'keep' default value", v); + return -1; + } + + return -1; /* default value */ +} + NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr) { diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index d9b995799..a429e6ea2 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -2054,6 +2054,7 @@ _git_config () core.sparseCheckout core.symlinks core.trustctime + core.untrackedCache core.warnAmbiguousRefs core.whitespace core.worktree diff --git a/read-cache.c b/read-cache.c index 84616c8e2..56614d54c 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1519,6 +1519,28 @@ static void check_ce_order(struct index_state *istate) } } +static void tweak_untracked_cache(struct index_state *istate) +{ + switch (git_config_get_untracked_cache()) { + case -1: /* keep: do nothing */ + break; + case 0: /* false */ + remove_untracked_cache(istate); + break; + case 1: /* true */ + add_untracked_cache(istate); + break; + default: /* unknown value: do nothing */ + break; + } +} + +static void post_read_index_from(struct index_state *istate) +{ + check_ce_order(istate); + tweak_untracked_cache(istate); +} + /* remember to discard_cache() before reading a different cache! */ int do_read_index(struct index_state *istate, const char *path, int must_exist) { @@ -1622,9 +1644,10 @@ int read_index_from(struct index_state *istate, const char *path) return istate->cache_nr; ret = do_read_index(istate, path, 0); + split_index = istate->split_index; if (!split_index || is_null_sha1(split_index->base_sha1)) { - check_ce_order(istate); + post_read_index_from(istate); return ret; } @@ -1642,7 +1665,7 @@ int read_index_from(struct index_state *istate, const char *path) sha1_to_hex(split_index->base_sha1)), sha1_to_hex(split_index->base->sha1)); merge_base_index(istate); - check_ce_order(istate); + post_read_index_from(istate); return ret; } diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index 0e8d0d42f..253160a16 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -8,10 +8,8 @@ avoid_racy() { sleep 1 } -# It's fine if git update-index returns an error code other than one, -# it'll be caught in the first test. test_lazy_prereq UNTRACKED_CACHE ' - { git update-index --untracked-cache; ret=$?; } && + { git update-index --test-untracked-cache; ret=$?; } && test $ret -ne 1 ' |