/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

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

  • Committer: John Arbash Meinel
  • Date: 2006-04-25 15:05:42 UTC
  • mfrom: (1185.85.85 bzr-encoding)
  • mto: This revision was merged to the branch mainline in revision 1752.
  • Revision ID: john@arbash-meinel.com-20060425150542-c7b518dca9928691
[merge] the old bzr-encoding changes, reparenting them on bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2012, 2016 Canonical Ltd
2
 
#
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
 
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
5
6
# the Free Software Foundation; either version 2 of the License, or
6
7
# (at your option) any later version.
7
 
#
 
8
 
8
9
# This program is distributed in the hope that it will be useful,
9
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
12
# GNU General Public License for more details.
12
 
#
 
13
 
13
14
# You should have received a copy of the GNU General Public License
14
15
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
 
18
 
"""Black-box tests for brz push."""
19
 
 
20
 
import re
21
 
 
22
 
from breezy import (
23
 
    branch,
24
 
    controldir,
25
 
    directory_service,
26
 
    errors,
27
 
    osutils,
28
 
    tests,
29
 
    transport,
30
 
    uncommit,
31
 
    urlutils,
32
 
    workingtree
33
 
    )
34
 
from breezy.bzr import (
35
 
    bzrdir,
36
 
    )
37
 
from breezy.bzr import knitrepo
38
 
from breezy.tests import (
39
 
    http_server,
40
 
    scenarios,
41
 
    script,
42
 
    test_foreign,
43
 
    )
44
 
from breezy.tests.matchers import ContainsNoVfsCalls
45
 
from breezy.transport import memory
46
 
 
47
 
 
48
 
load_tests = scenarios.load_tests_apply_scenarios
49
 
 
50
 
 
51
 
class TestPush(tests.TestCaseWithTransport):
52
 
 
53
 
    def test_push_error_on_vfs_http(self):
54
 
        """ pushing a branch to a HTTP server fails cleanly. """
55
 
        # the trunk is published on a web server
56
 
        self.transport_readonly_server = http_server.HttpServer
57
 
        self.make_branch('source')
58
 
        public_url = self.get_readonly_url('target')
59
 
        self.run_bzr_error(['http does not support mkdir'],
60
 
                           ['push', public_url],
61
 
                           working_dir='source')
62
 
 
63
 
    def test_push_suggests_parent_alias(self):
64
 
        """Push suggests using :parent if there is a known parent branch."""
65
 
        tree_a = self.make_branch_and_tree('a')
66
 
        tree_a.commit('this is a commit')
67
 
        tree_b = self.make_branch_and_tree('b')
68
 
 
69
 
        # If there is no parent location set, :parent isn't mentioned.
70
 
        out = self.run_bzr('push', working_dir='a', retcode=3)
71
 
        self.assertEqual(out,
72
 
                         ('', 'brz: ERROR: No push location known or specified.\n'))
73
 
 
74
 
        # If there is a parent location set, the error suggests :parent.
75
 
        tree_a.branch.set_parent(tree_b.branch.base)
76
 
        out = self.run_bzr('push', working_dir='a', retcode=3)
77
 
        self.assertEqual(out,
78
 
                         ('', 'brz: ERROR: No push location known or specified. '
79
 
                          'To push to the parent branch '
80
 
                          '(at %s), use \'brz push :parent\'.\n' %
81
 
                          urlutils.unescape_for_display(tree_b.branch.base, 'utf-8')))
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
 
 
19
"""Black-box tests for bzr push.
 
20
"""
 
21
 
 
22
import os
 
23
 
 
24
from bzrlib.branch import Branch
 
25
from bzrlib.osutils import abspath
 
26
from bzrlib.tests.blackbox import ExternalBase
 
27
from bzrlib.uncommit import uncommit
 
28
 
 
29
 
 
30
class TestPush(ExternalBase):
82
31
 
83
32
    def test_push_remember(self):
84
33
        """Push changes from one branch to another and test push location."""
88
37
        self.build_tree(['branch_a/a'])
89
38
        tree_a.add('a')
90
39
        tree_a.commit('commit a')
91
 
        tree_b = branch_a.controldir.sprout('branch_b').open_workingtree()
 
40
        tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
92
41
        branch_b = tree_b.branch
93
 
        tree_c = branch_a.controldir.sprout('branch_c').open_workingtree()
 
42
        tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
94
43
        branch_c = tree_c.branch
95
44
        self.build_tree(['branch_a/b'])
96
45
        tree_a.add('b')
100
49
        tree_b.commit('commit c')
101
50
        # initial push location must be empty
102
51
        self.assertEqual(None, branch_b.get_push_location())
103
 
 
104
52
        # test push for failure without push location set
105
 
        out = self.run_bzr('push', working_dir='branch_a', retcode=3)
106
 
        self.assertEqual(out,
107
 
                         ('', 'brz: ERROR: No push location known or specified.\n'))
108
 
 
109
 
        # test not remembered if cannot actually push
110
 
        self.run_bzr('push path/which/doesnt/exist',
111
 
                     working_dir='branch_a', retcode=3)
112
 
        out = self.run_bzr('push', working_dir='branch_a', retcode=3)
113
 
        self.assertEqual(
114
 
            ('', 'brz: ERROR: No push location known or specified.\n'),
115
 
            out)
116
 
 
 
53
        os.chdir('branch_a')
 
54
        out = self.runbzr('push', retcode=3)
 
55
        self.assertEquals(out,
 
56
                ('','bzr: ERROR: No push location known or specified.\n'))
117
57
        # test implicit --remember when no push location set, push fails
118
 
        out = self.run_bzr('push ../branch_b',
119
 
                           working_dir='branch_a', retcode=3)
120
 
        self.assertEqual(out,
121
 
                         ('', 'brz: ERROR: These branches have diverged.  '
122
 
                          'See "brz help diverged-branches" for more information.\n'))
123
 
        # Refresh the branch as 'push' modified it
124
 
        branch_a = branch_a.controldir.open_branch()
125
 
        self.assertEqual(osutils.abspath(branch_a.get_push_location()),
126
 
                         osutils.abspath(branch_b.controldir.root_transport.base))
127
 
 
 
