~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_send.py

  • Committer: John Arbash Meinel
  • Date: 2008-07-09 21:42:24 UTC
  • mto: This revision was merged to the branch mainline in revision 3543.
  • Revision ID: john@arbash-meinel.com-20080709214224-r75k87r6a01pfc3h
Restore a real weave merge to 'bzr merge --weave'.

To do so efficiently, we only add the simple LCAs to the final weave
object, unless we run into complexities with the merge graph.
This gives the same effective result as adding all the texts,
with the advantage of not having to extract all of them.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2012, 2016 Canonical Ltd
 
1
# Copyright (C) 2006, 2007 Canonical Ltd
2
2
# Authors: Aaron Bentley
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
13
13
#
14
14
# You should have received a copy of the GNU General Public License
15
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
17
 
 
18
 
 
19
 
from cStringIO import StringIO
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
 
 
19
import os
 
20
import sys
 
21
from StringIO import StringIO
20
22
 
21
23
from bzrlib import (
22
 
    branch,
 
24
    branch as _mod_branch,
23
25
    merge_directive,
24
 
    tests,
25
26
    )
26
 
from bzrlib.controldir import ControlDir
27
27
from bzrlib.bundle import serializer
28
 
from bzrlib.transport import memory
29
 
from bzrlib.tests import (
30
 
    scenarios,
31
 
    )
32
 
from bzrlib.tests.matchers import ContainsNoVfsCalls
33
 
 
34
 
 
35
 
load_tests = scenarios.load_tests_apply_scenarios
36
 
 
37
 
 
38
 
class TestSendMixin(object):
39
 
 
40
 
    _default_command = ['send', '-o-']
41
 
    _default_wd = 'branch'
42
 
 
43
 
    def run_send(self, args, cmd=None, rc=0, wd=None, err_re=None):
44
 
        if cmd is None: cmd = self._default_command
45
 
        if wd is None: wd = self._default_wd
46
 
        if err_re is None: err_re = []
47
 
        return self.run_bzr(cmd + args, retcode=rc,
48
 
                            working_dir=wd,
49
 
                            error_regexes=err_re)
50
 
 
51
 
    def get_MD(self, args, cmd=None, wd='branch'):
52
 
        out = StringIO(self.run_send(args, cmd=cmd, wd=wd)[0])
53
 
        return merge_directive.MergeDirective.from_lines(out)
54
 
 
55
 
    def assertBundleContains(self, revs, args, cmd=None, wd='branch'):
56
 
        md = self.get_MD(args, cmd=cmd, wd=wd)
57
 
        br = serializer.read_bundle(StringIO(md.get_raw_bundle()))
58
 
        self.assertEqual(set(revs), set(r.revision_id for r in br.revisions))
59
 
 
60
 
 
61
 
class TestSend(tests.TestCaseWithTransport, TestSendMixin):
62
 
 
63
 
    def setUp(self):
64
 
        super(TestSend, self).setUp()
65
 
        grandparent_tree = ControlDir.create_standalone_workingtree(
66
 
            'grandparent')
 
28
from bzrlib.bzrdir import BzrDir
 
29
from bzrlib import tests
 
30
 
 
31
 
 
32
def read_bundle(fileobj):
 
33
    md = merge_directive.MergeDirective.from_lines(fileobj.readlines())
 
34
    return serializer.read_bundle(StringIO(md.get_raw_bundle()))
 
35
 
 
36
 
 
37
class TestSend(tests.TestCaseWithTransport):
 
38
 
 
39
    def make_trees(self):
 
40
        grandparent_tree = BzrDir.create_standalone_workingtree('grandparent')
67
41
        self.build_tree_contents([('grandparent/file1', 'grandparent')])
68
42
        grandparent_tree.add('file1')
69
 
        grandparent_tree.commit('initial commit', rev_id='rev1')
70
 
 
 
43
        grandparent_tree.commit('initial commit', rev_id='revision1')
71
44
        parent_bzrdir = grandparent_tree.bzrdir.sprout('parent')
72
45
        parent_tree = parent_bzrdir.open_workingtree()
