1
# Copyright (C) 2005 Canonical Ltd
2
# -*- coding: utf-8 -*-
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
"""Black-box tests for bzr push."""
27
from bzrlib.branch import Branch
28
from bzrlib.bzrdir import BzrDirMetaFormat1
29
from bzrlib.osutils import abspath
30
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
31
from bzrlib.tests.blackbox import ExternalBase
32
from bzrlib.uncommit import uncommit
33
from bzrlib.urlutils import local_path_from_url
34
from bzrlib.workingtree import WorkingTree
37
class TestPush(ExternalBase):
39
def test_push_remember(self):
40
"""Push changes from one branch to another and test push location."""
41
transport = self.get_transport()
42
tree_a = self.make_branch_and_tree('branch_a')
43
branch_a = tree_a.branch
44
self.build_tree(['branch_a/a'])
46
tree_a.commit('commit a')
47
tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
48
branch_b = tree_b.branch
49
tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
50
branch_c = tree_c.branch
51
self.build_tree(['branch_a/b'])
53
tree_a.commit('commit b')
54
self.build_tree(['branch_b/c'])
56
tree_b.commit('commit c')
57
# initial push location must be empty
58
self.assertEqual(None, branch_b.get_push_location())
60
# test push for failure without push location set
62
out = self.runbzr('push', retcode=3)
63
self.assertEquals(out,
64
('','bzr: ERROR: No push location known or specified.\n'))
66
# test not remembered if cannot actually push
67
self.run_bzr('push', '../path/which/doesnt/exist', retcode=3)
68
out = self.run_bzr('push', retcode=3)
70
('', 'bzr: ERROR: No push location known or specified.\n'),
73
# test implicit --remember when no push location set, push fails
74
out = self.run_bzr('push', '../branch_b', retcode=3)
75
self.assertEquals(out,
76
('','bzr: ERROR: These branches have diverged. '
77
'Try using "merge" and then "push".\n'))
78
self.assertEquals(abspath(branch_a.get_push_location()),
79
abspath(branch_b.bzrdir.root_transport.base))
81
# test implicit --remember after resolving previous failure
82
uncommit(branch=branch_b, tree=tree_b)
83
transport.delete('branch_b/c')
84
out = self.run_bzr('push')
85
path = branch_a.get_push_location()
86
self.assertEquals(('Using saved location: %s\n'
87
% (local_path_from_url(path),)
88
, 'All changes applied successfully.\n'
89
'1 revision(s) pushed.\n'), out)
90
self.assertEqual(path,
91
branch_b.bzrdir.root_transport.base)
92
# test explicit --remember
93
self.run_bzr('push', '../branch_c', '--remember')
94
self.assertEquals(branch_a.get_push_location(),
95
branch_c.bzrdir.root_transport.base)
97
def test_push_without_tree(self):
98
# bzr push from a branch that does not have a checkout should work.
99
b = self.make_branch('.')
100
out, err = self.run_bzr('push', 'pushed-location')
101
self.assertEqual('', out)
102
self.assertEqual('0 revision(s) pushed.\n', err)
103
b2 = bzrlib.branch.Branch.open('pushed-location')
104
self.assertEndsWith(b2.base, 'pushed-location/')
106
def test_push_new_branch_revision_count(self):
107
# bzr push of a branch with revisions to a new location
108
# should print the number of revisions equal to the length of the
110
t = self.make_branch_and_tree('tree')
111
self.build_tree(['tree/file'])
115
out, err = self.run_bzr('push', 'pushed-to')
117
self.assertEqual('', out)
118
self.assertEqual('1 revision(s) pushed.\n', err)
120
def test_push_only_pushes_history(self):
121
# Knit branches should only push the history for the current revision.
122
format = BzrDirMetaFormat1()
123
format.repository_format = RepositoryFormatKnit1()
124
shared_repo = self.make_repository('repo', format=format, shared=True)
125
shared_repo.set_make_working_trees(True)
127
def make_shared_tree(path):
128
shared_repo.bzrdir.root_transport.mkdir(path)
129
shared_repo.bzrdir.create_branch_convenience('repo/' + path)
130
return WorkingTree.open('repo/' + path)
131
tree_a = make_shared_tree('a')
132
self.build_tree(['repo/a/file'])
134
tree_a.commit('commit a-1', rev_id='a-1')
135
f = open('repo/a/file', 'ab')
136
f.write('more stuff\n')
138
tree_a.commit('commit a-2', rev_id='a-2')
140
tree_b = make_shared_tree('b')
141
self.build_tree(['repo/b/file'])
143
tree_b.commit('commit b-1', rev_id='b-1')
145
self.assertTrue(shared_repo.has_revision('a-1'))
146
self.assertTrue(shared_repo.has_revision('a-2'))
147
self.assertTrue(shared_repo.has_revision('b-1'))
149
# Now that we have a repository with shared files, make sure
150
# that things aren't copied out by a 'push'
152
self.run_bzr('push', '../../push-b')
153
pushed_tree = WorkingTree.open('../../push-b')
154
pushed_repo = pushed_tree.branch.repository
155
self.assertFalse(pushed_repo.has_revision('a-1'))
156
self.assertFalse(pushed_repo.has_revision('a-2'))
157
self.assertTrue(pushed_repo.has_revision('b-1'))
159
def test_push_funky_id(self):
160
t = self.make_branch_and_tree('tree')
162
self.build_tree(['filename'])
163
t.add('filename', 'funky-chars<>%&;"\'')
164
t.commit('commit filename')
165
self.run_bzr('push', '../new-tree')
167
def create_simple_tree(self):
168
tree = self.make_branch_and_tree('tree')
169
self.build_tree(['tree/a'])
170
tree.add(['a'], ['a-id'])
171
tree.commit('one', rev_id='r1')
174
def test_push_create_prefix(self):
175
"""'bzr push --create-prefix' will create leading directories."""
176
tree = self.create_simple_tree()
178
self.run_bzr_error(['Parent directory of ../new/tree does not exist'],
179
'push', '../new/tree',
181
self.run_bzr('push', '../new/tree', '--create-prefix',
183
new_tree = WorkingTree.open('new/tree')
184
self.assertEqual(tree.last_revision(), new_tree.last_revision())
185
self.failUnlessExists('new/tree/a')
187
def test_push_use_existing(self):
188
"""'bzr push --use-existing-dir' can push into an existing dir.
190
By default, 'bzr push' will not use an existing, non-versioned dir.
192
tree = self.create_simple_tree()
193
self.build_tree(['target/'])
195
self.run_bzr_error(['Target directory ../target already exists',
196
'Supply --use-existing-dir',
197
], 'push', '../target',
200
self.run_bzr('push', '--use-existing-dir', '../target',
203
new_tree = WorkingTree.open('target')
204
self.assertEqual(tree.last_revision(), new_tree.last_revision())
205
# The push should have created target/a
206
self.failUnlessExists('target/a')
208
def test_push_onto_repo(self):
209
"""We should be able to 'bzr push' into an existing bzrdir."""
210
tree = self.create_simple_tree()
211
repo = self.make_repository('repo', shared=True)
213
self.run_bzr('push', '../repo',
216
# Pushing onto an existing bzrdir will create a repository and
217
# branch as needed, but will only create a working tree if there was
219
self.assertRaises(errors.NoWorkingTree, WorkingTree.open, 'repo')
220
new_branch = Branch.open('repo')
221
self.assertEqual(tree.last_revision(), new_branch.last_revision())
223
def test_push_onto_just_bzrdir(self):
224
"""We don't handle when the target is just a bzrdir.
226
Because you shouldn't be able to create *just* a bzrdir in the wild.
228
# TODO: jam 20070109 Maybe it would be better to create the repository
230
tree = self.create_simple_tree()
231
a_bzrdir = self.make_bzrdir('dir')
233
self.run_bzr_error(['At ../dir you have a valid .bzr control'],