##// END OF EJS Templates
Add ability to send bundles to patchbomb extension
John Goerzen -
r4278:cfe886c1 default
parent child Browse files
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.Utils
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.MIMEText.MIMEText(body)
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