/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-15 11:53:48 UTC
  • mto: This revision was merged to the branch mainline in revision 6375.
  • Revision ID: jelmer@samba.org-20111215115348-murs91ipn8jbw6y0
Add tests for default_email behaviour.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
25
25
 
26
26
import bz2
27
27
from cStringIO import StringIO
 
28
import zlib
28
29
 
29
30
from bzrlib import (
30
31
    branch,
31
32
    bzrdir,
32
33
    config,
 
34
    controldir,
33
35
    errors,
34
 
    graph,
 
36
    graph as _mod_graph,
35
37
    inventory,
36
38
    inventory_delta,
37
 
    pack,
38
39
    remote,
39
40
    repository,
40
41
    tests,
 
42
    transport,
41
43
    treebuilder,
42
 
    urlutils,
43
44
    versionedfile,
 
45
    vf_search,
44
46
    )
45
47
from bzrlib.branch import Branch
46
 
from bzrlib.bzrdir import BzrDir, BzrDirFormat
 
48
from bzrlib.bzrdir import (
 
49
    BzrDir,
 
50
    BzrDirFormat,
 
51
    RemoteBzrProber,
 
52
    )
 
53
from bzrlib.chk_serializer import chk_bencode_serializer
47
54
from bzrlib.remote import (
48
55
    RemoteBranch,
49
56
    RemoteBranchFormat,
52
59
    RemoteRepository,
53
60
    RemoteRepositoryFormat,
54
61
    )
55
 
from bzrlib.repofmt import groupcompress_repo, pack_repo
56
 
from bzrlib.revision import NULL_REVISION
57
 
from bzrlib.smart import medium
 
62
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
 
63
from bzrlib.revision import (
 
64
    NULL_REVISION,
 
65
    Revision,
 
66
    )
 
67
from bzrlib.smart import medium, request
58
68
from bzrlib.smart.client import _SmartClient
59
 
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
 
69
from bzrlib.smart.repository import (
 
70
    SmartServerRepositoryGetParentMap,
 
71
    SmartServerRepositoryGetStream_1_19,
 
72
    _stream_to_byte_stream,
 
73
    )
 
74
from bzrlib.symbol_versioning import deprecated_in
60
75
from bzrlib.tests import (
61
 
    condition_isinstance,
62
 
    split_suite_by_condition,
63
 
    multiply_tests,
64
76
    test_server,
65
77
    )
66
 
from bzrlib.transport import get_transport
 
78
from bzrlib.tests.scenarios import load_tests_apply_scenarios
67
79
from bzrlib.transport.memory import MemoryTransport
68
80
from bzrlib.transport.remote import (
69
81
    RemoteTransport,
70
82
    RemoteSSHTransport,
71
83
    RemoteTCPTransport,
72
 
)
73
 
 
74
 
def load_tests(standard_tests, module, loader):
75
 
    to_adapt, result = split_suite_by_condition(
76
 
        standard_tests, condition_isinstance(BasicRemoteObjectTests))
77
 
    smart_server_version_scenarios = [
 
84
    )
 
85
 
 
86
 
 
87
load_tests = load_tests_apply_scenarios
 
88
 
 
89
 
 
90
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
 
91
 
 
92
    scenarios = [
78
93
        ('HPSS-v2',
79
 
         {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
 
94
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
80
95
        ('HPSS-v3',
81
 
         {'transport_server': test_server.SmartTCPServer_for_testing})]
82
 
    return multiply_tests(to_adapt, smart_server_version_scenarios, result)
83
 
 
84
 
 
85
 
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
 
96
            {'transport_server': test_server.SmartTCPServer_for_testing})]
 
97
 
86
98
 
87
99
    def setUp(self):
88
100
        super(BasicRemoteObjectTests, self).setUp()
89
101
        self.transport = self.get_transport()
90
102
        # make a branch that can be opened over the smart transport
91
103
        self.local_wt = BzrDir.create_standalone_workingtree('.')
92
 
 
93
 
    def tearDown(self):
94
 
        self.transport.disconnect()
95
 
        tests.TestCaseWithTransport.tearDown(self)
 
104
        self.addCleanup(self.transport.disconnect)
96
105
 
97
106
    def test_create_remote_bzrdir(self):
98
 
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
 
107
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
99
108
        self.assertIsInstance(b, BzrDir)
100
109
 
101
110
    def test_open_remote_branch(self):
102
111
        # open a standalone branch in the working directory
103
 
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
 
112
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
104
113
        branch = b.open_branch()
105
114
        self.assertIsInstance(branch, Branch)
106
115
 
114
123
 
115
124
    def test_remote_branch_revision_history(self):
116
125
        b = BzrDir.open_from_transport(self.transport).open_branch()
117
 
        self.assertEqual([], b.revision_history())
 
126
        self.assertEqual([],
 
127
            self.applyDeprecated(deprecated_in((2, 5, 0)), b.revision_history))
118
128
        r1 = self.local_wt.commit('1st commit')
119
129
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8'.encode('utf8'))
120
 
        self.assertEqual([r1, r2], b.revision_history())
 
130
        self.assertEqual([r1, r2],
 
131
            self.applyDeprecated(deprecated_in((2, 5, 0)), b.revision_history))
121
132
 
122
133
    def test_find_correct_format(self):
123
134
        """Should open a RemoteBzrDir over a RemoteTransport"""
124
135
        fmt = BzrDirFormat.find_format(self.transport)
125
 
        self.assertTrue(RemoteBzrDirFormat
126
 
                        in BzrDirFormat._control_server_formats)
127
 
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
 
136
        self.assertTrue(bzrdir.RemoteBzrProber
 
137
                        in controldir.ControlDirFormat._server_probers)
 
138
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
128
139
 
129
140
    def test_open_detected_smart_format(self):
130
141
        fmt = BzrDirFormat.find_format(self.transport)
359
370
        a given client_base and transport_base.
360
371
        """
361
372
        client_medium = medium.SmartClientMedium(client_base)
362
 
        transport = get_transport(transport_base)
363
 
        result = client_medium.remote_path_from_transport(transport)
 
373
        t = transport.get_transport(transport_base)
 
374
        result = client_medium.remote_path_from_transport(t)
364
375
        self.assertEqual(expected, result)
365
376
 
366
377
    def test_remote_path_from_transport(self):
377
388
        a given transport_base and relpath of that transport.  (Note that
378
389
        HttpTransportBase is a subclass of SmartClientMedium)
379
390
        """
380
 
        base_transport = get_transport(transport_base)
 
391
        base_transport = transport.get_transport(transport_base)
381
392
        client_medium = base_transport.get_smart_medium()
382
393
        cloned_transport = base_transport.clone(relpath)
383
394
        result = client_medium.remote_path_from_transport(cloned_transport)
450
461
        client.add_expected_call(
451
462
            'BzrDir.open_branchV3', ('quack/',),
452
463
            'success', ('ref', self.get_url('referenced'))),
453
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
464
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
454
465
            _client=client)
455
466
        result = a_bzrdir.cloning_metadir()
456
467
        # We should have got a control dir matching the referenced branch.
469
480
        client.add_expected_call(
470
481
            'BzrDir.cloning_metadir', ('quack/', 'False'),
471
482
            'success', (control_name, '', ('branch', ''))),
472
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
483
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
473
484
            _client=client)
474
485
        result = a_bzrdir.cloning_metadir()
475
486
        # We should have got a reference control dir with default branch and
480
491
        self.assertEqual(None, result._branch_format)
481
492
        self.assertFinished(client)
482
493
 
 
494
    def test_unknown(self):
 
495
        transport = self.get_transport('quack')
 
496
        referenced = self.make_branch('referenced')
 
497
        expected = referenced.bzrdir.cloning_metadir()
 
498
        client = FakeClient(transport.base)
 
499
        client.add_expected_call(
 
500
            'BzrDir.cloning_metadir', ('quack/', 'False'),
 
501
            'success', ('unknown', 'unknown', ('branch', ''))),
 
502
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
503
            _client=client)
 
504
        self.assertRaises(errors.UnknownFormatError, a_bzrdir.cloning_metadir)
 
505
 
 
506
 
 
507
class TestBzrDirCheckoutMetaDir(TestRemote):
 
508
 
 
509
    def test__get_checkout_format(self):
 
510
        transport = MemoryTransport()
 
511
        client = FakeClient(transport.base)
 
512
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
513
        control_name = reference_bzrdir_format.network_name()
 
514
        client.add_expected_call(
 
515
            'BzrDir.checkout_metadir', ('quack/', ),
 
516
            'success', (control_name, '', ''))
 
517
        transport.mkdir('quack')
 
518
        transport = transport.clone('quack')
 
519
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
520
            _client=client)
 
521
        result = a_bzrdir.checkout_metadir()
 
522
        # We should have got a reference control dir with default branch and
 
523
        # repository formats.
 
524
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
 
525
        self.assertEqual(None, result._repository_format)
 
526
        self.assertEqual(None, result._branch_format)
 
527
        self.assertFinished(client)
 
528
 
 
529
    def test_unknown_format(self):
 
530
        transport = MemoryTransport()
 
531
        client = FakeClient(transport.base)
 
532
        client.add_expected_call(
 
533
            'BzrDir.checkout_metadir', ('quack/',),
 
534
            'success', ('dontknow', '', ''))
 
535
        transport.mkdir('quack')
 
536
        transport = transport.clone('quack')
 
537
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
538
            _client=client)
 
539
        self.assertRaises(errors.UnknownFormatError,
 
540
            a_bzrdir.checkout_metadir)
 
541
        self.assertFinished(client)
 
542
 
 
543
 
 
544
class TestBzrDirDestroyBranch(TestRemote):
 
545
 
 
546
    def test_destroy_default(self):
 
547
        transport = self.get_transport('quack')
 
548
        referenced = self.make_branch('referenced')
 
