~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_branch.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-07-13 19:02:12 UTC
  • mfrom: (4986.2.8 deprecation)
  • Revision ID: pqm@pqm.ubuntu.com-20100713190212-bnayd5moplwtxhhb
(mbp) change some test tearDowns to addCleanup or overrideAttr (Martin Pool)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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
19
19
 
20
20
import os
21
21
 
22
 
from bzrlib import (branch, bzrdir, errors, repository)
 
22
from bzrlib import (
 
23
    branch,
 
24
    bzrdir,
 
25
    errors,
 
26
    repository,
 
27
    revision as _mod_revision,
 
28
    )
23
29
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
24
 
from bzrlib.tests.blackbox import ExternalBase
25
 
from bzrlib.tests import HardlinkFeature
 
30
from bzrlib.tests import TestCaseWithTransport
 
31
from bzrlib.tests import (
 
32
    KnownFailure,
 
33
    HardlinkFeature,
 
34
    test_server,
 
35
    )
26
36
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
27
37
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
28
38
from bzrlib.workingtree import WorkingTree
29
39
 
30
40
 
31
 
class TestBranch(ExternalBase):
 
41
class TestBranch(TestCaseWithTransport):
32
42
 
33
43
    def example_branch(self, path='.'):
34
44
        tree = self.make_branch_and_tree(path)
49
59
        self.assertFalse(b._transport.has('branch-name'))
50
60
        b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
51
61
 
 
62
    def test_branch_switch_no_branch(self):
 
63
        # No branch in the current directory:
 
64
        #  => new branch will be created, but switch fails
 
65
        self.example_branch('a')
 
66
        self.make_repository('current')
 
67
        self.run_bzr_error(['No WorkingTree exists for'],
 
68
            'branch --switch ../a ../b', working_dir='current')
 
69
        a = branch.Branch.open('a')
 
70
        b = branch.Branch.open('b')
 
71
        self.assertEqual(a.last_revision(), b.last_revision())
 
72
 
 
73
    def test_branch_switch_no_wt(self):
 
74
        # No working tree in the current directory:
 
75
        #  => new branch will be created, but switch fails and the current
 
76
        #     branch is unmodified
 
77
        self.example_branch('a')
 
78
        self.make_branch('current')
 
79
        self.run_bzr_error(['No WorkingTree exists for'],
 
80
            'branch --switch ../a ../b', working_dir='current')
 
81
        a = branch.Branch.open('a')
 
82
        b = branch.Branch.open('b')
 
83
        self.assertEqual(a.last_revision(), b.last_revision())
 
84
        work = branch.Branch.open('current')
 
85
        self.assertEqual(work.last_revision(), _mod_revision.NULL_REVISION)
 
86
 
 
87
    def test_branch_switch_no_checkout(self):
 
88
        # Standalone branch in the current directory:
 
89
        #  => new branch will be created, but switch fails and the current
 
90
        #     branch is unmodified
 
91
        self.example_branch('a')
 
92
        self.make_branch_and_tree('current')
 
93
        self.run_bzr_error(['Cannot switch a branch, only a checkout'],
 
94
            'branch --switch ../a ../b', working_dir='current')
 
95
        a = branch.Branch.open('a')
 
96
        b = branch.Branch.open('b')
 
97
        self.assertEqual(a.last_revision(), b.last_revision())
 
98
        work = branch.Branch.open('current')
 
99
        self.assertEqual(work.last_revision(), _mod_revision.NULL_REVISION)
 
100
 
 
101
    def test_branch_switch_checkout(self):
 
102
        # Checkout in the current directory:
 
103
        #  => new branch will be created and checkout bound to the new branch
 
104
        self.example_branch('a')
 
105
        self.run_bzr('checkout a current')
 
106
        out, err = self.run_bzr('branch --switch ../a ../b', working_dir='current')
 
107
        a = branch.Branch.open('a')
 
108
        b = branch.Branch.open('b')
 
109
        self.assertEqual(a.last_revision(), b.last_revision())
 
110
        work = WorkingTree.open('current')
 
111
        self.assertEndsWith(work.branch.get_bound_location(), '/b/')
 
112
        self.assertContainsRe(err, "Switched to branch: .*/b/")
 
113
 
 
114
    def test_branch_switch_lightweight_checkout(self):
 
115
        # Lightweight checkout in the current directory:
 
116
        #  => new branch will be created and lightweight checkout pointed to
 
117
        #     the new branch
 
118
        self.example_branch('a')
 
119
        self.run_bzr('checkout --lightweight a current')
 
120
        out, err = self.run_bzr('branch --switch ../a ../b', working_dir='current')
 
