~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: 2009-04-09 23:12:55 UTC
  • mfrom: (3920.2.37 dpush)
  • Revision ID: pqm@pqm.ubuntu.com-20090409231255-o8w1g2q3igiyf8b2
(Jelmer) Add the dpush command.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2008, 2009 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 (
23
 
    branch,
24
 
    bzrdir,
25
 
    errors,
26
 
    repository,
27
 
    revision as _mod_revision,
28
 
    )
 
22
from bzrlib import (branch, bzrdir, errors, repository)
29
23
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
30
 
from bzrlib.tests import TestCaseWithTransport
31
 
from bzrlib.tests import (
32
 
    KnownFailure,
33
 
    HardlinkFeature,
34
 
    test_server,
35
 
    )
 
24
from bzrlib.tests.blackbox import ExternalBase
 
25
from bzrlib.tests import HardlinkFeature
36
26
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
37
27
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
38
28
from bzrlib.workingtree import WorkingTree
39
29
 
40
30
 
41
 
class TestBranch(TestCaseWithTransport):
 
31
class TestBranch(ExternalBase):
42
32
 
43
33
    def example_branch(self, path='.'):
44
34
        tree = self.make_branch_and_tree(path)
59
49
        self.assertFalse(b._transport.has('branch-name'))
60
50
        b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
61
51
 
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
 
 
128
52
    def test_branch_only_copies_history(self):
129
53
        # Knit branches should only push the history for the current revision.
130
54
        format = bzrdir.BzrDirMetaFormat1()
169
93
        self.build_tree(['source/file1'])
170
94
        source.add('file1')
171
95
        source.commit('added file')
172
 
        out, err = self.run_bzr(['branch', 'source', 'target', '--hardlink'])
 
96
        self.run_bzr(['branch', 'source', 'target', '--hardlink'])
173
97
        source_stat = os.stat('source/file1')
174
98
        target_stat = os.stat('target/file1')
175
99
        self.assertEqual(source_stat, target_stat)
189
113
        self.failIfExists('target/hello')
190
114
        self.failIfExists('target/goodbye')
191
115
 
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):
 
116
 
 
117
class TestBranchStacked(ExternalBase):
252
118
    """Tests for branch --stacked"""
253
119
 
 
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
 
254
143
    def assertRevisionInRepository(self, repo_path, revid):
255
144
        """Check that a revision is in a repository, disregarding stacking."""
256
145
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
277
166
            format='1.9')
278
167
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
279
168
        # with some work on it
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)
 
169
        branch_tree.commit('moar work plz')
283
170
        # branching our local branch gives us a new stacked branch pointing at
284
171
        # mainline.
285
172
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
286
173
        self.assertEqual('', out)
287
 
        self.assertEqual('Branched 2 revision(s).\n',
 
174
        self.assertEqual('Branched 1 revision(s).\n',
288
175
            err)
289
176
        # it should have preserved the branch format, and so it should be
290
177
        # capable of supporting stacking, but not actually have a stacked_on
303
190
            format='1.9')
304
191
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
305
192
        # with some work on it
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)
 
193
        branch_revid = branch_tree.commit('moar work plz')
309
194
        # you can chain branches on from there
310
195
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
311
196
        self.assertEqual('', out)
314
199
        self.assertEqual(branch_tree.branch.base,
315
200
            branch.Branch.open('branch2').get_stacked_on_url())
316
201
        branch2_tree = WorkingTree.open('branch2')
317
 
        branch2_revid = work_tree.commit('work on second stacked branch')
318
 
        work_tree.branch.push(branch2_tree.branch)
 
202
        branch2_revid = branch2_tree.commit('work on second stacked branch')
319
203
        self.assertRevisionInRepository('branch2', branch2_revid)
320
204
        self.assertRevisionsInBranchRepository(
321
205
            [trunk_revid, branch_revid, branch2_revid],
334
218
        self.assertEqual('Created new stacked branch referring to %s.\n' %
335
219
            trunk_tree.branch.base, err)
336
220
        self.assertRevisionNotInRepository('newbranch', original_revid)
337
 
        new_branch = branch.Branch.open('newbranch')
338
 
        self.assertEqual(trunk_tree.branch.base, new_branch.get_stacked_on_url())
 
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)
339
224
 
340
225
    def test_branch_stacked_from_smart_server(self):
341
226
        # We can branch stacking on a smart server
342
 
        self.transport_server = test_server.SmartTCPServer_for_testing
 
227
        from bzrlib.smart.server import SmartTCPServer_for_testing
 
228
        self.transport_server = SmartTCPServer_for_testing
343
229
        trunk = self.make_branch('mainline', format='1.9')
344
230
        out, err = self.run_bzr(
345
231
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
351
237
            ['branch', '--stacked', 'trunk', 'shallow'])
352
238
        # We should notify the user that we upgraded their format
353
239
        self.assertEqualDiff(
354
 
            'Source repository format does not support stacking, using format:\n'
 
240
            'Source format does not support stacking, using format: \'1.6\'\n'
355
241
            '  Packs 5 (adds stacking support, requires bzr 1.6)\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'
 
242
            '\n'
360
243
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
361
244
            err)
362
245
 
366
249
            ['branch', '--stacked', 'trunk', 'shallow'])
367
250
        # We should notify the user that we upgraded their format
368
251
        self.assertEqualDiff(
369
 
            'Source repository format does not support stacking, using format:\n'
 
252
            'Source format does not support stacking, using format:'
 
253
            ' \'1.6.1-rich-root\'\n'
370
254
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\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'
 
255
            '\n'
375
256
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
376
257
            err)
377
258
 
378
259
 
379
 
class TestSmartServerBranching(TestCaseWithTransport):
 
260
class TestSmartServerBranching(ExternalBase):
380
261
 
381
262
    def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
382
263
        self.setup_smart_server_with_call_log()
391
272
        # being too low. If rpc_count increases, more network roundtrips have
392
273
        # become necessary for this use case. Please do not adjust this number
393
274
        # upwards without agreement from bzr's network support maintainers.
394
 
        self.assertLength(38, self.hpss_calls)
 
275
        self.assertLength(53, self.hpss_calls)
395
276
 
396
277
    def test_branch_from_trivial_branch_streaming_acceptance(self):
397
278
        self.setup_smart_server_with_call_log()
415
296
            t.commit(message='commit %d' % count)
416
297
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
417
298
            ).open_workingtree()
418
 
        local_tree = t.branch.bzrdir.sprout('local-working').open_workingtree()
419
 
        local_tree.commit('feature change')
420
 
        local_tree.branch.push(tree2.branch)
 
299
        tree2.commit('feature change')
421
300
        self.reset_smart_call_log()
422
301
        out, err = self.run_bzr(['branch', self.get_url('feature'),
423
302
            'local-target'])