Skip to content

Commit ee52b35

Browse files
committed
Merge branch 'ms/update-index-racy'
"git update-index --refresh" has been taught to deal better with racy timestamps (just like "git status" already does). * ms/update-index-racy: update-index: refresh should rewrite index in case of racy timestamps t7508: add tests capturing racy timestamp handling t7508: fix bogus mtime verification test-lib: introduce API for verifying file mtime
2 parents 1b4d9b4 + 2ede073 commit ee52b35

File tree

6 files changed

+135
-6
lines changed

6 files changed

+135
-6
lines changed

builtin/update-index.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,17 @@ static int refresh(struct refresh_params *o, unsigned int flag)
787787
setup_work_tree();
788788
read_cache();
789789
*o->has_errors |= refresh_cache(o->flags | flag);
790+
if (has_racy_timestamp(&the_index)) {
791+
/*
792+
* Even if nothing else has changed, updating the file
793+
* increases the chance that racy timestamps become
794+
* non-racy, helping future run-time performance.
795+
* We do that even in case of "errors" returned by
796+
* refresh_cache() as these are no actual errors.
797+
* cmd_status() does the same.
798+
*/
799+
active_cache_changed |= SOMETHING_CHANGED;
800+
}
790801
return 0;
791802
}
792803

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,7 @@ void *read_blob_data_from_index(struct index_state *, const char *, unsigned lon
889889
#define CE_MATCH_IGNORE_FSMONITOR 0X20
890890
int is_racy_timestamp(const struct index_state *istate,
891891
const struct cache_entry *ce);
892+
int has_racy_timestamp(struct index_state *istate);
892893
int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
893894
int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
894895

read-cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2775,7 +2775,7 @@ static int repo_verify_index(struct repository *repo)
27752775
return verify_index_from(repo->index, repo->index_file);
27762776
}
27772777

2778-
static int has_racy_timestamp(struct index_state *istate)
2778+
int has_racy_timestamp(struct index_state *istate)
27792779
{
27802780
int entries = istate->cache_nr;
27812781
int i;

t/t2108-update-index-refresh-racy.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/bin/sh
2+
3+
test_description='update-index refresh tests related to racy timestamps'
4+
5+
TEST_PASSES_SANITIZE_LEAK=true
6+
. ./test-lib.sh
7+
8+
reset_files () {
9+
echo content >file &&
10+
echo content >other &&
11+
test_set_magic_mtime file &&
12+
test_set_magic_mtime other
13+
}
14+
15+
update_assert_changed () {
16+
test_set_magic_mtime .git/index &&
17+
test_might_fail git update-index "$1" &&
18+
! test_is_magic_mtime .git/index
19+
}
20+
21+
test_expect_success 'setup' '
22+
reset_files &&
23+
# we are calling reset_files() a couple of times during tests;
24+
# test-tool chmtime does not change the ctime; to not weaken
25+
# or even break our tests, disable ctime-checks entirely
26+
git config core.trustctime false &&
27+
git add file other &&
28+
git commit -m "initial import"
29+
'
30+
31+
test_expect_success '--refresh has no racy timestamps to fix' '
32+
reset_files &&
33+
# set the index time far enough to the future;
34+
# it must be at least 3 seconds for VFAT
35+
test_set_magic_mtime .git/index +60 &&
36+
git update-index --refresh &&
37+
test_is_magic_mtime .git/index +60
38+
'
39+
40+
test_expect_success '--refresh should fix racy timestamp' '
41+
reset_files &&
42+
update_assert_changed --refresh
43+
'
44+
45+
test_expect_success '--really-refresh should fix racy timestamp' '
46+
reset_files &&
47+
update_assert_changed --really-refresh
48+
'
49+
50+
test_expect_success '--refresh should fix racy timestamp if other file needs update' '
51+
reset_files &&
52+
echo content2 >other &&
53+
test_set_magic_mtime other &&
54+
update_assert_changed --refresh
55+
'
56+
57+
test_expect_success '--refresh should fix racy timestamp if racy file needs update' '
58+
reset_files &&
59+
echo content2 >file &&
60+
test_set_magic_mtime file &&
61+
update_assert_changed --refresh
62+
'
63+
64+
test_done

t/t7508-status.sh

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,13 +1647,33 @@ test_expect_success '"Initial commit" should not be noted in commit template' '
16471647
'
16481648

16491649
test_expect_success '--no-optional-locks prevents index update' '
1650-
test-tool chmtime =1234567890 .git/index &&
1650+
test_set_magic_mtime .git/index &&
16511651
git --no-optional-locks status &&
1652-
test-tool chmtime --get .git/index >out &&
1653-
grep ^1234567890 out &&
1652+
test_is_magic_mtime .git/index &&
16541653
git status &&
1655-
test-tool chmtime --get .git/index >out &&
1656-
! grep ^1234567890 out
1654+
! test_is_magic_mtime .git/index
1655+
'
1656+
1657+
test_expect_success 'racy timestamps will be fixed for clean worktree' '
1658+
echo content >racy-dirty &&
1659+
echo content >racy-racy &&
1660+
git add racy* &&
1661+
git commit -m "racy test files" &&
1662+
# let status rewrite the index, if necessary; after that we expect
1663+
# no more index writes unless caused by racy timestamps; note that
1664+
# timestamps may already be racy now (depending on previous tests)
1665+
git status &&
1666+
test_set_magic_mtime .git/index &&
1667+
git status &&
1668+
! test_is_magic_mtime .git/index
1669+
'
1670+
1671+
test_expect_success 'racy timestamps will be fixed for dirty worktree' '
1672+
echo content2 >racy-dirty &&
1673+
git status &&
1674+
test_set_magic_mtime .git/index &&
1675+
git status &&
1676+
! test_is_magic_mtime .git/index
16571677
'
16581678

16591679
test_done

t/test-lib-functions.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,3 +1840,36 @@ test_region () {
18401840
test_readlink () {
18411841
perl -le 'print readlink($_) for @ARGV' "$@"
18421842
}
1843+
1844+
# Set mtime to a fixed "magic" timestamp in mid February 2009, before we
1845+
# run an operation that may or may not touch the file. If the file was
1846+
# touched, its timestamp will not accidentally have such an old timestamp,
1847+
# as long as your filesystem clock is reasonably correct. To verify the
1848+
# timestamp, follow up with test_is_magic_mtime.
1849+
#
1850+
# An optional increment to the magic timestamp may be specified as second
1851+
# argument.
1852+
test_set_magic_mtime () {
1853+
local inc=${2:-0} &&
1854+
local mtime=$((1234567890 + $inc)) &&
1855+
test-tool chmtime =$mtime "$1" &&
1856+
test_is_magic_mtime "$1" $inc
1857+
}
1858+
1859+
# Test whether the given file has the "magic" mtime set. This is meant to
1860+
# be used in combination with test_set_magic_mtime.
1861+
#
1862+
# An optional increment to the magic timestamp may be specified as second
1863+
# argument. Usually, this should be the same increment which was used for
1864+
# the associated test_set_magic_mtime.
1865+
test_is_magic_mtime () {
1866+
local inc=${2:-0} &&
1867+
local mtime=$((1234567890 + $inc)) &&
1868+
echo $mtime >.git/test-mtime-expect &&
1869+
test-tool chmtime --get "$1" >.git/test-mtime-actual &&
1870+
test_cmp .git/test-mtime-expect .git/test-mtime-actual
1871+
local ret=$?
1872+
rm -f .git/test-mtime-expect
1873+
rm -f .git/test-mtime-actual
1874+
return $ret
1875+
}

0 commit comments

Comments
 (0)