comparison hgext/show.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 86e4daa2d54c
comparison
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
47 47
48 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for 48 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
49 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should 49 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
50 # be specifying the version(s) of Mercurial they are tested with, or 50 # be specifying the version(s) of Mercurial they are tested with, or
51 # leave the attribute unspecified. 51 # leave the attribute unspecified.
52 testedwith = 'ships-with-hg-core' 52 testedwith = b'ships-with-hg-core'
53 53
54 cmdtable = {} 54 cmdtable = {}
55 command = registrar.command(cmdtable) 55 command = registrar.command(cmdtable)
56 56
57 revsetpredicate = registrar.revsetpredicate() 57 revsetpredicate = registrar.revsetpredicate()
59 59
60 class showcmdfunc(registrar._funcregistrarbase): 60 class showcmdfunc(registrar._funcregistrarbase):
61 """Register a function to be invoked for an `hg show <thing>`.""" 61 """Register a function to be invoked for an `hg show <thing>`."""
62 62
63 # Used by _formatdoc(). 63 # Used by _formatdoc().
64 _docformat = '%s -- %s' 64 _docformat = b'%s -- %s'
65 65
66 def _extrasetup(self, name, func, fmtopic=None, csettopic=None): 66 def _extrasetup(self, name, func, fmtopic=None, csettopic=None):
67 """Called with decorator arguments to register a show view. 67 """Called with decorator arguments to register a show view.
68 68
69 ``name`` is the sub-command name. 69 ``name`` is the sub-command name.
86 86
87 showview = showcmdfunc() 87 showview = showcmdfunc()
88 88
89 89
90 @command( 90 @command(
91 'show', 91 b'show',
92 [ 92 [
93 # TODO: Switch this template flag to use cmdutil.formatteropts if 93 # TODO: Switch this template flag to use cmdutil.formatteropts if
94 # 'hg show' becomes stable before --template/-T is stable. For now, 94 # 'hg show' becomes stable before --template/-T is stable. For now,
95 # we are putting it here without the '(EXPERIMENTAL)' flag because it 95 # we are putting it here without the '(EXPERIMENTAL)' flag because it
96 # is an important part of the 'hg show' user experience and the entire 96 # is an important part of the 'hg show' user experience and the entire
97 # 'hg show' experience is experimental. 97 # 'hg show' experience is experimental.
98 ('T', 'template', '', 'display with template', _('TEMPLATE')), 98 (b'T', b'template', b'', b'display with template', _(b'TEMPLATE')),
99 ], 99 ],
100 _('VIEW'), 100 _(b'VIEW'),
101 helpcategory=command.CATEGORY_CHANGE_NAVIGATION, 101 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
102 ) 102 )
103 def show(ui, repo, view=None, template=None): 103 def show(ui, repo, view=None, template=None):
104 """show various repository information 104 """show various repository information
105 105
117 ``-T/--template``. 117 ``-T/--template``.
118 118
119 List of available views: 119 List of available views:
120 """ 120 """
121 if ui.plain() and not template: 121 if ui.plain() and not template:
122 hint = _('invoke with -T/--template to control output format') 122 hint = _(b'invoke with -T/--template to control output format')
123 raise error.Abort(_('must specify a template in plain mode'), hint=hint) 123 raise error.Abort(
124 _(b'must specify a template in plain mode'), hint=hint
125 )
124 126
125 views = showview._table 127 views = showview._table
126 128
127 if not view: 129 if not view:
128 ui.pager('show') 130 ui.pager(b'show')
129 # TODO consider using formatter here so available views can be 131 # TODO consider using formatter here so available views can be
130 # rendered to custom format. 132 # rendered to custom format.
131 ui.write(_('available views:\n')) 133 ui.write(_(b'available views:\n'))
132 ui.write('\n') 134 ui.write(b'\n')
133 135
134 for name, func in sorted(views.items()): 136 for name, func in sorted(views.items()):
135 ui.write('%s\n' % pycompat.sysbytes(func.__doc__)) 137 ui.write(b'%s\n' % pycompat.sysbytes(func.__doc__))
136 138
137 ui.write('\n') 139 ui.write(b'\n')
138 raise error.Abort( 140 raise error.Abort(
139 _('no view requested'), 141 _(b'no view requested'),
140 hint=_('use "hg show VIEW" to choose a view'), 142 hint=_(b'use "hg show VIEW" to choose a view'),
141 ) 143 )
142 144
143 # TODO use same logic as dispatch to perform prefix matching. 145 # TODO use same logic as dispatch to perform prefix matching.
144 if view not in views: 146 if view not in views:
145 raise error.Abort( 147 raise error.Abort(
146 _('unknown view: %s') % view, 148 _(b'unknown view: %s') % view,
147 hint=_('run "hg show" to see available views'), 149 hint=_(b'run "hg show" to see available views'),
148 ) 150 )
149 151
150 template = template or 'show' 152 template = template or b'show'
151 153
152 fn = views[view] 154 fn = views[view]
153 ui.pager('show') 155 ui.pager(b'show')
154 156
155 if fn._fmtopic: 157 if fn._fmtopic:
156 fmtopic = 'show%s' % fn._fmtopic 158 fmtopic = b'show%s' % fn._fmtopic
157 with ui.formatter(fmtopic, {'template': template}) as fm: 159 with ui.formatter(fmtopic, {b'template': template}) as fm:
158 return fn(ui, repo, fm) 160 return fn(ui, repo, fm)
159 elif fn._csettopic: 161 elif fn._csettopic:
160 ref = 'show%s' % fn._csettopic 162 ref = b'show%s' % fn._csettopic
161 spec = formatter.lookuptemplate(ui, ref, template) 163 spec = formatter.lookuptemplate(ui, ref, template)
162 displayer = logcmdutil.changesettemplater(ui, repo, spec, buffered=True) 164 displayer = logcmdutil.changesettemplater(ui, repo, spec, buffered=True)
163 return fn(ui, repo, displayer) 165 return fn(ui, repo, displayer)
164 else: 166 else:
165 return fn(ui, repo) 167 return fn(ui, repo)
166 168
167 169
168 @showview('bookmarks', fmtopic='bookmarks') 170 @showview(b'bookmarks', fmtopic=b'bookmarks')
169 def showbookmarks(ui, repo, fm): 171 def showbookmarks(ui, repo, fm):
170 """bookmarks and their associated changeset""" 172 """bookmarks and their associated changeset"""
171 marks = repo._bookmarks 173 marks = repo._bookmarks
172 if not len(marks): 174 if not len(marks):
173 # This is a bit hacky. Ideally, templates would have a way to 175 # This is a bit hacky. Ideally, templates would have a way to
174 # specify an empty output, but we shouldn't corrupt JSON while 176 # specify an empty output, but we shouldn't corrupt JSON while
175 # waiting for this functionality. 177 # waiting for this functionality.
176 if not isinstance(fm, formatter.jsonformatter): 178 if not isinstance(fm, formatter.jsonformatter):
177 ui.write(_('(no bookmarks set)\n')) 179 ui.write(_(b'(no bookmarks set)\n'))
178 return 180 return
179 181
180 revs = [repo[node].rev() for node in marks.values()] 182 revs = [repo[node].rev() for node in marks.values()]
181 active = repo._activebookmark 183 active = repo._activebookmark
182 longestname = max(len(b) for b in marks) 184 longestname = max(len(b) for b in marks)
183 nodelen = longestshortest(repo, revs) 185 nodelen = longestshortest(repo, revs)
184 186
185 for bm, node in sorted(marks.items()): 187 for bm, node in sorted(marks.items()):
186 fm.startitem() 188 fm.startitem()
187 fm.context(ctx=repo[node]) 189 fm.context(ctx=repo[node])
188 fm.write('bookmark', '%s', bm) 190 fm.write(b'bookmark', b'%s', bm)
189 fm.write('node', fm.hexfunc(node), fm.hexfunc(node)) 191 fm.write(b'node', fm.hexfunc(node), fm.hexfunc(node))
190 fm.data( 192 fm.data(
191 active=bm == active, longestbookmarklen=longestname, nodelen=nodelen 193 active=bm == active, longestbookmarklen=longestname, nodelen=nodelen
192 ) 194 )
193 195
194 196
195 @showview('stack', csettopic='stack') 197 @showview(b'stack', csettopic=b'stack')
196 def showstack(ui, repo, displayer): 198 def showstack(ui, repo, displayer):
197 """current line of work""" 199 """current line of work"""
198 wdirctx = repo['.'] 200 wdirctx = repo[b'.']
199 if wdirctx.rev() == nullrev: 201 if wdirctx.rev() == nullrev:
200 raise error.Abort( 202 raise error.Abort(
201 _('stack view only available when there is a ' 'working directory') 203 _(
204 b'stack view only available when there is a '
205 b'working directory'
206 )
202 ) 207 )
203 208
204 if wdirctx.phase() == phases.public: 209 if wdirctx.phase() == phases.public:
205 ui.write( 210 ui.write(
206 _( 211 _(
207 '(empty stack; working directory parent is a published ' 212 b'(empty stack; working directory parent is a published '
208 'changeset)\n' 213 b'changeset)\n'
209 ) 214 )
210 ) 215 )
211 return 216 return
212 217
213 # TODO extract "find stack" into a function to facilitate 218 # TODO extract "find stack" into a function to facilitate
218 223
219 if baserev is None: 224 if baserev is None:
220 baserev = wdirctx.rev() 225 baserev = wdirctx.rev()
221 stackrevs = {wdirctx.rev()} 226 stackrevs = {wdirctx.rev()}
222 else: 227 else:
223 stackrevs = set(repo.revs('%d::.', baserev)) 228 stackrevs = set(repo.revs(b'%d::.', baserev))
224 229
225 ctx = repo[baserev] 230 ctx = repo[baserev]
226 if ctx.p1().rev() != nullrev: 231 if ctx.p1().rev() != nullrev:
227 basectx = ctx.p1() 232 basectx = ctx.p1()
228 233
254 # merge or rebase targets. 259 # merge or rebase targets.
255 if basectx: 260 if basectx:
256 # TODO make this customizable? 261 # TODO make this customizable?
257 newheads = set( 262 newheads = set(
258 repo.revs( 263 repo.revs(
259 'heads(%d::) - %ld - not public()', basectx.rev(), stackrevs 264 b'heads(%d::) - %ld - not public()', basectx.rev(), stackrevs
260 ) 265 )
261 ) 266 )
262 else: 267 else:
263 newheads = set() 268 newheads = set()
264 269
265 allrevs = set(stackrevs) | newheads | {baserev} 270 allrevs = set(stackrevs) | newheads | {baserev}
266 nodelen = longestshortest(repo, allrevs) 271 nodelen = longestshortest(repo, allrevs)
267 272
268 try: 273 try:
269 cmdutil.findcmd('rebase', commands.table) 274 cmdutil.findcmd(b'rebase', commands.table)
270 haverebase = True 275 haverebase = True
271 except (error.AmbiguousCommand, error.UnknownCommand): 276 except (error.AmbiguousCommand, error.UnknownCommand):
272 haverebase = False 277 haverebase = False
273 278
274 # TODO use templating. 279 # TODO use templating.
276 # our simplicity and the customizations required. 281 # our simplicity and the customizations required.
277 # TODO use proper graph symbols from graphmod 282 # TODO use proper graph symbols from graphmod
278 283
279 tres = formatter.templateresources(ui, repo) 284 tres = formatter.templateresources(ui, repo)
280 shortesttmpl = formatter.maketemplater( 285 shortesttmpl = formatter.maketemplater(
281 ui, '{shortest(node, %d)}' % nodelen, resources=tres 286 ui, b'{shortest(node, %d)}' % nodelen, resources=tres
282 ) 287 )
283 288
284 def shortest(ctx): 289 def shortest(ctx):
285 return shortesttmpl.renderdefault({'ctx': ctx, 'node': ctx.hex()}) 290 return shortesttmpl.renderdefault({b'ctx': ctx, b'node': ctx.hex()})
286 291
287 # We write out new heads to aid in DAG awareness and to help with decision 292 # We write out new heads to aid in DAG awareness and to help with decision
288 # making on how the stack should be reconciled with commits made since the 293 # making on how the stack should be reconciled with commits made since the
289 # branch point. 294 # branch point.
290 if newheads: 295 if newheads:
305 310
306 for i, rev in enumerate(sortedheads): 311 for i, rev in enumerate(sortedheads):
307 ctx = repo[rev] 312 ctx = repo[rev]
308 313
309 if i: 314 if i:
310 ui.write(': ') 315 ui.write(b': ')
311 else: 316 else:
312 ui.write(' ') 317 ui.write(b' ')
313 318
314 ui.write('o ') 319 ui.write(b'o ')
315 displayer.show(ctx, nodelen=nodelen) 320 displayer.show(ctx, nodelen=nodelen)
316 displayer.flush(ctx) 321 displayer.flush(ctx)
317 ui.write('\n') 322 ui.write(b'\n')
318 323
319 if i: 324 if i:
320 ui.write(':/') 325 ui.write(b':/')
321 else: 326 else:
322 ui.write(' /') 327 ui.write(b' /')
323 328
324 ui.write(' (') 329 ui.write(b' (')
325 ui.write( 330 ui.write(
326 _('%d commits ahead') % revdistance[rev], 331 _(b'%d commits ahead') % revdistance[rev],
327 label='stack.commitdistance', 332 label=b'stack.commitdistance',
328 ) 333 )
329 334
330 if haverebase: 335 if haverebase:
331 # TODO may be able to omit --source in some scenarios 336 # TODO may be able to omit --source in some scenarios
332 ui.write('; ') 337 ui.write(b'; ')
333 ui.write( 338 ui.write(
334 ( 339 (
335 'hg rebase --source %s --dest %s' 340 b'hg rebase --source %s --dest %s'
336 % (shortest(sourcectx), shortest(ctx)) 341 % (shortest(sourcectx), shortest(ctx))
337 ), 342 ),
338 label='stack.rebasehint', 343 label=b'stack.rebasehint',
339 ) 344 )
340 345
341 ui.write(')\n') 346 ui.write(b')\n')
342 347
343 ui.write(':\n: ') 348 ui.write(b':\n: ')
344 ui.write(_('(stack head)\n'), label='stack.label') 349 ui.write(_(b'(stack head)\n'), label=b'stack.label')
345 350
346 if branchpointattip: 351 if branchpointattip:
347 ui.write(' \\ / ') 352 ui.write(b' \\ / ')
348 ui.write(_('(multiple children)\n'), label='stack.label') 353 ui.write(_(b'(multiple children)\n'), label=b'stack.label')
349 ui.write(' |\n') 354 ui.write(b' |\n')
350 355
351 for rev in stackrevs: 356 for rev in stackrevs:
352 ctx = repo[rev] 357 ctx = repo[rev]
353 symbol = '@' if rev == wdirctx.rev() else 'o' 358 symbol = b'@' if rev == wdirctx.rev() else b'o'
354 359
355 if newheads: 360 if newheads:
356 ui.write(': ') 361 ui.write(b': ')
357 else: 362 else:
358 ui.write(' ') 363 ui.write(b' ')
359 364
360 ui.write(symbol, ' ') 365 ui.write(symbol, b' ')
361 displayer.show(ctx, nodelen=nodelen) 366 displayer.show(ctx, nodelen=nodelen)
362 displayer.flush(ctx) 367 displayer.flush(ctx)
363 ui.write('\n') 368 ui.write(b'\n')
364 369
365 # TODO display histedit hint? 370 # TODO display histedit hint?
366 371
367 if basectx: 372 if basectx:
368 # Vertically and horizontally separate stack base from parent 373 # Vertically and horizontally separate stack base from parent
369 # to reinforce stack boundary. 374 # to reinforce stack boundary.
370 if newheads: 375 if newheads:
371 ui.write(':/ ') 376 ui.write(b':/ ')
372 else: 377 else:
373 ui.write(' / ') 378 ui.write(b' / ')
374 379
375 ui.write(_('(stack base)'), '\n', label='stack.label') 380 ui.write(_(b'(stack base)'), b'\n', label=b'stack.label')
376 ui.write('o ') 381 ui.write(b'o ')
377 382
378 displayer.show(basectx, nodelen=nodelen) 383 displayer.show(basectx, nodelen=nodelen)
379 displayer.flush(basectx) 384 displayer.flush(basectx)
380 ui.write('\n') 385 ui.write(b'\n')
381 386
382 387
383 @revsetpredicate('_underway([commitage[, headage]])') 388 @revsetpredicate(b'_underway([commitage[, headage]])')
384 def underwayrevset(repo, subset, x): 389 def underwayrevset(repo, subset, x):
385 args = revset.getargsdict(x, 'underway', 'commitage headage') 390 args = revset.getargsdict(x, b'underway', b'commitage headage')
386 if 'commitage' not in args: 391 if b'commitage' not in args:
387 args['commitage'] = None 392 args[b'commitage'] = None
388 if 'headage' not in args: 393 if b'headage' not in args:
389 args['headage'] = None 394 args[b'headage'] = None
390 395
391 # We assume callers of this revset add a topographical sort on the 396 # We assume callers of this revset add a topographical sort on the
392 # result. This means there is no benefit to making the revset lazy 397 # result. This means there is no benefit to making the revset lazy
393 # since the topographical sort needs to consume all revs. 398 # since the topographical sort needs to consume all revs.
394 # 399 #
397 402
398 # Mutable changesets (non-public) are the most important changesets 403 # Mutable changesets (non-public) are the most important changesets
399 # to return. ``not public()`` will also pull in obsolete changesets if 404 # to return. ``not public()`` will also pull in obsolete changesets if
400 # there is a non-obsolete changeset with obsolete ancestors. This is 405 # there is a non-obsolete changeset with obsolete ancestors. This is
401 # why we exclude obsolete changesets from this query. 406 # why we exclude obsolete changesets from this query.
402 rs = 'not public() and not obsolete()' 407 rs = b'not public() and not obsolete()'
403 rsargs = [] 408 rsargs = []
404 if args['commitage']: 409 if args[b'commitage']:
405 rs += ' and date(%s)' 410 rs += b' and date(%s)'
406 rsargs.append( 411 rsargs.append(
407 revsetlang.getstring( 412 revsetlang.getstring(
408 args['commitage'], _('commitage requires a string') 413 args[b'commitage'], _(b'commitage requires a string')
409 ) 414 )
410 ) 415 )
411 416
412 mutable = repo.revs(rs, *rsargs) 417 mutable = repo.revs(rs, *rsargs)
413 relevant = revset.baseset(mutable) 418 relevant = revset.baseset(mutable)
414 419
415 # Add parents of mutable changesets to provide context. 420 # Add parents of mutable changesets to provide context.
416 relevant += repo.revs('parents(%ld)', mutable) 421 relevant += repo.revs(b'parents(%ld)', mutable)
417 422
418 # We also pull in (public) heads if they a) aren't closing a branch 423 # We also pull in (public) heads if they a) aren't closing a branch
419 # b) are recent. 424 # b) are recent.
420 rs = 'head() and not closed()' 425 rs = b'head() and not closed()'
421 rsargs = [] 426 rsargs = []
422 if args['headage']: 427 if args[b'headage']:
423 rs += ' and date(%s)' 428 rs += b' and date(%s)'
424 rsargs.append( 429 rsargs.append(
425 revsetlang.getstring( 430 revsetlang.getstring(
426 args['headage'], _('headage requires a string') 431 args[b'headage'], _(b'headage requires a string')
427 ) 432 )
428 ) 433 )
429 434
430 relevant += repo.revs(rs, *rsargs) 435 relevant += repo.revs(rs, *rsargs)
431 436
432 # Add working directory parent. 437 # Add working directory parent.
433 wdirrev = repo['.'].rev() 438 wdirrev = repo[b'.'].rev()
434 if wdirrev != nullrev: 439 if wdirrev != nullrev:
435 relevant += revset.baseset({wdirrev}) 440 relevant += revset.baseset({wdirrev})
436 441
437 return subset & relevant 442 return subset & relevant
438 443
439 444
440 @showview('work', csettopic='work') 445 @showview(b'work', csettopic=b'work')
441 def showwork(ui, repo, displayer): 446 def showwork(ui, repo, displayer):
442 """changesets that aren't finished""" 447 """changesets that aren't finished"""
443 # TODO support date-based limiting when calling revset. 448 # TODO support date-based limiting when calling revset.
444 revs = repo.revs('sort(_underway(), topo)') 449 revs = repo.revs(b'sort(_underway(), topo)')
445 nodelen = longestshortest(repo, revs) 450 nodelen = longestshortest(repo, revs)
446 451
447 revdag = graphmod.dagwalker(repo, revs) 452 revdag = graphmod.dagwalker(repo, revs)
448 453
449 ui.setconfig('experimental', 'graphshorten', True) 454 ui.setconfig(b'experimental', b'graphshorten', True)
450 logcmdutil.displaygraph( 455 logcmdutil.displaygraph(
451 ui, 456 ui,
452 repo, 457 repo,
453 revdag, 458 revdag,
454 displayer, 459 displayer,
455 graphmod.asciiedges, 460 graphmod.asciiedges,
456 props={'nodelen': nodelen}, 461 props={b'nodelen': nodelen},
457 ) 462 )
458 463
459 464
460 def extsetup(ui): 465 def extsetup(ui):
461 # Alias `hg <prefix><view>` to `hg show <view>`. 466 # Alias `hg <prefix><view>` to `hg show <view>`.
462 for prefix in ui.configlist('commands', 'show.aliasprefix'): 467 for prefix in ui.configlist(b'commands', b'show.aliasprefix'):
463 for view in showview._table: 468 for view in showview._table:
464 name = '%s%s' % (prefix, view) 469 name = b'%s%s' % (prefix, view)
465 470
466 choice, allcommands = cmdutil.findpossible( 471 choice, allcommands = cmdutil.findpossible(
467 name, commands.table, strict=True 472 name, commands.table, strict=True
468 ) 473 )
469 474
470 # This alias is already a command name. Don't set it. 475 # This alias is already a command name. Don't set it.
471 if name in choice: 476 if name in choice:
472 continue 477 continue
473 478
474 # Same for aliases. 479 # Same for aliases.
475 if ui.config('alias', name, None): 480 if ui.config(b'alias', name, None):
476 continue 481 continue
477 482
478 ui.setconfig('alias', name, 'show %s' % view, source='show') 483 ui.setconfig(b'alias', name, b'show %s' % view, source=b'show')
479 484
480 485
481 def longestshortest(repo, revs, minlen=4): 486 def longestshortest(repo, revs, minlen=4):
482 """Return the length of the longest shortest node to identify revisions. 487 """Return the length of the longest shortest node to identify revisions.
483 488
514 pycompat.sysstr(key.ljust(longest)), 519 pycompat.sysstr(key.ljust(longest)),
515 showview._table[key]._origdoc, 520 showview._table[key]._origdoc,
516 ) 521 )
517 ) 522 )
518 523
519 cmdtable['show'][0].__doc__ = pycompat.sysstr('%s\n\n%s\n ') % ( 524 cmdtable[b'show'][0].__doc__ = pycompat.sysstr(b'%s\n\n%s\n ') % (
520 cmdtable['show'][0].__doc__.rstrip(), 525 cmdtable[b'show'][0].__doc__.rstrip(),
521 pycompat.sysstr('\n\n').join(entries), 526 pycompat.sysstr(b'\n\n').join(entries),
522 ) 527 )
523 528
524 529
525 _updatedocstring() 530 _updatedocstring()