Skip to content

Commit 435ec09

Browse files
chriscoolgitster
authored andcommitted
config: add core.untrackedCache
When we know that mtime on directory as given by the environment is usable for the purpose of untracked cache, we may want the untracked cache to be always used without any mtime test or kernel name check being performed. Also when we know that mtime is not usable for the purpose of untracked cache, for example because the repo is shared over a network file system, we may want the untracked-cache to be automatically removed from the index. Allow the user to express such preference by setting the 'core.untrackedCache' configuration variable, which can take 'keep', 'false', or 'true' and default to 'keep'. When read_index_from() is called, it now adds or removes the untracked cache in the index to respect the value of this variable. So it does nothing if the value is `keep` or if the variable is unset; it adds the untracked cache if the value is `true`; and it removes the cache if the value is `false`. `git update-index --[no-|force-]untracked-cache` still adds the untracked cache to, or removes it, from the index, but this shows a warning if it goes against the value of core.untrackedCache, because the next time the index is read the untracked cache will be added or removed if the configuration is set to do so. 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 because those tests take a long time, `--untracked-cache` no longer performs them. Instead, there is now `--test-untracked-cache` to perform the tests. This change makes `--untracked-cache` the same as `--force-untracked-cache`. This last change is backward incompatible and should be mentioned in the release notes. Helped-by: Duy Nguyen <[email protected]> Helped-by: Torsten Bögershausen <[email protected]> Helped-by: Stefan Beller <[email protected]> Signed-off-by: Christian Couder <[email protected]> Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> read-cache: Duy'sfixup Signed-off-by: Christian Couder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0e0f761 commit 435ec09

File tree

8 files changed

+133
-31
lines changed

8 files changed

+133
-31
lines changed

Documentation/config.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,15 @@ core.trustctime::
308308
crawlers and some backup systems).
309309
See linkgit:git-update-index[1]. True by default.
310310

311+
core.untrackedCache::
312+
Determines what to do about the untracked cache feature of the
313+
index. It will be kept, if this variable is unset or set to
314+
`keep`. It will automatically be added if set to `true`. And
315+
it will automatically be removed, if set to `false`. Before
316+
setting it to `true`, you should check that mtime is working
317+
properly on your system.
318+
See linkgit:git-update-index[1]. `keep` by default.
319+
311320
core.checkStat::
312321
Determines which stat fields to match between the index
313322
and work tree. The user can set this to 'default' or

Documentation/git-update-index.txt

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -174,27 +174,30 @@ may not support it yet.
174174

175175
--untracked-cache::
176176
--no-untracked-cache::
177-
Enable or disable untracked cache extension. This could speed
178-
up for commands that involve determining untracked files such
179-
as `git status`. The underlying operating system and file
180-
system must change `st_mtime` field of a directory if files
181-
are added or deleted in that directory.
177+
Enable or disable untracked cache feature. Please use
178+
`--test-untracked-cache` before enabling it.
179+
+
180+
These options take effect whatever the value of the `core.untrackedCache`
181+
configuration variable (see linkgit:git-config[1]). But a warning is
182+
emitted when the change goes against the configured value, as the
183+
configured value will take effect next time the index is read and this
184+
will remove the intended effect of the option.
182185

183186
--test-untracked-cache::
184187
Only perform tests on the working directory to make sure
185188
untracked cache can be used. You have to manually enable
186-
untracked cache using `--force-untracked-cache` (or
187-
`--untracked-cache` but this will run the tests again)
188-
afterwards if you really want to use it. If a test fails
189-
the exit code is 1 and a message explains what is not
190-
working as needed, otherwise the exit code is 0 and OK is
191-
printed.
189+
untracked cache using `--untracked-cache` or
190+
`--force-untracked-cache` or the `core.untrackedCache`
191+
configuration variable afterwards if you really want to use
192+
it. If a test fails the exit code is 1 and a message
193+
explains what is not working as needed, otherwise the exit
194+
code is 0 and OK is printed.
192195

