Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/logcmdutil.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | 90b9a7e06c2c |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
42 ) | 42 ) |
43 | 43 |
44 | 44 |
45 def getlimit(opts): | 45 def getlimit(opts): |
46 """get the log limit according to option -l/--limit""" | 46 """get the log limit according to option -l/--limit""" |
47 limit = opts.get('limit') | 47 limit = opts.get(b'limit') |
48 if limit: | 48 if limit: |
49 try: | 49 try: |
50 limit = int(limit) | 50 limit = int(limit) |
51 except ValueError: | 51 except ValueError: |
52 raise error.Abort(_('limit must be a positive integer')) | 52 raise error.Abort(_(b'limit must be a positive integer')) |
53 if limit <= 0: | 53 if limit <= 0: |
54 raise error.Abort(_('limit must be positive')) | 54 raise error.Abort(_(b'limit must be positive')) |
55 else: | 55 else: |
56 limit = None | 56 limit = None |
57 return limit | 57 return limit |
58 | 58 |
59 | 59 |
66 match, | 66 match, |
67 changes=None, | 67 changes=None, |
68 stat=False, | 68 stat=False, |
69 fp=None, | 69 fp=None, |
70 graphwidth=0, | 70 graphwidth=0, |
71 prefix='', | 71 prefix=b'', |
72 root='', | 72 root=b'', |
73 listsubrepos=False, | 73 listsubrepos=False, |
74 hunksfilterfn=None, | 74 hunksfilterfn=None, |
75 ): | 75 ): |
76 '''show diff or diffstat.''' | 76 '''show diff or diffstat.''' |
77 ctx1 = repo[node1] | 77 ctx1 = repo[node1] |
78 ctx2 = repo[node2] | 78 ctx2 = repo[node2] |
79 if root: | 79 if root: |
80 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root) | 80 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root) |
81 else: | 81 else: |
82 relroot = '' | 82 relroot = b'' |
83 copysourcematch = None | 83 copysourcematch = None |
84 | 84 |
85 def compose(f, g): | 85 def compose(f, g): |
86 return lambda x: f(g(x)) | 86 return lambda x: f(g(x)) |
87 | 87 |
88 def pathfn(f): | 88 def pathfn(f): |
89 return posixpath.join(prefix, f) | 89 return posixpath.join(prefix, f) |
90 | 90 |
91 if relroot != '': | 91 if relroot != b'': |
92 # XXX relative roots currently don't work if the root is within a | 92 # XXX relative roots currently don't work if the root is within a |
93 # subrepo | 93 # subrepo |
94 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) | 94 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) |
95 uirelroot = uipathfn(pathfn(relroot)) | 95 uirelroot = uipathfn(pathfn(relroot)) |
96 relroot += '/' | 96 relroot += b'/' |
97 for matchroot in match.files(): | 97 for matchroot in match.files(): |
98 if not matchroot.startswith(relroot): | 98 if not matchroot.startswith(relroot): |
99 ui.warn( | 99 ui.warn( |
100 _('warning: %s not inside relative root %s\n') | 100 _(b'warning: %s not inside relative root %s\n') |
101 % (uipathfn(pathfn(matchroot)), uirelroot) | 101 % (uipathfn(pathfn(matchroot)), uirelroot) |
102 ) | 102 ) |
103 | 103 |
104 relrootmatch = scmutil.match(ctx2, pats=[relroot], default='path') | 104 relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b'path') |
105 match = matchmod.intersectmatchers(match, relrootmatch) | 105 match = matchmod.intersectmatchers(match, relrootmatch) |
106 copysourcematch = relrootmatch | 106 copysourcematch = relrootmatch |
107 | 107 |
108 checkroot = repo.ui.configbool( | 108 checkroot = repo.ui.configbool( |
109 'devel', 'all-warnings' | 109 b'devel', b'all-warnings' |
110 ) or repo.ui.configbool('devel', 'check-relroot') | 110 ) or repo.ui.configbool(b'devel', b'check-relroot') |
111 | 111 |
112 def relrootpathfn(f): | 112 def relrootpathfn(f): |
113 if checkroot and not f.startswith(relroot): | 113 if checkroot and not f.startswith(relroot): |
114 raise AssertionError( | 114 raise AssertionError( |
115 "file %s doesn't start with relroot %s" % (f, relroot) | 115 b"file %s doesn't start with relroot %s" % (f, relroot) |
116 ) | 116 ) |
117 return f[len(relroot) :] | 117 return f[len(relroot) :] |
118 | 118 |
119 pathfn = compose(relrootpathfn, pathfn) | 119 pathfn = compose(relrootpathfn, pathfn) |
120 | 120 |
212 hunksfilterfn=self._makehunksfilter(ctx), | 212 hunksfilterfn=self._makehunksfilter(ctx), |
213 ) | 213 ) |
214 | 214 |
215 | 215 |
216 def changesetlabels(ctx): | 216 def changesetlabels(ctx): |
217 labels = ['log.changeset', 'changeset.%s' % ctx.phasestr()] | 217 labels = [b'log.changeset', b'changeset.%s' % ctx.phasestr()] |
218 if ctx.obsolete(): | 218 if ctx.obsolete(): |
219 labels.append('changeset.obsolete') | 219 labels.append(b'changeset.obsolete') |
220 if ctx.isunstable(): | 220 if ctx.isunstable(): |
221 labels.append('changeset.unstable') | 221 labels.append(b'changeset.unstable') |
222 for instability in ctx.instabilities(): | 222 for instability in ctx.instabilities(): |
223 labels.append('instability.%s' % instability) | 223 labels.append(b'instability.%s' % instability) |
224 return ' '.join(labels) | 224 return b' '.join(labels) |
225 | 225 |
226 | 226 |
227 class changesetprinter(object): | 227 class changesetprinter(object): |
228 '''show changeset information when templating not requested.''' | 228 '''show changeset information when templating not requested.''' |
229 | 229 |
231 self.ui = ui | 231 self.ui = ui |
232 self.repo = repo | 232 self.repo = repo |
233 self.buffered = buffered | 233 self.buffered = buffered |
234 self._differ = differ or changesetdiffer() | 234 self._differ = differ or changesetdiffer() |
235 self._diffopts = patch.diffallopts(ui, diffopts) | 235 self._diffopts = patch.diffallopts(ui, diffopts) |
236 self._includestat = diffopts and diffopts.get('stat') | 236 self._includestat = diffopts and diffopts.get(b'stat') |
237 self._includediff = diffopts and diffopts.get('patch') | 237 self._includediff = diffopts and diffopts.get(b'patch') |
238 self.header = {} | 238 self.header = {} |
239 self.hunk = {} | 239 self.hunk = {} |
240 self.lastheader = None | 240 self.lastheader = None |
241 self.footer = None | 241 self.footer = None |
242 self._columns = templatekw.getlogcolumns() | 242 self._columns = templatekw.getlogcolumns() |
267 self._show(ctx, copies, props) | 267 self._show(ctx, copies, props) |
268 | 268 |
269 def _show(self, ctx, copies, props): | 269 def _show(self, ctx, copies, props): |
270 '''show a single changeset or file revision''' | 270 '''show a single changeset or file revision''' |
271 changenode = ctx.node() | 271 changenode = ctx.node() |
272 graphwidth = props.get('graphwidth', 0) | 272 graphwidth = props.get(b'graphwidth', 0) |
273 | 273 |
274 if self.ui.quiet: | 274 if self.ui.quiet: |
275 self.ui.write( | 275 self.ui.write( |
276 "%s\n" % scmutil.formatchangeid(ctx), label='log.node' | 276 b"%s\n" % scmutil.formatchangeid(ctx), label=b'log.node' |
277 ) | 277 ) |
278 return | 278 return |
279 | 279 |
280 columns = self._columns | 280 columns = self._columns |
281 self.ui.write( | 281 self.ui.write( |
282 columns['changeset'] % scmutil.formatchangeid(ctx), | 282 columns[b'changeset'] % scmutil.formatchangeid(ctx), |
283 label=changesetlabels(ctx), | 283 label=changesetlabels(ctx), |
284 ) | 284 ) |
285 | 285 |
286 # branches are shown first before any other names due to backwards | 286 # branches are shown first before any other names due to backwards |
287 # compatibility | 287 # compatibility |
288 branch = ctx.branch() | 288 branch = ctx.branch() |
289 # don't show the default branch name | 289 # don't show the default branch name |
290 if branch != 'default': | 290 if branch != b'default': |
291 self.ui.write(columns['branch'] % branch, label='log.branch') | 291 self.ui.write(columns[b'branch'] % branch, label=b'log.branch') |
292 | 292 |
293 for nsname, ns in self.repo.names.iteritems(): | 293 for nsname, ns in self.repo.names.iteritems(): |
294 # branches has special logic already handled above, so here we just | 294 # branches has special logic already handled above, so here we just |
295 # skip it | 295 # skip it |
296 if nsname == 'branches': | 296 if nsname == b'branches': |
297 continue | 297 continue |
298 # we will use the templatename as the color name since those two | 298 # we will use the templatename as the color name since those two |
299 # should be the same | 299 # should be the same |
300 for name in ns.names(self.repo, changenode): | 300 for name in ns.names(self.repo, changenode): |
301 self.ui.write(ns.logfmt % name, label='log.%s' % ns.colorname) | 301 self.ui.write(ns.logfmt % name, label=b'log.%s' % ns.colorname) |
302 if self.ui.debugflag: | 302 if self.ui.debugflag: |
303 self.ui.write(columns['phase'] % ctx.phasestr(), label='log.phase') | 303 self.ui.write( |
304 columns[b'phase'] % ctx.phasestr(), label=b'log.phase' | |
305 ) | |
304 for pctx in scmutil.meaningfulparents(self.repo, ctx): | 306 for pctx in scmutil.meaningfulparents(self.repo, ctx): |
305 label = 'log.parent changeset.%s' % pctx.phasestr() | 307 label = b'log.parent changeset.%s' % pctx.phasestr() |
306 self.ui.write( | 308 self.ui.write( |
307 columns['parent'] % scmutil.formatchangeid(pctx), label=label | 309 columns[b'parent'] % scmutil.formatchangeid(pctx), label=label |
308 ) | 310 ) |
309 | 311 |
310 if self.ui.debugflag: | 312 if self.ui.debugflag: |
311 mnode = ctx.manifestnode() | 313 mnode = ctx.manifestnode() |
312 if mnode is None: | 314 if mnode is None: |
313 mnode = wdirid | 315 mnode = wdirid |
314 mrev = wdirrev | 316 mrev = wdirrev |
315 else: | 317 else: |
316 mrev = self.repo.manifestlog.rev(mnode) | 318 mrev = self.repo.manifestlog.rev(mnode) |
317 self.ui.write( | 319 self.ui.write( |
318 columns['manifest'] | 320 columns[b'manifest'] |
319 % scmutil.formatrevnode(self.ui, mrev, mnode), | 321 % scmutil.formatrevnode(self.ui, mrev, mnode), |
320 label='ui.debug log.manifest', | 322 label=b'ui.debug log.manifest', |
321 ) | 323 ) |
322 self.ui.write(columns['user'] % ctx.user(), label='log.user') | 324 self.ui.write(columns[b'user'] % ctx.user(), label=b'log.user') |
323 self.ui.write( | 325 self.ui.write( |
324 columns['date'] % dateutil.datestr(ctx.date()), label='log.date' | 326 columns[b'date'] % dateutil.datestr(ctx.date()), label=b'log.date' |
325 ) | 327 ) |
326 | 328 |
327 if ctx.isunstable(): | 329 if ctx.isunstable(): |
328 instabilities = ctx.instabilities() | 330 instabilities = ctx.instabilities() |
329 self.ui.write( | 331 self.ui.write( |
330 columns['instability'] % ', '.join(instabilities), | 332 columns[b'instability'] % b', '.join(instabilities), |
331 label='log.instability', | 333 label=b'log.instability', |
332 ) | 334 ) |
333 | 335 |
334 elif ctx.obsolete(): | 336 elif ctx.obsolete(): |
335 self._showobsfate(ctx) | 337 self._showobsfate(ctx) |
336 | 338 |
337 self._exthook(ctx) | 339 self._exthook(ctx) |
338 | 340 |
339 if self.ui.debugflag: | 341 if self.ui.debugflag: |
340 files = ctx.p1().status(ctx)[:3] | 342 files = ctx.p1().status(ctx)[:3] |
341 for key, value in zip(['files', 'files+', 'files-'], files): | 343 for key, value in zip([b'files', b'files+', b'files-'], files): |
342 if value: | 344 if value: |
343 self.ui.write( | 345 self.ui.write( |
344 columns[key] % " ".join(value), | 346 columns[key] % b" ".join(value), |
345 label='ui.debug log.files', | 347 label=b'ui.debug log.files', |
346 ) | 348 ) |
347 elif ctx.files() and self.ui.verbose: | 349 elif ctx.files() and self.ui.verbose: |
348 self.ui.write( | 350 self.ui.write( |
349 columns['files'] % " ".join(ctx.files()), | 351 columns[b'files'] % b" ".join(ctx.files()), |
350 label='ui.note log.files', | 352 label=b'ui.note log.files', |
351 ) | 353 ) |
352 if copies and self.ui.verbose: | 354 if copies and self.ui.verbose: |
353 copies = ['%s (%s)' % c for c in copies] | 355 copies = [b'%s (%s)' % c for c in copies] |
354 self.ui.write( | 356 self.ui.write( |
355 columns['copies'] % ' '.join(copies), label='ui.note log.copies' | 357 columns[b'copies'] % b' '.join(copies), |
358 label=b'ui.note log.copies', | |
356 ) | 359 ) |
357 | 360 |
358 extra = ctx.extra() | 361 extra = ctx.extra() |
359 if extra and self.ui.debugflag: | 362 if extra and self.ui.debugflag: |
360 for key, value in sorted(extra.items()): | 363 for key, value in sorted(extra.items()): |
361 self.ui.write( | 364 self.ui.write( |
362 columns['extra'] % (key, stringutil.escapestr(value)), | 365 columns[b'extra'] % (key, stringutil.escapestr(value)), |
363 label='ui.debug log.extra', | 366 label=b'ui.debug log.extra', |
364 ) | 367 ) |
365 | 368 |
366 description = ctx.description().strip() | 369 description = ctx.description().strip() |
367 if description: | 370 if description: |
368 if self.ui.verbose: | 371 if self.ui.verbose: |
369 self.ui.write( | 372 self.ui.write( |
370 _("description:\n"), label='ui.note log.description' | 373 _(b"description:\n"), label=b'ui.note log.description' |
371 ) | 374 ) |
372 self.ui.write(description, label='ui.note log.description') | 375 self.ui.write(description, label=b'ui.note log.description') |
373 self.ui.write("\n\n") | 376 self.ui.write(b"\n\n") |
374 else: | 377 else: |
375 self.ui.write( | 378 self.ui.write( |
376 columns['summary'] % description.splitlines()[0], | 379 columns[b'summary'] % description.splitlines()[0], |
377 label='log.summary', | 380 label=b'log.summary', |
378 ) | 381 ) |
379 self.ui.write("\n") | 382 self.ui.write(b"\n") |
380 | 383 |
381 self._showpatch(ctx, graphwidth) | 384 self._showpatch(ctx, graphwidth) |
382 | 385 |
383 def _showobsfate(self, ctx): | 386 def _showobsfate(self, ctx): |
384 # TODO: do not depend on templater | 387 # TODO: do not depend on templater |
385 tres = formatter.templateresources(self.repo.ui, self.repo) | 388 tres = formatter.templateresources(self.repo.ui, self.repo) |
386 t = formatter.maketemplater( | 389 t = formatter.maketemplater( |
387 self.repo.ui, | 390 self.repo.ui, |
388 '{join(obsfate, "\n")}', | 391 b'{join(obsfate, "\n")}', |
389 defaults=templatekw.keywords, | 392 defaults=templatekw.keywords, |
390 resources=tres, | 393 resources=tres, |
391 ) | 394 ) |
392 obsfate = t.renderdefault({'ctx': ctx}).splitlines() | 395 obsfate = t.renderdefault({b'ctx': ctx}).splitlines() |
393 | 396 |
394 if obsfate: | 397 if obsfate: |
395 for obsfateline in obsfate: | 398 for obsfateline in obsfate: |
396 self.ui.write( | 399 self.ui.write( |
397 self._columns['obsolete'] % obsfateline, label='log.obsfate' | 400 self._columns[b'obsolete'] % obsfateline, |
401 label=b'log.obsfate', | |
398 ) | 402 ) |
399 | 403 |
400 def _exthook(self, ctx): | 404 def _exthook(self, ctx): |
401 '''empty method used by extension as a hook point | 405 '''empty method used by extension as a hook point |
402 ''' | 406 ''' |
405 if self._includestat: | 409 if self._includestat: |
406 self._differ.showdiff( | 410 self._differ.showdiff( |
407 self.ui, ctx, self._diffopts, graphwidth, stat=True | 411 self.ui, ctx, self._diffopts, graphwidth, stat=True |
408 ) | 412 ) |
409 if self._includestat and self._includediff: | 413 if self._includestat and self._includediff: |
410 self.ui.write("\n") | 414 self.ui.write(b"\n") |
411 if self._includediff: | 415 if self._includediff: |
412 self._differ.showdiff( | 416 self._differ.showdiff( |
413 self.ui, ctx, self._diffopts, graphwidth, stat=False | 417 self.ui, ctx, self._diffopts, graphwidth, stat=False |
414 ) | 418 ) |
415 if self._includestat or self._includediff: | 419 if self._includestat or self._includediff: |
416 self.ui.write("\n") | 420 self.ui.write(b"\n") |
417 | 421 |
418 | 422 |
419 class changesetformatter(changesetprinter): | 423 class changesetformatter(changesetprinter): |
420 """Format changeset information by generic formatter""" | 424 """Format changeset information by generic formatter""" |
421 | 425 |
443 branch=ctx.branch(), | 447 branch=ctx.branch(), |
444 phase=ctx.phasestr(), | 448 phase=ctx.phasestr(), |
445 user=ctx.user(), | 449 user=ctx.user(), |
446 date=fm.formatdate(ctx.date()), | 450 date=fm.formatdate(ctx.date()), |
447 desc=ctx.description(), | 451 desc=ctx.description(), |
448 bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'), | 452 bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'), |
449 tags=fm.formatlist(ctx.tags(), name='tag'), | 453 tags=fm.formatlist(ctx.tags(), name=b'tag'), |
450 parents=fm.formatlist( | 454 parents=fm.formatlist( |
451 [fm.hexfunc(c.node()) for c in ctx.parents()], name='node' | 455 [fm.hexfunc(c.node()) for c in ctx.parents()], name=b'node' |
452 ), | 456 ), |
453 ) | 457 ) |
454 | 458 |
455 if self.ui.debugflag: | 459 if self.ui.debugflag: |
456 fm.data( | 460 fm.data( |
458 extra=fm.formatdict(ctx.extra()), | 462 extra=fm.formatdict(ctx.extra()), |
459 ) | 463 ) |
460 | 464 |
461 files = ctx.p1().status(ctx) | 465 files = ctx.p1().status(ctx) |
462 fm.data( | 466 fm.data( |
463 modified=fm.formatlist(files[0], name='file'), | 467 modified=fm.formatlist(files[0], name=b'file'), |
464 added=fm.formatlist(files[1], name='file'), | 468 added=fm.formatlist(files[1], name=b'file'), |
465 removed=fm.formatlist(files[2], name='file'), | 469 removed=fm.formatlist(files[2], name=b'file'), |
466 ) | 470 ) |
467 | 471 |
468 elif self.ui.verbose: | 472 elif self.ui.verbose: |
469 fm.data(files=fm.formatlist(ctx.files(), name='file')) | 473 fm.data(files=fm.formatlist(ctx.files(), name=b'file')) |
470 if copies: | 474 if copies: |
471 fm.data( | 475 fm.data( |
472 copies=fm.formatdict(copies, key='name', value='source') | 476 copies=fm.formatdict(copies, key=b'name', value=b'source') |
473 ) | 477 ) |
474 | 478 |
475 if self._includestat: | 479 if self._includestat: |
476 self.ui.pushbuffer() | 480 self.ui.pushbuffer() |
477 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=True) | 481 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=True) |
508 ) | 512 ) |
509 self._counter = itertools.count() | 513 self._counter = itertools.count() |
510 | 514 |
511 self._tref = tmplspec.ref | 515 self._tref = tmplspec.ref |
512 self._parts = { | 516 self._parts = { |
513 'header': '', | 517 b'header': b'', |
514 'footer': '', | 518 b'footer': b'', |
515 tmplspec.ref: tmplspec.ref, | 519 tmplspec.ref: tmplspec.ref, |
516 'docheader': '', | 520 b'docheader': b'', |
517 'docfooter': '', | 521 b'docfooter': b'', |
518 'separator': '', | 522 b'separator': b'', |
519 } | 523 } |
520 if tmplspec.mapfile: | 524 if tmplspec.mapfile: |
521 # find correct templates for current mode, for backward | 525 # find correct templates for current mode, for backward |
522 # compatibility with 'log -v/-q/--debug' using a mapfile | 526 # compatibility with 'log -v/-q/--debug' using a mapfile |
523 tmplmodes = [ | 527 tmplmodes = [ |
524 (True, ''), | 528 (True, b''), |
525 (self.ui.verbose, '_verbose'), | 529 (self.ui.verbose, b'_verbose'), |
526 (self.ui.quiet, '_quiet'), | 530 (self.ui.quiet, b'_quiet'), |
527 (self.ui.debugflag, '_debug'), | 531 (self.ui.debugflag, b'_debug'), |
528 ] | 532 ] |
529 for mode, postfix in tmplmodes: | 533 for mode, postfix in tmplmodes: |
530 for t in self._parts: | 534 for t in self._parts: |
531 cur = t + postfix | 535 cur = t + postfix |
532 if mode and cur in self.t: | 536 if mode and cur in self.t: |
534 else: | 538 else: |
535 partnames = [p for p in self._parts.keys() if p != tmplspec.ref] | 539 partnames = [p for p in self._parts.keys() if p != tmplspec.ref] |
536 m = formatter.templatepartsmap(tmplspec, self.t, partnames) | 540 m = formatter.templatepartsmap(tmplspec, self.t, partnames) |
537 self._parts.update(m) | 541 self._parts.update(m) |
538 | 542 |
539 if self._parts['docheader']: | 543 if self._parts[b'docheader']: |
540 self.ui.write(self.t.render(self._parts['docheader'], {})) | 544 self.ui.write(self.t.render(self._parts[b'docheader'], {})) |
541 | 545 |
542 def close(self): | 546 def close(self): |
543 if self._parts['docfooter']: | 547 if self._parts[b'docfooter']: |
544 if not self.footer: | 548 if not self.footer: |
545 self.footer = "" | 549 self.footer = b"" |
546 self.footer += self.t.render(self._parts['docfooter'], {}) | 550 self.footer += self.t.render(self._parts[b'docfooter'], {}) |
547 return super(changesettemplater, self).close() | 551 return super(changesettemplater, self).close() |
548 | 552 |
549 def _show(self, ctx, copies, props): | 553 def _show(self, ctx, copies, props): |
550 '''show a single changeset or file revision''' | 554 '''show a single changeset or file revision''' |
551 props = props.copy() | 555 props = props.copy() |
552 props['ctx'] = ctx | 556 props[b'ctx'] = ctx |
553 props['index'] = index = next(self._counter) | 557 props[b'index'] = index = next(self._counter) |
554 props['revcache'] = {'copies': copies} | 558 props[b'revcache'] = {b'copies': copies} |
555 graphwidth = props.get('graphwidth', 0) | 559 graphwidth = props.get(b'graphwidth', 0) |
556 | 560 |
557 # write separator, which wouldn't work well with the header part below | 561 # write separator, which wouldn't work well with the header part below |
558 # since there's inherently a conflict between header (across items) and | 562 # since there's inherently a conflict between header (across items) and |
559 # separator (per item) | 563 # separator (per item) |
560 if self._parts['separator'] and index > 0: | 564 if self._parts[b'separator'] and index > 0: |
561 self.ui.write(self.t.render(self._parts['separator'], {})) | 565 self.ui.write(self.t.render(self._parts[b'separator'], {})) |
562 | 566 |
563 # write header | 567 # write header |
564 if self._parts['header']: | 568 if self._parts[b'header']: |
565 h = self.t.render(self._parts['header'], props) | 569 h = self.t.render(self._parts[b'header'], props) |
566 if self.buffered: | 570 if self.buffered: |
567 self.header[ctx.rev()] = h | 571 self.header[ctx.rev()] = h |
568 else: | 572 else: |
569 if self.lastheader != h: | 573 if self.lastheader != h: |
570 self.lastheader = h | 574 self.lastheader = h |
573 # write changeset metadata, then patch if requested | 577 # write changeset metadata, then patch if requested |
574 key = self._parts[self._tref] | 578 key = self._parts[self._tref] |
575 self.ui.write(self.t.render(key, props)) | 579 self.ui.write(self.t.render(key, props)) |
576 self._showpatch(ctx, graphwidth) | 580 self._showpatch(ctx, graphwidth) |
577 | 581 |
578 if self._parts['footer']: | 582 if self._parts[b'footer']: |
579 if not self.footer: | 583 if not self.footer: |
580 self.footer = self.t.render(self._parts['footer'], props) | 584 self.footer = self.t.render(self._parts[b'footer'], props) |
581 | 585 |
582 | 586 |
583 def templatespec(tmpl, mapfile): | 587 def templatespec(tmpl, mapfile): |
584 if pycompat.ispy3: | 588 if pycompat.ispy3: |
585 assert not isinstance(tmpl, str), 'tmpl must not be a str' | 589 assert not isinstance(tmpl, str), b'tmpl must not be a str' |
586 if mapfile: | 590 if mapfile: |
587 return formatter.templatespec('changeset', tmpl, mapfile) | 591 return formatter.templatespec(b'changeset', tmpl, mapfile) |
588 else: | 592 else: |
589 return formatter.templatespec('', tmpl, None) | 593 return formatter.templatespec(b'', tmpl, None) |
590 | 594 |
591 | 595 |
592 def _lookuptemplate(ui, tmpl, style): | 596 def _lookuptemplate(ui, tmpl, style): |
593 """Find the template matching the given template spec or style | 597 """Find the template matching the given template spec or style |
594 | 598 |
595 See formatter.lookuptemplate() for details. | 599 See formatter.lookuptemplate() for details. |
596 """ | 600 """ |
597 | 601 |
598 # ui settings | 602 # ui settings |
599 if not tmpl and not style: # template are stronger than style | 603 if not tmpl and not style: # template are stronger than style |
600 tmpl = ui.config('ui', 'logtemplate') | 604 tmpl = ui.config(b'ui', b'logtemplate') |
601 if tmpl: | 605 if tmpl: |
602 return templatespec(templater.unquotestring(tmpl), None) | 606 return templatespec(templater.unquotestring(tmpl), None) |
603 else: | 607 else: |
604 style = util.expandpath(ui.config('ui', 'style')) | 608 style = util.expandpath(ui.config(b'ui', b'style')) |
605 | 609 |
606 if not tmpl and style: | 610 if not tmpl and style: |
607 mapfile = style | 611 mapfile = style |
608 if not os.path.split(mapfile)[0]: | 612 if not os.path.split(mapfile)[0]: |
609 mapname = templater.templatepath( | 613 mapname = templater.templatepath( |
610 'map-cmdline.' + mapfile | 614 b'map-cmdline.' + mapfile |
611 ) or templater.templatepath(mapfile) | 615 ) or templater.templatepath(mapfile) |
612 if mapname: | 616 if mapname: |
613 mapfile = mapname | 617 mapfile = mapname |
614 return templatespec(None, mapfile) | 618 return templatespec(None, mapfile) |
615 | 619 |
616 if not tmpl: | 620 if not tmpl: |
617 return templatespec(None, None) | 621 return templatespec(None, None) |
618 | 622 |
619 return formatter.lookuptemplate(ui, 'changeset', tmpl) | 623 return formatter.lookuptemplate(ui, b'changeset', tmpl) |
620 | 624 |
621 | 625 |
622 def maketemplater(ui, repo, tmpl, buffered=False): | 626 def maketemplater(ui, repo, tmpl, buffered=False): |
623 """Create a changesettemplater from a literal template 'tmpl' | 627 """Create a changesettemplater from a literal template 'tmpl' |
624 byte-string.""" | 628 byte-string.""" |
636 4. [ui] setting 'style' | 640 4. [ui] setting 'style' |
637 If all of these values are either the unset or the empty string, | 641 If all of these values are either the unset or the empty string, |
638 regular display via changesetprinter() is done. | 642 regular display via changesetprinter() is done. |
639 """ | 643 """ |
640 postargs = (differ, opts, buffered) | 644 postargs = (differ, opts, buffered) |
641 if opts.get('template') in {'cbor', 'json'}: | 645 if opts.get(b'template') in {b'cbor', b'json'}: |
642 fm = ui.formatter('log', opts) | 646 fm = ui.formatter(b'log', opts) |
643 return changesetformatter(ui, repo, fm, *postargs) | 647 return changesetformatter(ui, repo, fm, *postargs) |
644 | 648 |
645 spec = _lookuptemplate(ui, opts.get('template'), opts.get('style')) | 649 spec = _lookuptemplate(ui, opts.get(b'template'), opts.get(b'style')) |
646 | 650 |
647 if not spec.ref and not spec.tmpl and not spec.mapfile: | 651 if not spec.ref and not spec.tmpl and not spec.mapfile: |
648 return changesetprinter(ui, repo, *postargs) | 652 return changesetprinter(ui, repo, *postargs) |
649 | 653 |
650 return changesettemplater(ui, repo, spec, *postargs) | 654 return changesettemplater(ui, repo, spec, *postargs) |
664 # _matchfiles() revset but walkchangerevs() builds its matcher with | 668 # _matchfiles() revset but walkchangerevs() builds its matcher with |
665 # scmutil.match(). The difference is input pats are globbed on | 669 # scmutil.match(). The difference is input pats are globbed on |
666 # platforms without shell expansion (windows). | 670 # platforms without shell expansion (windows). |
667 wctx = repo[None] | 671 wctx = repo[None] |
668 match, pats = scmutil.matchandpats(wctx, pats, opts) | 672 match, pats = scmutil.matchandpats(wctx, pats, opts) |
669 slowpath = match.anypats() or (not match.always() and opts.get('removed')) | 673 slowpath = match.anypats() or (not match.always() and opts.get(b'removed')) |
670 if not slowpath: | 674 if not slowpath: |
671 follow = opts.get('follow') or opts.get('follow_first') | 675 follow = opts.get(b'follow') or opts.get(b'follow_first') |
672 startctxs = [] | 676 startctxs = [] |
673 if follow and opts.get('rev'): | 677 if follow and opts.get(b'rev'): |
674 startctxs = [repo[r] for r in revs] | 678 startctxs = [repo[r] for r in revs] |
675 for f in match.files(): | 679 for f in match.files(): |
676 if follow and startctxs: | 680 if follow and startctxs: |
677 # No idea if the path was a directory at that revision, so | 681 # No idea if the path was a directory at that revision, so |
678 # take the slow path. | 682 # take the slow path. |
685 if os.path.exists(repo.wjoin(f)): | 689 if os.path.exists(repo.wjoin(f)): |
686 slowpath = True | 690 slowpath = True |
687 continue | 691 continue |
688 else: | 692 else: |
689 raise error.Abort( | 693 raise error.Abort( |
690 _('cannot follow file not in parent ' 'revision: "%s"') | 694 _( |
695 b'cannot follow file not in parent ' | |
696 b'revision: "%s"' | |
697 ) | |
691 % f | 698 % f |
692 ) | 699 ) |
693 filelog = repo.file(f) | 700 filelog = repo.file(f) |
694 if not filelog: | 701 if not filelog: |
695 # A zero count may be a directory or deleted file, so | 702 # A zero count may be a directory or deleted file, so |
696 # try to find matching entries on the slow path. | 703 # try to find matching entries on the slow path. |
697 if follow: | 704 if follow: |
698 raise error.Abort( | 705 raise error.Abort( |
699 _('cannot follow nonexistent file: "%s"') % f | 706 _(b'cannot follow nonexistent file: "%s"') % f |
700 ) | 707 ) |
701 slowpath = True | 708 slowpath = True |
702 | 709 |
703 # We decided to fall back to the slowpath because at least one | 710 # We decided to fall back to the slowpath because at least one |
704 # of the paths was not a file. Check to see if at least one of them | 711 # of the paths was not a file. Check to see if at least one of them |
705 # existed in history - in that case, we'll continue down the | 712 # existed in history - in that case, we'll continue down the |
706 # slowpath; otherwise, we can turn off the slowpath | 713 # slowpath; otherwise, we can turn off the slowpath |
707 if slowpath: | 714 if slowpath: |
708 for path in match.files(): | 715 for path in match.files(): |
709 if path == '.' or path in repo.store: | 716 if path == b'.' or path in repo.store: |
710 break | 717 break |
711 else: | 718 else: |
712 slowpath = False | 719 slowpath = False |
713 | 720 |
714 return match, pats, slowpath | 721 return match, pats, slowpath |
742 '''hook for extensions to override the filematcher for non-follow cases''' | 749 '''hook for extensions to override the filematcher for non-follow cases''' |
743 return None | 750 return None |
744 | 751 |
745 | 752 |
746 _opt2logrevset = { | 753 _opt2logrevset = { |
747 'no_merges': ('not merge()', None), | 754 b'no_merges': (b'not merge()', None), |
748 'only_merges': ('merge()', None), | 755 b'only_merges': (b'merge()', None), |
749 '_matchfiles': (None, '_matchfiles(%ps)'), | 756 b'_matchfiles': (None, b'_matchfiles(%ps)'), |
750 'date': ('date(%s)', None), | 757 b'date': (b'date(%s)', None), |
751 'branch': ('branch(%s)', '%lr'), | 758 b'branch': (b'branch(%s)', b'%lr'), |
752 '_patslog': ('filelog(%s)', '%lr'), | 759 b'_patslog': (b'filelog(%s)', b'%lr'), |
753 'keyword': ('keyword(%s)', '%lr'), | 760 b'keyword': (b'keyword(%s)', b'%lr'), |
754 'prune': ('ancestors(%s)', 'not %lr'), | 761 b'prune': (b'ancestors(%s)', b'not %lr'), |
755 'user': ('user(%s)', '%lr'), | 762 b'user': (b'user(%s)', b'%lr'), |
756 } | 763 } |
757 | 764 |
758 | 765 |
759 def _makerevset(repo, match, pats, slowpath, opts): | 766 def _makerevset(repo, match, pats, slowpath, opts): |
760 """Return a revset string built from log options and file patterns""" | 767 """Return a revset string built from log options and file patterns""" |
761 opts = dict(opts) | 768 opts = dict(opts) |
762 # follow or not follow? | 769 # follow or not follow? |
763 follow = opts.get('follow') or opts.get('follow_first') | 770 follow = opts.get(b'follow') or opts.get(b'follow_first') |
764 | 771 |
765 # branch and only_branch are really aliases and must be handled at | 772 # branch and only_branch are really aliases and must be handled at |
766 # the same time | 773 # the same time |
767 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', []) | 774 opts[b'branch'] = opts.get(b'branch', []) + opts.get(b'only_branch', []) |
768 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']] | 775 opts[b'branch'] = [repo.lookupbranch(b) for b in opts[b'branch']] |
769 | 776 |
770 if slowpath: | 777 if slowpath: |
771 # See walkchangerevs() slow path. | 778 # See walkchangerevs() slow path. |
772 # | 779 # |
773 # pats/include/exclude cannot be represented as separate | 780 # pats/include/exclude cannot be represented as separate |
774 # revset expressions as their filtering logic applies at file | 781 # revset expressions as their filtering logic applies at file |
775 # level. For instance "-I a -X b" matches a revision touching | 782 # level. For instance "-I a -X b" matches a revision touching |
776 # "a" and "b" while "file(a) and not file(b)" does | 783 # "a" and "b" while "file(a) and not file(b)" does |
777 # not. Besides, filesets are evaluated against the working | 784 # not. Besides, filesets are evaluated against the working |
778 # directory. | 785 # directory. |
779 matchargs = ['r:', 'd:relpath'] | 786 matchargs = [b'r:', b'd:relpath'] |
780 for p in pats: | 787 for p in pats: |
781 matchargs.append('p:' + p) | 788 matchargs.append(b'p:' + p) |
782 for p in opts.get('include', []): | 789 for p in opts.get(b'include', []): |
783 matchargs.append('i:' + p) | 790 matchargs.append(b'i:' + p) |
784 for p in opts.get('exclude', []): | 791 for p in opts.get(b'exclude', []): |
785 matchargs.append('x:' + p) | 792 matchargs.append(b'x:' + p) |
786 opts['_matchfiles'] = matchargs | 793 opts[b'_matchfiles'] = matchargs |
787 elif not follow: | 794 elif not follow: |
788 opts['_patslog'] = list(pats) | 795 opts[b'_patslog'] = list(pats) |
789 | 796 |
790 expr = [] | 797 expr = [] |
791 for op, val in sorted(opts.iteritems()): | 798 for op, val in sorted(opts.iteritems()): |
792 if not val: | 799 if not val: |
793 continue | 800 continue |
794 if op not in _opt2logrevset: | 801 if op not in _opt2logrevset: |
795 continue | 802 continue |
796 revop, listop = _opt2logrevset[op] | 803 revop, listop = _opt2logrevset[op] |
797 if revop and '%' not in revop: | 804 if revop and b'%' not in revop: |
798 expr.append(revop) | 805 expr.append(revop) |
799 elif not listop: | 806 elif not listop: |
800 expr.append(revsetlang.formatspec(revop, val)) | 807 expr.append(revsetlang.formatspec(revop, val)) |
801 else: | 808 else: |
802 if revop: | 809 if revop: |
803 val = [revsetlang.formatspec(revop, v) for v in val] | 810 val = [revsetlang.formatspec(revop, v) for v in val] |
804 expr.append(revsetlang.formatspec(listop, val)) | 811 expr.append(revsetlang.formatspec(listop, val)) |
805 | 812 |
806 if expr: | 813 if expr: |
807 expr = '(' + ' and '.join(expr) + ')' | 814 expr = b'(' + b' and '.join(expr) + b')' |
808 else: | 815 else: |
809 expr = None | 816 expr = None |
810 return expr | 817 return expr |
811 | 818 |
812 | 819 |
813 def _initialrevs(repo, opts): | 820 def _initialrevs(repo, opts): |
814 """Return the initial set of revisions to be filtered or followed""" | 821 """Return the initial set of revisions to be filtered or followed""" |
815 follow = opts.get('follow') or opts.get('follow_first') | 822 follow = opts.get(b'follow') or opts.get(b'follow_first') |
816 if opts.get('rev'): | 823 if opts.get(b'rev'): |
817 revs = scmutil.revrange(repo, opts['rev']) | 824 revs = scmutil.revrange(repo, opts[b'rev']) |
818 elif follow and repo.dirstate.p1() == nullid: | 825 elif follow and repo.dirstate.p1() == nullid: |
819 revs = smartset.baseset() | 826 revs = smartset.baseset() |
820 elif follow: | 827 elif follow: |
821 revs = repo.revs('.') | 828 revs = repo.revs(b'.') |
822 else: | 829 else: |
823 revs = smartset.spanset(repo) | 830 revs = smartset.spanset(repo) |
824 revs.reverse() | 831 revs.reverse() |
825 return revs | 832 return revs |
826 | 833 |
828 def getrevs(repo, pats, opts): | 835 def getrevs(repo, pats, opts): |
829 """Return (revs, differ) where revs is a smartset | 836 """Return (revs, differ) where revs is a smartset |
830 | 837 |
831 differ is a changesetdiffer with pre-configured file matcher. | 838 differ is a changesetdiffer with pre-configured file matcher. |
832 """ | 839 """ |
833 follow = opts.get('follow') or opts.get('follow_first') | 840 follow = opts.get(b'follow') or opts.get(b'follow_first') |
834 followfirst = opts.get('follow_first') | 841 followfirst = opts.get(b'follow_first') |
835 limit = getlimit(opts) | 842 limit = getlimit(opts) |
836 revs = _initialrevs(repo, opts) | 843 revs = _initialrevs(repo, opts) |
837 if not revs: | 844 if not revs: |
838 return smartset.baseset(), None | 845 return smartset.baseset(), None |
839 match, pats, slowpath = _makematcher(repo, revs, pats, opts) | 846 match, pats, slowpath = _makematcher(repo, revs, pats, opts) |
850 | 857 |
851 def filematcher(ctx): | 858 def filematcher(ctx): |
852 return match | 859 return match |
853 | 860 |
854 expr = _makerevset(repo, match, pats, slowpath, opts) | 861 expr = _makerevset(repo, match, pats, slowpath, opts) |
855 if opts.get('graph'): | 862 if opts.get(b'graph'): |
856 # User-specified revs might be unsorted, but don't sort before | 863 # User-specified revs might be unsorted, but don't sort before |
857 # _makerevset because it might depend on the order of revs | 864 # _makerevset because it might depend on the order of revs |
858 if repo.ui.configbool('experimental', 'log.topo'): | 865 if repo.ui.configbool(b'experimental', b'log.topo'): |
859 if not revs.istopo(): | 866 if not revs.istopo(): |
860 revs = dagop.toposort(revs, repo.changelog.parentrevs) | 867 revs = dagop.toposort(revs, repo.changelog.parentrevs) |
861 # TODO: try to iterate the set lazily | 868 # TODO: try to iterate the set lazily |
862 revs = revset.baseset(list(revs), istopo=True) | 869 revs = revset.baseset(list(revs), istopo=True) |
863 elif not (revs.isdescending() or revs.istopo()): | 870 elif not (revs.isdescending() or revs.istopo()): |
876 def _parselinerangeopt(repo, opts): | 883 def _parselinerangeopt(repo, opts): |
877 """Parse --line-range log option and return a list of tuples (filename, | 884 """Parse --line-range log option and return a list of tuples (filename, |
878 (fromline, toline)). | 885 (fromline, toline)). |
879 """ | 886 """ |
880 linerangebyfname = [] | 887 linerangebyfname = [] |
881 for pat in opts.get('line_range', []): | 888 for pat in opts.get(b'line_range', []): |
882 try: | 889 try: |
883 pat, linerange = pat.rsplit(',', 1) | 890 pat, linerange = pat.rsplit(b',', 1) |
884 except ValueError: | 891 except ValueError: |
885 raise error.Abort(_('malformatted line-range pattern %s') % pat) | 892 raise error.Abort(_(b'malformatted line-range pattern %s') % pat) |
886 try: | 893 try: |
887 fromline, toline = map(int, linerange.split(':')) | 894 fromline, toline = map(int, linerange.split(b':')) |
888 except ValueError: | 895 except ValueError: |
889 raise error.Abort(_("invalid line range for %s") % pat) | 896 raise error.Abort(_(b"invalid line range for %s") % pat) |
890 msg = _("line range pattern '%s' must match exactly one file") % pat | 897 msg = _(b"line range pattern '%s' must match exactly one file") % pat |
891 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg) | 898 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg) |
892 linerangebyfname.append( | 899 linerangebyfname.append( |
893 (fname, util.processlinerange(fromline, toline)) | 900 (fname, util.processlinerange(fromline, toline)) |
894 ) | 901 ) |
895 return linerangebyfname | 902 return linerangebyfname |
909 # Two-levels map of "rev -> file ctx -> [line range]". | 916 # Two-levels map of "rev -> file ctx -> [line range]". |
910 linerangesbyrev = {} | 917 linerangesbyrev = {} |
911 for fname, (fromline, toline) in _parselinerangeopt(repo, opts): | 918 for fname, (fromline, toline) in _parselinerangeopt(repo, opts): |
912 if fname not in wctx: | 919 if fname not in wctx: |
913 raise error.Abort( | 920 raise error.Abort( |
914 _('cannot follow file not in parent ' 'revision: "%s"') % fname | 921 _(b'cannot follow file not in parent ' b'revision: "%s"') |
922 % fname | |
915 ) | 923 ) |
916 fctx = wctx.filectx(fname) | 924 fctx = wctx.filectx(fname) |
917 for fctx, linerange in dagop.blockancestors(fctx, fromline, toline): | 925 for fctx, linerange in dagop.blockancestors(fctx, fromline, toline): |
918 rev = fctx.introrev() | 926 rev = fctx.introrev() |
919 if rev not in userrevs: | 927 if rev not in userrevs: |
956 differ._makehunksfilter = hunksfilter | 964 differ._makehunksfilter = hunksfilter |
957 return revs, differ | 965 return revs, differ |
958 | 966 |
959 | 967 |
960 def _graphnodeformatter(ui, displayer): | 968 def _graphnodeformatter(ui, displayer): |
961 spec = ui.config('ui', 'graphnodetemplate') | 969 spec = ui.config(b'ui', b'graphnodetemplate') |
962 if not spec: | 970 if not spec: |
963 return templatekw.getgraphnode # fast path for "{graphnode}" | 971 return templatekw.getgraphnode # fast path for "{graphnode}" |
964 | 972 |
965 spec = templater.unquotestring(spec) | 973 spec = templater.unquotestring(spec) |
966 if isinstance(displayer, changesettemplater): | 974 if isinstance(displayer, changesettemplater): |
971 templ = formatter.maketemplater( | 979 templ = formatter.maketemplater( |
972 ui, spec, defaults=templatekw.keywords, resources=tres | 980 ui, spec, defaults=templatekw.keywords, resources=tres |
973 ) | 981 ) |
974 | 982 |
975 def formatnode(repo, ctx): | 983 def formatnode(repo, ctx): |
976 props = {'ctx': ctx, 'repo': repo} | 984 props = {b'ctx': ctx, b'repo': repo} |
977 return templ.renderdefault(props) | 985 return templ.renderdefault(props) |
978 | 986 |
979 return formatnode | 987 return formatnode |
980 | 988 |
981 | 989 |
982 def displaygraph(ui, repo, dag, displayer, edgefn, getcopies=None, props=None): | 990 def displaygraph(ui, repo, dag, displayer, edgefn, getcopies=None, props=None): |
983 props = props or {} | 991 props = props or {} |
984 formatnode = _graphnodeformatter(ui, displayer) | 992 formatnode = _graphnodeformatter(ui, displayer) |
985 state = graphmod.asciistate() | 993 state = graphmod.asciistate() |
986 styles = state['styles'] | 994 styles = state[b'styles'] |
987 | 995 |
988 # only set graph styling if HGPLAIN is not set. | 996 # only set graph styling if HGPLAIN is not set. |
989 if ui.plain('graph'): | 997 if ui.plain(b'graph'): |
990 # set all edge styles to |, the default pre-3.8 behaviour | 998 # set all edge styles to |, the default pre-3.8 behaviour |
991 styles.update(dict.fromkeys(styles, '|')) | 999 styles.update(dict.fromkeys(styles, b'|')) |
992 else: | 1000 else: |
993 edgetypes = { | 1001 edgetypes = { |
994 'parent': graphmod.PARENT, | 1002 b'parent': graphmod.PARENT, |
995 'grandparent': graphmod.GRANDPARENT, | 1003 b'grandparent': graphmod.GRANDPARENT, |
996 'missing': graphmod.MISSINGPARENT, | 1004 b'missing': graphmod.MISSINGPARENT, |
997 } | 1005 } |
998 for name, key in edgetypes.items(): | 1006 for name, key in edgetypes.items(): |
999 # experimental config: experimental.graphstyle.* | 1007 # experimental config: experimental.graphstyle.* |
1000 styles[key] = ui.config( | 1008 styles[key] = ui.config( |
1001 'experimental', 'graphstyle.%s' % name, styles[key] | 1009 b'experimental', b'graphstyle.%s' % name, styles[key] |
1002 ) | 1010 ) |
1003 if not styles[key]: | 1011 if not styles[key]: |
1004 styles[key] = None | 1012 styles[key] = None |
1005 | 1013 |
1006 # experimental config: experimental.graphshorten | 1014 # experimental config: experimental.graphshorten |
1007 state['graphshorten'] = ui.configbool('experimental', 'graphshorten') | 1015 state[b'graphshorten'] = ui.configbool(b'experimental', b'graphshorten') |
1008 | 1016 |
1009 for rev, type, ctx, parents in dag: | 1017 for rev, type, ctx, parents in dag: |
1010 char = formatnode(repo, ctx) | 1018 char = formatnode(repo, ctx) |
1011 copies = getcopies(ctx) if getcopies else None | 1019 copies = getcopies(ctx) if getcopies else None |
1012 edges = edgefn(type, char, state, rev, parents) | 1020 edges = edgefn(type, char, state, rev, parents) |
1013 firstedge = next(edges) | 1021 firstedge = next(edges) |
1014 width = firstedge[2] | 1022 width = firstedge[2] |
1015 displayer.show( | 1023 displayer.show( |
1016 ctx, copies=copies, graphwidth=width, **pycompat.strkwargs(props) | 1024 ctx, copies=copies, graphwidth=width, **pycompat.strkwargs(props) |
1017 ) | 1025 ) |
1018 lines = displayer.hunk.pop(rev).split('\n') | 1026 lines = displayer.hunk.pop(rev).split(b'\n') |
1019 if not lines[-1]: | 1027 if not lines[-1]: |
1020 del lines[-1] | 1028 del lines[-1] |
1021 displayer.flush(ctx) | 1029 displayer.flush(ctx) |
1022 for type, char, width, coldata in itertools.chain([firstedge], edges): | 1030 for type, char, width, coldata in itertools.chain([firstedge], edges): |
1023 graphmod.ascii(ui, state, type, char, lines, coldata) | 1031 graphmod.ascii(ui, state, type, char, lines, coldata) |
1038 displayer.flush(ctx) | 1046 displayer.flush(ctx) |
1039 displayer.close() | 1047 displayer.close() |
1040 | 1048 |
1041 | 1049 |
1042 def checkunsupportedgraphflags(pats, opts): | 1050 def checkunsupportedgraphflags(pats, opts): |
1043 for op in ["newest_first"]: | 1051 for op in [b"newest_first"]: |
1044 if op in opts and opts[op]: | 1052 if op in opts and opts[op]: |
1045 raise error.Abort( | 1053 raise error.Abort( |
1046 _("-G/--graph option is incompatible with --%s") | 1054 _(b"-G/--graph option is incompatible with --%s") |
1047 % op.replace("_", "-") | 1055 % op.replace(b"_", b"-") |
1048 ) | 1056 ) |
1049 | 1057 |
1050 | 1058 |
1051 def graphrevs(repo, nodes, opts): | 1059 def graphrevs(repo, nodes, opts): |
1052 limit = getlimit(opts) | 1060 limit = getlimit(opts) |