~bzr-pqm/bzr/bzr.dev

4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2006-2010 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
3066.3.2 by jml at canonical
Add tests to check the handling of TooManyRedirections.
20
import re
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
21
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
22
from bzrlib import (
4420.1.1 by Vincent Ladeuil
Cleanup imports.
23
    branch,
24
    bzrdir,
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
25
    errors,
4420.1.1 by Vincent Ladeuil
Cleanup imports.
26
    osutils,
27
    tests,
3878.4.4 by Vincent Ladeuil
Cleanup.
28
    transport,
4420.1.1 by Vincent Ladeuil
Cleanup imports.
29
    uncommit,
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
30
    urlutils,
4420.1.1 by Vincent Ladeuil
Cleanup imports.
31
    workingtree
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
32
    )
4420.1.1 by Vincent Ladeuil
Cleanup imports.
33
from bzrlib.repofmt import knitrepo
4925.1.1 by Jelmer Vernooij
Print a proper error when attempting to push to a foreign VCS for which
34
from bzrlib.tests import (
35
    blackbox,
36
    http_server,
37
    test_foreign,
5017.3.37 by Vincent Ladeuil
-s bb.test_push passing
38
    test_server,
4925.1.1 by Jelmer Vernooij
Print a proper error when attempting to push to a foreign VCS for which
39
    )
4420.1.1 by Vincent Ladeuil
Cleanup imports.
40
from bzrlib.transport import memory
41
42
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
43
def load_tests(standard_tests, module, loader):
44
    """Multiply tests for the push command."""
45
    result = loader.suiteClass()
46
47
    # one for each king of change
48
    changes_tests, remaining_tests = tests.split_suite_by_condition(
49
        standard_tests, tests.condition_isinstance((
50
                TestPushStrictWithChanges,
51
                )))
52
    changes_scenarios = [
53
        ('uncommitted',
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
54
         dict(_changes_type= '_uncommitted_changes')),
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
55
        ('pending-merges',
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
56
         dict(_changes_type= '_pending_merges')),
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
57
        ('out-of-sync-trees',
58
         dict(_changes_type= '_out_of_sync_trees')),
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
59
        ]
60
    tests.multiply_tests(changes_tests, changes_scenarios, result)
61
    # No parametrization for the remaining tests
62
    result.addTests(remaining_tests)
63
64
    return result
65
66
4420.1.1 by Vincent Ladeuil
Cleanup imports.
67
class TestPush(tests.TestCaseWithTransport):
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
68
4017.2.3 by Robert Collins
Review feedback.
69
    def test_push_error_on_vfs_http(self):
70
        """ pushing a branch to a HTTP server fails cleanly. """
71
        # the trunk is published on a web server
4420.1.1 by Vincent Ladeuil
Cleanup imports.
72
        self.transport_readonly_server = http_server.HttpServer
4017.2.3 by Robert Collins
Review feedback.
73
        self.make_branch('source')
74
        public_url = self.get_readonly_url('target')
75
        self.run_bzr_error(['http does not support mkdir'],
76
                           ['push', public_url],
77
                           working_dir='source')
78
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
79
    def test_push_remember(self):