193196
--force-untracked-cache::
194-
For safety, `--untracked-cache` performs tests on the working
195-
directory to make sure untracked cache can be used. These
196-
tests can take a few seconds. `--force-untracked-cache` can be
197-
used to skip the tests.
197+
Same as `--untracked-cache`. Provided for backwards
198+
compatibility with older versions of Git where
199+
`--untracked-cache` used to imply `--test-untracked-cache` but
200+
this option would enable the extension unconditionally.
198201

199202
\--::
200203
Do not interpret any more arguments as options.
@@ -385,6 +388,37 @@ Although this bit looks similar to assume-unchanged bit, its goal is
385388
different from assume-unchanged bit's. Skip-worktree also takes
386389
precedence over assume-unchanged bit when both are set.
387390

391+
Untracked cache
392+
---------------
393+
394+
This cache is meant to speed up commands that involve determining
395+
untracked files such as `git status`.
396+
397+
This feature works by recording the mtime of the working tree
398+
directories and then omitting reading directories and stat calls
399+
against files in those directories whose mtime hasn't changed. For
400+
this to work the underlying operating system and file system must
401+
change the `st_mtime` field of directories if files in the directory
402+
are added, modified or deleted.
403+
404+
You can test whether the filesystem supports that with the
405+
`--test-untracked-cache` option. The `--untracked-cache` option used
406+
to implicitly perform that test in older versions of Git, but that's
407+
no longer the case.
408+
409+
If you want to enable (or disable) this feature, it is easier to use
410+
the `core.untrackedCache` configuration variable (see
411+
linkgit:git-config[1]) than using the `--untracked-cache` option to
412+
`git update-index` in each repository, especially if you want to do so
413+
across all repositories you use, because you can set the configuration
414+
variable to `true` (or `false`) in your `$HOME/.gitconfig` just once
415+
and have it affect all repositories you touch.
416+
417+
When the `core.untrackedCache` configuration variable is changed, the
418+
untracked cache is added to or removed from the index the next time a
419+
command reads the index; while when `--[no-|force-]untracked-cache`
420+
are used, the untracked cache is immediately added to or removed from
421+
the index.
388422

389423
Configuration
390424
-------------
@@ -410,6 +444,9 @@ It can be useful when the inode change time is regularly modified by
410444
something outside Git (file system crawlers and backup systems use
411445
ctime for marking files processed) (see linkgit:git-config[1]).
412446

447+
The untracked cache extension can be enabled by the
448+
`core.untrackedCache` configuration variable (see
449+
linkgit:git-config[1]).
413450

414451
SEE ALSO
415452
--------

