When we know that mtime is fully supported by the environment, we
might want the untracked cache to be always used by default without
any mtime test or kernel version check being performed.

Also when we know that mtime is not supported by the environment,
for example because the repo is shared over a network file system,
then we might want 'git update-index --untracked-cache' to fail
immediately instead of performing tests (because it might work on
some systems using the repo over the network file system but not
others).

The normal way to achieve the above in Git is to use a config
variable. That's why this patch introduces "core.untrackedCache".

To keep things simple, this variable is a bool which default to
false.

When "git status" is run, it now adds or removes the untracked
cache in the index to respect the value of this variable.

The job of `git update-index --[no-|force-]untracked-cache` was
to add or remove the untracked cache from the index. This was a
kind of configuration because this was persistant across git
commands. To make this kind of configuration compatible with the
new config variable, the simple thing to do, and what this patch
does, is to make `git update-index --[no-|force-]untracked-cache`
set or unset this config option.

This new behavior is a backward incompatible change, but that is
deliberate. The untracked cache feature has been experimental
and is very unlikely used by beginners.

When people will upgrade, this will remove any untracked cache
they used unless they set "core.untrackedCache" before upgrading.
This should be stated in the release notes.

Also `--untracked-cache` used to check that the underlying
operating system and file system change `st_mtime` field of a
directory if files are added or deleted in that directory. But
those tests take a long time and there is now
`--test-untracked-cache` to perform them.

That's why, to be more consistent with other git commands, this
patch prevents `--untracked-cache` to perform tests, so that
after this patch there is no difference any more between
`--untracked-cache` and `--force-untracked-cache`.

All the changes to `--[no-|force-]untracked-cache` make it
possible to deprecate those options in the future.

Signed-off-by: Christian Couder <chrisc...@tuxfamily.org>
Signed-off-by: Ævar Arnfjörð Bjarmason <ava...@gmail.com>
---
 Documentation/config.txt               |  7 ++++
 Documentation/git-update-index.txt     | 58 +++++++++++++++++++++++++++-------
 builtin/update-index.c                 | 25 ++++++++-------
 cache.h                                |  1 +
 config.c                               |  4 +++
 contrib/completion/git-completion.bash |  1 +
 dir.c                                  |  2 +-
 environment.c                          |  1 +
 t/t7063-status-untracked-cache.sh      |  4 +--
 wt-status.c                            |  9 ++++++
 10 files changed, 85 insertions(+), 27 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 2d06b11..94820eb 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -308,6 +308,13 @@ core.trustctime::
        crawlers and some backup systems).
        See linkgit:git-update-index[1]. True by default.
 
+core.untrackedCache::
+       Determines if untracked cache will be enabled. Using
+       'git update-index --[no-|force-]untracked-cache' will set
+       this variable. Before setting it to true, you should check
+       that mtime is working properly on your system.
+       See linkgit:git-update-index[1]. False 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 0ff7396..cd02de4 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -173,24 +173,29 @@ 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 extension. Please use
+       `--test-untracked-cache` before enabling it.
++
+These options are mostly aliases for setting the `core.untrackedCache`
+configuration variable to 'true' or 'false' in the local config file
+(see linkgit:git-config[1]). You can equivalently just set those
+configuration values directly. These options are just provided for
+backwards compatibility with the older versions of Git where this was
+the only way to enable or disable the untracked cache extension.
 
 --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.
+       untracked cache using `--untracked-cache` or
+       `--force-untracked-cache` or the `core.untrackedCache`
+       configuration variable afterwards if you really want to use
+       it.
 
 --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.
@@ -381,6 +386,33 @@ 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 could 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.
+
+It is recommended to use the `core.untrackedCache` configuration
+variable (see linkgit:git-config[1]) to enable or disable this feature
+instead of using the `--[no-|force-]untracked-cache` which are going
+to set or unset this configuration variable anyway.
+
+When the `core.untrackedCache` configuration variable is changed, the
+untracked cache is added or removed from the index the next time "git
+status" is run, while when `--[no-|force-]untracked-cache` are used,
+the untracked cache is immediately added to the index.
 
 Configuration
 -------------