80
        """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.
81
        transport = self.get_transport()
82
        tree_a = self.make_branch_and_tree('branch_a')
83
        branch_a = tree_a.branch
84
        self.build_tree(['branch_a/a'])
85
        tree_a.add('a')
86
        tree_a.commit('commit a')
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
87
        tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
88
        branch_b = tree_b.branch
89
        tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
90
        branch_c = tree_c.branch
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
91
        self.build_tree(['branch_a/b'])
92
        tree_a.add('b')
93
        tree_a.commit('commit b')
94
        self.build_tree(['branch_b/c'])
95
        tree_b.add('c')
96
        tree_b.commit('commit c')
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
97
        # initial push location must be empty
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
98
        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)
99
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
100
        # test push for failure without push location set
4420.1.1 by Vincent Ladeuil
Cleanup imports.
101
        out = self.run_bzr('push', working_dir='branch_a', retcode=3)
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
102
        self.assertEquals(out,
103
                ('','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)
104
105
        # test not remembered if cannot actually push
4420.1.1 by Vincent Ladeuil
Cleanup imports.
106
        self.run_bzr('push path/which/doesnt/exist',
107
                     working_dir='branch_a', retcode=3)
108
        out = self.run_bzr('push', working_dir='branch_a', 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)
109
        self.assertEquals(
110
                ('', 'bzr: ERROR: No push location known or specified.\n'),
111
                out)
112
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
113
        # test implicit --remember when no push location set, push fails
4420.1.1 by Vincent Ladeuil
Cleanup imports.
114
        out = self.run_bzr('push ../branch_b',
115
                           working_dir='branch_a', retcode=3)
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
116
        self.assertEquals(out,
117
                ('','bzr: ERROR: These branches have diverged.  '
4441.1.1 by Aaron Bentley
Merge nmb's diverged-branch docs.
118
                 'See "bzr help diverged-branches" for more information.\n'))
4420.1.1 by Vincent Ladeuil
Cleanup imports.
119
        self.assertEquals(osutils.abspath(branch_a.get_push_location()),
120
                          osutils.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)
121
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
122
        # test implicit --remember after resolving previous failure
4420.1.1 by Vincent Ladeuil
Cleanup imports.
123
        uncommit.uncommit(branch=branch_b, tree=tree_b)
1614.2.16 by Olaf Conradi
Modified blackbox test cases to use bzrlib API.
124
        transport.delete('branch_b/c')
4420.1.1 by Vincent Ladeuil
Cleanup imports.
125
        out, err = self.run_bzr('push', working_dir='branch_a')
1785.1.1 by John Arbash Meinel
Fix the output of 'bzr push' so that it prints the location correctly.
126
        path = branch_a.get_push_location()
2220.2.38 by Martin Pool
Tag conflicts from push go to stdout.
127
        self.assertEquals(out,
3978.2.5 by Jelmer Vernooij
Fix trailing whitespace.
128
                          'Using saved push location: %s\n'
4420.1.1 by Vincent Ladeuil
Cleanup imports.
129
                          % urlutils.local_path_from_url(path))
2220.2.38 by Martin Pool
Tag conflicts from push go to stdout.
130
        self.assertEqual(err,
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
131
                         'All changes applied successfully.\n'
132
                         '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.
133
        self.assertEqual(path,
134
                         branch_b.bzrdir.root_transport.base)
1614.2.9 by Olaf Conradi
Added testcases for using push with --remember. Moved remember code to
135
        # test explicit --remember
4420.1.1 by Vincent Ladeuil
Cleanup imports.
136
        self.run_bzr('push ../branch_c --remember', working_dir='branch_a')
1785.1.1 by John Arbash Meinel
Fix the output of 'bzr push' so that it prints the location correctly.
137
        self.assertEquals(branch_a.get_push_location(),
138
                          branch_c.bzrdir.root_transport.base)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
139
1692.3.1 by Robert Collins
Fix push to work with just a branch, no need for a working tree.
140
    def test_push_without_tree(self):
141
        # bzr push from a branch that does not have a checkout should work.
142
        b = self.make_branch('.')
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
143
        out, err = self.run_bzr('push pushed-location')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
144
        self.assertEqual('', out)
145
        self.assertEqual('Created new branch.\n', err)
4420.1.1 by Vincent Ladeuil
Cleanup imports.
146
        b2 = branch.Branch.open('pushed-location')
1692.3.1 by Robert Collins
Fix push to work with just a branch, no need for a working tree.
147
        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).
148
149
    def test_push_new_branch_revision_count(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
150
        # bzr push of a branch with revisions to a new location
151
        # 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).
152
        # local branch.
153
        t = self.make_branch_and_tree('tree')
154
        self.build_tree(['tree/file'])
155
        t.add('file')
156
        t.commit('commit 1')
4420.1.1 by Vincent Ladeuil
Cleanup imports.
157
        out, err = self.run_bzr('push -d tree pushed-to')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
158
        self.assertEqual('', out)
159
        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???)
160
161
    def test_push_only_pushes_history(self):
162
        # Knit branches should only push the history for the current revision.
4420.1.1 by Vincent Ladeuil
Cleanup imports.
163
        format = bzrdir.BzrDirMetaFormat1()
164
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1711.2.3 by John Arbash Meinel
Fix push to only push revisions in the current ancestry. (bug???)
165
        shared_repo = self.make_repository('repo', format=format, shared=True)
166
        shared_repo.set_make_working_trees(True)
167
168
        def make_shared_tree(path):
169
            shared_repo.bzrdir.root_transport.mkdir(path)
170
            shared_repo.bzrdir.create_branch_convenience('repo/' + path)
4420.1.1 by Vincent Ladeuil
Cleanup imports.
171
            return workingtree.WorkingTree.open('repo/' + path)
1711.2.3 by John Arbash Meinel
Fix push to only push revisions in the current ancestry. (bug???)
172
        tree_a = make_shared_tree('a')
173
        self.build_tree(['repo/a/file'])
174
        tree_a.add('file')
175
        tree_a.commit('commit a-1', rev_id='a-1')
176
        f = open('repo/a/file', 'ab')
177
        f.write('more stuff\n')
178
        f.close()
179
        tree_a.commit('commit a-2', rev_id='a-2')
180
181
        tree_b = make_shared_tree('b')
182
        self.build_tree(['repo/b/file'])
183
        tree_b.add('file')
184
        tree_b.commit('commit b-1', rev_id='b-1')
185
186
        self.assertTrue(shared_repo.has_revision('a-1'))
187
        self.assertTrue(shared_repo.has_revision('a-2'))
188
        self.assertTrue(shared_repo.has_revision('b-1'))
189
190
        # Now that we have a repository with shared files, make sure
191
        # that things aren't copied out by a 'push'
4420.1.1 by Vincent Ladeuil
Cleanup imports.
192
        self.run_bzr('push ../../push-b', working_dir='repo/b')
193
        pushed_tree = workingtree.WorkingTree.open('push-b')
1711.2.3 by John Arbash Meinel
Fix push to only push revisions in the current ancestry. (bug???)
194
        pushed_repo = pushed_tree.branch.repository
195
        self.assertFalse(pushed_repo.has_revision('a-1'))
196
        self.assertFalse(pushed_repo.has_revision('a-2'))
197
        self.assertTrue(pushed_repo.has_revision('b-1'))
198
1843.2.1 by Aaron Bentley
Add failing tests for funky ids
199
    def test_push_funky_id(self):
200
        t = self.make_branch_and_tree('tree')
4420.1.1 by Vincent Ladeuil
Cleanup imports.
201
        self.build_tree(['tree/filename'])
1843.2.1 by Aaron Bentley
Add failing tests for funky ids
202
        t.add('filename', 'funky-chars<>%&;"\'')
203
        t.commit('commit filename')
4420.1.1 by Vincent Ladeuil
Cleanup imports.
204
        self.run_bzr('push -d tree new-tree')
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
205
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
206
    def test_push_dash_d(self):
207
        t = self.make_branch_and_tree('from')
208
        t.commit(allow_pointless=True,
209
                message='first commit')
2530.3.1 by Martin Pool
Cleanup old variations on run_bzr in the test suite
210
        self.run_bzr('push -d from to-one')
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
211
        self.failUnlessExists('to-one')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
212
        self.run_bzr('push -d %s %s'
2220.2.9 by Martin Pool
Add specific tests for push -d and pull -d
213
            % tuple(map(urlutils.local_path_to_url, ['from', 'to-two'])))
214
        self.failUnlessExists('to-two')
2279.3.1 by mbp at sourcefrog
Add a -d option to push, pull, merge (ported from tags branch)
215
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
216
    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.
217
        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)
218
        t = self.make_branch_and_tree('from')
219
        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.
220
        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)
221
        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.
222
        # This figure represent the amount of work to perform this use case. It
223
        # is entirely ok to reduce this number if a test fails due to rpc_count
224
        # being too low. If rpc_count increases, more network roundtrips have
225
        # become necessary for this use case. Please do not adjust this number
226
        # upwards without agreement from bzr's network support maintainers.
4307.2.2 by Robert Collins
Lock repositories created by BzrDirFormat.initialize_on_transport_ex.
227
        self.assertLength(9, self.hpss_calls)
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
228
229
    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.
230
        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)
231
        parent = self.make_branch_and_tree('parent', format='1.9')
232
        parent.commit(message='first commit')
233
        local = parent.bzrdir.sprout('local').open_workingtree()
234
        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.
235
        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)
236
        self.run_bzr(['push', '--stacked', '--stacked-on', '../parent',
237
            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.
238
        # This figure represent the amount of work to perform this use case. It
239
        # is entirely ok to reduce this number if a test fails due to rpc_count
240
        # being too low. If rpc_count increases, more network roundtrips have
241
        # become necessary for this use case. Please do not adjust this number
242
        # upwards without agreement from bzr's network support maintainers.
4307.2.5 by Robert Collins
Remove too-early checks for revisions adding unnecessary round trips, at the cost of actually reading revision data when pulling (because we currently don't have a hint as about whats local for fetch).
243
        self.assertLength(14, self.hpss_calls)
4420.1.1 by Vincent Ladeuil
Cleanup imports.
244
        remote = branch.Branch.open('public')
4011.2.1 by Robert Collins
Add ratchet style blackbox effort tests for push over bzr+ssh. (Andrew Bennetts, Robert Collins)
245
        self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
246
4556.2.1 by Andrew Bennetts
Add Branch.set_tags_bytes RPC, with HPSS call count acceptance test. Also fixes serialisation of LockDir, and uses external_url() in LockDir's repr and contention message.
247
    def test_push_smart_tags_streaming_acceptance(self):
248
        self.setup_smart_server_with_call_log()
249
        t = self.make_branch_and_tree('from')
250
        rev_id = t.commit(allow_pointless=True, message='first commit')
251
        t.branch.tags.set_tag('new-tag', rev_id)
252
        self.reset_smart_call_log()
253
        self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
254
        # This figure represent the amount of work to perform this use case. It
255
        # is entirely ok to reduce this number if a test fails due to rpc_count
256
        # being too low. If rpc_count increases, more network roundtrips have
257
        # become necessary for this use case. Please do not adjust this number
258
        # upwards without agreement from bzr's network support maintainers.
259
        self.assertLength(11, self.hpss_calls)
260
4634.47.3 by Andrew Bennetts
Add a BzrDir.open_2.1 verb that indicates if there is a workingtree present. Removes the last 2 VFS calls from incremental pushes.
261
    def test_push_smart_incremental_acceptance(self):
262
        self.setup_smart_server_with_call_log()
263
        t = self.make_branch_and_tree('from')
264
        rev_id1 = t.commit(allow_pointless=True, message='first commit')
265
        rev_id2 = t.commit(allow_pointless=True, message='second commit')
266
        self.run_bzr(
267
            ['push', self.get_url('to-one'), '-r1'], working_dir='from')
268
        self.reset_smart_call_log()
269
        self.run_bzr(['push', self.get_url('to-one')], working_dir='from')
270
        # This figure represent the amount of work to perform this use case. It
271
        # is entirely ok to reduce this number if a test fails due to rpc_count
272
        # being too low. If rpc_count increases, more network roundtrips have
273
        # become necessary for this use case. Please do not adjust this number
274
        # upwards without agreement from bzr's network support maintainers.
275
        self.assertLength(11, self.hpss_calls)
276
4416.3.1 by Jonathan Lange
Add two tests, the second of which demonstrates bug 385132.
277
    def test_push_smart_with_default_stacking_url_path_segment(self):
4416.3.2 by Jonathan Lange
Comment the blackbox tests, for my own sanity.
278
        # If the default stacked-on location is a path element then branches
279
        # we push there over the smart server are stacked and their
280
        # stacked_on_url is that exact path segment. Added to nail bug 385132.
4416.3.1 by Jonathan Lange
Add two tests, the second of which demonstrates bug 385132.
281
        self.setup_smart_server_with_call_log()
282
        self.make_branch('stack-on', format='1.9')
4416.3.7 by Jonathan Lange
Update the test to fail correctly.
283
        self.make_bzrdir('.').get_config().set_default_stack_on(
4416.3.9 by Jonathan Lange
Put the test back the way it was.
284
            '/stack-on')
4416.3.1 by Jonathan Lange
Add two tests, the second of which demonstrates bug 385132.
285
        self.make_branch('from', format='1.9')
286
        out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
4416.3.10 by Jonathan Lange
Merge trunk
287
        b = branch.Branch.open(self.get_url('to'))
4416.3.12 by Jonathan Lange
This makes the test pass, but it's a bit ick.
288
        self.assertEqual('/extra/stack-on', b.get_stacked_on_url())
4416.3.1 by Jonathan Lange
Add two tests, the second of which demonstrates bug 385132.
289
290
    def test_push_smart_with_default_stacking_relative_path(self):
4416.3.2 by Jonathan Lange
Comment the blackbox tests, for my own sanity.
291
        # If the default stacked-on location is a relative path then branches
292
        # we push there over the smart server are stacked and their
293
        # stacked_on_url is a relative path. Added to nail bug 385132.
4416.3.1 by Jonathan Lange
Add two tests, the second of which demonstrates bug 385132.
294
        self.setup_smart_server_with_call_log()
295
        self.make_branch('stack-on', format='1.9')
296
        self.make_bzrdir('.').get_config().set_default_stack_on('stack-on')
297
        self.make_branch('from', format='1.9')
298
        out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
4416.3.10 by Jonathan Lange
Merge trunk
299
        b = branch.Branch.open(self.get_url('to'))
300
        self.assertEqual('../stack-on', b.get_stacked_on_url())
4416.3.1 by Jonathan Lange
Add two tests, the second of which demonstrates bug 385132.
301
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
302
    def create_simple_tree(self):
303
        tree = self.make_branch_and_tree('tree')
304
        self.build_tree(['tree/a'])
305
        tree.add(['a'], ['a-id'])
306
        tree.commit('one', rev_id='r1')
307
        return tree
308
309
    def test_push_create_prefix(self):
310
        """'bzr push --create-prefix' will create leading directories."""
311
        tree = self.create_simple_tree()
312
313
        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.
314
                           'push ../new/tree',
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
315
                           working_dir='tree')
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
316
        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
317
                     working_dir='tree')
4420.1.1 by Vincent Ladeuil
Cleanup imports.
318
        new_tree = workingtree.WorkingTree.open('new/tree')
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
319
        self.assertEqual(tree.last_revision(), new_tree.last_revision())
320
        self.failUnlessExists('new/tree/a')
321
322
    def test_push_use_existing(self):
2227.3.4 by John Arbash Meinel
Switch back to --use-existing-dir
323
        """'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