58
        out = self.runbzr('push ../branch_b', retcode=3)
 
59
        self.assertEquals(out,
 
60
                ('','bzr: ERROR: These branches have diverged.  '
 
61
                    'Try a merge then push with overwrite.\n'))
 
62
        self.assertEquals(abspath(branch_a.get_push_location()),
 
63
                          abspath(branch_b.bzrdir.root_transport.base))
128
64
        # test implicit --remember after resolving previous failure
129
 
        uncommit.uncommit(branch=branch_b, tree=tree_b)
 
65
        uncommit(branch=branch_b, tree=tree_b)
130
66
        transport.delete('branch_b/c')
131
 
        out, err = self.run_bzr('push', working_dir='branch_a')
132
 
        # Refresh the branch as 'push' modified it
133
 
        branch_a = branch_a.controldir.open_branch()
134
 
        path = branch_a.get_push_location()
135
 
        self.assertEqual(err,
136
 
                         'Using saved push location: %s\n'
137
 
                         'All changes applied successfully.\n'
138
 
                         'Pushed up to revision 2.\n'
139
 
                         % urlutils.local_path_from_url(path))
140
 
        self.assertEqual(path,
141
 
                         branch_b.controldir.root_transport.base)
 
67
        self.runbzr('push')
 
68
        self.assertEquals(abspath(branch_a.get_push_location()),
 
69
                          abspath(branch_b.bzrdir.root_transport.base))
142
70
        # test explicit --remember
143
 
        self.run_bzr('push ../branch_c --remember', working_dir='branch_a')
144
 
        # Refresh the branch as 'push' modified it
145
 
        branch_a = branch_a.controldir.open_branch()
146
 
        self.assertEqual(branch_a.get_push_location(),
147
 
                         branch_c.controldir.root_transport.base)
148
 
 
149
 
    def test_push_without_tree(self):
150
 
        # brz push from a branch that does not have a checkout should work.
151
 
        b = self.make_branch('.')
152
 
        out, err = self.run_bzr('push pushed-location')
153
 
        self.assertEqual('', out)
154
 
        self.assertEqual('Created new branch.\n', err)
155
 
        b2 = branch.Branch.open('pushed-location')
156
 
        self.assertEndsWith(b2.base, 'pushed-location/')
157
 
 
158
 
    def test_push_no_tree(self):
159
 
        # brz push --no-tree of a branch with working trees
160
 
        b = self.make_branch_and_tree('push-from')
161
 
        self.build_tree(['push-from/file'])
162
 
        b.add('file')
163
 
        b.commit('commit 1')
164
 
        out, err = self.run_bzr('push --no-tree -d push-from push-to')
165
 
        self.assertEqual('', out)
166
 
        self.assertEqual('Created new branch.\n', err)
167
 
        self.assertPathDoesNotExist('push-to/file')
168
 
 
169
 
    def test_push_new_branch_revision_count(self):
170
 
        # brz push of a branch with revisions to a new location
171
 
        # should print the number of revisions equal to the length of the
172
 
        # local branch.
173
 
        t = self.make_branch_and_tree('tree')
174
 
        self.build_tree(['tree/file'])
175
 
        t.add('file')
176
 
        t.commit('commit 1')
177
 
        out, err = self.run_bzr('push -d tree pushed-to')
178
 
        self.assertEqual('', out)
179
 
        self.assertEqual('Created new branch.\n', err)
180
 
 
181
 
    def test_push_quiet(self):
182
 
        # test that using -q makes output quiet
183
 
        t = self.make_branch_and_tree('tree')
184
 
        self.build_tree(['tree/file'])
185
 
        t.add('file')
186
 
        t.commit('commit 1')
187
 
        self.run_bzr('push -d tree pushed-to')
188
 
        # Refresh the branch as 'push' modified it and get the push location
189
 
        push_loc = t.branch.controldir.open_branch().get_push_location()
190
 
        out, err = self.run_bzr('push', working_dir="tree")
191
 
        self.assertEqual('Using saved push location: %s\n'
192
 
                         'No new revisions or tags to push.\n' %
193
 
                         urlutils.local_path_from_url(push_loc), err)
194
 
        out, err = self.run_bzr('push -q', working_dir="tree")
195
 
        self.assertEqual('', out)
196
 
        self.assertEqual('', err)
197
 
 
198
 
    def test_push_only_pushes_history(self):
199
 
        # Knit branches should only push the history for the current revision.
200
 
        format = bzrdir.BzrDirMetaFormat1()
201
 
        format.repository_format = knitrepo.RepositoryFormatKnit1()
202
 
        shared_repo = self.make_repository('repo', format=format, shared=True)
203
 
        shared_repo.set_make_working_trees(True)
204
 
 
205
 
        def make_shared_tree(path):
206
 
            shared_repo.controldir.root_transport.mkdir(path)
207
 
            controldir.ControlDir.create_branch_convenience('repo/' + path)
208
 
            return workingtree.WorkingTree.open('repo/' + path)
209
 
        tree_a = make_shared_tree('a')
210
 
        self.build_tree(['repo/a/file'])
211
 
        tree_a.add('file')
212
 
        tree_a.commit('commit a-1', rev_id=b'a-1')
213
 
        f = open('repo/a/file', 'ab')
214
 
        f.write(b'more stuff\n')
215
 
        f.close()
216
 
        tree_a.commit('commit a-2', rev_id=b'a-2')
217
 
 
218
 
        tree_b = make_shared_tree('b')
219
 
        self.build_tree(['repo/b/file'])
220
 
        tree_b.add('file')
221
 
        tree_b.commit('commit b-1', rev_id=b'b-1')
222
 
 
223
 
        self.assertTrue(shared_repo.has_revision(b'a-1'))
224
 
        self.assertTrue(shared_repo.has_revision(b'a-2'))
225
 
        self.assertTrue(shared_repo.has_revision(b'b-1'))
226
 
 
227
 
        # Now that we have a repository with shared files, make sure
228
 
        # that things aren't copied out by a 'push'
229
 
        self.run_bzr('push ../../push-b', working_dir='repo/b')
230
 
        pushed_tree = workingtree.WorkingTree.open('push-b')
231
 
        pushed_repo = pushed_tree.branch.repository