549
        client = FakeClient(transport.base)
 
550
        client.add_expected_call(
 
551
            'BzrDir.destroy_branch', ('quack/', ),
 
552
            'success', ('ok',)),
 
553
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
554
            _client=client)
 
555
        a_bzrdir.destroy_branch()
 
556
        self.assertFinished(client)
 
557
 
 
558
    def test_destroy_named(self):
 
559
        transport = self.get_transport('quack')
 
560
        referenced = self.make_branch('referenced')
 
561
        client = FakeClient(transport.base)
 
562
        client.add_expected_call(
 
563
            'BzrDir.destroy_branch', ('quack/', "foo"),
 
564
            'success', ('ok',)),
 
565
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
566
            _client=client)
 
567
        a_bzrdir.destroy_branch("foo")
 
568
        self.assertFinished(client)
 
569
 
 
570
 
 
571
class TestBzrDirHasWorkingTree(TestRemote):
 
572
 
 
573
    def test_has_workingtree(self):
 
574
        transport = self.get_transport('quack')
 
575
        client = FakeClient(transport.base)
 
576
        client.add_expected_call(
 
577
            'BzrDir.has_workingtree', ('quack/',),
 
578
            'success', ('yes',)),
 
579
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
580
            _client=client)
 
581
        self.assertTrue(a_bzrdir.has_workingtree())
 
582
        self.assertFinished(client)
 
583
 
 
584
    def test_no_workingtree(self):
 
585
        transport = self.get_transport('quack')
 
586
        client = FakeClient(transport.base)
 
587
        client.add_expected_call(
 
588
            'BzrDir.has_workingtree', ('quack/',),
 
589
            'success', ('no',)),
 
590
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
591
            _client=client)
 
592
        self.assertFalse(a_bzrdir.has_workingtree())
 
593
        self.assertFinished(client)
 
594
 
 
595
 
 
596
class TestBzrDirDestroyRepository(TestRemote):
 
597
 
 
598
    def test_destroy_repository(self):
 
599
        transport = self.get_transport('quack')
 
600
        client = FakeClient(transport.base)
 
601
        client.add_expected_call(
 
602
            'BzrDir.destroy_repository', ('quack/',),
 
603
            'success', ('ok',)),
 
604
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
605
            _client=client)
 
606
        a_bzrdir.destroy_repository()
 
607
        self.assertFinished(client)
 
608
 
483
609
 
484
610
class TestBzrDirOpen(TestRemote):
485
611
 
495
621
        client.add_expected_call(
496
622
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
497
623
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
498
 
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
624
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
499
625
        self.assertFinished(client)
500
626
 
501
627
    def test_present_without_workingtree(self):
502
628
        client, transport = self.make_fake_client_and_transport()
503
629
        client.add_expected_call(
504
630
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
505
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
631
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
506
632
            _client=client, _force_probe=True)
507
633
        self.assertIsInstance(bd, RemoteBzrDir)
508
634
        self.assertFalse(bd.has_workingtree())
513
639
        client, transport = self.make_fake_client_and_transport()
514
640
        client.add_expected_call(
515
641
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
516
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
642
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
517
643
            _client=client, _force_probe=True)
518
644
        self.assertIsInstance(bd, RemoteBzrDir)
519
645
        self.assertTrue(bd.has_workingtree())
526
652
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
527
653
        client.add_expected_call(
528
654
            'BzrDir.open', ('quack/',), 'success', ('yes',))
529
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
655
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
530
656
            _client=client, _force_probe=True)
531
657
        self.assertIsInstance(bd, RemoteBzrDir)
532
658
        self.assertFinished(client)
548
674
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
549
675
        client.add_expected_call(
550
676
            'BzrDir.open', ('quack/',), 'success', ('yes',))
551
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
677
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
552
678
            _client=client, _force_probe=True)
553
679
        self.assertIsInstance(bd, RemoteBzrDir)
554
680
        self.assertFinished(client)
585
711
        client.add_expected_call(
586
712
            'Branch.get_stacked_on_url', ('quack/',),
587
713
            'error', ('NotStacked',))
588
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
714
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
589
715
            _client=client)
590
716
        result = bzrdir.open_branch()
591
717
        self.assertIsInstance(result, RemoteBranch)
598
724
        transport = transport.clone('quack')
599
725
        client = FakeClient(transport.base)
600
726
        client.add_error_response('nobranch')
601
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
727
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
602
728
            _client=client)
603
729
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
604
730
        self.assertEqual(
609
735
        # _get_tree_branch is a form of open_branch, but it should only ask for
610
736
        # branch opening, not any other network requests.
611
737
        calls = []
612
 
        def open_branch():
 
738
        def open_branch(name=None, possible_transports=None):
613
739
            calls.append("Called")
614
740
            return "a-branch"
615
741
        transport = MemoryTransport()
616
742
        # no requests on the network - catches other api calls being made.
617
743
        client = FakeClient(transport.base)
618
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
744
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
619
745
            _client=client)
620
746
        # patch the open_branch call to record that it was called.
621
747
        bzrdir.open_branch = open_branch
640
766
        client.add_expected_call(
641
767
            'Branch.get_stacked_on_url', ('~hello/',),
642
768
            'error', ('NotStacked',))
643
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
769
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
644
770
            _client=client)
645
771
        result = bzrdir.open_branch()
646
772
        self.assertFinished(client)
663
789
        client.add_success_response(
664
790
            'ok', '', rich_response, subtree_response, external_lookup,
665
791
            network_name)
666
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
792
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
667
793
            _client=client)
668
794
        result = bzrdir.open_repository()