324
325
        By default, 'bzr push' will not use an existing, non-versioned dir.
326
        """
327
        tree = self.create_simple_tree()
328
        self.build_tree(['target/'])
329
330
        self.run_bzr_error(['Target directory ../target already exists',
2227.3.4 by John Arbash Meinel
Switch back to --use-existing-dir
331
                            'Supply --use-existing-dir',
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
332
                           ],
333
                           'push ../target', working_dir='tree')
2227.3.4 by John Arbash Meinel
Switch back to --use-existing-dir
334
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
335
        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
336
                     working_dir='tree')
337
4420.1.1 by Vincent Ladeuil
Cleanup imports.
338
        new_tree = workingtree.WorkingTree.open('target')
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
339
        self.assertEqual(tree.last_revision(), new_tree.last_revision())
340
        # The push should have created target/a
341
        self.failUnlessExists('target/a')
342
4634.105.1 by Andrew Bennetts
Fix traceback when doing 'bzr push --use-existing-dir' into a dir with an invalid .bzr directory.
343
    def test_push_use_existing_into_empty_bzrdir(self):
344
        """'bzr push --use-existing-dir' into a dir with an empty .bzr dir
345
        fails.
346
        """
347
        tree = self.create_simple_tree()
348
        self.build_tree(['target/', 'target/.bzr/'])
349
        self.run_bzr_error(
4634.105.2 by Andrew Bennetts
Clearer code and error message.
350
            ['Target directory ../target already contains a .bzr directory, '
351
             'but it is not valid.'],
4634.105.1 by Andrew Bennetts
Fix traceback when doing 'bzr push --use-existing-dir' into a dir with an invalid .bzr directory.
352
            'push ../target --use-existing-dir', working_dir='tree')
353
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
354
    def test_push_onto_repo(self):
355
        """We should be able to 'bzr push' into an existing bzrdir."""
356
        tree = self.create_simple_tree()
357
        repo = self.make_repository('repo', shared=True)
358
2552.2.3 by Vincent Ladeuil
Deprecate the varargs syntax and fix the tests.
359
        self.run_bzr('push ../repo',
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
360
                     working_dir='tree')
361
362
        # Pushing onto an existing bzrdir will create a repository and
363
        # branch as needed, but will only create a working tree if there was
364
        # no BzrDir before.
4420.1.1 by Vincent Ladeuil
Cleanup imports.
365
        self.assertRaises(errors.NoWorkingTree,
366
                          workingtree.WorkingTree.open, 'repo')
367
        new_branch = branch.Branch.open('repo')
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
368
        self.assertEqual(tree.last_revision(), new_branch.last_revision())
369
370
    def test_push_onto_just_bzrdir(self):
371
        """We don't handle when the target is just a bzrdir.