232
 
        self.assertFalse(pushed_repo.has_revision(b'a-1'))
233
 
        self.assertFalse(pushed_repo.has_revision(b'a-2'))
234
 
        self.assertTrue(pushed_repo.has_revision(b'b-1'))
235
 
 
236
 
    def test_push_funky_id(self):
237
 
        t = self.make_branch_and_tree('tree')
238
 
        self.build_tree(['tree/filename'])
239
 
        t.add('filename', b'funky-chars<>%&;"\'')
240
 
        t.commit('commit filename')
241
 
        self.run_bzr('push -d tree new-tree')
242
 
 
243
 
    def test_push_dash_d(self):
244
 
        t = self.make_branch_and_tree('from')
245
 
        t.commit(allow_pointless=True,
246
 
                 message='first commit')
247
 
        self.run_bzr('push -d from to-one')
248
 
        self.assertPathExists('to-one')
249
 
        self.run_bzr('push -d %s %s'
250
 
                     % tuple(map(urlutils.local_path_to_url, ['from', 'to-two'])))
251
 
        self.assertPathExists('to-two')
252
 
 
253
 
    def test_push_repository_no_branch_doesnt_fetch_all_revs(self):
254
 
        # See https://bugs.launchpad.net/bzr/+bug/465517
255
 
        target_repo = self.make_repository('target')
256
 
        source = self.make_branch_builder('source')
257
 
        source.start_series()
258
 
        source.build_snapshot(None, [
259
 
            ('add', ('', b'root-id', 'directory', None))],
260
 
            revision_id=b'A')
261
 
        source.build_snapshot([b'A'], [], revision_id=b'B')
262
 
        source.build_snapshot([b'A'], [], revision_id=b'C')
263
 
        source.finish_series()
264
 
        self.run_bzr('push target -d source')
265
 
        self.addCleanup(target_repo.lock_read().unlock)
266
 
        # We should have pushed 'C', but not 'B', since it isn't in the
267
 
        # ancestry
268
 
        self.assertEqual([(b'A',), (b'C',)], sorted(
269
 
            target_repo.revisions.keys()))
270
 
 
271
 
    def test_push_smart_non_stacked_streaming_acceptance(self):
272
 
        self.setup_smart_server_with_call_log()
273
 
        t = self.make_branch_and_tree('from')
274
 
        t.commit(allow_pointless=True, message='first commit')
275
 
        self.reset_smart_call_log()
276
 
        self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
277
 
        # This figure represent the amount of work to perform this use case. It
278
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
279
 
        # being too low. If rpc_count increases, more network roundtrips have
280
 
        # become necessary for this use case. Please do not adjust this number
281
 
        # upwards without agreement from bzr's network support maintainers.
282
 
        self.assertLength(9, self.hpss_calls)
283
 
        self.assertLength(1, self.hpss_connections)
284
 
        self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
285
 
 
286
 
    def test_push_smart_stacked_streaming_acceptance(self):
287
 
        self.setup_smart_server_with_call_log()
288
 
        parent = self.make_branch_and_tree('parent', format='1.9')
289
 
        parent.commit(message='first commit')
290
 
        local = parent.controldir.sprout('local').open_workingtree()
291
 
        local.commit(message='local commit')
292
 
        self.reset_smart_call_log()
293
 
        self.run_bzr(['push', '--stacked', '--stacked-on', '../parent',
294
 
                      self.get_url('public')], working_dir='local')
295
 
        # This figure represent the amount of work to perform this use case. It
296
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
297
 
        # being too low. If rpc_count increases, more network roundtrips have
298
 
        # become necessary for this use case. Please do not adjust this number
299
 
        # upwards without agreement from bzr's network support maintainers.
300
 
        self.assertLength(15, self.hpss_calls)
301
 
        self.assertLength(1, self.hpss_connections)
302
 
        self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
303
 
        remote = branch.Branch.open('public')
304
 
        self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
305
 
 
306
 
    def test_push_smart_tags_streaming_acceptance(self):
307
 
        self.setup_smart_server_with_call_log()
308
 
        t = self.make_branch_and_tree('from')
309
 
        rev_id = t.commit(allow_pointless=True, message='first commit')
310
 
        t.branch.tags.set_tag('new-tag', rev_id)
311
 
        self.reset_smart_call_log()
312
 
        self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
313
 
        # This figure represent the amount of work to perform this use case. It
314
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
315
 
        # being too low. If rpc_count increases, more network roundtrips have
316
 
        # become necessary for this use case. Please do not adjust this number
317
 
        # upwards without agreement from bzr's network support maintainers.
318
 
        self.assertLength(11, self.hpss_calls)
319
 
        self.assertLength(1, self.hpss_connections)
320
 
        self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
321
 
 
322
 
    def test_push_smart_incremental_acceptance(self):
323
 
        self.setup_smart_server_with_call_log()
324
 
        t = self.make_branch_and_tree('from')
325
 
        rev_id1 = t.commit(allow_pointless=True, message='first commit')
326
 
        rev_id2 = t.commit(allow_pointless=True, message='second commit')
327
 
        self.run_bzr(
328
 
            ['push', self.get_url('to-one'), '-r1'], working_dir='from')
329
 
        self.reset_smart_call_log()
330
 
        self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
331
 
        # This figure represent the amount of work to perform this use case. It
332
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
333
 
        # being too low. If rpc_count increases, more network roundtrips have
334
 
        # become necessary for this use case. Please do not adjust this number
335
 
        # upwards without agreement from bzr's network support maintainers.
336
 
        self.assertLength(11, self.hpss_calls)
337
 
        self.assertLength(1, self.hpss_connections)
338
 
        self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
339
 
 
340
 
    def test_push_smart_with_default_stacking_url_path_segment(self):
341
 
        # If the default stacked-on location is a path element then branches
342
 
        # we push there over the smart server are stacked and their
343
 
        # stacked_on_url is that exact path segment. Added to nail bug 385132.
344
 
        self.setup_smart_server_with_call_log()
345
 
        self.make_branch('stack-on', format='1.9')
346
 
        self.make_controldir('.').get_config().set_default_stack_on(
347
 
            '/stack-on')
348
 
        self.make_branch('from', format='1.9')
