mq: restore _branchtags() fast path (issue3223)
Since a5917346c72e, mq saves the nodeid of the first applied patch to
cache/branchheads, which breaks the optimized cache handling introduced in
fbf8320f25c8. The problem is the revision being committed is appended to
mqrepo.applied after the commit succeeds, which means mqrepo._branchtags()
performs a regular update and write the first applied patch to the branch
cache.
One solution is to set a context variable _committingpatch on the mqrepo while
it is committing a patch and to take it in account when deciding to fast-path
mqrepo._branchtags(). Not really elegant but it works.
The changes to test-mq-caches.t reverse changes introduced by a5917346c72e. The
cache should not have been updated with mq records.
The changes to test-keyword.t are indirectly caused by a5917346c72e.
Reported and analyzed by Yuya Nishihara <yuya@tcha.org>
Notes:
- qpush still makes a slow path _branchtags() call when checking heads. Maybe
this can be optimized.
- be careful when merging this patch in default as secretcommit() was renamed
newcommit() right after the end of the code freeze.
--- a/hgext/mq.py Tue Feb 07 18:47:13 2012 +0100
+++ b/hgext/mq.py Tue Feb 07 18:47:16 2012 +0100
@@ -267,11 +267,15 @@
phase = phases.secret
if phase is not None:
backup = repo.ui.backupconfig('phases', 'new-commit')
+ # Marking the repository as committing an mq patch can be used
+ # to optimize operations like _branchtags().
+ repo._committingpatch = True
try:
if phase is not None:
repo.ui.setconfig('phases', 'new-commit', phase)
return repo.commit(*args, **kwargs)
finally:
+ repo._committingpatch = False
if phase is not None:
repo.ui.restoreconfig(backup)
@@ -3254,16 +3258,20 @@
def _branchtags(self, partial, lrev):
q = self.mq
+ cl = self.changelog
+ qbase = None
if not q.applied:
- return super(mqrepo, self)._branchtags(partial, lrev)
-
- cl = self.changelog
- qbasenode = q.applied[0].node
- try:
- qbase = cl.rev(qbasenode)
- except error.LookupError:
- self.ui.warn(_('mq status file refers to unknown node %s\n')
- % short(qbasenode))
+ if getattr(self, '_committingpatch', False):
+ # Committing a new patch, must be tip
+ qbase = len(cl) - 1
+ else:
+ qbasenode = q.applied[0].node
+ try:
+ qbase = cl.rev(qbasenode)
+ except error.LookupError:
+ self.ui.warn(_('mq status file refers to unknown node %s\n')
+ % short(qbasenode))
+ if qbase is None:
return super(mqrepo, self)._branchtags(partial, lrev)
start = lrev + 1
--- a/tests/test-keyword.t Tue Feb 07 18:47:13 2012 +0100
+++ b/tests/test-keyword.t Tue Feb 07 18:47:16 2012 +0100
@@ -556,7 +556,6 @@
Commit and show expansion in original and copy
$ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
- invalidating branch cache (tip differs)
c
c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
overwriting c expanding keywords
--- a/tests/test-mq-caches.t Tue Feb 07 18:47:13 2012 +0100
+++ b/tests/test-mq-caches.t Tue Feb 07 18:47:16 2012 +0100
@@ -29,16 +29,14 @@
$ hg qnew -d '0 0' p1
$ show_branch_cache
tip: 0
- d986d5caac23a7d44a46efc0ddaf5eb9665844cf 0
- d986d5caac23a7d44a46efc0ddaf5eb9665844cf default
+ No branch cache
$ echo > pfile
$ hg add pfile
$ hg qrefresh -m 'patch 1'
$ show_branch_cache
tip: 0
- a7977e38ed2c2942fa6c278030badfef3d180979 0
- a7977e38ed2c2942fa6c278030badfef3d180979 default
+ No branch cache
some regular revisions
@@ -67,8 +65,8 @@
now at: p1
$ show_branch_cache
tip: 2
- 982611f6955f9c48d3365decea203217c945ef0d 2
- 982611f6955f9c48d3365decea203217c945ef0d bar
+ c229711f16da3d7591f89b1b8d963b79bda22714 1
+ c229711f16da3d7591f89b1b8d963b79bda22714 bar
dc25e3827021582e979f600811852e36cbe57341 foo
$ hg qnew -d '0 0' p2
@@ -77,8 +75,8 @@
$ hg qrefresh -m 'patch 2'
$ show_branch_cache 1
tip: 3
- 982611f6955f9c48d3365decea203217c945ef0d 2
- 982611f6955f9c48d3365decea203217c945ef0d bar
+ c229711f16da3d7591f89b1b8d963b79bda22714 1
+ c229711f16da3d7591f89b1b8d963b79bda22714 bar
dc25e3827021582e979f600811852e36cbe57341 foo
branch foo: 3
branch bar: 2
@@ -121,6 +119,6 @@
now at: p2
$ show_branch_cache
tip: 3
- 3fe2e3b237359b5c55cec6ed172ac41d3850fade 1
- 3fe2e3b237359b5c55cec6ed172ac41d3850fade foo
+ dc25e3827021582e979f600811852e36cbe57341 0
+ dc25e3827021582e979f600811852e36cbe57341 foo