372
373
        Because you shouldn't be able to create *just* a bzrdir in the wild.
374
        """
375
        # TODO: jam 20070109 Maybe it would be better to create the repository
376
        #       if at this point
377
        tree = self.create_simple_tree()
378
        a_bzrdir = self.make_bzrdir('dir')
379
380
        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.
381
                'push ../dir',
2227.3.1 by John Arbash Meinel
Allow push to create Branch when necessary, and add --use-existing
382
                working_dir='tree')
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
383
3256.1.1 by Daniel Watkins
Added test for push with a revspec.
384
    def test_push_with_revisionspec(self):
3256.1.3 by Daniel Watkins
Clarified test intent.
385
        """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.
386
        tree_from = self.make_branch_and_tree('from')
387
        tree_from.commit("One.", rev_id="from-1")
388
        tree_from.commit("Two.", rev_id="from-2")
389
390
        self.run_bzr('push -r1 ../to', working_dir='from')
391
4420.1.1 by Vincent Ladeuil
Cleanup imports.
392
        tree_to = workingtree.WorkingTree.open('to')
3256.1.1 by Daniel Watkins
Added test for push with a revspec.
393
        repo_to = tree_to.branch.repository
394
        self.assertTrue(repo_to.has_revision('from-1'))
395
        self.assertFalse(repo_to.has_revision('from-2'))
396
        self.assertEqual(tree_to.branch.last_revision_info()[1], 'from-1')
397
3256.1.4 by Daniel Watkins
Added test to ensure that passing a range of revisions errors.
398
        self.run_bzr_error(
4325.4.6 by Vincent Ladeuil
Fixed as per John's and Markus reviews.
399
            ['bzr: ERROR: bzr push --revision '
400
             'takes exactly one revision identifier\n'],
3256.1.4 by Daniel Watkins
Added test to ensure that passing a range of revisions errors.
401
            'push -r0..2 ../to', working_dir='from')
402
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
403
    def create_trunk_and_feature_branch(self):
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
404
        # We have a mainline
