comparison hgext/patchbomb.py @ 7353:982b55ec80be

patchbomb: make `hg email` reusable for other patch sources Adds two internal options, patches and patchnames, which allow other extensions to email a given set of patches. The pbranch extension needs this to send its patches which are diffs between topic branches.
author Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
date Wed, 12 Nov 2008 14:07:47 +0100
parents 6c336e7dc145
children cad454f295b0
comparison
equal deleted inserted replaced
7352:6c336e7dc145 7353:982b55ec80be
157 elif s is None: 157 elif s is None:
158 ui.warn(_('No diffstat information available.\n')) 158 ui.warn(_('No diffstat information available.\n'))
159 s = '' 159 s = ''
160 return s 160 return s
161 161
162 def makepatch(patch, idx, total): 162 def makepatch(patch, idx, total, patchname=None):
163 desc = [] 163 desc = []
164 node = None 164 node = None
165 body = '' 165 body = ''
166 for line in patch: 166 for line in patch:
167 if line.startswith('#'): 167 if line.startswith('#'):
169 node = line.split()[-1] 169 node = line.split()[-1]
170 continue 170 continue
171 if line.startswith('diff -r') or line.startswith('diff --git'): 171 if line.startswith('diff -r') or line.startswith('diff --git'):
172 break 172 break
173 desc.append(line) 173 desc.append(line)
174 if not node: 174 if not patchname and not node:
175 raise ValueError 175 raise ValueError
176 176
177 if opts.get('attach'): 177 if opts.get('attach'):
178 body = ('\n'.join(desc[1:]).strip() or 178 body = ('\n'.join(desc[1:]).strip() or
179 'Patch subject is complete summary.') 179 'Patch subject is complete summary.')
195 opts.get('test'))) 195 opts.get('test')))
196 p = mail.mimetextpatch('\n'.join(patch), 'x-patch', 196 p = mail.mimetextpatch('\n'.join(patch), 'x-patch',
197 opts.get('test')) 197 opts.get('test'))
198 binnode = bin(node) 198 binnode = bin(node)
199 # if node is mq patch, it will have patch file name as tag 199 # if node is mq patch, it will have patch file name as tag
200 patchname = [t for t in repo.nodetags(binnode) 200 if not patchname:
201 if t.endswith('.patch') or t.endswith('.diff')] 201 patchtags = [t for t in repo.nodetags(binnode)
202 if patchname: 202 if t.endswith('.patch') or t.endswith('.diff')]
203 patchname = patchname[0] 203 if patchtags:
204 elif total > 1: 204 patchname = patchtags[0]
205 patchname = cmdutil.make_filename(repo, '%b-%n.patch', 205 elif total > 1:
206 binnode, idx, total) 206 patchname = cmdutil.make_filename(repo, '%b-%n.patch',
207 else: 207 binnode, idx, total)
208 patchname = cmdutil.make_filename(repo, '%b.patch', binnode) 208 else:
209 patchname = cmdutil.make_filename(repo, '%b.patch', binnode)
209 disposition = 'inline' 210 disposition = 'inline'
210 if opts.get('attach'): 211 if opts.get('attach'):
211 disposition = 'attachment' 212 disposition = 'attachment'
212 p['Content-Disposition'] = disposition + '; filename=' + patchname 213 p['Content-Disposition'] = disposition + '; filename=' + patchname
213 msg.attach(p) 214 msg.attach(p)
254 if not (opts.get('test') or opts.get('mbox')): 255 if not (opts.get('test') or opts.get('mbox')):
255 # really sending 256 # really sending
256 mail.validateconfig(ui) 257 mail.validateconfig(ui)
257 258
258 if not (revs or opts.get('rev') 259 if not (revs or opts.get('rev')
259 or opts.get('outgoing') or opts.get('bundle')): 260 or opts.get('outgoing') or opts.get('bundle')
261 or opts.get('patches')):
260 raise util.Abort(_('specify at least one changeset with -r or -o')) 262 raise util.Abort(_('specify at least one changeset with -r or -o'))
261 263
262 cmdutil.setremoteconfig(ui, opts) 264 cmdutil.setremoteconfig(ui, opts)
263 if opts.get('outgoing') and opts.get('bundle'): 265 if opts.get('outgoing') and opts.get('bundle'):
264 raise util.Abort(_("--outgoing mode always on with --bundle;" 266 raise util.Abort(_("--outgoing mode always on with --bundle;"
296 ui.write(_('\nWrite the introductory message for the ' 298 ui.write(_('\nWrite the introductory message for the '
297 'patch series.\n\n')) 299 'patch series.\n\n'))
298 body = ui.edit(body, sender) 300 body = ui.edit(body, sender)
299 return body 301 return body
300 302
301 def getexportmsgs(): 303 def getpatchmsgs(patches, patchnames=None):
302 patches = []
303 commands.export(ui, repo, *revs, **{'output': exportee(patches),
304 'switch_parent': False,
305 'text': None,
306 'git': opts.get('git')})
307
308 jumbo = [] 304 jumbo = []
309 msgs = [] 305 msgs = []
310 306
311 ui.write(_('This patch series consists of %d patches.\n\n') 307 ui.write(_('This patch series consists of %d patches.\n\n')
312 % len(patches)) 308 % len(patches))
313 309
310 name = None
314 for p, i in zip(patches, xrange(len(patches))): 311 for p, i in zip(patches, xrange(len(patches))):
315 jumbo.extend(p) 312 jumbo.extend(p)
316 msgs.append(makepatch(p, i + 1, len(patches))) 313 if patchnames:
314 name = patchnames[i]
315 msgs.append(makepatch(p, i + 1, len(patches), name))
317 316
318 if len(patches) > 1: 317 if len(patches) > 1:
319 tlen = len(str(len(patches))) 318 tlen = len(str(len(patches)))
320 319
321 subj = '[PATCH %0*d of %d] %s' % ( 320 subj = '[PATCH %0*d of %d] %s' % (
357 356
358 sender = (opts.get('from') or ui.config('email', 'from') or 357 sender = (opts.get('from') or ui.config('email', 'from') or
359 ui.config('patchbomb', 'from') or 358 ui.config('patchbomb', 'from') or
360 prompt('From', ui.username())) 359 prompt('From', ui.username()))
361 360
362 if opts.get('bundle'): 361 patches = opts.get('patches')
362 if patches:
363 msgs = getpatchmsgs(patches, opts.get('patchnames'))
364 elif opts.get('bundle'):
363 msgs = getbundlemsgs(getbundle(dest)) 365 msgs = getbundlemsgs(getbundle(dest))
364 else: 366 else:
365 msgs = getexportmsgs() 367 patches = []
368 commands.export(ui, repo, *revs, **{'output': exportee(patches),
369 'switch_parent': False,
370 'text': None,
371 'git': opts.get('git')})
372 msgs = getpatchmsgs(patches)
366 373
367 def getaddrs(opt, prpt, default = None): 374 def getaddrs(opt, prpt, default = None):
368 addrs = opts.get(opt) or (ui.config('email', opt) or 375 addrs = opts.get(opt) or (ui.config('email', opt) or
369 ui.config('patchbomb', opt) or 376 ui.config('patchbomb', opt) or
370 prompt(prpt, default = default)).split(',') 377 prompt(prpt, default = default)).split(',')