/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3549.1.1 by Martin Pool
rename push --reference to --stacked-on
1
# Copyright (C) 2005, 2007, 2008 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
16
17
1692.3.1 by Robert Collins
Fix push to work with just a branch, no need for a working tree.
18
"""Black-box tests for bzr push."""
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
19
20
import os
3066.3.2 by jml at canonical
Add tests to check the handling of TooManyRedirections.
21
import re
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
22
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
23
from bzrlib import (
24
    errors,
3878.4.4 by Vincent Ladeuil
Cleanup.
25
    transport,
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
26
    urlutils,
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
27
    )
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
28
from bzrlib.branch import Branch
2279.1.3 by John Arbash Meinel
Switch the test to being a branch_implementation test.
29
from bzrlib.bzrdir import BzrDirMetaFormat1
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
30
from bzrlib.osutils import abspath
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
31
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
32
from bzrlib.smart import client, server
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
33
from bzrlib.tests.blackbox import ExternalBase
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
34
from bzrlib.tests.http_server import HttpServer
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
35
from bzrlib.transport.memory import MemoryServer, MemoryTransport
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
36
from bzrlib.uncommit import uncommit
1785.1.1 by John Arbash Meinel
Fix the output of 'bzr push' so that it prints the location correctly.
37
from bzrlib.urlutils import local_path_from_url
1711.2.3 by John Arbash Meinel
Fix push to only push revisions in the current ancestry. (bug???)
38
from bzrlib.workingtree import WorkingTree
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
39
40
41
class TestPush(ExternalBase):
42
4017.2.3 by Robert Collins
Review feedback.
43
    def test_push_error_on_vfs_http(self):
44
        """ pushing a branch to a HTTP server fails cleanly. """
45
        # the trunk is published on a web server
46
        self.transport_readonly_server = HttpServer
47
        self.make_branch('source')
48
        public_url = self.get_readonly_url('target')
49
        self.run_bzr_error(['http does not support mkdir'],
50
                           ['push', public_url],
51
                           working_dir='source')
52
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
53
    def test_push_remember(self):
54
        """Push changes from one branch to another and test push location."""
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
55
        transport = self.get_transport()
56
        tree_a = self.make_branch_and_tree('branch_a')
57
        branch_a = tree_a.branch
58
        self.build_tree(['branch_a/a'])
59
        tree_a.add('a')
60
        tree_a.commit('commit a')
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
61
        tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
62
        branch_b = tree_b.branch
63
        tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
64
        branch_c = tree_c.branch
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
65
        self.build_tree(['branch_a/b'])
66
        tree_a.add('b')
67
        tree_a.commit('commit b')
68
        self.build_tree(['branch_b/c'])
69
        tree_b.add('c')
70
        tree_b.commit('commit c')
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
71
        # initial push location must be empty
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
72
        self.assertEqual(None, branch_b.get_push_location())