405
        trunk_tree = self.make_branch_and_tree('target',
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
406
            format='1.9')
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
407
        trunk_tree.commit('mainline')
408
        # and a branch from it
409
        branch_tree = self.make_branch_and_tree('branch',
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
410
            format='1.9')
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
411
        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.
412
        branch_tree.branch.set_parent(trunk_tree.branch.base)
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
413
        # 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.
414
        branch_tree.commit('moar work plz')
415
        return trunk_tree, branch_tree
416
3221.11.14 by Robert Collins
Refactor to reduce duplication.
417
    def assertPublished(self, branch_revid, stacked_on):
418
        """Assert that the branch 'published' has been published correctly."""
4420.1.1 by Vincent Ladeuil
Cleanup imports.
419
        published_branch = branch.Branch.open('published')
3221.11.14 by Robert Collins
Refactor to reduce duplication.
420
        # The published branch refers to the mainline
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
421
        self.assertEqual(stacked_on, published_branch.get_stacked_on_url())
3221.11.14 by Robert Collins
Refactor to reduce duplication.
422
        # and the branch's work was pushed
423
        self.assertTrue(published_branch.repository.has_revision(branch_revid))
424
3549.1.1 by Martin Pool
rename push --reference to --stacked-on
425
    def test_push_new_branch_stacked_on(self):
426
        """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.
427
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
428
        # we publish branch_tree with a reference to the mainline.
3549.1.1 by Martin Pool
rename push --reference to --stacked-on
429
        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.
430
            self.get_url('published')], working_dir='branch')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
431
        self.assertEqual('', out)
3221.19.4 by Ian Clatworthy
shallow -> stacked
432
        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.
433
            trunk_tree.branch.base, err)
3221.11.14 by Robert Collins
Refactor to reduce duplication.
434
        self.assertPublished(branch_tree.last_revision(),
435
            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.
436
3221.19.4 by Ian Clatworthy
shallow -> stacked
437
    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.
438
        """When the parent has no public url the parent is used as-is."""
439
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
3221.19.4 by Ian Clatworthy
shallow -> stacked
440
        # 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.
441
        # for us.
3221.19.4 by Ian Clatworthy
shallow -> stacked
442
        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.
443
            self.get_url('published')], working_dir='branch')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
444
        self.assertEqual('', out)
3221.19.4 by Ian Clatworthy
shallow -> stacked
445
        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.
446
            trunk_tree.branch.base, err)
4420.1.1 by Vincent Ladeuil
Cleanup imports.
447
        self.assertPublished(branch_tree.last_revision(),
448
                             trunk_tree.branch.base)
3221.11.17 by Robert Collins
no public location causes the parent to be used directly with push --shallow.
449
3221.19.4 by Ian Clatworthy
shallow -> stacked
450
    def test_push_new_branch_stacked_uses_parent_public(self):
451
        """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.
452
        trunk_tree, branch_tree = self.create_trunk_and_feature_branch()
453
        # the trunk is published on a web server
4420.1.1 by Vincent Ladeuil
Cleanup imports.
454
        self.transport_readonly_server = http_server.HttpServer
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
455
        trunk_public = self.make_branch('public_trunk', format='1.9')
3221.11.13 by Robert Collins
Allow push --shallow to just work, and fix the testing HTTPServer to not be affected by chdir() calls.
456
        trunk_public.pull(trunk_tree.branch)
457
        trunk_public_url = self.get_readonly_url('public_trunk')
458
        trunk_tree.branch.set_public_branch(trunk_public_url)
3221.19.4 by Ian Clatworthy
shallow -> stacked
459
        # 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.
460
        # for us.
3221.19.4 by Ian Clatworthy
shallow -> stacked
461
        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.
462
            self.get_url('published')], working_dir='branch')
3978.2.2 by Jelmer Vernooij
Write status messages during push to stderr rather than stdout.
463
        self.assertEqual('', out)
3221.19.4 by Ian Clatworthy
shallow -> stacked
464
        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.
465
            trunk_public_url, err)
3221.11.14 by Robert Collins
Refactor to reduce duplication.
466
        self.assertPublished(branch_tree.last_revision(), trunk_public_url)
3221.11.12 by Robert Collins
Basic push --reference support, requires url, slow.
467
3221.19.4 by Ian Clatworthy
shallow -> stacked
468
    def test_push_new_branch_stacked_no_parent(self):
469
        """Pushing with --stacked and no parent branch errors."""
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
470
        branch = self.make_branch_and_tree('branch', format='1.9')
3221.19.4 by Ian Clatworthy
shallow -> stacked
471
        # 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.
472
        # cannot be determined.
473
        out, err = self.run_bzr_error(
3221.19.4 by Ian Clatworthy
shallow -> stacked
474
            ['Could not determine branch to refer to\\.'], ['push', '--stacked',
3221.11.15 by Robert Collins
no parent branch causes an error on push --shallow.
475
            self.get_url('published')], working_dir='branch')
476
        self.assertEqual('', out)
477
        self.assertFalse(self.get_transport('published').has('.'))
478
3606.8.3 by John Arbash Meinel
push doesn't notify because it doesn't notice by default.
479
    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.
480
        self.make_branch('stack_on', format='1.6')
3242.3.34 by Aaron Bentley
Add notification of default stacking
481
        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.
482
        self.make_branch('from', format='1.6')
3242.3.34 by Aaron Bentley
Add notification of default stacking
483
        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
484
        self.assertContainsRe(err,
485
                              'Using default stacking branch stack_on at .*')
3242.3.34 by Aaron Bentley
Add notification of default stacking
486
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.
487
    def test_push_stacks_with_default_stacking_if_target_is_stackable(self):
488
        self.make_branch('stack_on', format='1.6')
489
        self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
490
        self.make_branch('from', format='pack-0.92')
491
        out, err = self.run_bzr('push -d from to')
4420.1.1 by Vincent Ladeuil
Cleanup imports.
492
        b = branch.Branch.open('to')
