# HG changeset patch # User Augie Fackler # Date 1558366847 14400 # Node ID ffab9eed3921e0c3fdae3a45e345620e19fb1c0a # Parent de65ae32b82dec57aa34346bb7e86bbddc7140b0# Parent 2338bdea44744312e42632d68bc00491184c748b merge with stable diff -r de65ae32b82d -r ffab9eed3921 mercurial/localrepo.py --- a/mercurial/localrepo.py Mon May 20 08:40:54 2019 +0900 +++ b/mercurial/localrepo.py Mon May 20 11:40:47 2019 -0400 @@ -1226,7 +1226,7 @@ return cls(self, name, visibilityexceptions) @mixedrepostorecache(('bookmarks', ''), ('bookmarks.current', ''), - ('bookmarks', 'store')) + ('bookmarks', 'store'), ('00changelog.i', 'store')) def _bookmarks(self): return bookmarks.bmstore(self) diff -r de65ae32b82d -r ffab9eed3921 tests/test-bookmarks-corner-case.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-bookmarks-corner-case.t Mon May 20 11:40:47 2019 -0400 @@ -0,0 +1,238 @@ +================================ +Test corner case around bookmark +================================ + +This test file is meant to gather test around bookmark that are specific + enough to not find a place elsewhere. + +Test bookmark/changelog race condition +====================================== + +The data from the bookmark file are filtered to only contains bookmark with +node known to the changelog. If the cache invalidation between these two bits +goes wrong, bookmark can be dropped. + +global setup +------------ + + $ cat >> $HGRCPATH << EOF + > [ui] + > ssh = "$PYTHON" "$TESTDIR/dummyssh" + > [server] + > concurrent-push-mode=check-related + > EOF + +Setup +----- + +initial repository setup + + $ hg init bookrace-server + $ cd bookrace-server + $ echo a > a + $ hg add a + $ hg commit -m root + $ echo a >> a + $ hg bookmark book-A + $ hg commit -m A0 + $ hg up 'desc(root)' + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (leaving bookmark book-A) + $ echo b > b + $ hg add b + $ hg bookmark book-B + $ hg commit -m B0 + created new head + $ hg up null + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + (leaving bookmark book-B) + $ hg phase --public --rev 'all()' + $ hg log -G + o changeset: 2:c79985706978 + | bookmark: book-B + | tag: tip + | parent: 0:6569b5a81c7e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B0 + | + | o changeset: 1:39c28d785860 + |/ bookmark: book-A + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:6569b5a81c7e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: root + + $ hg book + book-A 1:39c28d785860 + book-B 2:c79985706978 + $ cd .. + +Add new changeset on each bookmark in distinct clones + + $ hg clone ssh://user@dummy/bookrace-server client-A + requesting all changes + adding changesets + adding manifests + adding file changes + added 3 changesets with 3 changes to 2 files (+1 heads) + new changesets 6569b5a81c7e:c79985706978 + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg -R client-A update book-A + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + (activating bookmark book-A) + $ echo a >> client-A/a + $ hg -R client-A commit -m A1 + $ hg clone ssh://user@dummy/bookrace-server client-B + requesting all changes + adding changesets + adding manifests + adding file changes + added 3 changesets with 3 changes to 2 files (+1 heads) + new changesets 6569b5a81c7e:c79985706978 + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg -R client-B update book-B + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + (activating bookmark book-B) + $ echo b >> client-B/b + $ hg -R client-B commit -m B1 + +extension to reproduce the race +------------------------------- + +If two process are pushing we want to make sure the following happens: + +* process A read changelog +* process B to its full push +* process A read bookmarks +* process A proceed with rest of the push + +We build a server side extension for this purpose + + $ cat > bookrace.py << EOF + > import os + > import time + > import atexit + > from mercurial import error, extensions, bookmarks + > def wrapinit(orig, self, repo): + > if not os.path.exists('push-A-started'): + > print('setting raced push up') + > with open('push-A-started', 'w'): + > pass + > clock = 300 + > while not os.path.exists('push-B-done'): + > clock -= 1 + > if clock <= 0: + > raise error.Abort("race scenario timed out") + > time.sleep(0.1) + > return orig(self, repo) + > + > repo.__class__ = racedrepo + > def uisetup(ui): + > extensions.wrapfunction(bookmarks.bmstore, '__init__', wrapinit) + > def e(): + > with open('push-A-done', 'w'): + > pass + > atexit.register(e) + > EOF + +Actual test +----------- + +Start the raced push. + + $ cat >> bookrace-server/.hg/hgrc << EOF + > [extensions] + > bookrace=$TESTTMP/bookrace.py + > EOF + $ hg push -R client-A -r book-A >push-output.txt 2>&1 & + +Wait up to 30 seconds for that push to start. + + $ clock=30 + $ while [ ! -f push-A-started ] && [ $clock -gt 0 ] ; do + > clock=`expr $clock - 1` + > sleep 1 + > done + +Do the other push. + + $ cat >> bookrace-server/.hg/hgrc << EOF + > [extensions] + > bookrace=! + > EOF + + $ hg push -R client-B -r book-B + pushing to ssh://user@dummy/bookrace-server + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + updating bookmark book-B + +Signal the raced put that we are done (it waits up to 30 seconds). + + $ touch push-B-done + +Wait for the raced push to finish (with the remaning of the initial 30 seconds). + + $ while [ ! -f push-A-done ] && [ $clock -gt 0 ] ; do + > clock=`expr $clock - 1` + > sleep 1 + > done + +Check raced push output. + + $ cat push-output.txt + pushing to ssh://user@dummy/bookrace-server + searching for changes + remote: setting raced push up + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + updating bookmark book-A + +Check result of the push. + + $ hg -R bookrace-server log -G + o changeset: 4:9ce3b28c16de + | bookmark: book-A + | tag: tip + | parent: 1:39c28d785860 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A1 + | + | o changeset: 3:f26c3b5167d1 + | | bookmark: book-B + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: B1 + | | + | o changeset: 2:c79985706978 + | | parent: 0:6569b5a81c7e + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: B0 + | | + o | changeset: 1:39c28d785860 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:6569b5a81c7e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: root + + $ hg -R bookrace-server book + book-A 4:9ce3b28c16de + book-B 3:f26c3b5167d1 diff -r de65ae32b82d -r ffab9eed3921 tests/test-repo-compengines.t --- a/tests/test-repo-compengines.t Mon May 20 08:40:54 2019 +0900 +++ b/tests/test-repo-compengines.t Mon May 20 11:40:47 2019 -0400 @@ -111,6 +111,7 @@ > done $ $RUNTESTDIR/f -s */.hg/store/data/* + default/.hg/store/data/foo.i: size=64 (pure !) zlib-level-1/.hg/store/data/a.i: size=4146 zlib-level-9/.hg/store/data/a.i: size=4138 zlib-level-default/.hg/store/data/a.i: size=4138 @@ -138,6 +139,8 @@ abort: invalid value for `storage.revlog.zlib.level` config: 42 [255] +#if zstd + checking zstd options ===================== @@ -193,3 +196,4 @@ abort: invalid value for `storage.revlog.zstd.level` config: 42 [255] +#endif