121
        a = branch.Branch.open('a')
 
122
        b = branch.Branch.open('b')
 
123
        self.assertEqual(a.last_revision(), b.last_revision())
 
124
        work = WorkingTree.open('current')
 
125
        self.assertEndsWith(work.branch.base, '/b/')
 
126
        self.assertContainsRe(err, "Switched to branch: .*/b/")
 
127
 
52
128
    def test_branch_only_copies_history(self):
53
129
        # Knit branches should only push the history for the current revision.
54
130
        format = bzrdir.BzrDirMetaFormat1()
93
169
        self.build_tree(['source/file1'])
94
170
        source.add('file1')
95
171
        source.commit('added file')
96
 
        self.run_bzr(['branch', 'source', 'target', '--hardlink'])
 
172
        out, err = self.run_bzr(['branch', 'source', 'target', '--hardlink'])
97
173
        source_stat = os.stat('source/file1')
98
174
        target_stat = os.stat('target/file1')
99
175
        self.assertEqual(source_stat, target_stat)
113
189
        self.failIfExists('target/hello')
114
190
        self.failIfExists('target/goodbye')
115
191
 
116
 
 
117
 
class TestBranchStacked(ExternalBase):
 
192
    def test_branch_into_existing_dir(self):
 
193
        self.example_branch('a')
 
194
        # existing dir with similar files but no .bzr dir
 
195
        self.build_tree_contents([('b/',)])
 
196
        self.build_tree_contents([('b/hello', 'bar')])  # different content
 
197
        self.build_tree_contents([('b/goodbye', 'baz')])# same content
 
198
        # fails without --use-existing-dir
 
199
        out,err = self.run_bzr('branch a b', retcode=3)
 
200
        self.assertEqual('', out)
 
201
        self.assertEqual('bzr: ERROR: Target directory "b" already exists.\n',
 
202
            err)
 
203
        # force operation
 
204
        self.run_bzr('branch a b --use-existing-dir')
 
205
        # check conflicts
 
206
        self.failUnlessExists('b/hello.moved')
 
207
        self.failIfExists('b/godbye.moved')
 
208
        # we can't branch into branch
 
209
        out,err = self.run_bzr('branch a b --use-existing-dir', retcode=3)
 
210
        self.assertEqual('', out)
 
211
        self.assertEqual('bzr: ERROR: Already a branch: "b".\n', err)
 
212
 
 
213
    def test_branch_bind(self):
 
214
        self.example_branch('a')
 
215
        out, err = self.run_bzr('branch a b --bind')
 
216
        self.assertEndsWith(err, "New branch bound to a\n")
 
217
        b = branch.Branch.open('b')
 
218
        self.assertEndsWith(b.get_bound_location(), '/a/')
 
219
 
 
220
    def test_branch_with_post_branch_init_hook(self):
 
221
        calls = []
 
222
        branch.Branch.hooks.install_named_hook('post_branch_init',
 
223
            calls.append, None)
 
224
        self.assertLength(0, calls)
 
225
        self.example_branch('a')
 
226
        self.assertLength(1, calls)
 
227
        self.run_bzr('branch a b')
 
228
        self.assertLength(2, calls)
 
229
 
 
230
    def test_checkout_with_post_branch_init_hook(self):
 
231
        calls = []
 
232
        branch.Branch.hooks.install_named_hook('post_branch_init',
 
233
            calls.append, None)
 
234
        self.assertLength(0, calls)
 
235
        self.example_branch('a')
 
236
        self.assertLength(1, calls)
 
237
        self.run_bzr('checkout a b')
 
238
        self.assertLength(2, calls)
 
239
 
 
240
    def test_lightweight_checkout_with_post_branch_init_hook(self):
 
241
        calls = []
 
242
        branch.Branch.hooks.install_named_hook('post_branch_init',
 
243
            calls.append, None)
 
244
        self.assertLength(0, calls)
 
245
        self.example_branch('a')
 
246
        self.assertLength(1, calls)
 
247
        self.run_bzr('checkout --lightweight a b')
 
248
        self.assertLength(2, calls)
 
249
 
 
250
 
 
251
class TestBranchStacked(TestCaseWithTransport):
118
252
    """Tests for branch --stacked"""
119
253
 
120
 
    def check_shallow_branch(self, branch_revid, stacked_on):
121
 
        """Assert that the branch 'newbranch' has been published correctly.
122
 
 
123
 
        :param stacked_on: url of a branch this one is stacked upon.
124
 
        :param branch_revid: a revision id that should be the only
125
 
            revision present in the stacked branch, and it should not be in
126
 
            the reference branch.
127
 
        """
