Skip to content

Commit f315a8b

Browse files
committed
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
2 parents f834089 + 061dd72 commit f315a8b

File tree

4 files changed

+72
-18
lines changed

4 files changed

+72
-18
lines changed

fsmonitor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static inline void mark_fsmonitor_valid(struct index_state *istate, struct cache
8686
!(ce->ce_flags & CE_FSMONITOR_VALID)) {
8787
if (S_ISGITLINK(ce->ce_mode))
8888
return;
89-
istate->cache_changed = 1;
89+
istate->cache_changed |= FSMONITOR_CHANGED;
9090
ce->ce_flags |= CE_FSMONITOR_VALID;
9191
trace_printf_key(&trace_fsmonitor, "mark_fsmonitor_clean '%s'", ce->name);
9292
}

read-cache.c

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2903,6 +2903,16 @@ static int record_ieot(void)
29032903
return !git_config_get_index_threads(&val) && val != 1;
29042904
}
29052905

2906+
enum write_extensions {
2907+
WRITE_NO_EXTENSION = 0,
2908+
WRITE_SPLIT_INDEX_EXTENSION = 1<<0,
2909+
WRITE_CACHE_TREE_EXTENSION = 1<<1,
2910+
WRITE_RESOLVE_UNDO_EXTENSION = 1<<2,
2911+
WRITE_UNTRACKED_CACHE_EXTENSION = 1<<3,
2912+
WRITE_FSMONITOR_EXTENSION = 1<<4,
2913+
};
2914+
#define WRITE_ALL_EXTENSIONS ((enum write_extensions)-1)
2915+
29062916
/*
29072917
* On success, `tempfile` is closed. If it is the temporary file
29082918
* of a `struct lock_file`, we will therefore effectively perform
@@ -2911,7 +2921,7 @@ static int record_ieot(void)
29112921
* rely on it.
29122922
*/
29132923
static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
2914-
int strip_extensions, unsigned flags)
2924+
enum write_extensions write_extensions, unsigned flags)
29152925
{
29162926
uint64_t start = getnanotime();
29172927
struct hashfile *f;
@@ -3084,8 +3094,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
30843094
return -1;
30853095
}
30863096