349
 
        out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
350
 
        b = branch.Branch.open(self.get_url('to'))
351
 
        self.assertEqual('/extra/stack-on', b.get_stacked_on_url())
352
 
 
353
 
    def test_push_smart_with_default_stacking_relative_path(self):
354
 
        # If the default stacked-on location is a relative path then branches
355
 
        # we push there over the smart server are stacked and their
356
 
        # stacked_on_url is a relative path. Added to nail bug 385132.
357
 
        self.setup_smart_server_with_call_log()
358
 
        self.make_branch('stack-on', format='1.9')
359
 
        self.make_controldir('.').get_config().set_default_stack_on('stack-on')
360
 
        self.make_branch('from', format='1.9')
361
 
        out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
362
 
        b = branch.Branch.open(self.get_url('to'))
363
 
        self.assertEqual('../stack-on', b.get_stacked_on_url())
364
 
 
365
 
    def create_simple_tree(self):
366
 
        tree = self.make_branch_and_tree('tree')
367
 
        self.build_tree(['tree/a'])
368
 
        tree.add(['a'], [b'a-id'])
369
 
        tree.commit('one', rev_id=b'r1')
370
 
        return tree
371
 
 
372
 
    def test_push_create_prefix(self):
373
 
        """'brz push --create-prefix' will create leading directories."""
374
 
        tree = self.create_simple_tree()
375
 
 
376
 
        self.run_bzr_error(['Parent directory of ../new/tree does not exist'],
377
 
                           'push ../new/tree',
378
 
                           working_dir='tree')
379
 
        self.run_bzr('push ../new/tree --create-prefix',
380
 
                     working_dir='tree')
381
 
        new_tree = workingtree.WorkingTree.open('new/tree')
382
 
        self.assertEqual(tree.last_revision(), new_tree.last_revision())
383
 
        self.assertPathExists('new/tree/a')
384
 
 
385
 
    def test_push_use_existing(self):
386
 
        """'brz push --use-existing-dir' can push into an existing dir.
387
 
 
388
 
        By default, 'brz push' will not use an existing, non-versioned dir.
389
 
        """
390
 
        tree = self.create_simple_tree()
391
 
        self.build_tree(['target/'])
392
 
 
393
 
        self.run_bzr_error(['Target directory ../target already exists',
394
 
                            'Supply --use-existing-dir',
395
 
                            ],
396
 
                           'push ../target', working_dir='tree')
397
 
 
398
 
        self.run_bzr('push --use-existing-dir ../target',
399
 
                     working_dir='tree')
400
 
 
401
 
        new_tree = workingtree.WorkingTree.open('target')
402
 
        self.assertEqual(tree.last_revision(), new_tree.last_revision())
403
 
        # The push should have created target/a
404
 
        self.assertPathExists('target/a')
405
 
 
406
 
    def test_push_use_existing_into_empty_bzrdir(self):
407
 
        """'brz push --use-existing-dir' into a dir with an empty .bzr dir
408
 
        fails.
409
 
        """
410
 
        tree = self.create_simple_tree()
411
 
        self.build_tree(['target/', 'target/.bzr/'])
412
 
        self.run_bzr_error(
413
 
            ['Target directory ../target already contains a .bzr directory, '
414
 
             'but it is not valid.'],
415
 
            'push ../target --use-existing-dir', working_dir='tree')
416
 
 
417
 
    def test_push_onto_repo(self):
418
 
        """We should be able to 'brz push' into an existing bzrdir."""
419
 
        tree = self.create_simple_tree()
420
 
        repo = self.make_repository('repo', shared=True)
421
 
 
422
 
        self.run_bzr('push ../repo',
423
 
                     working_dir='tree')
424
 
 
425
 
        # Pushing onto an existing bzrdir will create a repository and
426
 
        # branch as needed, but will only create a working tree if there was
427
 
        # no BzrDir before.
428
 
        self.assertRaises(errors.NoWorkingTree,
429
 
                          workingtree.WorkingTree.open, 'repo')
430
 
        new_branch = branch.Branch.open('repo')
431
 
        self.assertEqual(tree.last_revision(), new_branch.last_revision())
432
 
 
433
 
    def test_push_onto_just_bzrdir(self):
434
 
        """We don't handle when the target is just a bzrdir.
435
 
 
436
 
        Because you shouldn't be able to create *just* a bzrdir in the wild.
437
 
        """
438
 
        # TODO: jam 20070109 Maybe it would be better to create the repository
439
 
        #       if at this point
440
 
        tree = self.create_simple_tree()
441
 
        a_controldir = self.make_controldir('dir')
442
 
 
443
 
        self.run_bzr_error(['At ../dir you have a valid .bzr control'],
444
 
                           'push ../dir',
445
 
                           working_dir='tree')
446
 
 
447
 
    def test_push_with_revisionspec(self):
448
 
        """We should be able to push a revision older than the tip."""
449
 
        tree_from = self.make_branch_and_tree('from')
450
 
        tree_from.commit("One.", rev_id=b"from-1")
451
 
        tree_from.commit("Two.", rev_id=b"from-2")
452
 
 
453
 
        self.run_bzr('push -r1 ../to', working_dir='from')
454
 
 
455
 
        tree_to = workingtree.WorkingTree.open('to')
456
 
        repo_to = tree_to.branch.repository
457
 
        self.assertTrue(repo_to.has_revision(b'from-1'))
458
 
        self.assertFalse(repo_to.has_revision(b'from-2'))
459
 
        self.assertEqual(tree_to.branch.last_revision_info()[1], b'from-1')
460
 
        self.assertFalse(
461
 
            tree_to.changes_from(tree_to.basis_tree()).has_changed())
462
 
 
463
 
        self.run_bzr_error(
464
 
            ['brz: ERROR: brz push --revision '
465
 
             'takes exactly one revision identifier\n'],
466
 
            'push -r0..2 ../to', working_dir='from')
467
 
 
468
 
    def create_trunk_and_feature_branch(self):
469
 
        # We have a mainline
470
 
        trunk_tree = self.make_branch_and_tree('target',
471
 
                                               format='1.9')
472
 
        trunk_tree.commit('mainline')
473
 
        # and a branch from it
