Rev 3355: Add Branch.set_last_revision_info smart request. (Andrew Bennetts) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Apr 10 11:53:58 BST 2008
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 3355
revision-id:pqm at pqm.ubuntu.com-20080410105350-e0c4d8n5hqgzqzi7
parent: pqm at pqm.ubuntu.com-20080410091416-1so11izeyk0tsbk9
parent: andrew.bennetts at canonical.com-20080408081821-vs80hwo6kt0fm8sr
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2008-04-10 11:53:50 +0100
message:
Add Branch.set_last_revision_info smart request. (Andrew Bennetts)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/branch.py branch.py-20061124031907-mzh3pla28r83r97f-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
------------------------------------------------------------
revno: 3297.3.5.1.4
revision-id:andrew.bennetts at canonical.com-20080408081821-vs80hwo6kt0fm8sr
parent: andrew.bennetts at canonical.com-20080408081333-lov0qqto26hyycoj
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: smart-set-revision-info
timestamp: Tue 2008-04-08 18:18:21 +1000
message:
Add NEWS entry.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
------------------------------------------------------------
revno: 3297.3.5.1.3
revision-id:andrew.bennetts at canonical.com-20080408081333-lov0qqto26hyycoj
parent: andrew.bennetts at canonical.com-20080408074439-n3j4ic7bcliq9s05
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: smart-set-revision-info
timestamp: Tue 2008-04-08 18:13:33 +1000
message:
Add more tests, handle NoSuchRevision in case the remote branch's format can raise it.
modified:
bzrlib/smart/branch.py branch.py-20061124031907-mzh3pla28r83r97f-1
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
------------------------------------------------------------
revno: 3297.3.5.1.2
revision-id:andrew.bennetts at canonical.com-20080408074439-n3j4ic7bcliq9s05
parent: andrew.bennetts at canonical.com-20080408063834-o4mid7woclibs6yj
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: smart-set-revision-info
timestamp: Tue 2008-04-08 17:44:39 +1000
message:
Add backwards compatibility for servers older than 1.4.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/branch.py branch.py-20061124031907-mzh3pla28r83r97f-1
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
------------------------------------------------------------
revno: 3297.3.5.1.1
revision-id:andrew.bennetts at canonical.com-20080408063834-o4mid7woclibs6yj
parent: andrew.bennetts at canonical.com-20080407104900-qbxxs53xvmwzzo7k
parent: andrew.bennetts at canonical.com-20080325072121-67qctpl7mxhr3onc
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: smart-set-revision-info
timestamp: Tue 2008-04-08 16:38:34 +1000
message:
Merge 'Add Branch.set_last_revision_info smart method'.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/branch.py branch.py-20061124031907-mzh3pla28r83r97f-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
------------------------------------------------------------
revno: 2892.2.1
revision-id:andrew.bennetts at canonical.com-20080325072121-67qctpl7mxhr3onc
parent: pqm at pqm.ubuntu.com-20071006144547-0e1mpht72yd6wyfz
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: smart-set-last-revision
timestamp: Tue 2008-03-25 18:21:21 +1100
message:
Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/branch.py branch.py-20061124031907-mzh3pla28r83r97f-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/branch_implementations/test_revision_history.py test_revision_histor-20070326062311-v7co92liyuchb80w-1
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
=== modified file 'NEWS'
--- a/NEWS 2008-04-10 06:03:33 +0000
+++ b/NEWS 2008-04-10 10:53:50 +0000
@@ -43,6 +43,11 @@
IMPROVEMENTS:
+ * The smart protocol now has support for setting branches' revision info
+ directly. This should make operations like push slightly faster, and is a
+ step towards server-side hooks. The new request method name is
+ ``Branch.set_last_revision_info``. (Andrew Bennetts)
+
* ``bzr commit --fixes`` now recognises "gnome" as a tag by default.
(James Westby, Andrew Cowie)
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2008-04-07 10:34:57 +0000
+++ b/bzrlib/remote.py 2008-04-08 07:44:39 +0000
@@ -42,7 +42,7 @@
deprecated_method,
zero_ninetyone,
)
-from bzrlib.revision import NULL_REVISION
+from bzrlib.revision import ensure_null, NULL_REVISION
from bzrlib.trace import mutter, note, warning
# Note: RemoteBzrDirFormat is in bzrdir.py
@@ -1228,6 +1228,7 @@
self._control_files = None
self._lock_mode = None
self._lock_token = None
+ self._repo_lock_token = None
self._lock_count = 0
self._leave_lock = False
@@ -1488,10 +1489,24 @@
def is_locked(self):
return self._lock_count >= 1
+ @needs_write_lock
def set_last_revision_info(self, revno, revision_id):
- self._ensure_real()
- self._clear_cached_state()
- return self._real_branch.set_last_revision_info(revno, revision_id)
+ assert type(revno) is int
+ revision_id = ensure_null(revision_id)
+ path = self.bzrdir._path_for_remote_call(self._client)
+ try:
+ response = self._client.call('Branch.set_last_revision_info',
+ path, self._lock_token, self._repo_lock_token, str(revno), revision_id)
+ except errors.UnknownSmartMethod:
+ self._ensure_real()
+ self._clear_cached_state()
+ return self._real_branch.set_last_revision_info(revno, revision_id)
+ if response == ('ok',):
+ self._clear_cached_state()
+ elif response[0] == 'NoSuchRevision':
+ raise NoSuchRevision(self, response[1])
+ else:
+ raise errors.UnexpectedSmartServerResponse(response)
def generate_revision_history(self, revision_id, last_rev=None,
other_branch=None):
=== modified file 'bzrlib/smart/branch.py'
--- a/bzrlib/smart/branch.py 2007-12-05 07:09:42 +0000
+++ b/bzrlib/smart/branch.py 2008-04-08 08:13:33 +0000
@@ -123,6 +123,23 @@
return SuccessfulSmartServerResponse(('ok',))
+class SmartServerBranchRequestSetLastRevisionInfo(
+ SmartServerLockedBranchRequest):
+ """Branch.set_last_revision_info. Sets the revno and the revision ID of
+ the specified branch.
+
+ New in bzrlib 1.4.
+ """
+
+ def do_with_locked_branch(self, branch, new_revno, new_last_revision_id):
+ try:
+ branch.set_last_revision_info(int(new_revno), new_last_revision_id)
+ except errors.NoSuchRevision:
+ return FailedSmartServerResponse(
+ ('NoSuchRevision', new_last_revision_id))
+ return SuccessfulSmartServerResponse(('ok',))
+
+
class SmartServerBranchRequestLockWrite(SmartServerBranchRequest):
def do_with_branch(self, branch, branch_token='', repo_token=''):
=== modified file 'bzrlib/smart/request.py'
--- a/bzrlib/smart/request.py 2008-03-27 06:10:18 +0000
+++ b/bzrlib/smart/request.py 2008-04-08 06:38:34 +0000
@@ -340,6 +340,9 @@
request_handlers.register_lazy(
'Branch.set_last_revision', 'bzrlib.smart.branch', 'SmartServerBranchRequestSetLastRevision')
request_handlers.register_lazy(
+ 'Branch.set_last_revision_info', 'bzrlib.smart.branch',
+ 'SmartServerBranchRequestSetLastRevisionInfo')
+request_handlers.register_lazy(
'Branch.unlock', 'bzrlib.smart.branch', 'SmartServerBranchRequestUnlock')
request_handlers.register_lazy(
'BzrDir.find_repository', 'bzrlib.smart.bzrdir', 'SmartServerRequestFindRepositoryV1')
=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py 2008-04-07 10:49:00 +0000
+++ b/bzrlib/tests/test_remote.py 2008-04-08 07:44:39 +0000
@@ -494,6 +494,114 @@
branch.unlock()
+class TestBranchSetLastRevisionInfo(tests.TestCase):
+
+ def test_set_last_revision_info(self):
+ # set_last_revision_info(num, 'rev-id') is translated to calling
+ # Branch.set_last_revision_info(num, 'rev-id') on the wire.
+ transport = MemoryTransport()
+ transport.mkdir('branch')
+ transport = transport.clone('branch')
+ client = FakeClient([
+ # lock_write
+ (('ok', 'branch token', 'repo token'), ),
+ # set_last_revision_info
+ (('ok',), ),
+ # unlock
+ (('ok',), )], transport.base)
+
+ bzrdir = RemoteBzrDir(transport, _client=False)
+ branch = RemoteBranch(bzrdir, None, _client=client)
+ # This is a hack to work around the problem that RemoteBranch currently
+ # unnecessarily invokes _ensure_real upon a call to lock_write.
+ branch._ensure_real = lambda: None
+ # Lock the branch, reset the record of remote calls.
+ branch.lock_write()
+ client._calls = []
+ result = branch.set_last_revision_info(1234, 'a-revision-id')
+ self.assertEqual(
+ [('call', 'Branch.set_last_revision_info',
+ ('branch/', 'branch token', 'repo token',
+ '1234', 'a-revision-id'))],
+ client._calls)
+ self.assertEqual(None, result)
+
+ def test_no_such_revision(self):
+ # A response of 'NoSuchRevision' is translated into an exception.
+ client = FakeClient([
+ # lock_write
+ (('ok', 'branch token', 'repo token'), ),
+ # set_last_revision_info
+ (('NoSuchRevision', 'revid'), ),
+ # unlock
+ (('ok',), ),
+ ])
+ transport = MemoryTransport()
+ transport.mkdir('branch')
+ transport = transport.clone('branch')
+
+ bzrdir = RemoteBzrDir(transport, _client=False)
+ branch = RemoteBranch(bzrdir, None, _client=client)
+ # This is a hack to work around the problem that RemoteBranch currently
+ # unnecessarily invokes _ensure_real upon a call to lock_write.
+ branch._ensure_real = lambda: None
+ # Lock the branch, reset the record of remote calls.
+ branch.lock_write()
+ client._calls = []
+
+ self.assertRaises(
+ errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
+ branch.unlock()
+
+ def lock_remote_branch(self, branch):
+ """Trick a RemoteBranch into thinking it is locked."""
+ branch._lock_mode = 'w'
+ branch._lock_count = 2
+ branch._lock_token = 'branch token'
+ branch._repo_lock_token = 'repo token'
+
+ def test_backwards_compatibility(self):
+ """If the server does not support the Branch.set_last_revision_info
+ verb (which is new in 1.4), then the client falls back to VFS methods.
+ """
+ # This test is a little messy. Unlike most tests in this file, it
+ # doesn't purely test what a Remote* object sends over the wire, and
+ # how it reacts to responses from the wire. It instead relies partly
+ # on asserting that the RemoteBranch will call
+ # self._real_branch.set_last_revision_info(...).
+
+ # First, set up our RemoteBranch with a FakeClient that raises
+ # UnknownSmartMethod, and a StubRealBranch that logs how it is called.
+ transport = MemoryTransport()
+ transport.mkdir('branch')
+ transport = transport.clone('branch')
+ client = FakeClient(
+ [(('unknown verb', 'Branch.set_last_revision_info',), ),],
+ transport.base)
+ bzrdir = RemoteBzrDir(transport, _client=False)
+ branch = RemoteBranch(bzrdir, None, _client=client)
+ class StubRealBranch(object):
+ def __init__(self):
+ self.calls = []
+ def set_last_revision_info(self, revno, revision_id):
+ self.calls.append(
+ ('set_last_revision_info', revno, revision_id))
+ real_branch = StubRealBranch()
+ branch._real_branch = real_branch
+ self.lock_remote_branch(branch)
+
+ # Call set_last_revision_info, and verify it behaved as expected.
+ result = branch.set_last_revision_info(1234, 'a-revision-id')
+ self.assertEqual(
+ [('call', 'Branch.set_last_revision_info',
+ ('branch/', 'branch token', 'repo token',
+ '1234', 'a-revision-id')),],
+ client._calls)
+ self.assertEqual(
+ [('set_last_revision_info', 1234, 'a-revision-id')],
+ real_branch.calls)
+
+
class TestBranchControlGetBranchConf(tests.TestCaseWithMemoryTransport):
"""Test branch.control_files api munging...
=== modified file 'bzrlib/tests/test_smart.py'
--- a/bzrlib/tests/test_smart.py 2008-03-27 06:10:18 +0000
+++ b/bzrlib/tests/test_smart.py 2008-04-08 08:13:33 +0000
@@ -476,6 +476,70 @@
tree.branch.unlock()
+class TestSmartServerBranchRequestSetLastRevisionInfo(tests.TestCaseWithTransport):
+
+ def lock_branch(self, branch):
+ branch_token = branch.lock_write()
+ repo_token = branch.repository.lock_write()
+ branch.repository.unlock()
+ self.addCleanup(branch.unlock)
+ return branch_token, repo_token
+
+ def make_locked_branch(self, format=None):
+ branch = self.make_branch('.', format=format)
+ branch_token, repo_token = self.lock_branch(branch)
+ return branch, branch_token, repo_token
+
+ def test_empty(self):
+ """An empty branch can have its last revision set to 'null:'."""
+ b, branch_token, repo_token = self.make_locked_branch()
+ backing = self.get_transport()
+ request = smart.branch.SmartServerBranchRequestSetLastRevisionInfo(
+ backing)
+ response = request.execute('', branch_token, repo_token, '0', 'null:')
+ self.assertEqual(SmartServerResponse(('ok',)), response)
+
+ def assertBranchLastRevisionInfo(self, expected_info, branch_relpath):
+ branch = bzrdir.BzrDir.open(branch_relpath).open_branch()
+ self.assertEqual(expected_info, branch.last_revision_info())
+
+ def test_branch_revision_info_is_updated(self):
+ """This method really does update the branch last revision info."""
+ tree = self.make_branch_and_memory_tree('.')
+ tree.lock_write()
+ tree.add('')
+ tree.commit('First commit', rev_id='revision-1')
+ tree.commit('Second commit', rev_id='revision-2')
+ tree.unlock()
+ branch = tree.branch
+
+ branch_token, repo_token = self.lock_branch(branch)
+ backing = self.get_transport()
+ request = smart.branch.SmartServerBranchRequestSetLastRevisionInfo(
+ backing)
+ self.assertBranchLastRevisionInfo((2, 'revision-2'), '.')
+ response = request.execute(
+ '', branch_token, repo_token, '1', 'revision-1')
+ self.assertEqual(SmartServerResponse(('ok',)), response)
+ self.assertBranchLastRevisionInfo((1, 'revision-1'), '.')
+
+ def test_not_present_revid(self):
+ """Some branch formats will check that the revision is present in the
+ repository. When that check fails, a NoSuchRevision error is returned
+ to the client.
+ """
+ # Make a knit format branch, because that format checks the values
+ # given to set_last_revision_info.
+ b, branch_token, repo_token = self.make_locked_branch(format='knit')
+ backing = self.get_transport()
+ request = smart.branch.SmartServerBranchRequestSetLastRevisionInfo(
+ backing)
+ response = request.execute(
+ '', branch_token, repo_token, '1', 'not-present')
+ self.assertEqual(
+ SmartServerResponse(('NoSuchRevision', 'not-present')), response)
+
+
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
def setUp(self):
@@ -1014,6 +1078,9 @@
smart.request.request_handlers.get('Branch.set_last_revision'),
smart.branch.SmartServerBranchRequestSetLastRevision)
self.assertEqual(
+ smart.request.request_handlers.get('Branch.set_last_revision_info'),
+ smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
+ self.assertEqual(
smart.request.request_handlers.get('Branch.unlock'),
smart.branch.SmartServerBranchRequestUnlock)
self.assertEqual(
More information about the bazaar-commits
mailing list