161
170
def test_translate_client_path(self):
162
171
transport = self.get_transport()
163
172
request = smart_req.SmartServerRequest(transport, 'foo/')
164
self.assertEqual('./', request.translate_client_path('foo/'))
166
errors.InvalidURLJoin, request.translate_client_path, 'foo/..')
168
errors.PathNotChild, request.translate_client_path, '/')
170
errors.PathNotChild, request.translate_client_path, 'bar/')
171
self.assertEqual('./baz', request.translate_client_path('foo/baz'))
172
e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
173
self.assertEqual('./' + urlutils.escape(e_acute),
174
request.translate_client_path('foo/' + e_acute))
173
self.assertEqual('./', request.translate_client_path(b'foo/'))
175
urlutils.InvalidURLJoin, request.translate_client_path, b'foo/..')
177
errors.PathNotChild, request.translate_client_path, b'/')
179
errors.PathNotChild, request.translate_client_path, b'bar/')
180
self.assertEqual('./baz', request.translate_client_path(b'foo/baz'))
181
e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'
183
u'./' + urlutils.escape(e_acute),
184
request.translate_client_path(b'foo/' + e_acute.encode('utf-8')))
176
186
def test_translate_client_path_vfs(self):
177
187
"""VfsRequests receive escaped paths rather than raw UTF-8."""
178
188
transport = self.get_transport()
179
189
request = vfs.VfsRequest(transport, 'foo/')
180
e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
181
escaped = urlutils.escape('foo/' + e_acute)
182
self.assertEqual('./' + urlutils.escape(e_acute),
183
request.translate_client_path(escaped))
190
e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'
191
escaped = urlutils.escape(u'foo/' + e_acute)
193
'./' + urlutils.escape(e_acute),
194
request.translate_client_path(escaped.encode('ascii')))
185
196
def test_transport_from_client_path(self):
186
197
transport = self.get_transport()
187
198
request = smart_req.SmartServerRequest(transport, 'foo/')
188
199
self.assertEqual(
190
request.transport_from_client_path('foo/').base)
201
request.transport_from_client_path(b'foo/').base)
193
204
class TestSmartServerBzrDirRequestCloningMetaDir(
194
tests.TestCaseWithMemoryTransport):
205
tests.TestCaseWithMemoryTransport):
195
206
"""Tests for BzrDir.cloning_metadir."""
197
208
def test_cloning_metadir(self):
198
209
"""When there is a bzrdir present, the call succeeds."""
199
210
backing = self.get_transport()
200
dir = self.make_bzrdir('.')
211
dir = self.make_controldir('.')
201
212
local_result = dir.cloning_metadir()
202
213
request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
203
214
request = request_class(backing)
204
215
expected = smart_req.SuccessfulSmartServerResponse(
205
216
(local_result.network_name(),
206
local_result.repository_format.network_name(),
207
('branch', local_result.get_branch_format().network_name())))
208
self.assertEqual(expected, request.execute('', 'False'))
217
local_result.repository_format.network_name(),
218
(b'branch', local_result.get_branch_format().network_name())))
219
self.assertEqual(expected, request.execute(b'', b'False'))
210
221
def test_cloning_metadir_reference(self):
211
222
"""The request fails when bzrdir contains a branch reference."""
212
223
backing = self.get_transport()
213
224
referenced_branch = self.make_branch('referenced')
214
dir = self.make_bzrdir('.')
215
local_result = dir.cloning_metadir()
216
reference = _mod_branch.BranchReferenceFormat().initialize(
225
dir = self.make_controldir('.')
226
dir.cloning_metadir()
227
_mod_bzrbranch.BranchReferenceFormat().initialize(
217
228
dir, target_branch=referenced_branch)
218
reference_url = _mod_branch.BranchReferenceFormat().get_reference(dir)
229
_mod_bzrbranch.BranchReferenceFormat().get_reference(dir)
219
230
# The server shouldn't try to follow the branch reference, so it's fine
220
231
# if the referenced branch isn't reachable.
221
232
backing.rename('referenced', 'moved')
222
233
request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
223
234
request = request_class(backing)
224
expected = smart_req.FailedSmartServerResponse(('BranchReference',))
225
self.assertEqual(expected, request.execute('', 'False'))
228
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
235
expected = smart_req.FailedSmartServerResponse((b'BranchReference',))
236
self.assertEqual(expected, request.execute(b'', b'False'))
239
class TestSmartServerBzrDirRequestCheckoutMetaDir(
240
tests.TestCaseWithMemoryTransport):
241
"""Tests for BzrDir.checkout_metadir."""
243
def test_checkout_metadir(self):
244
backing = self.get_transport()
245
request = smart_dir.SmartServerBzrDirRequestCheckoutMetaDir(
247
self.make_branch('.', format='2a')
248
response = request.execute(b'')
250
smart_req.SmartServerResponse(
251
(b'Bazaar-NG meta directory, format 1\n',
252
b'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
253
b'Bazaar Branch Format 7 (needs bzr 1.6)\n')),
257
class TestSmartServerBzrDirRequestDestroyBranch(
258
tests.TestCaseWithMemoryTransport):
259
"""Tests for BzrDir.destroy_branch."""
261
def test_destroy_branch_default(self):
262
"""The default branch can be removed."""
263
backing = self.get_transport()
264
self.make_branch('.')
265
request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
266
request = request_class(backing)
267
expected = smart_req.SuccessfulSmartServerResponse((b'ok',))
268
self.assertEqual(expected, request.execute(b'', None))
270
def test_destroy_branch_named(self):
271
"""A named branch can be removed."""
272
backing = self.get_transport()
273
dir = self.make_repository('.', format="development-colo").controldir
274
dir.create_branch(name="branchname")
275
request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
276
request = request_class(backing)
277
expected = smart_req.SuccessfulSmartServerResponse((b'ok',))
278
self.assertEqual(expected, request.execute(b'', b"branchname"))
280
def test_destroy_branch_missing(self):
281
"""An error is raised if the branch didn't exist."""
282
backing = self.get_transport()
283
self.make_controldir('.', format="development-colo")
284
request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
285
request = request_class(backing)
286
expected = smart_req.FailedSmartServerResponse((b'nobranch',), None)
287
self.assertEqual(expected, request.execute(b'', b"branchname"))
290
class TestSmartServerBzrDirRequestHasWorkingTree(
291
tests.TestCaseWithTransport):
292
"""Tests for BzrDir.has_workingtree."""
294
def test_has_workingtree_yes(self):
295
"""A working tree is present."""
296
backing = self.get_transport()
297
self.make_branch_and_tree('.')
298
request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
299
request = request_class(backing)
300
expected = smart_req.SuccessfulSmartServerResponse((b'yes',))
301
self.assertEqual(expected, request.execute(b''))
303
def test_has_workingtree_no(self):
304
"""A working tree is missing."""
305
backing = self.get_transport()
306
self.make_controldir('.')
307
request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
308
request = request_class(backing)
309
expected = smart_req.SuccessfulSmartServerResponse((b'no',))
310
self.assertEqual(expected, request.execute(b''))
313
class TestSmartServerBzrDirRequestDestroyRepository(
314
tests.TestCaseWithMemoryTransport):
315
"""Tests for BzrDir.destroy_repository."""
317
def test_destroy_repository_default(self):
318
"""The repository can be removed."""
319
backing = self.get_transport()
320
self.make_repository('.')
321
request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
322
request = request_class(backing)
323
expected = smart_req.SuccessfulSmartServerResponse((b'ok',))
324
self.assertEqual(expected, request.execute(b''))
326
def test_destroy_repository_missing(self):
327
"""An error is raised if the repository didn't exist."""
328
backing = self.get_transport()
329
self.make_controldir('.')
330
request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
331
request = request_class(backing)
332
expected = smart_req.FailedSmartServerResponse(
333
(b'norepository',), None)
334
self.assertEqual(expected, request.execute(b''))
337
class TestSmartServerRequestCreateRepository(
338
tests.TestCaseWithMemoryTransport):
229
339
"""Tests for BzrDir.create_repository."""
231
341
def test_makes_repository(self):
232
342
"""When there is a bzrdir present, the call succeeds."""
233
343
backing = self.get_transport()
234
self.make_bzrdir('.')
344
self.make_controldir('.')
235
345
request_class = smart_dir.SmartServerRequestCreateRepository
236
346
request = request_class(backing)
237
reference_bzrdir_format = bzrdir.format_registry.get('pack-0.92')()
347
reference_bzrdir_format = controldir.format_registry.get('pack-0.92')()
238
348
reference_format = reference_bzrdir_format.repository_format
239
349
network_name = reference_format.network_name()
240
350
expected = smart_req.SuccessfulSmartServerResponse(
241
('ok', 'no', 'no', 'no', network_name))
242
self.assertEqual(expected, request.execute('', network_name, 'True'))
351
(b'ok', b'no', b'no', b'no', network_name))
352
self.assertEqual(expected, request.execute(b'', network_name, b'True'))
245
355
class TestSmartServerRequestFindRepository(tests.TestCaseWithMemoryTransport):
246
356
"""Tests for BzrDir.find_repository."""
248
358
def test_no_repository(self):
249
"""When there is no repository to be found, ('norepository', ) is returned."""
359
"""If no repository is found, ('norepository', ) is returned."""
250
360
backing = self.get_transport()
251
361
request = self._request_class(backing)
252
self.make_bzrdir('.')
253
self.assertEqual(smart_req.SmartServerResponse(('norepository', )),
362
self.make_controldir('.')
363
self.assertEqual(smart_req.SmartServerResponse((b'norepository', )),
364
request.execute(b''))
256
366
def test_nonshared_repository(self):
257
367
# nonshared repositorys only allow 'find' to return a handle when the
273
383
repo = self.make_repository('.', shared=shared, format=format)
274
384
if repo.supports_rich_root():
278
388
if repo._format.supports_tree_reference:
282
392
if repo._format.supports_external_lookups:
286
396
if (smart_dir.SmartServerRequestFindRepositoryV3 ==
287
self._request_class):
397
self._request_class):
288
398
return smart_req.SuccessfulSmartServerResponse(
289
('ok', '', rich_root, subtrees, external,
399
(b'ok', b'', rich_root, subtrees, external,
290
400
repo._format.network_name()))
291
401
elif (smart_dir.SmartServerRequestFindRepositoryV2 ==
292
self._request_class):
402
self._request_class):
293
403
# All tests so far are on formats, and for non-external
295
405
return smart_req.SuccessfulSmartServerResponse(
296
('ok', '', rich_root, subtrees, external))
406
(b'ok', b'', rich_root, subtrees, external))
298
408
return smart_req.SuccessfulSmartServerResponse(
299
('ok', '', rich_root, subtrees))
409
(b'ok', b'', rich_root, subtrees))
301
411
def test_shared_repository(self):
302
"""When there is a shared repository, we get 'ok', 'relpath-to-repo'."""
412
"""for a shared repository, we get 'ok', 'relpath-to-repo'."""
303
413
backing = self.get_transport()
304
414
request = self._request_class(backing)
305
415
result = self._make_repository_and_result(shared=True)
306
self.assertEqual(result, request.execute(''))
307
self.make_bzrdir('subdir')
416
self.assertEqual(result, request.execute(b''))
417
self.make_controldir('subdir')
308
418
result2 = smart_req.SmartServerResponse(
309
result.args[0:1] + ('..', ) + result.args[2:])
419
result.args[0:1] + (b'..', ) + result.args[2:])
310
420
self.assertEqual(result2,
311
request.execute('subdir'))
312
self.make_bzrdir('subdir/deeper')
421
request.execute(b'subdir'))
422
self.make_controldir('subdir/deeper')
313
423
result3 = smart_req.SmartServerResponse(
314
result.args[0:1] + ('../..', ) + result.args[2:])
424
result.args[0:1] + (b'../..', ) + result.args[2:])
315
425
self.assertEqual(result3,
316
request.execute('subdir/deeper'))
426
request.execute(b'subdir/deeper'))
318
428
def test_rich_root_and_subtree_encoding(self):
319
429
"""Test for the format attributes for rich root and subtree support."""
320
430
backing = self.get_transport()
321
431
request = self._request_class(backing)
322
432
result = self._make_repository_and_result(
323
format='dirstate-with-subtree')
433
format='development-subtree')
324
434
# check the test will be valid
325
self.assertEqual('yes', result.args[2])
326
self.assertEqual('yes', result.args[3])
327
self.assertEqual(result, request.execute(''))
435
self.assertEqual(b'yes', result.args[2])
436
self.assertEqual(b'yes', result.args[3])
437
self.assertEqual(result, request.execute(b''))
329
439
def test_supports_external_lookups_no_v2(self):
330
440
"""Test for the supports_external_lookups attribute."""
331
441
backing = self.get_transport()
332
442
request = self._request_class(backing)
333
443
result = self._make_repository_and_result(
334
format='dirstate-with-subtree')
444
format='development-subtree')
335
445
# check the test will be valid
336
self.assertEqual('no', result.args[4])
337
self.assertEqual(result, request.execute(''))
446
self.assertEqual(b'yes', result.args[4])
447
self.assertEqual(result, request.execute(b''))
340
450
class TestSmartServerBzrDirRequestGetConfigFile(
341
tests.TestCaseWithMemoryTransport):
451
tests.TestCaseWithMemoryTransport):
342
452
"""Tests for BzrDir.get_config_file."""
344
454
def test_present(self):
345
455
backing = self.get_transport()
346
dir = self.make_bzrdir('.')
456
dir = self.make_controldir('.')
347
457
dir.get_config().set_default_stack_on("/")
348
458
local_result = dir._get_config()._get_config_file().read()
349
459
request_class = smart_dir.SmartServerBzrDirRequestConfigFile
350
460
request = request_class(backing)
351
461
expected = smart_req.SuccessfulSmartServerResponse((), local_result)
352
self.assertEqual(expected, request.execute(''))
462
self.assertEqual(expected, request.execute(b''))
354
464
def test_missing(self):
355
465
backing = self.get_transport()
356
dir = self.make_bzrdir('.')
466
self.make_controldir('.')
357
467
request_class = smart_dir.SmartServerBzrDirRequestConfigFile
358
468
request = request_class(backing)
359
expected = smart_req.SuccessfulSmartServerResponse((), '')
360
self.assertEqual(expected, request.execute(''))
363
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithMemoryTransport):
469
expected = smart_req.SuccessfulSmartServerResponse((), b'')
470
self.assertEqual(expected, request.execute(b''))
473
class TestSmartServerBzrDirRequestGetBranches(
474
tests.TestCaseWithMemoryTransport):
475
"""Tests for BzrDir.get_branches."""
477
def test_simple(self):
478
backing = self.get_transport()
479
branch = self.make_branch('.')
480
request_class = smart_dir.SmartServerBzrDirRequestGetBranches
481
request = request_class(backing)
482
local_result = bencode.bencode(
483
{b"": (b"branch", branch._format.network_name())})
484
expected = smart_req.SuccessfulSmartServerResponse(
485
(b"success", ), local_result)
486
self.assertEqual(expected, request.execute(b''))
488
def test_empty(self):
489
backing = self.get_transport()
490
self.make_controldir('.')
491
request_class = smart_dir.SmartServerBzrDirRequestGetBranches
492
request = request_class(backing)
493
local_result = bencode.bencode({})
494
expected = smart_req.SuccessfulSmartServerResponse(
495
(b'success',), local_result)
496
self.assertEqual(expected, request.execute(b''))
499
class TestSmartServerRequestInitializeBzrDir(
500
tests.TestCaseWithMemoryTransport):
365
502
def test_empty_dir(self):
366
503
"""Initializing an empty dir should succeed and do it."""
367
504
backing = self.get_transport()
368
505
request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
369
self.assertEqual(smart_req.SmartServerResponse(('ok', )),
371
made_dir = bzrdir.BzrDir.open_from_transport(backing)
506
self.assertEqual(smart_req.SmartServerResponse((b'ok', )),
507
request.execute(b''))
508
made_dir = controldir.ControlDir.open_from_transport(backing)
372
509
# no branch, tree or repository is expected with the current
373
510
# default formart.
374
511
self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
698
837
"""When there is a bzrdir and no branch, NotBranchError is raised."""
699
838
backing = self.get_transport()
700
839
request = smart_branch.SmartServerBranchRequest(backing)
701
self.make_bzrdir('.')
840
self.make_controldir('.')
702
841
self.assertRaises(errors.NotBranchError,
842
request.execute, b'')
705
844
def test_branch_reference(self):
706
845
"""When there is a branch reference, NotBranchError is raised."""
707
846
backing = self.get_transport()
708
847
request = smart_branch.SmartServerBranchRequest(backing)
709
848
branch = self.make_branch('branch')
710
checkout = branch.create_checkout('reference',lightweight=True)
849
branch.create_checkout('reference', lightweight=True)
711
850
self.assertRaises(errors.NotBranchError,
712
request.execute, 'checkout')
851
request.execute, b'checkout')
715
854
class TestSmartServerBranchRequestLastRevisionInfo(
716
tests.TestCaseWithMemoryTransport):
855
tests.TestCaseWithMemoryTransport):
718
857
def test_empty(self):
719
"""For an empty branch, the result is ('ok', '0', 'null:')."""
858
"""For an empty branch, the result is ('ok', '0', b'null:')."""
720
859
backing = self.get_transport()
721
request = smart_branch.SmartServerBranchRequestLastRevisionInfo(backing)
860
request = smart_branch.SmartServerBranchRequestLastRevisionInfo(
722
862
self.make_branch('.')
723
self.assertEqual(smart_req.SmartServerResponse(('ok', '0', 'null:')),
864
smart_req.SmartServerResponse((b'ok', b'0', b'null:')),
865
request.execute(b''))
867
def test_ghost(self):
868
"""For an empty branch, the result is ('ok', '0', b'null:')."""
869
backing = self.get_transport()
870
request = smart_branch.SmartServerBranchRequestLastRevisionInfo(
872
branch = self.make_branch('.')
874
def last_revision_info():
875
raise errors.GhostRevisionsHaveNoRevno(b'revid1', b'revid2')
876
self.overrideAttr(branch, 'last_revision_info', last_revision_info)
877
self.assertRaises(errors.GhostRevisionsHaveNoRevno,
878
request.do_with_branch, branch)
726
880
def test_not_empty(self):
727
881
"""For a non-empty branch, the result is ('ok', 'revno', 'revid')."""
728
882
backing = self.get_transport()
729
request = smart_branch.SmartServerBranchRequestLastRevisionInfo(backing)
883
request = smart_branch.SmartServerBranchRequestLastRevisionInfo(
730
885
tree = self.make_branch_and_memory_tree('.')
731
886
tree.lock_write()
733
888
rev_id_utf8 = u'\xc8'.encode('utf-8')
889
tree.commit('1st commit')
890
tree.commit('2nd commit', rev_id=rev_id_utf8)
893
smart_req.SmartServerResponse((b'ok', b'2', rev_id_utf8)),
894
request.execute(b''))
897
class TestSmartServerBranchRequestRevisionIdToRevno(
898
tests.TestCaseWithMemoryTransport):
901
backing = self.get_transport()
902
request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
904
self.make_branch('.')
905
self.assertEqual(smart_req.SmartServerResponse((b'ok', b'0')),
906
request.execute(b'', b'null:'))
908
def test_simple(self):
909
backing = self.get_transport()
910
request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
912
tree = self.make_branch_and_memory_tree('.')
734
915
r1 = tree.commit('1st commit')
735
r2 = tree.commit('2nd commit', rev_id=rev_id_utf8)
737
917
self.assertEqual(
738
smart_req.SmartServerResponse(('ok', '2', rev_id_utf8)),
918
smart_req.SmartServerResponse((b'ok', b'1')),
919
request.execute(b'', r1))
921
def test_not_found(self):
922
backing = self.get_transport()
923
request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
925
self.make_branch('.')
927
smart_req.FailedSmartServerResponse(
928
(b'NoSuchRevision', b'idontexist')),
929
request.execute(b'', b'idontexist'))
742
932
class TestSmartServerBranchRequestGetConfigFile(
743
tests.TestCaseWithMemoryTransport):
933
tests.TestCaseWithMemoryTransport):
745
935
def test_default(self):
746
936
"""With no file, we get empty content."""
747
937
backing = self.get_transport()
748
938
request = smart_branch.SmartServerBranchGetConfigFile(backing)
749
branch = self.make_branch('.')
939
self.make_branch('.')
750
940
# there should be no file by default
752
self.assertEqual(smart_req.SmartServerResponse(('ok', ), content),
942
self.assertEqual(smart_req.SmartServerResponse((b'ok', ), content),
943
request.execute(b''))
755
945
def test_with_content(self):
756
946
# SmartServerBranchGetConfigFile should return the content from
757
# branch.control_files.get('branch.conf') for now - in the future it may
758
# perform more complex processing.
947
# branch.control_files.get('branch.conf') for now - in the future it
948
# may perform more complex processing.
759
949
backing = self.get_transport()
760
950
request = smart_branch.SmartServerBranchGetConfigFile(backing)
761
951
branch = self.make_branch('.')
762
branch._transport.put_bytes('branch.conf', 'foo bar baz')
763
self.assertEqual(smart_req.SmartServerResponse(('ok', ), 'foo bar baz'),
952
branch._transport.put_bytes('branch.conf', b'foo bar baz')
954
smart_req.SmartServerResponse((b'ok', ), b'foo bar baz'),
955
request.execute(b''))
767
958
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
769
960
def get_lock_tokens(self, branch):
770
branch_token = branch.lock_write()
771
repo_token = branch.repository.lock_write()
961
branch_token = branch.lock_write().token
962
repo_token = branch.repository.lock_write().repository_token
772
963
branch.repository.unlock()
773
964
return branch_token, repo_token
967
class TestSmartServerBranchRequestPutConfigFile(TestLockedBranch):
969
def test_with_content(self):
970
backing = self.get_transport()
971
request = smart_branch.SmartServerBranchPutConfigFile(backing)
972
branch = self.make_branch('.')
973
branch_token, repo_token = self.get_lock_tokens(branch)
974
self.assertIs(None, request.execute(b'', branch_token, repo_token))
976
smart_req.SmartServerResponse((b'ok', )),
977
request.do_body(b'foo bar baz'))
979
branch.control_transport.get_bytes('branch.conf'),
776
984
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
778
986
def test_value_name(self):
779
987
branch = self.make_branch('.')
780
988
request = smart_branch.SmartServerBranchRequestSetConfigOption(
781
branch.bzrdir.root_transport)
989
branch.controldir.root_transport)
782
990
branch_token, repo_token = self.get_lock_tokens(branch)
783
991
config = branch._get_config()
784
result = request.execute('', branch_token, repo_token, 'bar', 'foo',
992
result = request.execute(b'', branch_token, repo_token, b'bar', b'foo',
786
994
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
787
995
self.assertEqual('bar', config.get_option('foo'))
1082
1350
branch.unlock()
1083
1351
request = smart_branch.SmartServerBranchRequestSetParentLocation(
1084
1352
self.get_transport())
1085
branch_token = branch.lock_write()
1086
repo_token = branch.repository.lock_write()
1353
branch_token, repo_token = self.get_lock_tokens(branch)
1088
response = request.execute('base', branch_token, repo_token, '')
1355
response = request.execute(b'base', branch_token, repo_token, b'')
1090
branch.repository.unlock()
1091
1357
branch.unlock()
1092
1358
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1359
# Refresh branch as SetParentLocation modified it
1360
branch = branch.controldir.open_branch()
1093
1361
self.assertEqual(None, branch.get_parent())
1095
1363
def test_set_parent_something(self):
1096
1364
branch = self.make_branch('base', format="1.9")
1097
1365
request = smart_branch.SmartServerBranchRequestSetParentLocation(
1098
1366
self.get_transport())
1099
branch_token = branch.lock_write()
1100
repo_token = branch.repository.lock_write()
1367
branch_token, repo_token = self.get_lock_tokens(branch)
1102
response = request.execute('base', branch_token, repo_token,
1369
response = request.execute(b'base', branch_token, repo_token,
1105
branch.repository.unlock()
1106
1372
branch.unlock()
1107
1373
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1108
self.assertEqual('http://bar/', branch.get_parent())
1374
refreshed = _mod_branch.Branch.open(branch.base)
1375
self.assertEqual('http://bar/', refreshed.get_parent())
1111
1378
class TestSmartServerBranchRequestGetTagsBytes(
1112
tests.TestCaseWithMemoryTransport):
1379
tests.TestCaseWithMemoryTransport):
1113
1380
# Only called when the branch format and tags match [yay factory
1114
1381
# methods] so only need to test straight forward cases.
1116
1383
def test_get_bytes(self):
1117
base_branch = self.make_branch('base')
1384
self.make_branch('base')
1118
1385
request = smart_branch.SmartServerBranchGetTagsBytes(
1119
1386
self.get_transport())
1120
response = request.execute('base')
1122
smart_req.SuccessfulSmartServerResponse(('',)), response)
1125
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
1387
response = request.execute(b'base')
1389
smart_req.SuccessfulSmartServerResponse((b'',)), response)
1392
class TestSmartServerBranchRequestGetStackedOnURL(
1393
tests.TestCaseWithMemoryTransport):
1127
1395
def test_get_stacked_on_url(self):
1128
base_branch = self.make_branch('base', format='1.6')
1396
self.make_branch('base', format='1.6')
1129
1397
stacked_branch = self.make_branch('stacked', format='1.6')
1130
1398
# typically should be relative
1131
1399
stacked_branch.set_stacked_on_url('../base')
1132
1400
request = smart_branch.SmartServerBranchRequestGetStackedOnURL(
1133
1401
self.get_transport())
1134
response = request.execute('stacked')
1136
smart_req.SmartServerResponse(('ok', '../base')),
1402
response = request.execute(b'stacked')
1404
smart_req.SmartServerResponse((b'ok', b'../base')),
1140
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
1143
tests.TestCaseWithMemoryTransport.setUp(self)
1408
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
1145
1410
def test_lock_write_on_unlocked_branch(self):
1146
1411
backing = self.get_transport()
1147
1412
request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1148
1413
branch = self.make_branch('.', format='knit')
1149
1414
repository = branch.repository
1150
response = request.execute('')
1415
response = request.execute(b'')
1151
1416
branch_nonce = branch.control_files._lock.peek().get('nonce')
1152
1417
repository_nonce = repository.control_files._lock.peek().get('nonce')
1153
1418
self.assertEqual(smart_req.SmartServerResponse(
1154
('ok', branch_nonce, repository_nonce)),
1419
(b'ok', branch_nonce, repository_nonce)),
1156
1421
# The branch (and associated repository) is now locked. Verify that
1157
1422
# with a new branch object.
1158
new_branch = repository.bzrdir.open_branch()
1423
new_branch = repository.controldir.open_branch()
1159
1424
self.assertRaises(errors.LockContention, new_branch.lock_write)
1161
1426
request = smart_branch.SmartServerBranchRequestUnlock(backing)
1162
response = request.execute('', branch_nonce, repository_nonce)
1427
response = request.execute(b'', branch_nonce, repository_nonce)
1164
1429
def test_lock_write_on_locked_branch(self):
1165
1430
backing = self.get_transport()
1166
1431
request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1167
1432
branch = self.make_branch('.')
1168
branch_token = branch.lock_write()
1433
branch_token = branch.lock_write().token
1169
1434
branch.leave_lock_in_place()
1170
1435
branch.unlock()
1171
response = request.execute('')
1436
response = request.execute(b'')
1172
1437
self.assertEqual(
1173
smart_req.SmartServerResponse(('LockContention',)), response)
1438
smart_req.SmartServerResponse((b'LockContention',)), response)
1175
1440
branch.lock_write(branch_token)
1176
1441
branch.dont_leave_lock_in_place()
1240
1501
def test_lock_write_on_readonly_transport(self):
1241
1502
backing = self.get_readonly_transport()
1242
1503
request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1243
branch = self.make_branch('.')
1504
self.make_branch('.')
1244
1505
root = self.get_transport().clone('/')
1245
1506
path = urlutils.relative_url(root.base, self.get_transport().base)
1246
response = request.execute(path)
1507
response = request.execute(path.encode('utf-8'))
1247
1508
error_name, lock_str, why_str = response.args
1248
1509
self.assertFalse(response.is_successful())
1249
self.assertEqual('LockFailed', error_name)
1252
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
1255
tests.TestCaseWithMemoryTransport.setUp(self)
1510
self.assertEqual(b'LockFailed', error_name)
1513
class TestSmartServerBranchRequestGetPhysicalLockStatus(TestLockedBranch):
1515
def test_true(self):
1516
backing = self.get_transport()
1517
request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
1519
branch = self.make_branch('.')
1520
branch_token, repo_token = self.get_lock_tokens(branch)
1521
self.assertEqual(True, branch.get_physical_lock_status())
1522
response = request.execute(b'')
1524
smart_req.SmartServerResponse((b'yes',)), response)
1527
def test_false(self):
1528
backing = self.get_transport()
1529
request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
1531
branch = self.make_branch('.')
1532
self.assertEqual(False, branch.get_physical_lock_status())
1533
response = request.execute(b'')
1535
smart_req.SmartServerResponse((b'no',)), response)
1538
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1257
1540
def test_unlock_on_locked_branch_and_repo(self):
1258
1541
backing = self.get_transport()
1259
1542
request = smart_branch.SmartServerBranchRequestUnlock(backing)
1260
1543
branch = self.make_branch('.', format='knit')
1261
1544
# Lock the branch
1262
branch_token = branch.lock_write()
1263
repo_token = branch.repository.lock_write()
1264
branch.repository.unlock()
1545
branch_token, repo_token = self.get_lock_tokens(branch)
1265
1546
# Unlock the branch (and repo) object, leaving the physical locks
1267
1548
branch.leave_lock_in_place()
1268
1549
branch.repository.leave_lock_in_place()
1269
1550
branch.unlock()
1270
response = request.execute('',
1551
response = request.execute(b'',
1271
1552
branch_token, repo_token)
1272
1553
self.assertEqual(
1273
smart_req.SmartServerResponse(('ok',)), response)
1554
smart_req.SmartServerResponse((b'ok',)), response)
1274
1555
# The branch is now unlocked. Verify that with a new branch
1276
new_branch = branch.bzrdir.open_branch()
1557
new_branch = branch.controldir.open_branch()
1277
1558
new_branch.lock_write()
1278
1559
new_branch.unlock()
1280
1561
def test_unlock_on_unlocked_branch_unlocked_repo(self):
1281
1562
backing = self.get_transport()
1282
1563
request = smart_branch.SmartServerBranchRequestUnlock(backing)
1283
branch = self.make_branch('.', format='knit')
1564
self.make_branch('.', format='knit')
1284
1565
response = request.execute(
1285
'', 'branch token', 'repo token')
1566
b'', b'branch token', b'repo token')
1286
1567
self.assertEqual(
1287
smart_req.SmartServerResponse(('TokenMismatch',)), response)
1568
smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1289
1570
def test_unlock_on_unlocked_branch_locked_repo(self):
1290
1571
backing = self.get_transport()
1291
1572
request = smart_branch.SmartServerBranchRequestUnlock(backing)
1292
1573
branch = self.make_branch('.', format='knit')
1293
1574
# Lock the repository.
1294
repo_token = branch.repository.lock_write()
1575
repo_token = branch.repository.lock_write().repository_token
1295
1576
branch.repository.leave_lock_in_place()
1296
1577
branch.repository.unlock()
1297
1578
# Issue branch lock_write request on the unlocked branch (with locked
1299
response = request.execute(
1300
'', 'branch token', repo_token)
1580
response = request.execute(b'', b'branch token', repo_token)
1301
1581
self.assertEqual(
1302
smart_req.SmartServerResponse(('TokenMismatch',)), response)
1582
smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1304
1584
branch.repository.lock_write(repo_token)
1305
1585
branch.repository.dont_leave_lock_in_place()
1504
1924
tree.lock_write()
1506
1926
rev_id_utf8 = u'\xc8abc'.encode('utf-8')
1507
r1 = tree.commit('a commit', rev_id=rev_id_utf8)
1927
tree.commit('a commit', rev_id=rev_id_utf8)
1509
1929
self.assertTrue(tree.branch.repository.has_revision(rev_id_utf8))
1510
self.assertEqual(smart_req.SmartServerResponse(('yes', )),
1511
request.execute('', rev_id_utf8))
1930
self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
1931
request.execute(b'', rev_id_utf8))
1934
class TestSmartServerRepositoryIterFilesBytes(tests.TestCaseWithTransport):
1936
def test_single(self):
1937
backing = self.get_transport()
1938
request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
1939
t = self.make_branch_and_tree('.')
1940
self.addCleanup(t.lock_write().unlock)
1941
self.build_tree_contents([("file", b"somecontents")])
1942
t.add(["file"], [b"thefileid"])
1943
t.commit(rev_id=b'somerev', message="add file")
1944
self.assertIs(None, request.execute(b''))
1945
response = request.do_body(b"thefileid\0somerev\n")
1946
self.assertTrue(response.is_successful())
1947
self.assertEqual(response.args, (b"ok", ))
1948
self.assertEqual(b"".join(response.body_stream),
1949
b"ok\x000\n" + zlib.compress(b"somecontents"))
1951
def test_missing(self):
1952
backing = self.get_transport()
1953
request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
1954
t = self.make_branch_and_tree('.')
1955
self.addCleanup(t.lock_write().unlock)
1956
self.assertIs(None, request.execute(b''))
1957
response = request.do_body(b"thefileid\0revision\n")
1958
self.assertTrue(response.is_successful())
1959
self.assertEqual(response.args, (b"ok", ))
1960
self.assertEqual(b"".join(response.body_stream),
1961
b"absent\x00thefileid\x00revision\x000\n")
1964
class TestSmartServerRequestHasSignatureForRevisionId(
1965
tests.TestCaseWithMemoryTransport):
1967
def test_missing_revision(self):
1968
"""For a missing revision, NoSuchRevision is returned."""
1969
backing = self.get_transport()
1970
request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
1972
self.make_repository('.')
1974
smart_req.FailedSmartServerResponse(
1975
(b'nosuchrevision', b'revid'), None),
1976
request.execute(b'', b'revid'))
1978
def test_missing_signature(self):
1979
"""For a missing signature, ('no', ) is returned."""
1980
backing = self.get_transport()
1981
request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
1983
tree = self.make_branch_and_memory_tree('.')
1986
tree.commit('a commit', rev_id=b'A')
1988
self.assertTrue(tree.branch.repository.has_revision(b'A'))
1989
self.assertEqual(smart_req.SmartServerResponse((b'no', )),
1990
request.execute(b'', b'A'))
1992
def test_present_signature(self):
1993
"""For a present signature, ('yes', ) is returned."""
1994
backing = self.get_transport()
1995
request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
1997
strategy = gpg.LoopbackGPGStrategy(None)
1998
tree = self.make_branch_and_memory_tree('.')
2001
tree.commit('a commit', rev_id=b'A')
2002
tree.branch.repository.start_write_group()
2003
tree.branch.repository.sign_revision(b'A', strategy)
2004
tree.branch.repository.commit_write_group()
2006
self.assertTrue(tree.branch.repository.has_revision(b'A'))
2007
self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
2008
request.execute(b'', b'A'))
1514
2011
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1745
2341
repo.set_make_working_trees(False)
1746
2342
request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1747
2343
request = request_class(backing)
1748
self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1749
request.execute('', 'True'))
1750
repo = repo.bzrdir.open_repository()
2344
self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
2345
request.execute(b'', b'True'))
2346
repo = repo.controldir.open_repository()
1751
2347
self.assertTrue(repo.make_working_trees())
2350
class TestSmartServerRepositoryGetSerializerFormat(
2351
tests.TestCaseWithMemoryTransport):
2353
def test_get_serializer_format(self):
2354
backing = self.get_transport()
2355
repo = self.make_repository('.', format='2a')
2356
request_class = smart_repo.SmartServerRepositoryGetSerializerFormat
2357
request = request_class(backing)
2359
smart_req.SuccessfulSmartServerResponse((b'ok', b'10')),
2360
request.execute(b''))
2363
class TestSmartServerRepositoryWriteGroup(
2364
tests.TestCaseWithMemoryTransport):
2366
def test_start_write_group(self):
2367
backing = self.get_transport()
2368
repo = self.make_repository('.')
2369
lock_token = repo.lock_write().repository_token
2370
self.addCleanup(repo.unlock)
2371
request_class = smart_repo.SmartServerRepositoryStartWriteGroup
2372
request = request_class(backing)
2373
self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok', [])),
2374
request.execute(b'', lock_token))
2376
def test_start_write_group_unsuspendable(self):
2377
backing = self.get_transport()
2378
repo = self.make_repository('.', format='knit')
2379
lock_token = repo.lock_write().repository_token
2380
self.addCleanup(repo.unlock)
2381
request_class = smart_repo.SmartServerRepositoryStartWriteGroup
2382
request = request_class(backing)
2384
smart_req.FailedSmartServerResponse((b'UnsuspendableWriteGroup',)),
2385
request.execute(b'', lock_token))
2387
def test_commit_write_group(self):
2388
backing = self.get_transport()
2389
repo = self.make_repository('.')
2390
lock_token = repo.lock_write().repository_token
2391
self.addCleanup(repo.unlock)
2392
repo.start_write_group()
2393
tokens = repo.suspend_write_group()
2394
request_class = smart_repo.SmartServerRepositoryCommitWriteGroup
2395
request = request_class(backing)
2396
self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
2397
request.execute(b'', lock_token, tokens))
2399
def test_abort_write_group(self):
2400
backing = self.get_transport()
2401
repo = self.make_repository('.')
2402
lock_token = repo.lock_write().repository_token
2403
repo.start_write_group()
2404
tokens = repo.suspend_write_group()
2405
self.addCleanup(repo.unlock)
2406
request_class = smart_repo.SmartServerRepositoryAbortWriteGroup
2407
request = request_class(backing)
2408
self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
2409
request.execute(b'', lock_token, tokens))
2411
def test_check_write_group(self):
2412
backing = self.get_transport()
2413
repo = self.make_repository('.')
2414
lock_token = repo.lock_write().repository_token
2415
repo.start_write_group()
2416
tokens = repo.suspend_write_group()
2417
self.addCleanup(repo.unlock)
2418
request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
2419
request = request_class(backing)
2420
self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
2421
request.execute(b'', lock_token, tokens))
2423
def test_check_write_group_invalid(self):
2424
backing = self.get_transport()
2425
repo = self.make_repository('.')
2426
lock_token = repo.lock_write().repository_token
2427
self.addCleanup(repo.unlock)
2428
request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
2429
request = request_class(backing)
2430
self.assertEqual(smart_req.FailedSmartServerResponse(
2431
(b'UnresumableWriteGroup', [b'random'],
2432
b'Malformed write group token')),
2433
request.execute(b'', lock_token, [b"random"]))
1754
2436
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1756
2438
def make_repo_needing_autopacking(self, path='.'):
1822
2504
"""All registered request_handlers can be found."""
1823
2505
# If there's a typo in a register_lazy call, this loop will fail with
1824
2506
# an AttributeError.
1825
for key, item in smart_req.request_handlers.iteritems():
2507
for key in smart_req.request_handlers.keys():
2509
item = smart_req.request_handlers.get(key)
2510
except AttributeError as e:
2511
raise AttributeError('failed to get %s: %s' % (key, e))
1828
2513
def assertHandlerEqual(self, verb, handler):
1829
2514
self.assertEqual(smart_req.request_handlers.get(verb), handler)
1831
2516
def test_registered_methods(self):
1832
2517
"""Test that known methods are registered to the correct object."""
1833
self.assertHandlerEqual('Branch.get_config_file',
1834
smart_branch.SmartServerBranchGetConfigFile)
1835
self.assertHandlerEqual('Branch.get_parent',
1836
smart_branch.SmartServerBranchGetParent)
1837
self.assertHandlerEqual('Branch.get_tags_bytes',
1838
smart_branch.SmartServerBranchGetTagsBytes)
1839
self.assertHandlerEqual('Branch.lock_write',
1840
smart_branch.SmartServerBranchRequestLockWrite)
1841
self.assertHandlerEqual('Branch.last_revision_info',
1842
smart_branch.SmartServerBranchRequestLastRevisionInfo)
1843
self.assertHandlerEqual('Branch.revision_history',
1844
smart_branch.SmartServerRequestRevisionHistory)
1845
self.assertHandlerEqual('Branch.set_config_option',
1846
smart_branch.SmartServerBranchRequestSetConfigOption)
1847
self.assertHandlerEqual('Branch.set_last_revision',
1848
smart_branch.SmartServerBranchRequestSetLastRevision)
1849
self.assertHandlerEqual('Branch.set_last_revision_info',
1850
smart_branch.SmartServerBranchRequestSetLastRevisionInfo)
1851
self.assertHandlerEqual('Branch.set_last_revision_ex',
1852
smart_branch.SmartServerBranchRequestSetLastRevisionEx)
1853
self.assertHandlerEqual('Branch.set_parent_location',
1854
smart_branch.SmartServerBranchRequestSetParentLocation)
1855
self.assertHandlerEqual('Branch.unlock',
1856
smart_branch.SmartServerBranchRequestUnlock)
1857
self.assertHandlerEqual('BzrDir.find_repository',
1858
smart_dir.SmartServerRequestFindRepositoryV1)
1859
self.assertHandlerEqual('BzrDir.find_repositoryV2',
1860
smart_dir.SmartServerRequestFindRepositoryV2)
1861
self.assertHandlerEqual('BzrDirFormat.initialize',
1862
smart_dir.SmartServerRequestInitializeBzrDir)
1863
self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1864
smart_dir.SmartServerRequestBzrDirInitializeEx)
1865
self.assertHandlerEqual('BzrDir.cloning_metadir',
1866
smart_dir.SmartServerBzrDirRequestCloningMetaDir)
1867
self.assertHandlerEqual('BzrDir.get_config_file',
1868
smart_dir.SmartServerBzrDirRequestConfigFile)
1869
self.assertHandlerEqual('BzrDir.open_branch',
1870
smart_dir.SmartServerRequestOpenBranch)
1871
self.assertHandlerEqual('BzrDir.open_branchV2',
1872
smart_dir.SmartServerRequestOpenBranchV2)
1873
self.assertHandlerEqual('BzrDir.open_branchV3',
1874
smart_dir.SmartServerRequestOpenBranchV3)
1875
self.assertHandlerEqual('PackRepository.autopack',
1876
smart_packrepo.SmartServerPackRepositoryAutopack)
1877
self.assertHandlerEqual('Repository.gather_stats',
1878
smart_repo.SmartServerRepositoryGatherStats)
1879
self.assertHandlerEqual('Repository.get_parent_map',
1880
smart_repo.SmartServerRepositoryGetParentMap)
1881
self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1882
smart_repo.SmartServerRepositoryGetRevIdForRevno)
1883
self.assertHandlerEqual('Repository.get_revision_graph',
1884
smart_repo.SmartServerRepositoryGetRevisionGraph)
1885
self.assertHandlerEqual('Repository.get_stream',
1886
smart_repo.SmartServerRepositoryGetStream)
1887
self.assertHandlerEqual('Repository.has_revision',
1888
smart_repo.SmartServerRequestHasRevision)
1889
self.assertHandlerEqual('Repository.insert_stream',
1890
smart_repo.SmartServerRepositoryInsertStream)
1891
self.assertHandlerEqual('Repository.insert_stream_locked',
1892
smart_repo.SmartServerRepositoryInsertStreamLocked)
1893
self.assertHandlerEqual('Repository.is_shared',
1894
smart_repo.SmartServerRepositoryIsShared)
1895
self.assertHandlerEqual('Repository.lock_write',
1896
smart_repo.SmartServerRepositoryLockWrite)
1897
self.assertHandlerEqual('Repository.tarball',
1898
smart_repo.SmartServerRepositoryTarball)
1899
self.assertHandlerEqual('Repository.unlock',
1900
smart_repo.SmartServerRepositoryUnlock)
1901
self.assertHandlerEqual('Transport.is_readonly',
1902
smart_req.SmartServerIsReadonly)
2518
self.assertHandlerEqual(b'Branch.break_lock',
2519
smart_branch.SmartServerBranchBreakLock)
2520
self.assertHandlerEqual(b'Branch.get_config_file',
2521
smart_branch.SmartServerBranchGetConfigFile)
2522
self.assertHandlerEqual(b'Branch.put_config_file',
2523
smart_branch.SmartServerBranchPutConfigFile)
2524
self.assertHandlerEqual(b'Branch.get_parent',
2525
smart_branch.SmartServerBranchGetParent)
2526
self.assertHandlerEqual(b'Branch.get_physical_lock_status',
2527
smart_branch.SmartServerBranchRequestGetPhysicalLockStatus)
2528
self.assertHandlerEqual(b'Branch.get_tags_bytes',
2529
smart_branch.SmartServerBranchGetTagsBytes)
2530
self.assertHandlerEqual(b'Branch.lock_write',
2531
smart_branch.SmartServerBranchRequestLockWrite)
2532
self.assertHandlerEqual(b'Branch.last_revision_info',
2533
smart_branch.SmartServerBranchRequestLastRevisionInfo)
2534
self.assertHandlerEqual(b'Branch.revision_history',
2535
smart_branch.SmartServerRequestRevisionHistory)
2536
self.assertHandlerEqual(b'Branch.revision_id_to_revno',
2537
smart_branch.SmartServerBranchRequestRevisionIdToRevno)
2538
self.assertHandlerEqual(b'Branch.set_config_option',
2539
smart_branch.SmartServerBranchRequestSetConfigOption)
2540
self.assertHandlerEqual(b'Branch.set_last_revision',
2541
smart_branch.SmartServerBranchRequestSetLastRevision)
2542
self.assertHandlerEqual(b'Branch.set_last_revision_info',
2543
smart_branch.SmartServerBranchRequestSetLastRevisionInfo)
2544
self.assertHandlerEqual(b'Branch.set_last_revision_ex',
2545
smart_branch.SmartServerBranchRequestSetLastRevisionEx)
2546
self.assertHandlerEqual(b'Branch.set_parent_location',
2547
smart_branch.SmartServerBranchRequestSetParentLocation)
2548
self.assertHandlerEqual(b'Branch.unlock',
2549
smart_branch.SmartServerBranchRequestUnlock)
2550
self.assertHandlerEqual(b'BzrDir.destroy_branch',
2551
smart_dir.SmartServerBzrDirRequestDestroyBranch)
2552
self.assertHandlerEqual(b'BzrDir.find_repository',
2553
smart_dir.SmartServerRequestFindRepositoryV1)
2554
self.assertHandlerEqual(b'BzrDir.find_repositoryV2',
2555
smart_dir.SmartServerRequestFindRepositoryV2)
2556
self.assertHandlerEqual(b'BzrDirFormat.initialize',
2557
smart_dir.SmartServerRequestInitializeBzrDir)
2558
self.assertHandlerEqual(b'BzrDirFormat.initialize_ex_1.16',
2559
smart_dir.SmartServerRequestBzrDirInitializeEx)
2560
self.assertHandlerEqual(b'BzrDir.checkout_metadir',
2561
smart_dir.SmartServerBzrDirRequestCheckoutMetaDir)
2562
self.assertHandlerEqual(b'BzrDir.cloning_metadir',
2563
smart_dir.SmartServerBzrDirRequestCloningMetaDir)
2564
self.assertHandlerEqual(b'BzrDir.get_branches',
2565
smart_dir.SmartServerBzrDirRequestGetBranches)
2566
self.assertHandlerEqual(b'BzrDir.get_config_file',
2567
smart_dir.SmartServerBzrDirRequestConfigFile)
2568
self.assertHandlerEqual(b'BzrDir.open_branch',
2569
smart_dir.SmartServerRequestOpenBranch)
2570
self.assertHandlerEqual(b'BzrDir.open_branchV2',
2571
smart_dir.SmartServerRequestOpenBranchV2)
2572
self.assertHandlerEqual(b'BzrDir.open_branchV3',
2573
smart_dir.SmartServerRequestOpenBranchV3)
2574
self.assertHandlerEqual(b'PackRepository.autopack',
2575
smart_packrepo.SmartServerPackRepositoryAutopack)
2576
self.assertHandlerEqual(b'Repository.add_signature_text',
2577
smart_repo.SmartServerRepositoryAddSignatureText)
2578
self.assertHandlerEqual(b'Repository.all_revision_ids',
2579
smart_repo.SmartServerRepositoryAllRevisionIds)
2580
self.assertHandlerEqual(b'Repository.break_lock',
2581
smart_repo.SmartServerRepositoryBreakLock)
2582
self.assertHandlerEqual(b'Repository.gather_stats',
2583
smart_repo.SmartServerRepositoryGatherStats)
2584
self.assertHandlerEqual(b'Repository.get_parent_map',
2585
smart_repo.SmartServerRepositoryGetParentMap)
2586
self.assertHandlerEqual(b'Repository.get_physical_lock_status',
2587
smart_repo.SmartServerRepositoryGetPhysicalLockStatus)
2588
self.assertHandlerEqual(b'Repository.get_rev_id_for_revno',
2589
smart_repo.SmartServerRepositoryGetRevIdForRevno)
2590
self.assertHandlerEqual(b'Repository.get_revision_graph',
2591
smart_repo.SmartServerRepositoryGetRevisionGraph)
2592
self.assertHandlerEqual(b'Repository.get_revision_signature_text',
2593
smart_repo.SmartServerRepositoryGetRevisionSignatureText)
2594
self.assertHandlerEqual(b'Repository.get_stream',
2595
smart_repo.SmartServerRepositoryGetStream)
2596
self.assertHandlerEqual(b'Repository.get_stream_1.19',
2597
smart_repo.SmartServerRepositoryGetStream_1_19)
2598
self.assertHandlerEqual(b'Repository.iter_revisions',
2599
smart_repo.SmartServerRepositoryIterRevisions)
2600
self.assertHandlerEqual(b'Repository.has_revision',
2601
smart_repo.SmartServerRequestHasRevision)
2602
self.assertHandlerEqual(b'Repository.insert_stream',
2603
smart_repo.SmartServerRepositoryInsertStream)
2604
self.assertHandlerEqual(b'Repository.insert_stream_locked',
2605
smart_repo.SmartServerRepositoryInsertStreamLocked)
2606
self.assertHandlerEqual(b'Repository.is_shared',
2607
smart_repo.SmartServerRepositoryIsShared)
2608
self.assertHandlerEqual(b'Repository.iter_files_bytes',
2609
smart_repo.SmartServerRepositoryIterFilesBytes)
2610
self.assertHandlerEqual(b'Repository.lock_write',
2611
smart_repo.SmartServerRepositoryLockWrite)
2612
self.assertHandlerEqual(b'Repository.make_working_trees',
2613
smart_repo.SmartServerRepositoryMakeWorkingTrees)
2614
self.assertHandlerEqual(b'Repository.pack',
2615
smart_repo.SmartServerRepositoryPack)
2616
self.assertHandlerEqual(b'Repository.reconcile',
2617
smart_repo.SmartServerRepositoryReconcile)
2618
self.assertHandlerEqual(b'Repository.tarball',
2619
smart_repo.SmartServerRepositoryTarball)
2620
self.assertHandlerEqual(b'Repository.unlock',
2621
smart_repo.SmartServerRepositoryUnlock)
2622
self.assertHandlerEqual(b'Repository.start_write_group',
2623
smart_repo.SmartServerRepositoryStartWriteGroup)
2624
self.assertHandlerEqual(b'Repository.check_write_group',
2625
smart_repo.SmartServerRepositoryCheckWriteGroup)
2626
self.assertHandlerEqual(b'Repository.commit_write_group',
2627
smart_repo.SmartServerRepositoryCommitWriteGroup)
2628
self.assertHandlerEqual(b'Repository.abort_write_group',
2629
smart_repo.SmartServerRepositoryAbortWriteGroup)
2630
self.assertHandlerEqual(b'VersionedFileRepository.get_serializer_format',
2631
smart_repo.SmartServerRepositoryGetSerializerFormat)
2632
self.assertHandlerEqual(b'VersionedFileRepository.get_inventories',
2633
smart_repo.SmartServerRepositoryGetInventories)
2634
self.assertHandlerEqual(b'Transport.is_readonly',
2635
smart_req.SmartServerIsReadonly)
2638
class SmartTCPServerHookTests(tests.TestCaseWithMemoryTransport):
2639
"""Tests for SmartTCPServer hooks."""
2642
super(SmartTCPServerHookTests, self).setUp()
2643
self.server = server.SmartTCPServer(self.get_transport())
2645
def test_run_server_started_hooks(self):
2646
"""Test the server started hooks get fired properly."""
2648
server.SmartTCPServer.hooks.install_named_hook('server_started',
2649
lambda backing_urls, url: started_calls.append(
2650
(backing_urls, url)),
2652
started_ex_calls = []
2653
server.SmartTCPServer.hooks.install_named_hook('server_started_ex',
2654
lambda backing_urls, url: started_ex_calls.append(
2655
(backing_urls, url)),
2657
self.server._sockname = ('example.com', 42)
2658
self.server.run_server_started_hooks()
2659
self.assertEqual(started_calls,
2660
[([self.get_transport().base], 'bzr://example.com:42/')])
2661
self.assertEqual(started_ex_calls,
2662
[([self.get_transport().base], self.server)])
2664
def test_run_server_started_hooks_ipv6(self):
2665
"""Test that socknames can contain 4-tuples."""
2666
self.server._sockname = ('::', 42, 0, 0)
2668
server.SmartTCPServer.hooks.install_named_hook('server_started',
2669
lambda backing_urls, url: started_calls.append(
2670
(backing_urls, url)),
2672
self.server.run_server_started_hooks()
2673
self.assertEqual(started_calls,
2674
[([self.get_transport().base], 'bzr://:::42/')])
2676
def test_run_server_stopped_hooks(self):
2677
"""Test the server stopped hooks."""
2678
self.server._sockname = ('example.com', 42)
2680
server.SmartTCPServer.hooks.install_named_hook('server_stopped',
2681
lambda backing_urls, url: stopped_calls.append(
2682
(backing_urls, url)),
2684
self.server.run_server_stopped_hooks()
2685
self.assertEqual(stopped_calls,
2686
[([self.get_transport().base], 'bzr://example.com:42/')])
2689
class TestSmartServerRepositoryPack(tests.TestCaseWithMemoryTransport):
2691
def test_pack(self):
2692
backing = self.get_transport()
2693
request = smart_repo.SmartServerRepositoryPack(backing)
2694
tree = self.make_branch_and_memory_tree('.')
2695
repo_token = tree.branch.repository.lock_write().repository_token
2697
self.assertIs(None, request.execute(b'', repo_token, False))
2700
smart_req.SuccessfulSmartServerResponse((b'ok', ), ),
2701
request.do_body(b''))
2704
class TestSmartServerRepositoryGetInventories(tests.TestCaseWithTransport):
2706
def _get_serialized_inventory_delta(self, repository, base_revid, revid):
2707
base_inv = repository.revision_tree(base_revid).root_inventory
2708
inv = repository.revision_tree(revid).root_inventory
2709
inv_delta = inv._make_delta(base_inv)
2710
serializer = inventory_delta.InventoryDeltaSerializer(True, False)
2711
return b"".join(serializer.delta_to_lines(base_revid, revid, inv_delta))
2713
def test_single(self):
2714
backing = self.get_transport()
2715
request = smart_repo.SmartServerRepositoryGetInventories(backing)
2716
t = self.make_branch_and_tree('.', format='2a')
2717
self.addCleanup(t.lock_write().unlock)
2718
self.build_tree_contents([("file", b"somecontents")])
2719
t.add(["file"], [b"thefileid"])
2720
t.commit(rev_id=b'somerev', message="add file")
2721
self.assertIs(None, request.execute(b'', b'unordered'))
2722
response = request.do_body(b"somerev\n")
2723
self.assertTrue(response.is_successful())
2724
self.assertEqual(response.args, (b"ok", ))
2725
stream = [('inventory-deltas', [
2726
versionedfile.FulltextContentFactory(b'somerev', None, None,
2727
self._get_serialized_inventory_delta(
2728
t.branch.repository, b'null:', b'somerev'))])]
2729
fmt = controldir.format_registry.get('2a')().repository_format
2731
b"".join(response.body_stream),
2732
b"".join(smart_repo._stream_to_byte_stream(stream, fmt)))
2734
def test_empty(self):
2735
backing = self.get_transport()
2736
request = smart_repo.SmartServerRepositoryGetInventories(backing)
2737
t = self.make_branch_and_tree('.', format='2a')
2738
self.addCleanup(t.lock_write().unlock)
2739
self.build_tree_contents([("file", b"somecontents")])
2740
t.add(["file"], [b"thefileid"])
2741
t.commit(rev_id=b'somerev', message="add file")
2742
self.assertIs(None, request.execute(b'', b'unordered'))
2743
response = request.do_body(b"")
2744
self.assertTrue(response.is_successful())
2745
self.assertEqual(response.args, (b"ok", ))
2746
self.assertEqual(b"".join(response.body_stream),
2747
b"Bazaar pack format 1 (introduced in 0.18)\nB54\n\nBazaar repository format 2a (needs bzr 1.16 or later)\nE")
2750
class TestSmartServerRepositoryGetStreamForMissingKeys(GetStreamTestBase):
2752
def test_missing(self):
2753
"""The search argument may be a 'ancestry-of' some heads'."""
2754
backing = self.get_transport()
2755
request = smart_repo.SmartServerRepositoryGetStreamForMissingKeys(
2757
repo, r1, r2 = self.make_two_commit_repo()
2758
request.execute(b'', repo._format.network_name())
2759
lines = b'inventories\t' + r1
2760
response = request.do_body(lines)
2761
self.assertEqual((b'ok',), response.args)
2762
stream_bytes = b''.join(response.body_stream)
2763
self.assertStartsWith(stream_bytes, b'Bazaar pack format 1')
2765
def test_unknown_format(self):
2766
"""The format may not be known by the remote server."""
2767
backing = self.get_transport()
2768
request = smart_repo.SmartServerRepositoryGetStreamForMissingKeys(
2770
repo, r1, r2 = self.make_two_commit_repo()
2771
request.execute(b'', b'yada yada yada')
2772
expected = smart_req.FailedSmartServerResponse(
2773
(b'UnknownFormat', b'repository', b'yada yada yada'))
2776
class TestSmartServerRepositoryRevisionArchive(tests.TestCaseWithTransport):
2778
backing = self.get_transport()
2779
request = smart_repo.SmartServerRepositoryRevisionArchive(backing)
2780
t = self.make_branch_and_tree('.')
2781
self.addCleanup(t.lock_write().unlock)
2782
self.build_tree_contents([("file", b"somecontents")])
2783
t.add(["file"], [b"thefileid"])
2784
t.commit(rev_id=b'somerev', message="add file")
2785
response = request.execute(b'', b"somerev", b"tar", b"foo.tar", b"foo")
2786
self.assertTrue(response.is_successful())
2787
self.assertEqual(response.args, (b"ok", ))
2788
b = BytesIO(b"".join(response.body_stream))
2789
with tarfile.open(mode='r', fileobj=b) as tf:
2790
self.assertEqual(['foo/file'], tf.getnames())
2793
class TestSmartServerRepositoryAnnotateFileRevision(tests.TestCaseWithTransport):
2796
backing = self.get_transport()
2797
request = smart_repo.SmartServerRepositoryAnnotateFileRevision(backing)
2798
t = self.make_branch_and_tree('.')
2799
self.addCleanup(t.lock_write().unlock)
2800
self.build_tree_contents([("file", b"somecontents\nmorecontents\n")])
2801
t.add(["file"], [b"thefileid"])
2802
t.commit(rev_id=b'somerev', message="add file")
2803
response = request.execute(b'', b"somerev", b"file")
2804
self.assertTrue(response.is_successful())
2805
self.assertEqual(response.args, (b"ok", ))
2807
[[b'somerev', b'somecontents\n'], [b'somerev', b'morecontents\n']],
2808
bencode.bdecode(response.body))