@@ -406,6 +438,8 @@ 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 is 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 4ca6d94..98e3bac 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -1115,21 +1115,24 @@ 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_TEST) {
+               setup_work_tree();
+               return !test_if_untracked_cache_is_supported();
+       }
        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;
-               }
+               if (!use_untracked_cache && 
git_config_set("core.untrackedCache", "true"))
+                       die("could not set core.untrackedCache to true");
                add_untracked_cache();
                if (verbose)
                        printf(_("Untracked cache enabled\n"));
-       } else if (untracked_cache == UC_DISABLE && the_index.untracked) {
-               remove_untracked_cache();
-               if (verbose)
-                       printf(_("Untracked cache disabled\n"));
+       } else if (untracked_cache == UC_DISABLE) {
+               if (use_untracked_cache > 0 && 
git_config_set("core.untrackedCache", "false"))
+                       die("could not set core.untrackedCache to false");
+               if (the_index.untracked) {
+                       remove_untracked_cache();
+                       if (verbose)
+                               printf(_("Untracked cache disabled\n"));
+               }
        }
 
        if (active_cache_changed) {
diff --git a/cache.h b/cache.h
index 2a9e902..0cc2c2f 100644
--- a/cache.h
+++ b/cache.h
@@ -619,6 +619,7 @@ extern void set_alternate_index_output(const char *);
 /* Environment bits from configuration mechanism */
 extern int trust_executable_bit;
 extern int trust_ctime;
+extern int use_untracked_cache;
 extern int check_stat;
 extern int quote_path_fully;
 extern int has_symlinks;
diff --git a/config.c b/config.c
index 248a21a..f023ee7 100644
--- a/config.c
+++ b/config.c
@@ -691,6 +691,10 @@ static int git_default_core_config(const char *var, const 
char *value)
                trust_ctime = git_config_bool(var, value);
                return 0;
        }
+       if (!strcmp(var, "core.untrackedcache")) {
+               use_untracked_cache = git_config_bool(var, value);
+               return 0;
+       }
        if (!strcmp(var, "core.checkstat")) {
                if (!strcasecmp(value, "default"))
                        check_stat = 1;
diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index 111b053..b7e5736 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/dir.c b/dir.c
index 3b83cc0..0b07ba7 100644
--- a/dir.c
+++ b/dir.c
@@ -2015,7 +2015,7 @@ static struct untracked_cache_dir 
*validate_untracked_cache(struct dir_struct *d
        if (dir->exclude_list_group[EXC_CMDL].nr)
                return NULL;
 
-       if (!ident_in_untracked(dir->untracked)) {
+       if (use_untracked_cache != 1 && !ident_in_untracked(dir->untracked)) {
                warning(_("Untracked cache is disabled on this system."));
                return NULL;
        }
diff --git a/environment.c b/environment.c
index 2da7fe2..9ca71b1 100644
--- a/environment.c
+++ b/environment.c
@@ -14,6 +14,7 @@
 
 int trust_executable_bit = 1;
 int trust_ctime = 1;
+int use_untracked_cache;
 int check_stat = 1;
 int has_symlinks = 1;
 int minimum_abbrev = 4, default_abbrev = 7;
diff --git a/t/t7063-status-untracked-cache.sh 
b/t/t7063-status-untracked-cache.sh
index 0e8d0d4..253160a 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
 '
 
diff --git a/wt-status.c b/wt-status.c
index 435fc28..3e0fe02 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -586,6 +586,15 @@ static void wt_status_collect_untracked(struct wt_status 
*s)
                dir.flags |= DIR_SHOW_IGNORED_TOO;
        else
                dir.untracked = the_index.untracked;
+
+       if (!dir.untracked && use_untracked_cache == 1) {
+               add_untracked_cache();
+               dir.untracked = the_index.untracked;
+       } else if (dir.untracked && use_untracked_cache == 0) {
+               remove_untracked_cache();
+               dir.untracked = NULL;
+       }
+
        setup_standard_excludes(&dir);
 
        fill_directory(&dir, &s->pathspec);
-- 
2.6.3.479.g8eb29d4

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to