669
795
        self.assertEqual(
686
812
        old.
687
813
        """
688
814
        self.assertRaises(errors.NotBranchError,
689
 
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
 
815
            RemoteBzrProber.probe_transport, OldServerTransport())
690
816
 
691
817
 
692
818
class TestBzrDirCreateBranch(TestRemote):
715
841
            'BzrDir.create_branch', ('quack/', network_name),
716
842
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
717
843
            reference_repo_name))
718
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
844
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
719
845
            _client=client)
720
846
        branch = a_bzrdir.create_branch()
721
847
        # We should have got a remote branch
724
850
        format = branch._format
725
851
        self.assertEqual(network_name, format.network_name())
726
852
 
 
853
    def test_already_open_repo_and_reused_medium(self):
 
854
        """Bug 726584: create_branch(..., repository=repo) should work
 
855
        regardless of what the smart medium's base URL is.
 
856
        """
 
857
        self.transport_server = test_server.SmartTCPServer_for_testing
 
858
        transport = self.get_transport('.')
 
859
        repo = self.make_repository('quack')
 
860
        # Client's medium rooted a transport root (not at the bzrdir)
 
861
        client = FakeClient(transport.base)
 
862
        transport = transport.clone('quack')
 
863
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
864
        reference_format = reference_bzrdir_format.get_branch_format()
 
865
        network_name = reference_format.network_name()
 
866
        reference_repo_fmt = reference_bzrdir_format.repository_format
 
867
        reference_repo_name = reference_repo_fmt.network_name()
 
868
        client.add_expected_call(
 
869
            'BzrDir.create_branch', ('extra/quack/', network_name),
 
870
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
 
871
            reference_repo_name))
 
872
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
873
            _client=client)
 
874
        branch = a_bzrdir.create_branch(repository=repo)
 
875
        # We should have got a remote branch
 
876
        self.assertIsInstance(branch, remote.RemoteBranch)
 
877
        # its format should have the settings from the response
 
878
        format = branch._format
 
879
        self.assertEqual(network_name, format.network_name())
 
880
 
727
881
 
728
882
class TestBzrDirCreateRepository(TestRemote):
729
883
 
750
904
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
751
905
                'False'),
752
906
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
753
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
907
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
754
908
            _client=client)
755
909
        repo = a_bzrdir.create_repository()
756
910
        # We should have got a remote repository
785
939
        client.add_success_response('stat', '0', '65535')
786
940
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
787
941
            _client=client)
788
 
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
 
942
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
789
943
            _client=client)
790
944
        repo = bzrdir.open_repository()
791
945
        self.assertEqual(
818
972
        client.add_success_response('stat', '0', '65535')
819
973
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
820
974
            _client=client)
821
 
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
 
975
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
822
976
            _client=client)
823
977
        repo = bzrdir.open_repository()
824
978
        self.assertEqual(
839
993
        transport = transport.clone('quack')
840
994
        client = FakeClient(transport.base)
841
995
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
842
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
996
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
843
997
            _client=client)
844
998
        repo = bzrdir.open_repository()
845
999
        self.assertEqual(
852
1006
 
853
1007
    def test_success(self):
854
1008
        """Simple test for typical successful call."""
855
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
1009
        fmt = RemoteBzrDirFormat()
856
1010
        default_format_name = BzrDirFormat.get_default_format().network_name()
857
1011
        transport = self.get_transport()
858
1012
        client = FakeClient(transport.base)
874
1028
        """Error responses are translated, e.g. 'PermissionDenied' raises the
875
1029
        corresponding error from the client.
876
1030
        """
877
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
1031
        fmt = RemoteBzrDirFormat()
878
1032
        default_format_name = BzrDirFormat.get_default_format().network_name()
879
1033
        transport = self.get_transport()
880
1034
        client = FakeClient(transport.base)
898
1052
        """Integration test for error translation."""
899
1053
        transport = self.make_smart_server('foo')
900
1054
        transport = transport.clone('no-such-path')
901
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
1055
        fmt = RemoteBzrDirFormat()
902
1056
        err = self.assertRaises(errors.NoSuchFile,
903
1057
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
904
1058
 
935
1089
 
936
1090
    def make_remote_bzrdir(self, transport, client):
937
1091
        """Make a RemotebzrDir using 'client' as the _client."""
938
 
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1092
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
939
1093
            _client=client)
940
1094
 
941
1095
 
967
1121
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
968
1122
 
969
1123
 
 
1124
class TestBranchBreakLock(RemoteBranchTestCase):
 
1125
 
 
1126
    def test_break_lock(self):
 
1127
        transport_path = 'quack'
 
1128
        transport = MemoryTransport()
 
1129
        client = FakeClient(transport.base)
 
1130
        client.add_expected_call(
 
1131
            'Branch.get_stacked_on_url', ('quack/',),
 
1132
            'error', ('NotStacked',))
 
1133
        client.add_expected_call(
 
1134
            'Branch.break_lock', ('quack/',),
 
1135
            'success', ('ok',))
 
1136
        transport.mkdir('quack')
 
1137
        transport = transport.clone('quack')
 
1138
        branch = self.make_remote_branch(transport, client)
 
1139
        branch.break_lock()
 
1140
        self.assertFinished(client)
 
1141
 
 
1142
 
 
1143
class TestBranchGetPhysicalLockStatus(RemoteBranchTestCase):
 
1144
 
 
1145
    def test_get_physical_lock_status_yes(self):
 
1146
        transport = MemoryTransport()
 
1147
        client = FakeClient(transport.base)
 
1148
        client.add_expected_call(
 
1149
            'Branch.get_stacked_on_url', ('quack/',),
 
1150
            'error', ('NotStacked',))
 
1151
        client.add_expected_call(
 
1152
            'Branch.get_physical_lock_status', ('quack/',),
 
1153
            'success', ('yes',))
 
1154
        transport.mkdir('quack')
 
1155
        transport = transport.clone('quack')
 
1156
        branch = self.make_remote_branch(transport, client)
 
1157
        result = branch.get_physical_lock_status()
 
1158
        self.assertFinished(client)
 
1159
        self.assertEqual(True, result)
 
1160
 
 
1161
    def test_get_physical_lock_status_no(self):
 
1162
        transport = MemoryTransport()
 
1163
        client = FakeClient(transport.base)
 
1164
        client.add_expected_call(
 
1165
            'Branch.get_stacked_on_url', ('quack/',),
 
1166
            'error', ('NotStacked',))
 
1167
        client.add_expected_call(
 
1168
            'Branch.get_physical_lock_status', ('quack/',),
 
1169
            'success', ('no',))
 
1170
        transport.mkdir('quack')
 
1171
        transport = transport.clone('quack')
 
1172
        branch = self.make_remote_branch(transport, client)
 
1173
        result = branch.get_physical_lock_status()
 
1174
        self.assertFinished(client)
 
1175
        self.assertEqual(False, result)
 
1176
 
 
1177
 
970
1178
class TestBranchGetParent(RemoteBranchTestCase):
971
1179
 
972
1180
    def test_no_parent(self):
1143
1351
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1144
1352
 
1145
1353
 
 
1354
class TestBranchHeadsToFetch(RemoteBranchTestCase):
 
1355
 
 
1356
    def test_uses_last_revision_info_and_tags_by_default(self):
 
1357
        transport = MemoryTransport()
 
1358
        client = FakeClient(transport.base)
 
1359
        client.add_expected_call(
 
1360
            'Branch.get_stacked_on_url', ('quack/',),
 
1361
            'error', ('NotStacked',))
 
1362
        client.add_expected_call(
 
1363
            'Branch.last_revision_info', ('quack/',),
 
1364
            'success', ('ok', '1', 'rev-tip'))
 
1365
        client.add_expected_call(
 
1366
            'Branch.get_config_file', ('quack/',),
 
1367
            'success', ('ok',), '')
 
1368
        transport.mkdir('quack')
 
1369
        transport = transport.clone('quack')
 
1370
        branch = self.make_remote_branch(transport, client)
 
1371
        result = branch.heads_to_fetch()
 
1372
        self.assertFinished(client)
 
1373
        self.assertEqual((set(['rev-tip']), set()), result)
 
1374
 
 
1375
    def test_uses_last_revision_info_and_tags_when_set(self):
 
1376
        transport = MemoryTransport()
 
1377
        client = FakeClient(transport.base)
 
1378
        client.add_expected_call(
 
1379
            'Branch.get_stacked_on_url', ('quack/',),
 
1380
            'error', ('NotStacked',))
 
1381
        client.add_expected_call(
 
1382
            'Branch.last_revision_info', ('quack/',),
 
1383
            'success', ('ok', '1', 'rev-tip'))
 
1384
        client.add_expected_call(
 
1385
            'Branch.get_config_file', ('quack/',),
 
1386
            'success', ('ok',), 'branch.fetch_tags = True')
 
1387
        # XXX: this will break if the default format's serialization of tags
 
1388
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
 
1389
        client.add_expected_call(
 
1390
            'Branch.get_tags_bytes', ('quack/',),
 
1391
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
 
1392
        transport.mkdir('quack')
 
1393
        transport = transport.clone('quack')
 
1394
        branch = self.make_remote_branch(transport, client)
 
1395
        result = branch.heads_to_fetch()
 
1396
        self.assertFinished(client)
 
1397
        self.assertEqual(
 
1398
            (set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
 
1399
 
 
1400
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
 
1401
        transport = MemoryTransport()
 
1402
        client = FakeClient(transport.base)
 
1403
        client.add_expected_call(
 
1404
            'Branch.get_stacked_on_url', ('quack/',),
 
1405
            'error', ('NotStacked',))
 
1406
        client.add_expected_call(
 
1407
            'Branch.heads_to_fetch', ('quack/',),
 
1408
            'success', (['tip'], ['tagged-1', 'tagged-2']))
 
1409
        transport.mkdir('quack')
 
1410
        transport = transport.clone('quack')
 
1411
        branch = self.make_remote_branch(transport, client)
 
1412
        branch._format._use_default_local_heads_to_fetch = lambda: False
 
1413
        result = branch.heads_to_fetch()
 
1414
        self.assertFinished(client)
 
1415
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
 
1416
 
 
1417
    def make_branch_with_tags(self):
 
1418
        self.setup_smart_server_with_call_log()
 
1419
        # Make a branch with a single revision.
 
1420
        builder = self.make_branch_builder('foo')
 
1421
        builder.start_series()
 
1422
        builder.build_snapshot('tip', None, [
 
1423
            ('add', ('', 'root-id', 'directory', ''))])
 
1424
        builder.finish_series()
 
1425
        branch = builder.get_branch()
 
1426
        # Add two tags to that branch
 
1427
        branch.tags.set_tag('tag-1', 'rev-1')
 
1428
        branch.tags.set_tag('tag-2', 'rev-2')
 
1429
        return branch
 
1430
 
 
1431
    def test_backwards_compatible(self):
 
1432
        branch = self.make_branch_with_tags()
 
1433
        c = branch.get_config()
 
1434
        c.set_user_option('branch.fetch_tags', 'True')
 
1435
        self.addCleanup(branch.lock_read().unlock)
 
1436
        # Disable the heads_to_fetch verb
 
1437
        verb = 'Branch.heads_to_fetch'
 
1438
        self.disable_verb(verb)
 
1439
        self.reset_smart_call_log()
 
1440
        result = branch.heads_to_fetch()
 
1441
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
 
1442
        self.assertEqual(
 
1443
            ['Branch.last_revision_info', 'Branch.get_config_file',
 
1444
             'Branch.get_tags_bytes'],
 
1445
            [call.call.method for call in self.hpss_calls])
 
1446
 
 
1447
    def test_backwards_compatible_no_tags(self):
 
1448
        branch = self.make_branch_with_tags()
 
1449
        c = branch.get_config()
 
1450
        c.set_user_option('branch.fetch_tags', 'False')
 
1451
        self.addCleanup(branch.lock_read().unlock)
 
1452
        # Disable the heads_to_fetch verb
 
1453
        verb = 'Branch.heads_to_fetch'
 
1454
        self.disable_verb(verb)
 
1455
        self.reset_smart_call_log()
 
1456
        result = branch.heads_to_fetch()
 
1457
        self.assertEqual((set(['tip']), set()), result)
 
1458
        self.assertEqual(
 
1459
            ['Branch.last_revision_info', 'Branch.get_config_file'],
 
1460
            [call.call.method for call in self.hpss_calls])
 
1461
 
 
1462
 
1146
1463
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1147
1464
 
1148
1465
    def test_empty_branch(self):
1203
1520
        client.add_expected_call(
1204
1521
            'Branch.get_stacked_on_url', ('stacked/',),
1205
1522
            'success', ('ok', vfs_url))
1206
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1523
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1207
1524
            _client=client)
1208
1525
        repo_fmt = remote.RemoteRepositoryFormat()
1209
1526
        repo_fmt._custom_format = stacked_branch.repository._format
1236
1553
        # this will also do vfs access, but that goes direct to the transport
1237
1554
        # and isn't seen by the FakeClient.
1238
1555
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1239
 
            remote.RemoteBzrDirFormat(), _client=client)
 
1556
            RemoteBzrDirFormat(), _client=client)
1240
1557
        branch = bzrdir.open_branch()
1241
1558
        result = branch.get_stacked_on_url()
1242
1559
        self.assertEqual('../base', result)
1269
1586
            'Branch.get_stacked_on_url', ('stacked/',),
1270
1587
            'success', ('ok', '../base'))
1271
1588
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1272
 
            remote.RemoteBzrDirFormat(), _client=client)
 
1589
            RemoteBzrDirFormat(), _client=client)
1273
1590
        branch = bzrdir.open_branch()
1274
1591
        result = branch.get_stacked_on_url()
1275
1592
        self.assertEqual('../base', result)
1283
1600
class TestBranchSetLastRevision(RemoteBranchTestCase):
1284
1601
 
1285
1602
    def test_set_empty(self):
1286
 
        # set_revision_history([]) is translated to calling
 
1603
        # _set_last_revision_info('null:') is translated to calling
1287
1604
        # Branch.set_last_revision(path, '') on the wire.
1288
1605
        transport = MemoryTransport()
1289
1606
        transport.mkdir('branch')
1307
1624
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1308
1625
            'success', ('ok',))
1309
1626
        branch = self.make_remote_branch(transport, client)
1310
 
        # This is a hack to work around the problem that RemoteBranch currently
1311
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1312
 
        branch._ensure_real = lambda: None
1313
1627
        branch.lock_write()
1314
 
        result = branch.set_revision_history([])
 
1628
        result = branch._set_last_revision(NULL_REVISION)
1315
1629
        branch.unlock()
1316
1630
        self.assertEqual(None, result)
1317
1631
        self.assertFinished(client)
1318
1632
 
1319
1633
    def test_set_nonempty(self):
1320
 
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
 
1634
        # set_last_revision_info(N, rev-idN) is translated to calling
1321
1635
        # Branch.set_last_revision(path, rev-idN) on the wire.
1322
1636
        transport = MemoryTransport()
1323
1637
        transport.mkdir('branch')
1344
1658
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1345
1659
            'success', ('ok',))
1346
1660
        branch = self.make_remote_branch(transport, client)
1347
 
        # This is a hack to work around the problem that RemoteBranch currently
1348
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1349
 
        branch._ensure_real = lambda: None
1350
1661
        # Lock the branch, reset the record of remote calls.
1351
1662
        branch.lock_write()
1352
 
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
 
1663
        result = branch._set_last_revision('rev-id2')
1353
1664
        branch.unlock()
1354
1665
        self.assertEqual(None, result)
1355
1666
        self.assertFinished(client)
1385
1696
        branch = self.make_remote_branch(transport, client)
1386
1697
        branch.lock_write()
1387
1698
        self.assertRaises(
1388
 
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
 
1699
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
1389
1700
        branch.unlock()
1390
1701
        self.assertFinished(client)
1391
1702
 
1419
1730
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1420
1731
            'success', ('ok',))
1421
1732
        branch = self.make_remote_branch(transport, client)
1422
 
        branch._ensure_real = lambda: None
1423
1733
        branch.lock_write()
1424
1734
        # The 'TipChangeRejected' error response triggered by calling
1425
 
        # set_revision_history causes a TipChangeRejected exception.
 
1735
        # set_last_revision_info causes a TipChangeRejected exception.
1426
1736
        err = self.assertRaises(
1427
 
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
 
1737
            errors.TipChangeRejected,
 
1738
            branch._set_last_revision, 'rev-id')
1428
1739
        # The UTF-8 message from the response has been decoded into a unicode
1429
1740
        # object.
1430
1741
        self.assertIsInstance(err.msg, unicode)
1618
1929
    def test_get_multi_line_branch_conf(self):
1619
1930
        # Make sure that multiple-line branch.conf files are supported
1620
1931
        #
1621
 
        # https://bugs.edge.launchpad.net/bzr/+bug/354075
 
1932
        # https://bugs.launchpad.net/bzr/+bug/354075
1622
1933
        client = FakeClient()
1623
1934
        client.add_expected_call(
1624
1935
            'Branch.get_stacked_on_url', ('memory:///',),
1652
1963
        branch.unlock()
1653
1964
        self.assertFinished(client)
1654
1965
 
 
1966
    def test_set_option_with_dict(self):
 
1967
        client = FakeClient()
 
1968
        client.add_expected_call(
 
1969
            'Branch.get_stacked_on_url', ('memory:///',),
 
1970
            'error', ('NotStacked',),)
 
1971
        client.add_expected_call(
 
1972
            'Branch.lock_write', ('memory:///', '', ''),
 
1973
            'success', ('ok', 'branch token', 'repo token'))
 
1974
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
 
1975
        client.add_expected_call(
 
1976
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
 
1977
            'repo token', encoded_dict_value, 'foo', ''),
 
1978
            'success', ())
 
1979
        client.add_expected_call(
 
1980
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
1981
            'success', ('ok',))
 
1982
        transport = MemoryTransport()
 
1983
        branch = self.make_remote_branch(transport, client)
 
1984
        branch.lock_write()
 
1985
        config = branch._get_config()
 
1986
        config.set_option(
 
1987
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
 
1988
            'foo')
 
1989
        branch.unlock()
 
1990
        self.assertFinished(client)
 
1991
 
1655
1992
    def test_backwards_compat_set_option(self):
1656
1993
        self.setup_smart_server_with_call_log()
1657
1994
        branch = self.make_branch('.')
1664
2001
        self.assertLength(10, self.hpss_calls)
1665
2002
        self.assertEqual('value', branch._get_config().get_option('name'))
1666
2003
 
 
2004
    def test_backwards_compat_set_option_with_dict(self):
 
2005
        self.setup_smart_server_with_call_log()
 
2006
        branch = self.make_branch('.')
 
2007
        verb = 'Branch.set_config_option_dict'
 
2008
        self.disable_verb(verb)
 
2009
        branch.lock_write()
 
2010
        self.addCleanup(branch.unlock)
 
2011
        self.reset_smart_call_log()
 
2012
        config = branch._get_config()
 
2013
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
2014
        config.set_option(value_dict, 'name')
 
2015
        self.assertLength(10, self.hpss_calls)
 
2016
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
 
2017
 
 
2018
 
 
2019
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
 
2020
 
 
2021
    def test_get_branch_conf(self):
 
2022
        # in an empty branch we decode the response properly
 
2023
        client = FakeClient()
 
2024
        client.add_expected_call(
 
2025
            'Branch.get_stacked_on_url', ('memory:///',),
 
2026
            'error', ('NotStacked',),)
 
2027
        client.add_success_response_with_body('# config file body', 'ok')
 
2028
        transport = MemoryTransport()
 
2029
        branch = self.make_remote_branch(transport, client)
 
2030
        config = branch.get_config_stack()
 
2031
        config.get("email")
 
2032
        config.get("log_format")
 
2033
        self.assertEqual(
 
2034
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2035
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
 
2036
            client._calls)
 
2037
 
 
2038
    def test_set_branch_conf(self):
 
2039
        client = FakeClient()
 
2040
        client.add_expected_call(
 
2041
            'Branch.get_stacked_on_url', ('memory:///',),
 
2042
            'error', ('NotStacked',),)
 
2043
        client.add_expected_call(
 
2044
            'Branch.lock_write', ('memory:///', '', ''),
 
2045
            'success', ('ok', 'branch token', 'repo token'))
 
2046
        client.add_expected_call(
 
2047
            'Branch.get_config_file', ('memory:///', ),
 
2048
            'success', ('ok', ), "# line 1\n")
 
2049
        client.add_expected_call(
 
2050
            'Branch.put_config_file', ('memory:///', 'branch token',
 
2051
            'repo token'),
 
2052
            'success', ('ok',))
 
2053
        client.add_expected_call(
 
2054
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
2055
            'success', ('ok',))
 
2056
        transport = MemoryTransport()
 
2057
        branch = self.make_remote_branch(transport, client)
 
2058
        branch.lock_write()
 
2059
        config = branch.get_config_stack()
 
2060
        config.set('email', 'The Dude <lebowski@example.com>')
 
2061
        branch.unlock()
 
2062
        self.assertFinished(client)
 
2063
        self.assertEqual(
 
2064
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2065
             ('call', 'Branch.lock_write', ('memory:///', '', '')),
 
2066
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
 
2067
             ('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
 
2068
                 ('memory:///', 'branch token', 'repo token'),
 
2069
                 '# line 1\nemail = The Dude <lebowski@example.com>\n'),
 
2070
             ('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
 
2071
            client._calls)
 
2072
 
1667
2073
 
1668
2074
class TestBranchLockWrite(RemoteBranchTestCase):
1669
2075
 
1683
2089
        self.assertFinished(client)
1684
2090
 
1685
2091
 
 
2092
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
 
2093
 
 
2094
    def test_simple(self):
 
2095
        transport = MemoryTransport()
 
2096
        client = FakeClient(transport.base)
 
2097
        client.add_expected_call(
 
2098
            'Branch.get_stacked_on_url', ('quack/',),
 
2099
            'error', ('NotStacked',),)
 
2100
        client.add_expected_call(
 
2101
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2102
            'success', ('ok', '0',),)
 
2103
        client.add_expected_call(
 
2104
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2105
            'error', ('NoSuchRevision', 'unknown',),)
 
2106
        transport.mkdir('quack')
 
2107
        transport = transport.clone('quack')
 
2108
        branch = self.make_remote_branch(transport, client)
 
2109
        self.assertEquals(0, branch.revision_id_to_revno('null:'))
 
2110
        self.assertRaises(errors.NoSuchRevision,
 
2111
            branch.revision_id_to_revno, 'unknown')
 
2112
        self.assertFinished(client)
 
2113
 
 
2114
    def test_dotted(self):
 
2115
        transport = MemoryTransport()
 
2116
        client = FakeClient(transport.base)
 
2117
        client.add_expected_call(
 
2118
            'Branch.get_stacked_on_url', ('quack/',),
 
2119
            'error', ('NotStacked',),)
 
2120
        client.add_expected_call(
 
2121
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2122
            'success', ('ok', '0',),)
 
2123
        client.add_expected_call(
 
2124
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2125
            'error', ('NoSuchRevision', 'unknown',),)
 
2126
        transport.mkdir('quack')
 
2127
        transport = transport.clone('quack')
 
2128
        branch = self.make_remote_branch(transport, client)
 
2129
        self.assertEquals((0, ), branch.revision_id_to_dotted_revno('null:'))
 
2130
        self.assertRaises(errors.NoSuchRevision,
 
2131
            branch.revision_id_to_dotted_revno, 'unknown')
 
2132
        self.assertFinished(client)
 
2133
 
 
2134
    def test_dotted_no_smart_verb(self):
 
2135
        self.setup_smart_server_with_call_log()
 
2136
        branch = self.make_branch('.')
 
2137
        self.disable_verb('Branch.revision_id_to_revno')
 
2138
        self.reset_smart_call_log()
 
2139
        self.assertEquals((0, ),
 
2140
            branch.revision_id_to_dotted_revno('null:'))
 
2141
        self.assertLength(7, self.hpss_calls)
 
2142
 
 
2143
 
1686
2144
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1687
2145
 
1688
2146
    def test__get_config(self):
1805
2263
        client = FakeClient(transport.base)
1806
2264
        transport = transport.clone(transport_path)
1807
2265
        # we do not want bzrdir to make any remote calls
1808
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
2266
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1809
2267
            _client=False)
1810
2268
        repo = RemoteRepository(bzrdir, None, _client=client)
1811
2269
        return repo, client
1819
2277
 
1820
2278
    def test_get_format_description(self):
1821
2279
        remote_format = RemoteBranchFormat()
1822
 
        real_format = branch.BranchFormat.get_default_format()
 
2280
        real_format = branch.format_registry.get_default()
1823
2281
        remote_format._network_name = real_format.network_name()
1824
2282
        self.assertEqual(remoted_description(real_format),
1825
2283
            remote_format.get_format_description())
1828
2286
class TestRepositoryFormat(TestRemoteRepository):
1829
2287
 
1830
2288
    def test_fast_delta(self):
1831
 
        true_name = groupcompress_repo.RepositoryFormatCHK1().network_name()
 
2289
        true_name = groupcompress_repo.RepositoryFormat2a().network_name()
1832
2290
        true_format = RemoteRepositoryFormat()
1833
2291
        true_format._network_name = true_name
1834
2292
        self.assertEqual(True, true_format.fast_deltas)
1835
 
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
 
2293
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
1836
2294
        false_format = RemoteRepositoryFormat()
1837
2295
        false_format._network_name = false_name
1838
2296
        self.assertEqual(False, false_format.fast_deltas)
1839
2297
 
1840
2298
    def test_get_format_description(self):
1841
2299
        remote_repo_format = RemoteRepositoryFormat()
1842
 
        real_format = repository.RepositoryFormat.get_default_format()
 
2300
        real_format = repository.format_registry.get_default()
1843
2301
        remote_repo_format._network_name = real_format.network_name()
1844
2302
        self.assertEqual(remoted_description(real_format),
1845
2303
            remote_repo_format.get_format_description())
1846
2304
 
1847
2305
 
 
2306
class TestRepositoryAllRevisionIds(TestRemoteRepository):
 
2307
 
 
2308
    def test_empty(self):
 
2309
        transport_path = 'quack'
 
2310
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2311
        client.add_success_response_with_body('', 'ok')
 
2312
        self.assertEquals([], repo.all_revision_ids())
 
2313
        self.assertEqual(
 
2314
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2315
             ('quack/',))],
 
2316
            client._calls)
 
2317
 
 
2318
    def test_with_some_content(self):
 
2319
        transport_path = 'quack'
 
2320
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2321
        client.add_success_response_with_body(
 
2322
            'rev1\nrev2\nanotherrev\n', 'ok')
 
2323
        self.assertEquals(["rev1", "rev2", "anotherrev"],
 
2324
            repo.all_revision_ids())
 
2325
        self.assertEqual(
 
2326
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2327
             ('quack/',))],
 
2328
            client._calls)
 
2329
 
 
2330
 
1848
2331
class TestRepositoryGatherStats(TestRemoteRepository):
1849
2332
 
1850
2333
    def test_revid_none(self):
1903
2386
                         result)
1904
2387
 
1905
2388
 
 
2389
class TestRepositoryBreakLock(TestRemoteRepository):
 
2390
 
 
2391
    def test_break_lock(self):
 
2392
        transport_path = 'quack'
 
2393
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2394
        client.add_success_response('ok')
 
2395
        repo.break_lock()
 
2396
        self.assertEqual(
 
2397
            [('call', 'Repository.break_lock', ('quack/',))],
 
2398
            client._calls)
 
2399
 
 
2400
 
 
2401
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
 
2402
 
 
2403
    def test_get_serializer_format(self):
 
2404
        transport_path = 'hill'
 
2405
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2406
        client.add_success_response('ok', '7')
 
2407
        self.assertEquals('7', repo.get_serializer_format())
 
2408
        self.assertEqual(
 
2409
            [('call', 'VersionedFileRepository.get_serializer_format',
 
2410
              ('hill/', ))],
 
2411
            client._calls)
 
2412
 
 
2413
 
 
2414
class TestRepositoryReconcile(TestRemoteRepository):
 
2415
 
 
2416
    def test_reconcile(self):
 
2417
        transport_path = 'hill'
 
2418
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2419
        body = ("garbage_inventories: 2\n"
 
2420
                "inconsistent_parents: 3\n")
 
2421
        client.add_expected_call(
 
2422
            'Repository.lock_write', ('hill/', ''),
 
2423
            'success', ('ok', 'a token'))
 
2424
        client.add_success_response_with_body(body, 'ok')
 
2425
        reconciler = repo.reconcile()
 
2426
        self.assertEqual(
 
2427
            [('call', 'Repository.lock_write', ('hill/', '')),
 
2428
             ('call_expecting_body', 'Repository.reconcile',
 
2429
                ('hill/', 'a token'))],
 
2430
            client._calls)
 
2431
        self.assertEquals(2, reconciler.garbage_inventories)
 
2432
        self.assertEquals(3, reconciler.inconsistent_parents)
 
2433
 
 
2434
 
 
2435
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
 
2436
 
 
2437
    def test_text(self):
 
2438
        # ('ok',), body with signature text
 
2439
        transport_path = 'quack'
 
2440
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2441
        client.add_success_response_with_body(
 
2442
            'THETEXT', 'ok')
 
2443
        self.assertEquals("THETEXT", repo.get_signature_text("revid"))
 
2444
        self.assertEqual(
 
2445
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2446
             ('quack/', 'revid'))],
 
2447
            client._calls)
 
2448
 
 
2449
    def test_no_signature(self):
 
2450
        transport_path = 'quick'
 
2451
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2452
        client.add_error_response('nosuchrevision', 'unknown')
 
2453
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
 
2454
                "unknown")
 
2455
        self.assertEqual(
 
2456
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2457
              ('quick/', 'unknown'))],
 
2458
            client._calls)
 
2459
 
 
2460
 
1906
2461
class TestRepositoryGetGraph(TestRemoteRepository):
1907
2462
 
1908
2463
    def test_get_graph(self):
1913
2468
        self.assertNotEqual(graph._parents_provider, repo)
1914
2469
 
1915
2470
 
 
2471
class TestRepositoryAddSignatureText(TestRemoteRepository):
 
2472
 
 
2473
    def test_add_signature_text(self):
 
2474
        transport_path = 'quack'
 
2475
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2476
        client.add_expected_call(
 
2477
            'Repository.lock_write', ('quack/', ''),
 
2478
            'success', ('ok', 'a token'))
 
2479
        client.add_expected_call(
 
2480
            'Repository.start_write_group', ('quack/', 'a token'),
 
2481
            'success', ('ok', ('token1', )))
 
2482
        client.add_expected_call(
 
2483
            'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
 
2484
                'token1'),
 
2485
            'success', ('ok', ), None)
 
2486
        repo.lock_write()
 
2487
        repo.start_write_group()
 
2488
        self.assertIs(None,
 
2489
            repo.add_signature_text("rev1", "every bloody emperor"))
 
2490
        self.assertEqual(
 
2491
            ('call_with_body_bytes_expecting_body',
 
2492
              'Repository.add_signature_text',
 
2493
                ('quack/', 'a token', 'rev1', 'token1'),
 
2494
              'every bloody emperor'),
 
2495
            client._calls[-1])
 
2496
 
 
2497
 
1916
2498
class TestRepositoryGetParentMap(TestRemoteRepository):
1917
2499
 
1918
2500
    def test_get_parent_map_caching(self):
1968
2550
        parents = repo.get_parent_map([rev_id])
1969
2551
        self.assertEqual(
1970
2552
            [('call_with_body_bytes_expecting_body',
1971
 
              'Repository.get_parent_map', ('quack/', 'include-missing:',
1972
 
              rev_id), '\n\n0'),
 
2553
              'Repository.get_parent_map',
 
2554
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
1973
2555
             ('disconnect medium',),
1974
2556
             ('call_expecting_body', 'Repository.get_revision_graph',
1975
2557
              ('quack/', ''))],
2095
2677
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2096
2678
        self.assertLength(0, self.hpss_calls)
2097
2679
 
 
2680
    def test_exposes_get_cached_parent_map(self):
 
2681
        """RemoteRepository exposes get_cached_parent_map from
 
2682
        _unstacked_provider
 
2683
        """
 
2684
        r1 = u'\u0e33'.encode('utf8')
 
2685
        r2 = u'\u0dab'.encode('utf8')
 
2686
        lines = [' '.join([r2, r1]), r1]
 
2687
        encoded_body = bz2.compress('\n'.join(lines))
 
2688
 
 
2689
        transport_path = 'quack'
 
2690
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2691
        client.add_success_response_with_body(encoded_body, 'ok')
 
2692
        repo.lock_read()
 
2693
        # get_cached_parent_map should *not* trigger an RPC
 
2694
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
 
2695
        self.assertEqual([], client._calls)
 
2696
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
 
2697
        self.assertEqual({r1: (NULL_REVISION,)},
 
2698
            repo.get_cached_parent_map([r1]))
 
2699
        self.assertEqual(
 
2700
            [('call_with_body_bytes_expecting_body',
 
2701
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2702
              '\n\n0')],
 
2703
            client._calls)
 
2704
        repo.unlock()
 
2705
 
2098
2706
 
2099
2707
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2100
2708
 
2115
2723
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2116
2724
 
2117
2725
 
 
2726
class TestRepositoryGetRevisions(TestRemoteRepository):
 
2727
 
 
2728
    def test_hpss_missing_revision(self):
 
2729
        transport_path = 'quack'
 
2730
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2731
        client.add_success_response_with_body(
 
2732
            '', 'ok', '10')
 
2733
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
 
2734
            ['somerev1', 'anotherrev2'])
 
2735
        self.assertEqual(
 
2736
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2737
             ('quack/', ), "somerev1\nanotherrev2")],
 
2738
            client._calls)
 
2739
 
 
2740
    def test_hpss_get_single_revision(self):
 
2741
        transport_path = 'quack'
 
2742
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2743
        somerev1 = Revision("somerev1")
 
2744
        somerev1.committer = "Joe Committer <joe@example.com>"
 
2745
        somerev1.timestamp = 1321828927
 
2746
        somerev1.timezone = -60
 
2747
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
 
2748
        somerev1.message = "Message"
 
2749
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
 
2750
            somerev1))
 
2751
        # Split up body into two bits to make sure the zlib compression object
 
2752
        # gets data fed twice.
 
2753
        client.add_success_response_with_body(
 
2754
                [body[:10], body[10:]], 'ok', '10')
 
2755
        revs = repo.get_revisions(['somerev1'])
 
2756
        self.assertEquals(revs, [somerev1])
 
2757
        self.assertEqual(
 
2758
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2759
             ('quack/', ), "somerev1")],
 
2760
            client._calls)
 
2761
 
 
2762
 
2118
2763
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2119
2764
 
2120
2765
    def test_null_revision(self):
2257
2902
        self.setup_smart_server_with_call_log()
2258
2903
        tree = self.make_branch_and_memory_tree('.')
2259
2904
        tree.lock_write()
 
2905
        tree.add('')
2260
2906
        rev1 = tree.commit('First')
2261
2907
        rev2 = tree.commit('Second')
2262
2908
        tree.unlock()
2270
2916
                              call.call.method == verb])
2271
2917
 
2272
2918
 
 
2919
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
 
2920
 
 
2921
    def test_has_signature_for_revision_id(self):
 
2922
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
 
2923
        transport_path = 'quack'
 
2924
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2925
        client.add_success_response('yes')
 
2926
        result = repo.has_signature_for_revision_id('A')
 
2927
        self.assertEqual(
 
2928
            [('call', 'Repository.has_signature_for_revision_id',
 
2929
              ('quack/', 'A'))],
 
2930
            client._calls)
 
2931
        self.assertEqual(True, result)
 
2932
 
 
2933
    def test_is_not_shared(self):
 
2934
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
 
2935
        transport_path = 'qwack'
 
2936
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2937
        client.add_success_response('no')
 
2938
        result = repo.has_signature_for_revision_id('A')
 
2939
        self.assertEqual(
 
2940
            [('call', 'Repository.has_signature_for_revision_id',
 
2941
              ('qwack/', 'A'))],
 
2942
            client._calls)
 
2943
        self.assertEqual(False, result)
 
2944
 
 
2945
 
 
2946
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
 
2947
 
 
2948
    def test_get_physical_lock_status_yes(self):
 
2949
        transport_path = 'qwack'
 
2950
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2951
        client.add_success_response('yes')
 
2952
        result = repo.get_physical_lock_status()
 
2953
        self.assertEqual(
 
2954
            [('call', 'Repository.get_physical_lock_status',
 
2955
              ('qwack/', ))],
 
2956
            client._calls)
 
2957
        self.assertEqual(True, result)
 
2958
 
 
2959
    def test_get_physical_lock_status_no(self):
 
2960
        transport_path = 'qwack'
 
2961
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2962
        client.add_success_response('no')
 
2963
        result = repo.get_physical_lock_status()
 
2964
        self.assertEqual(
 
2965
            [('call', 'Repository.get_physical_lock_status',
 
2966
              ('qwack/', ))],
 
2967
            client._calls)
 
2968
        self.assertEqual(False, result)
 
2969
 
 
2970
 
2273
2971
class TestRepositoryIsShared(TestRemoteRepository):
2274
2972
 
2275
2973
    def test_is_shared(self):
2295
2993
        self.assertEqual(False, result)
2296
2994
 
2297
2995
 
 
2996
class TestRepositoryMakeWorkingTrees(TestRemoteRepository):
 
2997
 
 
2998
    def test_make_working_trees(self):
 
2999
        # ('yes', ) for Repository.make_working_trees -> 'True'.
 
3000
        transport_path = 'quack'
 
3001
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3002
        client.add_success_response('yes')
 
3003
        result = repo.make_working_trees()
 
3004
        self.assertEqual(
 
3005
            [('call', 'Repository.make_working_trees', ('quack/',))],
 
3006
            client._calls)
 
3007
        self.assertEqual(True, result)
 
3008
 
 
3009
    def test_no_working_trees(self):
 
3010
        # ('no', ) for Repository.make_working_trees -> 'False'.
 
3011
        transport_path = 'qwack'
 
3012
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3013
        client.add_success_response('no')
 
3014
        result = repo.make_working_trees()
 
3015
        self.assertEqual(
 
3016
            [('call', 'Repository.make_working_trees', ('qwack/',))],
 
3017
            client._calls)
 
3018
        self.assertEqual(False, result)
 
3019
 
 
3020
 
2298
3021
class TestRepositoryLockWrite(TestRemoteRepository):
2299
3022
 
2300
3023
    def test_lock_write(self):
2301
3024
        transport_path = 'quack'
2302
3025
        repo, client = self.setup_fake_client_and_repository(transport_path)
2303
3026
        client.add_success_response('ok', 'a token')
2304
 
        result = repo.lock_write()
 
3027
        token = repo.lock_write().repository_token
2305
3028
        self.assertEqual(
2306
3029
            [('call', 'Repository.lock_write', ('quack/', ''))],
2307
3030
            client._calls)
2308
 
        self.assertEqual('a token', result)
 
3031
        self.assertEqual('a token', token)
2309
3032
 
2310
3033
    def test_lock_write_already_locked(self):
2311
3034
        transport_path = 'quack'
2326
3049
            client._calls)
2327
3050
 
2328
3051
 
 
3052
class TestRepositoryWriteGroups(TestRemoteRepository):
 
3053
 
 
3054
    def test_start_write_group(self):
 
3055
        transport_path = 'quack'
 
3056
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3057
        client.add_expected_call(
 
3058
            'Repository.lock_write', ('quack/', ''),
 
3059
            'success', ('ok', 'a token'))
 
3060
        client.add_expected_call(
 
3061
            'Repository.start_write_group', ('quack/', 'a token'),
 
3062
            'success', ('ok', ('token1', )))
 
3063
        repo.lock_write()
 
3064
        repo.start_write_group()
 
3065
 
 
3066
    def test_start_write_group_unsuspendable(self):
 
3067
        # Some repositories do not support suspending write
 
3068
        # groups. For those, fall back to the "real" repository.
 
3069
        transport_path = 'quack'
 
3070
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3071
        def stub_ensure_real():
 
3072
            client._calls.append(('_ensure_real',))
 
3073
            repo._real_repository = _StubRealPackRepository(client._calls)
 
3074
        repo._ensure_real = stub_ensure_real
 
3075
        client.add_expected_call(
 
3076
            'Repository.lock_write', ('quack/', ''),
 
3077
            'success', ('ok', 'a token'))
 
3078
        client.add_expected_call(
 
3079
            'Repository.start_write_group', ('quack/', 'a token'),
 
3080
            'error', ('UnsuspendableWriteGroup',))
 
3081
        repo.lock_write()
 
3082
        repo.start_write_group()
 
3083
        self.assertEquals(client._calls[-2:], [ 
 
3084
            ('_ensure_real',),
 
3085
            ('start_write_group',)])
 
3086
 
 
3087
    def test_commit_write_group(self):
 
3088
        transport_path = 'quack'
 
3089
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3090
        client.add_expected_call(
 
3091
            'Repository.lock_write', ('quack/', ''),
 
3092
            'success', ('ok', 'a token'))
 
3093
        client.add_expected_call(
 
3094
            'Repository.start_write_group', ('quack/', 'a token'),
 
3095
            'success', ('ok', ['token1']))
 
3096
        client.add_expected_call(
 
3097
            'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
 
3098
            'success', ('ok',))
 
3099
        repo.lock_write()
 
3100
        repo.start_write_group()
 
3101
        repo.commit_write_group()
 
3102
 
 
3103
    def test_abort_write_group(self):
 
3104
        transport_path = 'quack'
 
3105
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3106
        client.add_expected_call(
 
3107
            'Repository.lock_write', ('quack/', ''),
 
3108
            'success', ('ok', 'a token'))
 
3109
        client.add_expected_call(
 
3110
            'Repository.start_write_group', ('quack/', 'a token'),
 
3111
            'success', ('ok', ['token1']))
 
3112
        client.add_expected_call(
 
3113
            'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
 
3114
            'success', ('ok',))
 
3115
        repo.lock_write()
 
3116
        repo.start_write_group()
 
3117
        repo.abort_write_group(False)
 
3118
 
 
3119
    def test_suspend_write_group(self):
 
3120
        transport_path = 'quack'
 
3121
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3122
        self.assertEquals([], repo.suspend_write_group())
 
3123
 
 
3124
    def test_resume_write_group(self):
 
3125
        transport_path = 'quack'
 
3126
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3127
        client.add_expected_call(
 
3128
            'Repository.lock_write', ('quack/', ''),
 
3129
            'success', ('ok', 'a token'))
 
3130
        client.add_expected_call(
 
3131
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
 
3132
            'success', ('ok',))
 
3133
        repo.lock_write()
 
3134
        repo.resume_write_group(['token1'])
 
3135
 
 
3136
 
2329
3137
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
2330
3138
 
2331
3139
    def test_backwards_compat(self):
2390
3198
        self.assertEqual([], client._calls)
2391
3199
 
2392
3200
 
 
3201
class TestRepositoryIterFilesBytes(TestRemoteRepository):
 
3202
    """Test Repository.iter_file_bytes."""
 
3203
 
 
3204
    def test_single(self):
 
3205
        transport_path = 'quack'
 
3206
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3207
        client.add_expected_call(
 
3208
            'Repository.iter_files_bytes', ('quack/', ),
 
3209
            'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
 
3210
        for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
 
3211
                "somerev", "myid")]):
 
3212
            self.assertEquals("myid", identifier)
 
3213
            self.assertEquals("".join(byte_stream), "mydata" * 10)
 
3214
 
 
3215
    def test_missing(self):
 
3216
        transport_path = 'quack'
 
3217
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3218
        client.add_expected_call(
 
3219
            'Repository.iter_files_bytes',
 
3220
                ('quack/', ),
 
3221
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
 
3222
            iter(["absent\0somefile\0somerev\n"]))
 
3223
        self.assertRaises(errors.RevisionNotPresent, list,
 
3224
                repo.iter_files_bytes(
 
3225
                [("somefile", "somerev", "myid")]))
 
3226
 
 
3227
 
2393
3228
class TestRepositoryInsertStreamBase(TestRemoteRepository):
2394
3229
    """Base class for Repository.insert_stream and .insert_stream_1.19
2395
3230
    tests.
2402
3237
        the client is finished.
2403
3238
        """
2404
3239
        sink = repo._get_sink()
2405
 
        fmt = repository.RepositoryFormat.get_default_format()
 
3240
        fmt = repository.format_registry.get_default()
2406
3241
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2407
3242
        self.assertEqual([], resume_tokens)
2408
3243
        self.assertEqual(set(), missing_keys)
2508
3343
                return True
2509
3344
        repo._real_repository = FakeRealRepository()
2510
3345
        sink = repo._get_sink()
2511
 
        fmt = repository.RepositoryFormat.get_default_format()
 
3346
        fmt = repository.format_registry.get_default()
2512
3347
        stream = self.make_stream_with_inv_deltas(fmt)
2513
3348
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2514
3349
        # Every record from the first inventory delta should have been sent to
2670
3505
        self.calls = calls
2671
3506
        self._pack_collection = _StubPackCollection(calls)
2672
3507
 
 
3508
    def start_write_group(self):
 
3509
        self.calls.append(('start_write_group',))
 
3510
 
2673
3511
    def is_in_write_group(self):
2674
3512
        return False
2675
3513
 
2734
3572
             ('pack collection autopack',)],
2735
3573
            client._calls)
2736
3574
 
 
3575
    def test_oom_error_reporting(self):
 
3576
        """An out-of-memory condition on the server is reported clearly"""
 
3577
        transport_path = 'quack'
 
3578
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3579
        client.add_expected_call(
 
3580
            'PackRepository.autopack', ('quack/',),
 
3581
            'error', ('MemoryError',))
 
3582
        err = self.assertRaises(errors.BzrError, repo.autopack)
 
3583
        self.assertContainsRe(str(err), "^remote server out of mem")
 
3584
 
2737
3585
 
2738
3586
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2739
3587
    """Base class for unit tests for bzrlib.remote._translate_error."""
2812
3660
            detail='extra detail')
2813
3661
        self.assertEqual(expected_error, translated_error)
2814
3662
 
 
3663
    def test_norepository(self):
 
3664
        bzrdir = self.make_bzrdir('')
 
3665
        translated_error = self.translateTuple(('norepository',),
 
3666
            bzrdir=bzrdir)
 
3667
        expected_error = errors.NoRepositoryPresent(bzrdir)
 
3668
        self.assertEqual(expected_error, translated_error)
 
3669
 
2815
3670
    def test_LockContention(self):
2816
3671
        translated_error = self.translateTuple(('LockContention',))
2817
3672
        expected_error = errors.LockContention('(remote lock)')
2845
3700
        expected_error = errors.DivergedBranches(branch, other_branch)
2846
3701
        self.assertEqual(expected_error, translated_error)
2847
3702
 
 
3703
    def test_NotStacked(self):
 
3704
        branch = self.make_branch('')
 
3705
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
 
3706
        expected_error = errors.NotStacked(branch)
 
3707
        self.assertEqual(expected_error, translated_error)
 
3708
 
2848
3709
    def test_ReadError_no_args(self):
2849
3710
        path = 'a path'
2850
3711
        translated_error = self.translateTuple(('ReadError',), path=path)
2866
3727
 
2867
3728
    def test_PermissionDenied_no_args(self):
2868
3729
        path = 'a path'
2869
 
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
 
3730
        translated_error = self.translateTuple(('PermissionDenied',),
 
3731
            path=path)
2870
3732
        expected_error = errors.PermissionDenied(path)
2871
3733
        self.assertEqual(expected_error, translated_error)
2872
3734
 
2895
3757
        expected_error = errors.PermissionDenied(path, extra)
2896
3758
        self.assertEqual(expected_error, translated_error)
2897
3759
 
 
3760
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
 
3761
 
 
3762
    def test_NoSuchFile_context_path(self):
 
3763
        local_path = "local path"
 
3764
        translated_error = self.translateTuple(('ReadError', "remote path"),
 
3765
            path=local_path)
 
3766
        expected_error = errors.ReadError(local_path)
 
3767
        self.assertEqual(expected_error, translated_error)
 
3768
 
 
3769
    def test_NoSuchFile_without_context(self):
 
3770
        remote_path = "remote path"
 
3771
        translated_error = self.translateTuple(('ReadError', remote_path))
 
3772
        expected_error = errors.ReadError(remote_path)
 
3773
        self.assertEqual(expected_error, translated_error)
 
3774
 
 
3775
    def test_ReadOnlyError(self):
 
3776
        translated_error = self.translateTuple(('ReadOnlyError',))
 
3777
        expected_error = errors.TransportNotPossible("readonly transport")
 
3778
        self.assertEqual(expected_error, translated_error)
 
3779
 
 
3780
    def test_MemoryError(self):
 
3781
        translated_error = self.translateTuple(('MemoryError',))
 
3782
        self.assertStartsWith(str(translated_error),
 
3783
            "remote server out of memory")
 
3784
 
 
3785
    def test_generic_IndexError_no_classname(self):
 
3786
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
 
3787
        translated_error = self.translateErrorFromSmartServer(err)
 
3788
        expected_error = errors.UnknownErrorFromSmartServer(err)
 
3789
        self.assertEqual(expected_error, translated_error)
 
3790
 
 
3791
    # GZ 2011-03-02: TODO test generic non-ascii error string
 
3792
 
 
3793
    def test_generic_KeyError(self):
 
3794
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
 
3795
        translated_error = self.translateErrorFromSmartServer(err)
 
3796
        expected_error = errors.UnknownErrorFromSmartServer(err)
 
3797
        self.assertEqual(expected_error, translated_error)
 
3798
 
2898
3799
 
2899
3800
class TestErrorTranslationRobustness(TestErrorTranslationBase):
2900
3801
    """Unit tests for bzrlib.remote._translate_error's robustness.
3045
3946
        _, stacked = branch_factory()
3046
3947
        source = stacked.repository._get_source(target_repository_format)
3047
3948
        tip = stacked.last_revision()
3048
 
        revs = stacked.repository.get_ancestry(tip)
3049
 
        search = graph.PendingAncestryResult([tip], stacked.repository)
 
3949
        stacked.repository._ensure_real()
 
3950
        graph = stacked.repository.get_graph()
 
3951
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
 
3952
                if r != NULL_REVISION]
 
