1
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
2
# Authors: Aaron Bentley
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
from cStringIO import StringIO
28
from bzrlib.bundle import serializer
31
def read_bundle(fileobj):
32
md = merge_directive.MergeDirective.from_lines(fileobj.readlines())
33
return serializer.read_bundle(StringIO(md.get_raw_bundle()))
36
class TestSend(tests.TestCaseWithTransport):
39
super(TestSend, self).setUp()
40
grandparent_tree = bzrdir.BzrDir.create_standalone_workingtree(
42
self.build_tree_contents([('grandparent/file1', 'grandparent')])
43
grandparent_tree.add('file1')
44
grandparent_tree.commit('initial commit', rev_id='rev1')
46
parent_bzrdir = grandparent_tree.bzrdir.sprout('parent')
47
parent_tree = parent_bzrdir.open_workingtree()
48
parent_tree.commit('next commit', rev_id='rev2')
50
branch_tree = parent_tree.bzrdir.sprout('branch').open_workingtree()
51
self.build_tree_contents([('branch/file1', 'branch')])
52
branch_tree.commit('last commit', rev_id='rev3')
54
def run_send(self, args, cmd=None, rc=0, wd='branch'):
57
return self.run_bzr(cmd + args, retcode=rc, working_dir=wd)
59
def get_MD(self, args, cmd=None, wd='branch'):
60
out = StringIO(self.run_send(args, cmd=cmd, wd=wd)[0])
61
return merge_directive.MergeDirective.from_lines(out.readlines())
63
def get_bundle(self, args, cmd=None, wd='branch'):
64
md = self.get_MD(args, cmd=cmd, wd=wd)
65
return serializer.read_bundle(StringIO(md.get_raw_bundle()))
67
def assertBundleContains(self, revs, args, cmd=None, wd='branch'):
68
out = self.run_send(args, cmd=cmd, wd=wd)[0]
69
br = read_bundle(StringIO(out))
70
self.assertEqual(set(revs), set(r.revision_id for r in br.revisions))
72
def assertFormatIs(self, fmt_string, md):
73
self.assertEqual(fmt_string, md.get_raw_bundle().splitlines()[0])
75
def test_uses_parent(self):
76
"""Parent location is used as a basis by default"""
77
errmsg = self.run_send([], rc=3, wd='grandparent')[1]
78
self.assertContainsRe(errmsg, 'No submit branch known or specified')
79
stdout, stderr = self.run_send([])
80
self.assertEqual(stderr.count('Using saved parent location'), 1)
81
self.assertBundleContains(['rev3'], [])
83
def test_bundle(self):
84
"""Bundle works like send, except -o is not required"""
85
errmsg = self.run_send([], cmd=['bundle'], rc=3, wd='grandparent')[1]
86
self.assertContainsRe(errmsg, 'No submit branch known or specified')
87
stdout, stderr = self.run_send([], cmd=['bundle'])
88
self.assertEqual(stderr.count('Using saved parent location'), 1)
89
self.assertBundleContains(['rev3'], [], cmd=['bundle'])
91
def test_uses_submit(self):
92
"""Submit location can be used and set"""
93
self.assertBundleContains(['rev3'], [])
94
self.assertBundleContains(['rev3', 'rev2'], ['../grandparent'])
95
# submit location should be auto-remembered
96
self.assertBundleContains(['rev3', 'rev2'], [])
98
self.run_send(['../parent'])
99
# We still point to ../grandparent
100
self.assertBundleContains(['rev3', 'rev2'], [])
101
# Remember parent now
102
self.run_send(['../parent', '--remember'])
103
# Now we point to parent
104
self.assertBundleContains(['rev3'], [])
106
err = self.run_send(['--remember'], rc=3)[1]
107
self.assertContainsRe(err,
108
'--remember requires a branch to be specified.')
110
def test_revision_branch_interaction(self):
111
self.assertBundleContains(['rev3', 'rev2'], ['../grandparent'])
112
self.assertBundleContains(['rev2'], ['../grandparent', '-r-2'])
113
self.assertBundleContains(['rev3', 'rev2'],
114
['../grandparent', '-r-2..-1'])
115
md = self.get_MD(['-r-2..-1'])
116
self.assertEqual('rev2', md.base_revision_id)
117
self.assertEqual('rev3', md.revision_id)
119
def test_output(self):
120
# check output for consistency
121
# win32 stdout converts LF to CRLF,
122
# which would break patch-based bundles
123
self.assertBundleContains(['rev3'], [])
125
def test_no_common_ancestor(self):
126
foo = self.make_branch_and_tree('foo')
128
bar = self.make_branch_and_tree('bar')
130
self.run_send(['--from', 'foo', '../bar'], wd='foo')
132
def test_content_options(self):
133
"""--no-patch and --no-bundle should work and be independant"""
135
self.assertIsNot(None, md.bundle)
136
self.assertIsNot(None, md.patch)
138
md = self.get_MD(['--format=0.9'])
139
self.assertIsNot(None, md.bundle)
140
self.assertIsNot(None, md.patch)
142
md = self.get_MD(['--no-patch'])
143
self.assertIsNot(None, md.bundle)
144
self.assertIs(None, md.patch)
145
self.run_bzr_error(['Format 0.9 does not permit bundle with no patch'],
146
['send', '--no-patch', '--format=0.9', '-o-'],
147
working_dir='branch')
148
md = self.get_MD(['--no-bundle', '.', '.'])
149
self.assertIs(None, md.bundle)
150
self.assertIsNot(None, md.patch)
152
md = self.get_MD(['--no-bundle', '--format=0.9', '../parent',
154
self.assertIs(None, md.bundle)
155
self.assertIsNot(None, md.patch)
157
md = self.get_MD(['--no-bundle', '--no-patch', '.', '.'])
158
self.assertIs(None, md.bundle)
159
self.assertIs(None, md.patch)
161
md = self.get_MD(['--no-bundle', '--no-patch', '--format=0.9',
163
self.assertIs(None, md.bundle)
164
self.assertIs(None, md.patch)
166
def test_from_option(self):
167
self.run_bzr('send', retcode=3)
168
md = self.get_MD(['--from', 'branch'])
169
self.assertEqual('rev3', md.revision_id)
170
md = self.get_MD(['-f', 'branch'])
171
self.assertEqual('rev3', md.revision_id)
173
def test_output_option(self):
174
stdout = self.run_bzr('send -f branch --output file1')[0]
175
self.assertEqual('', stdout)
176
md_file = open('file1', 'rb')
177
self.addCleanup(md_file.close)
178
self.assertContainsRe(md_file.read(), 'rev3')
179
stdout = self.run_bzr('send -f branch --output -')[0]
180
self.assertContainsRe(stdout, 'rev3')
182
def test_note_revisions(self):
183
stderr = self.run_send([])[1]
184
self.assertEndsWith(stderr, '\nBundling 1 revision(s).\n')
186
def test_mailto_option(self):
187
b = branch.Branch.open('branch')
188
b.get_config().set_user_option('mail_client', 'editor')
190
('No mail-to address \\(--mail-to\\) or output \\(-o\\) specified',
192
b.get_config().set_user_option('mail_client', 'bogus')
194
self.run_bzr_error(('Unknown mail client: bogus',),
195
'send -f branch --mail-to jrandom@example.org')
196
b.get_config().set_user_option('submit_to', 'jrandom@example.org')
197
self.run_bzr_error(('Unknown mail client: bogus',),
200
def test_mailto_child_option(self):
201
"""Make sure that child_submit_to is used."""
202
b = branch.Branch.open('branch')
203
b.get_config().set_user_option('mail_client', 'bogus')
204
parent = branch.Branch.open('parent')
205
parent.get_config().set_user_option('child_submit_to',
206
'somebody@example.org')
207
self.run_bzr_error(('Unknown mail client: bogus',),
210
def test_format(self):
211
md = self.get_MD(['--format=4'])
212
self.assertIs(merge_directive.MergeDirective2, md.__class__)
213
self.assertFormatIs('# Bazaar revision bundle v4', md)
215
md = self.get_MD(['--format=0.9'])
216
self.assertFormatIs('# Bazaar revision bundle v0.9', md)
218
md = self.get_MD(['--format=0.9'], cmd=['bundle'])
219
self.assertFormatIs('# Bazaar revision bundle v0.9', md)
220
self.assertIs(merge_directive.MergeDirective, md.__class__)
222
self.run_bzr_error(['Bad value .* for option .format.'],
223
'send -f branch -o- --format=0.999')[0]
225
def test_format_child_option(self):
226
parent_config = branch.Branch.open('parent').get_config()
227
parent_config.set_user_option('child_submit_format', '4')
229
self.assertIs(merge_directive.MergeDirective2, md.__class__)
231
parent_config.set_user_option('child_submit_format', '0.9')
233
self.assertFormatIs('# Bazaar revision bundle v0.9', md)
235
md = self.get_MD([], cmd=['bundle'])
236
self.assertFormatIs('# Bazaar revision bundle v0.9', md)
237
self.assertIs(merge_directive.MergeDirective, md.__class__)
239
parent_config.set_user_option('child_submit_format', '0.999')
240
self.run_bzr_error(["No such send format '0.999'"],
241
'send -f branch -o-')[0]
243
def test_message_option(self):
244
self.run_bzr('send', retcode=3)
246
self.assertIs(None, md.message)
247
md = self.get_MD(['-m', 'my message'])
248
self.assertEqual('my message', md.message)
250
def test_omitted_revision(self):
251
md = self.get_MD(['-r-2..'])
252
self.assertEqual('rev2', md.base_revision_id)
253
self.assertEqual('rev3', md.revision_id)
254
md = self.get_MD(['-r..3', '--from', 'branch', 'grandparent'], wd='.')
255
self.assertEqual('rev1', md.base_revision_id)
256
self.assertEqual('rev3', md.revision_id)
258
def test_nonexistant_branch(self):
259
if sys.platform == "win32":
260
location = "C:/i/do/not/exist/"
262
location = "/i/do/not/exist/"
263
out, err = self.run_bzr(["send", "--from", location], retcode=3)
264
self.assertEqual(out, '')
265
self.assertEqual(err, 'bzr: ERROR: Not a branch: "%s".\n' % location)