~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: Martin Packman
  • Date: 2011-12-19 10:37:57 UTC
  • mto: This revision was merged to the branch mainline in revision 6394.
  • Revision ID: martin.packman@canonical.com-20111219103757-b85as9n9pb7e6qvn
Add tests for deprecated unicode wrapper functions in win32utils

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
16
16
 
17
17
"""Tests for the Branch facility that are not interface  tests.
18
18
 
19
 
For interface tests see tests/per_branch/*.py.
 
19
For interface tests see `tests/per_branch/*.py`.
20
20
 
21
21
For concrete class tests see this file, and for meta-branch tests
22
22
also see this file.
29
29
    bzrdir,
30
30
    config,
31
31
    errors,
 
32
    symbol_versioning,
32
33
    tests,
33
34
    trace,
34
 
    transport,
35
35
    urlutils,
36
36
    )
37
37
 
40
40
 
41
41
    def test_default_format(self):
42
42
        # update this if you change the default branch format
43
 
        self.assertIsInstance(_mod_branch.BranchFormat.get_default_format(),
 
43
        self.assertIsInstance(_mod_branch.format_registry.get_default(),
44
44
                _mod_branch.BzrBranchFormat7)
45
45
 
46
46
    def test_default_format_is_same_as_bzrdir_default(self):
48
48
        # set, but at the moment that's not true -- mbp 20070814 --
49
49
        # https://bugs.launchpad.net/bzr/+bug/132376
50
50
        self.assertEqual(
51
 
            _mod_branch.BranchFormat.get_default_format(),
 
51
            _mod_branch.format_registry.get_default(),
52
52
            bzrdir.BzrDirFormat.get_default_format().get_branch_format())
53
53
 
54
54
    def test_get_set_default_format(self):
55
55
        # set the format and then set it back again
56
 
        old_format = _mod_branch.BranchFormat.get_default_format()
57
 
        _mod_branch.BranchFormat.set_default_format(SampleBranchFormat())
 
56
        old_format = _mod_branch.format_registry.get_default()
 
57
        _mod_branch.format_registry.set_default(SampleBranchFormat())
58
58
        try:
59
59
            # the default branch format is used by the meta dir format
60
60
            # which is not the default bzrdir format at this point
62
62
            result = dir.create_branch()
63
63
            self.assertEqual(result, 'A branch')
64
64
        finally:
65
 
            _mod_branch.BranchFormat.set_default_format(old_format)
 
65
            _mod_branch.format_registry.set_default(old_format)
66
66
        self.assertEqual(old_format,
67
 
                         _mod_branch.BranchFormat.get_default_format())
 
67
                         _mod_branch.format_registry.get_default())
68
68
 
69
69
 
70
70
class TestBranchFormat5(tests.TestCaseWithTransport):
74
74
        url = self.get_url()
75
75
        bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
76
76
        bdir.create_repository()
77
 
        branch = bdir.create_branch()
 
77
        branch = _mod_branch.BzrBranchFormat5().initialize(bdir)
78
78
        t = self.get_transport()
79
79
        self.log("branch instance is %r" % branch)
80
80
        self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
86
86
        self.assertIsDirectory('.bzr/branch/lock/held', t)
87
87
 
88
88
    def test_set_push_location(self):
89
 
        from bzrlib.config import (locations_config_filename,
90
 
                                   ensure_config_dir_exists)
91
 
        ensure_config_dir_exists()
92
 
        fn = locations_config_filename()
93
 
        # write correct newlines to locations.conf
94
 
        # by default ConfigObj uses native line-endings for new files
95
 
        # but uses already existing line-endings if file is not empty
96
 
        f = open(fn, 'wb')
97
 
        try:
98
 
            f.write('# comment\n')
99
 
        finally:
100
 
            f.close()
 
89
        conf = config.LocationConfig.from_string('# comment\n', '.', save=True)
101
90
 
102
91
        branch = self.make_branch('.', format='knit')
103
92
        branch.set_push_location('foo')
106
95
                             "[%s]\n"
107
96
                             "push_location = foo\n"
108
97
                             "push_location:policy = norecurse\n" % local_path,
109
 
                             fn)
 
98
                             config.locations_config_filename())
110
99
 
111
100
    # TODO RBC 20051029 test getting a push location from a branch in a
112
101
    # recursive section - that is, it appends the branch name.
113
102
 
114
103
 
115
 
class SampleBranchFormat(_mod_branch.BranchFormat):
 
104
class SampleBranchFormat(_mod_branch.BranchFormatMetadir):
116
105
    """A sample format
117
106
 