3953
        revs.reverse()
 
3954
        search = vf_search.PendingAncestryResult([tip], stacked.repository)
3050
3955
        self.reset_smart_call_log()
3051
3956
        stream = source.get_stream(search)
3052
 
        if None in revs:
3053
 
            revs.remove(None)
3054
3957
        # We trust that if a revision is in the stream the rest of the new
3055
3958
        # content for it is too, as per our main fetch tests; here we are
3056
3959
        # checking that the revisions are actually included at all, and their
3095
3998
        self.assertEqual(expected_revs, rev_ord)
3096
3999
        # Getting topological sort requires VFS calls still - one of which is
3097
4000
        # pushing up from the bound branch.
3098
 
        self.assertLength(13, self.hpss_calls)
 
4001
        self.assertLength(14, self.hpss_calls)
3099
4002
 
3100
4003
    def test_stacked_get_stream_groupcompress(self):
3101
4004
        # Repository._get_source.get_stream() from a stacked repository with
3142
4045
 
3143
4046
    def test_copy_content_into_avoids_revision_history(self):
3144
4047
        local = self.make_branch('local')
3145
 
        remote_backing_tree = self.make_branch_and_tree('remote')
3146
 
        remote_backing_tree.commit("Commit.")
 
4048
        builder = self.make_branch_builder('remote')
 
