##// END OF EJS Templates
show: use consistent (and possibly shorter) node lengths...
Gregory Szorc -
r34192:e6b5e732 default
parent child Browse files
Show More
@@ -1,439 +1,465 b''
1 # show.py - Extension implementing `hg show`
1 # show.py - Extension implementing `hg show`
2 #
2 #
3 # Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """unified command to show various repository information (EXPERIMENTAL)
8 """unified command to show various repository information (EXPERIMENTAL)
9
9
10 This extension provides the :hg:`show` command, which provides a central
10 This extension provides the :hg:`show` command, which provides a central
11 command for displaying commonly-accessed repository data and views of that
11 command for displaying commonly-accessed repository data and views of that
12 data.
12 data.
13
13
14 The following config options can influence operation.
14 The following config options can influence operation.
15
15
16 ``commands``
16 ``commands``
17 ------------
17 ------------
18
18
19 ``show.aliasprefix``
19 ``show.aliasprefix``
20 List of strings that will register aliases for views. e.g. ``s`` will
20 List of strings that will register aliases for views. e.g. ``s`` will
21 effectively set config options ``alias.s<view> = show <view>`` for all
21 effectively set config options ``alias.s<view> = show <view>`` for all
22 views. i.e. `hg swork` would execute `hg show work`.
22 views. i.e. `hg swork` would execute `hg show work`.
23
23
24 Aliases that would conflict with existing registrations will not be
24 Aliases that would conflict with existing registrations will not be
25 performed.
25 performed.
26 """
26 """
27
27
28 from __future__ import absolute_import
28 from __future__ import absolute_import
29
29
30 from mercurial.i18n import _
30 from mercurial.i18n import _
31 from mercurial.node import nullrev
31 from mercurial.node import nullrev
32 from mercurial import (
32 from mercurial import (
33 cmdutil,
33 cmdutil,
34 commands,
34 commands,
35 destutil,
35 destutil,
36 error,
36 error,
37 formatter,
37 formatter,
38 graphmod,
38 graphmod,
39 phases,
39 phases,
40 pycompat,
40 pycompat,
41 registrar,
41 registrar,
42 revset,
42 revset,
43 revsetlang,
43 revsetlang,
44 )
44 )
45
45
46 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
46 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
47 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
47 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
48 # be specifying the version(s) of Mercurial they are tested with, or
48 # be specifying the version(s) of Mercurial they are tested with, or
49 # leave the attribute unspecified.
49 # leave the attribute unspecified.
50 testedwith = 'ships-with-hg-core'
50 testedwith = 'ships-with-hg-core'
51
51
52 cmdtable = {}
52 cmdtable = {}
53 command = registrar.command(cmdtable)
53 command = registrar.command(cmdtable)
54 revsetpredicate = registrar.revsetpredicate()
54 revsetpredicate = registrar.revsetpredicate()
55
55
56 class showcmdfunc(registrar._funcregistrarbase):
56 class showcmdfunc(registrar._funcregistrarbase):
57 """Register a function to be invoked for an `hg show <thing>`."""
57 """Register a function to be invoked for an `hg show <thing>`."""
58
58
59 # Used by _formatdoc().
59 # Used by _formatdoc().
60 _docformat = '%s -- %s'
60 _docformat = '%s -- %s'
61
61
62 def _extrasetup(self, name, func, fmtopic=None, csettopic=None):
62 def _extrasetup(self, name, func, fmtopic=None, csettopic=None):
63 """Called with decorator arguments to register a show view.
63 """Called with decorator arguments to register a show view.
64
64
65 ``name`` is the sub-command name.
65 ``name`` is the sub-command name.
66
66
67 ``func`` is the function being decorated.
67 ``func`` is the function being decorated.
68
68
69 ``fmtopic`` is the topic in the style that will be rendered for
69 ``fmtopic`` is the topic in the style that will be rendered for
70 this view.
70 this view.
71
71
72 ``csettopic`` is the topic in the style to be used for a changeset
72 ``csettopic`` is the topic in the style to be used for a changeset
73 printer.
73 printer.
74
74
75 If ``fmtopic`` is specified, the view function will receive a
75 If ``fmtopic`` is specified, the view function will receive a
76 formatter instance. If ``csettopic`` is specified, the view
76 formatter instance. If ``csettopic`` is specified, the view
77 function will receive a changeset printer.
77 function will receive a changeset printer.
78 """
78 """
79 func._fmtopic = fmtopic
79 func._fmtopic = fmtopic
80 func._csettopic = csettopic
80 func._csettopic = csettopic
81
81
82 showview = showcmdfunc()
82 showview = showcmdfunc()
83
83
84 @command('show', [
84 @command('show', [
85 # TODO: Switch this template flag to use cmdutil.formatteropts if
85 # TODO: Switch this template flag to use cmdutil.formatteropts if
86 # 'hg show' becomes stable before --template/-T is stable. For now,
86 # 'hg show' becomes stable before --template/-T is stable. For now,
87 # we are putting it here without the '(EXPERIMENTAL)' flag because it
87 # we are putting it here without the '(EXPERIMENTAL)' flag because it
88 # is an important part of the 'hg show' user experience and the entire
88 # is an important part of the 'hg show' user experience and the entire
89 # 'hg show' experience is experimental.
89 # 'hg show' experience is experimental.
90 ('T', 'template', '', ('display with template'), _('TEMPLATE')),
90 ('T', 'template', '', ('display with template'), _('TEMPLATE')),
91 ], _('VIEW'))
91 ], _('VIEW'))
92 def show(ui, repo, view=None, template=None):
92 def show(ui, repo, view=None, template=None):
93 """show various repository information
93 """show various repository information
94
94
95 A requested view of repository data is displayed.
95 A requested view of repository data is displayed.
96
96
97 If no view is requested, the list of available views is shown and the
97 If no view is requested, the list of available views is shown and the
98 command aborts.
98 command aborts.
99
99
100 .. note::
100 .. note::
101
101
102 There are no backwards compatibility guarantees for the output of this
102 There are no backwards compatibility guarantees for the output of this
103 command. Output may change in any future Mercurial release.
103 command. Output may change in any future Mercurial release.
104
104
105 Consumers wanting stable command output should specify a template via
105 Consumers wanting stable command output should specify a template via
106 ``-T/--template``.
106 ``-T/--template``.
107
107
108 List of available views:
108 List of available views:
109 """
109 """
110 if ui.plain() and not template:
110 if ui.plain() and not template:
111 hint = _('invoke with -T/--template to control output format')
111 hint = _('invoke with -T/--template to control output format')
112 raise error.Abort(_('must specify a template in plain mode'), hint=hint)
112 raise error.Abort(_('must specify a template in plain mode'), hint=hint)
113
113
114 views = showview._table
114 views = showview._table
115
115
116 if not view:
116 if not view:
117 ui.pager('show')
117 ui.pager('show')
118 # TODO consider using formatter here so available views can be
118 # TODO consider using formatter here so available views can be
119 # rendered to custom format.
119 # rendered to custom format.
120 ui.write(_('available views:\n'))
120 ui.write(_('available views:\n'))
121 ui.write('\n')
121 ui.write('\n')
122
122
123 for name, func in sorted(views.items()):
123 for name, func in sorted(views.items()):
124 ui.write(('%s\n') % func.__doc__)
124 ui.write(('%s\n') % func.__doc__)
125
125
126 ui.write('\n')
126 ui.write('\n')
127 raise error.Abort(_('no view requested'),
127 raise error.Abort(_('no view requested'),
128 hint=_('use "hg show VIEW" to choose a view'))
128 hint=_('use "hg show VIEW" to choose a view'))
129
129
130 # TODO use same logic as dispatch to perform prefix matching.
130 # TODO use same logic as dispatch to perform prefix matching.
131 if view not in views:
131 if view not in views:
132 raise error.Abort(_('unknown view: %s') % view,
132 raise error.Abort(_('unknown view: %s') % view,
133 hint=_('run "hg show" to see available views'))
133 hint=_('run "hg show" to see available views'))
134
134
135 template = template or 'show'
135 template = template or 'show'
136
136
137 fn = views[view]
137 fn = views[view]
138 ui.pager('show')
138 ui.pager('show')
139
139
140 if fn._fmtopic:
140 if fn._fmtopic:
141 fmtopic = 'show%s' % fn._fmtopic
141 fmtopic = 'show%s' % fn._fmtopic
142 with ui.formatter(fmtopic, {'template': template}) as fm:
142 with ui.formatter(fmtopic, {'template': template}) as fm:
143 return fn(ui, repo, fm)
143 return fn(ui, repo, fm)
144 elif fn._csettopic:
144 elif fn._csettopic:
145 ref = 'show%s' % fn._csettopic
145 ref = 'show%s' % fn._csettopic
146 spec = formatter.lookuptemplate(ui, ref, template)
146 spec = formatter.lookuptemplate(ui, ref, template)
147 displayer = cmdutil.changeset_templater(ui, repo, spec, buffered=True)
147 displayer = cmdutil.changeset_templater(ui, repo, spec, buffered=True)
148 return fn(ui, repo, displayer)
148 return fn(ui, repo, displayer)
149 else:
149 else:
150 return fn(ui, repo)
150 return fn(ui, repo)
151
151
152 @showview('bookmarks', fmtopic='bookmarks')
152 @showview('bookmarks', fmtopic='bookmarks')
153 def showbookmarks(ui, repo, fm):
153 def showbookmarks(ui, repo, fm):
154 """bookmarks and their associated changeset"""
154 """bookmarks and their associated changeset"""
155 marks = repo._bookmarks
155 marks = repo._bookmarks
156 if not len(marks):
156 if not len(marks):
157 # This is a bit hacky. Ideally, templates would have a way to
157 # This is a bit hacky. Ideally, templates would have a way to
158 # specify an empty output, but we shouldn't corrupt JSON while
158 # specify an empty output, but we shouldn't corrupt JSON while
159 # waiting for this functionality.
159 # waiting for this functionality.
160 if not isinstance(fm, formatter.jsonformatter):
160 if not isinstance(fm, formatter.jsonformatter):
161 ui.write(_('(no bookmarks set)\n'))
161 ui.write(_('(no bookmarks set)\n'))
162 return
162 return
163
163
164 revs = [repo[node].rev() for node in marks.values()]
164 active = repo._activebookmark
165 active = repo._activebookmark
165 longestname = max(len(b) for b in marks)
166 longestname = max(len(b) for b in marks)
166 # TODO consider exposing longest shortest(node).
167 nodelen = longestshortest(repo, revs)
167
168
168 for bm, node in sorted(marks.items()):
169 for bm, node in sorted(marks.items()):
169 fm.startitem()
170 fm.startitem()
170 fm.context(ctx=repo[node])
171 fm.context(ctx=repo[node])
171 fm.write('bookmark', '%s', bm)
172 fm.write('bookmark', '%s', bm)
172 fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
173 fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
173 fm.data(active=bm == active,
174 fm.data(active=bm == active,
174 longestbookmarklen=longestname,
175 longestbookmarklen=longestname,
175 nodelen=5)
176 nodelen=nodelen)
176
177
177 @showview('stack', csettopic='stack')
178 @showview('stack', csettopic='stack')
178 def showstack(ui, repo, displayer):
179 def showstack(ui, repo, displayer):
179 """current line of work"""
180 """current line of work"""
180 wdirctx = repo['.']
181 wdirctx = repo['.']
181 if wdirctx.rev() == nullrev:
182 if wdirctx.rev() == nullrev:
182 raise error.Abort(_('stack view only available when there is a '
183 raise error.Abort(_('stack view only available when there is a '
183 'working directory'))
184 'working directory'))
184
185
185 if wdirctx.phase() == phases.public:
186 if wdirctx.phase() == phases.public:
186 ui.write(_('(empty stack; working directory parent is a published '
187 ui.write(_('(empty stack; working directory parent is a published '
187 'changeset)\n'))
188 'changeset)\n'))
188 return
189 return
189
190
190 # TODO extract "find stack" into a function to facilitate
191 # TODO extract "find stack" into a function to facilitate
191 # customization and reuse.
192 # customization and reuse.
192
193
193 baserev = destutil.stackbase(ui, repo)
194 baserev = destutil.stackbase(ui, repo)
194 basectx = None
195 basectx = None
195
196
196 if baserev is None:
197 if baserev is None:
197 baserev = wdirctx.rev()
198 baserev = wdirctx.rev()
198 stackrevs = {wdirctx.rev()}
199 stackrevs = {wdirctx.rev()}
199 else:
200 else:
200 stackrevs = set(repo.revs('%d::.', baserev))
201 stackrevs = set(repo.revs('%d::.', baserev))
201
202
202 ctx = repo[baserev]
203 ctx = repo[baserev]
203 if ctx.p1().rev() != nullrev:
204 if ctx.p1().rev() != nullrev:
204 basectx = ctx.p1()
205 basectx = ctx.p1()
205
206
206 # And relevant descendants.
207 # And relevant descendants.
207 branchpointattip = False
208 branchpointattip = False
208 cl = repo.changelog
209 cl = repo.changelog
209
210
210 for rev in cl.descendants([wdirctx.rev()]):
211 for rev in cl.descendants([wdirctx.rev()]):
211 ctx = repo[rev]
212 ctx = repo[rev]
212
213
213 # Will only happen if . is public.
214 # Will only happen if . is public.
214 if ctx.phase() == phases.public:
215 if ctx.phase() == phases.public:
215 break
216 break
216
217
217 stackrevs.add(ctx.rev())
218 stackrevs.add(ctx.rev())
218
219
219 # ctx.children() within a function iterating on descandants
220 # ctx.children() within a function iterating on descandants
220 # potentially has severe performance concerns because revlog.children()
221 # potentially has severe performance concerns because revlog.children()
221 # iterates over all revisions after ctx's node. However, the number of
222 # iterates over all revisions after ctx's node. However, the number of
222 # draft changesets should be a reasonably small number. So even if
223 # draft changesets should be a reasonably small number. So even if
223 # this is quadratic, the perf impact should be minimal.
224 # this is quadratic, the perf impact should be minimal.
224 if len(ctx.children()) > 1:
225 if len(ctx.children()) > 1:
225 branchpointattip = True
226 branchpointattip = True
226 break
227 break
227
228
228 stackrevs = list(sorted(stackrevs, reverse=True))
229 stackrevs = list(sorted(stackrevs, reverse=True))
229
230
230 # Find likely target heads for the current stack. These are likely
231 # Find likely target heads for the current stack. These are likely
231 # merge or rebase targets.
232 # merge or rebase targets.
232 if basectx:
233 if basectx:
233 # TODO make this customizable?
234 # TODO make this customizable?
234 newheads = set(repo.revs('heads(%d::) - %ld - not public()',
235 newheads = set(repo.revs('heads(%d::) - %ld - not public()',
235 basectx.rev(), stackrevs))
236 basectx.rev(), stackrevs))
236 else:
237 else:
237 newheads = set()
238 newheads = set()
238
239
240 allrevs = set(stackrevs) | newheads | set([baserev])
241 nodelen = longestshortest(repo, allrevs)
242
239 try:
243 try:
240 cmdutil.findcmd('rebase', commands.table)
244 cmdutil.findcmd('rebase', commands.table)
241 haverebase = True
245 haverebase = True
242 except (error.AmbiguousCommand, error.UnknownCommand):
246 except (error.AmbiguousCommand, error.UnknownCommand):
243 haverebase = False
247 haverebase = False
244
248
245 # TODO use templating.
249 # TODO use templating.
246 # TODO consider using graphmod. But it may not be necessary given
250 # TODO consider using graphmod. But it may not be necessary given
247 # our simplicity and the customizations required.
251 # our simplicity and the customizations required.
248 # TODO use proper graph symbols from graphmod
252 # TODO use proper graph symbols from graphmod
249
253
250 shortesttmpl = formatter.maketemplater(ui, '{shortest(node, 5)}')
254 shortesttmpl = formatter.maketemplater(ui, '{shortest(node, %d)}' % nodelen)
251 def shortest(ctx):
255 def shortest(ctx):
252 return shortesttmpl.render({'ctx': ctx, 'node': ctx.hex()})
256 return shortesttmpl.render({'ctx': ctx, 'node': ctx.hex()})
253
257
254 # We write out new heads to aid in DAG awareness and to help with decision
258 # We write out new heads to aid in DAG awareness and to help with decision
255 # making on how the stack should be reconciled with commits made since the
259 # making on how the stack should be reconciled with commits made since the
256 # branch point.
260 # branch point.
257 if newheads:
261 if newheads:
258 # Calculate distance from base so we can render the count and so we can
262 # Calculate distance from base so we can render the count and so we can
259 # sort display order by commit distance.
263 # sort display order by commit distance.
260 revdistance = {}
264 revdistance = {}
261 for head in newheads:
265 for head in newheads:
262 # There is some redundancy in DAG traversal here and therefore
266 # There is some redundancy in DAG traversal here and therefore
263 # room to optimize.
267 # room to optimize.
264 ancestors = cl.ancestors([head], stoprev=basectx.rev())
268 ancestors = cl.ancestors([head], stoprev=basectx.rev())
265 revdistance[head] = len(list(ancestors))
269 revdistance[head] = len(list(ancestors))
266
270
267 sourcectx = repo[stackrevs[-1]]
271 sourcectx = repo[stackrevs[-1]]
268
272
269 sortedheads = sorted(newheads, key=lambda x: revdistance[x],
273 sortedheads = sorted(newheads, key=lambda x: revdistance[x],
270 reverse=True)
274 reverse=True)
271
275
272 for i, rev in enumerate(sortedheads):
276 for i, rev in enumerate(sortedheads):
273 ctx = repo[rev]
277 ctx = repo[rev]
274
278
275 if i:
279 if i:
276 ui.write(': ')
280 ui.write(': ')
277 else:
281 else:
278 ui.write(' ')
282 ui.write(' ')
279
283
280 ui.write(('o '))
284 ui.write(('o '))
281 displayer.show(ctx, nodelen=5)
285 displayer.show(ctx, nodelen=nodelen)
282 displayer.flush(ctx)
286 displayer.flush(ctx)
283 ui.write('\n')
287 ui.write('\n')
284
288
285 if i:
289 if i:
286 ui.write(':/')
290 ui.write(':/')
287 else:
291 else:
288 ui.write(' /')
292 ui.write(' /')
289
293
290 ui.write(' (')
294 ui.write(' (')
291 ui.write(_('%d commits ahead') % revdistance[rev],
295 ui.write(_('%d commits ahead') % revdistance[rev],
292 label='stack.commitdistance')
296 label='stack.commitdistance')
293
297
294 if haverebase:
298 if haverebase:
295 # TODO may be able to omit --source in some scenarios
299 # TODO may be able to omit --source in some scenarios
296 ui.write('; ')
300 ui.write('; ')
297 ui.write(('hg rebase --source %s --dest %s' % (
301 ui.write(('hg rebase --source %s --dest %s' % (
298 shortest(sourcectx), shortest(ctx))),
302 shortest(sourcectx), shortest(ctx))),
299 label='stack.rebasehint')
303 label='stack.rebasehint')
300
304
301 ui.write(')\n')
305 ui.write(')\n')
302
306
303 ui.write(':\n: ')
307 ui.write(':\n: ')
304 ui.write(_('(stack head)\n'), label='stack.label')
308 ui.write(_('(stack head)\n'), label='stack.label')
305
309
306 if branchpointattip:
310 if branchpointattip:
307 ui.write(' \\ / ')
311 ui.write(' \\ / ')
308 ui.write(_('(multiple children)\n'), label='stack.label')
312 ui.write(_('(multiple children)\n'), label='stack.label')
309 ui.write(' |\n')
313 ui.write(' |\n')
310
314
311 for rev in stackrevs:
315 for rev in stackrevs:
312 ctx = repo[rev]
316 ctx = repo[rev]
313 symbol = '@' if rev == wdirctx.rev() else 'o'
317 symbol = '@' if rev == wdirctx.rev() else 'o'
314
318
315 if newheads:
319 if newheads:
316 ui.write(': ')
320 ui.write(': ')
317 else:
321 else:
318 ui.write(' ')
322 ui.write(' ')
319
323
320 ui.write(symbol, ' ')
324 ui.write(symbol, ' ')
321 displayer.show(ctx, nodelen=5)
325 displayer.show(ctx, nodelen=nodelen)
322 displayer.flush(ctx)
326 displayer.flush(ctx)
323 ui.write('\n')
327 ui.write('\n')
324
328
325 # TODO display histedit hint?
329 # TODO display histedit hint?
326
330
327 if basectx:
331 if basectx:
328 # Vertically and horizontally separate stack base from parent
332 # Vertically and horizontally separate stack base from parent
329 # to reinforce stack boundary.
333 # to reinforce stack boundary.
330 if newheads:
334 if newheads:
331 ui.write(':/ ')
335 ui.write(':/ ')
332 else:
336 else:
333 ui.write(' / ')
337 ui.write(' / ')
334
338
335 ui.write(_('(stack base)'), '\n', label='stack.label')
339 ui.write(_('(stack base)'), '\n', label='stack.label')
336 ui.write(('o '))
340 ui.write(('o '))
337
341
338 displayer.show(basectx, nodelen=5)
342 displayer.show(basectx, nodelen=nodelen)
339 displayer.flush(basectx)
343 displayer.flush(basectx)
340 ui.write('\n')
344 ui.write('\n')
341
345
342 @revsetpredicate('_underway([commitage[, headage]])')
346 @revsetpredicate('_underway([commitage[, headage]])')
343 def underwayrevset(repo, subset, x):
347 def underwayrevset(repo, subset, x):
344 args = revset.getargsdict(x, 'underway', 'commitage headage')
348 args = revset.getargsdict(x, 'underway', 'commitage headage')
345 if 'commitage' not in args:
349 if 'commitage' not in args:
346 args['commitage'] = None
350 args['commitage'] = None
347 if 'headage' not in args:
351 if 'headage' not in args:
348 args['headage'] = None
352 args['headage'] = None
349
353
350 # We assume callers of this revset add a topographical sort on the
354 # We assume callers of this revset add a topographical sort on the
351 # result. This means there is no benefit to making the revset lazy
355 # result. This means there is no benefit to making the revset lazy
352 # since the topographical sort needs to consume all revs.
356 # since the topographical sort needs to consume all revs.
353 #
357 #
354 # With this in mind, we build up the set manually instead of constructing
358 # With this in mind, we build up the set manually instead of constructing
355 # a complex revset. This enables faster execution.
359 # a complex revset. This enables faster execution.
356
360
357 # Mutable changesets (non-public) are the most important changesets
361 # Mutable changesets (non-public) are the most important changesets
358 # to return. ``not public()`` will also pull in obsolete changesets if
362 # to return. ``not public()`` will also pull in obsolete changesets if
359 # there is a non-obsolete changeset with obsolete ancestors. This is
363 # there is a non-obsolete changeset with obsolete ancestors. This is
360 # why we exclude obsolete changesets from this query.
364 # why we exclude obsolete changesets from this query.
361 rs = 'not public() and not obsolete()'
365 rs = 'not public() and not obsolete()'
362 rsargs = []
366 rsargs = []
363 if args['commitage']:
367 if args['commitage']:
364 rs += ' and date(%s)'
368 rs += ' and date(%s)'
365 rsargs.append(revsetlang.getstring(args['commitage'],
369 rsargs.append(revsetlang.getstring(args['commitage'],
366 _('commitage requires a string')))
370 _('commitage requires a string')))
367
371
368 mutable = repo.revs(rs, *rsargs)
372 mutable = repo.revs(rs, *rsargs)
369 relevant = revset.baseset(mutable)
373 relevant = revset.baseset(mutable)
370
374
371 # Add parents of mutable changesets to provide context.
375 # Add parents of mutable changesets to provide context.
372 relevant += repo.revs('parents(%ld)', mutable)
376 relevant += repo.revs('parents(%ld)', mutable)
373
377
374 # We also pull in (public) heads if they a) aren't closing a branch
378 # We also pull in (public) heads if they a) aren't closing a branch
375 # b) are recent.
379 # b) are recent.
376 rs = 'head() and not closed()'
380 rs = 'head() and not closed()'
377 rsargs = []
381 rsargs = []
378 if args['headage']:
382 if args['headage']:
379 rs += ' and date(%s)'
383 rs += ' and date(%s)'
380 rsargs.append(revsetlang.getstring(args['headage'],
384 rsargs.append(revsetlang.getstring(args['headage'],
381 _('headage requires a string')))
385 _('headage requires a string')))
382
386
383 relevant += repo.revs(rs, *rsargs)
387 relevant += repo.revs(rs, *rsargs)
384
388
385 # Add working directory parent.
389 # Add working directory parent.
386 wdirrev = repo['.'].rev()
390 wdirrev = repo['.'].rev()
387 if wdirrev != nullrev:
391 if wdirrev != nullrev:
388 relevant += revset.baseset({wdirrev})
392 relevant += revset.baseset({wdirrev})
389
393
390 return subset & relevant
394 return subset & relevant
391
395
392 @showview('work', csettopic='work')
396 @showview('work', csettopic='work')
393 def showwork(ui, repo, displayer):
397 def showwork(ui, repo, displayer):
394 """changesets that aren't finished"""
398 """changesets that aren't finished"""
395 # TODO support date-based limiting when calling revset.
399 # TODO support date-based limiting when calling revset.
396 revs = repo.revs('sort(_underway(), topo)')
400 revs = repo.revs('sort(_underway(), topo)')
401 nodelen = longestshortest(repo, revs)
397
402
398 revdag = graphmod.dagwalker(repo, revs)
403 revdag = graphmod.dagwalker(repo, revs)
399
404
400 ui.setconfig('experimental', 'graphshorten', True)
405 ui.setconfig('experimental', 'graphshorten', True)
401 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges,
406 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges,
402 props={'nodelen': 5})
407 props={'nodelen': nodelen})
403
408
404 def extsetup(ui):
409 def extsetup(ui):
405 # Alias `hg <prefix><view>` to `hg show <view>`.
410 # Alias `hg <prefix><view>` to `hg show <view>`.
406 for prefix in ui.configlist('commands', 'show.aliasprefix'):
411 for prefix in ui.configlist('commands', 'show.aliasprefix'):
407 for view in showview._table:
412 for view in showview._table:
408 name = '%s%s' % (prefix, view)
413 name = '%s%s' % (prefix, view)
409
414
410 choice, allcommands = cmdutil.findpossible(name, commands.table,
415 choice, allcommands = cmdutil.findpossible(name, commands.table,
411 strict=True)
416 strict=True)
412
417
413 # This alias is already a command name. Don't set it.
418 # This alias is already a command name. Don't set it.
414 if name in choice:
419 if name in choice:
415 continue
420 continue
416
421
417 # Same for aliases.
422 # Same for aliases.
418 if ui.config('alias', name):
423 if ui.config('alias', name):
419 continue
424 continue
420
425
421 ui.setconfig('alias', name, 'show %s' % view, source='show')
426 ui.setconfig('alias', name, 'show %s' % view, source='show')
422
427
428 def longestshortest(repo, revs, minlen=4):
429 """Return the length of the longest shortest node to identify revisions.
430
431 The result of this function can be used with the ``shortest()`` template
432 function to ensure that a value is unique and unambiguous for a given
433 set of nodes.
434
435 The number of revisions in the repo is taken into account to prevent
436 a numeric node prefix from conflicting with an integer revision number.
437 If we fail to do this, a value of e.g. ``10023`` could mean either
438 revision 10023 or node ``10023abc...``.
439 """
440 tmpl = formatter.maketemplater(repo.ui, '{shortest(node, %d)}' % minlen)
441 lens = [minlen]
442 for rev in revs:
443 ctx = repo[rev]
444 shortest = tmpl.render({'ctx': ctx, 'node': ctx.hex()})
445 lens.append(len(shortest))
446
447 return max(lens)
448
423 # Adjust the docstring of the show command so it shows all registered views.
449 # Adjust the docstring of the show command so it shows all registered views.
424 # This is a bit hacky because it runs at the end of module load. When moved
450 # This is a bit hacky because it runs at the end of module load. When moved
425 # into core or when another extension wants to provide a view, we'll need
451 # into core or when another extension wants to provide a view, we'll need
426 # to do this more robustly.
452 # to do this more robustly.
427 # TODO make this more robust.
453 # TODO make this more robust.
428 def _updatedocstring():
454 def _updatedocstring():
429 longest = max(map(len, showview._table.keys()))
455 longest = max(map(len, showview._table.keys()))
430 entries = []
456 entries = []
431 for key in sorted(showview._table.keys()):
457 for key in sorted(showview._table.keys()):
432 entries.append(pycompat.sysstr(' %s %s' % (
458 entries.append(pycompat.sysstr(' %s %s' % (
433 key.ljust(longest), showview._table[key]._origdoc)))
459 key.ljust(longest), showview._table[key]._origdoc)))
434
460
435 cmdtable['show'][0].__doc__ = pycompat.sysstr('%s\n\n%s\n ') % (
461 cmdtable['show'][0].__doc__ = pycompat.sysstr('%s\n\n%s\n ') % (
436 cmdtable['show'][0].__doc__.rstrip(),
462 cmdtable['show'][0].__doc__.rstrip(),
437 pycompat.sysstr('\n\n').join(entries))
463 pycompat.sysstr('\n\n').join(entries))
438
464
439 _updatedocstring()
465 _updatedocstring()
@@ -1,220 +1,220 b''
1 $ cat >> $HGRCPATH << EOF
1 $ cat >> $HGRCPATH << EOF
2 > [extensions]
2 > [extensions]
3 > show =
3 > show =
4 > EOF
4 > EOF
5
5
6 $ hg init repo0
6 $ hg init repo0
7 $ cd repo0
7 $ cd repo0
8
8
9 Empty repo / no checkout results in error
9 Empty repo / no checkout results in error
10
10
11 $ hg show stack
11 $ hg show stack
12 abort: stack view only available when there is a working directory
12 abort: stack view only available when there is a working directory
13 [255]
13 [255]
14
14
15 Stack displays single draft changeset as root revision
15 Stack displays single draft changeset as root revision
16
16
17 $ echo 0 > foo
17 $ echo 0 > foo
18 $ hg -q commit -A -m 'commit 0'
18 $ hg -q commit -A -m 'commit 0'
19 $ hg show stack
19 $ hg show stack
20 @ 9f171 commit 0
20 @ 9f17 commit 0
21
21
22 Stack displays multiple draft changesets
22 Stack displays multiple draft changesets
23
23
24 $ echo 1 > foo
24 $ echo 1 > foo
25 $ hg commit -m 'commit 1'
25 $ hg commit -m 'commit 1'
26 $ echo 2 > foo
26 $ echo 2 > foo
27 $ hg commit -m 'commit 2'
27 $ hg commit -m 'commit 2'
28 $ echo 3 > foo
28 $ echo 3 > foo
29 $ hg commit -m 'commit 3'
29 $ hg commit -m 'commit 3'
30 $ echo 4 > foo
30 $ echo 4 > foo
31 $ hg commit -m 'commit 4'
31 $ hg commit -m 'commit 4'
32 $ hg show stack
32 $ hg show stack
33 @ 2737b commit 4
33 @ 2737 commit 4
34 o d1a69 commit 3
34 o d1a6 commit 3
35 o 128c8 commit 2
35 o 128c commit 2
36 o 181cc commit 1
36 o 181c commit 1
37 o 9f171 commit 0
37 o 9f17 commit 0
38
38
39 Public parent of draft base is displayed, separated from stack
39 Public parent of draft base is displayed, separated from stack
40
40
41 $ hg phase --public -r 0
41 $ hg phase --public -r 0
42 $ hg show stack
42 $ hg show stack
43 @ 2737b commit 4
43 @ 2737 commit 4
44 o d1a69 commit 3
44 o d1a6 commit 3
45 o 128c8 commit 2
45 o 128c commit 2
46 o 181cc commit 1
46 o 181c commit 1
47 / (stack base)
47 / (stack base)
48 o 9f171 commit 0
48 o 9f17 commit 0
49
49
50 $ hg phase --public -r 1
50 $ hg phase --public -r 1
51 $ hg show stack
51 $ hg show stack
52 @ 2737b commit 4
52 @ 2737 commit 4
53 o d1a69 commit 3
53 o d1a6 commit 3
54 o 128c8 commit 2
54 o 128c commit 2
55 / (stack base)
55 / (stack base)
56 o 181cc commit 1
56 o 181c commit 1
57
57
58 Draft descendants are shown
58 Draft descendants are shown
59
59
60 $ hg -q up 2
60 $ hg -q up 2
61 $ hg show stack
61 $ hg show stack
62 o 2737b commit 4
62 o 2737 commit 4
63 o d1a69 commit 3
63 o d1a6 commit 3
64 @ 128c8 commit 2
64 @ 128c commit 2
65 / (stack base)
65 / (stack base)
66 o 181cc commit 1
66 o 181c commit 1
67
67
68 $ hg -q up 3
68 $ hg -q up 3
69 $ hg show stack
69 $ hg show stack
70 o 2737b commit 4
70 o 2737 commit 4
71 @ d1a69 commit 3
71 @ d1a6 commit 3
72 o 128c8 commit 2
72 o 128c commit 2
73 / (stack base)
73 / (stack base)
74 o 181cc commit 1
74 o 181c commit 1
75
75
76 working dir on public changeset should display special message
76 working dir on public changeset should display special message
77
77
78 $ hg -q up 1
78 $ hg -q up 1
79 $ hg show stack
79 $ hg show stack
80 (empty stack; working directory parent is a published changeset)
80 (empty stack; working directory parent is a published changeset)
81
81
82 Branch point in descendants displayed at top of graph
82 Branch point in descendants displayed at top of graph
83
83
84 $ hg -q up 3
84 $ hg -q up 3
85 $ echo b > foo
85 $ echo b > foo
86 $ hg commit -m 'commit 5 (new dag branch)'
86 $ hg commit -m 'commit 5 (new dag branch)'
87 created new head
87 created new head
88 $ hg -q up 2
88 $ hg -q up 2
89 $ hg show stack
89 $ hg show stack
90 \ / (multiple children)
90 \ / (multiple children)
91 |
91 |
92 o d1a69 commit 3
92 o d1a6 commit 3
93 @ 128c8 commit 2
93 @ 128c commit 2
94 / (stack base)
94 / (stack base)
95 o 181cc commit 1
95 o 181c commit 1
96
96
97 $ cd ..
97 $ cd ..
98
98
99 Base is stopped at merges
99 Base is stopped at merges
100
100
101 $ hg init merge-base
101 $ hg init merge-base
102 $ cd merge-base
102 $ cd merge-base
103 $ echo 0 > foo
103 $ echo 0 > foo
104 $ hg -q commit -A -m initial
104 $ hg -q commit -A -m initial
105 $ echo h1 > foo
105 $ echo h1 > foo
106 $ hg commit -m 'head 1'
106 $ hg commit -m 'head 1'
107 $ hg -q up 0
107 $ hg -q up 0
108 $ echo h2 > foo
108 $ echo h2 > foo
109 $ hg -q commit -m 'head 2'
109 $ hg -q commit -m 'head 2'
110 $ hg phase --public -r 0:tip
110 $ hg phase --public -r 0:tip
111 $ hg -q up 1
111 $ hg -q up 1
112 $ hg merge -t :local 2
112 $ hg merge -t :local 2
113 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
113 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
114 (branch merge, don't forget to commit)
114 (branch merge, don't forget to commit)
115 $ hg commit -m 'merge heads'
115 $ hg commit -m 'merge heads'
116
116
117 TODO doesn't yet handle case where wdir is a draft merge
117 TODO doesn't yet handle case where wdir is a draft merge
118
118
119 $ hg show stack
119 $ hg show stack
120 @ 8ee90 merge heads
120 @ 8ee9 merge heads
121 / (stack base)
121 / (stack base)
122 o 59478 head 1
122 o 5947 head 1
123
123
124 $ echo d1 > foo
124 $ echo d1 > foo
125 $ hg commit -m 'draft 1'
125 $ hg commit -m 'draft 1'
126 $ echo d2 > foo
126 $ echo d2 > foo
127 $ hg commit -m 'draft 2'
127 $ hg commit -m 'draft 2'
128
128
129 $ hg show stack
129 $ hg show stack
130 @ 430d5 draft 2
130 @ 430d draft 2
131 o 787b1 draft 1
131 o 787b draft 1
132 / (stack base)
132 / (stack base)
133 o 8ee90 merge heads
133 o 8ee9 merge heads
134
134
135 $ cd ..
135 $ cd ..
136
136
137 Now move on to stacks when there are more commits after the base branchpoint
137 Now move on to stacks when there are more commits after the base branchpoint
138
138
139 $ hg init public-rebase
139 $ hg init public-rebase
140 $ cd public-rebase
140 $ cd public-rebase
141 $ echo 0 > foo
141 $ echo 0 > foo
142 $ hg -q commit -A -m 'base'
142 $ hg -q commit -A -m 'base'
143 $ hg phase --public -r .
143 $ hg phase --public -r .
144 $ echo d1 > foo
144 $ echo d1 > foo
145 $ hg commit -m 'draft 1'
145 $ hg commit -m 'draft 1'
146 $ echo d2 > foo
146 $ echo d2 > foo
147 $ hg commit -m 'draft 2'
147 $ hg commit -m 'draft 2'
148 $ hg -q up 0
148 $ hg -q up 0
149 $ echo 1 > foo
149 $ echo 1 > foo
150 $ hg commit -m 'new 1'
150 $ hg commit -m 'new 1'
151 created new head
151 created new head
152 $ echo 2 > foo
152 $ echo 2 > foo
153 $ hg commit -m 'new 2'
153 $ hg commit -m 'new 2'
154 $ hg -q up 2
154 $ hg -q up 2
155
155
156 Newer draft heads don't impact output
156 Newer draft heads don't impact output
157
157
158 $ hg show stack
158 $ hg show stack
159 @ eaffc draft 2
159 @ eaff draft 2
160 o 2b218 draft 1
160 o 2b21 draft 1
161 / (stack base)
161 / (stack base)
162 o b66bb base
162 o b66b base
163
163
164 Newer public heads are rendered
164 Newer public heads are rendered
165
165
166 $ hg phase --public -r '::tip'
166 $ hg phase --public -r '::tip'
167
167
168 $ hg show stack
168 $ hg show stack
169 o baa4b new 2
169 o baa4 new 2
170 / (2 commits ahead)
170 / (2 commits ahead)
171 :
171 :
172 : (stack head)
172 : (stack head)
173 : @ eaffc draft 2
173 : @ eaff draft 2
174 : o 2b218 draft 1
174 : o 2b21 draft 1
175 :/ (stack base)
175 :/ (stack base)
176 o b66bb base
176 o b66b base
177
177
178 If rebase is available, we show a hint how to rebase to that head
178 If rebase is available, we show a hint how to rebase to that head
179
179
180 $ hg --config extensions.rebase= show stack
180 $ hg --config extensions.rebase= show stack
181 o baa4b new 2
181 o baa4 new 2
182 / (2 commits ahead; hg rebase --source 2b218 --dest baa4b)
182 / (2 commits ahead; hg rebase --source 2b21 --dest baa4)
183 :
183 :
184 : (stack head)
184 : (stack head)
185 : @ eaffc draft 2
185 : @ eaff draft 2
186 : o 2b218 draft 1
186 : o 2b21 draft 1
187 :/ (stack base)
187 :/ (stack base)
188 o b66bb base
188 o b66b base
189
189
190 Similar tests but for multiple heads
190 Similar tests but for multiple heads
191
191
192 $ hg -q up 0
192 $ hg -q up 0
193 $ echo h2 > foo
193 $ echo h2 > foo
194 $ hg -q commit -m 'new head 2'
194 $ hg -q commit -m 'new head 2'
195 $ hg phase --public -r .
195 $ hg phase --public -r .
196 $ hg -q up 2
196 $ hg -q up 2
197
197
198 $ hg show stack
198 $ hg show stack
199 o baa4b new 2
199 o baa4 new 2
200 / (2 commits ahead)
200 / (2 commits ahead)
201 : o 9a848 new head 2
201 : o 9a84 new head 2
202 :/ (1 commits ahead)
202 :/ (1 commits ahead)
203 :
203 :
204 : (stack head)
204 : (stack head)
205 : @ eaffc draft 2
205 : @ eaff draft 2
206 : o 2b218 draft 1
206 : o 2b21 draft 1
207 :/ (stack base)
207 :/ (stack base)
208 o b66bb base
208 o b66b base
209
209
210 $ hg --config extensions.rebase= show stack
210 $ hg --config extensions.rebase= show stack
211 o baa4b new 2
211 o baa4 new 2
212 / (2 commits ahead; hg rebase --source 2b218 --dest baa4b)
212 / (2 commits ahead; hg rebase --source 2b21 --dest baa4)
213 : o 9a848 new head 2
213 : o 9a84 new head 2
214 :/ (1 commits ahead; hg rebase --source 2b218 --dest 9a848)
214 :/ (1 commits ahead; hg rebase --source 2b21 --dest 9a84)
215 :
215 :
216 : (stack head)
216 : (stack head)
217 : @ eaffc draft 2
217 : @ eaff draft 2
218 : o 2b218 draft 1
218 : o 2b21 draft 1
219 :/ (stack base)
219 :/ (stack base)
220 o b66bb base
220 o b66b base
@@ -1,237 +1,267 b''
1 $ cat >> $HGRCPATH << EOF
1 $ cat >> $HGRCPATH << EOF
2 > [extensions]
2 > [extensions]
3 > show =
3 > show =
4 > EOF
4 > EOF
5
5
6 $ hg init repo0
6 $ hg init repo0
7 $ cd repo0
7 $ cd repo0
8
8
9 Command works on an empty repo
9 Command works on an empty repo
10
10
11 $ hg show work
11 $ hg show work
12
12
13 Single draft changeset shown
13 Single draft changeset shown
14
14
15 $ echo 0 > foo
15 $ echo 0 > foo
16 $ hg -q commit -A -m 'commit 0'
16 $ hg -q commit -A -m 'commit 0'
17
17
18 $ hg show work
18 $ hg show work
19 @ 9f171 commit 0
19 @ 9f17 commit 0
20
20
21 Even when it isn't the wdir
21 Even when it isn't the wdir
22
22
23 $ hg -q up null
23 $ hg -q up null
24
24
25 $ hg show work
25 $ hg show work
26 o 9f171 commit 0
26 o 9f17 commit 0
27
27
28 Single changeset is still there when public because it is a head
28 Single changeset is still there when public because it is a head
29
29
30 $ hg phase --public -r 0
30 $ hg phase --public -r 0
31 $ hg show work
31 $ hg show work
32 o 9f171 commit 0
32 o 9f17 commit 0
33
33
34 A draft child will show both it and public parent
34 A draft child will show both it and public parent
35
35
36 $ hg -q up 0
36 $ hg -q up 0
37 $ echo 1 > foo
37 $ echo 1 > foo
38 $ hg commit -m 'commit 1'
38 $ hg commit -m 'commit 1'
39
39
40 $ hg show work
40 $ hg show work
41 @ 181cc commit 1
41 @ 181c commit 1
42 o 9f171 commit 0
42 o 9f17 commit 0
43
43
44 Multiple draft children will be shown
44 Multiple draft children will be shown
45
45
46 $ echo 2 > foo
46 $ echo 2 > foo
47 $ hg commit -m 'commit 2'
47 $ hg commit -m 'commit 2'
48
48
49 $ hg show work
49 $ hg show work
50 @ 128c8 commit 2
50 @ 128c commit 2
51 o 181cc commit 1
51 o 181c commit 1
52 o 9f171 commit 0
52 o 9f17 commit 0
53
53
54 Bumping first draft changeset to public will hide its parent
54 Bumping first draft changeset to public will hide its parent
55
55
56 $ hg phase --public -r 1
56 $ hg phase --public -r 1
57 $ hg show work
57 $ hg show work
58 @ 128c8 commit 2
58 @ 128c commit 2
59 o 181cc commit 1
59 o 181c commit 1
60 |
60 |
61 ~
61 ~
62
62
63 Multiple DAG heads will be shown
63 Multiple DAG heads will be shown
64
64
65 $ hg -q up -r 1
65 $ hg -q up -r 1
66 $ echo 3 > foo
66 $ echo 3 > foo
67 $ hg commit -m 'commit 3'
67 $ hg commit -m 'commit 3'
68 created new head
68 created new head
69
69
70 $ hg show work
70 $ hg show work
71 @ f0abc commit 3
71 @ f0ab commit 3
72 | o 128c8 commit 2
72 | o 128c commit 2
73 |/
73 |/
74 o 181cc commit 1
74 o 181c commit 1
75 |
75 |
76 ~
76 ~
77
77
78 Even when wdir is something else
78 Even when wdir is something else
79
79
80 $ hg -q up null
80 $ hg -q up null
81
81
82 $ hg show work
82 $ hg show work
83 o f0abc commit 3
83 o f0ab commit 3
84 | o 128c8 commit 2
84 | o 128c commit 2
85 |/
85 |/
86 o 181cc commit 1
86 o 181c commit 1
87 |
87 |
88 ~
88 ~
89
89
90 Draft child shows public head (multiple heads)
90 Draft child shows public head (multiple heads)
91
91
92 $ hg -q up 0
92 $ hg -q up 0
93 $ echo 4 > foo
93 $ echo 4 > foo
94 $ hg commit -m 'commit 4'
94 $ hg commit -m 'commit 4'
95 created new head
95 created new head
96
96
97 $ hg show work
97 $ hg show work
98 @ 668ca commit 4
98 @ 668c commit 4
99 | o f0abc commit 3
99 | o f0ab commit 3
100 | | o 128c8 commit 2
100 | | o 128c commit 2
101 | |/
101 | |/
102 | o 181cc commit 1
102 | o 181c commit 1
103 |/
103 |/
104 o 9f171 commit 0
104 o 9f17 commit 0
105
105
106 $ cd ..
106 $ cd ..
107
107
108 Branch name appears in output
108 Branch name appears in output
109
109
110 $ hg init branches
110 $ hg init branches
111 $ cd branches
111 $ cd branches
112 $ echo 0 > foo
112 $ echo 0 > foo
113 $ hg -q commit -A -m 'commit 0'
113 $ hg -q commit -A -m 'commit 0'
114 $ echo 1 > foo
114 $ echo 1 > foo
115 $ hg commit -m 'commit 1'
115 $ hg commit -m 'commit 1'
116 $ echo 2 > foo
116 $ echo 2 > foo
117 $ hg commit -m 'commit 2'
117 $ hg commit -m 'commit 2'
118 $ hg phase --public -r .
118 $ hg phase --public -r .
119 $ hg -q up -r 1
119 $ hg -q up -r 1
120 $ hg branch mybranch
120 $ hg branch mybranch
121 marked working directory as branch mybranch
121 marked working directory as branch mybranch
122 (branches are permanent and global, did you want a bookmark?)
122 (branches are permanent and global, did you want a bookmark?)
123 $ echo 3 > foo
123 $ echo 3 > foo
124 $ hg commit -m 'commit 3'
124 $ hg commit -m 'commit 3'
125 $ echo 4 > foo
125 $ echo 4 > foo
126 $ hg commit -m 'commit 4'
126 $ hg commit -m 'commit 4'
127
127
128 $ hg show work
128 $ hg show work
129 @ f8dd3 (mybranch) commit 4
129 @ f8dd (mybranch) commit 4
130 o 90cfc (mybranch) commit 3
130 o 90cf (mybranch) commit 3
131 | o 128c8 commit 2
131 | o 128c commit 2
132 |/
132 |/
133 o 181cc commit 1
133 o 181c commit 1
134 |
134 |
135 ~
135 ~
136
136
137 $ cd ..
137 $ cd ..
138
138
139 Bookmark name appears in output
139 Bookmark name appears in output
140
140
141 $ hg init bookmarks
141 $ hg init bookmarks
142 $ cd bookmarks
142 $ cd bookmarks
143 $ echo 0 > foo
143 $ echo 0 > foo
144 $ hg -q commit -A -m 'commit 0'
144 $ hg -q commit -A -m 'commit 0'
145 $ echo 1 > foo
145 $ echo 1 > foo
146 $ hg commit -m 'commit 1'
146 $ hg commit -m 'commit 1'
147 $ echo 2 > foo
147 $ echo 2 > foo
148 $ hg commit -m 'commit 2'
148 $ hg commit -m 'commit 2'
149 $ hg phase --public -r .
149 $ hg phase --public -r .
150 $ hg bookmark @
150 $ hg bookmark @
151 $ hg -q up -r 1
151 $ hg -q up -r 1
152 $ echo 3 > foo
152 $ echo 3 > foo
153 $ hg commit -m 'commit 3'
153 $ hg commit -m 'commit 3'
154 created new head
154 created new head
155 $ echo 4 > foo
155 $ echo 4 > foo
156 $ hg commit -m 'commit 4'
156 $ hg commit -m 'commit 4'
157 $ hg bookmark mybook
157 $ hg bookmark mybook
158
158
159 $ hg show work
159 $ hg show work
160 @ cac82 (mybook) commit 4
160 @ cac8 (mybook) commit 4
161 o f0abc commit 3
161 o f0ab commit 3
162 | o 128c8 (@) commit 2
162 | o 128c (@) commit 2
163 |/
163 |/
164 o 181cc commit 1
164 o 181c commit 1
165 |
165 |
166 ~
166 ~
167
167
168 $ cd ..
168 $ cd ..
169
169
170 Tags are rendered
170 Tags are rendered
171
171
172 $ hg init tags
172 $ hg init tags
173 $ cd tags
173 $ cd tags
174 $ echo 0 > foo
174 $ echo 0 > foo
175 $ hg -q commit -A -m 'commit 1'
175 $ hg -q commit -A -m 'commit 1'
176 $ echo 1 > foo
176 $ echo 1 > foo
177 $ hg commit -m 'commit 2'
177 $ hg commit -m 'commit 2'
178 $ hg tag 0.1
178 $ hg tag 0.1
179 $ hg phase --public -r .
179 $ hg phase --public -r .
180 $ echo 2 > foo
180 $ echo 2 > foo
181 $ hg commit -m 'commit 3'
181 $ hg commit -m 'commit 3'
182 $ hg tag 0.2
182 $ hg tag 0.2
183
183
184 $ hg show work
184 $ hg show work
185 @ 37582 Added tag 0.2 for changeset 6379c25b76f1
185 @ 3758 Added tag 0.2 for changeset 6379c25b76f1
186 o 6379c (0.2) commit 3
186 o 6379 (0.2) commit 3
187 o a2ad9 Added tag 0.1 for changeset 6a75536ea0b1
187 o a2ad Added tag 0.1 for changeset 6a75536ea0b1
188 |
188 |
189 ~
189 ~
190
190
191 $ cd ..
191 $ cd ..
192
192
193 Multiple names on same changeset render properly
193 Multiple names on same changeset render properly
194
194
195 $ hg init multiplenames
195 $ hg init multiplenames
196 $ cd multiplenames
196 $ cd multiplenames
197 $ echo 0 > foo
197 $ echo 0 > foo
198 $ hg -q commit -A -m 'commit 1'
198 $ hg -q commit -A -m 'commit 1'
199 $ hg phase --public -r .
199 $ hg phase --public -r .
200 $ hg branch mybranch
200 $ hg branch mybranch
201 marked working directory as branch mybranch
201 marked working directory as branch mybranch
202 (branches are permanent and global, did you want a bookmark?)
202 (branches are permanent and global, did you want a bookmark?)
203 $ hg bookmark mybook
203 $ hg bookmark mybook
204 $ echo 1 > foo
204 $ echo 1 > foo
205 $ hg commit -m 'commit 2'
205 $ hg commit -m 'commit 2'
206
206
207 $ hg show work
207 $ hg show work
208 @ 34834 (mybook) (mybranch) commit 2
208 @ 3483 (mybook) (mybranch) commit 2
209 o 97fcc commit 1
209 o 97fc commit 1
210
210
211 Multiple bookmarks on same changeset render properly
211 Multiple bookmarks on same changeset render properly
212
212
213 $ hg book mybook2
213 $ hg book mybook2
214 $ hg show work
214 $ hg show work
215 @ 34834 (mybook mybook2) (mybranch) commit 2
215 @ 3483 (mybook mybook2) (mybranch) commit 2
216 o 97fcc commit 1
216 o 97fc commit 1
217
217
218 $ cd ..
218 $ cd ..
219
219
220 Extra namespaces are rendered
220 Extra namespaces are rendered
221
221
222 $ hg init extranamespaces
222 $ hg init extranamespaces
223 $ cd extranamespaces
223 $ cd extranamespaces
224 $ echo 0 > foo
224 $ echo 0 > foo
225 $ hg -q commit -A -m 'commit 1'
225 $ hg -q commit -A -m 'commit 1'
226 $ hg phase --public -r .
226 $ hg phase --public -r .
227 $ echo 1 > foo
227 $ echo 1 > foo
228 $ hg commit -m 'commit 2'
228 $ hg commit -m 'commit 2'
229 $ echo 2 > foo
229 $ echo 2 > foo
230 $ hg commit -m 'commit 3'
230 $ hg commit -m 'commit 3'
231
231
232 $ hg --config extensions.revnames=$TESTDIR/revnamesext.py show work
232 $ hg --config extensions.revnames=$TESTDIR/revnamesext.py show work
233 @ 32f3e (r2) commit 3
233 @ 32f3 (r2) commit 3
234 o 6a755 (r1) commit 2
234 o 6a75 (r1) commit 2
235 o 97fcc (r0) commit 1
235 o 97fc (r0) commit 1
236
236
237 $ cd ..
237 $ cd ..
238
239 Prefix collision on hashes increases shortest node length
240
241 $ hg init hashcollision
242 $ cd hashcollision
243 $ echo 0 > a
244 $ hg -q commit -Am 0
245 $ for i in 17 1057 2857 4025; do
246 > hg -q up 0
247 > echo $i > a
248 > hg -q commit -m $i
249 > echo 0 > a
250 > hg commit -m "$i commit 2"
251 > done
252
253 $ hg show work
254 @ cfd04 4025 commit 2
255 o c562d 4025
256 | o 08048 2857 commit 2
257 | o c5623 2857
258 |/
259 | o 6a6b6 1057 commit 2
260 | o c5625 1057
261 |/
262 | o 96b4e 17 commit 2
263 | o 11424 17
264 |/
265 o b4e73 0
266
267 $ cd ..
@@ -1,173 +1,173 b''
1 $ cat >> $HGRCPATH << EOF
1 $ cat >> $HGRCPATH << EOF
2 > [extensions]
2 > [extensions]
3 > show =
3 > show =
4 > EOF
4 > EOF
5
5
6 No arguments shows available views
6 No arguments shows available views
7
7
8 $ hg init empty
8 $ hg init empty
9 $ cd empty
9 $ cd empty
10 $ hg show
10 $ hg show
11 available views:
11 available views:
12
12
13 bookmarks -- bookmarks and their associated changeset
13 bookmarks -- bookmarks and their associated changeset
14 stack -- current line of work
14 stack -- current line of work
15 work -- changesets that aren't finished
15 work -- changesets that aren't finished
16
16
17 abort: no view requested
17 abort: no view requested
18 (use "hg show VIEW" to choose a view)
18 (use "hg show VIEW" to choose a view)
19 [255]
19 [255]
20
20
21 `hg help show` prints available views
21 `hg help show` prints available views
22
22
23 $ hg help show
23 $ hg help show
24 hg show VIEW
24 hg show VIEW
25
25
26 show various repository information
26 show various repository information
27
27
28 A requested view of repository data is displayed.
28 A requested view of repository data is displayed.
29
29
30 If no view is requested, the list of available views is shown and the
30 If no view is requested, the list of available views is shown and the
31 command aborts.
31 command aborts.
32
32
33 Note:
33 Note:
34 There are no backwards compatibility guarantees for the output of this
34 There are no backwards compatibility guarantees for the output of this
35 command. Output may change in any future Mercurial release.
35 command. Output may change in any future Mercurial release.
36
36
37 Consumers wanting stable command output should specify a template via
37 Consumers wanting stable command output should specify a template via
38 "-T/--template".
38 "-T/--template".
39
39
40 List of available views:
40 List of available views:
41
41
42 bookmarks bookmarks and their associated changeset
42 bookmarks bookmarks and their associated changeset
43
43
44 stack current line of work
44 stack current line of work
45
45
46 work changesets that aren't finished
46 work changesets that aren't finished
47
47
48 (use 'hg help -e show' to show help for the show extension)
48 (use 'hg help -e show' to show help for the show extension)
49
49
50 options:
50 options:
51
51
52 -T --template TEMPLATE display with template
52 -T --template TEMPLATE display with template
53
53
54 (some details hidden, use --verbose to show complete help)
54 (some details hidden, use --verbose to show complete help)
55
55
56 Unknown view prints error
56 Unknown view prints error
57
57
58 $ hg show badview
58 $ hg show badview
59 abort: unknown view: badview
59 abort: unknown view: badview
60 (run "hg show" to see available views)
60 (run "hg show" to see available views)
61 [255]
61 [255]
62
62
63 HGPLAIN results in abort
63 HGPLAIN results in abort
64
64
65 $ HGPLAIN=1 hg show bookmarks
65 $ HGPLAIN=1 hg show bookmarks
66 abort: must specify a template in plain mode
66 abort: must specify a template in plain mode
67 (invoke with -T/--template to control output format)
67 (invoke with -T/--template to control output format)
68 [255]
68 [255]
69
69
70 But not if a template is specified
70 But not if a template is specified
71
71
72 $ HGPLAIN=1 hg show bookmarks -T '{bookmark}\n'
72 $ HGPLAIN=1 hg show bookmarks -T '{bookmark}\n'
73 (no bookmarks set)
73 (no bookmarks set)
74
74
75 $ cd ..
75 $ cd ..
76
76
77 bookmarks view with no bookmarks prints empty message
77 bookmarks view with no bookmarks prints empty message
78
78
79 $ hg init books
79 $ hg init books
80 $ cd books
80 $ cd books
81 $ touch f0
81 $ touch f0
82 $ hg -q commit -A -m initial
82 $ hg -q commit -A -m initial
83
83
84 $ hg show bookmarks
84 $ hg show bookmarks
85 (no bookmarks set)
85 (no bookmarks set)
86
86
87 bookmarks view shows bookmarks in an aligned table
87 bookmarks view shows bookmarks in an aligned table
88
88
89 $ echo book1 > f0
89 $ echo book1 > f0
90 $ hg commit -m 'commit for book1'
90 $ hg commit -m 'commit for book1'
91 $ echo book2 > f0
91 $ echo book2 > f0
92 $ hg commit -m 'commit for book2'
92 $ hg commit -m 'commit for book2'
93
93
94 $ hg bookmark -r 1 book1
94 $ hg bookmark -r 1 book1
95 $ hg bookmark a-longer-bookmark
95 $ hg bookmark a-longer-bookmark
96
96
97 $ hg show bookmarks
97 $ hg show bookmarks
98 * a-longer-bookmark 7b570
98 * a-longer-bookmark 7b57
99 book1 b757f
99 book1 b757
100
100
101 A custom bookmarks template works
101 A custom bookmarks template works
102
102
103 $ hg show bookmarks -T '{node} {bookmark} {active}\n'
103 $ hg show bookmarks -T '{node} {bookmark} {active}\n'
104 7b5709ab64cbc34da9b4367b64afff47f2c4ee83 a-longer-bookmark True
104 7b5709ab64cbc34da9b4367b64afff47f2c4ee83 a-longer-bookmark True
105 b757f780b8ffd71267c6ccb32e0882d9d32a8cc0 book1 False
105 b757f780b8ffd71267c6ccb32e0882d9d32a8cc0 book1 False
106
106
107 bookmarks JSON works
107 bookmarks JSON works
108
108
109 $ hg show bookmarks -T json
109 $ hg show bookmarks -T json
110 [
110 [
111 {
111 {
112 "active": true,
112 "active": true,
113 "bookmark": "a-longer-bookmark",
113 "bookmark": "a-longer-bookmark",
114 "longestbookmarklen": 17,
114 "longestbookmarklen": 17,
115 "node": "7b5709ab64cbc34da9b4367b64afff47f2c4ee83",
115 "node": "7b5709ab64cbc34da9b4367b64afff47f2c4ee83",
116 "nodelen": 5
116 "nodelen": 4
117 },
117 },
118 {
118 {
119 "active": false,
119 "active": false,
120 "bookmark": "book1",
120 "bookmark": "book1",
121 "longestbookmarklen": 17,
121 "longestbookmarklen": 17,
122 "node": "b757f780b8ffd71267c6ccb32e0882d9d32a8cc0",
122 "node": "b757f780b8ffd71267c6ccb32e0882d9d32a8cc0",
123 "nodelen": 5
123 "nodelen": 4
124 }
124 }
125 ]
125 ]
126
126
127 JSON works with no bookmarks
127 JSON works with no bookmarks
128
128
129 $ hg book -d a-longer-bookmark
129 $ hg book -d a-longer-bookmark
130 $ hg book -d book1
130 $ hg book -d book1
131 $ hg show bookmarks -T json
131 $ hg show bookmarks -T json
132 [
132 [
133 ]
133 ]
134
134
135 commands.show.aliasprefix aliases values to `show <view>`
135 commands.show.aliasprefix aliases values to `show <view>`
136
136
137 $ hg --config commands.show.aliasprefix=s sbookmarks
137 $ hg --config commands.show.aliasprefix=s sbookmarks
138 (no bookmarks set)
138 (no bookmarks set)
139
139
140 $ hg --config commands.show.aliasprefix=sh shwork
140 $ hg --config commands.show.aliasprefix=sh shwork
141 @ 7b570 commit for book2
141 @ 7b57 commit for book2
142 o b757f commit for book1
142 o b757 commit for book1
143 o ba592 initial
143 o ba59 initial
144
144
145 $ hg --config commands.show.aliasprefix='s sh' swork
145 $ hg --config commands.show.aliasprefix='s sh' swork
146 @ 7b570 commit for book2
146 @ 7b57 commit for book2
147 o b757f commit for book1
147 o b757 commit for book1
148 o ba592 initial
148 o ba59 initial
149
149
150 $ hg --config commands.show.aliasprefix='s sh' shwork
150 $ hg --config commands.show.aliasprefix='s sh' shwork
151 @ 7b570 commit for book2
151 @ 7b57 commit for book2
152 o b757f commit for book1
152 o b757 commit for book1
153 o ba592 initial
153 o ba59 initial
154
154
155 The aliases don't appear in `hg config`
155 The aliases don't appear in `hg config`
156
156
157 $ hg --config commands.show.aliasprefix=s config alias
157 $ hg --config commands.show.aliasprefix=s config alias
158 [1]
158 [1]
159
159
160 Doesn't overwrite existing alias
160 Doesn't overwrite existing alias
161
161
162 $ hg --config alias.swork='log -r .' --config commands.show.aliasprefix=s swork
162 $ hg --config alias.swork='log -r .' --config commands.show.aliasprefix=s swork
163 changeset: 2:7b5709ab64cb
163 changeset: 2:7b5709ab64cb
164 tag: tip
164 tag: tip
165 user: test
165 user: test
166 date: Thu Jan 01 00:00:00 1970 +0000
166 date: Thu Jan 01 00:00:00 1970 +0000
167 summary: commit for book2
167 summary: commit for book2
168
168
169
169
170 $ hg --config alias.swork='log -r .' --config commands.show.aliasprefix=s config alias
170 $ hg --config alias.swork='log -r .' --config commands.show.aliasprefix=s config alias
171 alias.swork=log -r .
171 alias.swork=log -r .
172
172
173 $ cd ..
173 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now