1785.1.2 by John Arbash Meinel
Push should only save the location if it can actually connect (doesn't need to succeed)
73
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
74
        # test push for failure without push location set
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
75
        os.chdir('branch_a')
2530.3.1 by Martin Pool
Cleanup old variations on run_bzr in the test suite
76
        out = self.run_bzr('push', retcode=3)
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
77
        self.assertEquals(out,
78
                ('','bzr: ERROR: No push location known or specified.\n'))
1785.1.2 by John Arbash Meinel
Push should only save the location if it can actually connect (doesn't need to succeed)
79
80
        # test not remembered if cannot actually push
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
81
        self.run_bzr('push ../path/which/doesnt/exist', retcode=3)
1785.1.2 by John Arbash Meinel
Push should only save the location if it can actually connect (doesn't need to succeed)
82
        out = self.run_bzr('push', retcode=3)
83
        self.assertEquals(
84
                ('', 'bzr: ERROR: No push location known or specified.\n'),
85
                out)
86
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
87
        # test implicit --remember when no push location set, push fails
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
88
        out = self.run_bzr('push ../branch_b', retcode=3)
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
89
        self.assertEquals(out,
90
                ('','bzr: ERROR: These branches have diverged.  '
2063.2.1 by John Arbash Meinel
(Matthieu Moy) cleanup message when pushing to diverged branch
91
                    'Try using "merge" and then "push".\n'))
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
92
        self.assertEquals(abspath(branch_a.get_push_location()),
93
                          abspath(branch_b.bzrdir.root_transport.base))
1785.1.2 by John Arbash Meinel
Push should only save the location if it can actually connect (doesn't need to succeed)
94
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
95
        # test implicit --remember after resolving previous failure
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
96
        uncommit(branch=branch_b, tree=tree_b)
97
        transport.delete('branch_b/c')
2220.2.38 by Martin Pool
Tag conflicts from push go to stdout.
98
        out, err = self.run_bzr('push')
1785.1.1 by John Arbash Meinel
Fix the output of 'bzr push' so that it prints the location correctly.
99
        path = branch_a.get_push_location()
2220.2.38 by Martin Pool
Tag conflicts from push go to stdout.
100
        self.assertEquals(out,
3978.2.5 by Jelmer Vernooij
Fix trailing whitespace.
101
                          'Using saved push location: %s\n'
2220.2.38 by Martin Pool
Tag conflicts from push go to stdout.
102
                          % local_path_from_url(path))
103
        self.assertEqual(err,
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
104
                         'All changes applied successfully.\n'
105
                         'Pushed up to revision 2.\n')
1785.1.1 by John Arbash Meinel
Fix the output of 'bzr push' so that it prints the location correctly.
106
        self.assertEqual(path,
107
                         branch_b.bzrdir.root_transport.base)
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
108
        # test explicit --remember
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
109
        self.run_bzr('push ../branch_c --remember')
1785.1.1 by John Arbash Meinel
Fix the output of 'bzr push' so that it prints the location correctly.
110
        self.assertEquals(branch_a.get_push_location(),
111
                          branch_c.bzrdir.root_transport.base)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
112
1692.3.1 by Robert Collins
Fix push to work with just a branch, no need for a working tree.
113
    def test_push_without_tree(self):
114
        # bzr push from a branch that does not have a checkout should work.
115
        b = self.make_branch('.')
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
116
        out, err = self.run_bzr('push pushed-location')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
117
        self.assertEqual('', out)
118
        self.assertEqual('Created new branch.\n', err)
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
119
        b2 = Branch.open('pushed-location')
1692.3.1 by Robert Collins
Fix push to work with just a branch, no need for a working tree.
120
        self.assertEndsWith(b2.base, 'pushed-location/')
1692.3.6 by Robert Collins
Show the correct number of revisions pushed when pushing a new branch (Robert Collins).
121
122
    def test_push_new_branch_revision_count(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
123
        # bzr push of a branch with revisions to a new location
124
        # should print the number of revisions equal to the length of the
1692.3.6 by Robert Collins
Show the correct number of revisions pushed when pushing a new branch (Robert Collins).
125
        # local branch.
126
        t = self.make_branch_and_tree('tree')
127
        self.build_tree(['tree/file'])
128
        t.add('file')
129
        t.commit('commit 1')
130
        os.chdir('tree')
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
131
        out, err = self.run_bzr('push pushed-to')
1692.3.6 by Robert Collins
Show the correct number of revisions pushed when pushing a new branch (Robert Collins).
132
        os.chdir('..')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
133
        self.assertEqual('', out)
134
        self.assertEqual('Created new branch.\n', err)
1711.2.3 by John Arbash Meinel
Fix push to only push revisions in the current ancestry. (bug???)
135
136
    def test_push_only_pushes_history(self):
137
        # Knit branches should only push the history for the current revision.
138
        format = BzrDirMetaFormat1()
139
        format.repository_format = RepositoryFormatKnit1()
140
        shared_repo = self.make_repository('repo', format=format, shared=True)
141
        shared_repo.set_make_working_trees(True)
142
143
        def make_shared_tree(path):
144
            shared_repo.bzrdir.root_transport.mkdir(path)
145
            shared_repo.bzrdir.create_branch_convenience('repo/' + path)
146
            return WorkingTree.open('repo/' + path)
147
        tree_a = make_shared_tree('a')
148
        self.build_tree(['repo/a/file'])
149
        tree_a.add('file')
150
        tree_a.commit('commit a-1', rev_id='a-1')
151
        f = open('repo/a/file', 'ab')
152
        f.write('more stuff\n')
153
        f.close()
154
        tree_a.commit('commit a-2', rev_id='a-2')
155
156
        tree_b = make_shared_tree('b')
157
        self.build_tree(['repo/b/file'])
158
        tree_b.add('file')
159
        tree_b.commit('commit b-1', rev_id='b-1')
160
161
        self.assertTrue(shared_repo.has_revision('a-1'))
162
        self.assertTrue(shared_repo.has_revision('a-2'))
163
        self.assertTrue(shared_repo.has_revision('b-1'))
164
165
        # Now that we have a repository with shared files, make sure
166
        # that things aren't copied out by a 'push'
167
        os.chdir('repo/b')
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
168
        self.run_bzr('push ../../push-b')
1711.2.3 by John Arbash Meinel
Fix push to only push revisions in the current ancestry. (bug???)
169
        pushed_tree = WorkingTree.open('../../push-b')
170
        pushed_repo = pushed_tree.branch.repository
171
        self.assertFalse(pushed_repo.has_revision('a-1'))
172
        self.assertFalse(pushed_repo.has_revision('a-2'))
173
        self.assertTrue(pushed_repo.has_revision('b-1'))
174
1843.2.1 by Aaron Bentley
Add failing tests for funky ids
175
    def test_push_funky_id(self):
176
        t = self.make_branch_and_tree('tree')
177
        os.chdir('tree')
178
        self.build_tree(['filename'])
179
        t.add('filename', 'funky-chars<>%&;"\'')
180
        t.commit('commit filename')
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
181
        self.run_bzr('push ../new-tree')
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
182
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
183
    def test_push_dash_d(self):
184
        t = self.make_branch_and_tree('from')
185
        t.commit(allow_pointless=True,
186
                message='first commit')
2530.3.1 by Martin Pool
Cleanup old variations on run_bzr in the test suite
187
        self.run_bzr('push -d from to-one')
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
188
        self.failUnlessExists('to-one')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
189
        self.run_bzr('push -d %s %s'
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
190
            % tuple(map(urlutils.local_path_to_url, ['from', 'to-two'])))
191
        self.failUnlessExists('to-two')
2279.3.1 by mbp at sourcefrog
Add a -d option to push, pull, merge (ported from tags branch)
192
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
193
    def test_push_smart_non_stacked_streaming_acceptance(self):
4017.2.1 by Robert Collins
Add BzrDirFormatMeta1 test for the amount of rpc calls made initializing over the network.
194
        self.setup_smart_server_with_call_log()
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
195
        t = self.make_branch_and_tree('from')
196
        t.commit(allow_pointless=True, message='first commit')
4017.2.1 by Robert Collins
Add BzrDirFormatMeta1 test for the amount of rpc calls made initializing over the network.
197
        self.reset_smart_call_log()
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
198
        self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
4011.2.4 by Robert Collins
Make the ratchet aspect of the blackbox smart server push acceptance tests clearer.
199
        # This figure represent the amount of work to perform this use case. It
200
        # is entirely ok to reduce this number if a test fails due to rpc_count
201
        # being too low. If rpc_count increases, more network roundtrips have
202
        # become necessary for this use case. Please do not adjust this number
203
        # upwards without agreement from bzr's network support maintainers.
4226.1.6 by Robert Collins
Revert an overly optimistic change to the Remote acceptance tests - they are not improved yet.
204
        self.assertLength(20, self.hpss_calls)
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
205
206
    def test_push_smart_stacked_streaming_acceptance(self):
4017.2.1 by Robert Collins
Add BzrDirFormatMeta1 test for the amount of rpc calls made initializing over the network.
207
        self.setup_smart_server_with_call_log()
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
208
        parent = self.make_branch_and_tree('parent', format='1.9')
209
        parent.commit(message='first commit')
210
        local = parent.bzrdir.sprout('local').open_workingtree()
211
        local.commit(message='local commit')
4017.2.1 by Robert Collins
Add BzrDirFormatMeta1 test for the amount of rpc calls made initializing over the network.
212
        self.reset_smart_call_log()
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
213
        self.run_bzr(['push', '--stacked', '--stacked-on', '../parent',
214
            self.get_url('public')], working_dir='local')
4011.2.4 by Robert Collins
Make the ratchet aspect of the blackbox smart server push acceptance tests clearer.
215
        # This figure represent the amount of work to perform this use case. It
216
        # is entirely ok to reduce this number if a test fails due to rpc_count
217
        # being too low. If rpc_count increases, more network roundtrips have
218
        # become necessary for this use case. Please do not adjust this number
219
        # upwards without agreement from bzr's network support maintainers.
4226.1.3 by Robert Collins
Lift Branch.set_stacked_on_url up from BzrBranch7.
220
        self.assertLength(47, self.hpss_calls)
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
221
        remote = Branch.open('public')
222
        self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
223
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
224
    def create_simple_tree(self):
225
        tree = self.make_branch_and_tree('tree')
226
        self.build_tree(['tree/a'])
227
        tree.add(['a'], ['a-id'])
228
        tree.commit('one', rev_id='r1')
229
        return tree
230
231
    def test_push_create_prefix(self):
232
        """'bzr push --create-prefix' will create leading directories."""
233
        tree = self.create_simple_tree()
234
235
        self.run_bzr_error(['Parent directory of ../new/tree does not exist'],
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
236
                           'push ../new/tree',
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
237
                           working_dir='tree')
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
238
        self.run_bzr('push ../new/tree --create-prefix',
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
239
                     working_dir='tree')
240
        new_tree = WorkingTree.open('new/tree')
241
        self.assertEqual(tree.last_revision(), new_tree.last_revision())
242
        self.failUnlessExists('new/tree/a')
243
244
    def test_push_use_existing(self):
2227.3.4 by John Arbash Meinel
Switch back to --use-existing-dir
245
        """'bzr push --use-existing-dir' can push into an existing dir.
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
246
247
        By default, 'bzr push' will not use an existing, non-versioned dir.
248
        """
249
        tree = self.create_simple_tree()
250
        self.build_tree(['target/'])
251
252
        self.run_bzr_error(['Target directory ../target already exists',
2227.3.4 by John Arbash Meinel
Switch back to --use-existing-dir
253
                            'Supply --use-existing-dir',
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
254
                           ],
255
                           'push ../target', working_dir='tree')
2227.3.4 by John Arbash Meinel
Switch back to --use-existing-dir
256
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
257
        self.run_bzr('push --use-existing-dir ../target',
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
258
                     working_dir='tree')
259
260
        new_tree = WorkingTree.open('target')
261
        self.assertEqual(tree.last_revision(), new_tree.last_revision())
262
        # The push should have created target/a
263
        self.failUnlessExists('target/a')
264
265
    def test_push_onto_repo(self):
266
        """We should be able to 'bzr push' into an existing bzrdir."""
267
        tree = self.create_simple_tree()
268
        repo = self.make_repository('repo', shared=True)
269
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
270
        self.run_bzr('push ../repo',
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
271
                     working_dir='tree')
272
273
        # Pushing onto an existing bzrdir will create a repository and
274
        # branch as needed, but will only create a working tree if there was
275
        # no BzrDir before.
276
        self.assertRaises(errors.NoWorkingTree, WorkingTree.open, 'repo')
277
        new_branch = Branch.open('repo')
278
        self.assertEqual(tree.last_revision(), new_branch.last_revision())
279
280
    def test_push_onto_just_bzrdir(self):
281
        """We don't handle when the target is just a bzrdir.
282
283
        Because you shouldn't be able to create *just* a bzrdir in the wild.
284
        """
285
        # TODO: jam 20070109 Maybe it would be better to create the repository
286
        #       if at this point
287
        tree = self.create_simple_tree()
288
        a_bzrdir = self.make_bzrdir('dir')
289
290
        self.run_bzr_error(['At ../dir you have a valid .bzr control'],
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
291
                'push ../dir',
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
292
                working_dir='tree')
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
293
3256.1.1 by Daniel Watkins
Added test for push with a revspec.
294
    def test_push_with_revisionspec(self):
3256.1.3 by Daniel Watkins
Clarified test intent.
295
        """We should be able to push a revision older than the tip."""
3256.1.1 by Daniel Watkins
Added test for push with a revspec.
296
        tree_from = self.make_branch_and_tree('from')
297
        tree_from.commit("One.", rev_id="from-1")
298
        tree_from.commit("Two.", rev_id="from-2")
299
300
        self.run_bzr('push -r1 ../to', working_dir='from')
301
302
        tree_to = WorkingTree.open('to')
303
        repo_to = tree_to.branch.repository
304
        self.assertTrue(repo_to.has_revision('from-1'))
305
        self.assertFalse(repo_to.has_revision('from-2'))
306
        self.assertEqual(tree_to.branch.last_revision_info()[1], 'from-1')
307
3256.1.4 by Daniel Watkins
Added test to ensure that passing a range of revisions errors.
308
        self.run_bzr_error(
309
            "bzr: ERROR: bzr push --revision takes one value.\n",
310
            'push -r0..2 ../to', working_dir='from')
311
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
312
    def create_trunk_and_feature_branch(self):
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
313
        # We have a mainline
314
        trunk_tree = self.make_branch_and_tree('target',
315
            format='development')
316
        trunk_tree.commit('mainline')
317
        # and a branch from it
318
        branch_tree = self.make_branch_and_tree('branch',
319
            format='development')
320
        branch_tree.pull(trunk_tree.branch)
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
321
        branch_tree.branch.set_parent(trunk_tree.branch.base)
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
322
        # with some work on it
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
323
        branch_tree.commit('moar work plz')
324
        return trunk_tree, branch_tree
325
3221.11.14 by Robert Collins
Refactor to reduce duplication.
326
    def assertPublished(self, branch_revid, stacked_on):
327
        """Assert that the branch 'published' has been published correctly."""
328
        published_branch = Branch.open('published')
329
        # The published branch refers to the mainline
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
330
        self.assertEqual(stacked_on, published_branch.get_stacked_on_url())
3221.11.14 by Robert Collins
Refactor to reduce duplication.
331
        # and the branch's work was pushed
332
        self.assertTrue(published_branch.repository.has_revision(branch_revid))
333
3549.1.1 by Martin Pool
rename push --reference to --stacked-on
334
    def test_push_new_branch_stacked_on(self):
335
        """Pushing a new branch with --stacked-on creates a stacked branch."""
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
336
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
337
        # we publish branch_tree with a reference to the mainline.
3549.1.1 by Martin Pool
rename push --reference to --stacked-on
338
        out, err = self.run_bzr(['push', '--stacked-on', trunk_tree.branch.base,
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
339
            self.get_url('published')], working_dir='branch')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
340
        self.assertEqual('', out)
3221.19.4 by Ian Clatworthy
shallow -> stacked
341
        self.assertEqual('Created new stacked branch referring to %s.\n' %
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
342
            trunk_tree.branch.base, err)
3221.11.14 by Robert Collins
Refactor to reduce duplication.
343
        self.assertPublished(branch_tree.last_revision(),
344
            trunk_tree.branch.base)
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
345
3221.19.4 by Ian Clatworthy
shallow -> stacked
346
    def test_push_new_branch_stacked_uses_parent_when_no_public_url(self):
3221.11.17 by Robert Collins
no public location causes the parent to be used directly with push --shallow.
347
        """When the parent has no public url the parent is used as-is."""
348
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
3221.19.4 by Ian Clatworthy
shallow -> stacked
349
        # now we do a stacked push, which should determine the public location
3221.11.17 by Robert Collins
no public location causes the parent to be used directly with push --shallow.
350
        # for us.
3221.19.4 by Ian Clatworthy
shallow -> stacked
351
        out, err = self.run_bzr(['push', '--stacked',
3221.11.17 by Robert Collins
no public location causes the parent to be used directly with push --shallow.
352
            self.get_url('published')], working_dir='branch')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
353
        self.assertEqual('', out)
3221.19.4 by Ian Clatworthy
shallow -> stacked
354
        self.assertEqual('Created new stacked branch referring to %s.\n' %
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
355
            trunk_tree.branch.base, err)
3221.14.1 by Robert Collins
Fix typo.
356
        self.assertPublished(branch_tree.last_revision(), trunk_tree.branch.base)
3221.11.17 by Robert Collins
no public location causes the parent to be used directly with push --shallow.
357
3221.19.4 by Ian Clatworthy
shallow -> stacked
358
    def test_push_new_branch_stacked_uses_parent_public(self):
359
        """Pushing a new branch with --stacked creates a stacked branch."""
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
360
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
361
        # the trunk is published on a web server
362
        self.transport_readonly_server = HttpServer
363
        trunk_public = self.make_branch('public_trunk', format='development')
364
        trunk_public.pull(trunk_tree.branch)
365
        trunk_public_url = self.get_readonly_url('public_trunk')
366
        trunk_tree.branch.set_public_branch(trunk_public_url)
3221.19.4 by Ian Clatworthy
shallow -> stacked
367
        # now we do a stacked push, which should determine the public location
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
368
        # for us.
3221.19.4 by Ian Clatworthy
shallow -> stacked
369
        out, err = self.run_bzr(['push', '--stacked',
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
370
            self.get_url('published')], working_dir='branch')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
371
        self.assertEqual('', out)
3221.19.4 by Ian Clatworthy
shallow -> stacked
372
        self.assertEqual('Created new stacked branch referring to %s.\n' %
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
373
            trunk_public_url, err)
3221.11.14 by Robert Collins
Refactor to reduce duplication.
374
        self.assertPublished(branch_tree.last_revision(), trunk_public_url)
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
375
3221.19.4 by Ian Clatworthy
shallow -> stacked
376
    def test_push_new_branch_stacked_no_parent(self):
377
        """Pushing with --stacked and no parent branch errors."""
3221.11.15 by Robert Collins
no parent branch causes an error on push --shallow.
378
        branch = self.make_branch_and_tree('branch', format='development')
3221.19.4 by Ian Clatworthy
shallow -> stacked
379
        # now we do a stacked push, which should fail as the place to refer too
3221.11.15 by Robert Collins
no parent branch causes an error on push --shallow.
380
        # cannot be determined.
381
        out, err = self.run_bzr_error(
3221.19.4 by Ian Clatworthy
shallow -> stacked
382
            ['Could not determine branch to refer to\\.'], ['push', '--stacked',
3221.11.15 by Robert Collins
no parent branch causes an error on push --shallow.
383
            self.get_url('published')], working_dir='branch')
384
        self.assertEqual('', out)
385
        self.assertFalse(self.get_transport('published').has('.'))
386
3606.8.3 by John Arbash Meinel
push doesn't notify because it doesn't notice by default.
387
    def test_push_notifies_default_stacking(self):
3735.1.2 by Robert Collins
Remove 1.5 series dev formats and document development2 a little better.
388
        self.make_branch('stack_on', format='1.6')
3242.3.34 by Aaron Bentley
Add notification of default stacking
389
        self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
3735.1.2 by Robert Collins
Remove 1.5 series dev formats and document development2 a little better.
390
        self.make_branch('from', format='1.6')
3242.3.34 by Aaron Bentley
Add notification of default stacking
391
        out, err = self.run_bzr('push -d from to')
3641.1.1 by John Arbash Meinel
Merge in 1.6rc5 and revert disabling default stack on policy
392
        self.assertContainsRe(err,
393
                              'Using default stacking branch stack_on at .*')
3242.3.34 by Aaron Bentley
Add notification of default stacking
394
4165.2.1 by Robert Collins
Fix bzr failing to stack when a server requests it and the branch it is pushing from cannot stack but the branch it should stack on can.
395
    def test_push_stacks_with_default_stacking_if_target_is_stackable(self):
396
        self.make_branch('stack_on', format='1.6')
397
        self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
398
        self.make_branch('from', format='pack-0.92')
399
        out, err = self.run_bzr('push -d from to')
400
        branch = Branch.open('to')
401
        self.assertEqual('../stack_on', branch.get_stacked_on_url())
402
403
    def test_push_does_not_change_format_with_default_if_target_cannot(self):
404
        self.make_branch('stack_on', format='pack-0.92')
405
        self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
406
        self.make_branch('from', format='pack-0.92')
407
        out, err = self.run_bzr('push -d from to')
408
        branch = Branch.open('to')
409
        self.assertRaises(errors.UnstackableBranchFormat,
410
            branch.get_stacked_on_url)
411
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
412
    def test_push_doesnt_create_broken_branch(self):
3904.3.7 by Andrew Bennetts
Comment the new tests.
413
        """Pushing a new standalone branch works even when there's a default
414
        stacking policy at the destination.
415
416
        The new branch will preserve the repo format (even if it isn't the
417
        default for the branch), and will be stacked when the repo format
418
        allows (which means that the branch format isn't necessarly preserved).
419
        """
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
420
        self.make_repository('repo', shared=True, format='1.6')
421
        builder = self.make_branch_builder('repo/local', format='pack-0.92')
422
        builder.start_series()
423
        builder.build_snapshot('rev-1', None, [
424
            ('add', ('', 'root-id', 'directory', '')),
3904.3.3 by Andrew Bennetts
Simplify test slightly.
425
            ('add', ('filename', 'f-id', 'file', 'content\n'))])
426
        builder.build_snapshot('rev-2', ['rev-1'], [])
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
427
        builder.build_snapshot('rev-3', ['rev-2'],
3904.3.3 by Andrew Bennetts
Simplify test slightly.
428
            [('modify', ('f-id', 'new-content\n'))])
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
429
        builder.finish_series()
430
        branch = builder.get_branch()
3904.3.7 by Andrew Bennetts
Comment the new tests.
431
        # Push rev-1 to "trunk", so that we can stack on it.
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
432
        self.run_bzr('push -d repo/local trunk -r 1')
3904.3.7 by Andrew Bennetts
Comment the new tests.
433
        # Set a default stacking policy so that new branches will automatically
434
        # stack on trunk.
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
435
        self.make_bzrdir('.').get_config().set_default_stack_on('trunk')
3904.3.7 by Andrew Bennetts
Comment the new tests.
436
        # Push rev-2 to a new branch "remote".  It will be stacked on "trunk".
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
437
        out, err = self.run_bzr('push -d repo/local remote -r 2')
438
        self.assertContainsRe(
439
            err, 'Using default stacking branch trunk at .*')
3904.3.7 by Andrew Bennetts
Comment the new tests.
440
        # Push rev-3 onto "remote".  If "remote" not stacked and is missing the
441
        # fulltext record for f-id @ rev-1, then this will fail.
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
442
        out, err = self.run_bzr('push -d repo/local remote -r 3')
443
3848.1.19 by Aaron Bentley
Show log for non-initial push -v
444
    def test_push_verbose_shows_log(self):
445
        tree = self.make_branch_and_tree('source')
446
        tree.commit('rev1')
447
        out, err = self.run_bzr('push -v -d source target')
448
        # initial push contains log
449
        self.assertContainsRe(out, 'rev1')
450
        tree.commit('rev2')
451
        out, err = self.run_bzr('push -v -d source target')
452
        # subsequent push contains log
453
        self.assertContainsRe(out, 'rev2')
454
        # subsequent log is accurate
455
        self.assertNotContainsRe(out, 'rev1')
456
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
457
458
class RedirectingMemoryTransport(MemoryTransport):
459
3878.4.4 by Vincent Ladeuil
Cleanup.
460
    def mkdir(self, relpath, mode=None):
461
        from bzrlib.trace import mutter
462
        mutter('cwd: %r, rel: %r, abs: %r' % (self._cwd, relpath, abspath))
463
        if self._cwd == '/source/':
464
            raise errors.RedirectRequested(self.abspath(relpath),
465
                                           self.abspath('../target'),
466
                                           is_permanent=True)
467
        elif self._cwd == '/infinite-loop/':
468
            raise errors.RedirectRequested(self.abspath(relpath),
469
                                           self.abspath('../infinite-loop'),
470
                                           is_permanent=True)
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
471
        else:
472
            return super(RedirectingMemoryTransport, self).mkdir(
3878.4.4 by Vincent Ladeuil
Cleanup.
473
                relpath, mode)
474
3878.4.5 by Vincent Ladeuil
Don't use the exception as a parameter for _redirected_to.
475
    def _redirected_to(self, source, target):
3878.4.4 by Vincent Ladeuil
Cleanup.
476
        # We do accept redirections
3878.4.5 by Vincent Ladeuil
Don't use the exception as a parameter for _redirected_to.
477
        return transport.get_transport(target)
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
478
479
480
class RedirectingMemoryServer(MemoryServer):
481
482
    def setUp(self):
483
        self._dirs = {'/': None}
484
        self._files = {}
485
        self._locks = {}
486
        self._scheme = 'redirecting-memory+%s:///' % id(self)
3878.4.4 by Vincent Ladeuil
Cleanup.
487
        transport.register_transport(self._scheme, self._memory_factory)
3066.3.3 by jml at canonical
Unregister the test transport in order to be clean and to make test_selftest pass.
488
489
    def _memory_factory(self, url):
490
        result = RedirectingMemoryTransport(url)
491
        result._dirs = self._dirs
492
        result._files = self._files
493
        result._locks = self._locks
494
        return result
495
496
    def tearDown(self):
3878.4.4 by Vincent Ladeuil
Cleanup.
497
        transport.unregister_transport(self._scheme, self._memory_factory)
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
498
499
500
class TestPushRedirect(ExternalBase):
501
502
    def setUp(self):
503
        ExternalBase.setUp(self)
504
        self.memory_server = RedirectingMemoryServer()
505
        self.memory_server.setUp()
506
        self.addCleanup(self.memory_server.tearDown)
507
3066.3.2 by jml at canonical
Add tests to check the handling of TooManyRedirections.
508
        # Make the branch and tree that we'll be pushing.
509
        t = self.make_branch_and_tree('tree')
510
        self.build_tree(['tree/file'])
511
        t.add('file')
512
        t.commit('commit 1')
513
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
514
    def test_push_redirects_on_mkdir(self):
515
        """If the push requires a mkdir, push respects redirect requests.
516
517
        This is added primarily to handle lp:/ URI support, so that users can
518
        push to new branches by specifying lp:/ URIs.
519
        """
520
        destination_url = self.memory_server.get_url() + 'source'
3878.4.4 by Vincent Ladeuil
Cleanup.
521
        self.run_bzr(['push', '-d', 'tree', destination_url])
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
522
523
        local_revision = Branch.open('tree').last_revision()
524
        remote_revision = Branch.open(
525
            self.memory_server.get_url() + 'target').last_revision()
526
        self.assertEqual(remote_revision, local_revision)
3066.3.2 by jml at canonical
Add tests to check the handling of TooManyRedirections.
527
528
    def test_push_gracefully_handles_too_many_redirects(self):
529
        """Push fails gracefully if the mkdir generates a large number of
530
        redirects.
531
        """
532
        destination_url = self.memory_server.get_url() + 'infinite-loop'
533
        out, err = self.run_bzr_error(
534
            ['Too many redirections trying to make %s\\.\n'
535
             % re.escape(destination_url)],
3878.4.4 by Vincent Ladeuil
Cleanup.
536
            ['push', '-d', 'tree', destination_url], retcode=3)
3066.3.2 by jml at canonical
Add tests to check the handling of TooManyRedirections.
537
        self.assertEqual('', out)