4049
        builder.build_commit(message="Commit.")
3147
4050
        remote_branch_url = self.smart_server.get_url() + 'remote'
3148
4051
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3149
4052
        local.repository.fetch(remote_branch.repository)
3150
4053
        self.hpss_calls = []
3151
4054
        remote_branch.copy_content_into(local)
3152
4055
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
 
4056
 
 
4057
    def test_fetch_everything_needs_just_one_call(self):
 
4058
        local = self.make_branch('local')
 
4059
        builder = self.make_branch_builder('remote')
 
4060
        builder.build_commit(message="Commit.")
 
4061
        remote_branch_url = self.smart_server.get_url() + 'remote'
 
4062
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
 
4063
        self.hpss_calls = []
 
4064
        local.repository.fetch(
 
4065
            remote_branch.repository,
 
4066
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
 
4067
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
 
4068
 
 
4069
    def override_verb(self, verb_name, verb):
 
4070
        request_handlers = request.request_handlers
 
4071
        orig_verb = request_handlers.get(verb_name)
 
4072
        orig_info = request_handlers.get_info(verb_name)
 
4073
        request_handlers.register(verb_name, verb, override_existing=True)
 
4074
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
 
4075
                override_existing=True, info=orig_info)
 
4076
 
 
4077
    def test_fetch_everything_backwards_compat(self):
 