118
107
    this format is initializable, unsupported to aid in testing the
119
108
    open and open_downlevel routines.
120
109
    """
121
110
 
122
 
    def get_format_string(self):
 
111
    @classmethod
 
112
    def get_format_string(cls):
123
113
        """See BzrBranchFormat.get_format_string()."""
124
114
        return "Sample branch format."
125
115
 
126
 
    def initialize(self, a_bzrdir, name=None):
 
116
    def initialize(self, a_bzrdir, name=None, repository=None,
 
117
                   append_revisions_only=None):
127
118
        """Format 4 branches cannot be created."""
128
119
        t = a_bzrdir.get_branch_transport(self, name=name)
129
120
        t.put_bytes('format', self.get_format_string())
132
123
    def is_supported(self):
133
124
        return False
134
125
 
135
 
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
 
126
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False,
 
127
             possible_transports=None):
136
128
        return "opened branch."
137
129
 
138
130
 
 
131
# Demonstrating how lazy loading is often implemented:
 
132
# A constant string is created.
 
133
SampleSupportedBranchFormatString = "Sample supported branch format."
 
134
 
 
135
# And the format class can then reference the constant to avoid skew.
 
136
class SampleSupportedBranchFormat(_mod_branch.BranchFormatMetadir):
 
137
    """A sample supported format."""
 
138
 
 
139
    @classmethod
 
140
    def get_format_string(cls):
 
141
        """See BzrBranchFormat.get_format_string()."""
 
142
        return SampleSupportedBranchFormatString
 
143
 
 
144
    def initialize(self, a_bzrdir, name=None, append_revisions_only=None):
 
145
        t = a_bzrdir.get_branch_transport(self, name=name)
 
146
        t.put_bytes('format', self.get_format_string())
 
147
        return 'A branch'
 
148
 
 
149
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False,
 
150
             possible_transports=None):
 
151
        return "opened supported branch."
 
152
 
 
153
 
 
154
class SampleExtraBranchFormat(_mod_branch.BranchFormat):
 
155
    """A sample format that is not usable in a metadir."""
 
156
 
 
157
    def get_format_string(self):
 
158
        # This format is not usable in a metadir.
 
159
        return None
 
160
 
 
161
    def network_name(self):
 
162
        # Network name always has to be provided.
 
163
        return "extra"
 
164
 
 
165
    def initialize(self, a_bzrdir, name=None):
 
166
        raise NotImplementedError(self.initialize)
 
167
 
 
168
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False,
 
169
             possible_transports=None):
 
170
        raise NotImplementedError(self.open)
 
171
 
 
172
 
139
173
class TestBzrBranchFormat(tests.TestCaseWithTransport):
140
174
    """Tests for the BzrBranchFormat facility."""
141
175
 
148
182
            dir = format._matchingbzrdir.initialize(url)
149
183
            dir.create_repository()
150
184
            format.initialize(dir)
151
 
            found_format = _mod_branch.BranchFormat.find_format(dir)
152
 
            self.failUnless(isinstance(found_format, format.__class__))
 
185
            found_format = _mod_branch.BranchFormatMetadir.find_format(dir)
 
186
            self.assertIsInstance(found_format, format.__class__)
153
187
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
154
188
 
 
189
    def test_find_format_factory(self):
 
190
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
 
191
        SampleSupportedBranchFormat().initialize(dir)
 
192
        factory = _mod_branch.MetaDirBranchFormatFactory(
 
193
            SampleSupportedBranchFormatString,
 
194
            "bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
 
195
        _mod_branch.format_registry.register(factory)
 
196
        self.addCleanup(_mod_branch.format_registry.remove, factory)
 
197
        b = _mod_branch.Branch.open(self.get_url())
 
198
        self.assertEqual(b, "opened supported branch.")
 
199
 
 
200
    def test_from_string(self):
 
201
        self.assertIsInstance(
 
202
            SampleBranchFormat.from_string("Sample branch format."),
 
203
            SampleBranchFormat)
 
204
        self.assertRaises(ValueError,
 
205
            SampleBranchFormat.from_string, "Different branch format.")
 
206
 
155
207
    def test_find_format_not_branch(self):
156
208
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
157
209
        self.assertRaises(errors.NotBranchError,
158
 
                          _mod_branch.BranchFormat.find_format,
 
210
                          _mod_branch.BranchFormatMetadir.find_format,
159
211
                          dir)
160
212
 
161
213
    def test_find_format_unknown_format(self):
162
214
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
163
215
        SampleBranchFormat().initialize(dir)
164
216
        self.assertRaises(errors.UnknownFormatError,
165
 
                          _mod_branch.BranchFormat.find_format,
 
217
                          _mod_branch.BranchFormatMetadir.find_format,
166
218
                          dir)
167
219
 
168
220
    def test_register_unregister_format(self):
 
221
        # Test the deprecated format registration functions
169
222
        format = SampleBranchFormat()
170
223
        # make a control dir
171
224
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
172
225
        # make a branch
173
226
        format.initialize(dir)
174
227
        # register a format for it.
175
 
        _mod_branch.BranchFormat.register_format(format)
 
228
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
229
            _mod_branch.BranchFormat.register_format, format)
176
230
        # which branch.Open will refuse (not supported)
177
231
        self.assertRaises(errors.UnsupportedFormatError,
178
232
                          _mod_branch.Branch.open, self.get_url())
182
236
            format.open(dir),
183
237
            bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
184
238
        # unregister the format
185
 
        _mod_branch.BranchFormat.unregister_format(format)
 
239
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
240
            _mod_branch.BranchFormat.unregister_format, format)
186
241
        self.make_branch_and_tree('bar')
187
242
 
188
243
 
 
244
class TestBranchFormatRegistry(tests.TestCase):
 
245
 
 
246
    def setUp(self):
 
247
        super(TestBranchFormatRegistry, self).setUp()
 
248
        self.registry = _mod_branch.BranchFormatRegistry()
 
249
 
 
250
    def test_default(self):
 
251
        self.assertIs(None, self.registry.get_default())
 
252
        format = SampleBranchFormat()
 
253
        self.registry.set_default(format)
 
254
        self.assertEquals(format, self.registry.get_default())
 
255
 
 
256
    def test_register_unregister_format(self):
 
257
        format = SampleBranchFormat()
 
258
        self.registry.register(format)
 
259
        self.assertEquals(format,
 
260
            self.registry.get("Sample branch format."))
 
261
        self.registry.remove(format)
 
262
        self.assertRaises(KeyError, self.registry.get,
 
263
            "Sample branch format.")
 
264
 
 
265
    def test_get_all(self):
 
266
        format = SampleBranchFormat()
 
267
        self.assertEquals([], self.registry._get_all())
 
268
        self.registry.register(format)
 
269
        self.assertEquals([format], self.registry._get_all())
 
270
 
 
271
    def test_register_extra(self):
 
272
        format = SampleExtraBranchFormat()
 
273
        self.assertEquals([], self.registry._get_all())
 
274
        self.registry.register_extra(format)
 
275
        self.assertEquals([format], self.registry._get_all())
 
276
 
 
277
    def test_register_extra_lazy(self):
 
278
        self.assertEquals([], self.registry._get_all())
 
279
        self.registry.register_extra_lazy("bzrlib.tests.test_branch",
 
280
            "SampleExtraBranchFormat")
 
281
        formats = self.registry._get_all()
 
282
        self.assertEquals(1, len(formats))
 
283
        self.assertIsInstance(formats[0], SampleExtraBranchFormat)
 
284
 
 
285
 
 
286
#Used by TestMetaDirBranchFormatFactory 
 
287
FakeLazyFormat = None
 
288
 
 
289
 
 
290
class TestMetaDirBranchFormatFactory(tests.TestCase):
 
291
 
 
292
    def test_get_format_string_does_not_load(self):
 
293
        """Formats have a static format string."""
 
294
        factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
 
295
        self.assertEqual("yo", factory.get_format_string())
 
296
 
 
297
    def test_call_loads(self):
 
298
        # __call__ is used by the network_format_registry interface to get a
 
299
        # Format.
 
300
        global FakeLazyFormat
 
301
        del FakeLazyFormat
 
302
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
 
303
            "bzrlib.tests.test_branch", "FakeLazyFormat")
 
304
        self.assertRaises(AttributeError, factory)
 
305
 
 
306
    def test_call_returns_call_of_referenced_object(self):
 
307
        global FakeLazyFormat
 
308
        FakeLazyFormat = lambda:'called'
 
309
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
 
310
            "bzrlib.tests.test_branch", "FakeLazyFormat")
 
311
        self.assertEqual('called', factory())
 
312
 
 
313
 
189
314
class TestBranch67(object):
190
315
    """Common tests for both branch 6 and 7 which are mostly the same."""
191
316
 
210
335
 
211
336
    def test_layout(self):
212
337
        branch = self.make_branch('a', format=self.get_format_name())
213
 
        self.failUnlessExists('a/.bzr/branch/last-revision')
214
 
        self.failIfExists('a/.bzr/branch/revision-history')
215
 
        self.failIfExists('a/.bzr/branch/references')
 
338
        self.assertPathExists('a/.bzr/branch/last-revision')
 
339
        self.assertPathDoesNotExist('a/.bzr/branch/revision-history')
 
340
        self.assertPathDoesNotExist('a/.bzr/branch/references')
216
341
 
217
342
    def test_config(self):
218
343
        """Ensure that all configuration data is stored in the branch"""
219
344
        branch = self.make_branch('a', format=self.get_format_name())
220
 
        branch.set_parent('http://bazaar-vcs.org')
221
 
        self.failIfExists('a/.bzr/branch/parent')
222
 
        self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
223
 
        branch.set_push_location('sftp://bazaar-vcs.org')
 
345
        branch.set_parent('http://example.com')
 
346
        self.assertPathDoesNotExist('a/.bzr/branch/parent')
 
347
        self.assertEqual('http://example.com', branch.get_parent())
 
348
        branch.set_push_location('sftp://example.com')
224
349
        config = branch.get_config()._get_branch_data_config()
225
 
        self.assertEqual('sftp://bazaar-vcs.org',
 
350
        self.assertEqual('sftp://example.com',
226
351
                         config.get_user_option('push_location'))
227
 
        branch.set_bound_location('ftp://bazaar-vcs.org')
228
 
        self.failIfExists('a/.bzr/branch/bound')
229
 
        self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
 
352
        branch.set_bound_location('ftp://example.com')
 
353
        self.assertPathDoesNotExist('a/.bzr/branch/bound')
 
354
        self.assertEqual('ftp://example.com', branch.get_bound_location())
230
355
 
231
356
    def test_set_revision_history(self):
232
357
        builder = self.make_branch_builder('.', format=self.get_format_name())
237
362
        branch = builder.get_branch()
238
363
        branch.lock_write()
239
364
        self.addCleanup(branch.unlock)
240
 
        branch.set_revision_history(['foo', 'bar'])
241
 
        branch.set_revision_history(['foo'])
 
365
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
366
            branch.set_revision_history, ['foo', 'bar'])
 
367
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
368
                branch.set_revision_history, ['foo'])
242
369
        self.assertRaises(errors.NotLefthandHistory,
243
 
                          branch.set_revision_history, ['bar'])
 
370
            self.applyDeprecated, symbol_versioning.deprecated_in((2, 4, 0)),
 
371
            branch.set_revision_history, ['bar'])
244
372
 
245
373
    def do_checkout_test(self, lightweight=False):
246
374
        tree = self.make_branch_and_tree('source',
259
387
        subtree.commit('a subtree file')
260
388
        subsubtree.commit('a subsubtree file')
261
389
        tree.branch.create_checkout('target', lightweight=lightweight)
262
 
        self.failUnlessExists('target')
263
 
        self.failUnlessExists('target/subtree')
264
 
        self.failUnlessExists('target/subtree/file')
265
 
        self.failUnlessExists('target/subtree/subsubtree/file')
 
390
        self.assertPathExists('target')
 
391
        self.assertPathExists('target/subtree')
 
392
        self.assertPathExists('target/subtree/file')
 
393
        self.assertPathExists('target/subtree/subsubtree/file')
266
394
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
267
395
        if lightweight:
268
396
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
425
553
        self.assertEqual(('path3', 'location3'),
426
554
                         branch.get_reference_info('file-id'))
427
555
 
 
556
    def _recordParentMapCalls(self, repo):
 
557
        self._parent_map_calls = []
 
558
        orig_get_parent_map = repo.revisions.get_parent_map
 
559
        def get_parent_map(q):
 
560
            q = list(q)
 
561
            self._parent_map_calls.extend([e[0] for e in q])
 
562
            return orig_get_parent_map(q)
 
563
        repo.revisions.get_parent_map = get_parent_map
 
564
 
 
565
 
428
566
class TestBranchReference(tests.TestCaseWithTransport):
429
567
    """Tests for the branch reference facility."""
430
568
 
431
569
    def test_create_open_reference(self):
432
570
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
433
 
        t = transport.get_transport(self.get_url('.'))
 
571
        t = self.get_transport()
434
572
        t.mkdir('repo')
435
573
        dir = bzrdirformat.initialize(self.get_url('repo'))
436
574
        dir.create_repository()
492
630
        self.assertTrue(hasattr(params, 'bzrdir'))
493
631
        self.assertTrue(hasattr(params, 'branch'))
494
632
 
 
633
    def test_post_branch_init_hook_repr(self):
 
634
        param_reprs = []
 
635
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
 
636
            lambda params: param_reprs.append(repr(params)), None)
 
637
        branch = self.make_branch('a')
 
638
        self.assertLength(1, param_reprs)
 
639
        param_repr = param_reprs[0]
 
640
        self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
 
641
 
495
642
    def test_post_switch_hook(self):
496
643
        from bzrlib import switch
497
644
        calls = []
528
675
        if value is not None:
529
676
            self.config.set_user_option('append_revisions_only', value)
530
677
        self.assertEqual(expected_value,
531
 
                         self.branch._get_append_revisions_only())
 
678
                         self.branch.get_append_revisions_only())
532
679
 
533
680
    def test_valid_append_revisions_only(self):
534
681
        self.assertEquals(None,
564
711
        # this usage of results is not recommended for new code (because it
565
712
        # doesn't describe very well what happened), but for api stability
566
713
        # it's still supported
567
 
        a = "%d revisions pulled" % r
568
 
        self.assertEqual(a, "10 revisions pulled")
 
714
        self.assertEqual(self.applyDeprecated(
 
715
            symbol_versioning.deprecated_in((2, 3, 0)),
 
716
            r.__int__),
 
717
            10)
569
718
 
570
719
    def test_report_changed(self):
571
720
        r = _mod_branch.PullResult()
576
725
        f = StringIO()
577
726
        r.report(f)
578
727
        self.assertEqual("Now on revision 20.\n", f.getvalue())
 
728
        self.assertEqual("Now on revision 20.\n", f.getvalue())
579
729
 
580
730
    def test_report_unchanged(self):
581
731
        r = _mod_branch.PullResult()
583
733
        r.new_revid = "same-revid"
584
734
        f = StringIO()
585
735
        r.report(f)
586
 
        self.assertEqual("No revisions to pull.\n", f.getvalue())
587
 
 
588
 
 
589
 
class _StubLockable(object):
590
 
    """Helper for TestRunWithWriteLockedTarget."""
591
 
 
592
 
    def __init__(self, calls, unlock_exc=None):
593
 
        self.calls = calls
594
 
        self.unlock_exc = unlock_exc
595
 
 
596
 
    def lock_write(self):
597
 
        self.calls.append('lock_write')
598
 
 
599
 
    def unlock(self):
600
 
        self.calls.append('unlock')
601
 
        if self.unlock_exc is not None:
602
 
            raise self.unlock_exc
603
 
 
604
 
 
605
 
class _ErrorFromCallable(Exception):
606
 
    """Helper for TestRunWithWriteLockedTarget."""
607
 
 
608
 
 
609
 
class _ErrorFromUnlock(Exception):
610
 
    """Helper for TestRunWithWriteLockedTarget."""
611
 
 
612
 
 
613
 
class TestRunWithWriteLockedTarget(tests.TestCase):
614
 
    """Tests for _run_with_write_locked_target."""
615
 
 
616
 
    def setUp(self):
617
 
        tests.TestCase.setUp(self)
618
 
        self._calls = []
619
 
 
620
 
    def func_that_returns_ok(self):
621
 
        self._calls.append('func called')
622
 
        return 'ok'
623
 
 
624
 
    def func_that_raises(self):
625
 
        self._calls.append('func called')
626
 
        raise _ErrorFromCallable()
627
 
 
628
 
    def test_success_unlocks(self):
629
 
        lockable = _StubLockable(self._calls)
630
 
        result = _mod_branch._run_with_write_locked_target(
631
 
            lockable, self.func_that_returns_ok)
632
 
        self.assertEqual('ok', result)
633
 
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
634
 
 
635
 
    def test_exception_unlocks_and_propagates(self):
636
 
        lockable = _StubLockable(self._calls)
637
 
        self.assertRaises(_ErrorFromCallable,
638
 
                          _mod_branch._run_with_write_locked_target,
639
 
                          lockable, self.func_that_raises)
640
 
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
641
 
 
642
 
    def test_callable_succeeds_but_error_during_unlock(self):
643
 
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
644
 
        self.assertRaises(_ErrorFromUnlock,
645
 
                          _mod_branch._run_with_write_locked_target,
646
 
                          lockable, self.func_that_returns_ok)
647
 
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
648
 
 
649
 
    def test_error_during_unlock_does_not_mask_original_error(self):
650
 
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
651
 
        self.assertRaises(_ErrorFromCallable,
652
 
                          _mod_branch._run_with_write_locked_target,
653
 
                          lockable, self.func_that_raises)
654
 
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
655
 
 
 
736
        self.assertEqual("No revisions or tags to pull.\n", f.getvalue())
656
737