Rev 4046: (robertc) Create a clean method for cloning a branch and optimise the in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Feb 25 05:15:43 GMT 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4046
revision-id: pqm at pqm.ubuntu.com-20090225051539-61fkvmey7t598fzs
parent: pqm at pqm.ubuntu.com-20090225025839-qzk3lo9bipdwf7cj
parent: robertc at robertcollins.net-20090225042842-jwojup508avng2hc
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2009-02-25 05:15:39 +0000
message:
(robertc) Create a clean method for cloning a branch and optimise the
specific case of clone-to-RemoteBranch to avoid round trips
reopening a branch we just created. (Robert Collins)
added:
bzrlib/tests/branch_implementations/test_create_clone.py test_create_clone.py-20090225031440-8ybpkzojo7cvourv-1
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/push.py push.py-20080606021927-5fe39050e8xne9un-1
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
bzrlib/tests/branch_implementations/__init__.py __init__.py-20060123013057-b12a52c3f361daf4
------------------------------------------------------------
revno: 4044.1.3
revision-id: robertc at robertcollins.net-20090225042842-jwojup508avng2hc
parent: robertc at robertcollins.net-20090225042748-l0n1e8v5osu8dgd8
committer: Robert Collins <robertc at robertcollins.net>
branch nick: push.roundtrips
timestamp: Wed 2009-02-25 15:28:42 +1100
message:
Create a one-shot cache of the result of RemoteBzrDir.create_branch, eliminating 3 round trips for nonstacked branches and 5 for stacked.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
------------------------------------------------------------
revno: 4044.1.2
revision-id: robertc at robertcollins.net-20090225042748-l0n1e8v5osu8dgd8
parent: robertc at robertcollins.net-20090225032212-odesl979bcnjrk3f
committer: Robert Collins <robertc at robertcollins.net>
branch nick: push.roundtrips
timestamp: Wed 2009-02-25 15:27:48 +1100
message:
Reinstate the TODO comment about bzrdir.clone_on_transport.
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
------------------------------------------------------------
revno: 4044.1.1
revision-id: robertc at robertcollins.net-20090225032212-odesl979bcnjrk3f
parent: pqm at pqm.ubuntu.com-20090225011157-xn0w5zux5mrges6j
committer: Robert Collins <robertc at robertcollins.net>
branch nick: push.roundtrips
timestamp: Wed 2009-02-25 14:22:12 +1100
message:
Create Branch.create_clone_on_transport helper method to combine bzr and branch creation for push.
added:
bzrlib/tests/branch_implementations/test_create_clone.py test_create_clone.py-20090225031440-8ybpkzojo7cvourv-1
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/push.py push.py-20080606021927-5fe39050e8xne9un-1
bzrlib/tests/branch_implementations/__init__.py __init__.py-20060123013057-b12a52c3f361daf4
=== modified file 'NEWS'
--- a/NEWS 2009-02-24 10:31:49 +0000
+++ b/NEWS 2009-02-25 03:22:12 +0000
@@ -99,6 +99,9 @@
* ``bzrlib.tests.run_suite`` accepts a runner_class parameter
supporting the use of different runners. (Robert Collins)
+ * New branch method ``create_clone_on_transport`` that returns a
+ branch object. (Robert Collins)
+
* New hook Commands['extend_command'] to allow plugins to access a
command object before the command is run (or help generated from
it), without overriding the command. (Robert Collins)
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2009-02-24 08:47:58 +0000
+++ b/bzrlib/branch.py 2009-02-25 04:27:48 +0000
@@ -916,6 +916,9 @@
def clone(self, to_bzrdir, revision_id=None):
"""Clone this branch into to_bzrdir preserving all semantic values.
+ Most API users will want 'create_clone_on_transport', which creates a
+ new bzrdir and branch on the fly.
+
revision_id: if not None, the revision history in the new branch will
be truncated to end with revision_id.
"""
@@ -1036,6 +1039,21 @@
format.set_branch_format(self._format)
return format
+ def create_clone_on_transport(self, to_transport, revision_id=None,
+ stacked_on=None):
+ """Create a clone of this branch and its bzrdir.
+
+ :param to_transport: The transport to clone onto.
+ :param revision_id: The revision id to use as tip in the new branch.
+ If None the tip is obtained from this branch.
+ :param stacked_on: An optional URL to stack the clone on.
+ """
+ # XXX: Fix the bzrdir API to allow getting the branch back from the
+ # clone call. Or something. 20090224 RBC/spiv.
+ dir_to = self.bzrdir.clone_on_transport(to_transport,
+ revision_id=revision_id, stacked_on=stacked_on)
+ return dir_to.open_branch()
+
def create_checkout(self, to_location, revision_id=None,
lightweight=False, accelerator_tree=None,
hardlink=False):
=== modified file 'bzrlib/push.py'
--- a/bzrlib/push.py 2009-02-24 08:09:17 +0000
+++ b/bzrlib/push.py 2009-02-25 03:22:12 +0000
@@ -101,11 +101,8 @@
# Now the target directory exists, but doesn't have a .bzr
# directory. So we need to create it, along with any work to create
# all of the dependent branches, etc.
- dir_to = br_from.bzrdir.clone_on_transport(to_transport,
+ br_to = br_from.create_clone_on_transport(to_transport,
revision_id=revision_id, stacked_on=stacked_on)
- # XXX: Fix this API to allow getting the branch back from the clone
- # call. Or something. 20090224 RBC/spiv.
- br_to = dir_to.open_branch()
# TODO: Some more useful message about what was copied
try:
finally_stacked_on = br_to.get_stacked_on_url()
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2009-02-25 00:31:09 +0000
+++ b/bzrlib/remote.py 2009-02-25 04:28:42 +0000
@@ -96,6 +96,9 @@
# this object holds a delegated bzrdir that uses file-level operations
# to talk to the other side
self._real_bzrdir = None
+ # 1-shot cache for the call pattern 'create_branch; open_branch' - see
+ # create_branch for details.
+ self._next_open_branch_result = None
if _client is None:
medium = transport.get_smart_medium()
@@ -123,6 +126,12 @@
def _translate_error(self, err, **context):
_translate_error(err, bzrdir=self, **context)
+ def break_lock(self):
+ # Prevent aliasing problems in the next_open_branch_result cache.
+ # See create_branch for rationale.
+ self._next_open_branch_result = None
+ return BzrDir.break_lock(self)
+
def cloning_metadir(self, stacked=False):
self._ensure_real()
return self._real_bzrdir.cloning_metadir(stacked)
@@ -146,14 +155,23 @@
# be parameterised.
real_branch = self._format.get_branch_format().initialize(self)
if not isinstance(real_branch, RemoteBranch):
- return RemoteBranch(self, self.find_repository(), real_branch)
+ result = RemoteBranch(self, self.find_repository(), real_branch)
else:
- return real_branch
+ result = real_branch
+ # BzrDir.clone_on_transport() uses the result of create_branch but does
+ # not return it to its callers; we save approximately 8% of our round
+ # trips by handing the branch we created back to the first caller to
+ # open_branch rather than probing anew. Long term we need a API in
+ # bzrdir that doesn't discard result objects (like result_branch).
+ # RBC 20090225
+ self._next_open_branch_result = result
+ return result
def destroy_branch(self):
"""See BzrDir.destroy_branch"""
self._ensure_real()
self._real_bzrdir.destroy_branch()
+ self._next_open_branch_result = None
def create_workingtree(self, revision_id=None, from_branch=None):
raise errors.NotLocalUrl(self.transport.base)
@@ -187,6 +205,11 @@
def open_branch(self, _unsupported=False):
if _unsupported:
raise NotImplementedError('unsupported flag support not implemented yet.')
+ if self._next_open_branch_result is not None:
+ # See create_branch for details.
+ result = self._next_open_branch_result
+ self._next_open_branch_result = None
+ return result
reference_url = self.get_branch_reference()
if reference_url is None:
# branch at this location.
=== modified file 'bzrlib/tests/blackbox/test_push.py'
--- a/bzrlib/tests/blackbox/test_push.py 2009-02-24 21:22:43 +0000
+++ b/bzrlib/tests/blackbox/test_push.py 2009-02-25 04:28:42 +0000
@@ -202,7 +202,7 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertEqual(32, rpc_count)
+ self.assertEqual(29, rpc_count)
def test_push_smart_stacked_streaming_acceptance(self):
self.setup_smart_server_with_call_log()
@@ -219,7 +219,7 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertEqual(61, rpc_count)
+ self.assertEqual(56, rpc_count)
remote = Branch.open('public')
self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
=== modified file 'bzrlib/tests/branch_implementations/__init__.py'
--- a/bzrlib/tests/branch_implementations/__init__.py 2009-02-23 15:29:35 +0000
+++ b/bzrlib/tests/branch_implementations/__init__.py 2009-02-25 03:22:12 +0000
@@ -156,6 +156,7 @@
'bzrlib.tests.branch_implementations.test_break_lock',
'bzrlib.tests.branch_implementations.test_check',
'bzrlib.tests.branch_implementations.test_create_checkout',
+ 'bzrlib.tests.branch_implementations.test_create_clone',
'bzrlib.tests.branch_implementations.test_commit',
'bzrlib.tests.branch_implementations.test_dotted_revno_to_revision_id',
'bzrlib.tests.branch_implementations.test_get_revision_id_to_revno_map',
=== added file 'bzrlib/tests/branch_implementations/test_create_clone.py'
--- a/bzrlib/tests/branch_implementations/test_create_clone.py 1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/branch_implementations/test_create_clone.py 2009-02-25 03:22:12 +0000
@@ -0,0 +1,56 @@
+# Copyright (C) 2009 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Tests for branch.create_clone behaviour."""
+
+from bzrlib.tests.branch_implementations.test_branch import TestCaseWithBranch
+
+
+class TestCreateClone(TestCaseWithBranch):
+
+ def test_create_clone_on_transport_no_revision_id(self):
+ tree = self.make_branch_and_tree('source')
+ tree.commit('a commit')
+ source = tree.branch
+ target_transport = self.get_transport('target')
+ result = tree.branch.create_clone_on_transport(target_transport)
+ self.assertEqual(source.last_revision(), result.last_revision())
+
+ def test_create_clone_on_transport_revision_id(self):
+ tree = self.make_branch_and_tree('source')
+ old_revid = tree.commit('a commit')
+ source_tip = tree.commit('a second commit')
+ source = tree.branch
+ target_transport = self.get_transport('target')
+ result = tree.branch.create_clone_on_transport(target_transport,
+ revision_id=old_revid)
+ self.assertEqual(old_revid, result.last_revision())
+ result.lock_read()
+ self.addCleanup(result.unlock)
+ self.assertFalse(result.repository.has_revision(source_tip))
+
+ def test_create_clone_on_transport_stacked(self):
+ tree = self.make_branch_and_tree('source')
+ tree.commit('a commit')
+ trunk = tree.branch.create_clone_on_transport(
+ self.get_transport('trunk'))
+ revid = tree.commit('a second commit')
+ source = tree.branch
+ target_transport = self.get_transport('target')
+ result = tree.branch.create_clone_on_transport(target_transport,
+ stacked_on=trunk.base)
+ self.assertEqual(revid, result.last_revision())
+ self.assertEqual(trunk.base, result.get_stacked_on_url())
More information about the bazaar-commits
mailing list