diff --git a/mercurial/changelog.py b/mercurial/changelog.py --- a/mercurial/changelog.py +++ b/mercurial/changelog.py @@ -357,8 +357,10 @@ class changelog(revlog.revlog): if new_index is not None: self._indexfile = new_index tr.registertmp(new_index) - tr.addpending(b'cl-%i' % id(self), self._writepending) - tr.addfinalize(b'cl-%i' % id(self), self._finalize) + # use "000" as prefix to make sure we run before the spliting of legacy + # inline changelog.. + tr.addpending(b'000-cl-%i' % id(self), self._writepending) + tr.addfinalize(b'000-cl-%i' % id(self), self._finalize) def _finalize(self, tr): """finalize index updates""" diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -2895,10 +2895,13 @@ class revlog: maybe_self._inner.index_file = old_index_file_path tr.registertmp(new_index_file_path) + # we use 001 here to make this this happens after the finalisation of + # pending changelog write (using 000). Otherwise the two finalizer + # would step over each other and delete the changelog.i file. if self.target[1] is not None: - callback_id = b'000-revlog-split-%d-%s' % self.target + callback_id = b'001-revlog-split-%d-%s' % self.target else: - callback_id = b'000-revlog-split-%d' % self.target[0] + callback_id = b'001-revlog-split-%d' % self.target[0] tr.addfinalize(callback_id, finalize_callback) tr.addabort(callback_id, abort_callback) diff --git a/tests/bundles/inlined-changelog.tar b/tests/bundles/inlined-changelog.tar new file mode 100644 index 0000000000000000000000000000000000000000..7edf8ae70e0b46ef77cfe33662c5d84f12b070ae GIT binary patch literal 20480 zc%1EKzSjtm0Z-og>)#BRSE{6CBT@fo`TS1_(xv{hz~VNG-6*%- zen{4b&ic2UK*%Dk&Yq}$(yo84KK~=AN&QPC*P1T#zspJoO@Asc3I?~4pnpxrSMopI zXy{)o0Hpr207I;+kg5m+h$nDiLW6mVbkM9WcnGc%Fs4%?Lbz)WnB;+DPv<&*w?@ZK#4vPx@4@F? z$K2V)AF^KlbZ9%;qwS2mq4n4Ag|7xhgZZkeLF{$$sz1e~=GEHT5o>udl=tg#f#_*? ztok6}7I!12GS}_mWZxb0nmE~PWibb?uAPlMrhWH}B7vz@LG9Jh!pnkjeRn}yw)GS_H;?&W9&sR@h`t0uGw|{r>hplHu$14}w zZ;#oAn=*%rUiycy$~?#BVKmqnkf?v6x9MN6>z``!{5Kn}=>LB48gCXi_5beKPd}M` zw)F9q+Kh7e(oy#3zWaV_zddG(X%vdKWfiGa!nS5w7#B;(vI?AAHnd9=a%|E9*W^HP z9nxF>={yCJq<>7wa{U`r&i~mk($aq{UWc2-P5mEv@s=;XF?S!Jo1XhceRKBMp3NWb zXuo~x_&sMI9z6}VDPJypeq`(HGf!^O(Hl42`Qy0@7dPGf>T4tJ&%e$bI`-(;iC5m9 zd;H{2x1PW2#>c+;`mb~I)||fok&ot{KDgtKz3%)Idq?O0`1{+rljxuM1Mh8r;neT9 zEo}bY`C#Ac`(J)%+e^w*@6U|yS~#(=efL}Uj%C?CLryRK+g^#4Duegh8#R;>Rq zl={ztW{xK(=Z#4({l}i=r(q*e{{*kt|B=ssWJ7C@2j;Fy_v)AJt3N0Qh@qsH{%aK$ z^1%0_a4;Lm`qx^|e^ZJY`9H=||5<=Q0UI_#rfq2yYbIeDg_v+ou~kH-F7kE`sYy^t z4gkYQFZ~DnQ0xSJK=rTY_a7_v|1~Jr|CwO<5%)^I#dAy9UarhN9x%6YT%NmpvObA& zVT}c1GH6`p8r?&V2g5*T{imh;%OvOj+Vb^3(x}vb7K9ZRa5ZGM)U!k)kw_#Gi9{li MNF)-8L^5>z2TTUB=>Px# diff --git a/tests/test-bookmarks.t b/tests/test-bookmarks.t --- a/tests/test-bookmarks.t +++ b/tests/test-bookmarks.t @@ -1082,9 +1082,9 @@ ensure changelog is written before bookm > time.sleep(0.5) > if os.path.exists(b"$TESTTMP/unpause"): > os.remove(b"$TESTTMP/unpause") - > # It is important that this finalizer start with 'a', so it runs before - > # the changelog finalizer appends to the changelog. - > tr.addfinalize(b'a-sleep', sleep) + > # It is important that this finalizer start with '000-a', so it runs + > # before the changelog finalizer appends to the changelog. + > tr.addfinalize(b'000-a-sleep', sleep) > return tr > > def extsetup(ui): diff --git a/tests/test-split-legacy-inline-changelog.t b/tests/test-split-legacy-inline-changelog.t new file mode 100644 --- /dev/null +++ b/tests/test-split-legacy-inline-changelog.t @@ -0,0 +1,307 @@ +====================================================== +Test operation on repository with an inlined changelog +====================================================== + +Inlined revlog has been a bag of complexity for a long time and the combination +with special transaction logic on the changelog was a long source of bugs +poorly covered by the test suites. + +We stopped doing any usage of inlined-revlog for changelog in a93e52f0b6ff, +upgrading legacy inlined version as soon as possible when we see them. However +this Mercurial does not produce such inlined-changelog that case is very poorly +covered in the test suites. This test file aims at covering these cases. + +Double checking test data +========================= + +We should have a repository around + + $ mkdir sanity-check + $ cd sanity-check + $ tar xf $TESTDIR/bundles/inlined-changelog.tar + $ cd inlined-changelog + $ hg root + $TESTTMP/sanity-check/inlined-changelog + +The repository should not be corrupted initially + + $ hg verify + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + checking dirstate + checked 1 changesets with 1 changes to 1 files + +The changelog of that repository MUST be inlined + + $ hg debugrevlog -c | grep -E '^flags\b' + flags : inline + +Touching that repository MUST split that inlined changelog + + $ hg branch foo --quiet + $ hg commit -m foo --quiet + $ hg debugrevlog -c | grep -E '^flags\b' + flags : (none) + + $ cd ../.. + +Test doing a simple commit +========================== + +Simple commit +------------- + + $ mkdir simple-commit + $ cd simple-commit + $ tar xf $TESTDIR/bundles/inlined-changelog.tar + $ cd inlined-changelog + $ hg up --quiet + $ hg log -GT '[{rev}] {desc}\n' + @ [0] first commit + + $ echo b > b + $ hg add b + $ hg commit -m "second changeset" + $ hg verify + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + checking dirstate + checked 2 changesets with 2 changes to 2 files + $ hg log -GT '[{rev}] {desc}\n' + @ [1] second changeset + | + o [0] first commit + + $ cd ../.. + +Simple commit with a pretxn hook configured +------------------------------------------- + +Before 6.7.3 this used to delete the changelog index + + $ mkdir pretxnclose-commit + $ cd pretxnclose-commit + $ tar xf $TESTDIR/bundles/inlined-changelog.tar + $ cat >> inlined-changelog/.hg/hgrc < [hooks] + > pretxnclose=hg log -r tip -T "pre-txn tip rev: {rev}\n" + > EOF + $ cd inlined-changelog + $ hg up --quiet + $ hg log -GT '[{rev}] {desc}\n' + @ [0] first commit + + $ echo b > b + $ hg add b + $ hg commit -m "second changeset" + pre-txn tip rev: 1 (missing-correct-output !) + warning: ignoring unknown working parent 11b63e930bf2! (known-bad-output !) + pre-txn tip rev: 0 (known-bad-output !) + $ hg verify + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + checking dirstate + checked 2 changesets with 2 changes to 2 files + $ hg log -GT '[{rev}] {desc}\n' + @ [1] second changeset + | + o [0] first commit + + $ cd ../.. + +Test pushing to a repository with a repository revlog +===================================================== + +Simple local push +----------------- + + $ mkdir simple-local-push + $ cd simple-local-push + $ tar xf $TESTDIR/bundles/inlined-changelog.tar + $ hg log -R inlined-changelog -T '[{rev}] {desc}\n' + [0] first commit + + $ hg clone --pull inlined-changelog client + requesting all changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets 827f11bfd362 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd client + $ echo b > b + $ hg add b + $ hg commit -m "second changeset" + $ hg push + pushing to $TESTTMP/*/inlined-changelog (glob) + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ cd .. + + $ hg verify -R inlined-changelog + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + checking dirstate + checked 2 changesets with 2 changes to 2 files + $ hg log -R inlined-changelog -T '[{rev}] {desc}\n' + [1] second changeset + [0] first commit + $ cd .. + +Simple local push with a pretxnchangegroup hook +----------------------------------------------- + +Before 6.7.3 this used to delete the server changelog + + $ mkdir pretxnchangegroup-local-push + $ cd pretxnchangegroup-local-push + $ tar xf $TESTDIR/bundles/inlined-changelog.tar + $ cat >> inlined-changelog/.hg/hgrc < [hooks] + > pretxnchangegroup=hg log -r tip -T "pre-txn tip rev: {rev}\n" + > EOF + $ hg log -R inlined-changelog -T '[{rev}] {desc}\n' + [0] first commit + + $ hg clone --pull inlined-changelog client + requesting all changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets 827f11bfd362 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd client + $ echo b > b + $ hg add b + $ hg commit -m "second changeset" + $ hg push + pushing to $TESTTMP/*/inlined-changelog (glob) + searching for changes + adding changesets + adding manifests + adding file changes + pre-txn tip rev: 1 (missing-correct-output !) + pre-txn tip rev: 0 (known-bad-output !) + added 1 changesets with 1 changes to 1 files + $ cd .. + + $ hg verify -R inlined-changelog + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + checking dirstate + checked 2 changesets with 2 changes to 2 files + $ hg log -R inlined-changelog -T '[{rev}] {desc}\n' + [1] second changeset + [0] first commit + $ cd .. + +Simple ssh push +----------------- + + $ mkdir simple-ssh-push + $ cd simple-ssh-push + $ tar xf $TESTDIR/bundles/inlined-changelog.tar + $ hg log -R inlined-changelog -T '[{rev}] {desc}\n' + [0] first commit + + $ hg clone ssh://user@dummy/"`pwd`"/inlined-changelog client + requesting all changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets 827f11bfd362 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd client + $ echo b > b + $ hg add b + $ hg commit -m "second changeset" + $ hg push + pushing to ssh://user@dummy/$TESTTMP/simple-ssh-push/inlined-changelog + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + $ cd .. + + $ hg verify -R inlined-changelog + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + checking dirstate + checked 2 changesets with 2 changes to 2 files + $ hg log -R inlined-changelog -T '[{rev}] {desc}\n' + [1] second changeset + [0] first commit + $ cd .. + +Simple ssh push with a pretxnchangegroup hook +----------------------------------------------- + +Before 6.7.3 this used to delete the server changelog + + $ mkdir pretxnchangegroup-ssh-push + $ cd pretxnchangegroup-ssh-push + $ tar xf $TESTDIR/bundles/inlined-changelog.tar + $ cat >> inlined-changelog/.hg/hgrc < [hooks] + > pretxnchangegroup=hg log -r tip -T "pre-txn tip rev: {rev}\n" + > EOF + $ hg log -R inlined-changelog -T '[{rev}] {desc}\n' + [0] first commit + + $ hg clone ssh://user@dummy/"`pwd`"/inlined-changelog client + requesting all changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets 827f11bfd362 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd client + $ echo b > b + $ hg add b + $ hg commit -m "second changeset" + $ hg push + pushing to ssh://user@dummy/$TESTTMP/pretxnchangegroup-ssh-push/inlined-changelog + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: pre-txn tip rev: 1 (missing-correct-output !) + remote: pre-txn tip rev: 0 (known-bad-output !) + remote: added 1 changesets with 1 changes to 1 files + $ cd .. + + $ hg verify -R inlined-changelog + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + checking dirstate + checked 2 changesets with 2 changes to 2 files + $ hg log -R inlined-changelog -T '[{rev}] {desc}\n' + [1] second changeset + [0] first commit + $ cd ..