summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 29e4d36)
raw | patch | inline | side by side (parent: 29e4d36)
author | Junio C Hamano <junkio@cox.net> | |
Tue, 20 Dec 2005 20:12:18 +0000 (12:12 -0800) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Tue, 20 Dec 2005 20:12:18 +0000 (12:12 -0800) |
The previous round caught the most trivial case well, but broke
down once index file is updated again. Smudge problematic
entries (they should be very few if any under normal interactive
workflow) before writing a new index file out.
Signed-off-by: Junio C Hamano <junkio@cox.net>
down once index file is updated again. Smudge problematic
entries (they should be very few if any under normal interactive
workflow) before writing a new index file out.
Signed-off-by: Junio C Hamano <junkio@cox.net>
read-cache.c | patch | blob | history | |
t/t0010-racy-git.sh | patch | blob | history |
diff --git a/read-cache.c b/read-cache.c
index 780601f071a0f5ae35b6d379abdd935d79ca92e2..afdc2b075b00c035c378a6f2ff29de267ff45b4d 100644 (file)
--- a/read-cache.c
+++ b/read-cache.c
return 0;
}
-int ce_match_stat(struct cache_entry *ce, struct stat *st)
+static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
{
unsigned int changed = 0;
if (ce->ce_size != htonl(st->st_size))
changed |= DATA_CHANGED;
+ return changed;
+}
+
+int ce_match_stat(struct cache_entry *ce, struct stat *st)
+{
+ unsigned int changed = ce_match_stat_basic(ce, st);
+
/*
* Within 1 second of this sequence:
* echo xyzzy >file && git-update-index --add file
return 0;
}
+static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
+{
+ /*
+ * The only thing we care about in this function is to smudge the
+ * falsely clean entry due to touch-update-touch race, so we leave
+ * everything else as they are. We are called for entries whose
+ * ce_mtime match the index file mtime.
+ */
+ struct stat st;
+
+ if (lstat(ce->name, &st) < 0)
+ return;
+ if (ce_match_stat_basic(ce, &st))
+ return;
+ if (ce_modified_check_fs(ce, &st)) {
+ /* This is "racily clean"; smudge it */
+ ce->ce_size = htonl(0);
+ }
+}
+
int write_cache(int newfd, struct cache_entry **cache, int entries)
{
SHA_CTX c;
struct cache_entry *ce = cache[i];
if (!ce->ce_mode)
continue;
+ if (index_file_timestamp &&
+ index_file_timestamp <= ntohl(ce->ce_mtime.sec))
+ ce_smudge_racily_clean_entry(ce);
if (ce_write(&c, newfd, ce, ce_size(ce)) < 0)
return -1;
}
diff --git a/t/t0010-racy-git.sh b/t/t0010-racy-git.sh
index eb175b780f4f60574425a720fb3536ad4618a94c..e45a9e40e432524454e94a041599b201a092879a 100755 (executable)
--- a/t/t0010-racy-git.sh
+++ b/t/t0010-racy-git.sh
# This test can give false success if your machine is sufficiently
# slow or your trial happened to happen on second boundary.
-for trial in 0 1 2 3 4 5 6 7 8 9
+for trial in 0 1 2 3 4
do
rm -f .git/index
echo frotz >infocom
- echo xyzzy >activision
- git update-index --add infocom activision
+ git update-index --add infocom
echo xyzzy >infocom
files=`git diff-files -p`
test_expect_success \
- "Racy GIT trial #$trial" \
+ "Racy GIT trial #$trial part A" \
'test "" != "$files"'
+
+ sleep 1
+ echo xyzzy >cornerstone
+ git update-index --add cornerstone
+
+ files=`git diff-files -p`
+ test_expect_success \
+ "Racy GIT trial #$trial part B" \
+ 'test "" != "$files"'
+
done
test_done