128
 
        new_branch = branch.Branch.open('newbranch')
129
 
        # The branch refers to the mainline
130
 
        self.assertEqual(stacked_on, new_branch.get_stacked_on_url())
131
 
        # and the branch's work was pushed
132
 
        self.assertTrue(new_branch.repository.has_revision(branch_revid))
133
 
        # The newly committed revision shoud be present in the stacked branch,
134
 
        # but not in the stacked-on branch.  Because stacking is set up by the
135
 
        # branch object, if we open the stacked branch's repository directly,
136
 
        # bypassing the branch, we see only what's in the stacked repository.
137
 
        stacked_repo = bzrdir.BzrDir.open('newbranch').open_repository()
138
 
        stacked_repo_revisions = set(stacked_repo.all_revision_ids())
139
 
        if len(stacked_repo_revisions) != 1:
140
 
            self.fail("wrong revisions in stacked repository: %r"
141
 
                % (stacked_repo_revisions,))
142
 
 
143
254
    def assertRevisionInRepository(self, repo_path, revid):
144
255
        """Check that a revision is in a repository, disregarding stacking."""
145
256
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
159
270
        """Branching a stacked branch is not stacked by default"""
160
271
        # We have a mainline
161
272
        trunk_tree = self.make_branch_and_tree('target',
162
 
            format='development')
 
273
            format='1.9')
163
274
        trunk_tree.commit('mainline')
164
275
        # and a branch from it which is stacked
165
276
        branch_tree = self.make_branch_and_tree('branch',
166
 
            format='development')
 
277
            format='1.9')
167
278
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
168
279
        # with some work on it
169
 
        branch_tree.commit('moar work plz')
 
280
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
 
281
        work_tree.commit('moar work plz')
 
282
        work_tree.branch.push(branch_tree.branch)
170
283
        # branching our local branch gives us a new stacked branch pointing at
171
284
        # mainline.
172
285
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
173
286
        self.assertEqual('', out)
174
 
        self.assertEqual('Branched 1 revision(s).\n',
 
287
        self.assertEqual('Branched 2 revision(s).\n',
175
288
            err)
176
289
        # it should have preserved the branch format, and so it should be
177
290
        # capable of supporting stacking, but not actually have a stacked_on
183
296
        """Asking to stack on a stacked branch does work"""
184
297
        # We have a mainline
185
298
        trunk_tree = self.make_branch_and_tree('target',
186
 
            format='development')
 
299
            format='1.9')
187
300
        trunk_revid = trunk_tree.commit('mainline')
188
301
        # and a branch from it which is stacked
189
302
        branch_tree = self.make_branch_and_tree('branch',
190
 
            format='development')
 
303
            format='1.9')
191
304
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
192
305
        # with some work on it
193
 
        branch_revid = branch_tree.commit('moar work plz')
 
306
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
 
307
        branch_revid = work_tree.commit('moar work plz')
 
308
        work_tree.branch.push(branch_tree.branch)
194
309
        # you can chain branches on from there
195
310
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
196
311
        self.assertEqual('', out)
199
314
        self.assertEqual(branch_tree.branch.base,
200
315
            branch.Branch.open('branch2').get_stacked_on_url())
201
316
        branch2_tree = WorkingTree.open('branch2')
202
 
        branch2_revid = branch2_tree.commit('work on second stacked branch')
 
317
        branch2_revid = work_tree.commit('work on second stacked branch')
 
318
        work_tree.branch.push(branch2_tree.branch)
203
319
        self.assertRevisionInRepository('branch2', branch2_revid)
204
320
        self.assertRevisionsInBranchRepository(
205
321
            [trunk_revid, branch_revid, branch2_revid],
208
324
    def test_branch_stacked(self):
209
325
        # We have a mainline
210
326
        trunk_tree = self.make_branch_and_tree('mainline',
211
 
            format='development')
 
327
            format='1.9')
212
328
        original_revid = trunk_tree.commit('mainline')
213
329
        self.assertRevisionInRepository('mainline', original_revid)
214
330
        # and a branch from it which is stacked
218
334
        self.assertEqual('Created new stacked branch referring to %s.\n' %
219
335
            trunk_tree.branch.base, err)
220
336
        self.assertRevisionNotInRepository('newbranch', original_revid)
221
 
        new_tree = WorkingTree.open('newbranch')
222
 
        new_revid = new_tree.commit('new work')
223
 
        self.check_shallow_branch(new_revid, trunk_tree.branch.base)
 
337
        new_branch = branch.Branch.open('newbranch')
 
338
        self.assertEqual(trunk_tree.branch.base, new_branch.get_stacked_on_url())
224
339
 
