1
# Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27
from bzrlib.commands import (
30
from bzrlib.option import (
36
format_registry = registry.Registry()
39
class cmd_send(Command):
40
"""Mail or create a merge-directive for submitting changes.
42
A merge directive provides many things needed for requesting merges:
44
* A machine-readable description of the merge to perform
46
* An optional patch that is a preview of the changes requested
48
* An optional bundle of revision data, so that the changes can be applied
49
directly from the merge directive, without retrieving data from a
52
If --no-bundle is specified, then public_branch is needed (and must be
53
up-to-date), so that the receiver can perform the merge using the
54
public_branch. The public_branch is always included if known, so that
55
people can check it later.
57
The submit branch defaults to the parent, but can be overridden. Both
58
submit branch and public branch will be remembered if supplied.
60
If a public_branch is known for the submit_branch, that public submit
61
branch is used in the merge instructions. This means that a local mirror
62
can be used as your actual submit branch, once you have set public_branch
65
Mail is sent using your preferred mail program. This should be transparent
66
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
67
If the preferred client can't be found (or used), your editor will be used.
69
To use a specific mail program, set the mail_client configuration option.
70
(For Thunderbird 1.5, this works around some bugs.) Supported values for
71
specific clients are "claws", "evolution", "kmail", "mutt", and
72
"thunderbird"; generic options are "default", "editor", "emacsclient",
73
"mapi", and "xdg-email". Plugins may also add supported clients.
75
If mail is being sent, a to address is required. This can be supplied
76
either on the commandline, by setting the submit_to configuration
77
option in the branch itself or the child_submit_to configuration option
80
Two formats are currently supported: "4" uses revision bundle format 4 and
81
merge directive format 2. It is significantly faster and smaller than
82
older formats. It is compatible with Bazaar 0.19 and later. It is the
83
default. "0.9" uses revision bundle format 0.9 and merge directive
84
format 1. It is compatible with Bazaar 0.12 - 0.18.
86
The merge directives created by bzr send may be applied using bzr merge or
87
bzr pull by specifying a file containing a merge directive as the location.
90
encoding_type = 'exact'
92
_see_also = ['merge', 'pull']
94
takes_args = ['submit_branch?', 'public_branch?']
98
help='Do not include a bundle in the merge directive.'),
99
Option('no-patch', help='Do not include a preview patch in the merge'
102
help='Remember submit and public branch.'),
104
help='Branch to generate the submission from, '
105
'rather than the one containing the working directory.',
108
Option('output', short_name='o',
109
help='Write merge directive to this file; '
112
Option('mail-to', help='Mail the request to this address.',
116
Option('body', help='Body for the email.', type=unicode),
117
RegistryOption('format',
118
help='Use the specified output format.',
119
registry=format_registry)
122
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
123
no_patch=False, revision=None, remember=False, output=None,
124
format=None, mail_to=None, message=None, body=None, **kwargs):
125
return self._run(submit_branch, revision, public_branch, remember,
126
format, no_bundle, no_patch, output,
127
kwargs.get('from', '.'), mail_to, message, body)
129
def _run(self, submit_branch, revision, public_branch, remember, format,
130
no_bundle, no_patch, output, from_, mail_to, message, body):
131
from bzrlib import bzrdir
132
from bzrlib.branch import Branch
133
from bzrlib.revision import NULL_REVISION
134
tree, branch = bzrdir.BzrDir.open_containing_tree_or_branch(from_)[:2]
135
# we may need to write data into branch's repository to calculate
140
config = branch.get_config()
142
mail_to = config.get_user_option('submit_to')
143
mail_client = config.get_mail_client()
144
if (not getattr(mail_client, 'supports_body', False)
145
and body is not None):
146
raise errors.BzrCommandError(
147
'Mail client "%s" does not support specifying body' %
148
mail_client.__class__.__name__)
149
if remember and submit_branch is None:
150
raise errors.BzrCommandError(
151
'--remember requires a branch to be specified.')
152
stored_submit_branch = branch.get_submit_branch()
153
remembered_submit_branch = None
154
if submit_branch is None:
155
submit_branch = stored_submit_branch
156
remembered_submit_branch = "submit"
158
if stored_submit_branch is None or remember:
159
branch.set_submit_branch(submit_branch)
160
if submit_branch is None:
161
submit_branch = branch.get_parent()
162
remembered_submit_branch = "parent"
163
if submit_branch is None:
164
raise errors.BzrCommandError('No submit branch known or'
166
if remembered_submit_branch is not None:
167
trace.note('Using saved %s location "%s" to determine what '
168
'changes to submit.', remembered_submit_branch,
172
submit_config = Branch.open(submit_branch).get_config()
173
mail_to = submit_config.get_user_option("child_submit_to")
175
stored_public_branch = branch.get_public_branch()
176
if public_branch is None:
177
public_branch = stored_public_branch
178
elif stored_public_branch is None or remember:
179
branch.set_public_branch(public_branch)
180
if no_bundle and public_branch is None:
181
raise errors.BzrCommandError('No public branch specified or'
183
base_revision_id = None
185
if revision is not None:
186
if len(revision) > 2:
187
raise errors.BzrCommandError('bzr send takes '
188
'at most two one revision identifiers')
189
revision_id = revision[-1].as_revision_id(branch)
190
if len(revision) == 2:
191
base_revision_id = revision[0].as_revision_id(branch)
192
if revision_id is None:
193
revision_id = branch.last_revision()
194
if revision_id == NULL_REVISION:
195
raise errors.BzrCommandError('No revisions to submit.')
197
# TODO: Query submit branch for its preferred format
198
format = format_registry.get()
199
directive = format(branch, revision_id, submit_branch,
200
public_branch, no_patch, no_bundle, message, base_revision_id)
202
directive.compose_merge_request(mail_client, mail_to, body,
208
outfile = open(output, 'wb')
210
outfile.writelines(directive.to_lines())
212
if outfile is not self.outf:
218
class cmd_bundle_revisions(cmd_send):
220
"""Create a merge-directive for submitting changes.
222
A merge directive provides many things needed for requesting merges:
224
* A machine-readable description of the merge to perform
226
* An optional patch that is a preview of the changes requested
228
* An optional bundle of revision data, so that the changes can be applied
229
directly from the merge directive, without retrieving data from a
232
If --no-bundle is specified, then public_branch is needed (and must be
233
up-to-date), so that the receiver can perform the merge using the
234
public_branch. The public_branch is always included if known, so that
235
people can check it later.
237
The submit branch defaults to the parent, but can be overridden. Both
238
submit branch and public branch will be remembered if supplied.
240
If a public_branch is known for the submit_branch, that public submit
241
branch is used in the merge instructions. This means that a local mirror
242
can be used as your actual submit branch, once you have set public_branch
245
Two formats are currently supported: "4" uses revision bundle format 4 and
246
merge directive format 2. It is significantly faster and smaller than
247
older formats. It is compatible with Bazaar 0.19 and later. It is the
248
default. "0.9" uses revision bundle format 0.9 and merge directive
249
format 1. It is compatible with Bazaar 0.12 - 0.18.
254
help='Do not include a bundle in the merge directive.'),
255
Option('no-patch', help='Do not include a preview patch in the merge'
258
help='Remember submit and public branch.'),
260
help='Branch to generate the submission from, '
261
'rather than the one containing the working directory.',
264
Option('output', short_name='o', help='Write directive to this file.',
267
RegistryOption('format',
268
help='Use the specified output format.',
269
registry=format_registry),
273
_see_also = ['send', 'merge']
277
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
278
no_patch=False, revision=None, remember=False, output=None,
279
format=None, **kwargs):
282
return self._run(submit_branch, revision, public_branch, remember,
283
format, no_bundle, no_patch, output,
284
kwargs.get('from', '.'), None, None, None)
287
def _send_4(branch, revision_id, submit_branch, public_branch,
288
no_patch, no_bundle, message, base_revision_id):
289
return merge_directive.MergeDirective2.from_objects(
290
branch.repository, revision_id, time.time(),
291
osutils.local_time_offset(), submit_branch,
292
public_branch=public_branch, include_patch=not no_patch,
293
include_bundle=not no_bundle, message=message,
294
base_revision_id=base_revision_id)
297
def _send_0_9(branch, revision_id, submit_branch, public_branch,
298
no_patch, no_bundle, message, base_revision_id):
301
patch_type = 'bundle'
303
raise errors.BzrCommandError('Format 0.9 does not'
304
' permit bundle with no patch')
310
return merge_directive.MergeDirective.from_objects(
311
branch.repository, revision_id, time.time(),
312
osutils.local_time_offset(), submit_branch,
313
public_branch=public_branch, patch_type=patch_type,
317
format_registry.register('4',
318
_send_4, 'Bundle format 4, Merge Directive 2 (default)')
319
format_registry.register('0.9',
320
_send_0_9, 'Bundle format 0.9, Merge Directive 1')
321
format_registry.default_key = '4'