474
 
        branch_tree = self.make_branch_and_tree('branch',
475
 
                                                format='1.9')
476
 
        branch_tree.pull(trunk_tree.branch)
477
 
        branch_tree.branch.set_parent(trunk_tree.branch.base)
478
 
        # with some work on it
479
 
        branch_tree.commit('moar work plz')
480
 
        return trunk_tree, branch_tree
481
 
 
482
 
    def assertPublished(self, branch_revid, stacked_on):
483
 
        """Assert that the branch 'published' has been published correctly."""
484
 
        published_branch = branch.Branch.open('published')
485
 
        # The published branch refers to the mainline
486
 
        self.assertEqual(stacked_on, published_branch.get_stacked_on_url())
487
 
        # and the branch's work was pushed
488
 
        self.assertTrue(published_branch.repository.has_revision(branch_revid))
489
 
 
490
 
    def test_push_new_branch_stacked_on(self):
491
 
        """Pushing a new branch with --stacked-on creates a stacked branch."""
492
 
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
493
 
        # we publish branch_tree with a reference to the mainline.
494
 
        out, err = self.run_bzr(['push', '--stacked-on', trunk_tree.branch.base,
495
 
                                 self.get_url('published')], working_dir='branch')
496
 
        self.assertEqual('', out)
497
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
498
 
                         trunk_tree.branch.base, err)
499
 
        self.assertPublished(branch_tree.last_revision(),
500
 
                             trunk_tree.branch.base)
501
 
 
502
 
    def test_push_new_branch_stacked_on(self):
503
 
        """Pushing a new branch with --stacked-on can use directory URLs."""
504
 
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
505
 
        class FooDirectory(object):
506
 
            def look_up(self, name, url, purpose=None):
507
 
                if url == 'foo:':
508
 
                    return trunk_tree.branch.base
509
 
                return url
510
 
        directory_service.directories.register('foo:', FooDirectory, 'Foo directory')
511
 
        self.addCleanup(directory_service.directories.remove, 'foo:')
512
 
        # we publish branch_tree with a reference to the mainline.
513
 
        out, err = self.run_bzr(['push', '--stacked-on', 'foo:',
514
 
                                 self.get_url('published')], working_dir='branch')
515
 
        self.assertEqual('', out)
516
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
517
 
                         trunk_tree.branch.base, err)
518
 
        self.assertPublished(branch_tree.last_revision(),
519
 
                             trunk_tree.branch.base)
520
 
 
521
 
    def test_push_new_branch_stacked_uses_parent_when_no_public_url(self):
522
 
        """When the parent has no public url the parent is used as-is."""
523
 
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
524
 
        # now we do a stacked push, which should determine the public location
525
 
        # for us.
526
 
        out, err = self.run_bzr(['push', '--stacked',
527
 
                                 self.get_url('published')], working_dir='branch')
528
 
        self.assertEqual('', out)
529
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
530
 
                         trunk_tree.branch.base, err)
531
 
        self.assertPublished(branch_tree.last_revision(),
532
 
                             trunk_tree.branch.base)
533
 
 
534
 
    def test_push_new_branch_stacked_uses_parent_public(self):
535
 
        """Pushing a new branch with --stacked creates a stacked branch."""
536
 
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
537
 
        # the trunk is published on a web server
538
 
        self.transport_readonly_server = http_server.HttpServer
539
 
        trunk_public = self.make_branch('public_trunk', format='1.9')
540
 
        trunk_public.pull(trunk_tree.branch)
541
 
        trunk_public_url = self.get_readonly_url('public_trunk')
542
 
        br = trunk_tree.branch
543
 
        br.set_public_branch(trunk_public_url)
544
 
        # now we do a stacked push, which should determine the public location
545
 
        # for us.
546
 
        out, err = self.run_bzr(['push', '--stacked',
547
 
                                 self.get_url('published')], working_dir='branch')
548
 
        self.assertEqual('', out)
549
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
550
 
                         trunk_public_url, err)
551
 
        self.assertPublished(branch_tree.last_revision(), trunk_public_url)
552
 
 
553
 
    def test_push_new_branch_stacked_no_parent(self):
554
 
        """Pushing with --stacked and no parent branch errors."""
555
 
        branch = self.make_branch_and_tree('branch', format='1.9')
556
 
        # now we do a stacked push, which should fail as the place to refer too
557
 
        # cannot be determined.
558
 
        out, err = self.run_bzr_error(
559
 
            ['Could not determine branch to refer to\\.'], ['push', '--stacked',
560
 
                                                            self.get_url('published')], working_dir='branch')
561
 
        self.assertEqual('', out)
562
 
        self.assertFalse(self.get_transport('published').has('.'))
563
 
 
564
 
    def test_push_notifies_default_stacking(self):
565
 
        self.make_branch('stack_on', format='1.6')
566
 
        self.make_controldir('.').get_config().set_default_stack_on('stack_on')
567
 
        self.make_branch('from', format='1.6')
568
 
        out, err = self.run_bzr('push -d from to')
569
 
        self.assertContainsRe(err,
570
 
                              'Using default stacking branch stack_on at .*')
571
 
 
572
 
    def test_push_stacks_with_default_stacking_if_target_is_stackable(self):
573
 
        self.make_branch('stack_on', format='1.6')
574
 
        self.make_controldir('.').get_config().set_default_stack_on('stack_on')
575
 
        self.make_branch('from', format='pack-0.92')
576
 
        out, err = self.run_bzr('push -d from to')
577
 
        b = branch.Branch.open('to')
578
 
        self.assertEqual('../stack_on', b.get_stacked_on_url())
579
 
 
580
 
    def test_push_does_not_change_format_with_default_if_target_cannot(self):
581
 
        self.make_branch('stack_on', format='pack-0.92')
582
 
        self.make_controldir('.').get_config().set_default_stack_on('stack_on')
583
 
        self.make_branch('from', format='pack-0.92')
584
 
        out, err = self.run_bzr('push -d from to')
585
 
        b = branch.Branch.open('to')
586
 
        self.assertRaises(branch.UnstackableBranchFormat, b.get_stacked_on_url)
587
 
 
588
 
    def test_push_doesnt_create_broken_branch(self):