225
340
    def test_branch_stacked_from_smart_server(self):
226
341
        # We can branch stacking on a smart server
227
 
        from bzrlib.smart.server import SmartTCPServer_for_testing
228
 
        self.transport_server = SmartTCPServer_for_testing
229
 
        trunk = self.make_branch('mainline', format='development')
 
342
        self.transport_server = test_server.SmartTCPServer_for_testing
 
343
        trunk = self.make_branch('mainline', format='1.9')
230
344
        out, err = self.run_bzr(
231
345
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
232
346
 
237
351
            ['branch', '--stacked', 'trunk', 'shallow'])
238
352
        # We should notify the user that we upgraded their format
239
353
        self.assertEqualDiff(
240
 
            'Source format does not support stacking, using format: \'1.6\'\n'
 
354
            'Source repository format does not support stacking, using format:\n'
241
355
            '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
242
 
            '\n'
 
356
            'Source branch format does not support stacking, using format:\n'
 
357
            '  Branch format 7\n'
 
358
            'Doing on-the-fly conversion from RepositoryFormatKnitPack1() to RepositoryFormatKnitPack5().\n'
 
359
            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
243
360
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
244
361
            err)
245
362
 
249
366
            ['branch', '--stacked', 'trunk', 'shallow'])
250
367
        # We should notify the user that we upgraded their format
251
368
        self.assertEqualDiff(
252
 
            'Source format does not support stacking, using format:'
253
 
            ' \'1.6.1-rich-root\'\n'
 
369
            'Source repository format does not support stacking, using format:\n'
254
370
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
255
 
            '\n'
 
371
            'Source branch format does not support stacking, using format:\n'
 
372
            '  Branch format 7\n'
 
373
            'Doing on-the-fly conversion from RepositoryFormatKnitPack4() to RepositoryFormatKnitPack5RichRoot().\n'
 
374
            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
256
375
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
257
376
            err)
258
377
 
259
378
 
260
 
class TestSmartServerBranching(ExternalBase):
 
379
class TestSmartServerBranching(TestCaseWithTransport):
261
380
 
262
381
    def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
263
382
        self.setup_smart_server_with_call_log()
267
386
        self.reset_smart_call_log()
268
387
        out, err = self.run_bzr(['branch', self.get_url('from'),
269
388
            self.get_url('target')])
270
 
        rpc_count = len(self.hpss_calls)
271
389
        # This figure represent the amount of work to perform this use case. It
272
390
        # is entirely ok to reduce this number if a test fails due to rpc_count
273
391
        # being too low. If rpc_count increases, more network roundtrips have
274
392
        # become necessary for this use case. Please do not adjust this number
275
393
        # upwards without agreement from bzr's network support maintainers.
276
 
        self.assertEqual(53, rpc_count)
 
394
        self.assertLength(38, self.hpss_calls)
277
395
 
278
396
    def test_branch_from_trivial_branch_streaming_acceptance(self):
279
397
        self.setup_smart_server_with_call_log()
283
401
        self.reset_smart_call_log()
284
402
        out, err = self.run_bzr(['branch', self.get_url('from'),
285
403
            'local-target'])
286
 
        rpc_count = len(self.hpss_calls)
287
404
        # This figure represent the amount of work to perform this use case. It
288
405
        # is entirely ok to reduce this number if a test fails due to rpc_count
289
406
        # being too low. If rpc_count increases, more network roundtrips have
290
407
        # become necessary for this use case. Please do not adjust this number
291
408
        # upwards without agreement from bzr's network support maintainers.
292
 
        self.assertEqual(10, rpc_count)
 
409
        self.assertLength(10, self.hpss_calls)
293
410
 
294
411
    def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
295
412
        self.setup_smart_server_with_call_log()
298
415
            t.commit(message='commit %d' % count)
299
416
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
300
417
            ).open_workingtree()
301
 
        tree2.commit('feature change')
 
418
        local_tree = t.branch.bzrdir.sprout('local-working').open_workingtree()
 
419
        local_tree.commit('feature change')
 
420
        local_tree.branch.push(tree2.branch)
302
421
        self.reset_smart_call_log()
303
422
        out, err = self.run_bzr(['branch', self.get_url('feature'),
304
423
            'local-target'])
307
426
        # being too low. If rpc_count increases, more network roundtrips have
308
427
        # become necessary for this use case. Please do not adjust this number
309
428
        # upwards without agreement from bzr's network support maintainers.
310
 
        self.assertLength(23, self.hpss_calls)
 
429
        self.assertLength(15, self.hpss_calls)
311
430
 
312
431
 
313
432
class TestRemoteBranch(TestCaseWithSFTPServer):