73
 
        parent_tree.commit('next commit', rev_id='rev2')
74
 
 
 
46
        parent_tree.commit('next commit', rev_id='revision2')
75
47
        branch_tree = parent_tree.bzrdir.sprout('branch').open_workingtree()
76
48
        self.build_tree_contents([('branch/file1', 'branch')])
77
 
        branch_tree.commit('last commit', rev_id='rev3')
78
 
 
79
 
    def assertFormatIs(self, fmt_string, md):
80
 
        self.assertEqual(fmt_string, md.get_raw_bundle().splitlines()[0])
 
49
        branch_tree.commit('last commit', rev_id='revision3')
81
50
 
82
51
    def test_uses_parent(self):
83
52
        """Parent location is used as a basis by default"""
84
 
        errmsg = self.run_send([], rc=3, wd='grandparent')[1]
 
53
        self.make_trees()
 
54
        os.chdir('grandparent')
 
55
        errmsg = self.run_bzr('send -o-', retcode=3)[1]
85
56
        self.assertContainsRe(errmsg, 'No submit branch known or specified')
86
 
        stdout, stderr = self.run_send([])
87
 
        self.assertEqual(stderr.count('Using saved parent location'), 1)
88
 
        self.assertBundleContains(['rev3'], [])
 
57
        os.chdir('../branch')
 
58
        stdout, stderr = self.run_bzr('send -o-')
 
59
        self.assertEqual(stderr.count('Using saved location'), 1)
 
60
        br = read_bundle(StringIO(stdout))
 
61
        self.assertRevisions(br, ['revision3'])
89
62
 
90
63
    def test_bundle(self):
91
64
        """Bundle works like send, except -o is not required"""
92
 
        errmsg = self.run_send([], cmd=['bundle'], rc=3, wd='grandparent')[1]
 
65
        self.make_trees()
 
66
        os.chdir('grandparent')
 
67
        errmsg = self.run_bzr('bundle', retcode=3)[1]
93
68
        self.assertContainsRe(errmsg, 'No submit branch known or specified')
94
 
        stdout, stderr = self.run_send([], cmd=['bundle'])
95
 
        self.assertEqual(stderr.count('Using saved parent location'), 1)
96
 
        self.assertBundleContains(['rev3'], [], cmd=['bundle'])
 
69
        os.chdir('../branch')
 
70
        stdout, stderr = self.run_bzr('bundle')
 
71
        self.assertEqual(stderr.count('Using saved location'), 1)
 
72
        br = read_bundle(StringIO(stdout))
 
73
        self.assertRevisions(br, ['revision3'])
 
74
 
 
75
    def assertRevisions(self, bi, expected):
 
76
        self.assertEqual(set(r.revision_id for r in bi.revisions),
 
77
            set(expected))
97
78
 
98
79
    def test_uses_submit(self):
99
80
        """Submit location can be used and set"""
100
 
        self.assertBundleContains(['rev3'], [])
101
 
        self.assertBundleContains(['rev3', 'rev2'], ['../grandparent'])
 
81
        self.make_trees()
 
82
        os.chdir('branch')
 
83
        br = read_bundle(StringIO(self.run_bzr('send -o-')[0]))
 
84
        self.assertRevisions(br, ['revision3'])
 
85
        br = read_bundle(StringIO(self.run_bzr('send ../grandparent -o-')[0]))
 
86
        self.assertRevisions(br, ['revision3', 'revision2'])
102
87
        # submit location should be auto-remembered
103
 
        self.assertBundleContains(['rev3', 'rev2'], [])
104
 
 
105
 
        self.run_send(['../parent'])
106
 
        # We still point to ../grandparent
107
 
        self.assertBundleContains(['rev3', 'rev2'], [])
108
 
        # Remember parent now
109
 
        self.run_send(['../parent', '--remember'])
110
 
        # Now we point to parent
111
 
        self.assertBundleContains(['rev3'], [])
112
 
 
113
 
        err = self.run_send(['--remember'], rc=3)[1]