589
 
        """Pushing a new standalone branch works even when there's a default
590
 
        stacking policy at the destination.
591
 
 
592
 
        The new branch will preserve the repo format (even if it isn't the
593
 
        default for the branch), and will be stacked when the repo format
594
 
        allows (which means that the branch format isn't necessarly preserved).
595
 
        """
596
 
        self.make_repository('repo', shared=True, format='1.6')
597
 
        builder = self.make_branch_builder('repo/local', format='pack-0.92')
598
 
        builder.start_series()
599
 
        builder.build_snapshot(None, [
600
 
            ('add', ('', b'root-id', 'directory', '')),
601
 
            ('add', ('filename', b'f-id', 'file', b'content\n'))],
602
 
            revision_id=b'rev-1')
603
 
        builder.build_snapshot([b'rev-1'], [], revision_id=b'rev-2')
604
 
        builder.build_snapshot([b'rev-2'],
605
 
                               [('modify', ('filename', b'new-content\n'))],
606
 
                               revision_id=b'rev-3')
607
 
        builder.finish_series()
608
 
        branch = builder.get_branch()
609
 
        # Push rev-1 to "trunk", so that we can stack on it.
610
 
        self.run_bzr('push -d repo/local trunk -r 1')
611
 
        # Set a default stacking policy so that new branches will automatically
612
 
        # stack on trunk.
613
 
        self.make_controldir('.').get_config().set_default_stack_on('trunk')
614
 
        # Push rev-2 to a new branch "remote".  It will be stacked on "trunk".
615
 
        out, err = self.run_bzr('push -d repo/local remote -r 2')
616
 
        self.assertContainsRe(
617
 
            err, 'Using default stacking branch trunk at .*')
618
 
        # Push rev-3 onto "remote".  If "remote" not stacked and is missing the
619
 
        # fulltext record for f-id @ rev-1, then this will fail.
620
 
        out, err = self.run_bzr('push -d repo/local remote -r 3')
621
 
 
622
 
    def test_push_verbose_shows_log(self):
623
 
        tree = self.make_branch_and_tree('source')
624
 
        tree.commit('rev1')
625
 
        out, err = self.run_bzr('push -v -d source target')
626
 
        # initial push contains log
627
 
        self.assertContainsRe(out, 'rev1')
628
 
        tree.commit('rev2')
629
 
        out, err = self.run_bzr('push -v -d source target')
630
 
        # subsequent push contains log
631
 
        self.assertContainsRe(out, 'rev2')
632
 
        # subsequent log is accurate
633
 
        self.assertNotContainsRe(out, 'rev1')
634
 
 
635
 
    def test_push_from_subdir(self):
636
 
        t = self.make_branch_and_tree('tree')
637
 
        self.build_tree(['tree/dir/', 'tree/dir/file'])
638
 
        t.add(['dir', 'dir/file'])
639
 
        t.commit('r1')
640
 
        out, err = self.run_bzr('push ../../pushloc', working_dir='tree/dir')
641
 
        self.assertEqual('', out)
642
 
        self.assertEqual('Created new branch.\n', err)
643
 
 
644
 
    def test_overwrite_tags(self):
645
 
        """--overwrite-tags only overwrites tags, not revisions."""
646
 
        from_tree = self.make_branch_and_tree('from')
647
 
        from_tree.branch.tags.set_tag("mytag", b"somerevid")
648
 
        to_tree = self.make_branch_and_tree('to')
649
 
        to_tree.branch.tags.set_tag("mytag", b"anotherrevid")
650
 
        revid1 = to_tree.commit('my commit')
651
 
        out = self.run_bzr(['push', '-d', 'from', 'to'])
652
 
        self.assertEqual(out,
653
 
                         ('Conflicting tags:\n    mytag\n', 'No new revisions to push.\n'))
654
 
        out = self.run_bzr(['push', '-d', 'from', '--overwrite-tags', 'to'])
655
 
        self.assertEqual(out, ('', '1 tag updated.\n'))
656
 
        self.assertEqual(to_tree.branch.tags.lookup_tag('mytag'),
657
 
                         b'somerevid')
658
 
        self.assertEqual(to_tree.branch.last_revision(), revid1)
659
 
 
660
 
 
661
 
class RedirectingMemoryTransport(memory.MemoryTransport):
662
 
 
663
 
    def mkdir(self, relpath, mode=None):
664
 
        if self._cwd == '/source/':
665
 
            raise errors.RedirectRequested(self.abspath(relpath),
666
 
                                           self.abspath('../target'),
667
 
                                           is_permanent=True)
668
 
        elif self._cwd == '/infinite-loop/':
669
 
            raise errors.RedirectRequested(self.abspath(relpath),
670
 
                                           self.abspath('../infinite-loop'),
671
 
                                           is_permanent=True)
672
 
        else:
673
 
            return super(RedirectingMemoryTransport, self).mkdir(
674
 
                relpath, mode)
675
 
 
676
 
    def get(self, relpath):
677
 
        if self.clone(relpath)._cwd == '/infinite-loop/':
678
 
            raise errors.RedirectRequested(self.abspath(relpath),
679
 
                                           self.abspath('../infinite-loop'),
680
 
                                           is_permanent=True)
681
 
        else:
682
 
            return super(RedirectingMemoryTransport, self).get(relpath)
683
 
 
684
 
    def _redirected_to(self, source, target):
685
 
        # We do accept redirections
686
 
        return transport.get_transport(target)
687
 
 
688
 
 
689
 
class RedirectingMemoryServer(memory.MemoryServer):
690
 
 
691
 
    def start_server(self):
692
 
        self._dirs = {'/': None}
693
 
        self._files = {}
694
 
        self._locks = {}
695
 
        self._scheme = 'redirecting-memory+%s:///' % id(self)
696
 
        transport.register_transport(self._scheme, self._memory_factory)
697
 
 
698
 
    def _memory_factory(self, url):
699
 
        result = RedirectingMemoryTransport(url)
700
 
        result._dirs = self._dirs
701
 
        result._files = self._files
702
 
        result._locks = self._locks
703
 
        return result
704
 
 
705
 
    def stop_server(self):
706
 
        transport.unregister_transport(self._scheme, self._memory_factory)
707
 
 
708
 
 
709
 