4078
        """Can fetch with EverythingResult even with pre 2.4 servers.
 
4079
        
 
4080
        Pre-2.4 do not support 'everything' searches with the
 
4081
        Repository.get_stream_1.19 verb.
 
4082
        """
 
4083
        verb_log = []
 
4084
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
 
4085
            """A version of the Repository.get_stream_1.19 verb patched to
 
4086
            reject 'everything' searches the way 2.3 and earlier do.
 
4087
            """
 
4088
            def recreate_search(self, repository, search_bytes,
 
4089
                                discard_excess=False):
 
4090
                verb_log.append(search_bytes.split('\n', 1)[0])
 
4091
                if search_bytes == 'everything':
 
4092
                    return (None,
 
4093
                            request.FailedSmartServerResponse(('BadSearch',)))
 
4094
                return super(OldGetStreamVerb,
 
4095
                        self).recreate_search(repository, search_bytes,
 
4096
                            discard_excess=discard_excess)
 
4097
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
 
4098
        local = self.make_branch('local')
 
4099
        builder = self.make_branch_builder('remote')
 
4100
        builder.build_commit(message="Commit.")
 
4101
        remote_branch_url = self.smart_server.get_url() + 'remote'
 
4102
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
 
4103
        self.hpss_calls = []
 
4104
        local.repository.fetch(
 
4105
            remote_branch.repository,
 
4106
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
 
4107
        # make sure the overridden verb was used
 
4108
        self.assertLength(1, verb_log)
 
4109
        # more than one HPSS call is needed, but because it's a VFS callback
 
4110
        # its hard to predict exactly how many.
 
4111
        self.assertTrue(len(self.hpss_calls) > 1)
 
4112
 
 
4113
 
 
4114
class TestUpdateBoundBranchWithModifiedBoundLocation(
 
4115
    tests.TestCaseWithTransport):
 
4116
    """Ensure correct handling of bound_location modifications.
 
4117
 
 
4118
    This is tested against a smart server as http://pad.lv/786980 was about a
 
4119
    ReadOnlyError (write attempt during a read-only transaction) which can only
 
4120
    happen in this context.
 
4121
    """
 
4122
 
 
4123
    def setUp(self):
 
4124
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
 
4125
        self.transport_server = test_server.SmartTCPServer_for_testing
 
4126
 
 
4127
    def make_master_and_checkout(self, master_name, checkout_name):
 
4128
        # Create the master branch and its associated checkout
 
4129
        self.master = self.make_branch_and_tree(master_name)
 
4130
        self.checkout = self.master.branch.create_checkout(checkout_name)
 
4131
        # Modify the master branch so there is something to update
 
4132
        self.master.commit('add stuff')
 
4133
        self.last_revid = self.master.commit('even more stuff')
 
4134
        self.bound_location = self.checkout.branch.get_bound_location()
 
4135
 
 
4136
    def assertUpdateSucceeds(self, new_location):
 
4137
        self.checkout.branch.set_bound_location(new_location)
 
4138
        self.checkout.update()
 
4139
        self.assertEquals(self.last_revid, self.checkout.last_revision())
 
4140
 
 
4141
    def test_without_final_slash(self):
 
4142
        self.make_master_and_checkout('master', 'checkout')
 
4143
        # For unclear reasons some users have a bound_location without a final
 
4144
        # '/', simulate that by forcing such a value
 
4145
        self.assertEndsWith(self.bound_location, '/')
 
4146
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
 
4147
 
 
4148
    def test_plus_sign(self):
 
4149
        self.make_master_and_checkout('+master', 'checkout')
 
4150
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
 
4151
 
 
4152
    def test_tilda(self):
 
4153
        # Embed ~ in the middle of the path just to avoid any $HOME
 
4154
        # interpretation
 
4155
        self.make_master_and_checkout('mas~ter', 'checkout')
 
4156
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
 
4157
 
 
4158
 
 
4159
class TestWithCustomErrorHandler(RemoteBranchTestCase):
 
4160
 
 
4161
    def test_no_context(self):
 
4162
        class OutOfCoffee(errors.BzrError):
 
4163
            """A dummy exception for testing."""
 
4164
 
 
4165
            def __init__(self, urgency):
 
4166
                self.urgency = urgency
 
4167
        remote.no_context_error_translators.register("OutOfCoffee",
 
4168
            lambda err: OutOfCoffee(err.error_args[0]))
 
4169
        transport = MemoryTransport()
 
4170
        client = FakeClient(transport.base)
 
4171
        client.add_expected_call(
 
4172
            'Branch.get_stacked_on_url', ('quack/',),
 
4173
            'error', ('NotStacked',))
 
4174
        client.add_expected_call(
 
4175
            'Branch.last_revision_info',
 
4176
            ('quack/',),
 
4177
            'error', ('OutOfCoffee', 'low'))
 
4178
        transport.mkdir('quack')
 
4179
        transport = transport.clone('quack')
 
4180
        branch = self.make_remote_branch(transport, client)
 
4181
        self.assertRaises(OutOfCoffee, branch.last_revision_info)
 
4182
        self.assertFinished(client)
 
4183
 
 
4184
    def test_with_context(self):
 
4185
        class OutOfTea(errors.BzrError):
 
4186
            def __init__(self, branch, urgency):
 
4187
                self.branch = branch
 
4188
                self.urgency = urgency
 
4189
        remote.error_translators.register("OutOfTea",
 
4190
            lambda err, find, path: OutOfTea(err.error_args[0],
 
4191
                find("branch")))
 
4192
        transport = MemoryTransport()
 
4193
        client = FakeClient(transport.base)
 
4194
        client.add_expected_call(
 
4195
            'Branch.get_stacked_on_url', ('quack/',),
 
4196
            'error', ('NotStacked',))
 
4197
        client.add_expected_call(
 
4198
            'Branch.last_revision_info',
 
4199
            ('quack/',),
 
4200
            'error', ('OutOfTea', 'low'))
 
4201
        transport.mkdir('quack')
 
4202
        transport = transport.clone('quack')
 
4203
        branch = self.make_remote_branch(transport, client)
 
4204
        self.assertRaises(OutOfTea, branch.last_revision_info)
 
4205
        self.assertFinished(client)
 
4206
 
 
4207
 
 
4208
class TestRepositoryPack(TestRemoteRepository):
 
4209
 
 
4210
    def test_pack(self):
 
4211
        transport_path = 'quack'
 
4212
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4213
        client.add_expected_call(
 
4214
            'Repository.lock_write', ('quack/', ''),
 
4215
            'success', ('ok', 'token'))
 
4216
        client.add_expected_call(
 
4217
            'Repository.pack', ('quack/', 'token', 'False'),
 
4218
            'success', ('ok',), )
 
4219
        client.add_expected_call(
 
4220
            'Repository.unlock', ('quack/', 'token'),
 
4221
            'success', ('ok', ))
 
4222
        repo.pack()
 
4223
 
 
4224
    def test_pack_with_hint(self):
 
4225
        transport_path = 'quack'
 
4226
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4227
        client.add_expected_call(
 
4228
            'Repository.lock_write', ('quack/', ''),
 
4229
            'success', ('ok', 'token'))
 
4230
        client.add_expected_call(
 
4231
            'Repository.pack', ('quack/', 'token', 'False'),
 
4232
            'success', ('ok',), )
 
4233
        client.add_expected_call(
 
4234
            'Repository.unlock', ('quack/', 'token', 'False'),
 
4235
            'success', ('ok', ))
 
4236
        repo.pack(['hinta', 'hintb'])
 
4237
 
 
4238
 
 
4239
class TestRepositoryIterInventories(TestRemoteRepository):
 
4240
    """Test Repository.iter_inventories."""
 
4241
 
 
4242
    def _serialize_inv_delta(self, old_name, new_name, delta):
 
4243
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
4244
        return "".join(serializer.delta_to_lines(old_name, new_name, delta))
 
4245
 
 
4246
    def test_single_empty(self):
 
4247
        transport_path = 'quack'
 
4248
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4249
        fmt = bzrdir.format_registry.get('2a')().repository_format
 
4250
        repo._format = fmt
 
4251
        stream = [('inventory-deltas', [
 
4252
            versionedfile.FulltextContentFactory('somerevid', None, None,
 
4253
                self._serialize_inv_delta('null:', 'somerevid', []))])]
 
4254
        client.add_expected_call(
 
4255
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4256
            'success', ('ok', ),
 
4257
            _stream_to_byte_stream(stream, fmt))
 
4258
        ret = list(repo.iter_inventories(["somerevid"]))
 
4259
        self.assertLength(1, ret)
 
4260
        inv = ret[0]
 
4261
        self.assertEquals("somerevid", inv.revision_id)
 
4262
 
 
4263
    def test_empty(self):
 
4264
        transport_path = 'quack'
 
4265
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4266
        ret = list(repo.iter_inventories([]))
 
4267
        self.assertEquals(ret, [])
 
4268
 
 
4269
    def test_missing(self):
 
4270
        transport_path = 'quack'
 
4271
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4272
        client.add_expected_call(
 
4273
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4274
            'success', ('ok', ), iter([]))
 
4275
        self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
 
4276
            ["somerevid"]))