Merge branch 'js/split-index-fixes'
The index files can become corrupt under certain conditions when the split-index feature is in use, especially together with fsmonitor, which have been corrected. * js/split-index-fixes: unpack-trees: take care to propagate the split-index flag fsmonitor: avoid overriding `cache_changed` bits split-index; stop abusing the `base_oid` to strip the "link" extension split-index & fsmonitor: demonstrate a bug
This commit is contained in:
commit
f315a8b609
@ -86,7 +86,7 @@ static inline void mark_fsmonitor_valid(struct index_state *istate, struct cache
|
||||
!(ce->ce_flags & CE_FSMONITOR_VALID)) {
|
||||
if (S_ISGITLINK(ce->ce_mode))
|
||||
return;
|
||||
istate->cache_changed = 1;
|
||||
istate->cache_changed |= FSMONITOR_CHANGED;
|
||||
ce->ce_flags |= CE_FSMONITOR_VALID;
|
||||
trace_printf_key(&trace_fsmonitor, "mark_fsmonitor_clean '%s'", ce->name);
|
||||
}
|
||||
|
49
read-cache.c
49
read-cache.c
@ -2903,6 +2903,16 @@ static int record_ieot(void)
|
||||
return !git_config_get_index_threads(&val) && val != 1;
|
||||
}
|
||||
|
||||
enum write_extensions {
|
||||
WRITE_NO_EXTENSION = 0,
|
||||
WRITE_SPLIT_INDEX_EXTENSION = 1<<0,
|
||||
WRITE_CACHE_TREE_EXTENSION = 1<<1,
|
||||
WRITE_RESOLVE_UNDO_EXTENSION = 1<<2,
|
||||
WRITE_UNTRACKED_CACHE_EXTENSION = 1<<3,
|
||||
WRITE_FSMONITOR_EXTENSION = 1<<4,
|
||||
};
|
||||
#define WRITE_ALL_EXTENSIONS ((enum write_extensions)-1)
|
||||
|
||||
/*
|
||||
* On success, `tempfile` is closed. If it is the temporary file
|
||||
* of a `struct lock_file`, we will therefore effectively perform
|
||||
@ -2911,7 +2921,7 @@ static int record_ieot(void)
|
||||
* rely on it.
|
||||
*/
|
||||
static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
|
||||
int strip_extensions, unsigned flags)
|
||||
enum write_extensions write_extensions, unsigned flags)
|
||||
{
|
||||
uint64_t start = getnanotime();
|
||||
struct hashfile *f;
|
||||
@ -3084,8 +3094,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strip_extensions && istate->split_index &&
|
||||
!is_null_oid(&istate->split_index->base_oid)) {
|
||||
if (write_extensions & WRITE_SPLIT_INDEX_EXTENSION &&
|
||||
istate->split_index) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
if (istate->sparse_index)
|
||||
@ -3099,7 +3109,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
if (!strip_extensions && !drop_cache_tree && istate->cache_tree) {
|
||||
if (write_extensions & WRITE_CACHE_TREE_EXTENSION &&
|
||||
!drop_cache_tree && istate->cache_tree) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
cache_tree_write(&sb, istate->cache_tree);
|
||||
@ -3109,7 +3120,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
if (!strip_extensions && istate->resolve_undo) {
|
||||
if (write_extensions & WRITE_RESOLVE_UNDO_EXTENSION &&
|
||||
istate->resolve_undo) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
resolve_undo_write(&sb, istate->resolve_undo);
|
||||
@ -3120,7 +3132,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
if (!strip_extensions && istate->untracked) {
|
||||
if (write_extensions & WRITE_UNTRACKED_CACHE_EXTENSION &&
|
||||
istate->untracked) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
write_untracked_extension(&sb, istate->untracked);
|
||||
@ -3131,7 +3144,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
if (!strip_extensions && istate->fsmonitor_last_update) {
|
||||
if (write_extensions & WRITE_FSMONITOR_EXTENSION &&
|
||||
istate->fsmonitor_last_update) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
write_fsmonitor_extension(&sb, istate);
|
||||
@ -3205,8 +3219,10 @@ static int commit_locked_index(struct lock_file *lk)
|
||||
return commit_lock_file(lk);
|
||||
}
|
||||
|
||||
static int do_write_locked_index(struct index_state *istate, struct lock_file *lock,
|
||||
unsigned flags)
|
||||
static int do_write_locked_index(struct index_state *istate,
|
||||
struct lock_file *lock,
|
||||
unsigned flags,
|
||||
enum write_extensions write_extensions)
|
||||
{
|
||||
int ret;
|
||||
int was_full = istate->sparse_index == INDEX_EXPANDED;
|
||||
@ -3224,7 +3240,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
|
||||
*/
|
||||
trace2_region_enter_printf("index", "do_write_index", the_repository,
|
||||
"%s", get_lock_file_path(lock));
|
||||
ret = do_write_index(istate, lock->tempfile, 0, flags);
|
||||
ret = do_write_index(istate, lock->tempfile, write_extensions, flags);
|
||||
trace2_region_leave_printf("index", "do_write_index", the_repository,
|
||||
"%s", get_lock_file_path(lock));
|
||||
|
||||
@ -3253,7 +3269,7 @@ static int write_split_index(struct index_state *istate,
|
||||
{
|
||||
int ret;
|
||||
prepare_to_write_split_index(istate);
|
||||
ret = do_write_locked_index(istate, lock, flags);
|
||||
ret = do_write_locked_index(istate, lock, flags, WRITE_ALL_EXTENSIONS);
|
||||
finish_writing_split_index(istate);
|
||||
return ret;
|
||||
}
|
||||
@ -3328,7 +3344,7 @@ static int write_shared_index(struct index_state *istate,
|
||||
|
||||
trace2_region_enter_printf("index", "shared/do_write_index",
|
||||
the_repository, "%s", get_tempfile_path(*temp));
|
||||
ret = do_write_index(si->base, *temp, 1, flags);
|
||||
ret = do_write_index(si->base, *temp, WRITE_NO_EXTENSION, flags);
|
||||
trace2_region_leave_printf("index", "shared/do_write_index",
|
||||
the_repository, "%s", get_tempfile_path(*temp));
|
||||
|
||||
@ -3405,9 +3421,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
|
||||
if ((!si && !test_split_index_env) ||
|
||||
alternate_index_output ||
|
||||
(istate->cache_changed & ~EXTMASK)) {
|
||||
if (si)
|
||||
oidclr(&si->base_oid);
|
||||
ret = do_write_locked_index(istate, lock, flags);
|
||||
ret = do_write_locked_index(istate, lock, flags,
|
||||
~WRITE_SPLIT_INDEX_EXTENSION);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -3433,8 +3448,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
|
||||
/* Same initial permissions as the main .git/index file */
|
||||
temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666);
|
||||
if (!temp) {
|
||||
oidclr(&si->base_oid);
|
||||
ret = do_write_locked_index(istate, lock, flags);
|
||||
ret = do_write_locked_index(istate, lock, flags,
|
||||
~WRITE_SPLIT_INDEX_EXTENSION);
|
||||
goto out;
|
||||
}
|
||||
ret = write_shared_index(istate, &temp, flags);
|
||||
|
@ -995,4 +995,41 @@ test_expect_success !UNICODE_COMPOSITION_SENSITIVE 'Unicode nfc/nfd' '
|
||||
grep -E "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
|
||||
'
|
||||
|
||||
test_expect_success 'split-index and FSMonitor work well together' '
|
||||
git init split-index &&
|
||||
test_when_finished "git -C \"$PWD/split-index\" \
|
||||
fsmonitor--daemon stop" &&
|
||||
(
|
||||
cd split-index &&
|
||||
git config core.splitIndex true &&
|
||||
# force split-index in most cases
|
||||
git config splitIndex.maxPercentChange 99 &&
|
||||
git config core.fsmonitor true &&
|
||||
|
||||
# Create the following commit topology:
|
||||
#
|
||||
# * merge three
|
||||
# |\
|
||||
# | * three
|
||||
# * | merge two
|
||||
# |\|
|
||||
# | * two
|
||||
# * | one
|
||||
# |/
|
||||
# * 5a5efd7 initial
|
||||
|
||||
test_commit initial &&
|
||||
test_commit two &&
|
||||
test_commit three &&
|
||||
git reset --hard initial &&
|
||||
test_commit one &&
|
||||
test_tick &&
|
||||
git merge two &&
|
||||
test_tick &&
|
||||
git merge three &&
|
||||
|
||||
git rebase --force-rebase -r one
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -1926,6 +1926,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
|
||||
* avoid having to create a new one.
|
||||
*/
|
||||
o->internal.result.split_index = o->src_index->split_index;
|
||||
if (o->src_index->cache_changed & SPLIT_INDEX_ORDERED)
|
||||
o->internal.result.cache_changed |= SPLIT_INDEX_ORDERED;
|
||||
o->internal.result.split_index->refcount++;
|
||||
} else {
|
||||
o->internal.result.split_index =
|
||||
|
Loading…
Reference in New Issue
Block a user