class TestPushRedirect(tests.TestCaseWithTransport):
710
 
 
711
 
    def setUp(self):
712
 
        super(TestPushRedirect, self).setUp()
713
 
        self.memory_server = RedirectingMemoryServer()
714
 
        self.start_server(self.memory_server)
715
 
        # Make the branch and tree that we'll be pushing.
716
 
        t = self.make_branch_and_tree('tree')
717
 
        self.build_tree(['tree/file'])
718
 
        t.add('file')
719
 
        t.commit('commit 1')
720
 
 
721
 
    def test_push_redirects_on_mkdir(self):
722
 
        """If the push requires a mkdir, push respects redirect requests.
723
 
 
724
 
        This is added primarily to handle lp:/ URI support, so that users can
725
 
        push to new branches by specifying lp:/ URIs.
726
 
        """
727
 
        destination_url = self.memory_server.get_url() + 'source'
728
 
        self.run_bzr(['push', '-d', 'tree', destination_url])
729
 
 
730
 
        local_revision = branch.Branch.open('tree').last_revision()
731
 
        remote_revision = branch.Branch.open(
732
 
            self.memory_server.get_url() + 'target').last_revision()
733
 
        self.assertEqual(remote_revision, local_revision)
734
 
 
735
 
    def test_push_gracefully_handles_too_many_redirects(self):
736
 
        """Push fails gracefully if the mkdir generates a large number of
737
 
        redirects.
738
 
        """
739
 
        destination_url = self.memory_server.get_url() + 'infinite-loop'
740
 
        out, err = self.run_bzr_error(
741
 
            ['Too many redirections trying to make %s\\.\n'
742
 
             % re.escape(destination_url)],
743
 
            ['push', '-d', 'tree', destination_url], retcode=3)
744
 
        self.assertEqual('', out)
745
 
 
746
 
 
747
 
class TestPushStrictMixin(object):
748
 
 
749
 
    def make_local_branch_and_tree(self):
750
 
        self.tree = self.make_branch_and_tree('local')
751
 
        self.build_tree_contents([('local/file', b'initial')])
752
 
        self.tree.add('file')
753
 
        self.tree.commit('adding file', rev_id=b'added')
754
 
        self.build_tree_contents([('local/file', b'modified')])
755
 
        self.tree.commit('modify file', rev_id=b'modified')
756
 
 
757
 
    def set_config_push_strict(self, value):
758
 
        br = branch.Branch.open('local')
759
 
        br.get_config_stack().set('push_strict', value)
760
 
 
761
 
    _default_command = ['push', '../to']
762
 
    _default_wd = 'local'
763
 
    _default_errors = ['Working tree ".*/local/" has uncommitted '
764
 
                       'changes \\(See brz status\\)\\.', ]
765
 
    _default_additional_error = 'Use --no-strict to force the push.\n'
766
 
    _default_additional_warning = 'Uncommitted changes will not be pushed.'
767
 
 
768
 
    def assertPushFails(self, args):
769
 
        out, err = self.run_bzr_error(self._default_errors,
770
 
                                      self._default_command + args,
771
 
                                      working_dir=self._default_wd, retcode=3)
772
 
        self.assertContainsRe(err, self._default_additional_error)
773
 
 
774
 
    def assertPushSucceeds(self, args, with_warning=False, revid_to_push=None):
775
 
        if with_warning:
776
 
            error_regexes = self._default_errors
777
 
        else:
778
 
            error_regexes = []
779
 
        out, err = self.run_bzr(self._default_command + args,
780
 
                                working_dir=self._default_wd,
781
 
                                error_regexes=error_regexes)
782
 
        if with_warning:
783
 
            self.assertContainsRe(err, self._default_additional_warning)
784
 
        else:
785
 
            self.assertNotContainsRe(err, self._default_additional_warning)
786
 
        branch_from = branch.Branch.open(self._default_wd)
787
 
        if revid_to_push is None:
788
 
            revid_to_push = branch_from.last_revision()
789
 
        branch_to = branch.Branch.open('to')
790
 
        repo_to = branch_to.repository
791
 
        self.assertTrue(repo_to.has_revision(revid_to_push))
792
 
        self.assertEqual(revid_to_push, branch_to.last_revision())
793
 
 
794
 
 
795
 
class TestPushStrictWithoutChanges(tests.TestCaseWithTransport,
796
 
                                   TestPushStrictMixin):
797
 
 
798
 
    def setUp(self):
799
 
        super(TestPushStrictWithoutChanges, self).setUp()
800
 
        self.make_local_branch_and_tree()
801
 
 
802
 
    def test_push_default(self):
803
 
        self.assertPushSucceeds([])
804
 
 
805
 
    def test_push_strict(self):
806
 
        self.assertPushSucceeds(['--strict'])
807
 
 
808
 
    def test_push_no_strict(self):
809
 
        self.assertPushSucceeds(['--no-strict'])
810
 
 
811
 
    def test_push_config_var_strict(self):
812
 
        self.set_config_push_strict('true')
813
 
        self.assertPushSucceeds([])
814
 
 
815
 
    def test_push_config_var_no_strict(self):
816
 
        self.set_config_push_strict('false')
817
 
        self.assertPushSucceeds([])
818
 
 
819
 
 
820
 
strict_push_change_scenarios = [
821
 
    ('uncommitted',
822
 
        dict(_changes_type='_uncommitted_changes')),
823
 
    ('pending-merges',
824
 
        dict(_changes_type='_pending_merges')),
825
 
    ('out-of-sync-trees',
826
 
        dict(_changes_type='_out_of_sync_trees')),
827
 
    ]
828
 
 
829
 
 
830
 
class TestPushStrictWithChanges(tests.TestCaseWithTransport,
831
 
                                TestPushStrictMixin):
832
 
 
833
 
    scenarios = strict_push_change_scenarios
834
 
    _changes_type = None  # Set by load_tests
835
 
 
836
 
    def setUp(self):
837
 
        super(TestPushStrictWithChanges, self).setUp()
838
 
        # Apply the changes defined in load_tests: one of _uncommitted_changes,
839
 
        # _pending_merges or _out_of_sync_trees
840
 
        getattr(self, self._changes_type)()
