33
from bzrlib.branch import Branch
34
from bzrlib.bzrdir import BzrDir
35
from bzrlib.memorytree import MemoryTree
36
from bzrlib.revision import NULL_REVISION
37
from bzrlib.smart import client, server
38
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
39
from bzrlib.tests.per_branch.test_branch import TestCaseWithBranch
40
from bzrlib.transport import get_transport
41
from bzrlib.transport.local import LocalURLServer
44
class TestPush(TestCaseWithBranch):
37
from bzrlib.smart import (
40
repository as _mod_smart_repo,
42
from bzrlib.tests import (
48
class TestPush(per_branch.TestCaseWithBranch):
46
50
def test_push_convergence_simple(self):
47
51
# when revisions are pushed, the left-most accessible parents must
149
156
tree = a_branch.bzrdir.create_workingtree()
150
157
except errors.NotLocalUrl:
151
if self.vfs_transport_factory is LocalURLServer:
158
if self.vfs_transport_factory is test_server.LocalURLServer:
152
159
# the branch is colocated on disk, we cannot create a checkout.
153
160
# hopefully callers will expect this.
154
local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url('repo/tree'))
161
local_controldir= bzrdir.BzrDir.open(
162
self.get_vfs_only_url('repo/tree'))
155
163
tree = local_controldir.create_workingtree()
157
165
tree = a_branch.create_checkout('repo/tree', lightweight=True)
223
231
push._show_push_branch(trunk, 'rev-2', self.get_url('remote'), output)
224
232
# Push rev-3 onto "remote". If "remote" not stacked and is missing the
225
233
# fulltext record for f-id @ rev-1, then this will fail.
226
remote_branch = Branch.open(self.get_url('remote'))
234
remote_branch = branch.Branch.open(self.get_url('remote'))
227
235
trunk.push(remote_branch)
228
236
check.check_dwim(remote_branch.base, False, True, True)
230
def test_no_get_parent_map_after_insert_stream(self):
231
# Effort test for bug 331823
232
self.setup_smart_server_with_call_log()
233
# Make a local branch with four revisions. Four revisions because:
234
# one to push, one there for _walk_to_common_revisions to find, one we
235
# don't want to access, one for luck :)
236
if isinstance(self.branch_format, branch.BranchReferenceFormat):
237
# This test could in principle apply to BranchReferenceFormat, but
238
# make_branch_builder doesn't support it.
239
raise tests.TestSkipped(
240
"BranchBuilder can't make reference branches.")
242
builder = self.make_branch_builder('local')
243
except (errors.TransportNotPossible, errors.UninitializableFormat):
244
raise tests.TestNotApplicable('format not directly constructable')
245
builder.start_series()
246
builder.build_snapshot('first', None, [
247
('add', ('', 'root-id', 'directory', ''))])
248
builder.build_snapshot('second', ['first'], [])
249
builder.build_snapshot('third', ['second'], [])
250
builder.build_snapshot('fourth', ['third'], [])
251
builder.finish_series()
252
local = builder.get_branch()
253
local = branch.Branch.open(self.get_vfs_only_url('local'))
254
# Initial push of three revisions
255
remote_bzrdir = local.bzrdir.sprout(
256
self.get_url('remote'), revision_id='third')
257
remote = remote_bzrdir.open_branch()
258
# Push fourth revision
259
self.reset_smart_call_log()
260
self.disableOptimisticGetParentMap()
261
self.assertFalse(local.is_locked())
263
hpss_call_names = [item.call.method for item in self.hpss_calls]
264
self.assertTrue('Repository.insert_stream_1.19' in hpss_call_names)
265
insert_stream_idx = hpss_call_names.index(
266
'Repository.insert_stream_1.19')
267
calls_after_insert_stream = hpss_call_names[insert_stream_idx:]
268
# After inserting the stream the client has no reason to query the
269
# remote graph any further.
271
['Repository.insert_stream_1.19', 'Repository.insert_stream_1.19',
272
'get', 'Branch.set_last_revision_info', 'Branch.unlock'],
273
calls_after_insert_stream)
275
def disableOptimisticGetParentMap(self):
276
# Tweak some class variables to stop remote get_parent_map calls asking
277
# for or receiving more data than the caller asked for.
278
old_flag = SmartServerRepositoryGetParentMap.no_extra_results
279
inter_class = repository.InterRepository
280
old_batch_size = inter_class._walk_to_common_revisions_batch_size
281
inter_class._walk_to_common_revisions_batch_size = 1
282
SmartServerRepositoryGetParentMap.no_extra_results = True
284
SmartServerRepositoryGetParentMap.no_extra_results = old_flag
285
inter_class._walk_to_common_revisions_batch_size = old_batch_size
286
self.addCleanup(reset_values)
289
class TestPushHook(TestCaseWithBranch):
239
class TestPushHook(per_branch.TestCaseWithBranch):
292
242
self.hook_calls = []
293
TestCaseWithBranch.setUp(self)
243
super(TestPushHook, self).setUp()
295
245
def capture_post_push_hook(self, result):
296
246
"""Capture post push hook calls to self.hook_calls.
314
264
def test_post_push_empty_history(self):
315
265
target = self.make_branch('target')
316
266
source = self.make_branch('source')
317
Branch.hooks.install_named_hook('post_push',
318
self.capture_post_push_hook, None)
267
branch.Branch.hooks.install_named_hook(
268
'post_push', self.capture_post_push_hook, None)
319
269
source.push(target)
320
270
# with nothing there we should still get a notification, and
321
271
# have both branches locked at the notification time.
322
272
self.assertEqual([
323
('post_push', source, None, target.base, 0, NULL_REVISION,
324
0, NULL_REVISION, True, None, True)
273
('post_push', source, None, target.base, 0, revision.NULL_REVISION,
274
0, revision.NULL_REVISION, True, None, True)
340
290
# remotebranches can't be bound. Let's instead make a new local
341
291
# branch of the default type, which does allow binding.
342
292
# See https://bugs.launchpad.net/bzr/+bug/112020
343
local = BzrDir.create_branch_convenience('local2')
293
local = bzrdir.BzrDir.create_branch_convenience('local2')
344
294
local.bind(target)
345
295
source = self.make_branch('source')
346
Branch.hooks.install_named_hook('post_push',
347
self.capture_post_push_hook, None)
296
branch.Branch.hooks.install_named_hook(
297
'post_push', self.capture_post_push_hook, None)
348
298
source.push(local)
349
299
# with nothing there we should still get a notification, and
350
300
# have both branches locked at the notification time.
351
301
self.assertEqual([
352
('post_push', source, local.base, target.base, 0, NULL_REVISION,
353
0, NULL_REVISION, True, True, True)
302
('post_push', source, local.base, target.base, 0,
303
revision.NULL_REVISION, 0, revision.NULL_REVISION,
361
312
rev1 = target.commit('rev 1')
363
314
sourcedir = target.bzrdir.clone(self.get_url('source'))
364
source = MemoryTree.create_on_branch(sourcedir.open_branch())
315
source = memorytree.MemoryTree.create_on_branch(sourcedir.open_branch())
365
316
rev2 = source.commit('rev 2')
366
Branch.hooks.install_named_hook('post_push',
367
self.capture_post_push_hook, None)
317
branch.Branch.hooks.install_named_hook(
318
'post_push', self.capture_post_push_hook, None)
368
319
source.branch.push(target.branch)
369
320
# with nothing there we should still get a notification, and
370
321
# have both branches locked at the notification time.
378
class EmptyPushSmartEffortTests(TestCaseWithBranch):
329
class EmptyPushSmartEffortTests(per_branch.TestCaseWithBranch):
379
330
"""Tests that a push of 0 revisions should make a limited number of smart
384
335
# Skip some scenarios that don't apply to these tests.
385
if (self.transport_server is not None and
386
issubclass(self.transport_server, server.SmartTCPServer)):
336
if (self.transport_server is not None
337
and issubclass(self.transport_server,
338
test_server.SmartTCPServer_for_testing)):
387
339
raise tests.TestNotApplicable(
388
340
'Does not apply when remote backing branch is also '
389
341
'a smart branch')