114
 
        self.assertContainsRe(err,
 
88
        br = read_bundle(StringIO(self.run_bzr('send -o-')[0]))
 
89
        self.assertRevisions(br, ['revision3', 'revision2'])
 
90
        self.run_bzr('send ../parent -o-')
 
91
        br = read_bundle(StringIO(self.run_bzr('send -o-')[0]))
 
92
        self.assertRevisions(br, ['revision3', 'revision2'])
 
93
        self.run_bzr('send ../parent --remember -o-')
 
94
        br = read_bundle(StringIO(self.run_bzr('send -o-')[0]))
 
95
        self.assertRevisions(br, ['revision3'])
 
96
        err = self.run_bzr('send --remember -o-', retcode=3)[1]
 
97
        self.assertContainsRe(err, 
115
98
                              '--remember requires a branch to be specified.')
116
99
 
117
100
    def test_revision_branch_interaction(self):
118
 
        self.assertBundleContains(['rev3', 'rev2'], ['../grandparent'])
119
 
        self.assertBundleContains(['rev2'], ['../grandparent', '-r-2'])
120
 
        self.assertBundleContains(['rev3', 'rev2'],
121
 
                                  ['../grandparent', '-r-2..-1'])
122
 
        md = self.get_MD(['-r-2..-1'])
123
 
        self.assertEqual('rev2', md.base_revision_id)
124
 
        self.assertEqual('rev3', md.revision_id)
 
101
        self.make_trees()
 
102
        os.chdir('branch')
 
103
        bi = read_bundle(StringIO(self.run_bzr('send ../grandparent -o-')[0]))
 
104
        self.assertRevisions(bi, ['revision3', 'revision2'])
 
105
        out = StringIO(self.run_bzr('send ../grandparent -r -2 -o-')[0])
 
106
        bi = read_bundle(out)
 
107
        self.assertRevisions(bi, ['revision2'])
 
108
        sio = StringIO(self.run_bzr('send -r -2..-1 -o-')[0])
 
109
        md = merge_directive.MergeDirective.from_lines(sio.readlines())
 
110
        self.assertEqual('revision2', md.base_revision_id)
 
111
        self.assertEqual('revision3', md.revision_id)
 
112
        sio.seek(0)
 
113
        bi = read_bundle(sio)
 
114
        self.assertRevisions(bi, ['revision2', 'revision3'])
 
115
        self.run_bzr('send ../grandparent -r -2..-1 -o-')
125
116
 
126
117
    def test_output(self):
127
118
        # check output for consistency
128
119
        # win32 stdout converts LF to CRLF,
129
120
        # which would break patch-based bundles
130
 
        self.assertBundleContains(['rev3'], [])
 
121
        self.make_trees()        
 
122
        os.chdir('branch')
 
123
        stdout = self.run_bzr_subprocess('send -o-')[0]
 
124
        br = read_bundle(StringIO(stdout))
 
125
        self.assertRevisions(br, ['revision3'])
131
126
 
132
127
    def test_no_common_ancestor(self):
133
128
        foo = self.make_branch_and_tree('foo')
134
129
        foo.commit('rev a')
135
130
        bar = self.make_branch_and_tree('bar')
136
131
        bar.commit('rev b')
137
 
        self.run_send(['--from', 'foo', '../bar'], wd='foo')
 
132
        os.chdir('foo')
 
133
        self.run_bzr('send ../bar -o-')
 
134
 
 
135
    def send_directive(self, args):
 
136
        sio = StringIO(self.run_bzr(['send', '-o-'] + args)[0])
 
137
        return merge_directive.MergeDirective.from_lines(sio.readlines())
138
138
 
139
139
    def test_content_options(self):
140
140
        """--no-patch and --no-bundle should work and be independant"""
141
 
        md = self.get_MD([])
142
 
        self.assertIsNot(None, md.bundle)
143
 
        self.assertIsNot(None, md.patch)
144
 
 
145
 
        md = self.get_MD(['--format=0.9'])
146
 
        self.assertIsNot(None, md.bundle)
147
 
        self.assertIsNot(None, md.patch)
148
 
 
149
 
        md = self.get_MD(['--no-patch'])
 
141
        self.make_trees()
 
142
        os.chdir('branch')
 
143
        md = self.send_directive([])
 
144
        self.assertIsNot(None, md.bundle)
 
145
        self.assertIsNot(None, md.patch)
 
146
 
 
147
        md = self.send_directive(['--format=0.9'])
 
148
        self.assertIsNot(None, md.bundle)
 
149
        self.assertIsNot(None, md.patch)
 
150
 
 
151
        md = self.send_directive(['--no-patch'])
150
152
        self.assertIsNot(None, md.bundle)
151
153
        self.assertIs(None, md.patch)
152
154
        self.run_bzr_error(['Format 0.9 does not permit bundle with no patch'],
153
 
                           ['send', '--no-patch', '--format=0.9', '-o-'],
154
 
                           working_dir='branch')
155
 
        md = self.get_MD(['--no-bundle', '.', '.'])
 
155
                      'send --no-patch --format=0.9 -o-')
 