builtin/update-index.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,19 +1115,32 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
11151115
the_index.split_index = NULL;
11161116
the_index.cache_changed |= SOMETHING_CHANGED;
11171117
}
1118-
if (untracked_cache > UC_DISABLE) {
1119-
if (untracked_cache < UC_FORCE) {
1120-
setup_work_tree();
1121-
if (!test_if_untracked_cache_is_supported())
1122-
return 1;
1123-
if (untracked_cache == UC_TEST)
1124-
return 0;
1125-
}
1126-
add_untracked_cache(&the_index);
1127-
report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
1128-
} else if (untracked_cache == UC_DISABLE) {
1118+
1119+
switch (untracked_cache) {
1120+
case UC_UNSPECIFIED:
1121+
break;
1122+
case UC_DISABLE:
1123+
if (git_config_get_untracked_cache() == 1)
1124+
warning("core.untrackedCache is set to true; "
1125+
"remove or change it, if you really want to "
1126+
"disable the untracked cache");
11291127
remove_untracked_cache(&the_index);
11301128
report(_("Untracked cache disabled"));
1129+
break;
1130+
case UC_TEST:
1131+
setup_work_tree();
1132+
return !test_if_untracked_cache_is_supported();
1133+
case UC_ENABLE:
1134+
case UC_FORCE:
1135+
if (git_config_get_untracked_cache() == 0)
1136+
warning("core.untrackedCache is set to false; "
1137+
"remove or change it, if you really want to "
1138+
"enable the untracked cache");
1139+
add_untracked_cache(&the_index);
1140+
report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
1141+
break;
1142+
default:
1143+
die("Bug: bad untracked_cache value: %d", untracked_cache);
11311144
}
11321145

11331146
if (active_cache_changed) {

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,7 @@ extern int git_config_get_bool(const char *key, int *dest);
16021602
extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
16031603
extern int git_config_get_maybe_bool(const char *key, int *dest);
16041604
extern int git_config_get_pathname(const char *key, const char **dest);
1605+
extern int git_config_get_untracked_cache(void);
16051606

16061607
struct key_value_info {
16071608
const char *filename;

config.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,26 @@ int git_config_get_pathname(const char *key, const char **dest)
15941594
return ret;
15951595
}
15961596

1597+
int git_config_get_untracked_cache(void)
1598+
{
1599+
int val = -1;
1600+
const char *v;
1601+
1602+
if (!git_config_get_maybe_bool("core.untrackedcache", &val))
1603+
return val;
1604+
1605+
if (!git_config_get_value("core.untrackedcache", &v)) {
1606+
if (!strcasecmp(v, "keep"))
1607+
return -1;
1608+
1609+
error("unknown core.untrackedCache value '%s'; "
1610+
"using 'keep' default value", v);
1611+
return -1;
1612+
}
1613+
1614+
return -1; /* default value */
1615+
}
1616+
15971617
NORETURN
15981618
void git_die_config_linenr(const char *key, const char *filename, int linenr)
15991619
{

contrib/completion/git-completion.bash

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,6 +2054,7 @@ _git_config ()
20542054
core.sparseCheckout
20552055
core.symlinks
20562056
core.trustctime
2057+
core.untrackedCache
20572058
core.warnAmbiguousRefs
20582059
core.whitespace
20592060
core.worktree

read-cache.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,28 @@ static void check_ce_order(struct index_state *istate)
15191519
}
15201520
}
15211521

1522+
static void tweak_untracked_cache(struct index_state *istate)
1523+
{
1524+
switch (git_config_get_untracked_cache()) {
1525+
case -1: /* keep: do nothing */
1526+
break;
1527+
case 0: /* false */
1528+
remove_untracked_cache(istate);
1529+
break;
1530+
case 1: /* true */
1531+
add_untracked_cache(istate);
1532+
break;
1533+
default: /* unknown value: do nothing */
1534+
break;
1535+
}
1536+
}
1537+
1538+
static void post_read_index_from(struct index_state *istate)
1539+
{
1540+
check_ce_order(istate);
1541+
tweak_untracked_cache(istate);
1542+
}
1543+
15221544
/* remember to discard_cache() before reading a different cache! */
15231545
int do_read_index(struct index_state *istate, const char *path, int must_exist)
15241546
{
@@ -1622,9 +1644,10 @@ int read_index_from(struct index_state *istate, const char *path)
16221644
return istate->cache_nr;
16231645

16241646
ret = do_read_index(istate, path, 0);
1647+
16251648
split_index = istate->split_index;
16261649
if (!split_index || is_null_sha1(split_index->base_sha1)) {
1627-
check_ce_order(istate);
1650+
post_read_index_from(istate);
16281651
return ret;
16291652
}
16301653

@@ -1642,7 +1665,7 @@ int read_index_from(struct index_state *istate, const char *path)
16421665
sha1_to_hex(split_index->base_sha1)),
16431666
sha1_to_hex(split_index->base->sha1));
16441667
merge_base_index(istate);
1645-
check_ce_order(istate);
1668+
post_read_index_from(istate);
16461669
return ret;
16471670
}
16481671

t/t7063-status-untracked-cache.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ avoid_racy() {
88
sleep 1
99
}
1010

11-
# It's fine if git update-index returns an error code other than one,
12-
# it'll be caught in the first test.
1311
test_lazy_prereq UNTRACKED_CACHE '
14-
{ git update-index --untracked-cache; ret=$?; } &&
12+
{ git update-index --test-untracked-cache; ret=$?; } &&
1513
test $ret -ne 1
1614
'
1715

0 commit comments

Comments
 (0)