1
# Copyright (C) 2005, 2007 Canonical Ltd
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.
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.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""Black-box tests for bzr push."""
26
from bzrlib.branch import Branch
27
from bzrlib.bzrdir import BzrDirMetaFormat1
28
from bzrlib.osutils import abspath
29
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
30
from bzrlib.tests.blackbox import ExternalBase
31
from bzrlib.uncommit import uncommit
32
from bzrlib.urlutils import local_path_from_url
33
from bzrlib.workingtree import WorkingTree
36
class TestPush(ExternalBase):
38
def test_push_remember(self):
39
"""Push changes from one branch to another and test push location."""
40
transport = self.get_transport()
41
tree_a = self.make_branch_and_tree('branch_a')
42
branch_a = tree_a.branch
43
self.build_tree(['branch_a/a'])
45
tree_a.commit('commit a')
46
tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
47
branch_b = tree_b.branch
48
tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
49
branch_c = tree_c.branch
50
self.build_tree(['branch_a/b'])
52
tree_a.commit('commit b')
53
self.build_tree(['branch_b/c'])
55
tree_b.commit('commit c')
56
# initial push location must be empty
57
self.assertEqual(None, branch_b.get_push_location())
59
# test push for failure without push location set
61
out = self.run_bzr('push', retcode=3)
62
self.assertEquals(out,
63
('','bzr: ERROR: No push location known or specified.\n'))
65
# test not remembered if cannot actually push
66
self.run_bzr('push ../path/which/doesnt/exist', retcode=3)
67
out = self.run_bzr('push', retcode=3)
69
('', 'bzr: ERROR: No push location known or specified.\n'),
72
# test implicit --remember when no push location set, push fails
73
out = self.run_bzr('push ../branch_b', retcode=3)
74
self.assertEquals(out,
75
('','bzr: ERROR: These branches have diverged. '
76
'Try using "merge" and then "push".\n'))
77
self.assertEquals(abspath(branch_a.get_push_location()),
78
abspath(branch_b.bzrdir.root_transport.base))
80
# test implicit --remember after resolving previous failure
81
uncommit(branch=branch_b, tree=tree_b)
82
transport.delete('branch_b/c')
83
out, err = self.run_bzr('push')
84
path = branch_a.get_push_location()
85
self.assertEquals(out,
86
'Using saved location: %s\n'
87
'Pushed up to revision 2.\n'
88
% local_path_from_url(path))
90
'All changes applied successfully.\n')
91
self.assertEqual(path,
92
branch_b.bzrdir.root_transport.base)
93
# test explicit --remember
94
self.run_bzr('push ../branch_c --remember')
95
self.assertEquals(branch_a.get_push_location(),
96
branch_c.bzrdir.root_transport.base)
98
def test_push_without_tree(self):
99
# bzr push from a branch that does not have a checkout should work.
100
b = self.make_branch('.')
101
out, err = self.run_bzr('push pushed-location')
102
self.assertEqual('', out)
103
self.assertEqual('Created new branch.\n', err)
104
b2 = Branch.open('pushed-location')
105
self.assertEndsWith(b2.base, 'pushed-location/')
107
def test_push_new_branch_revision_count(self):
108
# bzr push of a branch with revisions to a new location
109
# should print the number of revisions equal to the length of the
111
t = self.make_branch_and_tree('tree')
112
self.build_tree(['tree/file'])
116
out, err = self.run_bzr('push pushed-to')
118
self.assertEqual('', out)
119
self.assertEqual('Created new branch.\n', err)
121
def test_push_only_pushes_history(self):
122
# Knit branches should only push the history for the current revision.
123
format = BzrDirMetaFormat1()
124
format.repository_format = RepositoryFormatKnit1()
125
shared_repo = self.make_repository('repo', format=format, shared=True)
126
shared_repo.set_make_working_trees(True)
128
def make_shared_tree(path):
129
shared_repo.bzrdir.root_transport.mkdir(path)
130
shared_repo.bzrdir.create_branch_convenience('repo/' + path)
131
return WorkingTree.open('repo/' + path)
132
tree_a = make_shared_tree('a')
133
self.build_tree(['repo/a/file'])
135
tree_a.commit('commit a-1', rev_id='a-1')
136
f = open('repo/a/file', 'ab')
137
f.write('more stuff\n')
139
tree_a.commit('commit a-2', rev_id='a-2')
141
tree_b = make_shared_tree('b')
142
self.build_tree(['repo/b/file'])
144
tree_b.commit('commit b-1', rev_id='b-1')
146
self.assertTrue(shared_repo.has_revision('a-1'))
147
self.assertTrue(shared_repo.has_revision('a-2'))
148
self.assertTrue(shared_repo.has_revision('b-1'))
150
# Now that we have a repository with shared files, make sure
151
# that things aren't copied out by a 'push'
153
self.run_bzr('push ../../push-b')
154
pushed_tree = WorkingTree.open('../../push-b')
155
pushed_repo = pushed_tree.branch.repository
156
self.assertFalse(pushed_repo.has_revision('a-1'))
157
self.assertFalse(pushed_repo.has_revision('a-2'))
158
self.assertTrue(pushed_repo.has_revision('b-1'))
160
def test_push_funky_id(self):
161
t = self.make_branch_and_tree('tree')
163
self.build_tree(['filename'])
164
t.add('filename', 'funky-chars<>%&;"\'')
165
t.commit('commit filename')
166
self.run_bzr('push ../new-tree')
168
def test_push_dash_d(self):
169
t = self.make_branch_and_tree('from')
170
t.commit(allow_pointless=True,
171
message='first commit')
172
self.run_bzr('push -d from to-one')
173
self.failUnlessExists('to-one')
174
self.run_bzr('push -d %s %s'
175
% tuple(map(urlutils.local_path_to_url, ['from', 'to-two'])))
176
self.failUnlessExists('to-two')
178
def create_simple_tree(self):
179
tree = self.make_branch_and_tree('tree')
180
self.build_tree(['tree/a'])
181
tree.add(['a'], ['a-id'])
182
tree.commit('one', rev_id='r1')
185
def test_push_create_prefix(self):
186
"""'bzr push --create-prefix' will create leading directories."""
187
tree = self.create_simple_tree()
189
self.run_bzr_error(['Parent directory of ../new/tree does not exist'],
192
self.run_bzr('push ../new/tree --create-prefix',
194
new_tree = WorkingTree.open('new/tree')
195
self.assertEqual(tree.last_revision(), new_tree.last_revision())
196
self.failUnlessExists('new/tree/a')
198
def test_push_use_existing(self):
199
"""'bzr push --use-existing-dir' can push into an existing dir.
201
By default, 'bzr push' will not use an existing, non-versioned dir.
203
tree = self.create_simple_tree()
204
self.build_tree(['target/'])
206
self.run_bzr_error(['Target directory ../target already exists',
207
'Supply --use-existing-dir',
209
'push ../target', working_dir='tree')
211
self.run_bzr('push --use-existing-dir ../target',
214
new_tree = WorkingTree.open('target')
215
self.assertEqual(tree.last_revision(), new_tree.last_revision())
216
# The push should have created target/a
217
self.failUnlessExists('target/a')
219
def test_push_onto_repo(self):
220
"""We should be able to 'bzr push' into an existing bzrdir."""
221
tree = self.create_simple_tree()
222
repo = self.make_repository('repo', shared=True)
224
self.run_bzr('push ../repo',
227
# Pushing onto an existing bzrdir will create a repository and
228
# branch as needed, but will only create a working tree if there was
230
self.assertRaises(errors.NoWorkingTree, WorkingTree.open, 'repo')
231
new_branch = Branch.open('repo')
232
self.assertEqual(tree.last_revision(), new_branch.last_revision())
234
def test_push_onto_just_bzrdir(self):
235
"""We don't handle when the target is just a bzrdir.
237
Because you shouldn't be able to create *just* a bzrdir in the wild.
239
# TODO: jam 20070109 Maybe it would be better to create the repository
241
tree = self.create_simple_tree()
242
a_bzrdir = self.make_bzrdir('dir')
244
self.run_bzr_error(['At ../dir you have a valid .bzr control'],