fncache: move fncache writing to be in a transaction
Previously the fncache was written at lock.release time. This meant it was not
tracked by a transaction, and if an error occurred during the fncache write it
would fail to update the fncache, but would not rollback the transaction,
resulting in an fncache that was not in sync with the files on disk (which
causes verify to fail, and causes streaming clones to not copy all the revlogs).
This uses the new transaction backup mechanism to make the fncache transacted.
It also moves the fncache from being written at lock.release time, to being
written at transaction.close time.
$ hg init
Revision 0:
$ echo "unchanged" > unchanged
$ echo "remove me" > remove
$ echo "copy me" > copy
$ echo "move me" > move
$ for i in 1 2 3 4 5 6 7 8 9; do
> echo "merge ok $i" >> zzz1_merge_ok
> done
$ echo "merge bad" > zzz2_merge_bad
$ hg ci -Am "revision 0"
adding copy
adding move
adding remove
adding unchanged
adding zzz1_merge_ok
adding zzz2_merge_bad
Revision 1:
$ hg rm remove
$ hg mv move moved
$ hg cp copy copied
$ echo "added" > added
$ hg add added
$ echo "new first line" > zzz1_merge_ok
$ hg cat zzz1_merge_ok >> zzz1_merge_ok
$ echo "new last line" >> zzz2_merge_bad
$ hg ci -m "revision 1"
Local changes to revision 0:
$ hg co 0
4 files updated, 0 files merged, 3 files removed, 0 files unresolved
$ echo "new last line" >> zzz1_merge_ok
$ echo "another last line" >> zzz2_merge_bad
$ hg diff --nodates | grep "^[+-][^<>]"
--- a/zzz1_merge_ok
+++ b/zzz1_merge_ok
+new last line
--- a/zzz2_merge_bad
+++ b/zzz2_merge_bad
+another last line
$ hg st
M zzz1_merge_ok
M zzz2_merge_bad
Local merge with bad merge tool:
$ HGMERGE=false hg co
merging zzz1_merge_ok
merging zzz2_merge_bad
merging zzz2_merge_bad failed!
3 files updated, 1 files merged, 2 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges
[1]
$ hg co 0
merging zzz1_merge_ok
merging zzz2_merge_bad
warning: conflicts during merge.
merging zzz2_merge_bad incomplete! (edit conflicts, then use 'hg resolve --mark')
2 files updated, 1 files merged, 3 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges
[1]
$ hg diff --nodates | grep "^[+-][^<>]"
--- a/zzz1_merge_ok
+++ b/zzz1_merge_ok
+new last line
--- a/zzz2_merge_bad
+++ b/zzz2_merge_bad
+another last line
+=======
$ hg st
M zzz1_merge_ok
M zzz2_merge_bad
? zzz2_merge_bad.orig
Local merge with conflicts:
$ hg co
merging zzz1_merge_ok
merging zzz2_merge_bad
warning: conflicts during merge.
merging zzz2_merge_bad incomplete! (edit conflicts, then use 'hg resolve --mark')
3 files updated, 1 files merged, 2 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges
[1]
$ hg co 0
merging zzz1_merge_ok
merging zzz2_merge_bad
warning: conflicts during merge.
merging zzz2_merge_bad incomplete! (edit conflicts, then use 'hg resolve --mark')
2 files updated, 1 files merged, 3 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges
[1]
$ hg diff --nodates | grep "^[+-][^<>]"
--- a/zzz1_merge_ok
+++ b/zzz1_merge_ok
+new last line
--- a/zzz2_merge_bad
+++ b/zzz2_merge_bad
+another last line
+=======
+=======
+new last line
+=======
$ hg st
M zzz1_merge_ok
M zzz2_merge_bad
? zzz2_merge_bad.orig
Local merge without conflicts:
$ hg revert zzz2_merge_bad
$ hg co
merging zzz1_merge_ok
4 files updated, 1 files merged, 2 files removed, 0 files unresolved
$ hg diff --nodates | grep "^[+-][^<>]"
--- a/zzz1_merge_ok
+++ b/zzz1_merge_ok
+new last line
$ hg st
M zzz1_merge_ok
? zzz2_merge_bad.orig