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 mtimemaint
commit
ee52b35e50
|
@ -787,6 +787,17 @@ static int refresh(struct refresh_params *o, unsigned int flag)
|
||||||
setup_work_tree();
|
setup_work_tree();
|
||||||
read_cache();
|
read_cache();
|
||||||
*o->has_errors |= refresh_cache(o->flags | flag);
|
*o->has_errors |= refresh_cache(o->flags | flag);
|
||||||
|
if (has_racy_timestamp(&the_index)) {
|
||||||
|
/*
|
||||||
|
* Even if nothing else has changed, updating the file
|
||||||
|
* increases the chance that racy timestamps become
|
||||||
|
* non-racy, helping future run-time performance.
|
||||||
|
* We do that even in case of "errors" returned by
|
||||||
|
* refresh_cache() as these are no actual errors.
|
||||||
|
* cmd_status() does the same.
|
||||||
|
*/
|
||||||
|
active_cache_changed |= SOMETHING_CHANGED;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
cache.h
1
cache.h
|
@ -889,6 +889,7 @@ void *read_blob_data_from_index(struct index_state *, const char *, unsigned lon
|
||||||
#define CE_MATCH_IGNORE_FSMONITOR 0X20
|
#define CE_MATCH_IGNORE_FSMONITOR 0X20
|
||||||
int is_racy_timestamp(const struct index_state *istate,
|
int is_racy_timestamp(const struct index_state *istate,
|
||||||
const struct cache_entry *ce);
|
const struct cache_entry *ce);
|
||||||
|
int has_racy_timestamp(struct index_state *istate);
|
||||||
int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
|
int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
|
||||||
int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
|
int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
|
||||||
|
|
||||||
|
|
|
@ -2775,7 +2775,7 @@ static int repo_verify_index(struct repository *repo)
|
||||||
return verify_index_from(repo->index, repo->index_file);
|
return verify_index_from(repo->index, repo->index_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int has_racy_timestamp(struct index_state *istate)
|
int has_racy_timestamp(struct index_state *istate)
|
||||||
{
|
{
|
||||||
int entries = istate->cache_nr;
|
int entries = istate->cache_nr;
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='update-index refresh tests related to racy timestamps'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
reset_files () {
|
||||||
|
echo content >file &&
|
||||||
|
echo content >other &&
|
||||||
|
test_set_magic_mtime file &&
|
||||||
|
test_set_magic_mtime other
|
||||||
|
}
|
||||||
|
|
||||||
|
update_assert_changed () {
|
||||||
|
test_set_magic_mtime .git/index &&
|
||||||
|
test_might_fail git update-index "$1" &&
|
||||||
|
! test_is_magic_mtime .git/index
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success 'setup' '
|
||||||
|
reset_files &&
|
||||||
|
# we are calling reset_files() a couple of times during tests;
|
||||||
|
# test-tool chmtime does not change the ctime; to not weaken
|
||||||
|
# or even break our tests, disable ctime-checks entirely
|
||||||
|
git config core.trustctime false &&
|
||||||
|
git add file other &&
|
||||||
|
git commit -m "initial import"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--refresh has no racy timestamps to fix' '
|
||||||
|
reset_files &&
|
||||||
|
# set the index time far enough to the future;
|
||||||
|
# it must be at least 3 seconds for VFAT
|
||||||
|
test_set_magic_mtime .git/index +60 &&
|
||||||
|
git update-index --refresh &&
|
||||||
|
test_is_magic_mtime .git/index +60
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--refresh should fix racy timestamp' '
|
||||||
|
reset_files &&
|
||||||
|
update_assert_changed --refresh
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--really-refresh should fix racy timestamp' '
|
||||||
|
reset_files &&
|
||||||
|
update_assert_changed --really-refresh
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--refresh should fix racy timestamp if other file needs update' '
|
||||||
|
reset_files &&
|
||||||
|
echo content2 >other &&
|
||||||
|
test_set_magic_mtime other &&
|
||||||
|
update_assert_changed --refresh
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--refresh should fix racy timestamp if racy file needs update' '
|
||||||
|
reset_files &&
|
||||||
|
echo content2 >file &&
|
||||||
|
test_set_magic_mtime file &&
|
||||||
|
update_assert_changed --refresh
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
|
@ -1647,13 +1647,33 @@ test_expect_success '"Initial commit" should not be noted in commit template' '
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '--no-optional-locks prevents index update' '
|
test_expect_success '--no-optional-locks prevents index update' '
|
||||||
test-tool chmtime =1234567890 .git/index &&
|
test_set_magic_mtime .git/index &&
|
||||||
git --no-optional-locks status &&
|
git --no-optional-locks status &&
|
||||||
test-tool chmtime --get .git/index >out &&
|
test_is_magic_mtime .git/index &&
|
||||||
grep ^1234567890 out &&
|
|
||||||
git status &&
|
git status &&
|
||||||
test-tool chmtime --get .git/index >out &&
|
! test_is_magic_mtime .git/index
|
||||||
! grep ^1234567890 out
|
'
|
||||||
|
|
||||||
|
test_expect_success 'racy timestamps will be fixed for clean worktree' '
|
||||||
|
echo content >racy-dirty &&
|
||||||
|
echo content >racy-racy &&
|
||||||
|
git add racy* &&
|
||||||
|
git commit -m "racy test files" &&
|
||||||
|
# let status rewrite the index, if necessary; after that we expect
|
||||||
|
# no more index writes unless caused by racy timestamps; note that
|
||||||
|
# timestamps may already be racy now (depending on previous tests)
|
||||||
|
git status &&
|
||||||
|
test_set_magic_mtime .git/index &&
|
||||||
|
git status &&
|
||||||
|
! test_is_magic_mtime .git/index
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'racy timestamps will be fixed for dirty worktree' '
|
||||||
|
echo content2 >racy-dirty &&
|
||||||
|
git status &&
|
||||||
|
test_set_magic_mtime .git/index &&
|
||||||
|
git status &&
|
||||||
|
! test_is_magic_mtime .git/index
|
||||||
'
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -1840,3 +1840,36 @@ test_region () {
|
||||||
test_readlink () {
|
test_readlink () {
|
||||||
perl -le 'print readlink($_) for @ARGV' "$@"
|
perl -le 'print readlink($_) for @ARGV' "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Set mtime to a fixed "magic" timestamp in mid February 2009, before we
|
||||||
|
# run an operation that may or may not touch the file. If the file was
|
||||||
|
# touched, its timestamp will not accidentally have such an old timestamp,
|
||||||
|
# as long as your filesystem clock is reasonably correct. To verify the
|
||||||
|
# timestamp, follow up with test_is_magic_mtime.
|
||||||
|
#
|
||||||
|
# An optional increment to the magic timestamp may be specified as second
|
||||||
|
# argument.
|
||||||
|
test_set_magic_mtime () {
|
||||||
|
local inc=${2:-0} &&
|
||||||
|
local mtime=$((1234567890 + $inc)) &&
|
||||||
|
test-tool chmtime =$mtime "$1" &&
|
||||||
|
test_is_magic_mtime "$1" $inc
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test whether the given file has the "magic" mtime set. This is meant to
|
||||||
|
# be used in combination with test_set_magic_mtime.
|
||||||
|
#
|
||||||
|
# An optional increment to the magic timestamp may be specified as second
|
||||||
|
# argument. Usually, this should be the same increment which was used for
|
||||||
|
# the associated test_set_magic_mtime.
|
||||||
|
test_is_magic_mtime () {
|
||||||
|
local inc=${2:-0} &&
|
||||||
|
local mtime=$((1234567890 + $inc)) &&
|
||||||
|
echo $mtime >.git/test-mtime-expect &&
|
||||||
|
test-tool chmtime --get "$1" >.git/test-mtime-actual &&
|
||||||
|
test_cmp .git/test-mtime-expect .git/test-mtime-actual
|
||||||
|
local ret=$?
|
||||||
|
rm -f .git/test-mtime-expect
|
||||||
|
rm -f .git/test-mtime-actual
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue