comparison mercurial/cmdutil.py @ 3645:b984dcb1df71

Refactor log ui buffering and patch display
author Matt Mackall <mpm@selenic.com>
date Mon, 13 Nov 2006 13:26:57 -0600
parents b4ad640a3bcf
children 2801a3efc7c3
comparison
equal deleted inserted replaced
3644:b7547efe78fb 3645:b984dcb1df71
7 7
8 from demandload import demandload 8 from demandload import demandload
9 from node import * 9 from node import *
10 from i18n import gettext as _ 10 from i18n import gettext as _
11 demandload(globals(), 'os sys') 11 demandload(globals(), 'os sys')
12 demandload(globals(), 'mdiff util templater cStringIO') 12 demandload(globals(), 'mdiff util templater cStringIO patch')
13 13
14 revrangesep = ':' 14 revrangesep = ':'
15 15
16 def revpair(ui, repo, revs): 16 def revpair(ui, repo, revs):
17 '''return pair of nodes, given list of revisions. second item can 17 '''return pair of nodes, given list of revisions. second item can
194 '(%d%% similar)\n') % 194 '(%d%% similar)\n') %
195 (oldrel, newrel, score * 100)) 195 (oldrel, newrel, score * 100))
196 if not dry_run: 196 if not dry_run:
197 repo.copy(old, new, wlock=wlock) 197 repo.copy(old, new, wlock=wlock)
198 198
199 class uibuffer(object):
200 # Implement and delegate some ui protocol. Save hunks of
201 # output for later display in the desired order.
202 def __init__(self, ui):
203 self.ui = ui
204 self.hunk = {}
205 self.header = {}
206 self.quiet = ui.quiet
207 self.verbose = ui.verbose
208 self.debugflag = ui.debugflag
209 self.lastheader = None
210 def note(self, *args):
211 if self.verbose:
212 self.write(*args)
213 def status(self, *args):
214 if not self.quiet:
215 self.write(*args)
216 def debug(self, *args):
217 if self.debugflag:
218 self.write(*args)
219 def write(self, *args):
220 self.hunk.setdefault(self.rev, []).extend(args)
221 def write_header(self, *args):
222 self.header.setdefault(self.rev, []).extend(args)
223 def mark(self, rev):
224 self.rev = rev
225 def flush(self, rev):
226 if rev in self.header:
227 h = "".join(self.header[rev])
228 if h != self.lastheader:
229 self.lastheader = h
230 self.ui.write(h)
231 del self.header[rev]
232 if rev in self.hunk:
233 self.ui.write("".join(self.hunk[rev]))
234 del self.hunk[rev]
235 return 1
236 return 0
237
199 class changeset_printer(object): 238 class changeset_printer(object):
200 '''show changeset information when templating not requested.''' 239 '''show changeset information when templating not requested.'''
201 240
202 def __init__(self, ui, repo): 241 def __init__(self, ui, repo, patch, buffered):
203 self.ui = ui 242 self.ui = ui
204 self.repo = repo 243 self.repo = repo
244 self.buffered = buffered
245 self.patch = patch
246 if buffered:
247 self.ui = uibuffer(ui)
248
249 def flush(self, rev):
250 return self.ui.flush(rev)
205 251
206 def show(self, rev=0, changenode=None, brinfo=None, copies=None): 252 def show(self, rev=0, changenode=None, brinfo=None, copies=None):
207 '''show a single changeset or file revision''' 253 '''show a single changeset or file revision'''
254 if self.buffered:
255 self.ui.mark(rev)
208 log = self.repo.changelog 256 log = self.repo.changelog
209 if changenode is None: 257 if changenode is None:
210 changenode = log.node(rev) 258 changenode = log.node(rev)
211 elif not rev: 259 elif not rev:
212 rev = log.rev(changenode) 260 rev = log.rev(changenode)
278 else: 326 else:
279 self.ui.write(_("summary: %s\n") % 327 self.ui.write(_("summary: %s\n") %
280 description.splitlines()[0]) 328 description.splitlines()[0])
281 self.ui.write("\n") 329 self.ui.write("\n")
282 330
283 class changeset_templater(object): 331 self.showpatch(changenode)
332
333 def showpatch(self, node):
334 if self.patch:
335 prev = self.repo.changelog.parents(node)[0]
336 patch.diff(self.repo, prev, node, fp=self.ui)
337 self.ui.write("\n")
338
339 class changeset_templater(changeset_printer):
284 '''format changeset information.''' 340 '''format changeset information.'''
285 341
286 def __init__(self, ui, repo, mapfile, dest=None): 342 def __init__(self, ui, repo, patch, mapfile, buffered):
343 changeset_printer.__init__(self, ui, repo, patch, buffered)
287 self.t = templater.templater(mapfile, templater.common_filters, 344 self.t = templater.templater(mapfile, templater.common_filters,
288 cache={'parent': '{rev}:{node|short} ', 345 cache={'parent': '{rev}:{node|short} ',
289 'manifest': '{rev}:{node|short}', 346 'manifest': '{rev}:{node|short}',
290 'filecopy': '{name} ({source})'}) 347 'filecopy': '{name} ({source})'})
291 self.ui = ui
292 self.dest = dest
293 self.repo = repo
294 348
295 def use_template(self, t): 349 def use_template(self, t):
296 '''set template string to use''' 350 '''set template string to use'''
297 self.t.cache['changeset'] = t 351 self.t.cache['changeset'] = t
298 352
299 def show(self, rev=0, changenode=None, brinfo=None, copies=[], **props): 353 def show(self, rev=0, changenode=None, brinfo=None, copies=[], **props):
300 '''show a single changeset or file revision''' 354 '''show a single changeset or file revision'''
355 if self.buffered:
356 self.ui.mark(rev)
301 log = self.repo.changelog 357 log = self.repo.changelog
302 if changenode is None: 358 if changenode is None:
303 changenode = log.node(rev) 359 changenode = log.node(rev)
304 elif not rev: 360 elif not rev:
305 rev = log.rev(changenode) 361 rev = log.rev(changenode)
438 } 494 }
439 props = props.copy() 495 props = props.copy()
440 props.update(defprops) 496 props.update(defprops)
441 497
442 try: 498 try:
443 dest = self.dest or self.ui
444 if self.ui.debugflag and 'header_debug' in self.t: 499 if self.ui.debugflag and 'header_debug' in self.t:
445 key = 'header_debug' 500 key = 'header_debug'
446 elif self.ui.quiet and 'header_quiet' in self.t: 501 elif self.ui.quiet and 'header_quiet' in self.t:
447 key = 'header_quiet' 502 key = 'header_quiet'
448 elif self.ui.verbose and 'header_verbose' in self.t: 503 elif self.ui.verbose and 'header_verbose' in self.t:
450 elif 'header' in self.t: 505 elif 'header' in self.t:
451 key = 'header' 506 key = 'header'
452 else: 507 else:
453 key = '' 508 key = ''
454 if key: 509 if key:
455 dest.write_header(templater.stringify(self.t(key, **props))) 510 h = templater.stringify(self.t(key, **props))
511 if self.buffered:
512 self.ui.write_header(h)
513 else:
514 self.ui.write(h)
456 if self.ui.debugflag and 'changeset_debug' in self.t: 515 if self.ui.debugflag and 'changeset_debug' in self.t:
457 key = 'changeset_debug' 516 key = 'changeset_debug'
458 elif self.ui.quiet and 'changeset_quiet' in self.t: 517 elif self.ui.quiet and 'changeset_quiet' in self.t:
459 key = 'changeset_quiet' 518 key = 'changeset_quiet'
460 elif self.ui.verbose and 'changeset_verbose' in self.t: 519 elif self.ui.verbose and 'changeset_verbose' in self.t:
461 key = 'changeset_verbose' 520 key = 'changeset_verbose'
462 else: 521 else:
463 key = 'changeset' 522 key = 'changeset'
464 dest.write(templater.stringify(self.t(key, **props))) 523 self.ui.write(templater.stringify(self.t(key, **props)))
524 self.showpatch(changenode)
465 except KeyError, inst: 525 except KeyError, inst:
466 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile, 526 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
467 inst.args[0])) 527 inst.args[0]))
468 except SyntaxError, inst: 528 except SyntaxError, inst:
469 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0])) 529 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
480 write_header = write 540 write_header = write
481 541
482 def __getattr__(self, key): 542 def __getattr__(self, key):
483 return getattr(self.fp, key) 543 return getattr(self.fp, key)
484 544
485 def show_changeset(ui, repo, opts): 545 def show_changeset(ui, repo, opts, buffered=False):
486 """show one changeset using template or regular display. 546 """show one changeset using template or regular display.
487 547
488 Display format will be the first non-empty hit of: 548 Display format will be the first non-empty hit of:
489 1. option 'template' 549 1. option 'template'
490 2. option 'style' 550 2. option 'style'
492 4. [ui] setting 'style' 552 4. [ui] setting 'style'
493 If all of these values are either the unset or the empty string, 553 If all of these values are either the unset or the empty string,
494 regular display via changeset_printer() is done. 554 regular display via changeset_printer() is done.
495 """ 555 """
496 # options 556 # options
557 patch = opts.get('patch')
497 tmpl = opts.get('template') 558 tmpl = opts.get('template')
498 mapfile = None 559 mapfile = None
499 if tmpl: 560 if tmpl:
500 tmpl = templater.parsestring(tmpl, quoted=False) 561 tmpl = templater.parsestring(tmpl, quoted=False)
501 else: 562 else:
513 if not os.path.split(mapfile)[0]: 574 if not os.path.split(mapfile)[0]:
514 mapname = (templater.templatepath('map-cmdline.' + mapfile) 575 mapname = (templater.templatepath('map-cmdline.' + mapfile)
515 or templater.templatepath(mapfile)) 576 or templater.templatepath(mapfile))
516 if mapname: mapfile = mapname 577 if mapname: mapfile = mapname
517 try: 578 try:
518 t = changeset_templater(ui, repo, mapfile) 579 t = changeset_templater(ui, repo, patch, mapfile, buffered)
519 except SyntaxError, inst: 580 except SyntaxError, inst:
520 raise util.Abort(inst.args[0]) 581 raise util.Abort(inst.args[0])
521 if tmpl: t.use_template(tmpl) 582 if tmpl: t.use_template(tmpl)
522 return t 583 return t
523 return changeset_printer(ui, repo) 584 return changeset_printer(ui, repo, patch, buffered)
524 585