~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: John Arbash Meinel
  • Date: 2009-03-27 22:29:55 UTC
  • mto: (3735.39.2 clean)
  • mto: This revision was merged to the branch mainline in revision 4280.
  • Revision ID: john@arbash-meinel.com-20090327222955-utifmfm888zerixt
Implement apply_delta_to_source which doesn't have to malloc another string.

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
24
from bzrlib.tests.blackbox import ExternalBase
31
 
from bzrlib.tests import (
32
 
    KnownFailure,
33
 
    HardlinkFeature,
34
 
    test_server,
35
 
    )
 
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
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
116
 
251
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()
270
159
        """Branching a stacked branch is not stacked by default"""
271
160
        # We have a mainline
272
161
        trunk_tree = self.make_branch_and_tree('target',
273
 
            format='1.9')
 
162
            format='development')
274
163
        trunk_tree.commit('mainline')
275
164
        # and a branch from it which is stacked
276
165
        branch_tree = self.make_branch_and_tree('branch',
277
 
            format='1.9')
 
166
            format='development')
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
296
183
        """Asking to stack on a stacked branch does work"""
297
184
        # We have a mainline
298
185
        trunk_tree = self.make_branch_and_tree('target',
299
 
            format='1.9')
 
186
            format='development')
300
187
        trunk_revid = trunk_tree.commit('mainline')
301
188
        # and a branch from it which is stacked
302
189
        branch_tree = self.make_branch_and_tree('branch',
303
 
            format='1.9')
 
190
            format='development')
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],
324
208
    def test_branch_stacked(self):
325
209
        # We have a mainline
326
210
        trunk_tree = self.make_branch_and_tree('mainline',
327
 
            format='1.9')
 
211
            format='development')
328
212
        original_revid = trunk_tree.commit('mainline')
329
213
        self.assertRevisionInRepository('mainline', original_revid)
330
214
        # and a branch from it which is stacked
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
343
 
        trunk = self.make_branch('mainline', format='1.9')
 
227
        from bzrlib.smart.server import SmartTCPServer_for_testing
 
228
        self.transport_server = SmartTCPServer_for_testing
 
229
        trunk = self.make_branch('mainline', format='development')
344
230
        out, err = self.run_bzr(
345
231
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
346
232
 
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
 
386
267
        self.reset_smart_call_log()
387
268
        out, err = self.run_bzr(['branch', self.get_url('from'),
388
269
            self.get_url('target')])
 
270
        rpc_count = len(self.hpss_calls)
389
271
        # This figure represent the amount of work to perform this use case. It
390
272
        # is entirely ok to reduce this number if a test fails due to rpc_count
391
273
        # being too low. If rpc_count increases, more network roundtrips have
392
274
        # become necessary for this use case. Please do not adjust this number
393
275
        # upwards without agreement from bzr's network support maintainers.
394
 
        self.assertLength(38, self.hpss_calls)
 
276
        self.assertEqual(53, rpc_count)
395
277
 
396
278
    def test_branch_from_trivial_branch_streaming_acceptance(self):
397
279
        self.setup_smart_server_with_call_log()
401
283
        self.reset_smart_call_log()
402
284
        out, err = self.run_bzr(['branch', self.get_url('from'),
403
285
            'local-target'])
 
286
        rpc_count = len(self.hpss_calls)
404
287
        # This figure represent the amount of work to perform this use case. It
405
288
        # is entirely ok to reduce this number if a test fails due to rpc_count
406
289
        # being too low. If rpc_count increases, more network roundtrips have
407
290
        # become necessary for this use case. Please do not adjust this number
408
291
        # upwards without agreement from bzr's network support maintainers.
409
 
        self.assertLength(10, self.hpss_calls)
 
292
        self.assertEqual(10, rpc_count)
410
293
 
411
294
    def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
412
295
        self.setup_smart_server_with_call_log()
415
298
            t.commit(message='commit %d' % count)
416
299
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
417
300
            ).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)
 
301
        tree2.commit('feature change')
421
302
        self.reset_smart_call_log()
422
303
        out, err = self.run_bzr(['branch', self.get_url('feature'),
423
304
            'local-target'])
426
307
        # being too low. If rpc_count increases, more network roundtrips have
427
308
        # become necessary for this use case. Please do not adjust this number
428
309
        # upwards without agreement from bzr's network support maintainers.
429
 
        self.assertLength(15, self.hpss_calls)
 
310
        self.assertLength(23, self.hpss_calls)
430
311
 
431
312
 
432
313
class TestRemoteBranch(TestCaseWithSFTPServer):