156
 
 
157
        md = self.send_directive(['--no-bundle', '.', '.'])
156
158
        self.assertIs(None, md.bundle)
157
159
        self.assertIsNot(None, md.patch)
158
160
 
159
 
        md = self.get_MD(['--no-bundle', '--format=0.9', '../parent',
 
161
        md = self.send_directive(['--no-bundle', '--format=0.9', '../parent',
160
162
                                  '.'])
161
163
        self.assertIs(None, md.bundle)
162
164
        self.assertIsNot(None, md.patch)
163
165
 
164
 
        md = self.get_MD(['--no-bundle', '--no-patch', '.', '.'])
 
166
        md = self.send_directive(['--no-bundle', '--no-patch', '.', '.'])
165
167
        self.assertIs(None, md.bundle)
166
168
        self.assertIs(None, md.patch)
167
169
 
168
 
        md = self.get_MD(['--no-bundle', '--no-patch', '--format=0.9',
169
 
                          '../parent', '.'])
 
170
        md = self.send_directive(['--no-bundle', '--no-patch', '--format=0.9',
 
171
                                  '../parent', '.'])
170
172
        self.assertIs(None, md.bundle)
171
173
        self.assertIs(None, md.patch)
172
174
 
173
175
    def test_from_option(self):
 
176
        self.make_trees()
174
177
        self.run_bzr('send', retcode=3)
175
 
        md = self.get_MD(['--from', 'branch'])
176
 
        self.assertEqual('rev3', md.revision_id)
177
 
        md = self.get_MD(['-f', 'branch'])
178
 
        self.assertEqual('rev3', md.revision_id)
 
178
        md = self.send_directive(['--from', 'branch'])
 
179
        self.assertEqual('revision3', md.revision_id)
 
180
        md = self.send_directive(['-f', 'branch'])
 
181
        self.assertEqual('revision3', md.revision_id)
179
182
 
180
183
    def test_output_option(self):
 
184
        self.make_trees()
181
185
        stdout = self.run_bzr('send -f branch --output file1')[0]
182
186
        self.assertEqual('', stdout)
183
187
        md_file = open('file1', 'rb')
184
188
        self.addCleanup(md_file.close)
185
 
        self.assertContainsRe(md_file.read(), 'rev3')
 
189
        self.assertContainsRe(md_file.read(), 'revision3')
186
190
        stdout = self.run_bzr('send -f branch --output -')[0]
187
 
        self.assertContainsRe(stdout, 'rev3')
188
 
 
189
 
    def test_note_revisions(self):
190
 
        stderr = self.run_send([])[1]
191
 
        self.assertEndsWith(stderr, '\nBundling 1 revision.\n')
 
191
        self.assertContainsRe(stdout, 'revision3')
192
192
 
193
193
    def test_mailto_option(self):
194
 
        b = branch.Branch.open('branch')
195
 
        b.get_config_stack().set('mail_client', 'editor')
196
 
        self.run_bzr_error(
197
 
            ('No mail-to address \\(--mail-to\\) or output \\(-o\\) specified',
198
 
            ), 'send -f branch')
199
 
        b.get_config_stack().set('mail_client', 'bogus')
200
 
        self.run_send([])
201
 
        self.run_bzr_error(('Bad value "bogus" for option "mail_client"',),
 
194
        self.make_trees()
 
195
        branch = _mod_branch.Branch.open('branch')
 
196
        branch.get_config().set_user_option('mail_client', 'editor')
 
197
        self.run_bzr_error(('No mail-to address specified',), 'send -f branch')
 
198
        branch.get_config().set_user_option('mail_client', 'bogus')
 
199
        self.run_bzr('send -f branch -o-')
 
200
        self.run_bzr_error(('Unknown mail client: bogus',),
202
201
                           'send -f branch --mail-to jrandom@example.org')
203
 
        b.get_config_stack().set('submit_to', 'jrandom@example.org')
204
 
        self.run_bzr_error(('Bad value "bogus" for option "mail_client"',),
 
202
        branch.get_config().set_user_option('submit_to', 'jrandom@example.org')
 
203
        self.run_bzr_error(('Unknown mail client: bogus',),
205
204
                           'send -f branch')
206
205
 
207
206
    def test_mailto_child_option(self):
208
207
        """Make sure that child_submit_to is used."""
209
 
        b = branch.Branch.open('branch')
210
 
        b.get_config_stack().set('mail_client', 'bogus')
211
 
        parent = branch.Branch.open('parent')
212
 
        parent.get_config_stack().set('child_submit_to', 'somebody@example.org')
213
 
        self.run_bzr_error(('Bad value "bogus" for option "mail_client"',),
214
 
                'send -f branch')
 
208
        self.make_trees()
 
209
        branch = _mod_branch.Branch.open('branch')
 
210
        branch.get_config().set_user_option('mail_client', 'bogus')
 
211
        parent = _mod_branch.Branch.open('parent')
 
212
        parent.get_config().set_user_option('child_submit_to', 
 
213
                           'somebody@example.org')
 
214
        self.run_bzr_error(('Unknown mail client: bogus',),
 
215
                           'send -f branch')
215
216
 
216
217
    def test_format(self):
217
 
        md = self.get_MD(['--format=4'])
 
218
        self.make_trees()
 
219
        s = StringIO(self.run_bzr('send -f branch -o- --format=4')[0])
 
220
        md = merge_directive.MergeDirective.from_lines(s.readlines())
218
221
        self.assertIs(merge_directive.MergeDirective2, md.__class__)
219
 
        self.assertFormatIs('# Bazaar revision bundle v4', md)
220
 
 
221
 
        md = self.get_MD(['--format=0.9'])
222
 
        self.assertFormatIs('# Bazaar revision bundle v0.9', md)
223
 
 
224
 
        md = self.get_MD(['--format=0.9'], cmd=['bundle'])
225
 
        self.assertFormatIs('# Bazaar revision bundle v0.9', md)
 
222
        s = StringIO(self.run_bzr('send -f branch -o- --format=0.9')[0])
 
223
        md = merge_directive.MergeDirective.from_lines(s.readlines())
 
224
        self.assertContainsRe(md.get_raw_bundle().splitlines()[0],
 
225
            '# Bazaar revision bundle v0.9')
 
226
        s = StringIO(self.run_bzr('bundle -f branch -o- --format=0.9')[0])
 
227
        md = merge_directive.MergeDirective.from_lines(s.readlines())
 
228
        self.assertContainsRe(md.get_raw_bundle().splitlines()[0],
 
229
            '# Bazaar revision bundle v0.9')
226
230
        self.assertIs(merge_directive.MergeDirective, md.__class__)
227
 
 
228
231
        self.run_bzr_error(['Bad value .* for option .format.'],
229
232
                            'send -f branch -o- --format=0.999')[0]
230
233
 
231
 
    def test_format_child_option(self):
232
 
        br = branch.Branch.open('parent')
233
 
        conf = br.get_config_stack()
234
 
        conf.set('child_submit_format', '4')
235
 
        md = self.get_MD([])
236
 
        self.assertIs(merge_directive.MergeDirective2, md.__class__)
237
 
 
238
 
        conf.set('child_submit_format', '0.9')
239
 
        md = self.get_MD([])
240
 
        self.assertFormatIs('# Bazaar revision bundle v0.9', md)
241
 
 
242
 
        md = self.get_MD([], cmd=['bundle'])
243
 
        self.assertFormatIs('# Bazaar revision bundle v0.9', md)
244
 
        self.assertIs(merge_directive.MergeDirective, md.__class__)
245
 
 
246
 
        conf.set('child_submit_format', '0.999')
247
 
        self.run_bzr_error(["No such send format '0.999'"],
248
 
                            'send -f branch -o-')[0]
249
 
 
250
234
    def test_message_option(self):
 
235
        self.make_trees()
251
236
        self.run_bzr('send', retcode=3)
252
 
        md = self.get_MD([])
 
237
        md = self.send_directive(['--from', 'branch'])
253
238
        self.assertIs(None, md.message)
254
 
        md = self.get_MD(['-m', 'my message'])
 
239
        md = self.send_directive(['--from', 'branch', '-m', 'my message'])
255
240
        self.assertEqual('my message', md.message)
256
241
 
257
242
    def test_omitted_revision(self):
258
 
        md = self.get_MD(['-r-2..'])
259
 
        self.assertEqual('rev2', md.base_revision_id)
260
 
        self.assertEqual('rev3', md.revision_id)
261
 
        md = self.get_MD(['-r..3', '--from', 'branch', 'grandparent'], wd='.')
262
 
        self.assertEqual('rev1', md.base_revision_id)
263
 
        self.assertEqual('rev3', md.revision_id)
 
243
        self.make_trees()
 
244
        md = self.send_directive(['-r-2..', '--from', 'branch'])
 
245
        self.assertEqual('revision2', md.base_revision_id)
 
246
        self.assertEqual('revision3', md.revision_id)
 
247
        md = self.send_directive(['-r..3', '--from', 'branch',
 
248
                                 'grandparent'])
 
249
        self.assertEqual('revision1', md.base_revision_id)
 
250
        self.assertEqual('revision3', md.revision_id)
264
251
 
265
252
    def test_nonexistant_branch(self):
266
 
        self.vfs_transport_factory = memory.MemoryServer
267
 
        location = self.get_url('absentdir/')
 
253
        if sys.platform == "win32":
 
254
            location = "C:/i/do/not/exist/"
 
255
        else:
 
256
            location = "/i/do/not/exist/"
268
257
        out, err = self.run_bzr(["send", "--from", location], retcode=3)
269
258
        self.assertEqual(out, '')
270
259
        self.assertEqual(err, 'bzr: ERROR: Not a branch: "%s".\n' % location)
271
 
 
272
 
 
273
 
class TestSendStrictMixin(TestSendMixin):
274
 
 
275
 
    def make_parent_and_local_branches(self):
276
 
        # Create a 'parent' branch as the base
277
 
        self.parent_tree = ControlDir.create_standalone_workingtree('parent')
278
 
        self.build_tree_contents([('parent/file', 'parent')])
279
 
        self.parent_tree.add('file')
280
 
        self.parent_tree.commit('first commit', rev_id='parent')
281
 
        # Branch 'local' from parent and do a change
282
 
        local_bzrdir = self.parent_tree.bzrdir.sprout('local')
283
 
        self.local_tree = local_bzrdir.open_workingtree()
284
 
        self.build_tree_contents([('local/file', 'local')])
285
 
        self.local_tree.commit('second commit', rev_id='local')
286
 
 
287
 
    _default_command = ['send', '-o-', '../parent']
288
 
    _default_wd = 'local'
289
 
    _default_sent_revs = ['local']
290
 
    _default_errors = ['Working tree ".*/local/" has uncommitted '
291
 
                       'changes \(See bzr status\)\.',]
292
 
    _default_additional_error = 'Use --no-strict to force the send.\n'
293
 
    _default_additional_warning = 'Uncommitted changes will not be sent.'
294
 
 
295
 
    def set_config_send_strict(self, value):
296
 
        br = branch.Branch.open('local')
297
 
        br.get_config_stack().set('send_strict', value)
298
 
 
299
 
    def assertSendFails(self, args):
300
 
        out, err = self.run_send(args, rc=3, err_re=self._default_errors)
301
 
        self.assertContainsRe(err, self._default_additional_error)
302
 
 
303
 
    def assertSendSucceeds(self, args, revs=None, with_warning=False):
304
 
        if with_warning:
305
 
            err_re = self._default_errors
306
 
        else:
307
 
            err_re = []
308
 
        if revs is None:
309
 
            revs = self._default_sent_revs
310
 
        out, err = self.run_send(args, err_re=err_re)
311
 
        if len(revs) == 1:
312
 
            bundling_revs = 'Bundling %d revision.\n'% len(revs)
313
 
        else:
314
 
            bundling_revs = 'Bundling %d revisions.\n' % len(revs)
315
 
        if with_warning:
316
 
            self.assertContainsRe(err, self._default_additional_warning)
317
 
            self.assertEndsWith(err, bundling_revs)
318
 
        else:
319
 
            self.assertEqual(bundling_revs, err)
320
 
        md = merge_directive.MergeDirective.from_lines(StringIO(out))
321
 
        self.assertEqual('parent', md.base_revision_id)
322
 
        br = serializer.read_bundle(StringIO(md.get_raw_bundle()))
323
 
        self.assertEqual(set(revs), set(r.revision_id for r in br.revisions))
324
 
 
325
 
 
326
 
class TestSendStrictWithoutChanges(tests.TestCaseWithTransport,
327
 
                                   TestSendStrictMixin):
328
 
 
329
 
    def setUp(self):
330
 
        super(TestSendStrictWithoutChanges, self).setUp()
331
 
        self.make_parent_and_local_branches()
332
 
 
333
 
    def test_send_without_workingtree(self):
334
 
        ControlDir.open("local").destroy_workingtree()
335
 
        self.assertSendSucceeds([])
336
 
 
337
 
    def test_send_default(self):
338
 
        self.assertSendSucceeds([])
339
 
 
340
 
    def test_send_strict(self):
341
 
        self.assertSendSucceeds(['--strict'])
342
 
 
343
 
    def test_send_no_strict(self):
344
 
        self.assertSendSucceeds(['--no-strict'])
345
 
 
346
 
    def test_send_config_var_strict(self):
347
 
        self.set_config_send_strict('true')
348
 
        self.assertSendSucceeds([])
349
 
 
350
 
    def test_send_config_var_no_strict(self):
351
 
        self.set_config_send_strict('false')
352
 
        self.assertSendSucceeds([])
353
 
 
354
 
 
355
 
class TestSendStrictWithChanges(tests.TestCaseWithTransport,
356
 
                                TestSendStrictMixin):
357
 
 
358
 
    # These are textually the same as test_push.strict_push_change_scenarios,
359
 
    # but since the functions are reimplemented here, the definitions are left
360
 
    # here too.
361
 
    scenarios = [
362
 
        ('uncommitted',
363
 
         dict(_changes_type='_uncommitted_changes')),
364
 
        ('pending_merges',
365
 
         dict(_changes_type='_pending_merges')),
366
 
        ('out-of-sync-trees',
367
 
         dict(_changes_type='_out_of_sync_trees')),
368
 
        ]
369
 
 
370
 
    _changes_type = None # Set by load_tests
371
 
 
372
 
    def setUp(self):
373
 
        super(TestSendStrictWithChanges, self).setUp()
374
 
        # load tests set _changes_types to the name of the method we want to
375
 
        # call now
376
 
        do_changes_func = getattr(self, self._changes_type)
377
 
        do_changes_func()
378
 
 
379
 
    def _uncommitted_changes(self):
380
 
        self.make_parent_and_local_branches()
381
 
        # Make a change without committing it
382
 
        self.build_tree_contents([('local/file', 'modified')])
383
 
 
384
 
    def _pending_merges(self):
385
 
        self.make_parent_and_local_branches()
386
 
        # Create 'other' branch containing a new file
387
 
        other_bzrdir = self.parent_tree.bzrdir.sprout('other')
388
 
        other_tree = other_bzrdir.open_workingtree()
389
 
        self.build_tree_contents([('other/other-file', 'other')])
390
 
        other_tree.add('other-file')
391
 
        other_tree.commit('other commit', rev_id='other')
392
 
        # Merge and revert, leaving a pending merge
393
 
        self.local_tree.merge_from_branch(other_tree.branch)
394
 
        self.local_tree.revert(filenames=['other-file'], backups=False)
395
 
 
396
 
    def _out_of_sync_trees(self):
397
 
        self.make_parent_and_local_branches()
398
 
        self.run_bzr(['checkout', '--lightweight', 'local', 'checkout'])
399
 
        # Make a change and commit it
400
 
        self.build_tree_contents([('local/file', 'modified in local')])
401
 
        self.local_tree.commit('modify file', rev_id='modified-in-local')
402
 
        # Exercise commands from the checkout directory
403
 
        self._default_wd = 'checkout'
404
 
        self._default_errors = ["Working tree is out of date, please run"
405
 
                                " 'bzr update'\.",]
406
 
        self._default_sent_revs = ['modified-in-local', 'local']
407
 
 
408
 
    def test_send_default(self):
409
 
        self.assertSendSucceeds([], with_warning=True)
410
 
 
411
 
    def test_send_with_revision(self):
412
 
        self.assertSendSucceeds(['-r', 'revid:local'], revs=['local'])
413
 
 
414
 
    def test_send_no_strict(self):
415
 
        self.assertSendSucceeds(['--no-strict'])
416
 
 
417
 
    def test_send_strict_with_changes(self):
418
 
        self.assertSendFails(['--strict'])
419
 
 
420
 
    def test_send_respect_config_var_strict(self):
421
 
        self.set_config_send_strict('true')
422
 
        self.assertSendFails([])
423
 
        self.assertSendSucceeds(['--no-strict'])
424
 
 
425
 
    def test_send_bogus_config_var_ignored(self):
426
 
        self.set_config_send_strict("I'm unsure")
427
 
        self.assertSendSucceeds([], with_warning=True)
428
 
 
429
 
    def test_send_no_strict_command_line_override_config(self):
430
 
        self.set_config_send_strict('true')
431
 
        self.assertSendFails([])
432
 
        self.assertSendSucceeds(['--no-strict'])
433
 
 
434
 
    def test_send_strict_command_line_override_config(self):
435
 
        self.set_config_send_strict('false')
436
 
        self.assertSendSucceeds([])
437
 
        self.assertSendFails(['--strict'])
438
 
 
439
 
 
440
 
class TestBundleStrictWithoutChanges(TestSendStrictWithoutChanges):
441
 
 
442
 
    _default_command = ['bundle-revisions', '../parent']
443
 
 
444
 
 
445
 
class TestSmartServerSend(tests.TestCaseWithTransport):
446
 
 
447
 
    def test_send(self):
448
 
        self.setup_smart_server_with_call_log()
449
 
        t = self.make_branch_and_tree('branch')
450
 
        self.build_tree_contents([('branch/foo', 'thecontents')])
451
 
        t.add("foo")
452
 
        t.commit("message")
453
 
        local = t.bzrdir.sprout('local-branch').open_workingtree()
454
 
        self.build_tree_contents([('branch/foo', 'thenewcontents')])
455
 
        local.commit("anothermessage")
456
 
        self.reset_smart_call_log()
457
 
        out, err = self.run_bzr(
458
 
            ['send', '-o', 'x.diff', self.get_url('branch')], working_dir='local-branch')
459
 
        # This figure represent the amount of work to perform this use case. It
460
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
461
 
        # being too low. If rpc_count increases, more network roundtrips have
462
 
        # become necessary for this use case. Please do not adjust this number
463
 
        # upwards without agreement from bzr's network support maintainers.
464
 
        self.assertLength(7, self.hpss_calls)
465
 
        self.assertLength(1, self.hpss_connections)
466
 
        self.assertThat(self.hpss_calls, ContainsNoVfsCalls)