Show More
@@ -63,8 +63,9 b'' | |||||
63 | # |
|
63 | # | |
64 | # That should be all. Now your patchbomb is on its way out. |
|
64 | # That should be all. Now your patchbomb is on its way out. | |
65 |
|
65 | |||
66 | import os, errno, socket |
|
66 | import os, errno, socket, tempfile | |
67 |
import email.MIMEMultipart, email.MIMEText, email. |
|
67 | import email.MIMEMultipart, email.MIMEText, email.MIMEBase | |
|
68 | import email.Utils, email.Encoders | |||
68 | from mercurial import cmdutil, commands, hg, mail, ui, patch, util |
|
69 | from mercurial import cmdutil, commands, hg, mail, ui, patch, util | |
69 | from mercurial.i18n import _ |
|
70 | from mercurial.i18n import _ | |
70 | from mercurial.node import * |
|
71 | from mercurial.node import * | |
@@ -184,9 +185,25 b' def patchbomb(ui, repo, *revs, **opts):' | |||||
184 | o = repo.changelog.nodesbetween(o, revs or None)[0] |
|
185 | o = repo.changelog.nodesbetween(o, revs or None)[0] | |
185 | return [str(repo.changelog.rev(r)) for r in o] |
|
186 | return [str(repo.changelog.rev(r)) for r in o] | |
186 |
|
187 | |||
|
188 | def getbundle(dest, revs): | |||
|
189 | tmpdir = tempfile.mkdtemp(prefix='hg-email-bundle-') | |||
|
190 | tmpfn = os.path.join(tmpdir, 'bundle') | |||
|
191 | try: | |||
|
192 | commands.bundle(ui, repo, tmpfn, dest, *revs, **{'force': 0}) | |||
|
193 | return open(tmpfn).read() | |||
|
194 | finally: | |||
|
195 | try: | |||
|
196 | os.unlink(tmpfn) | |||
|
197 | except: | |||
|
198 | pass | |||
|
199 | os.rmdir(tmpdir) | |||
|
200 | ||||
187 | # option handling |
|
201 | # option handling | |
188 | commands.setremoteconfig(ui, opts) |
|
202 | commands.setremoteconfig(ui, opts) | |
189 | if opts.get('outgoing'): |
|
203 | if opts.get('outgoint') and opts.get('bundle'): | |
|
204 | raise util.Abort(_("--outgoing mode always on with --bundle; do not re-specify --outgoing")) | |||
|
205 | ||||
|
206 | if opts.get('outgoing') or opts.get('bundle'): | |||
190 | if len(revs) > 1: |
|
207 | if len(revs) > 1: | |
191 | raise util.Abort(_("too many destinations")) |
|
208 | raise util.Abort(_("too many destinations")) | |
192 | dest = revs and revs[0] or None |
|
209 | dest = revs and revs[0] or None | |
@@ -206,35 +223,6 b' def patchbomb(ui, repo, *revs, **opts):' | |||||
206 | def genmsgid(id): |
|
223 | def genmsgid(id): | |
207 | return '<%s.%s@%s>' % (id[:20], int(start_time[0]), socket.getfqdn()) |
|
224 | return '<%s.%s@%s>' % (id[:20], int(start_time[0]), socket.getfqdn()) | |
208 |
|
225 | |||
209 | patches = [] |
|
|||
210 |
|
||||
211 | class exportee: |
|
|||
212 | def __init__(self, container): |
|
|||
213 | self.lines = [] |
|
|||
214 | self.container = container |
|
|||
215 | self.name = 'email' |
|
|||
216 |
|
||||
217 | def write(self, data): |
|
|||
218 | self.lines.append(data) |
|
|||
219 |
|
||||
220 | def close(self): |
|
|||
221 | self.container.append(''.join(self.lines).split('\n')) |
|
|||
222 | self.lines = [] |
|
|||
223 |
|
||||
224 | commands.export(ui, repo, *revs, **{'output': exportee(patches), |
|
|||
225 | 'switch_parent': False, |
|
|||
226 | 'text': None, |
|
|||
227 | 'git': opts.get('git')}) |
|
|||
228 |
|
||||
229 | jumbo = [] |
|
|||
230 | msgs = [] |
|
|||
231 |
|
||||
232 | ui.write(_('This patch series consists of %d patches.\n\n') % len(patches)) |
|
|||
233 |
|
||||
234 | for p, i in zip(patches, xrange(len(patches))): |
|
|||
235 | jumbo.extend(p) |
|
|||
236 | msgs.append(makepatch(p, i + 1, len(patches))) |
|
|||
237 |
|
||||
238 | sender = (opts['from'] or ui.config('email', 'from') or |
|
226 | sender = (opts['from'] or ui.config('email', 'from') or | |
239 | ui.config('patchbomb', 'from') or |
|
227 | ui.config('patchbomb', 'from') or | |
240 | prompt('From', ui.username())) |
|
228 | prompt('From', ui.username())) | |
@@ -244,6 +232,7 b' def patchbomb(ui, repo, *revs, **opts):' | |||||
244 | ui.config('patchbomb', opt) or |
|
232 | ui.config('patchbomb', opt) or | |
245 | prompt(prpt, default = default)).split(',') |
|
233 | prompt(prpt, default = default)).split(',') | |
246 | return [a.strip() for a in addrs if a.strip()] |
|
234 | return [a.strip() for a in addrs if a.strip()] | |
|
235 | ||||
247 | to = getaddrs('to', 'To') |
|
236 | to = getaddrs('to', 'To') | |
248 | cc = getaddrs('cc', 'Cc', '') |
|
237 | cc = getaddrs('cc', 'Cc', '') | |
249 |
|
238 | |||
@@ -251,28 +240,80 b' def patchbomb(ui, repo, *revs, **opts):' | |||||
251 | ui.config('patchbomb', 'bcc') or '').split(',') |
|
240 | ui.config('patchbomb', 'bcc') or '').split(',') | |
252 | bcc = [a.strip() for a in bcc if a.strip()] |
|
241 | bcc = [a.strip() for a in bcc if a.strip()] | |
253 |
|
242 | |||
254 | if len(patches) > 1: |
|
243 | def getexportmsgs(): | |
255 | tlen = len(str(len(patches))) |
|
244 | patches = [] | |
|
245 | ||||
|
246 | class exportee: | |||
|
247 | def __init__(self, container): | |||
|
248 | self.lines = [] | |||
|
249 | self.container = container | |||
|
250 | self.name = 'email' | |||
|
251 | ||||
|
252 | def write(self, data): | |||
|
253 | self.lines.append(data) | |||
|
254 | ||||
|
255 | def close(self): | |||
|
256 | self.container.append(''.join(self.lines).split('\n')) | |||
|
257 | self.lines = [] | |||
256 |
|
258 | |||
257 | subj = '[PATCH %0*d of %d] %s' % ( |
|
259 | commands.export(ui, repo, *revs, **{'output': exportee(patches), | |
258 | tlen, 0, |
|
260 | 'switch_parent': False, | |
259 | len(patches), |
|
261 | 'text': None, | |
260 | opts['subject'] or |
|
262 | 'git': opts.get('git')}) | |
261 | prompt('Subject:', rest = ' [PATCH %0*d of %d] ' % (tlen, 0, |
|
263 | ||
262 | len(patches)))) |
|
264 | jumbo = [] | |
|
265 | msgs = [] | |||
|
266 | ||||
|
267 | ui.write(_('This patch series consists of %d patches.\n\n') % len(patches)) | |||
|
268 | ||||
|
269 | for p, i in zip(patches, xrange(len(patches))): | |||
|
270 | jumbo.extend(p) | |||
|
271 | msgs.append(makepatch(p, i + 1, len(patches))) | |||
|
272 | ||||
|
273 | if len(patches) > 1: | |||
|
274 | tlen = len(str(len(patches))) | |||
263 |
|
275 | |||
264 | body = '' |
|
276 | subj = '[PATCH %0*d of %d] %s' % ( | |
265 | if opts['diffstat']: |
|
277 | tlen, 0, | |
266 | d = cdiffstat(_('Final summary:\n'), jumbo) |
|
278 | len(patches), | |
267 | if d: body = '\n' + d |
|
279 | opts['subject'] or | |
|
280 | prompt('Subject:', rest = ' [PATCH %0*d of %d] ' % (tlen, 0, | |||
|
281 | len(patches)))) | |||
|
282 | ||||
|
283 | body = '' | |||
|
284 | if opts['diffstat']: | |||
|
285 | d = cdiffstat(_('Final summary:\n'), jumbo) | |||
|
286 | if d: body = '\n' + d | |||
|
287 | ||||
|
288 | ui.write(_('\nWrite the introductory message for the patch series.\n\n')) | |||
|
289 | body = ui.edit(body, sender) | |||
|
290 | ||||
|
291 | msg = email.MIMEText.MIMEText(body) | |||
|
292 | msg['Subject'] = subj | |||
|
293 | ||||
|
294 | msgs.insert(0, msg) | |||
|
295 | return msgs | |||
268 |
|
296 | |||
269 | ui.write(_('\nWrite the introductory message for the patch series.\n\n')) |
|
297 | def getbundlemsgs(bundle): | |
270 | body = ui.edit(body, sender) |
|
298 | subj = opts['subject'] or \ | |
|
299 | prompt('Subject:', default='A bundle for your repository') | |||
|
300 | ui.write(_('\nWrite the introductory message for the bundle.\n\n')) | |||
|
301 | body = ui.edit('', sender) | |||
271 |
|
302 | |||
272 |
msg = email.MIME |
|
303 | msg = email.MIMEMultipart.MIMEMultipart() | |
|
304 | if body: | |||
|
305 | msg.attach(email.MIMEText.MIMEText(body, 'plain')) | |||
|
306 | datapart = email.MIMEBase.MIMEBase('application', 'x-mercurial-bundle') | |||
|
307 | datapart.set_payload(bundle) | |||
|
308 | email.Encoders.encode_base64(datapart) | |||
|
309 | msg.attach(datapart) | |||
273 | msg['Subject'] = subj |
|
310 | msg['Subject'] = subj | |
|
311 | return [msg] | |||
274 |
|
312 | |||
275 | msgs.insert(0, msg) |
|
313 | if opts.get('bundle'): | |
|
314 | msgs = getbundlemsgs(getbundle(dest, revs)) | |||
|
315 | else: | |||
|
316 | msgs = getexportmsgs() | |||
276 |
|
317 | |||
277 | ui.write('\n') |
|
318 | ui.write('\n') | |
278 |
|
319 | |||
@@ -336,6 +377,7 b' cmdtable = {' | |||||
336 | ('n', 'test', None, 'print messages that would be sent'), |
|
377 | ('n', 'test', None, 'print messages that would be sent'), | |
337 | ('m', 'mbox', '', 'write messages to mbox file instead of sending them'), |
|
378 | ('m', 'mbox', '', 'write messages to mbox file instead of sending them'), | |
338 | ('o', 'outgoing', None, _('send changes not found in the target repository')), |
|
379 | ('o', 'outgoing', None, _('send changes not found in the target repository')), | |
|
380 | ('b', 'bundle', None, _('send changes not in target as a binary bundle')), | |||
339 | ('r', 'rev', [], _('a revision to send')), |
|
381 | ('r', 'rev', [], _('a revision to send')), | |
340 | ('s', 'subject', '', 'subject of first message (intro or single patch)'), |
|
382 | ('s', 'subject', '', 'subject of first message (intro or single patch)'), | |
341 | ('t', 'to', [], 'email addresses of recipients')] + commands.remoteopts, |
|
383 | ('t', 'to', [], 'email addresses of recipients')] + commands.remoteopts, |
General Comments 0
You need to be logged in to leave comments.
Login now