841
 
 
842
 
    def _uncommitted_changes(self):
843
 
        self.make_local_branch_and_tree()
844
 
        # Make a change without committing it
845
 
        self.build_tree_contents([('local/file', b'in progress')])
846
 
 
847
 
    def _pending_merges(self):
848
 
        self.make_local_branch_and_tree()
849
 
        # Create 'other' branch containing a new file
850
 
        other_bzrdir = self.tree.controldir.sprout('other')
851
 
        other_tree = other_bzrdir.open_workingtree()
852
 
        self.build_tree_contents([('other/other-file', b'other')])
853
 
        other_tree.add('other-file')
854
 
        other_tree.commit('other commit', rev_id=b'other')
855
 
        # Merge and revert, leaving a pending merge
856
 
        self.tree.merge_from_branch(other_tree.branch)
857
 
        self.tree.revert(filenames=['other-file'], backups=False)
858
 
 
859
 
    def _out_of_sync_trees(self):
860
 
        self.make_local_branch_and_tree()
861
 
        self.run_bzr(['checkout', '--lightweight', 'local', 'checkout'])
862
 
        # Make a change and commit it
863
 
        self.build_tree_contents([('local/file', b'modified in local')])
864
 
        self.tree.commit('modify file', rev_id=b'modified-in-local')
865
 
        # Exercise commands from the checkout directory
866
 
        self._default_wd = 'checkout'
867
 
        self._default_errors = ["Working tree is out of date, please run"
868
 
                                " 'brz update'\\.", ]
869
 
 
870
 
    def test_push_default(self):
871
 
        self.assertPushSucceeds([], with_warning=True)
872
 
 
873
 
    def test_push_with_revision(self):
874
 
        self.assertPushSucceeds(['-r', 'revid:added'], revid_to_push=b'added')
875
 
 
876
 
    def test_push_no_strict(self):
877
 
        self.assertPushSucceeds(['--no-strict'])
878
 
 
879
 
    def test_push_strict_with_changes(self):
880
 
        self.assertPushFails(['--strict'])
881
 
 
882
 
    def test_push_respect_config_var_strict(self):
883
 
        self.set_config_push_strict('true')
884
 
        self.assertPushFails([])
885
 
 
886
 
    def test_push_bogus_config_var_ignored(self):
887
 
        self.set_config_push_strict("I don't want you to be strict")
888
 
        self.assertPushSucceeds([], with_warning=True)
889
 
 
890
 
    def test_push_no_strict_command_line_override_config(self):
891
 
        self.set_config_push_strict('yES')
892
 
        self.assertPushFails([])
893
 
        self.assertPushSucceeds(['--no-strict'])
894
 
 
895
 
    def test_push_strict_command_line_override_config(self):
896
 
        self.set_config_push_strict('oFF')
897
 
        self.assertPushFails(['--strict'])
898
 
        self.assertPushSucceeds([])
899
 
 
900
 
 
901
 
class TestPushForeign(tests.TestCaseWithTransport):
902
 
 
903
 
    def setUp(self):
904
 
        super(TestPushForeign, self).setUp()
905
 
        test_foreign.register_dummy_foreign_for_test(self)
906
 
 
907
 
    def make_dummy_builder(self, relpath):
908
 
        builder = self.make_branch_builder(
909
 
            relpath, format=test_foreign.DummyForeignVcsDirFormat())
910
 
        builder.build_snapshot(None,
911
 
                               [('add', ('', b'TREE_ROOT', 'directory', None)),
912
 
                                ('add', ('foo', b'fooid', 'file', b'bar'))],
913
 
                               revision_id=b'revid')
914
 
        return builder
915
 
 
916
 
    def test_no_roundtripping(self):
917
 
        target_branch = self.make_dummy_builder('dp').get_branch()
918
 
        source_tree = self.make_branch_and_tree("dc")
919
 
        output, error = self.run_bzr("push -d dc dp", retcode=3)
920
 
        self.assertEqual("", output)
921
 
        self.assertEqual(
922
 
            error,
923
 
            "brz: ERROR: It is not possible to losslessly"
924
 
            " push to dummy. You may want to use --lossy.\n")
925
 
 
926
 
 
927
 
class TestPushOutput(script.TestCaseWithTransportAndScript):
928
 
 
929
 
    def test_push_log_format(self):
930
 
        self.run_script("""
931
 
            $ brz init trunk
932
 
            Created a standalone tree (format: 2a)
933
 
            $ cd trunk
934
 
            $ echo foo > file
935
 
            $ brz add
936
 
            adding file
937
 
            $ brz commit -m 'we need some foo'
938
 
            2>Committing to:...trunk/
939
 
            2>added file
940
 
            2>Committed revision 1.
941
 
            $ brz init ../feature
942
 
            Created a standalone tree (format: 2a)
943
 
            $ brz push -v ../feature -Olog_format=line
944
 
            Added Revisions:
945
 
            1: jrandom@example.com ...we need some foo
946
 
            2>All changes applied successfully.
947
 
            2>Pushed up to revision 1.
948
 
            """)
949
 
 
950
 
    def test_push_with_revspec(self):
951
 
        self.run_script("""
952
 
            $ brz init-shared-repo .
953
 
            Shared repository with trees (format: 2a)
954
 
            Location:
955
 
              shared repository: .
956
 
            $ brz init trunk
957
 
            Created a repository tree (format: 2a)
958
 
            Using shared repository...
959
 
            $ cd trunk
960
 
            $ brz commit -m 'first rev' --unchanged
961
 
            2>Committing to:...trunk/
962
 
            2>Committed revision 1.
963
 
            $ echo foo > file
964
 
            $ brz add
965
 
            adding file
966
 
            $ brz commit -m 'we need some foo'
967
 
            2>Committing to:...trunk/
968
 
            2>added file
969
 
            2>Committed revision 2.
970
 
            $ brz push -r 1 ../other
971
 
            2>Created new branch.
972
 
            $ brz st ../other # checking that file is not created (#484516)
973
 
            """)
 
71
        self.runbzr('push ../branch_c --remember')
 
72
        self.assertEquals(abspath(branch_a.get_push_location()),
 
73
                          abspath(branch_c.bzrdir.root_transport.base))