##// END OF EJS Templates
templates: move changeset templating bits to cmdutils
Matt Mackall -
r3643:b4ad640a default
parent child Browse files
Show More
@@ -55,7 +55,7 b''
55 55 from mercurial.demandload import *
56 56 from mercurial.i18n import gettext as _
57 57 from mercurial.node import *
58 demandload(globals(), 'mercurial:templater,util os re time')
58 demandload(globals(), 'mercurial:cmdutil,templater,util os re time')
59 59
60 60 MySQLdb = None
61 61
@@ -267,8 +267,8 b' class bugzilla(object):'
267 267
268 268 mapfile = self.ui.config('bugzilla', 'style')
269 269 tmpl = self.ui.config('bugzilla', 'template')
270 sio = templater.stringio()
271 t = templater.changeset_templater(self.ui, self.repo, mapfile, sio)
270 sio = cmdutil.stringio()
271 t = cmdutil.changeset_templater(self.ui, self.repo, mapfile, sio)
272 272 if not mapfile and not tmpl:
273 273 tmpl = _('changeset {node|short} in repo {root} refers '
274 274 'to bug {bug}.\ndetails:\n\t{desc|tabindent}')
@@ -8,7 +8,7 b''
8 8
9 9 from mercurial.i18n import gettext as _
10 10 from mercurial.demandload import demandload
11 demandload(globals(), "os sys sets mercurial:hg,util,commands")
11 demandload(globals(), "os sys sets mercurial:hg,util,commands,cmdutil")
12 12
13 13 versionstr = "0.0.3"
14 14
@@ -169,7 +169,7 b' class bisect(object):'
169 169 if ancestors.pop() != self.badrev:
170 170 raise util.Abort(_("Could not find the first bad revision"))
171 171 self.ui.write(_("The first bad revision is:\n"))
172 displayer = commands.show_changeset(self.ui, self.repo, {})
172 displayer = cmdutil.show_changeset(self.ui, self.repo, {})
173 173 displayer.show(changenode=self.badrev)
174 174 return None
175 175 best_rev = None
@@ -68,7 +68,7 b''
68 68 from mercurial.demandload import *
69 69 from mercurial.i18n import gettext as _
70 70 from mercurial.node import *
71 demandload(globals(), 'mercurial:commands,patch,templater,util,mail')
71 demandload(globals(), 'mercurial:commands,patch,cmdutil,templater,util,mail')
72 72 demandload(globals(), 'email.Parser fnmatch socket time')
73 73
74 74 # template for single changeset can include email headers.
@@ -107,13 +107,13 b' class notifier(object):'
107 107 self.stripcount = int(self.ui.config('notify', 'strip', 0))
108 108 self.root = self.strip(self.repo.root)
109 109 self.domain = self.ui.config('notify', 'domain')
110 self.sio = templater.stringio()
110 self.sio = cmdutil.stringio()
111 111 self.subs = self.subscribers()
112 112
113 113 mapfile = self.ui.config('notify', 'style')
114 114 template = (self.ui.config('notify', hooktype) or
115 115 self.ui.config('notify', 'template'))
116 self.t = templater.changeset_templater(self.ui, self.repo, mapfile,
116 self.t = cmdutil.changeset_templater(self.ui, self.repo, mapfile,
117 117 self.sio)
118 118 if not mapfile and not template:
119 119 template = deftemplates.get(hooktype) or single_template
@@ -237,7 +237,7 b' class notifier(object):'
237 237 maxdiff = int(self.ui.config('notify', 'maxdiff', 300))
238 238 if maxdiff == 0:
239 239 return
240 fp = templater.stringio()
240 fp = cmdutil.stringio()
241 241 prev = self.repo.changelog.parents(node)[0]
242 242 patch.diff(self.repo, prev, ref, fp=fp)
243 243 difflines = fp.getvalue().splitlines(1)
@@ -8,8 +8,8 b''
8 8 from demandload import demandload
9 9 from node import *
10 10 from i18n import gettext as _
11 demandload(globals(), 'mdiff util')
12 11 demandload(globals(), 'os sys')
12 demandload(globals(), 'mdiff util templater cStringIO')
13 13
14 14 revrangesep = ':'
15 15
@@ -195,3 +195,330 b' def addremove(repo, pats=[], opts={}, wl'
195 195 (oldrel, newrel, score * 100))
196 196 if not dry_run:
197 197 repo.copy(old, new, wlock=wlock)
198
199 class changeset_printer(object):
200 '''show changeset information when templating not requested.'''
201
202 def __init__(self, ui, repo):
203 self.ui = ui
204 self.repo = repo
205
206 def show(self, rev=0, changenode=None, brinfo=None, copies=None):
207 '''show a single changeset or file revision'''
208 log = self.repo.changelog
209 if changenode is None:
210 changenode = log.node(rev)
211 elif not rev:
212 rev = log.rev(changenode)
213
214 if self.ui.quiet:
215 self.ui.write("%d:%s\n" % (rev, short(changenode)))
216 return
217
218 changes = log.read(changenode)
219 date = util.datestr(changes[2])
220 extra = changes[5]
221 branch = extra.get("branch")
222
223 hexfunc = self.ui.debugflag and hex or short
224
225 parents = log.parentrevs(rev)
226 if not self.ui.debugflag:
227 if parents[1] == nullrev:
228 if parents[0] >= rev - 1:
229 parents = []
230 else:
231 parents = [parents[0]]
232 parents = [(p, hexfunc(log.node(p))) for p in parents]
233
234 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)))
235
236 if branch:
237 self.ui.write(_("branch: %s\n") % branch)
238 for tag in self.repo.nodetags(changenode):
239 self.ui.write(_("tag: %s\n") % tag)
240 for parent in parents:
241 self.ui.write(_("parent: %d:%s\n") % parent)
242
243 if brinfo and changenode in brinfo:
244 br = brinfo[changenode]
245 self.ui.write(_("branch: %s\n") % " ".join(br))
246
247 if self.ui.debugflag:
248 self.ui.write(_("manifest: %d:%s\n") %
249 (self.repo.manifest.rev(changes[0]), hex(changes[0])))
250 self.ui.write(_("user: %s\n") % changes[1])
251 self.ui.write(_("date: %s\n") % date)
252
253 if self.ui.debugflag:
254 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
255 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
256 files):
257 if value:
258 self.ui.write("%-12s %s\n" % (key, " ".join(value)))
259 elif changes[3] and self.ui.verbose:
260 self.ui.write(_("files: %s\n") % " ".join(changes[3]))
261 if copies and self.ui.verbose:
262 copies = ['%s (%s)' % c for c in copies]
263 self.ui.write(_("copies: %s\n") % ' '.join(copies))
264
265 if extra and self.ui.debugflag:
266 extraitems = extra.items()
267 extraitems.sort()
268 for key, value in extraitems:
269 self.ui.write(_("extra: %s=%s\n")
270 % (key, value.encode('string_escape')))
271
272 description = changes[4].strip()
273 if description:
274 if self.ui.verbose:
275 self.ui.write(_("description:\n"))
276 self.ui.write(description)
277 self.ui.write("\n\n")
278 else:
279 self.ui.write(_("summary: %s\n") %
280 description.splitlines()[0])
281 self.ui.write("\n")
282
283 class changeset_templater(object):
284 '''format changeset information.'''
285
286 def __init__(self, ui, repo, mapfile, dest=None):
287 self.t = templater.templater(mapfile, templater.common_filters,
288 cache={'parent': '{rev}:{node|short} ',
289 'manifest': '{rev}:{node|short}',
290 'filecopy': '{name} ({source})'})
291 self.ui = ui
292 self.dest = dest
293 self.repo = repo
294
295 def use_template(self, t):
296 '''set template string to use'''
297 self.t.cache['changeset'] = t
298
299 def show(self, rev=0, changenode=None, brinfo=None, copies=[], **props):
300 '''show a single changeset or file revision'''
301 log = self.repo.changelog
302 if changenode is None:
303 changenode = log.node(rev)
304 elif not rev:
305 rev = log.rev(changenode)
306
307 changes = log.read(changenode)
308
309 def showlist(name, values, plural=None, **args):
310 '''expand set of values.
311 name is name of key in template map.
312 values is list of strings or dicts.
313 plural is plural of name, if not simply name + 's'.
314
315 expansion works like this, given name 'foo'.
316
317 if values is empty, expand 'no_foos'.
318
319 if 'foo' not in template map, return values as a string,
320 joined by space.
321
322 expand 'start_foos'.
323
324 for each value, expand 'foo'. if 'last_foo' in template
325 map, expand it instead of 'foo' for last key.
326
327 expand 'end_foos'.
328 '''
329 if plural: names = plural
330 else: names = name + 's'
331 if not values:
332 noname = 'no_' + names
333 if noname in self.t:
334 yield self.t(noname, **args)
335 return
336 if name not in self.t:
337 if isinstance(values[0], str):
338 yield ' '.join(values)
339 else:
340 for v in values:
341 yield dict(v, **args)
342 return
343 startname = 'start_' + names
344 if startname in self.t:
345 yield self.t(startname, **args)
346 vargs = args.copy()
347 def one(v, tag=name):
348 try:
349 vargs.update(v)
350 except (AttributeError, ValueError):
351 try:
352 for a, b in v:
353 vargs[a] = b
354 except ValueError:
355 vargs[name] = v
356 return self.t(tag, **vargs)
357 lastname = 'last_' + name
358 if lastname in self.t:
359 last = values.pop()
360 else:
361 last = None
362 for v in values:
363 yield one(v)
364 if last is not None:
365 yield one(last, tag=lastname)
366 endname = 'end_' + names
367 if endname in self.t:
368 yield self.t(endname, **args)
369
370 def showbranches(**args):
371 branch = changes[5].get("branch")
372 if branch:
373 yield showlist('branch', [branch], plural='branches', **args)
374 # add old style branches if requested
375 if brinfo and changenode in brinfo:
376 yield showlist('branch', brinfo[changenode],
377 plural='branches', **args)
378
379 def showparents(**args):
380 parents = [[('rev', log.rev(p)), ('node', hex(p))]
381 for p in log.parents(changenode)
382 if self.ui.debugflag or p != nullid]
383 if (not self.ui.debugflag and len(parents) == 1 and
384 parents[0][0][1] == rev - 1):
385 return
386 return showlist('parent', parents, **args)
387
388 def showtags(**args):
389 return showlist('tag', self.repo.nodetags(changenode), **args)
390
391 def showextras(**args):
392 extras = changes[5].items()
393 extras.sort()
394 for key, value in extras:
395 args = args.copy()
396 args.update(dict(key=key, value=value))
397 yield self.t('extra', **args)
398
399 def showcopies(**args):
400 c = [{'name': x[0], 'source': x[1]} for x in copies]
401 return showlist('file_copy', c, plural='file_copies', **args)
402
403 if self.ui.debugflag:
404 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
405 def showfiles(**args):
406 return showlist('file', files[0], **args)
407 def showadds(**args):
408 return showlist('file_add', files[1], **args)
409 def showdels(**args):
410 return showlist('file_del', files[2], **args)
411 def showmanifest(**args):
412 args = args.copy()
413 args.update(dict(rev=self.repo.manifest.rev(changes[0]),
414 node=hex(changes[0])))
415 return self.t('manifest', **args)
416 else:
417 def showfiles(**args):
418 yield showlist('file', changes[3], **args)
419 showadds = ''
420 showdels = ''
421 showmanifest = ''
422
423 defprops = {
424 'author': changes[1],
425 'branches': showbranches,
426 'date': changes[2],
427 'desc': changes[4],
428 'file_adds': showadds,
429 'file_dels': showdels,
430 'files': showfiles,
431 'file_copies': showcopies,
432 'manifest': showmanifest,
433 'node': hex(changenode),
434 'parents': showparents,
435 'rev': rev,
436 'tags': showtags,
437 'extras': showextras,
438 }
439 props = props.copy()
440 props.update(defprops)
441
442 try:
443 dest = self.dest or self.ui
444 if self.ui.debugflag and 'header_debug' in self.t:
445 key = 'header_debug'
446 elif self.ui.quiet and 'header_quiet' in self.t:
447 key = 'header_quiet'
448 elif self.ui.verbose and 'header_verbose' in self.t:
449 key = 'header_verbose'
450 elif 'header' in self.t:
451 key = 'header'
452 else:
453 key = ''
454 if key:
455 dest.write_header(templater.stringify(self.t(key, **props)))
456 if self.ui.debugflag and 'changeset_debug' in self.t:
457 key = 'changeset_debug'
458 elif self.ui.quiet and 'changeset_quiet' in self.t:
459 key = 'changeset_quiet'
460 elif self.ui.verbose and 'changeset_verbose' in self.t:
461 key = 'changeset_verbose'
462 else:
463 key = 'changeset'
464 dest.write(templater.stringify(self.t(key, **props)))
465 except KeyError, inst:
466 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
467 inst.args[0]))
468 except SyntaxError, inst:
469 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
470
471 class stringio(object):
472 '''wrap cStringIO for use by changeset_templater.'''
473 def __init__(self):
474 self.fp = cStringIO.StringIO()
475
476 def write(self, *args):
477 for a in args:
478 self.fp.write(a)
479
480 write_header = write
481
482 def __getattr__(self, key):
483 return getattr(self.fp, key)
484
485 def show_changeset(ui, repo, opts):
486 """show one changeset using template or regular display.
487
488 Display format will be the first non-empty hit of:
489 1. option 'template'
490 2. option 'style'
491 3. [ui] setting 'logtemplate'
492 4. [ui] setting 'style'
493 If all of these values are either the unset or the empty string,
494 regular display via changeset_printer() is done.
495 """
496 # options
497 tmpl = opts.get('template')
498 mapfile = None
499 if tmpl:
500 tmpl = templater.parsestring(tmpl, quoted=False)
501 else:
502 mapfile = opts.get('style')
503 # ui settings
504 if not mapfile:
505 tmpl = ui.config('ui', 'logtemplate')
506 if tmpl:
507 tmpl = templater.parsestring(tmpl)
508 else:
509 mapfile = ui.config('ui', 'style')
510
511 if tmpl or mapfile:
512 if mapfile:
513 if not os.path.split(mapfile)[0]:
514 mapname = (templater.templatepath('map-cmdline.' + mapfile)
515 or templater.templatepath(mapfile))
516 if mapname: mapfile = mapname
517 try:
518 t = changeset_templater(ui, repo, mapfile)
519 except SyntaxError, inst:
520 raise util.Abort(inst.args[0])
521 if tmpl: t.use_template(tmpl)
522 return t
523 return changeset_printer(ui, repo)
524
@@ -9,7 +9,7 b' from demandload import demandload'
9 9 from node import *
10 10 from i18n import gettext as _
11 11 demandload(globals(), "os re sys signal imp urllib pdb shlex")
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
12 demandload(globals(), "fancyopts ui hg util lock revlog bundlerepo")
13 13 demandload(globals(), "difflib patch tempfile time")
14 14 demandload(globals(), "traceback errno version atexit bz2")
15 15 demandload(globals(), "archival changegroup cmdutil hgweb.server sshserver")
@@ -295,130 +295,6 b' def write_bundle(cg, filename=None, comp'
295 295 if cleanup is not None:
296 296 os.unlink(cleanup)
297 297
298 class changeset_printer(object):
299 '''show changeset information when templating not requested.'''
300
301 def __init__(self, ui, repo):
302 self.ui = ui
303 self.repo = repo
304
305 def show(self, rev=0, changenode=None, brinfo=None, copies=None):
306 '''show a single changeset or file revision'''
307 log = self.repo.changelog
308 if changenode is None:
309 changenode = log.node(rev)
310 elif not rev:
311 rev = log.rev(changenode)
312
313 if self.ui.quiet:
314 self.ui.write("%d:%s\n" % (rev, short(changenode)))
315 return
316
317 changes = log.read(changenode)
318 date = util.datestr(changes[2])
319 extra = changes[5]
320 branch = extra.get("branch")
321
322 hexfunc = self.ui.debugflag and hex or short
323
324 parents = log.parentrevs(rev)
325 if not self.ui.debugflag:
326 if parents[1] == nullrev:
327 if parents[0] >= rev - 1:
328 parents = []
329 else:
330 parents = [parents[0]]
331 parents = [(p, hexfunc(log.node(p))) for p in parents]
332
333 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)))
334
335 if branch:
336 self.ui.write(_("branch: %s\n") % branch)
337 for tag in self.repo.nodetags(changenode):
338 self.ui.write(_("tag: %s\n") % tag)
339 for parent in parents:
340 self.ui.write(_("parent: %d:%s\n") % parent)
341
342 if brinfo and changenode in brinfo:
343 br = brinfo[changenode]
344 self.ui.write(_("branch: %s\n") % " ".join(br))
345
346 if self.ui.debugflag:
347 self.ui.write(_("manifest: %d:%s\n") %
348 (self.repo.manifest.rev(changes[0]), hex(changes[0])))
349 self.ui.write(_("user: %s\n") % changes[1])
350 self.ui.write(_("date: %s\n") % date)
351
352 if self.ui.debugflag:
353 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
354 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
355 files):
356 if value:
357 self.ui.write("%-12s %s\n" % (key, " ".join(value)))
358 elif changes[3] and self.ui.verbose:
359 self.ui.write(_("files: %s\n") % " ".join(changes[3]))
360 if copies and self.ui.verbose:
361 copies = ['%s (%s)' % c for c in copies]
362 self.ui.write(_("copies: %s\n") % ' '.join(copies))
363
364 if extra and self.ui.debugflag:
365 extraitems = extra.items()
366 extraitems.sort()
367 for key, value in extraitems:
368 self.ui.write(_("extra: %s=%s\n")
369 % (key, value.encode('string_escape')))
370
371 description = changes[4].strip()
372 if description:
373 if self.ui.verbose:
374 self.ui.write(_("description:\n"))
375 self.ui.write(description)
376 self.ui.write("\n\n")
377 else:
378 self.ui.write(_("summary: %s\n") %
379 description.splitlines()[0])
380 self.ui.write("\n")
381
382 def show_changeset(ui, repo, opts):
383 """show one changeset using template or regular display.
384
385 Display format will be the first non-empty hit of:
386 1. option 'template'
387 2. option 'style'
388 3. [ui] setting 'logtemplate'
389 4. [ui] setting 'style'
390 If all of these values are either the unset or the empty string,
391 regular display via changeset_printer() is done.
392 """
393 # options
394 tmpl = opts.get('template')
395 mapfile = None
396 if tmpl:
397 tmpl = templater.parsestring(tmpl, quoted=False)
398 else:
399 mapfile = opts.get('style')
400 # ui settings
401 if not mapfile:
402 tmpl = ui.config('ui', 'logtemplate')
403 if tmpl:
404 tmpl = templater.parsestring(tmpl)
405 else:
406 mapfile = ui.config('ui', 'style')
407
408 if tmpl or mapfile:
409 if mapfile:
410 if not os.path.split(mapfile)[0]:
411 mapname = (templater.templatepath('map-cmdline.' + mapfile)
412 or templater.templatepath(mapfile))
413 if mapname: mapfile = mapname
414 try:
415 t = templater.changeset_templater(ui, repo, mapfile)
416 except SyntaxError, inst:
417 raise util.Abort(inst.args[0])
418 if tmpl: t.use_template(tmpl)
419 return t
420 return changeset_printer(ui, repo)
421
422 298 def setremoteconfig(ui, opts):
423 299 "copy remote options to ui tree"
424 300 if opts.get('ssh'):
@@ -1563,7 +1439,7 b' def heads(ui, repo, **opts):'
1563 1439 ui.warn(_("the --branches option is deprecated, "
1564 1440 "please use 'hg branches' instead\n"))
1565 1441 br = repo.branchlookup(heads)
1566 displayer = show_changeset(ui, repo, opts)
1442 displayer = cmdutil.show_changeset(ui, repo, opts)
1567 1443 for n in heads:
1568 1444 displayer.show(changenode=n, brinfo=br)
1569 1445
@@ -1710,7 +1586,7 b' def incoming(ui, repo, source="default",'
1710 1586 o = other.changelog.nodesbetween(incoming, revs)[0]
1711 1587 if opts['newest_first']:
1712 1588 o.reverse()
1713 displayer = show_changeset(ui, other, opts)
1589 displayer = cmdutil.show_changeset(ui, other, opts)
1714 1590 for n in o:
1715 1591 parents = [p for p in other.changelog.parents(n) if p != nullid]
1716 1592 if opts['no_merges'] and len(parents) == 2:
@@ -1879,7 +1755,7 b' def log(ui, repo, *pats, **opts):'
1879 1755 return ncache[fn].get(dcache[1][fn])
1880 1756 return None
1881 1757
1882 displayer = show_changeset(ui, repo, opts)
1758 displayer = cmdutil.show_changeset(ui, repo, opts)
1883 1759 for st, rev, fns in changeiter:
1884 1760 if st == 'window':
1885 1761 du = dui(ui)
@@ -2015,7 +1891,7 b' def outgoing(ui, repo, dest=None, **opts'
2015 1891 o = repo.changelog.nodesbetween(o, revs)[0]
2016 1892 if opts['newest_first']:
2017 1893 o.reverse()
2018 displayer = show_changeset(ui, repo, opts)
1894 displayer = cmdutil.show_changeset(ui, repo, opts)
2019 1895 for n in o:
2020 1896 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2021 1897 if opts['no_merges'] and len(parents) == 2:
@@ -2056,7 +1932,7 b' def parents(ui, repo, file_=None, rev=No'
2056 1932 ui.warn(_("the --branches option is deprecated, "
2057 1933 "please use 'hg branches' instead\n"))
2058 1934 br = repo.branchlookup(p)
2059 displayer = show_changeset(ui, repo, opts)
1935 displayer = cmdutil.show_changeset(ui, repo, opts)
2060 1936 for n in p:
2061 1937 if n != nullid:
2062 1938 displayer.show(changenode=n, brinfo=br)
@@ -2683,7 +2559,7 b' def tip(ui, repo, **opts):'
2683 2559 ui.warn(_("the --branches option is deprecated, "
2684 2560 "please use 'hg branches' instead\n"))
2685 2561 br = repo.branchlookup([n])
2686 show_changeset(ui, repo, opts).show(changenode=n, brinfo=br)
2562 cmdutil.show_changeset(ui, repo, opts).show(changenode=n, brinfo=br)
2687 2563 if opts['patch']:
2688 2564 patch.diff(repo, repo.changelog.parents(n)[0], n)
2689 2565
@@ -2752,7 +2628,8 b' def _lookup(repo, node, branch=None):'
2752 2628 if len(found) > 1:
2753 2629 repo.ui.warn(_("Found multiple heads for %s\n") % branch)
2754 2630 for x in found:
2755 show_changeset(ui, repo, {}).show(changenode=x, brinfo=br)
2631 cmdutil.show_changeset(ui, repo, {}).show(
2632 changenode=x, brinfo=br)
2756 2633 raise util.Abort("")
2757 2634 if len(found) == 1:
2758 2635 node = found[0]
@@ -8,7 +8,7 b''
8 8 from demandload import demandload
9 9 from i18n import gettext as _
10 10 from node import *
11 demandload(globals(), "cStringIO cgi re sys os time urllib util textwrap")
11 demandload(globals(), "cgi re sys os time urllib util textwrap")
12 12
13 13 def parsestring(s, quoted=True):
14 14 '''parse a string using simple c-like syntax.
@@ -290,204 +290,3 b' def templatepath(name=None):'
290 290 if (name and os.path.exists(p)) or os.path.isdir(p):
291 291 return os.path.normpath(p)
292 292
293 class changeset_templater(object):
294 '''format changeset information.'''
295
296 def __init__(self, ui, repo, mapfile, dest=None):
297 self.t = templater(mapfile, common_filters,
298 cache={'parent': '{rev}:{node|short} ',
299 'manifest': '{rev}:{node|short}',
300 'filecopy': '{name} ({source})'})
301 self.ui = ui
302 self.dest = dest
303 self.repo = repo
304
305 def use_template(self, t):
306 '''set template string to use'''
307 self.t.cache['changeset'] = t
308
309 def show(self, rev=0, changenode=None, brinfo=None, copies=[], **props):
310 '''show a single changeset or file revision'''
311 log = self.repo.changelog
312 if changenode is None:
313 changenode = log.node(rev)
314 elif not rev:
315 rev = log.rev(changenode)
316
317 changes = log.read(changenode)
318
319 def showlist(name, values, plural=None, **args):
320 '''expand set of values.
321 name is name of key in template map.
322 values is list of strings or dicts.
323 plural is plural of name, if not simply name + 's'.
324
325 expansion works like this, given name 'foo'.
326
327 if values is empty, expand 'no_foos'.
328
329 if 'foo' not in template map, return values as a string,
330 joined by space.
331
332 expand 'start_foos'.
333
334 for each value, expand 'foo'. if 'last_foo' in template
335 map, expand it instead of 'foo' for last key.
336
337 expand 'end_foos'.
338 '''
339 if plural: names = plural
340 else: names = name + 's'
341 if not values:
342 noname = 'no_' + names
343 if noname in self.t:
344 yield self.t(noname, **args)
345 return
346 if name not in self.t:
347 if isinstance(values[0], str):
348 yield ' '.join(values)
349 else:
350 for v in values:
351 yield dict(v, **args)
352 return
353 startname = 'start_' + names
354 if startname in self.t:
355 yield self.t(startname, **args)
356 vargs = args.copy()
357 def one(v, tag=name):
358 try:
359 vargs.update(v)
360 except (AttributeError, ValueError):
361 try:
362 for a, b in v:
363 vargs[a] = b
364 except ValueError:
365 vargs[name] = v
366 return self.t(tag, **vargs)
367 lastname = 'last_' + name
368 if lastname in self.t:
369 last = values.pop()
370 else:
371 last = None
372 for v in values:
373 yield one(v)
374 if last is not None:
375 yield one(last, tag=lastname)
376 endname = 'end_' + names
377 if endname in self.t:
378 yield self.t(endname, **args)
379
380 def showbranches(**args):
381 branch = changes[5].get("branch")
382 if branch:
383 yield showlist('branch', [branch], plural='branches', **args)
384 # add old style branches if requested
385 if brinfo and changenode in brinfo:
386 yield showlist('branch', brinfo[changenode],
387 plural='branches', **args)
388
389 def showparents(**args):
390 parents = [[('rev', log.rev(p)), ('node', hex(p))]
391 for p in log.parents(changenode)
392 if self.ui.debugflag or p != nullid]
393 if (not self.ui.debugflag and len(parents) == 1 and
394 parents[0][0][1] == rev - 1):
395 return
396 return showlist('parent', parents, **args)
397
398 def showtags(**args):
399 return showlist('tag', self.repo.nodetags(changenode), **args)
400
401 def showextras(**args):
402 extras = changes[5].items()
403 extras.sort()
404 for key, value in extras:
405 args = args.copy()
406 args.update(dict(key=key, value=value))
407 yield self.t('extra', **args)
408
409 def showcopies(**args):
410 c = [{'name': x[0], 'source': x[1]} for x in copies]
411 return showlist('file_copy', c, plural='file_copies', **args)
412
413 if self.ui.debugflag:
414 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
415 def showfiles(**args):
416 return showlist('file', files[0], **args)
417 def showadds(**args):
418 return showlist('file_add', files[1], **args)
419 def showdels(**args):
420 return showlist('file_del', files[2], **args)
421 def showmanifest(**args):
422 args = args.copy()
423 args.update(dict(rev=self.repo.manifest.rev(changes[0]),
424 node=hex(changes[0])))
425 return self.t('manifest', **args)
426 else:
427 def showfiles(**args):
428 yield showlist('file', changes[3], **args)
429 showadds = ''
430 showdels = ''
431 showmanifest = ''
432
433 defprops = {
434 'author': changes[1],
435 'branches': showbranches,
436 'date': changes[2],
437 'desc': changes[4],
438 'file_adds': showadds,
439 'file_dels': showdels,
440 'files': showfiles,
441 'file_copies': showcopies,
442 'manifest': showmanifest,
443 'node': hex(changenode),
444 'parents': showparents,
445 'rev': rev,
446 'tags': showtags,
447 'extras': showextras,
448 }
449 props = props.copy()
450 props.update(defprops)
451
452 try:
453 dest = self.dest or self.ui
454 if self.ui.debugflag and 'header_debug' in self.t:
455 key = 'header_debug'
456 elif self.ui.quiet and 'header_quiet' in self.t:
457 key = 'header_quiet'
458 elif self.ui.verbose and 'header_verbose' in self.t:
459 key = 'header_verbose'
460 elif 'header' in self.t:
461 key = 'header'
462 else:
463 key = ''
464 if key:
465 dest.write_header(stringify(self.t(key, **props)))
466 if self.ui.debugflag and 'changeset_debug' in self.t:
467 key = 'changeset_debug'
468 elif self.ui.quiet and 'changeset_quiet' in self.t:
469 key = 'changeset_quiet'
470 elif self.ui.verbose and 'changeset_verbose' in self.t:
471 key = 'changeset_verbose'
472 else:
473 key = 'changeset'
474 dest.write(stringify(self.t(key, **props)))
475 except KeyError, inst:
476 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
477 inst.args[0]))
478 except SyntaxError, inst:
479 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
480
481 class stringio(object):
482 '''wrap cStringIO for use by changeset_templater.'''
483 def __init__(self):
484 self.fp = cStringIO.StringIO()
485
486 def write(self, *args):
487 for a in args:
488 self.fp.write(a)
489
490 write_header = write
491
492 def __getattr__(self, key):
493 return getattr(self.fp, key)
General Comments 0
You need to be logged in to leave comments. Login now