493
        self.assertEqual('../stack_on', b.get_stacked_on_url())
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.
494
495
    def test_push_does_not_change_format_with_default_if_target_cannot(self):
496
        self.make_branch('stack_on', format='pack-0.92')
497
        self.make_bzrdir('.').get_config().set_default_stack_on('stack_on')
498
        self.make_branch('from', format='pack-0.92')
499
        out, err = self.run_bzr('push -d from to')
4420.1.1 by Vincent Ladeuil
Cleanup imports.
500
        b = branch.Branch.open('to')
501
        self.assertRaises(errors.UnstackableBranchFormat, b.get_stacked_on_url)
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.
502
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
503
    def test_push_doesnt_create_broken_branch(self):
3904.3.7 by Andrew Bennetts
Comment the new tests.
504
        """Pushing a new standalone branch works even when there's a default
505
        stacking policy at the destination.
506
507
        The new branch will preserve the repo format (even if it isn't the
508
        default for the branch), and will be stacked when the repo format
509
        allows (which means that the branch format isn't necessarly preserved).
510
        """
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
511
        self.make_repository('repo', shared=True, format='1.6')
512
        builder = self.make_branch_builder('repo/local', format='pack-0.92')
513
        builder.start_series()
514
        builder.build_snapshot('rev-1', None, [
515
            ('add', ('', 'root-id', 'directory', '')),
3904.3.3 by Andrew Bennetts
Simplify test slightly.
516
            ('add', ('filename', 'f-id', 'file', 'content\n'))])
517
        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.
