2015-03-08 11:12:44 +01:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='test untracked cache'
|
|
|
|
|
2020-11-19 00:44:39 +01:00
|
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
tests: mark tests relying on the current default for `init.defaultBranch`
In addition to the manual adjustment to let the `linux-gcc` CI job run
the test suite with `master` and then with `main`, this patch makes sure
that GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME is set in all test scripts
that currently rely on the initial branch name being `master by default.
To determine which test scripts to mark up, the first step was to
force-set the default branch name to `master` in
- all test scripts that contain the keyword `master`,
- t4211, which expects `t/t4211/history.export` with a hard-coded ref to
initialize the default branch,
- t5560 because it sources `t/t556x_common` which uses `master`,
- t8002 and t8012 because both source `t/annotate-tests.sh` which also
uses `master`)
This trick was performed by this command:
$ sed -i '/^ *\. \.\/\(test-lib\|lib-\(bash\|cvs\|git-svn\)\|gitweb-lib\)\.sh$/i\
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\
' $(git grep -l master t/t[0-9]*.sh) \
t/t4211*.sh t/t5560*.sh t/t8002*.sh t/t8012*.sh
After that, careful, manual inspection revealed that some of the test
scripts containing the needle `master` do not actually rely on a
specific default branch name: either they mention `master` only in a
comment, or they initialize that branch specificially, or they do not
actually refer to the current default branch. Therefore, the
aforementioned modification was undone in those test scripts thusly:
$ git checkout HEAD -- \
t/t0027-auto-crlf.sh t/t0060-path-utils.sh \
t/t1011-read-tree-sparse-checkout.sh \
t/t1305-config-include.sh t/t1309-early-config.sh \
t/t1402-check-ref-format.sh t/t1450-fsck.sh \
t/t2024-checkout-dwim.sh \
t/t2106-update-index-assume-unchanged.sh \
t/t3040-subprojects-basic.sh t/t3301-notes.sh \
t/t3308-notes-merge.sh t/t3423-rebase-reword.sh \
t/t3436-rebase-more-options.sh \
t/t4015-diff-whitespace.sh t/t4257-am-interactive.sh \
t/t5323-pack-redundant.sh t/t5401-update-hooks.sh \
t/t5511-refspec.sh t/t5526-fetch-submodules.sh \
t/t5529-push-errors.sh t/t5530-upload-pack-error.sh \
t/t5548-push-porcelain.sh \
t/t5552-skipping-fetch-negotiator.sh \
t/t5572-pull-submodule.sh t/t5608-clone-2gb.sh \
t/t5614-clone-submodules-shallow.sh \
t/t7508-status.sh t/t7606-merge-custom.sh \
t/t9302-fast-import-unpack-limit.sh
We excluded one set of test scripts in these commands, though: the range
of `git p4` tests. The reason? `git p4` stores the (foreign) remote
branch in the branch called `p4/master`, which is obviously not the
default branch. Manual analysis revealed that only five of these tests
actually require a specific default branch name to pass; They were
modified thusly:
$ sed -i '/^ *\. \.\/lib-git-p4\.sh$/i\
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\
' t/t980[0167]*.sh t/t9811*.sh
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-19 00:44:19 +01:00
|
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
|
2015-03-08 11:12:44 +01:00
|
|
|
. ./test-lib.sh
|
|
|
|
|
t7063: work around FreeBSD's lazy mtime update feature
Let's start with the commit message of [1] from freebsd.git [2]
Sync timestamp changes for inodes of special files to disk as late
as possible (when the inode is reclaimed). Temporarily only do
this if option UFS_LAZYMOD configured and softupdates aren't
enabled. UFS_LAZYMOD is intentionally left out of
/sys/conf/options.
This is mainly to avoid almost useless disk i/o on battery powered
machines. It's silly to write to disk (on the next sync or when
the inode becomes inactive) just because someone hit a key or
something wrote to the screen or /dev/null.
PR: 5577 [3]
The short version of that, in the context of t7063, is that when a
directory is updated, its mtime may be updated later, not
immediately. This can be shown with a simple command sequence
date; sleep 1; touch abc; rm abc; sleep 10; ls -lTd .
One would expect that the date shown in `ls` would be one second from
`date`, but it's 10 seconds later. If we put another `ls -lTd .` in
front of `sleep 10`, then the date of the last `ls` comes as
expected. The first `ls` somehow forces mtime to be updated.
t7063 is really sensitive to directory mtime. When mtime is too "new",
git code suspects racy timestamps and will not trigger the shortcut in
untracked cache, in t7063.24 and eventually be detected in t7063.27
We have two options thanks to this special FreeBSD feature:
1) Stop supporting untracked cache on FreeBSD. Skip t7063 entirely
when running on FreeBSD
2) Work around this problem (using the same 'ls' trick) and continue
to support untracked cache on FreeBSD
I initially wanted to go with 1) because I didn't know the exact
nature of this feature and feared that it would make untracked cache
work unreliably, using the cached version when it should not.
Since the behavior of this thing is clearer now. The picture is not
that bad. If this indeed happens often, untracked cache would assume
racy condition more often and _fall back_ to non-untracked cache code
paths. Which means it may be less effective, but it will not show
wrong things.
This patch goes with option 2.
PS. For those who want to look further in FreeBSD source code, this
flag is now called IN_LAZYMOD. I can see it's effective in ext2 and
ufs. zfs is not affected.
[1] 660e6408e6df99a20dacb070c5e7f9739efdf96d
[2] git://github.com/freebsd/freebsd.git
[3] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=5577
Reported-by: Eric Wong <e@80x24.org>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-08-03 19:45:22 +02:00
|
|
|
# On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime
|
|
|
|
# is updated lazily after contents in the directory changes, which
|
|
|
|
# forces the untracked cache code to take the slow path. A test
|
|
|
|
# that wants to make sure that the fast path works correctly should
|
|
|
|
# call this helper to make mtime of the containing directory in sync
|
|
|
|
# with the reality before checking the fast path behaviour.
|
|
|
|
#
|
|
|
|
# See <20160803174522.5571-1-pclouds@gmail.com> if you want to know
|
|
|
|
# more.
|
|
|
|
|
2018-02-28 22:21:09 +01:00
|
|
|
GIT_FORCE_UNTRACKED_CACHE=true
|
|
|
|
export GIT_FORCE_UNTRACKED_CACHE
|
2018-02-05 20:56:19 +01:00
|
|
|
|
t7063: work around FreeBSD's lazy mtime update feature
Let's start with the commit message of [1] from freebsd.git [2]
Sync timestamp changes for inodes of special files to disk as late
as possible (when the inode is reclaimed). Temporarily only do
this if option UFS_LAZYMOD configured and softupdates aren't
enabled. UFS_LAZYMOD is intentionally left out of
/sys/conf/options.
This is mainly to avoid almost useless disk i/o on battery powered
machines. It's silly to write to disk (on the next sync or when
the inode becomes inactive) just because someone hit a key or
something wrote to the screen or /dev/null.
PR: 5577 [3]
The short version of that, in the context of t7063, is that when a
directory is updated, its mtime may be updated later, not
immediately. This can be shown with a simple command sequence
date; sleep 1; touch abc; rm abc; sleep 10; ls -lTd .
One would expect that the date shown in `ls` would be one second from
`date`, but it's 10 seconds later. If we put another `ls -lTd .` in
front of `sleep 10`, then the date of the last `ls` comes as
expected. The first `ls` somehow forces mtime to be updated.
t7063 is really sensitive to directory mtime. When mtime is too "new",
git code suspects racy timestamps and will not trigger the shortcut in
untracked cache, in t7063.24 and eventually be detected in t7063.27
We have two options thanks to this special FreeBSD feature:
1) Stop supporting untracked cache on FreeBSD. Skip t7063 entirely
when running on FreeBSD
2) Work around this problem (using the same 'ls' trick) and continue
to support untracked cache on FreeBSD
I initially wanted to go with 1) because I didn't know the exact
nature of this feature and feared that it would make untracked cache
work unreliably, using the cached version when it should not.
Since the behavior of this thing is clearer now. The picture is not
that bad. If this indeed happens often, untracked cache would assume
racy condition more often and _fall back_ to non-untracked cache code
paths. Which means it may be less effective, but it will not show
wrong things.
This patch goes with option 2.
PS. For those who want to look further in FreeBSD source code, this
flag is now called IN_LAZYMOD. I can see it's effective in ext2 and
ufs. zfs is not affected.
[1] 660e6408e6df99a20dacb070c5e7f9739efdf96d
[2] git://github.com/freebsd/freebsd.git
[3] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=5577
Reported-by: Eric Wong <e@80x24.org>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-08-03 19:45:22 +02:00
|
|
|
sync_mtime () {
|
2020-03-25 16:06:19 +01:00
|
|
|
find . -type d -exec ls -ld {} + >/dev/null
|
t7063: work around FreeBSD's lazy mtime update feature
Let's start with the commit message of [1] from freebsd.git [2]
Sync timestamp changes for inodes of special files to disk as late
as possible (when the inode is reclaimed). Temporarily only do
this if option UFS_LAZYMOD configured and softupdates aren't
enabled. UFS_LAZYMOD is intentionally left out of
/sys/conf/options.
This is mainly to avoid almost useless disk i/o on battery powered
machines. It's silly to write to disk (on the next sync or when
the inode becomes inactive) just because someone hit a key or
something wrote to the screen or /dev/null.
PR: 5577 [3]
The short version of that, in the context of t7063, is that when a
directory is updated, its mtime may be updated later, not
immediately. This can be shown with a simple command sequence
date; sleep 1; touch abc; rm abc; sleep 10; ls -lTd .
One would expect that the date shown in `ls` would be one second from
`date`, but it's 10 seconds later. If we put another `ls -lTd .` in
front of `sleep 10`, then the date of the last `ls` comes as
expected. The first `ls` somehow forces mtime to be updated.
t7063 is really sensitive to directory mtime. When mtime is too "new",
git code suspects racy timestamps and will not trigger the shortcut in
untracked cache, in t7063.24 and eventually be detected in t7063.27
We have two options thanks to this special FreeBSD feature:
1) Stop supporting untracked cache on FreeBSD. Skip t7063 entirely
when running on FreeBSD
2) Work around this problem (using the same 'ls' trick) and continue
to support untracked cache on FreeBSD
I initially wanted to go with 1) because I didn't know the exact
nature of this feature and feared that it would make untracked cache
work unreliably, using the cached version when it should not.
Since the behavior of this thing is clearer now. The picture is not
that bad. If this indeed happens often, untracked cache would assume
racy condition more often and _fall back_ to non-untracked cache code
paths. Which means it may be less effective, but it will not show
wrong things.
This patch goes with option 2.
PS. For those who want to look further in FreeBSD source code, this
flag is now called IN_LAZYMOD. I can see it's effective in ext2 and
ufs. zfs is not affected.
[1] 660e6408e6df99a20dacb070c5e7f9739efdf96d
[2] git://github.com/freebsd/freebsd.git
[3] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=5577
Reported-by: Eric Wong <e@80x24.org>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-08-03 19:45:22 +02:00
|
|
|
}
|
|
|
|
|
2015-03-08 11:12:44 +01:00
|
|
|
avoid_racy() {
|
|
|
|
sleep 1
|
|
|
|
}
|
|
|
|
|
2018-01-24 10:30:19 +01:00
|
|
|
status_is_clean() {
|
|
|
|
git status --porcelain >../status.actual &&
|
2018-07-27 19:48:11 +02:00
|
|
|
test_must_be_empty ../status.actual
|
2018-01-24 10:30:19 +01:00
|
|
|
}
|
|
|
|
|
2020-04-01 06:17:35 +02:00
|
|
|
# Ignore_Untracked_Cache, abbreviated to 3 letters because then people can
|
|
|
|
# compare commands side-by-side, e.g.
|
|
|
|
# iuc status --porcelain >expect &&
|
|
|
|
# git status --porcelain >actual &&
|
|
|
|
# test_cmp expect actual
|
|
|
|
iuc () {
|
|
|
|
git ls-files -s >../current-index-entries
|
|
|
|
git ls-files -t | sed -ne s/^S.//p >../current-sparse-entries
|
|
|
|
|
|
|
|
GIT_INDEX_FILE=.git/tmp_index
|
|
|
|
export GIT_INDEX_FILE
|
|
|
|
git update-index --index-info <../current-index-entries
|
|
|
|
git update-index --skip-worktree $(cat ../current-sparse-entries)
|
|
|
|
|
|
|
|
git -c core.untrackedCache=false "$@"
|
|
|
|
ret=$?
|
|
|
|
|
|
|
|
rm ../current-index-entries
|
|
|
|
rm $GIT_INDEX_FILE
|
|
|
|
unset GIT_INDEX_FILE
|
|
|
|
|
|
|
|
return $ret
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces () {
|
|
|
|
# From the GIT_TRACE2_PERF data of the form
|
|
|
|
# $TIME $FILE:$LINE | d0 | main | data | r1 | ? | ? | read_directo | $RELEVANT_STAT
|
|
|
|
# extract the $RELEVANT_STAT fields. We don't care about region_enter
|
|
|
|
# or region_leave, or stats for things outside read_directory.
|
|
|
|
INPUT_FILE=$1
|
|
|
|
OUTPUT_FILE=$2
|
|
|
|
grep data.*read_directo $INPUT_FILE |
|
2021-05-12 19:28:15 +02:00
|
|
|
cut -d "|" -f 9 |
|
|
|
|
grep -v visited \
|
2021-05-12 19:28:14 +02:00
|
|
|
>"$OUTPUT_FILE"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-27 11:34:58 +02:00
|
|
|
test_lazy_prereq UNTRACKED_CACHE '
|
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 <pclouds@gmail.com>
Helped-by: Torsten Bögershausen <tboegi@web.de>
Helped-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
read-cache: Duy'sfixup
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-27 07:58:05 +01:00
|
|
|
{ git update-index --test-untracked-cache; ret=$?; } &&
|
2015-05-27 11:34:58 +02:00
|
|
|
test $ret -ne 1
|
|
|
|
'
|
|
|
|
|
|
|
|
if ! test_have_prereq UNTRACKED_CACHE; then
|
2015-03-08 11:12:44 +01:00
|
|
|
skip_all='This system does not support untracked cache'
|
|
|
|
test_done
|
|
|
|
fi
|
|
|
|
|
2016-01-27 07:58:07 +01:00
|
|
|
test_expect_success 'core.untrackedCache is unset' '
|
|
|
|
test_must_fail git config --get core.untrackedCache
|
|
|
|
'
|
|
|
|
|
2015-03-08 11:12:44 +01:00
|
|
|
test_expect_success 'setup' '
|
|
|
|
git init worktree &&
|
|
|
|
cd worktree &&
|
|
|
|
mkdir done dtwo dthree &&
|
|
|
|
touch one two three done/one dtwo/two dthree/three &&
|
|
|
|
git add one two done/one &&
|
|
|
|
: >.git/info/exclude &&
|
2020-07-30 01:14:00 +02:00
|
|
|
git update-index --untracked-cache &&
|
|
|
|
test_oid_cache <<-EOF
|
|
|
|
root sha1:e6fcc8f2ee31bae321d66afd183fcb7237afae6e
|
|
|
|
root sha256:b90c672088c015b9c83876e919da311bad4cd39639fb139f988af6a11493b974
|
|
|
|
|
|
|
|
exclude sha1:13263c0978fb9fad16b2d580fb800b6d811c3ff0
|
|
|
|
exclude sha256:fe4aaa1bbbbce4cb8f73426748a14c5ad6026b26f90505a0bf2494b165a5b76c
|
|
|
|
|
|
|
|
done sha1:1946f0437f90c5005533cbe1736a6451ca301714
|
|
|
|
done sha256:7f079501d79f665b3acc50f5e0e9e94509084d5032ac20113a37dd5029b757cc
|
|
|
|
EOF
|
2015-03-08 11:12:44 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'untracked cache is empty' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
cat >../expect-empty <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $ZERO_OID
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
|
|
|
EOF
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-empty ../actual
|
2015-03-08 11:12:44 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
A done/one
|
|
|
|
A one
|
|
|
|
A two
|
|
|
|
?? dthree/
|
|
|
|
?? dtwo/
|
|
|
|
?? three
|
|
|
|
EOF
|
|
|
|
|
|
|
|
cat >../dump.expect <<EOF &&
|
2016-07-16 07:06:25 +02:00
|
|
|
info/exclude $EMPTY_BLOB
|
2020-07-30 01:14:00 +02:00
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $ZERO_OID recurse valid
|
2015-03-08 11:12:44 +01:00
|
|
|
dthree/
|
|
|
|
dtwo/
|
|
|
|
three
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
three
|
2020-07-30 01:14:00 +02:00
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'status first time (empty cache)' '
|
|
|
|
avoid_racy &&
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-03-08 11:12:44 +01:00
|
|
|
git status --porcelain >../actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../status.expect ../actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:3
|
|
|
|
....gitignore-invalidation:1
|
|
|
|
....directory-invalidation:0
|
|
|
|
....opendir:4
|
2015-03-08 11:12:44 +01:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-03-08 11:12:44 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'untracked cache after first status' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../dump.expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'status second time (fully populated cache)' '
|
|
|
|
avoid_racy &&
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-03-08 11:12:44 +01:00
|
|
|
git status --porcelain >../actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../status.expect ../actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:0
|
|
|
|
....directory-invalidation:0
|
|
|
|
....opendir:0
|
2015-03-08 11:12:44 +01:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-03-08 11:12:44 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'untracked cache after second status' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../dump.expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'modify in root directory, one dir invalidation' '
|
|
|
|
avoid_racy &&
|
|
|
|
: >four &&
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-03-08 11:12:44 +01:00
|
|
|
git status --porcelain >../actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
A done/one
|
|
|
|
A one
|
|
|
|
A two
|
|
|
|
?? dthree/
|
|
|
|
?? dtwo/
|
|
|
|
?? four
|
|
|
|
?? three
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../status.expect ../actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:0
|
|
|
|
....directory-invalidation:1
|
|
|
|
....opendir:1
|
2015-03-08 11:12:44 +01:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-03-08 11:12:44 +01:00
|
|
|
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'verify untracked cache dump' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../expect <<EOF &&
|
2016-07-16 07:06:25 +02:00
|
|
|
info/exclude $EMPTY_BLOB
|
2020-07-30 01:14:00 +02:00
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $ZERO_OID recurse valid
|
2015-03-08 11:12:44 +01:00
|
|
|
dthree/
|
|
|
|
dtwo/
|
|
|
|
four
|
|
|
|
three
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
three
|
2020-07-30 01:14:00 +02:00
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'new .gitignore invalidates recursively' '
|
|
|
|
avoid_racy &&
|
|
|
|
echo four >.gitignore &&
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-03-08 11:12:44 +01:00
|
|
|
git status --porcelain >../actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
A done/one
|
|
|
|
A one
|
|
|
|
A two
|
|
|
|
?? .gitignore
|
|
|
|
?? dthree/
|
|
|
|
?? dtwo/
|
|
|
|
?? three
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../status.expect ../actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:1
|
|
|
|
....directory-invalidation:1
|
|
|
|
....opendir:4
|
2015-03-08 11:12:44 +01:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-03-08 11:12:44 +01:00
|
|
|
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'verify untracked cache dump' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../expect <<EOF &&
|
2016-07-16 07:06:25 +02:00
|
|
|
info/exclude $EMPTY_BLOB
|
2020-07-30 01:14:00 +02:00
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse valid
|
2015-03-08 11:12:44 +01:00
|
|
|
.gitignore
|
|
|
|
dthree/
|
|
|
|
dtwo/
|
|
|
|
three
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
three
|
2020-07-30 01:14:00 +02:00
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'new info/exclude invalidates everything' '
|
|
|
|
avoid_racy &&
|
|
|
|
echo three >>.git/info/exclude &&
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-03-08 11:12:44 +01:00
|
|
|
git status --porcelain >../actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
A done/one
|
|
|
|
A one
|
|
|
|
A two
|
|
|
|
?? .gitignore
|
|
|
|
?? dtwo/
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../status.expect ../actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:1
|
|
|
|
....directory-invalidation:0
|
|
|
|
....opendir:4
|
2015-03-08 11:12:44 +01:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-03-08 11:12:44 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'verify untracked cache dump' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../expect <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $(test_oid exclude)
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse valid
|
2015-03-08 11:12:44 +01:00
|
|
|
.gitignore
|
|
|
|
dtwo/
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'move two from tracked to untracked' '
|
|
|
|
git rm --cached two &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../expect <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $(test_oid exclude)
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse
|
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'status after the move' '
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-03-08 11:12:44 +01:00
|
|
|
git status --porcelain >../actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
A done/one
|
|
|
|
A one
|
|
|
|
?? .gitignore
|
|
|
|
?? dtwo/
|
|
|
|
?? two
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../status.expect ../actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:0
|
|
|
|
....directory-invalidation:0
|
|
|
|
....opendir:1
|
2015-03-08 11:12:44 +01:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-03-08 11:12:44 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'verify untracked cache dump' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../expect <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $(test_oid exclude)
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse valid
|
2015-03-08 11:12:44 +01:00
|
|
|
.gitignore
|
|
|
|
dtwo/
|
|
|
|
two
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'move two from untracked to tracked' '
|
|
|
|
git add two &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../expect <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $(test_oid exclude)
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse
|
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'status after the move' '
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-03-08 11:12:44 +01:00
|
|
|
git status --porcelain >../actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
A done/one
|
|
|
|
A one
|
|
|
|
A two
|
|
|
|
?? .gitignore
|
|
|
|
?? dtwo/
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-03-08 11:12:44 +01:00
|
|
|
test_cmp ../status.expect ../actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:0
|
|
|
|
....directory-invalidation:0
|
|
|
|
....opendir:1
|
2015-03-08 11:12:44 +01:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-03-08 11:12:44 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'verify untracked cache dump' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-03-08 11:12:44 +01:00
|
|
|
cat >../expect <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $(test_oid exclude)
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-03-08 11:12:44 +01:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse valid
|
2015-03-08 11:12:44 +01:00
|
|
|
.gitignore
|
|
|
|
dtwo/
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-03-08 11:12:44 +01:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
2015-07-31 19:35:01 +02:00
|
|
|
test_expect_success 'set up for sparse checkout testing' '
|
|
|
|
echo two >done/.gitignore &&
|
|
|
|
echo three >>done/.gitignore &&
|
|
|
|
echo two >done/two &&
|
|
|
|
git add -f done/two done/.gitignore &&
|
|
|
|
git commit -m "first commit"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'status after commit' '
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-07-31 19:35:01 +02:00
|
|
|
git status --porcelain >../actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-07-31 19:35:01 +02:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
?? .gitignore
|
|
|
|
?? dtwo/
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-07-31 19:35:01 +02:00
|
|
|
test_cmp ../status.expect ../actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-07-31 19:35:01 +02:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:0
|
|
|
|
....directory-invalidation:0
|
|
|
|
....opendir:2
|
2015-07-31 19:35:01 +02:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-07-31 19:35:01 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'untracked cache correct after commit' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-07-31 19:35:01 +02:00
|
|
|
cat >../expect <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $(test_oid exclude)
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-07-31 19:35:01 +02:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse valid
|
2015-07-31 19:35:01 +02:00
|
|
|
.gitignore
|
|
|
|
dtwo/
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $ZERO_OID recurse valid
|
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-07-31 19:35:01 +02:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'set up sparse checkout' '
|
|
|
|
echo "done/[a-z]*" >.git/info/sparse-checkout &&
|
|
|
|
test_config core.sparsecheckout true &&
|
2020-11-19 00:44:39 +01:00
|
|
|
git checkout main &&
|
2015-08-19 15:01:24 +02:00
|
|
|
git update-index --force-untracked-cache &&
|
2015-07-31 19:35:01 +02:00
|
|
|
git status --porcelain >/dev/null && # prime the cache
|
|
|
|
test_path_is_missing done/.gitignore &&
|
|
|
|
test_path_is_file done/one
|
|
|
|
'
|
|
|
|
|
2015-08-19 15:01:25 +02:00
|
|
|
test_expect_success 'create/modify files, some of which are gitignored' '
|
|
|
|
echo two bis >done/two &&
|
2015-07-31 19:35:01 +02:00
|
|
|
echo three >done/three && # three is gitignored
|
|
|
|
echo four >done/four && # four is gitignored at a higher level
|
2015-10-19 21:48:15 +02:00
|
|
|
echo five >done/five && # five is not gitignored
|
|
|
|
echo test >base && #we need to ensure that the root dir is touched
|
t7063: work around FreeBSD's lazy mtime update feature
Let's start with the commit message of [1] from freebsd.git [2]
Sync timestamp changes for inodes of special files to disk as late
as possible (when the inode is reclaimed). Temporarily only do
this if option UFS_LAZYMOD configured and softupdates aren't
enabled. UFS_LAZYMOD is intentionally left out of
/sys/conf/options.
This is mainly to avoid almost useless disk i/o on battery powered
machines. It's silly to write to disk (on the next sync or when
the inode becomes inactive) just because someone hit a key or
something wrote to the screen or /dev/null.
PR: 5577 [3]
The short version of that, in the context of t7063, is that when a
directory is updated, its mtime may be updated later, not
immediately. This can be shown with a simple command sequence
date; sleep 1; touch abc; rm abc; sleep 10; ls -lTd .
One would expect that the date shown in `ls` would be one second from
`date`, but it's 10 seconds later. If we put another `ls -lTd .` in
front of `sleep 10`, then the date of the last `ls` comes as
expected. The first `ls` somehow forces mtime to be updated.
t7063 is really sensitive to directory mtime. When mtime is too "new",
git code suspects racy timestamps and will not trigger the shortcut in
untracked cache, in t7063.24 and eventually be detected in t7063.27
We have two options thanks to this special FreeBSD feature:
1) Stop supporting untracked cache on FreeBSD. Skip t7063 entirely
when running on FreeBSD
2) Work around this problem (using the same 'ls' trick) and continue
to support untracked cache on FreeBSD
I initially wanted to go with 1) because I didn't know the exact
nature of this feature and feared that it would make untracked cache
work unreliably, using the cached version when it should not.
Since the behavior of this thing is clearer now. The picture is not
that bad. If this indeed happens often, untracked cache would assume
racy condition more often and _fall back_ to non-untracked cache code
paths. Which means it may be less effective, but it will not show
wrong things.
This patch goes with option 2.
PS. For those who want to look further in FreeBSD source code, this
flag is now called IN_LAZYMOD. I can see it's effective in ext2 and
ufs. zfs is not affected.
[1] 660e6408e6df99a20dacb070c5e7f9739efdf96d
[2] git://github.com/freebsd/freebsd.git
[3] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=5577
Reported-by: Eric Wong <e@80x24.org>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-08-03 19:45:22 +02:00
|
|
|
rm base &&
|
|
|
|
sync_mtime
|
2015-07-31 19:35:01 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'test sparse status with untracked cache' '
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
2015-07-31 19:35:01 +02:00
|
|
|
avoid_racy &&
|
2021-05-12 19:28:14 +02:00
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-07-31 19:35:01 +02:00
|
|
|
git status --porcelain >../status.actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-07-31 19:35:01 +02:00
|
|
|
cat >../status.expect <<EOF &&
|
2015-08-19 15:01:25 +02:00
|
|
|
M done/two
|
2015-07-31 19:35:01 +02:00
|
|
|
?? .gitignore
|
|
|
|
?? done/five
|
|
|
|
?? dtwo/
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-07-31 19:35:01 +02:00
|
|
|
test_cmp ../status.expect ../status.actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-07-31 19:35:01 +02:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:1
|
|
|
|
....directory-invalidation:2
|
|
|
|
....opendir:2
|
2015-07-31 19:35:01 +02:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-07-31 19:35:01 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'untracked cache correct after status' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2015-07-31 19:35:01 +02:00
|
|
|
cat >../expect <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $(test_oid exclude)
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-07-31 19:35:01 +02:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse valid
|
2015-07-31 19:35:01 +02:00
|
|
|
.gitignore
|
|
|
|
dtwo/
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $(test_oid done) recurse valid
|
2015-07-31 19:35:01 +02:00
|
|
|
five
|
2020-07-30 01:14:00 +02:00
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-07-31 19:35:01 +02:00
|
|
|
two
|
|
|
|
EOF
|
|
|
|
test_cmp ../expect ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'test sparse status again with untracked cache' '
|
|
|
|
avoid_racy &&
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-07-31 19:35:01 +02:00
|
|
|
git status --porcelain >../status.actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-07-31 19:35:01 +02:00
|
|
|
cat >../status.expect <<EOF &&
|
2015-08-19 15:01:25 +02:00
|
|
|
M done/two
|
2015-07-31 19:35:01 +02:00
|
|
|
?? .gitignore
|
|
|
|
?? done/five
|
|
|
|
?? dtwo/
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-07-31 19:35:01 +02:00
|
|
|
test_cmp ../status.expect ../status.actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-07-31 19:35:01 +02:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:0
|
|
|
|
....directory-invalidation:0
|
|
|
|
....opendir:0
|
2015-07-31 19:35:01 +02:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-07-31 19:35:01 +02:00
|
|
|
'
|
|
|
|
|
2015-08-19 15:01:25 +02:00
|
|
|
test_expect_success 'set up for test of subdir and sparse checkouts' '
|
|
|
|
mkdir done/sub &&
|
|
|
|
mkdir done/sub/sub &&
|
|
|
|
echo "sub" > done/sub/sub/file
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'test sparse status with untracked cache and subdir' '
|
|
|
|
avoid_racy &&
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-08-19 15:01:25 +02:00
|
|
|
git status --porcelain >../status.actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-08-19 15:01:25 +02:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
M done/two
|
|
|
|
?? .gitignore
|
|
|
|
?? done/five
|
|
|
|
?? done/sub/
|
|
|
|
?? dtwo/
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-08-19 15:01:25 +02:00
|
|
|
test_cmp ../status.expect ../status.actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-08-19 15:01:25 +02:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:2
|
|
|
|
....gitignore-invalidation:0
|
|
|
|
....directory-invalidation:1
|
|
|
|
....opendir:3
|
2015-08-19 15:01:25 +02:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-08-19 15:01:25 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
cat >../expect-from-test-dump <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
info/exclude $(test_oid exclude)
|
|
|
|
core.excludesfile $ZERO_OID
|
2015-08-19 15:01:25 +02:00
|
|
|
exclude_per_dir .gitignore
|
|
|
|
flags 00000006
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $(test_oid root) recurse valid
|
2015-08-19 15:01:25 +02:00
|
|
|
.gitignore
|
|
|
|
dtwo/
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/ $(test_oid done) recurse valid
|
2015-08-19 15:01:25 +02:00
|
|
|
five
|
|
|
|
sub/
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/sub/ $ZERO_OID recurse check_only valid
|
2015-08-19 15:01:25 +02:00
|
|
|
sub/
|
2020-07-30 01:14:00 +02:00
|
|
|
/done/sub/sub/ $ZERO_OID recurse check_only valid
|
2015-08-19 15:01:25 +02:00
|
|
|
file
|
2020-07-30 01:14:00 +02:00
|
|
|
/dthree/ $ZERO_OID recurse check_only valid
|
|
|
|
/dtwo/ $ZERO_OID recurse check_only valid
|
2015-08-19 15:01:25 +02:00
|
|
|
two
|
|
|
|
EOF
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-from-test-dump ../actual
|
2015-08-19 15:01:25 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'test sparse status again with untracked cache and subdir' '
|
|
|
|
avoid_racy &&
|
2021-05-12 19:28:14 +02:00
|
|
|
: >../trace.output &&
|
|
|
|
GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \
|
2015-08-19 15:01:25 +02:00
|
|
|
git status --porcelain >../status.actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-08-19 15:01:25 +02:00
|
|
|
test_cmp ../status.expect ../status.actual &&
|
2021-05-12 19:28:14 +02:00
|
|
|
get_relevant_traces ../trace.output ../trace.relevant &&
|
2015-08-19 15:01:25 +02:00
|
|
|
cat >../trace.expect <<EOF &&
|
2021-05-12 19:28:14 +02:00
|
|
|
....path:
|
|
|
|
....node-creation:0
|
|
|
|
....gitignore-invalidation:0
|
|
|
|
....directory-invalidation:0
|
|
|
|
....opendir:0
|
2015-08-19 15:01:25 +02:00
|
|
|
EOF
|
2021-05-12 19:28:14 +02:00
|
|
|
test_cmp ../trace.expect ../trace.relevant
|
2015-08-19 15:01:25 +02:00
|
|
|
'
|
|
|
|
|
2015-08-19 15:01:26 +02:00
|
|
|
test_expect_success 'move entry in subdir from untracked to cached' '
|
|
|
|
git add dtwo/two &&
|
|
|
|
git status --porcelain >../status.actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-08-19 15:01:26 +02:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
M done/two
|
|
|
|
A dtwo/two
|
|
|
|
?? .gitignore
|
|
|
|
?? done/five
|
|
|
|
?? done/sub/
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-08-19 15:01:26 +02:00
|
|
|
test_cmp ../status.expect ../status.actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'move entry in subdir from cached to untracked' '
|
|
|
|
git rm --cached dtwo/two &&
|
|
|
|
git status --porcelain >../status.actual &&
|
2020-04-01 06:17:35 +02:00
|
|
|
iuc status --porcelain >../status.iuc &&
|
2015-08-19 15:01:26 +02:00
|
|
|
cat >../status.expect <<EOF &&
|
|
|
|
M done/two
|
|
|
|
?? .gitignore
|
|
|
|
?? done/five
|
|
|
|
?? done/sub/
|
|
|
|
?? dtwo/
|
|
|
|
EOF
|
2020-04-01 06:17:35 +02:00
|
|
|
test_cmp ../status.expect ../status.iuc &&
|
2015-08-19 15:01:26 +02:00
|
|
|
test_cmp ../status.expect ../status.actual
|
|
|
|
'
|
|
|
|
|
2016-01-27 07:58:07 +01:00
|
|
|
test_expect_success '--no-untracked-cache removes the cache' '
|
|
|
|
git update-index --no-untracked-cache &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
echo "no untracked cache" >../expect-no-uc &&
|
|
|
|
test_cmp ../expect-no-uc ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'git status does not change anything' '
|
|
|
|
git status &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-no-uc ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'setting core.untrackedCache to true and using git status creates the cache' '
|
|
|
|
git config core.untrackedCache true &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-no-uc ../actual &&
|
|
|
|
git status &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-from-test-dump ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'using --no-untracked-cache does not fail when core.untrackedCache is true' '
|
|
|
|
git update-index --no-untracked-cache &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-no-uc ../actual &&
|
|
|
|
git update-index --untracked-cache &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-empty ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'setting core.untrackedCache to false and using git status removes the cache' '
|
|
|
|
git config core.untrackedCache false &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-empty ../actual &&
|
|
|
|
git status &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-no-uc ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'using --untracked-cache does not fail when core.untrackedCache is false' '
|
|
|
|
git update-index --untracked-cache &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-empty ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'setting core.untrackedCache to keep' '
|
|
|
|
git config core.untrackedCache keep &&
|
|
|
|
git update-index --untracked-cache &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-empty ../actual &&
|
|
|
|
git status &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-from-test-dump ../actual &&
|
|
|
|
git update-index --no-untracked-cache &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-no-uc ../actual &&
|
|
|
|
git update-index --force-untracked-cache &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-empty ../actual &&
|
|
|
|
git status &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2016-01-27 07:58:07 +01:00
|
|
|
test_cmp ../expect-from-test-dump ../actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'test ident field is working' '
|
|
|
|
mkdir ../other_worktree &&
|
|
|
|
cp -R done dthree dtwo four three ../other_worktree &&
|
|
|
|
GIT_WORK_TREE=../other_worktree git status 2>../err &&
|
2018-07-21 09:49:19 +02:00
|
|
|
echo "warning: untracked cache is disabled on this system or location" >../expect &&
|
2021-02-11 02:53:53 +01:00
|
|
|
test_cmp ../expect ../err
|
2016-01-27 07:58:07 +01:00
|
|
|
'
|
|
|
|
|
2017-05-08 11:41:42 +02:00
|
|
|
test_expect_success 'untracked cache survives a checkout' '
|
|
|
|
git commit --allow-empty -m empty &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../before &&
|
2020-11-19 00:44:39 +01:00
|
|
|
test_when_finished "git checkout main" &&
|
2017-05-08 11:41:42 +02:00
|
|
|
git checkout -b other_branch &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../after &&
|
2017-05-08 11:41:42 +02:00
|
|
|
test_cmp ../before ../after &&
|
|
|
|
test_commit test &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../before &&
|
2020-11-19 00:44:39 +01:00
|
|
|
git checkout main &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../after &&
|
2017-05-08 11:41:42 +02:00
|
|
|
test_cmp ../before ../after
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'untracked cache survives a commit' '
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../before &&
|
2017-05-08 11:41:42 +02:00
|
|
|
git add done/two &&
|
|
|
|
git commit -m commit &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../after &&
|
2017-05-08 11:41:42 +02:00
|
|
|
test_cmp ../before ../after
|
|
|
|
'
|
|
|
|
|
2018-01-24 10:30:19 +01:00
|
|
|
test_expect_success 'teardown worktree' '
|
|
|
|
cd ..
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success SYMLINKS 'setup worktree for symlink test' '
|
|
|
|
git init worktree-symlink &&
|
|
|
|
cd worktree-symlink &&
|
|
|
|
git config core.untrackedCache true &&
|
|
|
|
mkdir one two &&
|
|
|
|
touch one/file two/file &&
|
|
|
|
git add one/file two/file &&
|
|
|
|
git commit -m"first commit" &&
|
|
|
|
git rm -rf one &&
|
|
|
|
ln -s two one &&
|
|
|
|
git add one &&
|
|
|
|
git commit -m"second commit"
|
|
|
|
'
|
|
|
|
|
dir.c: fix missing dir invalidation in untracked code
Let's start with how create a new directory cache after the last one
becomes invalid (e.g. because its dir mtime has changed...). In
open_cached_dir():
1. We start out with valid_cached_dir() returning false, which should
call invalidate_directory() to put a directory state back to
initial state, no untracked entries (untracked_nr zero), no sub
directory traversal (dirs[].recurse zero).
2. Since the cache cannot be used, we go the slow path opendir() and
go through items one by one via readdir(). All the directories on
disk will be added back to the cache (if not already exist in
dirs[]) and its flag "recurse" gets changed to one to note that
it's part of the cached dir travesal next time.
3. By the time we reach close_cached_dir() we should have a good
subdir list in dirs[]. Those with "recurse" flag set are the ones
present in the on-disk directory. The directory is now marked
"valid".
Next time read_directory() is called, since the directory is marked
valid, it will skip readdir(), go fast path and traverse through
dirs[] array instead.
Steps one and two need some tight cooperation. If a subdir is removed,
readdir() will not find it and of course we cannot examine/invalidate
it. To make sure removed directories on disk are gone from the cache,
step one must make sure recurse flag of all subdirs are zero.
But that's not true. If "valid" flag is already false, there is a
chance we go straight to the end of valid_cached_dir() without calling
invalidate_directory(). Or we fail to meet the "if (untracked-valid)"
condition and skip over the invalidate_directory().
After step 3, we mark the cache valid. Any stale subdir with incorrect
recurse flag becomes a real subdir next time we traverse the directory
using dirs[] array.
We could avoid this by making sure invalidate_directory() is always
called (therefore dirs[].recurse cleared) at the beginning of
open_cached_dir(). Which is what this patch does.
As to how we get into this situation, the key in the test is this
command
git checkout master
where "one/file" is replaced with "one" in the index. This index
update triggers untracked_cache_invalidate_path(), which clears valid
flag of the root directory while keeping "recurse" flag on the subdir
"one" on. On the next git-status, we go through steps 1-3 above and
save an incorrect cache on disk. The second git-status blindly follows
the bad cache data and shows the problem.
This is arguably because of a bad design where "recurse" flag plays
double roles: whether a directory should be saved on disk, and whether
it is part of a directory traversal.
We need to keep recurse flag set at "checkout master" because of the
first role: we need to keep subdir caches (dir "two" for example has
not been touched at all, no reason to throw its cache away).
As long as we make sure to ignore/reset "recurse" flag at the
beginning of a directory traversal, we're good. But maybe eventually
we should separate these two roles.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-01-24 10:30:21 +01:00
|
|
|
test_expect_success SYMLINKS '"status" after symlink replacement should be clean with UC=true' '
|
2018-01-24 10:30:19 +01:00
|
|
|
git checkout HEAD~ &&
|
|
|
|
status_is_clean &&
|
|
|
|
status_is_clean &&
|
2020-11-19 00:44:39 +01:00
|
|
|
git checkout main &&
|
2018-01-24 10:30:19 +01:00
|
|
|
avoid_racy &&
|
|
|
|
status_is_clean &&
|
|
|
|
status_is_clean
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success SYMLINKS '"status" after symlink replacement should be clean with UC=false' '
|
|
|
|
git config core.untrackedCache false &&
|
|
|
|
git checkout HEAD~ &&
|
|
|
|
status_is_clean &&
|
|
|
|
status_is_clean &&
|
2020-11-19 00:44:39 +01:00
|
|
|
git checkout main &&
|
2018-01-24 10:30:19 +01:00
|
|
|
avoid_racy &&
|
|
|
|
status_is_clean &&
|
|
|
|
status_is_clean
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'setup worktree for non-symlink test' '
|
|
|
|
git init worktree-non-symlink &&
|
|
|
|
cd worktree-non-symlink &&
|
|
|
|
git config core.untrackedCache true &&
|
|
|
|
mkdir one two &&
|
|
|
|
touch one/file two/file &&
|
|
|
|
git add one/file two/file &&
|
|
|
|
git commit -m"first commit" &&
|
|
|
|
git rm -rf one &&
|
|
|
|
cp two/file one &&
|
|
|
|
git add one &&
|
|
|
|
git commit -m"second commit"
|
|
|
|
'
|
|
|
|
|
dir.c: fix missing dir invalidation in untracked code
Let's start with how create a new directory cache after the last one
becomes invalid (e.g. because its dir mtime has changed...). In
open_cached_dir():
1. We start out with valid_cached_dir() returning false, which should
call invalidate_directory() to put a directory state back to
initial state, no untracked entries (untracked_nr zero), no sub
directory traversal (dirs[].recurse zero).
2. Since the cache cannot be used, we go the slow path opendir() and
go through items one by one via readdir(). All the directories on
disk will be added back to the cache (if not already exist in
dirs[]) and its flag "recurse" gets changed to one to note that
it's part of the cached dir travesal next time.
3. By the time we reach close_cached_dir() we should have a good
subdir list in dirs[]. Those with "recurse" flag set are the ones
present in the on-disk directory. The directory is now marked
"valid".
Next time read_directory() is called, since the directory is marked
valid, it will skip readdir(), go fast path and traverse through
dirs[] array instead.
Steps one and two need some tight cooperation. If a subdir is removed,
readdir() will not find it and of course we cannot examine/invalidate
it. To make sure removed directories on disk are gone from the cache,
step one must make sure recurse flag of all subdirs are zero.
But that's not true. If "valid" flag is already false, there is a
chance we go straight to the end of valid_cached_dir() without calling
invalidate_directory(). Or we fail to meet the "if (untracked-valid)"
condition and skip over the invalidate_directory().
After step 3, we mark the cache valid. Any stale subdir with incorrect
recurse flag becomes a real subdir next time we traverse the directory
using dirs[] array.
We could avoid this by making sure invalidate_directory() is always
called (therefore dirs[].recurse cleared) at the beginning of
open_cached_dir(). Which is what this patch does.
As to how we get into this situation, the key in the test is this
command
git checkout master
where "one/file" is replaced with "one" in the index. This index
update triggers untracked_cache_invalidate_path(), which clears valid
flag of the root directory while keeping "recurse" flag on the subdir
"one" on. On the next git-status, we go through steps 1-3 above and
save an incorrect cache on disk. The second git-status blindly follows
the bad cache data and shows the problem.
This is arguably because of a bad design where "recurse" flag plays
double roles: whether a directory should be saved on disk, and whether
it is part of a directory traversal.
We need to keep recurse flag set at "checkout master" because of the
first role: we need to keep subdir caches (dir "two" for example has
not been touched at all, no reason to throw its cache away).
As long as we make sure to ignore/reset "recurse" flag at the
beginning of a directory traversal, we're good. But maybe eventually
we should separate these two roles.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-01-24 10:30:21 +01:00
|
|
|
test_expect_success '"status" after file replacement should be clean with UC=true' '
|
2018-01-24 10:30:19 +01:00
|
|
|
git checkout HEAD~ &&
|
|
|
|
status_is_clean &&
|
|
|
|
status_is_clean &&
|
2020-11-19 00:44:39 +01:00
|
|
|
git checkout main &&
|
2018-01-24 10:30:19 +01:00
|
|
|
avoid_racy &&
|
|
|
|
status_is_clean &&
|
2018-09-09 19:36:27 +02:00
|
|
|
test-tool dump-untracked-cache >../actual &&
|
2018-01-24 10:30:19 +01:00
|
|
|
grep -F "recurse valid" ../actual >../actual.grep &&
|
|
|
|
cat >../expect.grep <<EOF &&
|
2020-07-30 01:14:00 +02:00
|
|
|
/ $ZERO_OID recurse valid
|
|
|
|
/two/ $ZERO_OID recurse valid
|
2018-01-24 10:30:19 +01:00
|
|
|
EOF
|
|
|
|
status_is_clean &&
|
|
|
|
test_cmp ../expect.grep ../actual.grep
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success '"status" after file replacement should be clean with UC=false' '
|
|
|
|
git config core.untrackedCache false &&
|
|
|
|
git checkout HEAD~ &&
|
|
|
|
status_is_clean &&
|
|
|
|
status_is_clean &&
|
2020-11-19 00:44:39 +01:00
|
|
|
git checkout main &&
|
2018-01-24 10:30:19 +01:00
|
|
|
avoid_racy &&
|
|
|
|
status_is_clean &&
|
|
|
|
status_is_clean
|
|
|
|
'
|
|
|
|
|
2015-03-08 11:12:44 +01:00
|
|
|
test_done
|