3087-
if (!strip_extensions && istate->split_index &&
3088-
!is_null_oid(&istate->split_index->base_oid)) {
3097+
if (write_extensions & WRITE_SPLIT_INDEX_EXTENSION &&
3098+
istate->split_index) {
30893099
struct strbuf sb = STRBUF_INIT;
30903100

30913101
if (istate->sparse_index)
@@ -3099,7 +3109,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
30993109
if (err)
31003110
return -1;
31013111
}
3102-
if (!strip_extensions && !drop_cache_tree && istate->cache_tree) {
3112+
if (write_extensions & WRITE_CACHE_TREE_EXTENSION &&
3113+
!drop_cache_tree && istate->cache_tree) {
31033114
struct strbuf sb = STRBUF_INIT;
31043115

31053116
cache_tree_write(&sb, istate->cache_tree);
@@ -3109,7 +3120,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
31093120
if (err)
31103121
return -1;
31113122
}
3112-
if (!strip_extensions && istate->resolve_undo) {
3123+
if (write_extensions & WRITE_RESOLVE_UNDO_EXTENSION &&
3124+
istate->resolve_undo) {
31133125
struct strbuf sb = STRBUF_INIT;
31143126

31153127
resolve_undo_write(&sb, istate->resolve_undo);
@@ -3120,7 +3132,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
31203132
if (err)
31213133
return -1;
31223134
}
3123-
if (!strip_extensions && istate->untracked) {
3135+
if (write_extensions & WRITE_UNTRACKED_CACHE_EXTENSION &&
3136+
istate->untracked) {
31243137
struct strbuf sb = STRBUF_INIT;
31253138

31263139
write_untracked_extension(&sb, istate->untracked);
@@ -3131,7 +3144,8 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
31313144
if (err)
31323145
return -1;
31333146
}
3134-
if (!strip_extensions && istate->fsmonitor_last_update) {
3147+
if (write_extensions & WRITE_FSMONITOR_EXTENSION &&
3148+
istate->fsmonitor_last_update) {
31353149
struct strbuf sb = STRBUF_INIT;
31363150

31373151
write_fsmonitor_extension(&sb, istate);
@@ -3205,8 +3219,10 @@ static int commit_locked_index(struct lock_file *lk)
32053219
return commit_lock_file(lk);
32063220
}
32073221

3208-
static int do_write_locked_index(struct index_state *istate, struct lock_file *lock,
3209-
unsigned flags)
3222+
static int do_write_locked_index(struct index_state *istate,
3223+
struct lock_file *lock,
3224+
unsigned flags,
3225+
enum write_extensions write_extensions)
32103226
{
32113227
int ret;
32123228
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
32243240
*/
32253241
trace2_region_enter_printf("index", "do_write_index", the_repository,
32263242
"%s", get_lock_file_path(lock));
3227-
ret = do_write_index(istate, lock->tempfile, 0, flags);
3243+
ret = do_write_index(istate, lock->tempfile, write_extensions, flags);
32283244
trace2_region_leave_printf("index", "do_write_index", the_repository,
32293245
"%s", get_lock_file_path(lock));
32303246

@@ -3253,7 +3269,7 @@ static int write_split_index(struct index_state *istate,
32533269
{
32543270
int ret;
32553271
prepare_to_write_split_index(istate);
3256-
ret = do_write_locked_index(istate, lock, flags);
3272+
ret = do_write_locked_index(istate, lock, flags, WRITE_ALL_EXTENSIONS);
32573273
finish_writing_split_index(istate);
32583274
return ret;
32593275
}
@@ -3328,7 +3344,7 @@ static int write_shared_index(struct index_state *istate,
33283344

33293345
trace2_region_enter_printf("index", "shared/do_write_index",
33303346
the_repository, "%s", get_tempfile_path(*temp));
3331-
ret = do_write_index(si->base, *temp, 1, flags);
3347+
ret = do_write_index(si->base, *temp, WRITE_NO_EXTENSION, flags);
33323348
trace2_region_leave_printf("index", "shared/do_write_index",
33333349
the_repository, "%s", get_tempfile_path(*temp));
33343350

@@ -3405,9 +3421,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
34053421
if ((!si && !test_split_index_env) ||
34063422
alternate_index_output ||
34073423
(istate->cache_changed & ~EXTMASK)) {
3408-
if (si)
3409-
oidclr(&si->base_oid);
3410-
ret = do_write_locked_index(istate, lock, flags);
3424+
ret = do_write_locked_index(istate, lock, flags,
3425+
~WRITE_SPLIT_INDEX_EXTENSION);
34113426
goto out;
34123427
}
34133428

@@ -3433,8 +3448,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
34333448
/* Same initial permissions as the main .git/index file */
34343449
temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666);
34353450
if (!temp) {
3436-
oidclr(&si->base_oid);
3437-
ret = do_write_locked_index(istate, lock, flags);
3451+
ret = do_write_locked_index(istate, lock, flags,
3452+
~WRITE_SPLIT_INDEX_EXTENSION);
34383453
goto out;
34393454
}
34403455
ret = write_shared_index(istate, &temp, flags);

t/t7527-builtin-fsmonitor.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,4 +995,41 @@ test_expect_success !UNICODE_COMPOSITION_SENSITIVE 'Unicode nfc/nfd' '
995995
grep -E "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
996996
'
997997

998+
test_expect_success 'split-index and FSMonitor work well together' '
999+
git init split-index &&
1000+
test_when_finished "git -C \"$PWD/split-index\" \
1001+
fsmonitor--daemon stop" &&
1002+
(
1003+
cd split-index &&
1004+
git config core.splitIndex true &&
1005+
# force split-index in most cases
1006+
git config splitIndex.maxPercentChange 99 &&
1007+
git config core.fsmonitor true &&
1008+
1009+
# Create the following commit topology:
1010+
#
1011+
# * merge three
1012+
# |\
1013+
# | * three
1014+
# * | merge two
1015+
# |\|
1016+
# | * two
1017+
# * | one
1018+
# |/
1019+
# * 5a5efd7 initial
1020+
1021+
test_commit initial &&
1022+
test_commit two &&
1023+
test_commit three &&
1024+
git reset --hard initial &&
1025+
test_commit one &&
1026+
test_tick &&
1027+
git merge two &&
1028+
test_tick &&
1029+
git merge three &&
1030+
1031+
git rebase --force-rebase -r one
1032+
)
1033+
'
1034+
9981035
test_done

unpack-trees.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
19261926
* avoid having to create a new one.
19271927
*/
19281928
o->internal.result.split_index = o->src_index->split_index;
1929+
if (o->src_index->cache_changed & SPLIT_INDEX_ORDERED)
1930+
o->internal.result.cache_changed |= SPLIT_INDEX_ORDERED;
19291931
o->internal.result.split_index->refcount++;
19301932
} else {
19311933
o->internal.result.split_index =

0 commit comments

Comments
 (0)