518
        builder.build_snapshot('rev-3', ['rev-2'],
3904.3.3 by Andrew Bennetts
Simplify test slightly.
519
            [('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.
520
        builder.finish_series()
521
        branch = builder.get_branch()
3904.3.7 by Andrew Bennetts
Comment the new tests.
522
        # 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.
523
        self.run_bzr('push -d repo/local trunk -r 1')
3904.3.7 by Andrew Bennetts
Comment the new tests.
524
        # Set a default stacking policy so that new branches will automatically
525
        # stack on trunk.
3904.3.2 by Andrew Bennetts
Blackbox test that triggers the bug. Should get replaced with a unit test.
526
        self.make_bzrdir('.').get_config().set_default_stack_on('trunk')
3904.3.7 by Andrew Bennetts
Comment the new tests.
527
        # 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.
528
        out, err = self.run_bzr('push -d repo/local remote -r 2')
529
        self.assertContainsRe(
530
            err, 'Using default stacking branch trunk at .*')
3904.3.7 by Andrew Bennetts
Comment the new tests.
531
        # Push rev-3 onto "remote".  If "remote" not stacked and is missing the
532
        # 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.
533
        out, err = self.run_bzr('push -d repo/local remote -r 3')
534
3848.1.19 by Aaron Bentley
Show log for non-initial push -v
535
    def test_push_verbose_shows_log(self):
536
        tree = self.make_branch_and_tree('source')
537
        tree.commit('rev1')
538
        out, err = self.run_bzr('push -v -d source target')
539
        # initial push contains log
540
        self.assertContainsRe(out, 'rev1')
541
        tree.commit('rev2')
542
        out, err = self.run_bzr('push -v -d source target')
543
        # subsequent push contains log
544
        self.assertContainsRe(out, 'rev2')
545
        # subsequent log is accurate
546
        self.assertNotContainsRe(out, 'rev1')
547
4453.1.2 by Matthew Fuller
Add a test for pushing from subdir.
548
    def test_push_from_subdir(self):
549
        t = self.make_branch_and_tree('tree')
550
        self.build_tree(['tree/dir/', 'tree/dir/file'])
551
        t.add('dir', 'dir/file')
552
        t.commit('r1')
553
        out, err = self.run_bzr('push ../../pushloc', working_dir='tree/dir')
554
        self.assertEqual('', out)
555
        self.assertEqual('Created new branch.\n', err)
556
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
557
4420.1.1 by Vincent Ladeuil
Cleanup imports.
558
class RedirectingMemoryTransport(memory.MemoryTransport):
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
559
3878.4.4 by Vincent Ladeuil
Cleanup.
560
    def mkdir(self, relpath, mode=None):
561
        if self._cwd == '/source/':
562
            raise errors.RedirectRequested(self.abspath(relpath),
563
                                           self.abspath('../target'),
564
                                           is_permanent=True)
565
        elif self._cwd == '/infinite-loop/':
566
            raise errors.RedirectRequested(self.abspath(relpath),
567
                                           self.abspath('../infinite-loop'),
568
                                           is_permanent=True)
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
569
        else:
570
            return super(RedirectingMemoryTransport, self).mkdir(
3878.4.4 by Vincent Ladeuil
Cleanup.
571
                relpath, mode)
572
4547.2.2 by Andrew Bennetts
Add test for read_mergeable_from_transport raising NotABundle when TooManyRedirections happens.
573
    def get(self, relpath):
574
        if self.clone(relpath)._cwd == '/infinite-loop/':
575
            raise errors.RedirectRequested(self.abspath(relpath),
576
                                           self.abspath('../infinite-loop'),
577
                                           is_permanent=True)
578
        else:
579
            return super(RedirectingMemoryTransport, self).get(relpath)
580
3878.4.5 by Vincent Ladeuil
Don't use the exception as a parameter for _redirected_to.
581
    def _redirected_to(self, source, target):
3878.4.4 by Vincent Ladeuil
Cleanup.
582
        # We do accept redirections
3878.4.5 by Vincent Ladeuil
Don't use the exception as a parameter for _redirected_to.
583
        return transport.get_transport(target)
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
584
585
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
586
class RedirectingMemoryServer(memory.MemoryServer):
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
587
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
588
    def start_server(self):
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
589
        self._dirs = {'/': None}
590
        self._files = {}
591
        self._locks = {}
592
        self._scheme = 'redirecting-memory+%s:///' % id(self)
3878.4.4 by Vincent Ladeuil
Cleanup.
593
        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.
594
595
    def _memory_factory(self, url):
596
        result = RedirectingMemoryTransport(url)
597
        result._dirs = self._dirs
598
        result._files = self._files
599
        result._locks = self._locks
600
        return result
601
4934.3.1 by Martin Pool
Rename Server.tearDown to .stop_server
602
    def stop_server(self):
3878.4.4 by Vincent Ladeuil
Cleanup.
603
        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
604
605
4420.1.1 by Vincent Ladeuil
Cleanup imports.
606
class TestPushRedirect(tests.TestCaseWithTransport):
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
607
608
    def setUp(self):
4420.1.1 by Vincent Ladeuil
Cleanup imports.
609
        tests.TestCaseWithTransport.setUp(self)
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
610
        self.memory_server = RedirectingMemoryServer()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
611
        self.start_server(self.memory_server)
3066.3.2 by jml at canonical
Add tests to check the handling of TooManyRedirections.
612
        # Make the branch and tree that we'll be pushing.
613
        t = self.make_branch_and_tree('tree')
614
        self.build_tree(['tree/file'])
615
        t.add('file')
616
        t.commit('commit 1')
617
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
618
    def test_push_redirects_on_mkdir(self):
619
        """If the push requires a mkdir, push respects redirect requests.
620
621
        This is added primarily to handle lp:/ URI support, so that users can
622
        push to new branches by specifying lp:/ URIs.
623
        """
624
        destination_url = self.memory_server.get_url() + 'source'
3878.4.4 by Vincent Ladeuil
Cleanup.
625
        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
626
4420.1.1 by Vincent Ladeuil
Cleanup imports.
627
        local_revision = branch.Branch.open('tree').last_revision()
628
        remote_revision = branch.Branch.open(
3066.3.1 by jml at canonical
Catch redirects raised by mkdir() in the push command. This is primarily
629
            self.memory_server.get_url() + 'target').last_revision()
630
        self.assertEqual(remote_revision, local_revision)
3066.3.2 by jml at canonical
Add tests to check the handling of TooManyRedirections.
631
632
    def test_push_gracefully_handles_too_many_redirects(self):
633
        """Push fails gracefully if the mkdir generates a large number of
634
        redirects.
635
        """
636
        destination_url = self.memory_server.get_url() + 'infinite-loop'
637
        out, err = self.run_bzr_error(
638
            ['Too many redirections trying to make %s\\.\n'
639
             % re.escape(destination_url)],
3878.4.4 by Vincent Ladeuil
Cleanup.
640
            ['push', '-d', 'tree', destination_url], retcode=3)
3066.3.2 by jml at canonical
Add tests to check the handling of TooManyRedirections.
641
        self.assertEqual('', out)
4420.1.2 by Vincent Ladeuil
Fix bug #284038 by adding a --strict option to push.
642
643
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
644
class TestPushStrictMixin(object):
4420.1.2 by Vincent Ladeuil
Fix bug #284038 by adding a --strict option to push.
645
646
    def make_local_branch_and_tree(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
647
        self.tree = self.make_branch_and_tree('local')
4420.1.2 by Vincent Ladeuil
Fix bug #284038 by adding a --strict option to push.
648
        self.build_tree_contents([('local/file', 'initial')])
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
649
        self.tree.add('file')
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
650
        self.tree.commit('adding file', rev_id='added')
651
        self.build_tree_contents([('local/file', 'modified')])
652
        self.tree.commit('modify file', rev_id='modified')
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
653
654
    def set_config_push_strict(self, value):
4420.1.5 by Vincent Ladeuil
Start implementing jam's review feedback.
655
        # set config var (any of bazaar.conf, locations.conf, branch.conf
656
        # should do)
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
657
        conf = self.tree.branch.get_config()
4420.1.5 by Vincent Ladeuil
Start implementing jam's review feedback.
658
        conf.set_user_option('push_strict', value)
659
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
660
    _default_command = ['push', '../to']
661
    _default_wd = 'local'
662
    _default_errors = ['Working tree ".*/local/" has uncommitted '
663
                       'changes \(See bzr status\)\.',]
664
    _default_pushed_revid = 'modified'
665
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
666
    def assertPushFails(self, args):
5147.2.1 by Vincent Ladeuil
Failing tests for bug #519319.
667
        ret = self.run_bzr_error(self._default_errors,
668
                                 self._default_command + args,
669
                                 working_dir=self._default_wd, retcode=3)
4420.1.5 by Vincent Ladeuil
Start implementing jam's review feedback.
670
5147.2.1 by Vincent Ladeuil
Failing tests for bug #519319.
671
    def assertPushSucceeds(self, args, pushed_revid=None, with_warning=False):
672
        if with_warning:
673
            error_regexes = self._default_errors
674
        else:
675
            error_regexes = []
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
676
        self.run_bzr(self._default_command + args,
5147.2.1 by Vincent Ladeuil
Failing tests for bug #519319.
677
                     working_dir=self._default_wd, error_regexes=error_regexes)
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
678
        if pushed_revid is None:
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
679
            pushed_revid = self._default_pushed_revid
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
680
        tree_to = workingtree.WorkingTree.open('to')
4420.1.2 by Vincent Ladeuil
Fix bug #284038 by adding a --strict option to push.
681
        repo_to = tree_to.branch.repository
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
682
        self.assertTrue(repo_to.has_revision(pushed_revid))
683
        self.assertEqual(tree_to.branch.last_revision_info()[1], pushed_revid)
4420.1.2 by Vincent Ladeuil
Fix bug #284038 by adding a --strict option to push.
684
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
685
686
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
687
class TestPushStrictWithoutChanges(tests.TestCaseWithTransport,
688
                                   TestPushStrictMixin):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
689
690
    def setUp(self):
691
        super(TestPushStrictWithoutChanges, self).setUp()
692
        self.make_local_branch_and_tree()
693
694
    def test_push_default(self):
695
        self.assertPushSucceeds([])
696
697
    def test_push_strict(self):
698
        self.assertPushSucceeds(['--strict'])
699
700
    def test_push_no_strict(self):
701
        self.assertPushSucceeds(['--no-strict'])
702
703
    def test_push_config_var_strict(self):
704
        self.set_config_push_strict('true')
705
        self.assertPushSucceeds([])
706
707
    def test_push_config_var_no_strict(self):
708
        self.set_config_push_strict('false')
709
        self.assertPushSucceeds([])
710
711
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
712
class TestPushStrictWithChanges(tests.TestCaseWithTransport,
713
                                TestPushStrictMixin):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
714
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
715
    _changes_type = None # Set by load_tests
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
716
717
    def setUp(self):
718
        super(TestPushStrictWithChanges, self).setUp()
4721.2.6 by Vincent Ladeuil
More agressive test sharing between push and dpush.
719
        # Apply the changes defined in load_tests: one of _uncommitted_changes,
720
        # _pending_merges or _out_of_sync_trees
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
721
        getattr(self, self._changes_type)()
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
722
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
723
    def _uncommitted_changes(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
724
        self.make_local_branch_and_tree()
725
        # Make a change without committing it
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
726
        self.build_tree_contents([('local/file', 'in progress')])
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
727
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
728
    def _pending_merges(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
729
        self.make_local_branch_and_tree()
730
        # Create 'other' branch containing a new file
731
        other_bzrdir = self.tree.bzrdir.sprout('other')
732
        other_tree = other_bzrdir.open_workingtree()
733
        self.build_tree_contents([('other/other-file', 'other')])
734
        other_tree.add('other-file')
735
        other_tree.commit('other commit', rev_id='other')
736
        # Merge and revert, leaving a pending merge
737
        self.tree.merge_from_branch(other_tree.branch)
738
        self.tree.revert(filenames=['other-file'], backups=False)
739
4487.2.6 by Vincent Ladeuil
Fixed as per jam's review.
740
    def _out_of_sync_trees(self):
741
        self.make_local_branch_and_tree()
742
        self.run_bzr(['checkout', '--lightweight', 'local', 'checkout'])
743
        # Make a change and commit it
744
        self.build_tree_contents([('local/file', 'modified in local')])
745
        self.tree.commit('modify file', rev_id='modified-in-local')
746
        # Exercise commands from the checkout directory
747
        self._default_wd = 'checkout'
748
        self._default_errors = ["Working tree is out of date, please run"
749
                                " 'bzr update'\.",]
750
        self._default_pushed_revid = 'modified-in-local'
751
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
752
    def test_push_default(self):
5147.2.1 by Vincent Ladeuil
Failing tests for bug #519319.
753
        self.assertPushSucceeds([], with_warning=True)
4420.1.5 by Vincent Ladeuil
Start implementing jam's review feedback.
754
4487.2.3 by Vincent Ladeuil
--strict is meaningless when --revision is specified.
755
    def test_push_with_revision(self):
756
        self.assertPushSucceeds(['-r', 'revid:added'], pushed_revid='added')
757
758
    def test_push_no_strict(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
759
        self.assertPushSucceeds(['--no-strict'])
4420.1.2 by Vincent Ladeuil
Fix bug #284038 by adding a --strict option to push.
760
761
    def test_push_strict_with_changes(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
762
        self.assertPushFails(['--strict'])
4420.1.5 by Vincent Ladeuil
Start implementing jam's review feedback.
763
764
    def test_push_respect_config_var_strict(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
765
        self.set_config_push_strict('true')
766
        self.assertPushFails([])
4420.1.5 by Vincent Ladeuil
Start implementing jam's review feedback.
767
4420.1.6 by Vincent Ladeuil
Fixed as per John's review feedback.
768
    def test_push_bogus_config_var_ignored(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
769
        self.set_config_push_strict("I don't want you to be strict")
5147.2.1 by Vincent Ladeuil
Failing tests for bug #519319.
770
        self.assertPushSucceeds([], with_warning=True)
4420.1.6 by Vincent Ladeuil
Fixed as per John's review feedback.
771
4420.1.5 by Vincent Ladeuil
Start implementing jam's review feedback.
772
    def test_push_no_strict_command_line_override_config(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
773
        self.set_config_push_strict('yES')
774
        self.assertPushFails([])
775
        self.assertPushSucceeds(['--no-strict'])
4420.1.5 by Vincent Ladeuil
Start implementing jam's review feedback.
776
777
    def test_push_strict_command_line_override_config(self):
4487.2.2 by Vincent Ladeuil
Add tests for push --strict against pending merges.
778
        self.set_config_push_strict('oFF')
779
        self.assertPushFails(['--strict'])
780
        self.assertPushSucceeds([])
4925.1.1 by Jelmer Vernooij
Print a proper error when attempting to push to a foreign VCS for which
781
782
783
class TestPushForeign(blackbox.ExternalBase):
784
785
    def setUp(self):
786
        super(TestPushForeign, self).setUp()
787
        test_foreign.register_dummy_foreign_for_test(self)
788
789
    def make_dummy_builder(self, relpath):
790
        builder = self.make_branch_builder(
791
            relpath, format=test_foreign.DummyForeignVcsDirFormat())
792
        builder.build_snapshot('revid', None,
793
            [('add', ('', 'TREE_ROOT', 'directory', None)),
794
             ('add', ('foo', 'fooid', 'file', 'bar'))])
795
        return builder
796
797
    def test_no_roundtripping(self):
798
        target_branch = self.make_dummy_builder('dp').get_branch()
799
        source_tree = self.make_branch_and_tree("dc")
800
        output, error = self.run_bzr("push -d dc dp", retcode=3)
801
        self.assertEquals("", output)
802
        self.assertEquals(error, "bzr: ERROR: It is not possible to losslessly"
803
            " push to dummy. You may want to use dpush instead.\n")