comparison mercurial/logcmdutil.py @ 37772:814151cd8c4a

logcmdutil: rewrite jsonchangeset printer to be backed by jsonformatter This is a bit slower than the original implementation, but I don't think that would actually matter. It's still faster than full templating. $ hg log -Tjson -r0:5000 --time > /dev/null (orig) time: real 1.550 secs (user 1.500+0.000 sys 0.040+0.000) (new) time: real 1.810 secs (user 1.740+0.000 sys 0.070+0.000) cf. $ hg log -Tdefault -r0:5000 --time > /dev/null time: real 4.980 secs (user 4.850+0.000 sys 0.130+0.000) $ hg log -r0:5000 --time > /dev/null time: real 2.340 secs (user 2.220+0.000 sys 0.100+0.000) $ hg log -r0:5000 -q --time > /dev/null time: real 0.750 secs (user 0.670+0.000 sys 0.070+0.000) The test output changes because keys are sorted alphabetically.
author Yuya Nishihara <yuya@tcha.org>
date Fri, 13 Apr 2018 22:47:14 +0900
parents 8c48a3c088a7
children 0f084741cd66
comparison
equal deleted inserted replaced
37771:8c48a3c088a7 37772:814151cd8c4a
10 import itertools 10 import itertools
11 import os 11 import os
12 12
13 from .i18n import _ 13 from .i18n import _
14 from .node import ( 14 from .node import (
15 hex,
16 nullid, 15 nullid,
17 ) 16 )
18 17
19 from . import ( 18 from . import (
20 dagop, 19 dagop,
21 encoding,
22 error, 20 error,
23 formatter, 21 formatter,
24 graphmod, 22 graphmod,
25 match as matchmod, 23 match as matchmod,
26 mdiff, 24 mdiff,
315 class jsonchangeset(changesetprinter): 313 class jsonchangeset(changesetprinter):
316 '''format changeset information.''' 314 '''format changeset information.'''
317 315
318 def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False): 316 def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False):
319 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered) 317 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
320 self._first = True 318 self._fm = formatter.jsonformatter(ui, ui, 'log', {})
321 319
322 def close(self): 320 def close(self):
323 if not self._first: 321 self._fm.end()
324 self.ui.write("\n]\n")
325 else:
326 self.ui.write("[]\n")
327 322
328 def _show(self, ctx, copies, props): 323 def _show(self, ctx, copies, props):
329 '''show a single changeset or file revision''' 324 '''show a single changeset or file revision'''
325 fm = self._fm
326 fm.startitem()
327
328 # TODO: maybe this should be wdirrev/wdirnode?
330 rev = ctx.rev() 329 rev = ctx.rev()
331 if rev is None: 330 if rev is None:
332 jrev = jnode = 'null' 331 hexnode = None
333 else: 332 else:
334 jrev = '%d' % rev 333 hexnode = fm.hexfunc(ctx.node())
335 jnode = '"%s"' % hex(ctx.node()) 334 fm.data(rev=rev,
336 j = encoding.jsonescape 335 node=hexnode)
337
338 if self._first:
339 self.ui.write("[\n {")
340 self._first = False
341 else:
342 self.ui.write(",\n {")
343 336
344 if self.ui.quiet: 337 if self.ui.quiet:
345 self.ui.write(('\n "rev": %s') % jrev)
346 self.ui.write((',\n "node": %s') % jnode)
347 self.ui.write('\n }')
348 return 338 return
349 339
350 self.ui.write(('\n "rev": %s') % jrev) 340 fm.data(branch=ctx.branch(),
351 self.ui.write((',\n "node": %s') % jnode) 341 phase=ctx.phasestr(),
352 self.ui.write((',\n "branch": "%s"') % j(ctx.branch())) 342 user=ctx.user(),
353 self.ui.write((',\n "phase": "%s"') % ctx.phasestr()) 343 date=fm.formatdate(ctx.date()),
354 self.ui.write((',\n "user": "%s"') % j(ctx.user())) 344 desc=ctx.description(),
355 self.ui.write((',\n "date": [%d, %d]') % ctx.date()) 345 bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'),
356 self.ui.write((',\n "desc": "%s"') % j(ctx.description())) 346 tags=fm.formatlist(ctx.tags(), name='tag'),
357 347 parents=fm.formatlist([fm.hexfunc(c.node())
358 self.ui.write((',\n "bookmarks": [%s]') % 348 for c in ctx.parents()], name='node'))
359 ", ".join('"%s"' % j(b) for b in ctx.bookmarks()))
360 self.ui.write((',\n "tags": [%s]') %
361 ", ".join('"%s"' % j(t) for t in ctx.tags()))
362 self.ui.write((',\n "parents": [%s]') %
363 ", ".join('"%s"' % c.hex() for c in ctx.parents()))
364 349
365 if self.ui.debugflag: 350 if self.ui.debugflag:
366 if rev is None: 351 if rev is None:
367 jmanifestnode = 'null' 352 hexnode = None
368 else: 353 else:
369 jmanifestnode = '"%s"' % hex(ctx.manifestnode()) 354 hexnode = fm.hexfunc(ctx.manifestnode())
370 self.ui.write((',\n "manifest": %s') % jmanifestnode) 355 fm.data(manifest=hexnode,
371 356 extra=fm.formatdict(ctx.extra()))
372 self.ui.write((',\n "extra": {%s}') %
373 ", ".join('"%s": "%s"' % (j(k), j(v))
374 for k, v in ctx.extra().items()))
375 357
376 files = ctx.p1().status(ctx) 358 files = ctx.p1().status(ctx)
377 self.ui.write((',\n "modified": [%s]') % 359 fm.data(modified=fm.formatlist(files[0], name='file'),
378 ", ".join('"%s"' % j(f) for f in files[0])) 360 added=fm.formatlist(files[1], name='file'),
379 self.ui.write((',\n "added": [%s]') % 361 removed=fm.formatlist(files[2], name='file'))
380 ", ".join('"%s"' % j(f) for f in files[1]))
381 self.ui.write((',\n "removed": [%s]') %
382 ", ".join('"%s"' % j(f) for f in files[2]))
383 362
384 elif self.ui.verbose: 363 elif self.ui.verbose:
385 self.ui.write((',\n "files": [%s]') % 364 fm.data(files=fm.formatlist(ctx.files(), name='file'))
386 ", ".join('"%s"' % j(f) for f in ctx.files()))
387
388 if copies: 365 if copies:
389 self.ui.write((',\n "copies": {%s}') % 366 fm.data(copies=fm.formatdict(copies,
390 ", ".join('"%s": "%s"' % (j(k), j(v)) 367 key='name', value='source'))
391 for k, v in copies))
392 368
393 stat = self.diffopts.get('stat') 369 stat = self.diffopts.get('stat')
394 diff = self.diffopts.get('patch') 370 diff = self.diffopts.get('patch')
395 diffopts = patch.difffeatureopts(self.ui, self.diffopts, git=True) 371 diffopts = patch.difffeatureopts(self.ui, self.diffopts, git=True)
396 if stat: 372 if stat:
397 self.ui.pushbuffer() 373 self.ui.pushbuffer()
398 self._differ.showdiff(self.ui, ctx, diffopts, stat=True) 374 self._differ.showdiff(self.ui, ctx, diffopts, stat=True)
399 self.ui.write((',\n "diffstat": "%s"') 375 fm.data(diffstat=self.ui.popbuffer())
400 % j(self.ui.popbuffer()))
401 if diff: 376 if diff:
402 self.ui.pushbuffer() 377 self.ui.pushbuffer()
403 self._differ.showdiff(self.ui, ctx, diffopts, stat=False) 378 self._differ.showdiff(self.ui, ctx, diffopts, stat=False)
404 self.ui.write((',\n "diff": "%s"') % j(self.ui.popbuffer())) 379 fm.data(diff=self.ui.popbuffer())
405
406 self.ui.write("\n }")
407 380
408 class changesettemplater(changesetprinter): 381 class changesettemplater(changesetprinter):
409 '''format changeset information. 382 '''format changeset information.
410 383
411 Note: there are a variety of convenience functions to build a 384 Note: there are a variety of convenience functions to build a