summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cache.h2
-rw-r--r--read-cache.c2
-rw-r--r--split-index.c42
-rwxr-xr-xt/t1701-racy-split-index.sh8
4 files changed, 46 insertions, 8 deletions
diff --git a/cache.h b/cache.h
index 4d01454..3f419b6 100644
--- a/cache.h
+++ b/cache.h
@@ -781,6 +781,8 @@ extern void *read_blob_data_from_index(const struct index_state *, const char *,
#define CE_MATCH_REFRESH 0x10
/* don't refresh_fsmonitor state or do stat comparison even if CE_FSMONITOR_VALID is true */
#define CE_MATCH_IGNORE_FSMONITOR 0X20
+extern int is_racy_timestamp(const struct index_state *istate,
+ const struct cache_entry *ce);
extern int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
extern int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
diff --git a/read-cache.c b/read-cache.c
index 7b1354d..8f644f6 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -337,7 +337,7 @@ static int is_racy_stat(const struct index_state *istate,
);
}
-static int is_racy_timestamp(const struct index_state *istate,
+int is_racy_timestamp(const struct index_state *istate,
const struct cache_entry *ce)
{
return (!S_ISGITLINK(ce->ce_mode) &&
diff --git a/split-index.c b/split-index.c
index 187b910..875f538 100644
--- a/split-index.c
+++ b/split-index.c
@@ -259,8 +259,39 @@ void prepare_to_write_split_index(struct index_state *istate)
}
ce->ce_flags |= CE_MATCHED; /* or "shared" */
base = si->base->cache[ce->index - 1];
- if (ce == base)
+ if (ce == base) {
+ /* The entry is present in the shared index. */
+ if (ce->ce_flags & CE_UPDATE_IN_BASE) {
+ /*
+ * Already marked for inclusion in
+ * the split index, either because
+ * the corresponding file was
+ * modified and the cached stat data
+ * was refreshed, or because there
+ * is already a replacement entry in
+ * the split index.
+ * Nothing more to do here.
+ */
+ } else if (!ce_uptodate(ce) &&
+ is_racy_timestamp(istate, ce)) {
+ /*
+ * A racily clean cache entry stored
+ * only in the shared index: it must
+ * be added to the split index, so
+ * the subsequent do_write_index()
+ * can smudge its stat data.
+ */
+ ce->ce_flags |= CE_UPDATE_IN_BASE;
+ } else {
+ /*
+ * The entry is only present in the
+ * shared index and it was not
+ * refreshed.
+ * Just leave it there.
+ */
+ }
continue;
+ }
if (ce->ce_namelen != base->ce_namelen ||
strcmp(ce->name, base->name)) {
ce->index = 0;
@@ -281,6 +312,15 @@ void prepare_to_write_split_index(struct index_state *istate)
* the split index.
* Nothing to do.
*/
+ } else if (!ce_uptodate(ce) &&
+ is_racy_timestamp(istate, ce)) {
+ /*
+ * A copy of a racily clean cache entry from
+ * the shared index. It must be added to
+ * the split index, so the subsequent
+ * do_write_index() can smudge its stat data.
+ */
+ ce->ce_flags |= CE_UPDATE_IN_BASE;
} else {
/*
* Thoroughly compare the cached data to see
diff --git a/t/t1701-racy-split-index.sh b/t/t1701-racy-split-index.sh
index fbb7704..5dc221e 100755
--- a/t/t1701-racy-split-index.sh
+++ b/t/t1701-racy-split-index.sh
@@ -148,7 +148,7 @@ done
for trial in $trials
do
- test_expect_failure "update the split index when a racily clean cache entry is stored only in the shared index $trial" '
+ test_expect_success "update the split index when a racily clean cache entry is stored only in the shared index #$trial" '
rm -f .git/index .git/sharedindex.* &&
# The next three commands must be run within the same
@@ -170,8 +170,6 @@ do
# entry of racy-file is only stored in the shared index.
# A corresponding replacement cache entry with smudged
# stat data should be added to the new split index.
- #
- # Alas, such a smudged replacement entry is not added!
git update-index --add other-file &&
# Subsequent git commands should notice the smudged
@@ -182,7 +180,7 @@ done
for trial in $trials
do
- test_expect_failure "update the split index after unpack trees() copied a racily clean cache entry from the shared index $trial" '
+ test_expect_success "update the split index after unpack trees() copied a racily clean cache entry from the shared index #$trial" '
rm -f .git/index .git/sharedindex.* &&
# The next three commands must be run within the same
@@ -205,8 +203,6 @@ do
# index. A corresponding replacement cache entry
# with smudged stat data should be added to the new
# split index.
- #
- # Alas, such a smudged replacement entry is not added!
git read-tree -m HEAD &&
# Subsequent git commands should notice the smudged