Rev 4074: Alter branch sprouting with an alternate fix for stacked branches that does not require multiple copy_content_into and set_parent calls, reducing IO and round trips. in http://people.ubuntu.com/~robertc/baz2.0/branch.roundtrips
Robert Collins
robertc at robertcollins.net
Tue Mar 3 05:50:58 GMT 2009
At http://people.ubuntu.com/~robertc/baz2.0/branch.roundtrips
------------------------------------------------------------
revno: 4074
revision-id: robertc at robertcollins.net-20090303055055-0g2rfypt83bapygo
parent: robertc at robertcollins.net-20090303032751-ubyfhezgjul6y5ic
committer: Robert Collins <robertc at robertcollins.net>
branch nick: branch.roundtrips
timestamp: Tue 2009-03-03 16:50:55 +1100
message:
Alter branch sprouting with an alternate fix for stacked branches that does not require multiple copy_content_into and set_parent calls, reducing IO and round trips.
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2009-03-03 01:06:25 +0000
+++ b/bzrlib/branch.py 2009-03-03 05:50:55 +0000
@@ -892,7 +892,7 @@
return result
@needs_read_lock
- def sprout(self, to_bzrdir, revision_id=None):
+ def sprout(self, to_bzrdir, revision_id=None, repository_policy=None):
"""Create a new line of development from the branch, into to_bzrdir.
to_bzrdir controls the branch format.
@@ -901,6 +901,8 @@
be truncated to end with revision_id.
"""
result = to_bzrdir.create_branch()
+ if repository_policy is not None:
+ repository_policy.configure_branch(result)
self.copy_content_into(result, revision_id=revision_id)
result.set_parent(self.bzrdir.root_transport.base)
return result
=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py 2009-03-03 03:27:51 +0000
+++ b/bzrlib/bzrdir.py 2009-03-03 05:50:55 +0000
@@ -1126,17 +1126,9 @@
# Not especially, but it's part of the contract.
result_branch = result.create_branch()
else:
- # Force NULL revision to avoid using repository before stacking
- # is configured.
- result_branch = source_branch.sprout(
- result, revision_id=_mod_revision.NULL_REVISION)
- parent_location = result_branch.get_parent()
+ result_branch = source_branch.sprout(result,
+ revision_id=revision_id, repository_policy=repository_policy)
mutter("created new branch %r" % (result_branch,))
- repository_policy.configure_branch(result_branch)
- if source_branch is not None:
- source_branch.copy_content_into(result_branch, revision_id)
- # Override copy_content_into
- result_branch.set_parent(parent_location)
# Create/update the result working tree
if (create_tree_if_local and
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2009-03-01 11:11:14 +0000
+++ b/bzrlib/tests/__init__.py 2009-03-03 05:50:55 +0000
@@ -1820,6 +1820,29 @@
return sio
+class CapturedCall(object):
+ """A helper for capturing smart server calls for easy debug analysis."""
+
+ def __init__(self, params, prefix_length):
+ """Capture the call with params and skip prefix_length stack frames."""
+ self.call = params
+ import traceback
+ # The last 5 frames are the __init__, the hook frame, and 3 smart
+ # client frames. Beyond this we could get more clever, but this is good
+ # enough for now.
+ stack = traceback.extract_stack()[prefix_length:-5]
+ self.stack = ''.join(traceback.format_list(stack))
+
+ def __str__(self):
+ return self.call.method
+
+ def __repr__(self):
+ return self.call.method
+
+ def stack(self):
+ return self.stack
+
+
class TestCaseWithMemoryTransport(TestCase):
"""Common test class for tests that do not need disk resources.
@@ -2116,9 +2139,13 @@
"""Sets up a smart server as the transport server with a call log."""
self.transport_server = server.SmartTCPServer_for_testing
self.hpss_calls = []
+ import traceback
+ # Skip the current stack down to the caller of
+ # setup_smart_server_with_call_log
+ prefix_length = len(traceback.extract_stack()) - 2
def capture_hpss_call(params):
- import traceback
- self.hpss_calls.append((params, traceback.format_stack()))
+ self.hpss_calls.append(
+ CapturedCall(params, prefix_length))
client._SmartClient.hooks.install_named_hook(
'call', capture_hpss_call, None)
=== modified file 'bzrlib/tests/blackbox/test_branch.py'
--- a/bzrlib/tests/blackbox/test_branch.py 2009-03-03 03:27:51 +0000
+++ b/bzrlib/tests/blackbox/test_branch.py 2009-03-03 05:50:55 +0000
@@ -273,7 +273,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(95, rpc_count)
+ self.assertEqual(71, rpc_count)
def test_branch_from_trivial_branch_streaming_acceptance(self):
self.setup_smart_server_with_call_log()
@@ -289,7 +289,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(21, rpc_count)
+ self.assertEqual(17, rpc_count)
class TestRemoteBranch(TestCaseWithSFTPServer):
=== modified file 'bzrlib/tests/branch_implementations/test_sprout.py'
--- a/bzrlib/tests/branch_implementations/test_sprout.py 2009-02-24 05:37:17 +0000
+++ b/bzrlib/tests/branch_implementations/test_sprout.py 2009-03-03 05:50:55 +0000
@@ -19,6 +19,7 @@
import os
from bzrlib import (
branch as _mod_branch,
+ errors,
remote,
revision as _mod_revision,
tests,
@@ -151,3 +152,36 @@
raise KnownFailure('there is no support for'
' symlinks to non-ASCII targets (bug #272444)')
+ def assertBranchHookBranchIsStacked(self, pre_change_params):
+ # Just calling will either succeed or fail.
+ pre_change_params.branch.get_stacked_on_url()
+ self.hook_calls.append(pre_change_params)
+
+ def test_sprout_stacked_hooks_get_stacked_branch(self):
+ tree = self.make_branch_and_tree('source')
+ tree.commit('a commit')
+ revid = tree.commit('a second commit')
+ source = tree.branch
+ target_transport = self.get_transport('target')
+ self.hook_calls = []
+ _mod_branch.Branch.hooks.install_named_hook("pre_change_branch_tip",
+ self.assertBranchHookBranchIsStacked, None)
+ try:
+ dir = source.bzrdir.sprout(target_transport.base,
+ source.last_revision(), possible_transports=[target_transport],
+ source_branch=source, stacked=True)
+ except errors.UnstackableBranchFormat:
+ if isinstance(self.branch_format, _mod_branch.BzrBranchFormat4):
+ raise KnownFailure("Format 4 doesn't auto stack successfully.")
+ else:
+ raise
+ result = dir.open_branch()
+ self.assertEqual(revid, result.last_revision())
+ self.assertEqual(source.base, result.get_stacked_on_url())
+ # Smart servers invoke hooks on both sides
+ if isinstance(result, remote.RemoteBranch):
+ expected_calls = 2
+ else:
+ expected_calls = 1
+ self.assertEqual(expected_calls, len(self.hook_calls))
+
=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py 2009-03-03 03:27:51 +0000
+++ b/bzrlib/tests/test_remote.py 2009-03-03 05:50:55 +0000
@@ -359,7 +359,7 @@
self.disable_verb(verb)
format = a_dir.cloning_metadir()
call_count = len([call for call in self.hpss_calls if
- call[0].method == verb])
+ call.call.method == verb])
self.assertEqual(1, call_count)
def test_current_server(self):
@@ -516,7 +516,7 @@
self.disable_verb('BzrDir.create_branch')
branch = repo.bzrdir.create_branch()
create_branch_call_count = len([call for call in self.hpss_calls if
- call[0].method == 'BzrDir.create_branch'])
+ call.call.method == 'BzrDir.create_branch'])
self.assertEqual(1, create_branch_call_count)
def test_current_server(self):
@@ -552,7 +552,7 @@
self.disable_verb('BzrDir.create_repository')
repo = bzrdir.create_repository()
create_repo_call_count = len([call for call in self.hpss_calls if
- call[0].method == 'BzrDir.create_repository'])
+ call.call.method == 'BzrDir.create_repository'])
self.assertEqual(1, create_repo_call_count)
def test_current_server(self):
@@ -1632,7 +1632,7 @@
self.disable_verb(verb)
repo.set_make_working_trees(True)
call_count = len([call for call in self.hpss_calls if
- call[0].method == verb])
+ call.call.method == verb])
self.assertEqual(1, call_count)
def test_current(self):
More information about the bazaar-commits
mailing list