~bzr-pqm/bzr/bzr.dev

2297.1.2 by Martin Pool
Cleanup imports
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
2
#
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
7
#
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
12
#
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for the Branch facility that are not interface  tests.
18
1534.4.39 by Robert Collins
Basic BzrDir support.
19
For interface tests see tests/branch_implementations/*.py.
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
20
21
For concrete class tests see this file, and for meta-branch tests
22
also see this file.
23
"""
24
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
25
from StringIO import StringIO
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
26
2230.3.3 by Aaron Bentley
Add more config testing
27
from bzrlib import (
28
    branch as _mod_branch,
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
29
    bzrdir,
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
30
    config,
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
31
    errors,
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
32
    trace,
2230.3.3 by Aaron Bentley
Add more config testing
33
    urlutils,
34
    )
2297.1.2 by Martin Pool
Cleanup imports
35
from bzrlib.branch import (
36
    Branch,
37
    BranchHooks,
38
    BranchFormat,
39
    BranchReferenceFormat,
40
    BzrBranch5,
41
    BzrBranchFormat5,
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
42
    BzrBranchFormat6,
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
43
    PullResult,
2297.1.2 by Martin Pool
Cleanup imports
44
    )
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
45
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1, 
46
                           BzrDir, BzrDirFormat)
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
47
from bzrlib.errors import (NotBranchError,
48
                           UnknownFormatError,
2245.1.3 by Robert Collins
Add install_hook to the BranchHooks class as the official means for installing a hook.
49
                           UnknownHook,
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
50
                           UnsupportedFormatError,
51
                           )
52
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
53
from bzrlib.tests import TestCase, TestCaseWithTransport
1534.4.4 by Robert Collins
Make BzrBranchFormat.find_format take a transport not a url for efficiency.
54
from bzrlib.transport import get_transport
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
55
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
56
class TestDefaultFormat(TestCase):
57
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
58
    def test_default_format(self):
59
        # update this if you change the default branch format
60
        self.assertIsInstance(BranchFormat.get_default_format(),
61
                BzrBranchFormat6)
62
2696.3.3 by Martin Pool
Start setting the default format to dirstate-tags
63
    def test_default_format_is_same_as_bzrdir_default(self):
64
        # XXX: it might be nice if there was only one place the default was
65
        # set, but at the moment that's not true -- mbp 20070814 -- 
2696.3.8 by Martin Pool
doc
66
        # https://bugs.launchpad.net/bzr/+bug/132376
2696.3.3 by Martin Pool
Start setting the default format to dirstate-tags
67
        self.assertEqual(BranchFormat.get_default_format(),
68
                BzrDirFormat.get_default_format().get_branch_format())
69
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
70
    def test_get_set_default_format(self):
2696.3.1 by Martin Pool
(broken) start switching format to dirstate-tags
71
        # set the format and then set it back again
2297.1.2 by Martin Pool
Cleanup imports
72
        old_format = BranchFormat.get_default_format()
73
        BranchFormat.set_default_format(SampleBranchFormat())
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
74
        try:
75
            # the default branch format is used by the meta dir format
76
            # which is not the default bzrdir format at this point
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
77
            dir = BzrDirMetaFormat1().initialize('memory:///')
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
78
            result = dir.create_branch()
79
            self.assertEqual(result, 'A branch')
80
        finally:
2297.1.2 by Martin Pool
Cleanup imports
81
            BranchFormat.set_default_format(old_format)
82
        self.assertEqual(old_format, BranchFormat.get_default_format())
1508.1.25 by Robert Collins
Update per review comments.
83
84
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
85
class TestBranchFormat5(TestCaseWithTransport):
86
    """Tests specific to branch format 5"""
87
88
    def test_branch_format_5_uses_lockdir(self):
89
        url = self.get_url()
1553.5.72 by Martin Pool
Clean up test for Branch5 lockdirs
90
        bzrdir = BzrDirMetaFormat1().initialize(url)
91
        bzrdir.create_repository()
92
        branch = bzrdir.create_branch()
93
        t = self.get_transport()
94
        self.log("branch instance is %r" % branch)
95
        self.assert_(isinstance(branch, BzrBranch5))
96
        self.assertIsDirectory('.', t)
97
        self.assertIsDirectory('.bzr/branch', t)
98
        self.assertIsDirectory('.bzr/branch/lock', t)
1553.5.73 by Martin Pool
Additional test that Branch5 uses lockdir properly
99
        branch.lock_write()
1658.1.5 by Martin Pool
Release more locks taken during test suite
100
        try:
101
            self.assertIsDirectory('.bzr/branch/lock/held', t)
102
        finally:
103
            branch.unlock()
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
104
2230.3.3 by Aaron Bentley
Add more config testing
105
    def test_set_push_location(self):
106
        from bzrlib.config import (locations_config_filename,
107
                                   ensure_config_dir_exists)
108
        ensure_config_dir_exists()
109
        fn = locations_config_filename()
110
        branch = self.make_branch('.', format='knit')
111
        branch.set_push_location('foo')
112
        local_path = urlutils.local_path_from_url(branch.base[:-1])
113
        self.assertFileEqual("[%s]\n"
114
                             "push_location = foo\n"
115
                             "push_location:policy = norecurse" % local_path,
116
                             fn)
117
2230.3.12 by Aaron Bentley
Clean up trailing whitespace
118
    # TODO RBC 20051029 test getting a push location from a branch in a
2230.3.3 by Aaron Bentley
Add more config testing
119
    # recursive section - that is, it appends the branch name.
120
1553.5.71 by Martin Pool
Change branch format 5 to use LockDirs, not transport locks
121
2297.1.2 by Martin Pool
Cleanup imports
122
class SampleBranchFormat(BranchFormat):
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
123
    """A sample format
124
125
    this format is initializable, unsupported to aid in testing the 
126
    open and open_downlevel routines.
127
    """
128
129
    def get_format_string(self):
130
        """See BzrBranchFormat.get_format_string()."""
131
        return "Sample branch format."
132
133
    def initialize(self, a_bzrdir):
134
        """Format 4 branches cannot be created."""
135
        t = a_bzrdir.get_branch_transport(self)
1955.3.9 by John Arbash Meinel
Find more occurrances of put() and replace with put_file or put_bytes
136
        t.put_bytes('format', self.get_format_string())
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
137
        return 'A branch'
138
139
    def is_supported(self):
140
        return False
141
142
    def open(self, transport, _found=False):
143
        return "opened branch."
144
145
146
class TestBzrBranchFormat(TestCaseWithTransport):
147
    """Tests for the BzrBranchFormat facility."""
148
149
    def test_find_format(self):
150
        # is the right format object found for a branch?
151
        # create a branch with a few known format objects.
152
        # this is not quite the same as 
153
        self.build_tree(["foo/", "bar/"])
154
        def check_format(format, url):
155
            dir = format._matchingbzrdir.initialize(url)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
156
            dir.create_repository()
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
157
            format.initialize(dir)
2297.1.2 by Martin Pool
Cleanup imports
158
            found_format = BranchFormat.find_format(dir)
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
159
            self.failUnless(isinstance(found_format, format.__class__))
2297.1.2 by Martin Pool
Cleanup imports
160
        check_format(BzrBranchFormat5(), "bar")
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
161
        
162
    def test_find_format_not_branch(self):
163
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
164
        self.assertRaises(NotBranchError,
2297.1.2 by Martin Pool
Cleanup imports
165
                          BranchFormat.find_format,
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
166
                          dir)
167
168
    def test_find_format_unknown_format(self):
169
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
170
        SampleBranchFormat().initialize(dir)
171
        self.assertRaises(UnknownFormatError,
2297.1.2 by Martin Pool
Cleanup imports
172
                          BranchFormat.find_format,
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
173
                          dir)
174
175
    def test_register_unregister_format(self):
176
        format = SampleBranchFormat()
177
        # make a control dir
178
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
179
        # make a branch
180
        format.initialize(dir)
181
        # register a format for it.
2297.1.2 by Martin Pool
Cleanup imports
182
        BranchFormat.register_format(format)
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
183
        # which branch.Open will refuse (not supported)
2297.1.2 by Martin Pool
Cleanup imports
184
        self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
2230.3.22 by Aaron Bentley
Make test suite use format registry default, not BzrDir default
185
        self.make_branch_and_tree('foo')
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
186
        # but open_downlevel will work
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
187
        self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
188
        # unregister the format
2297.1.2 by Martin Pool
Cleanup imports
189
        BranchFormat.unregister_format(format)
2230.3.22 by Aaron Bentley
Make test suite use format registry default, not BzrDir default
190
        self.make_branch_and_tree('bar')
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
191
192
2230.3.1 by Aaron Bentley
Get branch6 creation working
193
class TestBranch6(TestCaseWithTransport):
194
195
    def test_creation(self):
196
        format = BzrDirMetaFormat1()
2230.3.55 by Aaron Bentley
Updates from review
197
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
2230.3.1 by Aaron Bentley
Get branch6 creation working
198
        branch = self.make_branch('a', format=format)
199
        self.assertIsInstance(branch, _mod_branch.BzrBranch6)
1551.13.1 by Aaron Bentley
Introduce dirstate-tags format
200
        branch = self.make_branch('b', format='dirstate-tags')
2230.3.1 by Aaron Bentley
Get branch6 creation working
201
        self.assertIsInstance(branch, _mod_branch.BzrBranch6)
202
        branch = _mod_branch.Branch.open('a')
203
        self.assertIsInstance(branch, _mod_branch.BzrBranch6)
204
205
    def test_layout(self):
1551.13.1 by Aaron Bentley
Introduce dirstate-tags format
206
        branch = self.make_branch('a', format='dirstate-tags')
2230.3.1 by Aaron Bentley
Get branch6 creation working
207
        self.failUnlessExists('a/.bzr/branch/last-revision')
208
        self.failIfExists('a/.bzr/branch/revision-history')
209
2230.3.3 by Aaron Bentley
Add more config testing
210
    def test_config(self):
211
        """Ensure that all configuration data is stored in the branch"""
1551.13.1 by Aaron Bentley
Introduce dirstate-tags format
212
        branch = self.make_branch('a', format='dirstate-tags')
2230.3.3 by Aaron Bentley
Add more config testing
213
        branch.set_parent('http://bazaar-vcs.org')
214
        self.failIfExists('a/.bzr/branch/parent')
215
        self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
216
        branch.set_push_location('sftp://bazaar-vcs.org')
217
        config = branch.get_config()._get_branch_data_config()
2230.3.12 by Aaron Bentley
Clean up trailing whitespace
218
        self.assertEqual('sftp://bazaar-vcs.org',
2230.3.3 by Aaron Bentley
Add more config testing
219
                         config.get_user_option('push_location'))
220
        branch.set_bound_location('ftp://bazaar-vcs.org')
221
        self.failIfExists('a/.bzr/branch/bound')
222
        self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
223
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
224
    def test_set_revision_history(self):
225
        tree = self.make_branch_and_memory_tree('.',
1551.13.1 by Aaron Bentley
Introduce dirstate-tags format
226
            format='dirstate-tags')
2230.3.44 by Aaron Bentley
Change asserts to specific errors for left-hand history violations
227
        tree.lock_write()
228
        try:
229
            tree.add('.')
230
            tree.commit('foo', rev_id='foo')
231
            tree.commit('bar', rev_id='bar')
232
            tree.branch.set_revision_history(['foo', 'bar'])
233
            tree.branch.set_revision_history(['foo'])
234
            self.assertRaises(errors.NotLefthandHistory,
235
                              tree.branch.set_revision_history, ['bar'])
236
        finally:
237
            tree.unlock()
238
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
239
    def do_checkout_test(self, lightweight=False):
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
240
        tree = self.make_branch_and_tree('source', format='dirstate-with-subtree')
241
        subtree = self.make_branch_and_tree('source/subtree',
242
            format='dirstate-with-subtree')
2100.3.25 by Aaron Bentley
add subsubtree to test
243
        subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
244
            format='dirstate-with-subtree')
2100.3.25 by Aaron Bentley
add subsubtree to test
245
        self.build_tree(['source/subtree/file',
246
                         'source/subtree/subsubtree/file'])
247
        subsubtree.add('file')
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
248
        subtree.add('file')
2100.3.25 by Aaron Bentley
add subsubtree to test
249
        subtree.add_reference(subsubtree)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
250
        tree.add_reference(subtree)
251
        tree.commit('a revision')
2100.3.23 by Aaron Bentley
Nested checkouts kinda work
252
        subtree.commit('a subtree file')
2100.3.25 by Aaron Bentley
add subsubtree to test
253
        subsubtree.commit('a subsubtree file')
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
254
        tree.branch.create_checkout('target', lightweight=lightweight)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
255
        self.failUnlessExists('target')
256
        self.failUnlessExists('target/subtree')
257
        self.failUnlessExists('target/subtree/file')
2100.3.25 by Aaron Bentley
add subsubtree to test
258
        self.failUnlessExists('target/subtree/subsubtree/file')
2100.3.31 by Aaron Bentley
Merged bzr.dev (17 tests failing)
259
        subbranch = _mod_branch.Branch.open('target/subtree/subsubtree')
2100.3.26 by Aaron Bentley
checkout type is maintained for subtrees
260
        if lightweight:
261
            self.assertEndsWith(subbranch.base, 'source/subtree/subsubtree/')
262
        else:
263
            self.assertEndsWith(subbranch.base, 'target/subtree/subsubtree/')
264
265
    def test_checkout_with_references(self):
266
        self.do_checkout_test()
267
268
    def test_light_checkout_with_references(self):
269
        self.do_checkout_test(lightweight=True)
2230.3.51 by Aaron Bentley
Store revno for Branch6, set_last_revision -> set_last_revision_info
270
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
271
    def test_set_push(self):
272
        branch = self.make_branch('source', format='dirstate-tags')
273
        branch.get_config().set_user_option('push_location', 'old',
274
            store=config.STORE_LOCATION)
275
        warnings = []
276
        def warning(*args):
277
            warnings.append(args[0] % args[1:])
278
        _warning = trace.warning
279
        trace.warning = warning
280
        try:
281
            branch.set_push_location('new')
282
        finally:
283
            trace.warning = _warning
284
        self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
285
                         'locations.conf')
286
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
287
class TestBranchReference(TestCaseWithTransport):
288
    """Tests for the branch reference facility."""
289
290
    def test_create_open_reference(self):
291
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
292
        t = get_transport(self.get_url('.'))
293
        t.mkdir('repo')
294
        dir = bzrdirformat.initialize(self.get_url('repo'))
295
        dir.create_repository()
296
        target_branch = dir.create_branch()
297
        t.mkdir('branch')
298
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
2297.1.2 by Martin Pool
Cleanup imports
299
        made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
300
        self.assertEqual(made_branch.base, target_branch.base)
301
        opened_branch = branch_dir.open_branch()
302
        self.assertEqual(opened_branch.base, target_branch.base)
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
303
304
    def test_get_reference(self):
305
        """For a BranchReference, get_reference should reutrn the location."""
306
        branch = self.make_branch('target')
307
        checkout = branch.create_checkout('checkout', lightweight=True)
308
        reference_url = branch.bzrdir.root_transport.abspath('') + '/'
309
        # if the api for create_checkout changes to return different checkout types
310
        # then this file read will fail.
311
        self.assertFileEqual(reference_url, 'checkout/.bzr/branch/location')
312
        self.assertEqual(reference_url,
2018.5.97 by Andrew Bennetts
Fix more tests.
313
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
2018.5.45 by Andrew Bennetts
Merge from bzr.dev
314
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
315
316
class TestHooks(TestCase):
317
2245.1.2 by Robert Collins
Remove the static DefaultHooks method from Branch, replacing it with a derived dict BranchHooks object, which is easier to use and provides a place to put the policy-checking add method discussed on list.
318
    def test_constructor(self):
319
        """Check that creating a BranchHooks instance has the right defaults."""
2297.1.2 by Martin Pool
Cleanup imports
320
        hooks = BranchHooks()
2245.1.2 by Robert Collins
Remove the static DefaultHooks method from Branch, replacing it with a derived dict BranchHooks object, which is easier to use and provides a place to put the policy-checking add method discussed on list.
321
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
322
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
323
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
324
        self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
325
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
326
        self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
327
2245.1.2 by Robert Collins
Remove the static DefaultHooks method from Branch, replacing it with a derived dict BranchHooks object, which is easier to use and provides a place to put the policy-checking add method discussed on list.
328
    def test_installed_hooks_are_BranchHooks(self):
329
        """The installed hooks object should be a BranchHooks."""
330
        # the installed hooks are saved in self._preserved_hooks.
2376.3.5 by Robert Collins
Fix Branch hook tests for the new eans of preserving hooks by the test suite.
331
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch], BranchHooks)
2245.1.3 by Robert Collins
Add install_hook to the BranchHooks class as the official means for installing a hook.
332
2297.1.3 by Martin Pool
PullResult can pretend to be an int for api compatibility with old .pull()
333
334
class TestPullResult(TestCase):
335
336
    def test_pull_result_to_int(self):
337
        # to support old code, the pull result can be used as an int
338
        r = PullResult()
339
        r.old_revno = 10
340
        r.new_revno = 20
341
        # this usage of results is not recommended for new code (because it
342
        # doesn't describe very well what happened), but for api stability
343
        # it's still supported
344
        a = "%d revisions pulled" % r
345
        self.assertEqual(a, "10 revisions pulled")