##// END OF EJS Templates
help: supporting both help and doc for aliases...
Rodrigo Damazio -
r37152:6890b7e9 default
parent child Browse files
Show More
@@ -1,469 +1,469 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 (
31 from mercurial.node import (
32 hex,
32 hex,
33 nullrev,
33 nullrev,
34 )
34 )
35 from mercurial import (
35 from mercurial import (
36 cmdutil,
36 cmdutil,
37 commands,
37 commands,
38 destutil,
38 destutil,
39 error,
39 error,
40 formatter,
40 formatter,
41 graphmod,
41 graphmod,
42 logcmdutil,
42 logcmdutil,
43 phases,
43 phases,
44 pycompat,
44 pycompat,
45 registrar,
45 registrar,
46 revset,
46 revset,
47 revsetlang,
47 revsetlang,
48 )
48 )
49
49
50 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
50 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
51 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
51 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
52 # be specifying the version(s) of Mercurial they are tested with, or
52 # be specifying the version(s) of Mercurial they are tested with, or
53 # leave the attribute unspecified.
53 # leave the attribute unspecified.
54 testedwith = 'ships-with-hg-core'
54 testedwith = 'ships-with-hg-core'
55
55
56 cmdtable = {}
56 cmdtable = {}
57 command = registrar.command(cmdtable)
57 command = registrar.command(cmdtable)
58
58
59 revsetpredicate = registrar.revsetpredicate()
59 revsetpredicate = registrar.revsetpredicate()
60
60
61 class showcmdfunc(registrar._funcregistrarbase):
61 class showcmdfunc(registrar._funcregistrarbase):
62 """Register a function to be invoked for an `hg show <thing>`."""
62 """Register a function to be invoked for an `hg show <thing>`."""
63
63
64 # Used by _formatdoc().
64 # Used by _formatdoc().
65 _docformat = '%s -- %s'
65 _docformat = '%s -- %s'
66
66
67 def _extrasetup(self, name, func, fmtopic=None, csettopic=None):
67 def _extrasetup(self, name, func, fmtopic=None, csettopic=None):
68 """Called with decorator arguments to register a show view.
68 """Called with decorator arguments to register a show view.
69
69
70 ``name`` is the sub-command name.
70 ``name`` is the sub-command name.
71
71
72 ``func`` is the function being decorated.
72 ``func`` is the function being decorated.
73
73
74 ``fmtopic`` is the topic in the style that will be rendered for
74 ``fmtopic`` is the topic in the style that will be rendered for
75 this view.
75 this view.
76
76
77 ``csettopic`` is the topic in the style to be used for a changeset
77 ``csettopic`` is the topic in the style to be used for a changeset
78 printer.
78 printer.
79
79
80 If ``fmtopic`` is specified, the view function will receive a
80 If ``fmtopic`` is specified, the view function will receive a
81 formatter instance. If ``csettopic`` is specified, the view
81 formatter instance. If ``csettopic`` is specified, the view
82 function will receive a changeset printer.
82 function will receive a changeset printer.
83 """
83 """
84 func._fmtopic = fmtopic
84 func._fmtopic = fmtopic
85 func._csettopic = csettopic
85 func._csettopic = csettopic
86
86
87 showview = showcmdfunc()
87 showview = showcmdfunc()
88
88
89 @command('show', [
89 @command('show', [
90 # TODO: Switch this template flag to use cmdutil.formatteropts if
90 # TODO: Switch this template flag to use cmdutil.formatteropts if
91 # 'hg show' becomes stable before --template/-T is stable. For now,
91 # 'hg show' becomes stable before --template/-T is stable. For now,
92 # we are putting it here without the '(EXPERIMENTAL)' flag because it
92 # we are putting it here without the '(EXPERIMENTAL)' flag because it
93 # is an important part of the 'hg show' user experience and the entire
93 # is an important part of the 'hg show' user experience and the entire
94 # 'hg show' experience is experimental.
94 # 'hg show' experience is experimental.
95 ('T', 'template', '', ('display with template'), _('TEMPLATE')),
95 ('T', 'template', '', ('display with template'), _('TEMPLATE')),
96 ], _('VIEW'))
96 ], _('VIEW'))
97 def show(ui, repo, view=None, template=None):
97 def show(ui, repo, view=None, template=None):
98 """show various repository information
98 """show various repository information
99
99
100 A requested view of repository data is displayed.
100 A requested view of repository data is displayed.
101
101
102 If no view is requested, the list of available views is shown and the
102 If no view is requested, the list of available views is shown and the
103 command aborts.
103 command aborts.
104
104
105 .. note::
105 .. note::
106
106
107 There are no backwards compatibility guarantees for the output of this
107 There are no backwards compatibility guarantees for the output of this
108 command. Output may change in any future Mercurial release.
108 command. Output may change in any future Mercurial release.
109
109
110 Consumers wanting stable command output should specify a template via
110 Consumers wanting stable command output should specify a template via
111 ``-T/--template``.
111 ``-T/--template``.
112
112
113 List of available views:
113 List of available views:
114 """
114 """
115 if ui.plain() and not template:
115 if ui.plain() and not template:
116 hint = _('invoke with -T/--template to control output format')
116 hint = _('invoke with -T/--template to control output format')
117 raise error.Abort(_('must specify a template in plain mode'), hint=hint)
117 raise error.Abort(_('must specify a template in plain mode'), hint=hint)
118
118
119 views = showview._table
119 views = showview._table
120
120
121 if not view:
121 if not view:
122 ui.pager('show')
122 ui.pager('show')
123 # TODO consider using formatter here so available views can be
123 # TODO consider using formatter here so available views can be
124 # rendered to custom format.
124 # rendered to custom format.
125 ui.write(_('available views:\n'))
125 ui.write(_('available views:\n'))
126 ui.write('\n')
126 ui.write('\n')
127
127
128 for name, func in sorted(views.items()):
128 for name, func in sorted(views.items()):
129 ui.write(('%s\n') % pycompat.sysbytes(func.__doc__))
129 ui.write(('%s\n') % pycompat.sysbytes(func.__doc__))
130
130
131 ui.write('\n')
131 ui.write('\n')
132 raise error.Abort(_('no view requested'),
132 raise error.Abort(_('no view requested'),
133 hint=_('use "hg show VIEW" to choose a view'))
133 hint=_('use "hg show VIEW" to choose a view'))
134
134
135 # TODO use same logic as dispatch to perform prefix matching.
135 # TODO use same logic as dispatch to perform prefix matching.
136 if view not in views:
136 if view not in views:
137 raise error.Abort(_('unknown view: %s') % view,
137 raise error.Abort(_('unknown view: %s') % view,
138 hint=_('run "hg show" to see available views'))
138 hint=_('run "hg show" to see available views'))
139
139
140 template = template or 'show'
140 template = template or 'show'
141
141
142 fn = views[view]
142 fn = views[view]
143 ui.pager('show')
143 ui.pager('show')
144
144
145 if fn._fmtopic:
145 if fn._fmtopic:
146 fmtopic = 'show%s' % fn._fmtopic
146 fmtopic = 'show%s' % fn._fmtopic
147 with ui.formatter(fmtopic, {'template': template}) as fm:
147 with ui.formatter(fmtopic, {'template': template}) as fm:
148 return fn(ui, repo, fm)
148 return fn(ui, repo, fm)
149 elif fn._csettopic:
149 elif fn._csettopic:
150 ref = 'show%s' % fn._csettopic
150 ref = 'show%s' % fn._csettopic
151 spec = formatter.lookuptemplate(ui, ref, template)
151 spec = formatter.lookuptemplate(ui, ref, template)
152 displayer = logcmdutil.changesettemplater(ui, repo, spec, buffered=True)
152 displayer = logcmdutil.changesettemplater(ui, repo, spec, buffered=True)
153 return fn(ui, repo, displayer)
153 return fn(ui, repo, displayer)
154 else:
154 else:
155 return fn(ui, repo)
155 return fn(ui, repo)
156
156
157 @showview('bookmarks', fmtopic='bookmarks')
157 @showview('bookmarks', fmtopic='bookmarks')
158 def showbookmarks(ui, repo, fm):
158 def showbookmarks(ui, repo, fm):
159 """bookmarks and their associated changeset"""
159 """bookmarks and their associated changeset"""
160 marks = repo._bookmarks
160 marks = repo._bookmarks
161 if not len(marks):
161 if not len(marks):
162 # This is a bit hacky. Ideally, templates would have a way to
162 # This is a bit hacky. Ideally, templates would have a way to
163 # specify an empty output, but we shouldn't corrupt JSON while
163 # specify an empty output, but we shouldn't corrupt JSON while
164 # waiting for this functionality.
164 # waiting for this functionality.
165 if not isinstance(fm, formatter.jsonformatter):
165 if not isinstance(fm, formatter.jsonformatter):
166 ui.write(_('(no bookmarks set)\n'))
166 ui.write(_('(no bookmarks set)\n'))
167 return
167 return
168
168
169 revs = [repo[node].rev() for node in marks.values()]
169 revs = [repo[node].rev() for node in marks.values()]
170 active = repo._activebookmark
170 active = repo._activebookmark
171 longestname = max(len(b) for b in marks)
171 longestname = max(len(b) for b in marks)
172 nodelen = longestshortest(repo, revs)
172 nodelen = longestshortest(repo, revs)
173
173
174 for bm, node in sorted(marks.items()):
174 for bm, node in sorted(marks.items()):
175 fm.startitem()
175 fm.startitem()
176 fm.context(ctx=repo[node])
176 fm.context(ctx=repo[node])
177 fm.write('bookmark', '%s', bm)
177 fm.write('bookmark', '%s', bm)
178 fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
178 fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
179 fm.data(active=bm == active,
179 fm.data(active=bm == active,
180 longestbookmarklen=longestname,
180 longestbookmarklen=longestname,
181 nodelen=nodelen)
181 nodelen=nodelen)
182
182
183 @showview('stack', csettopic='stack')
183 @showview('stack', csettopic='stack')
184 def showstack(ui, repo, displayer):
184 def showstack(ui, repo, displayer):
185 """current line of work"""
185 """current line of work"""
186 wdirctx = repo['.']
186 wdirctx = repo['.']
187 if wdirctx.rev() == nullrev:
187 if wdirctx.rev() == nullrev:
188 raise error.Abort(_('stack view only available when there is a '
188 raise error.Abort(_('stack view only available when there is a '
189 'working directory'))
189 'working directory'))
190
190
191 if wdirctx.phase() == phases.public:
191 if wdirctx.phase() == phases.public:
192 ui.write(_('(empty stack; working directory parent is a published '
192 ui.write(_('(empty stack; working directory parent is a published '
193 'changeset)\n'))
193 'changeset)\n'))
194 return
194 return
195
195
196 # TODO extract "find stack" into a function to facilitate
196 # TODO extract "find stack" into a function to facilitate
197 # customization and reuse.
197 # customization and reuse.
198
198
199 baserev = destutil.stackbase(ui, repo)
199 baserev = destutil.stackbase(ui, repo)
200 basectx = None
200 basectx = None
201
201
202 if baserev is None:
202 if baserev is None:
203 baserev = wdirctx.rev()
203 baserev = wdirctx.rev()
204 stackrevs = {wdirctx.rev()}
204 stackrevs = {wdirctx.rev()}
205 else:
205 else:
206 stackrevs = set(repo.revs('%d::.', baserev))
206 stackrevs = set(repo.revs('%d::.', baserev))
207
207
208 ctx = repo[baserev]
208 ctx = repo[baserev]
209 if ctx.p1().rev() != nullrev:
209 if ctx.p1().rev() != nullrev:
210 basectx = ctx.p1()
210 basectx = ctx.p1()
211
211
212 # And relevant descendants.
212 # And relevant descendants.
213 branchpointattip = False
213 branchpointattip = False
214 cl = repo.changelog
214 cl = repo.changelog
215
215
216 for rev in cl.descendants([wdirctx.rev()]):
216 for rev in cl.descendants([wdirctx.rev()]):
217 ctx = repo[rev]
217 ctx = repo[rev]
218
218
219 # Will only happen if . is public.
219 # Will only happen if . is public.
220 if ctx.phase() == phases.public:
220 if ctx.phase() == phases.public:
221 break
221 break
222
222
223 stackrevs.add(ctx.rev())
223 stackrevs.add(ctx.rev())
224
224
225 # ctx.children() within a function iterating on descandants
225 # ctx.children() within a function iterating on descandants
226 # potentially has severe performance concerns because revlog.children()
226 # potentially has severe performance concerns because revlog.children()
227 # iterates over all revisions after ctx's node. However, the number of
227 # iterates over all revisions after ctx's node. However, the number of
228 # draft changesets should be a reasonably small number. So even if
228 # draft changesets should be a reasonably small number. So even if
229 # this is quadratic, the perf impact should be minimal.
229 # this is quadratic, the perf impact should be minimal.
230 if len(ctx.children()) > 1:
230 if len(ctx.children()) > 1:
231 branchpointattip = True
231 branchpointattip = True
232 break
232 break
233
233
234 stackrevs = list(sorted(stackrevs, reverse=True))
234 stackrevs = list(sorted(stackrevs, reverse=True))
235
235
236 # Find likely target heads for the current stack. These are likely
236 # Find likely target heads for the current stack. These are likely
237 # merge or rebase targets.
237 # merge or rebase targets.
238 if basectx:
238 if basectx:
239 # TODO make this customizable?
239 # TODO make this customizable?
240 newheads = set(repo.revs('heads(%d::) - %ld - not public()',
240 newheads = set(repo.revs('heads(%d::) - %ld - not public()',
241 basectx.rev(), stackrevs))
241 basectx.rev(), stackrevs))
242 else:
242 else:
243 newheads = set()
243 newheads = set()
244
244
245 allrevs = set(stackrevs) | newheads | set([baserev])
245 allrevs = set(stackrevs) | newheads | set([baserev])
246 nodelen = longestshortest(repo, allrevs)
246 nodelen = longestshortest(repo, allrevs)
247
247
248 try:
248 try:
249 cmdutil.findcmd('rebase', commands.table)
249 cmdutil.findcmd('rebase', commands.table)
250 haverebase = True
250 haverebase = True
251 except (error.AmbiguousCommand, error.UnknownCommand):
251 except (error.AmbiguousCommand, error.UnknownCommand):
252 haverebase = False
252 haverebase = False
253
253
254 # TODO use templating.
254 # TODO use templating.
255 # TODO consider using graphmod. But it may not be necessary given
255 # TODO consider using graphmod. But it may not be necessary given
256 # our simplicity and the customizations required.
256 # our simplicity and the customizations required.
257 # TODO use proper graph symbols from graphmod
257 # TODO use proper graph symbols from graphmod
258
258
259 tres = formatter.templateresources(ui, repo)
259 tres = formatter.templateresources(ui, repo)
260 shortesttmpl = formatter.maketemplater(ui, '{shortest(node, %d)}' % nodelen,
260 shortesttmpl = formatter.maketemplater(ui, '{shortest(node, %d)}' % nodelen,
261 resources=tres)
261 resources=tres)
262 def shortest(ctx):
262 def shortest(ctx):
263 return shortesttmpl.renderdefault({'ctx': ctx, 'node': ctx.hex()})
263 return shortesttmpl.renderdefault({'ctx': ctx, 'node': ctx.hex()})
264
264
265 # We write out new heads to aid in DAG awareness and to help with decision
265 # We write out new heads to aid in DAG awareness and to help with decision
266 # making on how the stack should be reconciled with commits made since the
266 # making on how the stack should be reconciled with commits made since the
267 # branch point.
267 # branch point.
268 if newheads:
268 if newheads:
269 # Calculate distance from base so we can render the count and so we can
269 # Calculate distance from base so we can render the count and so we can
270 # sort display order by commit distance.
270 # sort display order by commit distance.
271 revdistance = {}
271 revdistance = {}
272 for head in newheads:
272 for head in newheads:
273 # There is some redundancy in DAG traversal here and therefore
273 # There is some redundancy in DAG traversal here and therefore
274 # room to optimize.
274 # room to optimize.
275 ancestors = cl.ancestors([head], stoprev=basectx.rev())
275 ancestors = cl.ancestors([head], stoprev=basectx.rev())
276 revdistance[head] = len(list(ancestors))
276 revdistance[head] = len(list(ancestors))
277
277
278 sourcectx = repo[stackrevs[-1]]
278 sourcectx = repo[stackrevs[-1]]
279
279
280 sortedheads = sorted(newheads, key=lambda x: revdistance[x],
280 sortedheads = sorted(newheads, key=lambda x: revdistance[x],
281 reverse=True)
281 reverse=True)
282
282
283 for i, rev in enumerate(sortedheads):
283 for i, rev in enumerate(sortedheads):
284 ctx = repo[rev]
284 ctx = repo[rev]
285
285
286 if i:
286 if i:
287 ui.write(': ')
287 ui.write(': ')
288 else:
288 else:
289 ui.write(' ')
289 ui.write(' ')
290
290
291 ui.write(('o '))
291 ui.write(('o '))
292 displayer.show(ctx, nodelen=nodelen)
292 displayer.show(ctx, nodelen=nodelen)
293 displayer.flush(ctx)
293 displayer.flush(ctx)
294 ui.write('\n')
294 ui.write('\n')
295
295
296 if i:
296 if i:
297 ui.write(':/')
297 ui.write(':/')
298 else:
298 else:
299 ui.write(' /')
299 ui.write(' /')
300
300
301 ui.write(' (')
301 ui.write(' (')
302 ui.write(_('%d commits ahead') % revdistance[rev],
302 ui.write(_('%d commits ahead') % revdistance[rev],
303 label='stack.commitdistance')
303 label='stack.commitdistance')
304
304
305 if haverebase:
305 if haverebase:
306 # TODO may be able to omit --source in some scenarios
306 # TODO may be able to omit --source in some scenarios
307 ui.write('; ')
307 ui.write('; ')
308 ui.write(('hg rebase --source %s --dest %s' % (
308 ui.write(('hg rebase --source %s --dest %s' % (
309 shortest(sourcectx), shortest(ctx))),
309 shortest(sourcectx), shortest(ctx))),
310 label='stack.rebasehint')
310 label='stack.rebasehint')
311
311
312 ui.write(')\n')
312 ui.write(')\n')
313
313
314 ui.write(':\n: ')
314 ui.write(':\n: ')
315 ui.write(_('(stack head)\n'), label='stack.label')
315 ui.write(_('(stack head)\n'), label='stack.label')
316
316
317 if branchpointattip:
317 if branchpointattip:
318 ui.write(' \\ / ')
318 ui.write(' \\ / ')
319 ui.write(_('(multiple children)\n'), label='stack.label')
319 ui.write(_('(multiple children)\n'), label='stack.label')
320 ui.write(' |\n')
320 ui.write(' |\n')
321
321
322 for rev in stackrevs:
322 for rev in stackrevs:
323 ctx = repo[rev]
323 ctx = repo[rev]
324 symbol = '@' if rev == wdirctx.rev() else 'o'
324 symbol = '@' if rev == wdirctx.rev() else 'o'
325
325
326 if newheads:
326 if newheads:
327 ui.write(': ')
327 ui.write(': ')
328 else:
328 else:
329 ui.write(' ')
329 ui.write(' ')
330
330
331 ui.write(symbol, ' ')
331 ui.write(symbol, ' ')
332 displayer.show(ctx, nodelen=nodelen)
332 displayer.show(ctx, nodelen=nodelen)
333 displayer.flush(ctx)
333 displayer.flush(ctx)
334 ui.write('\n')
334 ui.write('\n')
335
335
336 # TODO display histedit hint?
336 # TODO display histedit hint?
337
337
338 if basectx:
338 if basectx:
339 # Vertically and horizontally separate stack base from parent
339 # Vertically and horizontally separate stack base from parent
340 # to reinforce stack boundary.
340 # to reinforce stack boundary.
341 if newheads:
341 if newheads:
342 ui.write(':/ ')
342 ui.write(':/ ')
343 else:
343 else:
344 ui.write(' / ')
344 ui.write(' / ')
345
345
346 ui.write(_('(stack base)'), '\n', label='stack.label')
346 ui.write(_('(stack base)'), '\n', label='stack.label')
347 ui.write(('o '))
347 ui.write(('o '))
348
348
349 displayer.show(basectx, nodelen=nodelen)
349 displayer.show(basectx, nodelen=nodelen)
350 displayer.flush(basectx)
350 displayer.flush(basectx)
351 ui.write('\n')
351 ui.write('\n')
352
352
353 @revsetpredicate('_underway([commitage[, headage]])')
353 @revsetpredicate('_underway([commitage[, headage]])')
354 def underwayrevset(repo, subset, x):
354 def underwayrevset(repo, subset, x):
355 args = revset.getargsdict(x, 'underway', 'commitage headage')
355 args = revset.getargsdict(x, 'underway', 'commitage headage')
356 if 'commitage' not in args:
356 if 'commitage' not in args:
357 args['commitage'] = None
357 args['commitage'] = None
358 if 'headage' not in args:
358 if 'headage' not in args:
359 args['headage'] = None
359 args['headage'] = None
360
360
361 # We assume callers of this revset add a topographical sort on the
361 # We assume callers of this revset add a topographical sort on the
362 # result. This means there is no benefit to making the revset lazy
362 # result. This means there is no benefit to making the revset lazy
363 # since the topographical sort needs to consume all revs.
363 # since the topographical sort needs to consume all revs.
364 #
364 #
365 # With this in mind, we build up the set manually instead of constructing
365 # With this in mind, we build up the set manually instead of constructing
366 # a complex revset. This enables faster execution.
366 # a complex revset. This enables faster execution.
367
367
368 # Mutable changesets (non-public) are the most important changesets
368 # Mutable changesets (non-public) are the most important changesets
369 # to return. ``not public()`` will also pull in obsolete changesets if
369 # to return. ``not public()`` will also pull in obsolete changesets if
370 # there is a non-obsolete changeset with obsolete ancestors. This is
370 # there is a non-obsolete changeset with obsolete ancestors. This is
371 # why we exclude obsolete changesets from this query.
371 # why we exclude obsolete changesets from this query.
372 rs = 'not public() and not obsolete()'
372 rs = 'not public() and not obsolete()'
373 rsargs = []
373 rsargs = []
374 if args['commitage']:
374 if args['commitage']:
375 rs += ' and date(%s)'
375 rs += ' and date(%s)'
376 rsargs.append(revsetlang.getstring(args['commitage'],
376 rsargs.append(revsetlang.getstring(args['commitage'],
377 _('commitage requires a string')))
377 _('commitage requires a string')))
378
378
379 mutable = repo.revs(rs, *rsargs)
379 mutable = repo.revs(rs, *rsargs)
380 relevant = revset.baseset(mutable)
380 relevant = revset.baseset(mutable)
381
381
382 # Add parents of mutable changesets to provide context.
382 # Add parents of mutable changesets to provide context.
383 relevant += repo.revs('parents(%ld)', mutable)
383 relevant += repo.revs('parents(%ld)', mutable)
384
384
385 # We also pull in (public) heads if they a) aren't closing a branch
385 # We also pull in (public) heads if they a) aren't closing a branch
386 # b) are recent.
386 # b) are recent.
387 rs = 'head() and not closed()'
387 rs = 'head() and not closed()'
388 rsargs = []
388 rsargs = []
389 if args['headage']:
389 if args['headage']:
390 rs += ' and date(%s)'
390 rs += ' and date(%s)'
391 rsargs.append(revsetlang.getstring(args['headage'],
391 rsargs.append(revsetlang.getstring(args['headage'],
392 _('headage requires a string')))
392 _('headage requires a string')))
393
393
394 relevant += repo.revs(rs, *rsargs)
394 relevant += repo.revs(rs, *rsargs)
395
395
396 # Add working directory parent.
396 # Add working directory parent.
397 wdirrev = repo['.'].rev()
397 wdirrev = repo['.'].rev()
398 if wdirrev != nullrev:
398 if wdirrev != nullrev:
399 relevant += revset.baseset({wdirrev})
399 relevant += revset.baseset({wdirrev})
400
400
401 return subset & relevant
401 return subset & relevant
402
402
403 @showview('work', csettopic='work')
403 @showview('work', csettopic='work')
404 def showwork(ui, repo, displayer):
404 def showwork(ui, repo, displayer):
405 """changesets that aren't finished"""
405 """changesets that aren't finished"""
406 # TODO support date-based limiting when calling revset.
406 # TODO support date-based limiting when calling revset.
407 revs = repo.revs('sort(_underway(), topo)')
407 revs = repo.revs('sort(_underway(), topo)')
408 nodelen = longestshortest(repo, revs)
408 nodelen = longestshortest(repo, revs)
409
409
410 revdag = graphmod.dagwalker(repo, revs)
410 revdag = graphmod.dagwalker(repo, revs)
411
411
412 ui.setconfig('experimental', 'graphshorten', True)
412 ui.setconfig('experimental', 'graphshorten', True)
413 logcmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges,
413 logcmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges,
414 props={'nodelen': nodelen})
414 props={'nodelen': nodelen})
415
415
416 def extsetup(ui):
416 def extsetup(ui):
417 # Alias `hg <prefix><view>` to `hg show <view>`.
417 # Alias `hg <prefix><view>` to `hg show <view>`.
418 for prefix in ui.configlist('commands', 'show.aliasprefix'):
418 for prefix in ui.configlist('commands', 'show.aliasprefix'):
419 for view in showview._table:
419 for view in showview._table:
420 name = '%s%s' % (prefix, view)
420 name = '%s%s' % (prefix, view)
421
421
422 choice, allcommands = cmdutil.findpossible(name, commands.table,
422 choice, allcommands = cmdutil.findpossible(name, commands.table,
423 strict=True)
423 strict=True)
424
424
425 # This alias is already a command name. Don't set it.
425 # This alias is already a command name. Don't set it.
426 if name in choice:
426 if name in choice:
427 continue
427 continue
428
428
429 # Same for aliases.
429 # Same for aliases.
430 if ui.config('alias', name):
430 if ui.config('alias', name, None):
431 continue
431 continue
432
432
433 ui.setconfig('alias', name, 'show %s' % view, source='show')
433 ui.setconfig('alias', name, 'show %s' % view, source='show')
434
434
435 def longestshortest(repo, revs, minlen=4):
435 def longestshortest(repo, revs, minlen=4):
436 """Return the length of the longest shortest node to identify revisions.
436 """Return the length of the longest shortest node to identify revisions.
437
437
438 The result of this function can be used with the ``shortest()`` template
438 The result of this function can be used with the ``shortest()`` template
439 function to ensure that a value is unique and unambiguous for a given
439 function to ensure that a value is unique and unambiguous for a given
440 set of nodes.
440 set of nodes.
441
441
442 The number of revisions in the repo is taken into account to prevent
442 The number of revisions in the repo is taken into account to prevent
443 a numeric node prefix from conflicting with an integer revision number.
443 a numeric node prefix from conflicting with an integer revision number.
444 If we fail to do this, a value of e.g. ``10023`` could mean either
444 If we fail to do this, a value of e.g. ``10023`` could mean either
445 revision 10023 or node ``10023abc...``.
445 revision 10023 or node ``10023abc...``.
446 """
446 """
447 if not revs:
447 if not revs:
448 return minlen
448 return minlen
449 # don't use filtered repo because it's slow. see templater.shortest().
449 # don't use filtered repo because it's slow. see templater.shortest().
450 cl = repo.unfiltered().changelog
450 cl = repo.unfiltered().changelog
451 return max(len(cl.shortest(hex(cl.node(r)), minlen)) for r in revs)
451 return max(len(cl.shortest(hex(cl.node(r)), minlen)) for r in revs)
452
452
453 # Adjust the docstring of the show command so it shows all registered views.
453 # Adjust the docstring of the show command so it shows all registered views.
454 # This is a bit hacky because it runs at the end of module load. When moved
454 # This is a bit hacky because it runs at the end of module load. When moved
455 # into core or when another extension wants to provide a view, we'll need
455 # into core or when another extension wants to provide a view, we'll need
456 # to do this more robustly.
456 # to do this more robustly.
457 # TODO make this more robust.
457 # TODO make this more robust.
458 def _updatedocstring():
458 def _updatedocstring():
459 longest = max(map(len, showview._table.keys()))
459 longest = max(map(len, showview._table.keys()))
460 entries = []
460 entries = []
461 for key in sorted(showview._table.keys()):
461 for key in sorted(showview._table.keys()):
462 entries.append(pycompat.sysstr(' %s %s' % (
462 entries.append(pycompat.sysstr(' %s %s' % (
463 key.ljust(longest), showview._table[key]._origdoc)))
463 key.ljust(longest), showview._table[key]._origdoc)))
464
464
465 cmdtable['show'][0].__doc__ = pycompat.sysstr('%s\n\n%s\n ') % (
465 cmdtable['show'][0].__doc__ = pycompat.sysstr('%s\n\n%s\n ') % (
466 cmdtable['show'][0].__doc__.rstrip(),
466 cmdtable['show'][0].__doc__.rstrip(),
467 pycompat.sysstr('\n\n').join(entries))
467 pycompat.sysstr('\n\n').join(entries))
468
468
469 _updatedocstring()
469 _updatedocstring()
@@ -1,1320 +1,1320 b''
1 # configitems.py - centralized declaration of configuration option
1 # configitems.py - centralized declaration of configuration option
2 #
2 #
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import functools
10 import functools
11 import re
11 import re
12
12
13 from . import (
13 from . import (
14 encoding,
14 encoding,
15 error,
15 error,
16 )
16 )
17
17
18 def loadconfigtable(ui, extname, configtable):
18 def loadconfigtable(ui, extname, configtable):
19 """update config item known to the ui with the extension ones"""
19 """update config item known to the ui with the extension ones"""
20 for section, items in sorted(configtable.items()):
20 for section, items in sorted(configtable.items()):
21 knownitems = ui._knownconfig.setdefault(section, itemregister())
21 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 knownkeys = set(knownitems)
22 knownkeys = set(knownitems)
23 newkeys = set(items)
23 newkeys = set(items)
24 for key in sorted(knownkeys & newkeys):
24 for key in sorted(knownkeys & newkeys):
25 msg = "extension '%s' overwrite config item '%s.%s'"
25 msg = "extension '%s' overwrite config item '%s.%s'"
26 msg %= (extname, section, key)
26 msg %= (extname, section, key)
27 ui.develwarn(msg, config='warn-config')
27 ui.develwarn(msg, config='warn-config')
28
28
29 knownitems.update(items)
29 knownitems.update(items)
30
30
31 class configitem(object):
31 class configitem(object):
32 """represent a known config item
32 """represent a known config item
33
33
34 :section: the official config section where to find this item,
34 :section: the official config section where to find this item,
35 :name: the official name within the section,
35 :name: the official name within the section,
36 :default: default value for this item,
36 :default: default value for this item,
37 :alias: optional list of tuples as alternatives,
37 :alias: optional list of tuples as alternatives,
38 :generic: this is a generic definition, match name using regular expression.
38 :generic: this is a generic definition, match name using regular expression.
39 """
39 """
40
40
41 def __init__(self, section, name, default=None, alias=(),
41 def __init__(self, section, name, default=None, alias=(),
42 generic=False, priority=0):
42 generic=False, priority=0):
43 self.section = section
43 self.section = section
44 self.name = name
44 self.name = name
45 self.default = default
45 self.default = default
46 self.alias = list(alias)
46 self.alias = list(alias)
47 self.generic = generic
47 self.generic = generic
48 self.priority = priority
48 self.priority = priority
49 self._re = None
49 self._re = None
50 if generic:
50 if generic:
51 self._re = re.compile(self.name)
51 self._re = re.compile(self.name)
52
52
53 class itemregister(dict):
53 class itemregister(dict):
54 """A specialized dictionary that can handle wild-card selection"""
54 """A specialized dictionary that can handle wild-card selection"""
55
55
56 def __init__(self):
56 def __init__(self):
57 super(itemregister, self).__init__()
57 super(itemregister, self).__init__()
58 self._generics = set()
58 self._generics = set()
59
59
60 def update(self, other):
60 def update(self, other):
61 super(itemregister, self).update(other)
61 super(itemregister, self).update(other)
62 self._generics.update(other._generics)
62 self._generics.update(other._generics)
63
63
64 def __setitem__(self, key, item):
64 def __setitem__(self, key, item):
65 super(itemregister, self).__setitem__(key, item)
65 super(itemregister, self).__setitem__(key, item)
66 if item.generic:
66 if item.generic:
67 self._generics.add(item)
67 self._generics.add(item)
68
68
69 def get(self, key):
69 def get(self, key):
70 baseitem = super(itemregister, self).get(key)
70 baseitem = super(itemregister, self).get(key)
71 if baseitem is not None and not baseitem.generic:
71 if baseitem is not None and not baseitem.generic:
72 return baseitem
72 return baseitem
73
73
74 # search for a matching generic item
74 # search for a matching generic item
75 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
75 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
76 for item in generics:
76 for item in generics:
77 # we use 'match' instead of 'search' to make the matching simpler
77 # we use 'match' instead of 'search' to make the matching simpler
78 # for people unfamiliar with regular expression. Having the match
78 # for people unfamiliar with regular expression. Having the match
79 # rooted to the start of the string will produce less surprising
79 # rooted to the start of the string will produce less surprising
80 # result for user writing simple regex for sub-attribute.
80 # result for user writing simple regex for sub-attribute.
81 #
81 #
82 # For example using "color\..*" match produces an unsurprising
82 # For example using "color\..*" match produces an unsurprising
83 # result, while using search could suddenly match apparently
83 # result, while using search could suddenly match apparently
84 # unrelated configuration that happens to contains "color."
84 # unrelated configuration that happens to contains "color."
85 # anywhere. This is a tradeoff where we favor requiring ".*" on
85 # anywhere. This is a tradeoff where we favor requiring ".*" on
86 # some match to avoid the need to prefix most pattern with "^".
86 # some match to avoid the need to prefix most pattern with "^".
87 # The "^" seems more error prone.
87 # The "^" seems more error prone.
88 if item._re.match(key):
88 if item._re.match(key):
89 return item
89 return item
90
90
91 return None
91 return None
92
92
93 coreitems = {}
93 coreitems = {}
94
94
95 def _register(configtable, *args, **kwargs):
95 def _register(configtable, *args, **kwargs):
96 item = configitem(*args, **kwargs)
96 item = configitem(*args, **kwargs)
97 section = configtable.setdefault(item.section, itemregister())
97 section = configtable.setdefault(item.section, itemregister())
98 if item.name in section:
98 if item.name in section:
99 msg = "duplicated config item registration for '%s.%s'"
99 msg = "duplicated config item registration for '%s.%s'"
100 raise error.ProgrammingError(msg % (item.section, item.name))
100 raise error.ProgrammingError(msg % (item.section, item.name))
101 section[item.name] = item
101 section[item.name] = item
102
102
103 # special value for case where the default is derived from other values
103 # special value for case where the default is derived from other values
104 dynamicdefault = object()
104 dynamicdefault = object()
105
105
106 # Registering actual config items
106 # Registering actual config items
107
107
108 def getitemregister(configtable):
108 def getitemregister(configtable):
109 f = functools.partial(_register, configtable)
109 f = functools.partial(_register, configtable)
110 # export pseudo enum as configitem.*
110 # export pseudo enum as configitem.*
111 f.dynamicdefault = dynamicdefault
111 f.dynamicdefault = dynamicdefault
112 return f
112 return f
113
113
114 coreconfigitem = getitemregister(coreitems)
114 coreconfigitem = getitemregister(coreitems)
115
115
116 coreconfigitem('alias', '.*',
116 coreconfigitem('alias', '.*',
117 default=None,
117 default=dynamicdefault,
118 generic=True,
118 generic=True,
119 )
119 )
120 coreconfigitem('annotate', 'nodates',
120 coreconfigitem('annotate', 'nodates',
121 default=False,
121 default=False,
122 )
122 )
123 coreconfigitem('annotate', 'showfunc',
123 coreconfigitem('annotate', 'showfunc',
124 default=False,
124 default=False,
125 )
125 )
126 coreconfigitem('annotate', 'unified',
126 coreconfigitem('annotate', 'unified',
127 default=None,
127 default=None,
128 )
128 )
129 coreconfigitem('annotate', 'git',
129 coreconfigitem('annotate', 'git',
130 default=False,
130 default=False,
131 )
131 )
132 coreconfigitem('annotate', 'ignorews',
132 coreconfigitem('annotate', 'ignorews',
133 default=False,
133 default=False,
134 )
134 )
135 coreconfigitem('annotate', 'ignorewsamount',
135 coreconfigitem('annotate', 'ignorewsamount',
136 default=False,
136 default=False,
137 )
137 )
138 coreconfigitem('annotate', 'ignoreblanklines',
138 coreconfigitem('annotate', 'ignoreblanklines',
139 default=False,
139 default=False,
140 )
140 )
141 coreconfigitem('annotate', 'ignorewseol',
141 coreconfigitem('annotate', 'ignorewseol',
142 default=False,
142 default=False,
143 )
143 )
144 coreconfigitem('annotate', 'nobinary',
144 coreconfigitem('annotate', 'nobinary',
145 default=False,
145 default=False,
146 )
146 )
147 coreconfigitem('annotate', 'noprefix',
147 coreconfigitem('annotate', 'noprefix',
148 default=False,
148 default=False,
149 )
149 )
150 coreconfigitem('auth', 'cookiefile',
150 coreconfigitem('auth', 'cookiefile',
151 default=None,
151 default=None,
152 )
152 )
153 # bookmarks.pushing: internal hack for discovery
153 # bookmarks.pushing: internal hack for discovery
154 coreconfigitem('bookmarks', 'pushing',
154 coreconfigitem('bookmarks', 'pushing',
155 default=list,
155 default=list,
156 )
156 )
157 # bundle.mainreporoot: internal hack for bundlerepo
157 # bundle.mainreporoot: internal hack for bundlerepo
158 coreconfigitem('bundle', 'mainreporoot',
158 coreconfigitem('bundle', 'mainreporoot',
159 default='',
159 default='',
160 )
160 )
161 # bundle.reorder: experimental config
161 # bundle.reorder: experimental config
162 coreconfigitem('bundle', 'reorder',
162 coreconfigitem('bundle', 'reorder',
163 default='auto',
163 default='auto',
164 )
164 )
165 coreconfigitem('censor', 'policy',
165 coreconfigitem('censor', 'policy',
166 default='abort',
166 default='abort',
167 )
167 )
168 coreconfigitem('chgserver', 'idletimeout',
168 coreconfigitem('chgserver', 'idletimeout',
169 default=3600,
169 default=3600,
170 )
170 )
171 coreconfigitem('chgserver', 'skiphash',
171 coreconfigitem('chgserver', 'skiphash',
172 default=False,
172 default=False,
173 )
173 )
174 coreconfigitem('cmdserver', 'log',
174 coreconfigitem('cmdserver', 'log',
175 default=None,
175 default=None,
176 )
176 )
177 coreconfigitem('color', '.*',
177 coreconfigitem('color', '.*',
178 default=None,
178 default=None,
179 generic=True,
179 generic=True,
180 )
180 )
181 coreconfigitem('color', 'mode',
181 coreconfigitem('color', 'mode',
182 default='auto',
182 default='auto',
183 )
183 )
184 coreconfigitem('color', 'pagermode',
184 coreconfigitem('color', 'pagermode',
185 default=dynamicdefault,
185 default=dynamicdefault,
186 )
186 )
187 coreconfigitem('commands', 'show.aliasprefix',
187 coreconfigitem('commands', 'show.aliasprefix',
188 default=list,
188 default=list,
189 )
189 )
190 coreconfigitem('commands', 'status.relative',
190 coreconfigitem('commands', 'status.relative',
191 default=False,
191 default=False,
192 )
192 )
193 coreconfigitem('commands', 'status.skipstates',
193 coreconfigitem('commands', 'status.skipstates',
194 default=[],
194 default=[],
195 )
195 )
196 coreconfigitem('commands', 'status.verbose',
196 coreconfigitem('commands', 'status.verbose',
197 default=False,
197 default=False,
198 )
198 )
199 coreconfigitem('commands', 'update.check',
199 coreconfigitem('commands', 'update.check',
200 default=None,
200 default=None,
201 # Deprecated, remove after 4.4 release
201 # Deprecated, remove after 4.4 release
202 alias=[('experimental', 'updatecheck')]
202 alias=[('experimental', 'updatecheck')]
203 )
203 )
204 coreconfigitem('commands', 'update.requiredest',
204 coreconfigitem('commands', 'update.requiredest',
205 default=False,
205 default=False,
206 )
206 )
207 coreconfigitem('committemplate', '.*',
207 coreconfigitem('committemplate', '.*',
208 default=None,
208 default=None,
209 generic=True,
209 generic=True,
210 )
210 )
211 coreconfigitem('convert', 'cvsps.cache',
211 coreconfigitem('convert', 'cvsps.cache',
212 default=True,
212 default=True,
213 )
213 )
214 coreconfigitem('convert', 'cvsps.fuzz',
214 coreconfigitem('convert', 'cvsps.fuzz',
215 default=60,
215 default=60,
216 )
216 )
217 coreconfigitem('convert', 'cvsps.logencoding',
217 coreconfigitem('convert', 'cvsps.logencoding',
218 default=None,
218 default=None,
219 )
219 )
220 coreconfigitem('convert', 'cvsps.mergefrom',
220 coreconfigitem('convert', 'cvsps.mergefrom',
221 default=None,
221 default=None,
222 )
222 )
223 coreconfigitem('convert', 'cvsps.mergeto',
223 coreconfigitem('convert', 'cvsps.mergeto',
224 default=None,
224 default=None,
225 )
225 )
226 coreconfigitem('convert', 'git.committeractions',
226 coreconfigitem('convert', 'git.committeractions',
227 default=lambda: ['messagedifferent'],
227 default=lambda: ['messagedifferent'],
228 )
228 )
229 coreconfigitem('convert', 'git.extrakeys',
229 coreconfigitem('convert', 'git.extrakeys',
230 default=list,
230 default=list,
231 )
231 )
232 coreconfigitem('convert', 'git.findcopiesharder',
232 coreconfigitem('convert', 'git.findcopiesharder',
233 default=False,
233 default=False,
234 )
234 )
235 coreconfigitem('convert', 'git.remoteprefix',
235 coreconfigitem('convert', 'git.remoteprefix',
236 default='remote',
236 default='remote',
237 )
237 )
238 coreconfigitem('convert', 'git.renamelimit',
238 coreconfigitem('convert', 'git.renamelimit',
239 default=400,
239 default=400,
240 )
240 )
241 coreconfigitem('convert', 'git.saverev',
241 coreconfigitem('convert', 'git.saverev',
242 default=True,
242 default=True,
243 )
243 )
244 coreconfigitem('convert', 'git.similarity',
244 coreconfigitem('convert', 'git.similarity',
245 default=50,
245 default=50,
246 )
246 )
247 coreconfigitem('convert', 'git.skipsubmodules',
247 coreconfigitem('convert', 'git.skipsubmodules',
248 default=False,
248 default=False,
249 )
249 )
250 coreconfigitem('convert', 'hg.clonebranches',
250 coreconfigitem('convert', 'hg.clonebranches',
251 default=False,
251 default=False,
252 )
252 )
253 coreconfigitem('convert', 'hg.ignoreerrors',
253 coreconfigitem('convert', 'hg.ignoreerrors',
254 default=False,
254 default=False,
255 )
255 )
256 coreconfigitem('convert', 'hg.revs',
256 coreconfigitem('convert', 'hg.revs',
257 default=None,
257 default=None,
258 )
258 )
259 coreconfigitem('convert', 'hg.saverev',
259 coreconfigitem('convert', 'hg.saverev',
260 default=False,
260 default=False,
261 )
261 )
262 coreconfigitem('convert', 'hg.sourcename',
262 coreconfigitem('convert', 'hg.sourcename',
263 default=None,
263 default=None,
264 )
264 )
265 coreconfigitem('convert', 'hg.startrev',
265 coreconfigitem('convert', 'hg.startrev',
266 default=None,
266 default=None,
267 )
267 )
268 coreconfigitem('convert', 'hg.tagsbranch',
268 coreconfigitem('convert', 'hg.tagsbranch',
269 default='default',
269 default='default',
270 )
270 )
271 coreconfigitem('convert', 'hg.usebranchnames',
271 coreconfigitem('convert', 'hg.usebranchnames',
272 default=True,
272 default=True,
273 )
273 )
274 coreconfigitem('convert', 'ignoreancestorcheck',
274 coreconfigitem('convert', 'ignoreancestorcheck',
275 default=False,
275 default=False,
276 )
276 )
277 coreconfigitem('convert', 'localtimezone',
277 coreconfigitem('convert', 'localtimezone',
278 default=False,
278 default=False,
279 )
279 )
280 coreconfigitem('convert', 'p4.encoding',
280 coreconfigitem('convert', 'p4.encoding',
281 default=dynamicdefault,
281 default=dynamicdefault,
282 )
282 )
283 coreconfigitem('convert', 'p4.startrev',
283 coreconfigitem('convert', 'p4.startrev',
284 default=0,
284 default=0,
285 )
285 )
286 coreconfigitem('convert', 'skiptags',
286 coreconfigitem('convert', 'skiptags',
287 default=False,
287 default=False,
288 )
288 )
289 coreconfigitem('convert', 'svn.debugsvnlog',
289 coreconfigitem('convert', 'svn.debugsvnlog',
290 default=True,
290 default=True,
291 )
291 )
292 coreconfigitem('convert', 'svn.trunk',
292 coreconfigitem('convert', 'svn.trunk',
293 default=None,
293 default=None,
294 )
294 )
295 coreconfigitem('convert', 'svn.tags',
295 coreconfigitem('convert', 'svn.tags',
296 default=None,
296 default=None,
297 )
297 )
298 coreconfigitem('convert', 'svn.branches',
298 coreconfigitem('convert', 'svn.branches',
299 default=None,
299 default=None,
300 )
300 )
301 coreconfigitem('convert', 'svn.startrev',
301 coreconfigitem('convert', 'svn.startrev',
302 default=0,
302 default=0,
303 )
303 )
304 coreconfigitem('debug', 'dirstate.delaywrite',
304 coreconfigitem('debug', 'dirstate.delaywrite',
305 default=0,
305 default=0,
306 )
306 )
307 coreconfigitem('defaults', '.*',
307 coreconfigitem('defaults', '.*',
308 default=None,
308 default=None,
309 generic=True,
309 generic=True,
310 )
310 )
311 coreconfigitem('devel', 'all-warnings',
311 coreconfigitem('devel', 'all-warnings',
312 default=False,
312 default=False,
313 )
313 )
314 coreconfigitem('devel', 'bundle2.debug',
314 coreconfigitem('devel', 'bundle2.debug',
315 default=False,
315 default=False,
316 )
316 )
317 coreconfigitem('devel', 'cache-vfs',
317 coreconfigitem('devel', 'cache-vfs',
318 default=None,
318 default=None,
319 )
319 )
320 coreconfigitem('devel', 'check-locks',
320 coreconfigitem('devel', 'check-locks',
321 default=False,
321 default=False,
322 )
322 )
323 coreconfigitem('devel', 'check-relroot',
323 coreconfigitem('devel', 'check-relroot',
324 default=False,
324 default=False,
325 )
325 )
326 coreconfigitem('devel', 'default-date',
326 coreconfigitem('devel', 'default-date',
327 default=None,
327 default=None,
328 )
328 )
329 coreconfigitem('devel', 'deprec-warn',
329 coreconfigitem('devel', 'deprec-warn',
330 default=False,
330 default=False,
331 )
331 )
332 coreconfigitem('devel', 'disableloaddefaultcerts',
332 coreconfigitem('devel', 'disableloaddefaultcerts',
333 default=False,
333 default=False,
334 )
334 )
335 coreconfigitem('devel', 'warn-empty-changegroup',
335 coreconfigitem('devel', 'warn-empty-changegroup',
336 default=False,
336 default=False,
337 )
337 )
338 coreconfigitem('devel', 'legacy.exchange',
338 coreconfigitem('devel', 'legacy.exchange',
339 default=list,
339 default=list,
340 )
340 )
341 coreconfigitem('devel', 'servercafile',
341 coreconfigitem('devel', 'servercafile',
342 default='',
342 default='',
343 )
343 )
344 coreconfigitem('devel', 'serverexactprotocol',
344 coreconfigitem('devel', 'serverexactprotocol',
345 default='',
345 default='',
346 )
346 )
347 coreconfigitem('devel', 'serverrequirecert',
347 coreconfigitem('devel', 'serverrequirecert',
348 default=False,
348 default=False,
349 )
349 )
350 coreconfigitem('devel', 'strip-obsmarkers',
350 coreconfigitem('devel', 'strip-obsmarkers',
351 default=True,
351 default=True,
352 )
352 )
353 coreconfigitem('devel', 'warn-config',
353 coreconfigitem('devel', 'warn-config',
354 default=None,
354 default=None,
355 )
355 )
356 coreconfigitem('devel', 'warn-config-default',
356 coreconfigitem('devel', 'warn-config-default',
357 default=None,
357 default=None,
358 )
358 )
359 coreconfigitem('devel', 'user.obsmarker',
359 coreconfigitem('devel', 'user.obsmarker',
360 default=None,
360 default=None,
361 )
361 )
362 coreconfigitem('devel', 'warn-config-unknown',
362 coreconfigitem('devel', 'warn-config-unknown',
363 default=None,
363 default=None,
364 )
364 )
365 coreconfigitem('devel', 'debug.peer-request',
365 coreconfigitem('devel', 'debug.peer-request',
366 default=False,
366 default=False,
367 )
367 )
368 coreconfigitem('diff', 'nodates',
368 coreconfigitem('diff', 'nodates',
369 default=False,
369 default=False,
370 )
370 )
371 coreconfigitem('diff', 'showfunc',
371 coreconfigitem('diff', 'showfunc',
372 default=False,
372 default=False,
373 )
373 )
374 coreconfigitem('diff', 'unified',
374 coreconfigitem('diff', 'unified',
375 default=None,
375 default=None,
376 )
376 )
377 coreconfigitem('diff', 'git',
377 coreconfigitem('diff', 'git',
378 default=False,
378 default=False,
379 )
379 )
380 coreconfigitem('diff', 'ignorews',
380 coreconfigitem('diff', 'ignorews',
381 default=False,
381 default=False,
382 )
382 )
383 coreconfigitem('diff', 'ignorewsamount',
383 coreconfigitem('diff', 'ignorewsamount',
384 default=False,
384 default=False,
385 )
385 )
386 coreconfigitem('diff', 'ignoreblanklines',
386 coreconfigitem('diff', 'ignoreblanklines',
387 default=False,
387 default=False,
388 )
388 )
389 coreconfigitem('diff', 'ignorewseol',
389 coreconfigitem('diff', 'ignorewseol',
390 default=False,
390 default=False,
391 )
391 )
392 coreconfigitem('diff', 'nobinary',
392 coreconfigitem('diff', 'nobinary',
393 default=False,
393 default=False,
394 )
394 )
395 coreconfigitem('diff', 'noprefix',
395 coreconfigitem('diff', 'noprefix',
396 default=False,
396 default=False,
397 )
397 )
398 coreconfigitem('email', 'bcc',
398 coreconfigitem('email', 'bcc',
399 default=None,
399 default=None,
400 )
400 )
401 coreconfigitem('email', 'cc',
401 coreconfigitem('email', 'cc',
402 default=None,
402 default=None,
403 )
403 )
404 coreconfigitem('email', 'charsets',
404 coreconfigitem('email', 'charsets',
405 default=list,
405 default=list,
406 )
406 )
407 coreconfigitem('email', 'from',
407 coreconfigitem('email', 'from',
408 default=None,
408 default=None,
409 )
409 )
410 coreconfigitem('email', 'method',
410 coreconfigitem('email', 'method',
411 default='smtp',
411 default='smtp',
412 )
412 )
413 coreconfigitem('email', 'reply-to',
413 coreconfigitem('email', 'reply-to',
414 default=None,
414 default=None,
415 )
415 )
416 coreconfigitem('email', 'to',
416 coreconfigitem('email', 'to',
417 default=None,
417 default=None,
418 )
418 )
419 coreconfigitem('experimental', 'archivemetatemplate',
419 coreconfigitem('experimental', 'archivemetatemplate',
420 default=dynamicdefault,
420 default=dynamicdefault,
421 )
421 )
422 coreconfigitem('experimental', 'bundle-phases',
422 coreconfigitem('experimental', 'bundle-phases',
423 default=False,
423 default=False,
424 )
424 )
425 coreconfigitem('experimental', 'bundle2-advertise',
425 coreconfigitem('experimental', 'bundle2-advertise',
426 default=True,
426 default=True,
427 )
427 )
428 coreconfigitem('experimental', 'bundle2-output-capture',
428 coreconfigitem('experimental', 'bundle2-output-capture',
429 default=False,
429 default=False,
430 )
430 )
431 coreconfigitem('experimental', 'bundle2.pushback',
431 coreconfigitem('experimental', 'bundle2.pushback',
432 default=False,
432 default=False,
433 )
433 )
434 coreconfigitem('experimental', 'bundle2.stream',
434 coreconfigitem('experimental', 'bundle2.stream',
435 default=False,
435 default=False,
436 )
436 )
437 coreconfigitem('experimental', 'bundle2lazylocking',
437 coreconfigitem('experimental', 'bundle2lazylocking',
438 default=False,
438 default=False,
439 )
439 )
440 coreconfigitem('experimental', 'bundlecomplevel',
440 coreconfigitem('experimental', 'bundlecomplevel',
441 default=None,
441 default=None,
442 )
442 )
443 coreconfigitem('experimental', 'changegroup3',
443 coreconfigitem('experimental', 'changegroup3',
444 default=False,
444 default=False,
445 )
445 )
446 coreconfigitem('experimental', 'clientcompressionengines',
446 coreconfigitem('experimental', 'clientcompressionengines',
447 default=list,
447 default=list,
448 )
448 )
449 coreconfigitem('experimental', 'copytrace',
449 coreconfigitem('experimental', 'copytrace',
450 default='on',
450 default='on',
451 )
451 )
452 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
452 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
453 default=100,
453 default=100,
454 )
454 )
455 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
455 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
456 default=100,
456 default=100,
457 )
457 )
458 coreconfigitem('experimental', 'crecordtest',
458 coreconfigitem('experimental', 'crecordtest',
459 default=None,
459 default=None,
460 )
460 )
461 coreconfigitem('experimental', 'directaccess',
461 coreconfigitem('experimental', 'directaccess',
462 default=False,
462 default=False,
463 )
463 )
464 coreconfigitem('experimental', 'directaccess.revnums',
464 coreconfigitem('experimental', 'directaccess.revnums',
465 default=False,
465 default=False,
466 )
466 )
467 coreconfigitem('experimental', 'editortmpinhg',
467 coreconfigitem('experimental', 'editortmpinhg',
468 default=False,
468 default=False,
469 )
469 )
470 coreconfigitem('experimental', 'evolution',
470 coreconfigitem('experimental', 'evolution',
471 default=list,
471 default=list,
472 )
472 )
473 coreconfigitem('experimental', 'evolution.allowdivergence',
473 coreconfigitem('experimental', 'evolution.allowdivergence',
474 default=False,
474 default=False,
475 alias=[('experimental', 'allowdivergence')]
475 alias=[('experimental', 'allowdivergence')]
476 )
476 )
477 coreconfigitem('experimental', 'evolution.allowunstable',
477 coreconfigitem('experimental', 'evolution.allowunstable',
478 default=None,
478 default=None,
479 )
479 )
480 coreconfigitem('experimental', 'evolution.createmarkers',
480 coreconfigitem('experimental', 'evolution.createmarkers',
481 default=None,
481 default=None,
482 )
482 )
483 coreconfigitem('experimental', 'evolution.effect-flags',
483 coreconfigitem('experimental', 'evolution.effect-flags',
484 default=True,
484 default=True,
485 alias=[('experimental', 'effect-flags')]
485 alias=[('experimental', 'effect-flags')]
486 )
486 )
487 coreconfigitem('experimental', 'evolution.exchange',
487 coreconfigitem('experimental', 'evolution.exchange',
488 default=None,
488 default=None,
489 )
489 )
490 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
490 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
491 default=False,
491 default=False,
492 )
492 )
493 coreconfigitem('experimental', 'evolution.report-instabilities',
493 coreconfigitem('experimental', 'evolution.report-instabilities',
494 default=True,
494 default=True,
495 )
495 )
496 coreconfigitem('experimental', 'evolution.track-operation',
496 coreconfigitem('experimental', 'evolution.track-operation',
497 default=True,
497 default=True,
498 )
498 )
499 coreconfigitem('experimental', 'worddiff',
499 coreconfigitem('experimental', 'worddiff',
500 default=False,
500 default=False,
501 )
501 )
502 coreconfigitem('experimental', 'maxdeltachainspan',
502 coreconfigitem('experimental', 'maxdeltachainspan',
503 default=-1,
503 default=-1,
504 )
504 )
505 coreconfigitem('experimental', 'mergetempdirprefix',
505 coreconfigitem('experimental', 'mergetempdirprefix',
506 default=None,
506 default=None,
507 )
507 )
508 coreconfigitem('experimental', 'mmapindexthreshold',
508 coreconfigitem('experimental', 'mmapindexthreshold',
509 default=None,
509 default=None,
510 )
510 )
511 coreconfigitem('experimental', 'nonnormalparanoidcheck',
511 coreconfigitem('experimental', 'nonnormalparanoidcheck',
512 default=False,
512 default=False,
513 )
513 )
514 coreconfigitem('experimental', 'exportableenviron',
514 coreconfigitem('experimental', 'exportableenviron',
515 default=list,
515 default=list,
516 )
516 )
517 coreconfigitem('experimental', 'extendedheader.index',
517 coreconfigitem('experimental', 'extendedheader.index',
518 default=None,
518 default=None,
519 )
519 )
520 coreconfigitem('experimental', 'extendedheader.similarity',
520 coreconfigitem('experimental', 'extendedheader.similarity',
521 default=False,
521 default=False,
522 )
522 )
523 coreconfigitem('experimental', 'format.compression',
523 coreconfigitem('experimental', 'format.compression',
524 default='zlib',
524 default='zlib',
525 )
525 )
526 coreconfigitem('experimental', 'graphshorten',
526 coreconfigitem('experimental', 'graphshorten',
527 default=False,
527 default=False,
528 )
528 )
529 coreconfigitem('experimental', 'graphstyle.parent',
529 coreconfigitem('experimental', 'graphstyle.parent',
530 default=dynamicdefault,
530 default=dynamicdefault,
531 )
531 )
532 coreconfigitem('experimental', 'graphstyle.missing',
532 coreconfigitem('experimental', 'graphstyle.missing',
533 default=dynamicdefault,
533 default=dynamicdefault,
534 )
534 )
535 coreconfigitem('experimental', 'graphstyle.grandparent',
535 coreconfigitem('experimental', 'graphstyle.grandparent',
536 default=dynamicdefault,
536 default=dynamicdefault,
537 )
537 )
538 coreconfigitem('experimental', 'hook-track-tags',
538 coreconfigitem('experimental', 'hook-track-tags',
539 default=False,
539 default=False,
540 )
540 )
541 coreconfigitem('experimental', 'httppostargs',
541 coreconfigitem('experimental', 'httppostargs',
542 default=False,
542 default=False,
543 )
543 )
544 coreconfigitem('experimental', 'mergedriver',
544 coreconfigitem('experimental', 'mergedriver',
545 default=None,
545 default=None,
546 )
546 )
547 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
547 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
548 default=False,
548 default=False,
549 )
549 )
550 coreconfigitem('experimental', 'remotenames',
550 coreconfigitem('experimental', 'remotenames',
551 default=False,
551 default=False,
552 )
552 )
553 coreconfigitem('experimental', 'revlogv2',
553 coreconfigitem('experimental', 'revlogv2',
554 default=None,
554 default=None,
555 )
555 )
556 coreconfigitem('experimental', 'single-head-per-branch',
556 coreconfigitem('experimental', 'single-head-per-branch',
557 default=False,
557 default=False,
558 )
558 )
559 coreconfigitem('experimental', 'sshserver.support-v2',
559 coreconfigitem('experimental', 'sshserver.support-v2',
560 default=False,
560 default=False,
561 )
561 )
562 coreconfigitem('experimental', 'spacemovesdown',
562 coreconfigitem('experimental', 'spacemovesdown',
563 default=False,
563 default=False,
564 )
564 )
565 coreconfigitem('experimental', 'sparse-read',
565 coreconfigitem('experimental', 'sparse-read',
566 default=False,
566 default=False,
567 )
567 )
568 coreconfigitem('experimental', 'sparse-read.density-threshold',
568 coreconfigitem('experimental', 'sparse-read.density-threshold',
569 default=0.25,
569 default=0.25,
570 )
570 )
571 coreconfigitem('experimental', 'sparse-read.min-gap-size',
571 coreconfigitem('experimental', 'sparse-read.min-gap-size',
572 default='256K',
572 default='256K',
573 )
573 )
574 coreconfigitem('experimental', 'treemanifest',
574 coreconfigitem('experimental', 'treemanifest',
575 default=False,
575 default=False,
576 )
576 )
577 coreconfigitem('experimental', 'update.atomic-file',
577 coreconfigitem('experimental', 'update.atomic-file',
578 default=False,
578 default=False,
579 )
579 )
580 coreconfigitem('experimental', 'sshpeer.advertise-v2',
580 coreconfigitem('experimental', 'sshpeer.advertise-v2',
581 default=False,
581 default=False,
582 )
582 )
583 coreconfigitem('experimental', 'web.apiserver',
583 coreconfigitem('experimental', 'web.apiserver',
584 default=False,
584 default=False,
585 )
585 )
586 coreconfigitem('experimental', 'web.api.http-v2',
586 coreconfigitem('experimental', 'web.api.http-v2',
587 default=False,
587 default=False,
588 )
588 )
589 coreconfigitem('experimental', 'web.api.debugreflect',
589 coreconfigitem('experimental', 'web.api.debugreflect',
590 default=False,
590 default=False,
591 )
591 )
592 coreconfigitem('experimental', 'xdiff',
592 coreconfigitem('experimental', 'xdiff',
593 default=False,
593 default=False,
594 )
594 )
595 coreconfigitem('extensions', '.*',
595 coreconfigitem('extensions', '.*',
596 default=None,
596 default=None,
597 generic=True,
597 generic=True,
598 )
598 )
599 coreconfigitem('extdata', '.*',
599 coreconfigitem('extdata', '.*',
600 default=None,
600 default=None,
601 generic=True,
601 generic=True,
602 )
602 )
603 coreconfigitem('format', 'aggressivemergedeltas',
603 coreconfigitem('format', 'aggressivemergedeltas',
604 default=False,
604 default=False,
605 )
605 )
606 coreconfigitem('format', 'chunkcachesize',
606 coreconfigitem('format', 'chunkcachesize',
607 default=None,
607 default=None,
608 )
608 )
609 coreconfigitem('format', 'dotencode',
609 coreconfigitem('format', 'dotencode',
610 default=True,
610 default=True,
611 )
611 )
612 coreconfigitem('format', 'generaldelta',
612 coreconfigitem('format', 'generaldelta',
613 default=False,
613 default=False,
614 )
614 )
615 coreconfigitem('format', 'manifestcachesize',
615 coreconfigitem('format', 'manifestcachesize',
616 default=None,
616 default=None,
617 )
617 )
618 coreconfigitem('format', 'maxchainlen',
618 coreconfigitem('format', 'maxchainlen',
619 default=None,
619 default=None,
620 )
620 )
621 coreconfigitem('format', 'obsstore-version',
621 coreconfigitem('format', 'obsstore-version',
622 default=None,
622 default=None,
623 )
623 )
624 coreconfigitem('format', 'usefncache',
624 coreconfigitem('format', 'usefncache',
625 default=True,
625 default=True,
626 )
626 )
627 coreconfigitem('format', 'usegeneraldelta',
627 coreconfigitem('format', 'usegeneraldelta',
628 default=True,
628 default=True,
629 )
629 )
630 coreconfigitem('format', 'usestore',
630 coreconfigitem('format', 'usestore',
631 default=True,
631 default=True,
632 )
632 )
633 coreconfigitem('fsmonitor', 'warn_when_unused',
633 coreconfigitem('fsmonitor', 'warn_when_unused',
634 default=True,
634 default=True,
635 )
635 )
636 coreconfigitem('fsmonitor', 'warn_update_file_count',
636 coreconfigitem('fsmonitor', 'warn_update_file_count',
637 default=50000,
637 default=50000,
638 )
638 )
639 coreconfigitem('hooks', '.*',
639 coreconfigitem('hooks', '.*',
640 default=dynamicdefault,
640 default=dynamicdefault,
641 generic=True,
641 generic=True,
642 )
642 )
643 coreconfigitem('hgweb-paths', '.*',
643 coreconfigitem('hgweb-paths', '.*',
644 default=list,
644 default=list,
645 generic=True,
645 generic=True,
646 )
646 )
647 coreconfigitem('hostfingerprints', '.*',
647 coreconfigitem('hostfingerprints', '.*',
648 default=list,
648 default=list,
649 generic=True,
649 generic=True,
650 )
650 )
651 coreconfigitem('hostsecurity', 'ciphers',
651 coreconfigitem('hostsecurity', 'ciphers',
652 default=None,
652 default=None,
653 )
653 )
654 coreconfigitem('hostsecurity', 'disabletls10warning',
654 coreconfigitem('hostsecurity', 'disabletls10warning',
655 default=False,
655 default=False,
656 )
656 )
657 coreconfigitem('hostsecurity', 'minimumprotocol',
657 coreconfigitem('hostsecurity', 'minimumprotocol',
658 default=dynamicdefault,
658 default=dynamicdefault,
659 )
659 )
660 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
660 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
661 default=dynamicdefault,
661 default=dynamicdefault,
662 generic=True,
662 generic=True,
663 )
663 )
664 coreconfigitem('hostsecurity', '.*:ciphers$',
664 coreconfigitem('hostsecurity', '.*:ciphers$',
665 default=dynamicdefault,
665 default=dynamicdefault,
666 generic=True,
666 generic=True,
667 )
667 )
668 coreconfigitem('hostsecurity', '.*:fingerprints$',
668 coreconfigitem('hostsecurity', '.*:fingerprints$',
669 default=list,
669 default=list,
670 generic=True,
670 generic=True,
671 )
671 )
672 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
672 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
673 default=None,
673 default=None,
674 generic=True,
674 generic=True,
675 )
675 )
676
676
677 coreconfigitem('http_proxy', 'always',
677 coreconfigitem('http_proxy', 'always',
678 default=False,
678 default=False,
679 )
679 )
680 coreconfigitem('http_proxy', 'host',
680 coreconfigitem('http_proxy', 'host',
681 default=None,
681 default=None,
682 )
682 )
683 coreconfigitem('http_proxy', 'no',
683 coreconfigitem('http_proxy', 'no',
684 default=list,
684 default=list,
685 )
685 )
686 coreconfigitem('http_proxy', 'passwd',
686 coreconfigitem('http_proxy', 'passwd',
687 default=None,
687 default=None,
688 )
688 )
689 coreconfigitem('http_proxy', 'user',
689 coreconfigitem('http_proxy', 'user',
690 default=None,
690 default=None,
691 )
691 )
692 coreconfigitem('logtoprocess', 'commandexception',
692 coreconfigitem('logtoprocess', 'commandexception',
693 default=None,
693 default=None,
694 )
694 )
695 coreconfigitem('logtoprocess', 'commandfinish',
695 coreconfigitem('logtoprocess', 'commandfinish',
696 default=None,
696 default=None,
697 )
697 )
698 coreconfigitem('logtoprocess', 'command',
698 coreconfigitem('logtoprocess', 'command',
699 default=None,
699 default=None,
700 )
700 )
701 coreconfigitem('logtoprocess', 'develwarn',
701 coreconfigitem('logtoprocess', 'develwarn',
702 default=None,
702 default=None,
703 )
703 )
704 coreconfigitem('logtoprocess', 'uiblocked',
704 coreconfigitem('logtoprocess', 'uiblocked',
705 default=None,
705 default=None,
706 )
706 )
707 coreconfigitem('merge', 'checkunknown',
707 coreconfigitem('merge', 'checkunknown',
708 default='abort',
708 default='abort',
709 )
709 )
710 coreconfigitem('merge', 'checkignored',
710 coreconfigitem('merge', 'checkignored',
711 default='abort',
711 default='abort',
712 )
712 )
713 coreconfigitem('experimental', 'merge.checkpathconflicts',
713 coreconfigitem('experimental', 'merge.checkpathconflicts',
714 default=False,
714 default=False,
715 )
715 )
716 coreconfigitem('merge', 'followcopies',
716 coreconfigitem('merge', 'followcopies',
717 default=True,
717 default=True,
718 )
718 )
719 coreconfigitem('merge', 'on-failure',
719 coreconfigitem('merge', 'on-failure',
720 default='continue',
720 default='continue',
721 )
721 )
722 coreconfigitem('merge', 'preferancestor',
722 coreconfigitem('merge', 'preferancestor',
723 default=lambda: ['*'],
723 default=lambda: ['*'],
724 )
724 )
725 coreconfigitem('merge-tools', '.*',
725 coreconfigitem('merge-tools', '.*',
726 default=None,
726 default=None,
727 generic=True,
727 generic=True,
728 )
728 )
729 coreconfigitem('merge-tools', br'.*\.args$',
729 coreconfigitem('merge-tools', br'.*\.args$',
730 default="$local $base $other",
730 default="$local $base $other",
731 generic=True,
731 generic=True,
732 priority=-1,
732 priority=-1,
733 )
733 )
734 coreconfigitem('merge-tools', br'.*\.binary$',
734 coreconfigitem('merge-tools', br'.*\.binary$',
735 default=False,
735 default=False,
736 generic=True,
736 generic=True,
737 priority=-1,
737 priority=-1,
738 )
738 )
739 coreconfigitem('merge-tools', br'.*\.check$',
739 coreconfigitem('merge-tools', br'.*\.check$',
740 default=list,
740 default=list,
741 generic=True,
741 generic=True,
742 priority=-1,
742 priority=-1,
743 )
743 )
744 coreconfigitem('merge-tools', br'.*\.checkchanged$',
744 coreconfigitem('merge-tools', br'.*\.checkchanged$',
745 default=False,
745 default=False,
746 generic=True,
746 generic=True,
747 priority=-1,
747 priority=-1,
748 )
748 )
749 coreconfigitem('merge-tools', br'.*\.executable$',
749 coreconfigitem('merge-tools', br'.*\.executable$',
750 default=dynamicdefault,
750 default=dynamicdefault,
751 generic=True,
751 generic=True,
752 priority=-1,
752 priority=-1,
753 )
753 )
754 coreconfigitem('merge-tools', br'.*\.fixeol$',
754 coreconfigitem('merge-tools', br'.*\.fixeol$',
755 default=False,
755 default=False,
756 generic=True,
756 generic=True,
757 priority=-1,
757 priority=-1,
758 )
758 )
759 coreconfigitem('merge-tools', br'.*\.gui$',
759 coreconfigitem('merge-tools', br'.*\.gui$',
760 default=False,
760 default=False,
761 generic=True,
761 generic=True,
762 priority=-1,
762 priority=-1,
763 )
763 )
764 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
764 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
765 default='basic',
765 default='basic',
766 generic=True,
766 generic=True,
767 priority=-1,
767 priority=-1,
768 )
768 )
769 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
769 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
770 default=dynamicdefault, # take from ui.mergemarkertemplate
770 default=dynamicdefault, # take from ui.mergemarkertemplate
771 generic=True,
771 generic=True,
772 priority=-1,
772 priority=-1,
773 )
773 )
774 coreconfigitem('merge-tools', br'.*\.priority$',
774 coreconfigitem('merge-tools', br'.*\.priority$',
775 default=0,
775 default=0,
776 generic=True,
776 generic=True,
777 priority=-1,
777 priority=-1,
778 )
778 )
779 coreconfigitem('merge-tools', br'.*\.premerge$',
779 coreconfigitem('merge-tools', br'.*\.premerge$',
780 default=dynamicdefault,
780 default=dynamicdefault,
781 generic=True,
781 generic=True,
782 priority=-1,
782 priority=-1,
783 )
783 )
784 coreconfigitem('merge-tools', br'.*\.symlink$',
784 coreconfigitem('merge-tools', br'.*\.symlink$',
785 default=False,
785 default=False,
786 generic=True,
786 generic=True,
787 priority=-1,
787 priority=-1,
788 )
788 )
789 coreconfigitem('pager', 'attend-.*',
789 coreconfigitem('pager', 'attend-.*',
790 default=dynamicdefault,
790 default=dynamicdefault,
791 generic=True,
791 generic=True,
792 )
792 )
793 coreconfigitem('pager', 'ignore',
793 coreconfigitem('pager', 'ignore',
794 default=list,
794 default=list,
795 )
795 )
796 coreconfigitem('pager', 'pager',
796 coreconfigitem('pager', 'pager',
797 default=dynamicdefault,
797 default=dynamicdefault,
798 )
798 )
799 coreconfigitem('patch', 'eol',
799 coreconfigitem('patch', 'eol',
800 default='strict',
800 default='strict',
801 )
801 )
802 coreconfigitem('patch', 'fuzz',
802 coreconfigitem('patch', 'fuzz',
803 default=2,
803 default=2,
804 )
804 )
805 coreconfigitem('paths', 'default',
805 coreconfigitem('paths', 'default',
806 default=None,
806 default=None,
807 )
807 )
808 coreconfigitem('paths', 'default-push',
808 coreconfigitem('paths', 'default-push',
809 default=None,
809 default=None,
810 )
810 )
811 coreconfigitem('paths', '.*',
811 coreconfigitem('paths', '.*',
812 default=None,
812 default=None,
813 generic=True,
813 generic=True,
814 )
814 )
815 coreconfigitem('phases', 'checksubrepos',
815 coreconfigitem('phases', 'checksubrepos',
816 default='follow',
816 default='follow',
817 )
817 )
818 coreconfigitem('phases', 'new-commit',
818 coreconfigitem('phases', 'new-commit',
819 default='draft',
819 default='draft',
820 )
820 )
821 coreconfigitem('phases', 'publish',
821 coreconfigitem('phases', 'publish',
822 default=True,
822 default=True,
823 )
823 )
824 coreconfigitem('profiling', 'enabled',
824 coreconfigitem('profiling', 'enabled',
825 default=False,
825 default=False,
826 )
826 )
827 coreconfigitem('profiling', 'format',
827 coreconfigitem('profiling', 'format',
828 default='text',
828 default='text',
829 )
829 )
830 coreconfigitem('profiling', 'freq',
830 coreconfigitem('profiling', 'freq',
831 default=1000,
831 default=1000,
832 )
832 )
833 coreconfigitem('profiling', 'limit',
833 coreconfigitem('profiling', 'limit',
834 default=30,
834 default=30,
835 )
835 )
836 coreconfigitem('profiling', 'nested',
836 coreconfigitem('profiling', 'nested',
837 default=0,
837 default=0,
838 )
838 )
839 coreconfigitem('profiling', 'output',
839 coreconfigitem('profiling', 'output',
840 default=None,
840 default=None,
841 )
841 )
842 coreconfigitem('profiling', 'showmax',
842 coreconfigitem('profiling', 'showmax',
843 default=0.999,
843 default=0.999,
844 )
844 )
845 coreconfigitem('profiling', 'showmin',
845 coreconfigitem('profiling', 'showmin',
846 default=dynamicdefault,
846 default=dynamicdefault,
847 )
847 )
848 coreconfigitem('profiling', 'sort',
848 coreconfigitem('profiling', 'sort',
849 default='inlinetime',
849 default='inlinetime',
850 )
850 )
851 coreconfigitem('profiling', 'statformat',
851 coreconfigitem('profiling', 'statformat',
852 default='hotpath',
852 default='hotpath',
853 )
853 )
854 coreconfigitem('profiling', 'type',
854 coreconfigitem('profiling', 'type',
855 default='stat',
855 default='stat',
856 )
856 )
857 coreconfigitem('progress', 'assume-tty',
857 coreconfigitem('progress', 'assume-tty',
858 default=False,
858 default=False,
859 )
859 )
860 coreconfigitem('progress', 'changedelay',
860 coreconfigitem('progress', 'changedelay',
861 default=1,
861 default=1,
862 )
862 )
863 coreconfigitem('progress', 'clear-complete',
863 coreconfigitem('progress', 'clear-complete',
864 default=True,
864 default=True,
865 )
865 )
866 coreconfigitem('progress', 'debug',
866 coreconfigitem('progress', 'debug',
867 default=False,
867 default=False,
868 )
868 )
869 coreconfigitem('progress', 'delay',
869 coreconfigitem('progress', 'delay',
870 default=3,
870 default=3,
871 )
871 )
872 coreconfigitem('progress', 'disable',
872 coreconfigitem('progress', 'disable',
873 default=False,
873 default=False,
874 )
874 )
875 coreconfigitem('progress', 'estimateinterval',
875 coreconfigitem('progress', 'estimateinterval',
876 default=60.0,
876 default=60.0,
877 )
877 )
878 coreconfigitem('progress', 'format',
878 coreconfigitem('progress', 'format',
879 default=lambda: ['topic', 'bar', 'number', 'estimate'],
879 default=lambda: ['topic', 'bar', 'number', 'estimate'],
880 )
880 )
881 coreconfigitem('progress', 'refresh',
881 coreconfigitem('progress', 'refresh',
882 default=0.1,
882 default=0.1,
883 )
883 )
884 coreconfigitem('progress', 'width',
884 coreconfigitem('progress', 'width',
885 default=dynamicdefault,
885 default=dynamicdefault,
886 )
886 )
887 coreconfigitem('push', 'pushvars.server',
887 coreconfigitem('push', 'pushvars.server',
888 default=False,
888 default=False,
889 )
889 )
890 coreconfigitem('server', 'bookmarks-pushkey-compat',
890 coreconfigitem('server', 'bookmarks-pushkey-compat',
891 default=True,
891 default=True,
892 )
892 )
893 coreconfigitem('server', 'bundle1',
893 coreconfigitem('server', 'bundle1',
894 default=True,
894 default=True,
895 )
895 )
896 coreconfigitem('server', 'bundle1gd',
896 coreconfigitem('server', 'bundle1gd',
897 default=None,
897 default=None,
898 )
898 )
899 coreconfigitem('server', 'bundle1.pull',
899 coreconfigitem('server', 'bundle1.pull',
900 default=None,
900 default=None,
901 )
901 )
902 coreconfigitem('server', 'bundle1gd.pull',
902 coreconfigitem('server', 'bundle1gd.pull',
903 default=None,
903 default=None,
904 )
904 )
905 coreconfigitem('server', 'bundle1.push',
905 coreconfigitem('server', 'bundle1.push',
906 default=None,
906 default=None,
907 )
907 )
908 coreconfigitem('server', 'bundle1gd.push',
908 coreconfigitem('server', 'bundle1gd.push',
909 default=None,
909 default=None,
910 )
910 )
911 coreconfigitem('server', 'compressionengines',
911 coreconfigitem('server', 'compressionengines',
912 default=list,
912 default=list,
913 )
913 )
914 coreconfigitem('server', 'concurrent-push-mode',
914 coreconfigitem('server', 'concurrent-push-mode',
915 default='strict',
915 default='strict',
916 )
916 )
917 coreconfigitem('server', 'disablefullbundle',
917 coreconfigitem('server', 'disablefullbundle',
918 default=False,
918 default=False,
919 )
919 )
920 coreconfigitem('server', 'maxhttpheaderlen',
920 coreconfigitem('server', 'maxhttpheaderlen',
921 default=1024,
921 default=1024,
922 )
922 )
923 coreconfigitem('server', 'preferuncompressed',
923 coreconfigitem('server', 'preferuncompressed',
924 default=False,
924 default=False,
925 )
925 )
926 coreconfigitem('server', 'uncompressed',
926 coreconfigitem('server', 'uncompressed',
927 default=True,
927 default=True,
928 )
928 )
929 coreconfigitem('server', 'uncompressedallowsecret',
929 coreconfigitem('server', 'uncompressedallowsecret',
930 default=False,
930 default=False,
931 )
931 )
932 coreconfigitem('server', 'validate',
932 coreconfigitem('server', 'validate',
933 default=False,
933 default=False,
934 )
934 )
935 coreconfigitem('server', 'zliblevel',
935 coreconfigitem('server', 'zliblevel',
936 default=-1,
936 default=-1,
937 )
937 )
938 coreconfigitem('share', 'pool',
938 coreconfigitem('share', 'pool',
939 default=None,
939 default=None,
940 )
940 )
941 coreconfigitem('share', 'poolnaming',
941 coreconfigitem('share', 'poolnaming',
942 default='identity',
942 default='identity',
943 )
943 )
944 coreconfigitem('smtp', 'host',
944 coreconfigitem('smtp', 'host',
945 default=None,
945 default=None,
946 )
946 )
947 coreconfigitem('smtp', 'local_hostname',
947 coreconfigitem('smtp', 'local_hostname',
948 default=None,
948 default=None,
949 )
949 )
950 coreconfigitem('smtp', 'password',
950 coreconfigitem('smtp', 'password',
951 default=None,
951 default=None,
952 )
952 )
953 coreconfigitem('smtp', 'port',
953 coreconfigitem('smtp', 'port',
954 default=dynamicdefault,
954 default=dynamicdefault,
955 )
955 )
956 coreconfigitem('smtp', 'tls',
956 coreconfigitem('smtp', 'tls',
957 default='none',
957 default='none',
958 )
958 )
959 coreconfigitem('smtp', 'username',
959 coreconfigitem('smtp', 'username',
960 default=None,
960 default=None,
961 )
961 )
962 coreconfigitem('sparse', 'missingwarning',
962 coreconfigitem('sparse', 'missingwarning',
963 default=True,
963 default=True,
964 )
964 )
965 coreconfigitem('subrepos', 'allowed',
965 coreconfigitem('subrepos', 'allowed',
966 default=dynamicdefault, # to make backporting simpler
966 default=dynamicdefault, # to make backporting simpler
967 )
967 )
968 coreconfigitem('subrepos', 'hg:allowed',
968 coreconfigitem('subrepos', 'hg:allowed',
969 default=dynamicdefault,
969 default=dynamicdefault,
970 )
970 )
971 coreconfigitem('subrepos', 'git:allowed',
971 coreconfigitem('subrepos', 'git:allowed',
972 default=dynamicdefault,
972 default=dynamicdefault,
973 )
973 )
974 coreconfigitem('subrepos', 'svn:allowed',
974 coreconfigitem('subrepos', 'svn:allowed',
975 default=dynamicdefault,
975 default=dynamicdefault,
976 )
976 )
977 coreconfigitem('templates', '.*',
977 coreconfigitem('templates', '.*',
978 default=None,
978 default=None,
979 generic=True,
979 generic=True,
980 )
980 )
981 coreconfigitem('trusted', 'groups',
981 coreconfigitem('trusted', 'groups',
982 default=list,
982 default=list,
983 )
983 )
984 coreconfigitem('trusted', 'users',
984 coreconfigitem('trusted', 'users',
985 default=list,
985 default=list,
986 )
986 )
987 coreconfigitem('ui', '_usedassubrepo',
987 coreconfigitem('ui', '_usedassubrepo',
988 default=False,
988 default=False,
989 )
989 )
990 coreconfigitem('ui', 'allowemptycommit',
990 coreconfigitem('ui', 'allowemptycommit',
991 default=False,
991 default=False,
992 )
992 )
993 coreconfigitem('ui', 'archivemeta',
993 coreconfigitem('ui', 'archivemeta',
994 default=True,
994 default=True,
995 )
995 )
996 coreconfigitem('ui', 'askusername',
996 coreconfigitem('ui', 'askusername',
997 default=False,
997 default=False,
998 )
998 )
999 coreconfigitem('ui', 'clonebundlefallback',
999 coreconfigitem('ui', 'clonebundlefallback',
1000 default=False,
1000 default=False,
1001 )
1001 )
1002 coreconfigitem('ui', 'clonebundleprefers',
1002 coreconfigitem('ui', 'clonebundleprefers',
1003 default=list,
1003 default=list,
1004 )
1004 )
1005 coreconfigitem('ui', 'clonebundles',
1005 coreconfigitem('ui', 'clonebundles',
1006 default=True,
1006 default=True,
1007 )
1007 )
1008 coreconfigitem('ui', 'color',
1008 coreconfigitem('ui', 'color',
1009 default='auto',
1009 default='auto',
1010 )
1010 )
1011 coreconfigitem('ui', 'commitsubrepos',
1011 coreconfigitem('ui', 'commitsubrepos',
1012 default=False,
1012 default=False,
1013 )
1013 )
1014 coreconfigitem('ui', 'debug',
1014 coreconfigitem('ui', 'debug',
1015 default=False,
1015 default=False,
1016 )
1016 )
1017 coreconfigitem('ui', 'debugger',
1017 coreconfigitem('ui', 'debugger',
1018 default=None,
1018 default=None,
1019 )
1019 )
1020 coreconfigitem('ui', 'editor',
1020 coreconfigitem('ui', 'editor',
1021 default=dynamicdefault,
1021 default=dynamicdefault,
1022 )
1022 )
1023 coreconfigitem('ui', 'fallbackencoding',
1023 coreconfigitem('ui', 'fallbackencoding',
1024 default=None,
1024 default=None,
1025 )
1025 )
1026 coreconfigitem('ui', 'forcecwd',
1026 coreconfigitem('ui', 'forcecwd',
1027 default=None,
1027 default=None,
1028 )
1028 )
1029 coreconfigitem('ui', 'forcemerge',
1029 coreconfigitem('ui', 'forcemerge',
1030 default=None,
1030 default=None,
1031 )
1031 )
1032 coreconfigitem('ui', 'formatdebug',
1032 coreconfigitem('ui', 'formatdebug',
1033 default=False,
1033 default=False,
1034 )
1034 )
1035 coreconfigitem('ui', 'formatjson',
1035 coreconfigitem('ui', 'formatjson',
1036 default=False,
1036 default=False,
1037 )
1037 )
1038 coreconfigitem('ui', 'formatted',
1038 coreconfigitem('ui', 'formatted',
1039 default=None,
1039 default=None,
1040 )
1040 )
1041 coreconfigitem('ui', 'graphnodetemplate',
1041 coreconfigitem('ui', 'graphnodetemplate',
1042 default=None,
1042 default=None,
1043 )
1043 )
1044 coreconfigitem('ui', 'interactive',
1044 coreconfigitem('ui', 'interactive',
1045 default=None,
1045 default=None,
1046 )
1046 )
1047 coreconfigitem('ui', 'interface',
1047 coreconfigitem('ui', 'interface',
1048 default=None,
1048 default=None,
1049 )
1049 )
1050 coreconfigitem('ui', 'interface.chunkselector',
1050 coreconfigitem('ui', 'interface.chunkselector',
1051 default=None,
1051 default=None,
1052 )
1052 )
1053 coreconfigitem('ui', 'logblockedtimes',
1053 coreconfigitem('ui', 'logblockedtimes',
1054 default=False,
1054 default=False,
1055 )
1055 )
1056 coreconfigitem('ui', 'logtemplate',
1056 coreconfigitem('ui', 'logtemplate',
1057 default=None,
1057 default=None,
1058 )
1058 )
1059 coreconfigitem('ui', 'merge',
1059 coreconfigitem('ui', 'merge',
1060 default=None,
1060 default=None,
1061 )
1061 )
1062 coreconfigitem('ui', 'mergemarkers',
1062 coreconfigitem('ui', 'mergemarkers',
1063 default='basic',
1063 default='basic',
1064 )
1064 )
1065 coreconfigitem('ui', 'mergemarkertemplate',
1065 coreconfigitem('ui', 'mergemarkertemplate',
1066 default=('{node|short} '
1066 default=('{node|short} '
1067 '{ifeq(tags, "tip", "", '
1067 '{ifeq(tags, "tip", "", '
1068 'ifeq(tags, "", "", "{tags} "))}'
1068 'ifeq(tags, "", "", "{tags} "))}'
1069 '{if(bookmarks, "{bookmarks} ")}'
1069 '{if(bookmarks, "{bookmarks} ")}'
1070 '{ifeq(branch, "default", "", "{branch} ")}'
1070 '{ifeq(branch, "default", "", "{branch} ")}'
1071 '- {author|user}: {desc|firstline}')
1071 '- {author|user}: {desc|firstline}')
1072 )
1072 )
1073 coreconfigitem('ui', 'nontty',
1073 coreconfigitem('ui', 'nontty',
1074 default=False,
1074 default=False,
1075 )
1075 )
1076 coreconfigitem('ui', 'origbackuppath',
1076 coreconfigitem('ui', 'origbackuppath',
1077 default=None,
1077 default=None,
1078 )
1078 )
1079 coreconfigitem('ui', 'paginate',
1079 coreconfigitem('ui', 'paginate',
1080 default=True,
1080 default=True,
1081 )
1081 )
1082 coreconfigitem('ui', 'patch',
1082 coreconfigitem('ui', 'patch',
1083 default=None,
1083 default=None,
1084 )
1084 )
1085 coreconfigitem('ui', 'portablefilenames',
1085 coreconfigitem('ui', 'portablefilenames',
1086 default='warn',
1086 default='warn',
1087 )
1087 )
1088 coreconfigitem('ui', 'promptecho',
1088 coreconfigitem('ui', 'promptecho',
1089 default=False,
1089 default=False,
1090 )
1090 )
1091 coreconfigitem('ui', 'quiet',
1091 coreconfigitem('ui', 'quiet',
1092 default=False,
1092 default=False,
1093 )
1093 )
1094 coreconfigitem('ui', 'quietbookmarkmove',
1094 coreconfigitem('ui', 'quietbookmarkmove',
1095 default=False,
1095 default=False,
1096 )
1096 )
1097 coreconfigitem('ui', 'remotecmd',
1097 coreconfigitem('ui', 'remotecmd',
1098 default='hg',
1098 default='hg',
1099 )
1099 )
1100 coreconfigitem('ui', 'report_untrusted',
1100 coreconfigitem('ui', 'report_untrusted',
1101 default=True,
1101 default=True,
1102 )
1102 )
1103 coreconfigitem('ui', 'rollback',
1103 coreconfigitem('ui', 'rollback',
1104 default=True,
1104 default=True,
1105 )
1105 )
1106 coreconfigitem('ui', 'slash',
1106 coreconfigitem('ui', 'slash',
1107 default=False,
1107 default=False,
1108 )
1108 )
1109 coreconfigitem('ui', 'ssh',
1109 coreconfigitem('ui', 'ssh',
1110 default='ssh',
1110 default='ssh',
1111 )
1111 )
1112 coreconfigitem('ui', 'ssherrorhint',
1112 coreconfigitem('ui', 'ssherrorhint',
1113 default=None,
1113 default=None,
1114 )
1114 )
1115 coreconfigitem('ui', 'statuscopies',
1115 coreconfigitem('ui', 'statuscopies',
1116 default=False,
1116 default=False,
1117 )
1117 )
1118 coreconfigitem('ui', 'strict',
1118 coreconfigitem('ui', 'strict',
1119 default=False,
1119 default=False,
1120 )
1120 )
1121 coreconfigitem('ui', 'style',
1121 coreconfigitem('ui', 'style',
1122 default='',
1122 default='',
1123 )
1123 )
1124 coreconfigitem('ui', 'supportcontact',
1124 coreconfigitem('ui', 'supportcontact',
1125 default=None,
1125 default=None,
1126 )
1126 )
1127 coreconfigitem('ui', 'textwidth',
1127 coreconfigitem('ui', 'textwidth',
1128 default=78,
1128 default=78,
1129 )
1129 )
1130 coreconfigitem('ui', 'timeout',
1130 coreconfigitem('ui', 'timeout',
1131 default='600',
1131 default='600',
1132 )
1132 )
1133 coreconfigitem('ui', 'timeout.warn',
1133 coreconfigitem('ui', 'timeout.warn',
1134 default=0,
1134 default=0,
1135 )
1135 )
1136 coreconfigitem('ui', 'traceback',
1136 coreconfigitem('ui', 'traceback',
1137 default=False,
1137 default=False,
1138 )
1138 )
1139 coreconfigitem('ui', 'tweakdefaults',
1139 coreconfigitem('ui', 'tweakdefaults',
1140 default=False,
1140 default=False,
1141 )
1141 )
1142 coreconfigitem('ui', 'username',
1142 coreconfigitem('ui', 'username',
1143 alias=[('ui', 'user')]
1143 alias=[('ui', 'user')]
1144 )
1144 )
1145 coreconfigitem('ui', 'verbose',
1145 coreconfigitem('ui', 'verbose',
1146 default=False,
1146 default=False,
1147 )
1147 )
1148 coreconfigitem('verify', 'skipflags',
1148 coreconfigitem('verify', 'skipflags',
1149 default=None,
1149 default=None,
1150 )
1150 )
1151 coreconfigitem('web', 'allowbz2',
1151 coreconfigitem('web', 'allowbz2',
1152 default=False,
1152 default=False,
1153 )
1153 )
1154 coreconfigitem('web', 'allowgz',
1154 coreconfigitem('web', 'allowgz',
1155 default=False,
1155 default=False,
1156 )
1156 )
1157 coreconfigitem('web', 'allow-pull',
1157 coreconfigitem('web', 'allow-pull',
1158 alias=[('web', 'allowpull')],
1158 alias=[('web', 'allowpull')],
1159 default=True,
1159 default=True,
1160 )
1160 )
1161 coreconfigitem('web', 'allow-push',
1161 coreconfigitem('web', 'allow-push',
1162 alias=[('web', 'allow_push')],
1162 alias=[('web', 'allow_push')],
1163 default=list,
1163 default=list,
1164 )
1164 )
1165 coreconfigitem('web', 'allowzip',
1165 coreconfigitem('web', 'allowzip',
1166 default=False,
1166 default=False,
1167 )
1167 )
1168 coreconfigitem('web', 'archivesubrepos',
1168 coreconfigitem('web', 'archivesubrepos',
1169 default=False,
1169 default=False,
1170 )
1170 )
1171 coreconfigitem('web', 'cache',
1171 coreconfigitem('web', 'cache',
1172 default=True,
1172 default=True,
1173 )
1173 )
1174 coreconfigitem('web', 'contact',
1174 coreconfigitem('web', 'contact',
1175 default=None,
1175 default=None,
1176 )
1176 )
1177 coreconfigitem('web', 'deny_push',
1177 coreconfigitem('web', 'deny_push',
1178 default=list,
1178 default=list,
1179 )
1179 )
1180 coreconfigitem('web', 'guessmime',
1180 coreconfigitem('web', 'guessmime',
1181 default=False,
1181 default=False,
1182 )
1182 )
1183 coreconfigitem('web', 'hidden',
1183 coreconfigitem('web', 'hidden',
1184 default=False,
1184 default=False,
1185 )
1185 )
1186 coreconfigitem('web', 'labels',
1186 coreconfigitem('web', 'labels',
1187 default=list,
1187 default=list,
1188 )
1188 )
1189 coreconfigitem('web', 'logoimg',
1189 coreconfigitem('web', 'logoimg',
1190 default='hglogo.png',
1190 default='hglogo.png',
1191 )
1191 )
1192 coreconfigitem('web', 'logourl',
1192 coreconfigitem('web', 'logourl',
1193 default='https://mercurial-scm.org/',
1193 default='https://mercurial-scm.org/',
1194 )
1194 )
1195 coreconfigitem('web', 'accesslog',
1195 coreconfigitem('web', 'accesslog',
1196 default='-',
1196 default='-',
1197 )
1197 )
1198 coreconfigitem('web', 'address',
1198 coreconfigitem('web', 'address',
1199 default='',
1199 default='',
1200 )
1200 )
1201 coreconfigitem('web', 'allow_archive',
1201 coreconfigitem('web', 'allow_archive',
1202 default=list,
1202 default=list,
1203 )
1203 )
1204 coreconfigitem('web', 'allow_read',
1204 coreconfigitem('web', 'allow_read',
1205 default=list,
1205 default=list,
1206 )
1206 )
1207 coreconfigitem('web', 'baseurl',
1207 coreconfigitem('web', 'baseurl',
1208 default=None,
1208 default=None,
1209 )
1209 )
1210 coreconfigitem('web', 'cacerts',
1210 coreconfigitem('web', 'cacerts',
1211 default=None,
1211 default=None,
1212 )
1212 )
1213 coreconfigitem('web', 'certificate',
1213 coreconfigitem('web', 'certificate',
1214 default=None,
1214 default=None,
1215 )
1215 )
1216 coreconfigitem('web', 'collapse',
1216 coreconfigitem('web', 'collapse',
1217 default=False,
1217 default=False,
1218 )
1218 )
1219 coreconfigitem('web', 'csp',
1219 coreconfigitem('web', 'csp',
1220 default=None,
1220 default=None,
1221 )
1221 )
1222 coreconfigitem('web', 'deny_read',
1222 coreconfigitem('web', 'deny_read',
1223 default=list,
1223 default=list,
1224 )
1224 )
1225 coreconfigitem('web', 'descend',
1225 coreconfigitem('web', 'descend',
1226 default=True,
1226 default=True,
1227 )
1227 )
1228 coreconfigitem('web', 'description',
1228 coreconfigitem('web', 'description',
1229 default="",
1229 default="",
1230 )
1230 )
1231 coreconfigitem('web', 'encoding',
1231 coreconfigitem('web', 'encoding',
1232 default=lambda: encoding.encoding,
1232 default=lambda: encoding.encoding,
1233 )
1233 )
1234 coreconfigitem('web', 'errorlog',
1234 coreconfigitem('web', 'errorlog',
1235 default='-',
1235 default='-',
1236 )
1236 )
1237 coreconfigitem('web', 'ipv6',
1237 coreconfigitem('web', 'ipv6',
1238 default=False,
1238 default=False,
1239 )
1239 )
1240 coreconfigitem('web', 'maxchanges',
1240 coreconfigitem('web', 'maxchanges',
1241 default=10,
1241 default=10,
1242 )
1242 )
1243 coreconfigitem('web', 'maxfiles',
1243 coreconfigitem('web', 'maxfiles',
1244 default=10,
1244 default=10,
1245 )
1245 )
1246 coreconfigitem('web', 'maxshortchanges',
1246 coreconfigitem('web', 'maxshortchanges',
1247 default=60,
1247 default=60,
1248 )
1248 )
1249 coreconfigitem('web', 'motd',
1249 coreconfigitem('web', 'motd',
1250 default='',
1250 default='',
1251 )
1251 )
1252 coreconfigitem('web', 'name',
1252 coreconfigitem('web', 'name',
1253 default=dynamicdefault,
1253 default=dynamicdefault,
1254 )
1254 )
1255 coreconfigitem('web', 'port',
1255 coreconfigitem('web', 'port',
1256 default=8000,
1256 default=8000,
1257 )
1257 )
1258 coreconfigitem('web', 'prefix',
1258 coreconfigitem('web', 'prefix',
1259 default='',
1259 default='',
1260 )
1260 )
1261 coreconfigitem('web', 'push_ssl',
1261 coreconfigitem('web', 'push_ssl',
1262 default=True,
1262 default=True,
1263 )
1263 )
1264 coreconfigitem('web', 'refreshinterval',
1264 coreconfigitem('web', 'refreshinterval',
1265 default=20,
1265 default=20,
1266 )
1266 )
1267 coreconfigitem('web', 'server-header',
1267 coreconfigitem('web', 'server-header',
1268 default=None,
1268 default=None,
1269 )
1269 )
1270 coreconfigitem('web', 'staticurl',
1270 coreconfigitem('web', 'staticurl',
1271 default=None,
1271 default=None,
1272 )
1272 )
1273 coreconfigitem('web', 'stripes',
1273 coreconfigitem('web', 'stripes',
1274 default=1,
1274 default=1,
1275 )
1275 )
1276 coreconfigitem('web', 'style',
1276 coreconfigitem('web', 'style',
1277 default='paper',
1277 default='paper',
1278 )
1278 )
1279 coreconfigitem('web', 'templates',
1279 coreconfigitem('web', 'templates',
1280 default=None,
1280 default=None,
1281 )
1281 )
1282 coreconfigitem('web', 'view',
1282 coreconfigitem('web', 'view',
1283 default='served',
1283 default='served',
1284 )
1284 )
1285 coreconfigitem('worker', 'backgroundclose',
1285 coreconfigitem('worker', 'backgroundclose',
1286 default=dynamicdefault,
1286 default=dynamicdefault,
1287 )
1287 )
1288 # Windows defaults to a limit of 512 open files. A buffer of 128
1288 # Windows defaults to a limit of 512 open files. A buffer of 128
1289 # should give us enough headway.
1289 # should give us enough headway.
1290 coreconfigitem('worker', 'backgroundclosemaxqueue',
1290 coreconfigitem('worker', 'backgroundclosemaxqueue',
1291 default=384,
1291 default=384,
1292 )
1292 )
1293 coreconfigitem('worker', 'backgroundcloseminfilecount',
1293 coreconfigitem('worker', 'backgroundcloseminfilecount',
1294 default=2048,
1294 default=2048,
1295 )
1295 )
1296 coreconfigitem('worker', 'backgroundclosethreadcount',
1296 coreconfigitem('worker', 'backgroundclosethreadcount',
1297 default=4,
1297 default=4,
1298 )
1298 )
1299 coreconfigitem('worker', 'enabled',
1299 coreconfigitem('worker', 'enabled',
1300 default=True,
1300 default=True,
1301 )
1301 )
1302 coreconfigitem('worker', 'numcpus',
1302 coreconfigitem('worker', 'numcpus',
1303 default=None,
1303 default=None,
1304 )
1304 )
1305
1305
1306 # Rebase related configuration moved to core because other extension are doing
1306 # Rebase related configuration moved to core because other extension are doing
1307 # strange things. For example, shelve import the extensions to reuse some bit
1307 # strange things. For example, shelve import the extensions to reuse some bit
1308 # without formally loading it.
1308 # without formally loading it.
1309 coreconfigitem('commands', 'rebase.requiredest',
1309 coreconfigitem('commands', 'rebase.requiredest',
1310 default=False,
1310 default=False,
1311 )
1311 )
1312 coreconfigitem('experimental', 'rebaseskipobsolete',
1312 coreconfigitem('experimental', 'rebaseskipobsolete',
1313 default=True,
1313 default=True,
1314 )
1314 )
1315 coreconfigitem('rebase', 'singletransaction',
1315 coreconfigitem('rebase', 'singletransaction',
1316 default=False,
1316 default=False,
1317 )
1317 )
1318 coreconfigitem('rebase', 'experimental.inmemory',
1318 coreconfigitem('rebase', 'experimental.inmemory',
1319 default=False,
1319 default=False,
1320 )
1320 )
@@ -1,1030 +1,1040 b''
1 # dispatch.py - command dispatching for mercurial
1 # dispatch.py - command dispatching for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.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 from __future__ import absolute_import, print_function
8 from __future__ import absolute_import, print_function
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import getopt
12 import getopt
13 import os
13 import os
14 import pdb
14 import pdb
15 import re
15 import re
16 import signal
16 import signal
17 import sys
17 import sys
18 import time
18 import time
19 import traceback
19 import traceback
20
20
21
21
22 from .i18n import _
22 from .i18n import _
23
23
24 from . import (
24 from . import (
25 cmdutil,
25 cmdutil,
26 color,
26 color,
27 commands,
27 commands,
28 demandimport,
28 demandimport,
29 encoding,
29 encoding,
30 error,
30 error,
31 extensions,
31 extensions,
32 fancyopts,
32 fancyopts,
33 help,
33 help,
34 hg,
34 hg,
35 hook,
35 hook,
36 profiling,
36 profiling,
37 pycompat,
37 pycompat,
38 registrar,
38 registrar,
39 scmutil,
39 scmutil,
40 ui as uimod,
40 ui as uimod,
41 util,
41 util,
42 )
42 )
43
43
44 from .utils import (
44 from .utils import (
45 procutil,
45 procutil,
46 stringutil,
46 stringutil,
47 )
47 )
48
48
49 unrecoverablewrite = registrar.command.unrecoverablewrite
49 unrecoverablewrite = registrar.command.unrecoverablewrite
50
50
51 class request(object):
51 class request(object):
52 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
52 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
53 ferr=None, prereposetups=None):
53 ferr=None, prereposetups=None):
54 self.args = args
54 self.args = args
55 self.ui = ui
55 self.ui = ui
56 self.repo = repo
56 self.repo = repo
57
57
58 # input/output/error streams
58 # input/output/error streams
59 self.fin = fin
59 self.fin = fin
60 self.fout = fout
60 self.fout = fout
61 self.ferr = ferr
61 self.ferr = ferr
62
62
63 # remember options pre-parsed by _earlyparseopts()
63 # remember options pre-parsed by _earlyparseopts()
64 self.earlyoptions = {}
64 self.earlyoptions = {}
65
65
66 # reposetups which run before extensions, useful for chg to pre-fill
66 # reposetups which run before extensions, useful for chg to pre-fill
67 # low-level repo state (for example, changelog) before extensions.
67 # low-level repo state (for example, changelog) before extensions.
68 self.prereposetups = prereposetups or []
68 self.prereposetups = prereposetups or []
69
69
70 def _runexithandlers(self):
70 def _runexithandlers(self):
71 exc = None
71 exc = None
72 handlers = self.ui._exithandlers
72 handlers = self.ui._exithandlers
73 try:
73 try:
74 while handlers:
74 while handlers:
75 func, args, kwargs = handlers.pop()
75 func, args, kwargs = handlers.pop()
76 try:
76 try:
77 func(*args, **kwargs)
77 func(*args, **kwargs)
78 except: # re-raises below
78 except: # re-raises below
79 if exc is None:
79 if exc is None:
80 exc = sys.exc_info()[1]
80 exc = sys.exc_info()[1]
81 self.ui.warn(('error in exit handlers:\n'))
81 self.ui.warn(('error in exit handlers:\n'))
82 self.ui.traceback(force=True)
82 self.ui.traceback(force=True)
83 finally:
83 finally:
84 if exc is not None:
84 if exc is not None:
85 raise exc
85 raise exc
86
86
87 def run():
87 def run():
88 "run the command in sys.argv"
88 "run the command in sys.argv"
89 _initstdio()
89 _initstdio()
90 req = request(pycompat.sysargv[1:])
90 req = request(pycompat.sysargv[1:])
91 err = None
91 err = None
92 try:
92 try:
93 status = (dispatch(req) or 0)
93 status = (dispatch(req) or 0)
94 except error.StdioError as e:
94 except error.StdioError as e:
95 err = e
95 err = e
96 status = -1
96 status = -1
97 if util.safehasattr(req.ui, 'fout'):
97 if util.safehasattr(req.ui, 'fout'):
98 try:
98 try:
99 req.ui.fout.flush()
99 req.ui.fout.flush()
100 except IOError as e:
100 except IOError as e:
101 err = e
101 err = e
102 status = -1
102 status = -1
103 if util.safehasattr(req.ui, 'ferr'):
103 if util.safehasattr(req.ui, 'ferr'):
104 try:
104 try:
105 if err is not None and err.errno != errno.EPIPE:
105 if err is not None and err.errno != errno.EPIPE:
106 req.ui.ferr.write('abort: %s\n' %
106 req.ui.ferr.write('abort: %s\n' %
107 encoding.strtolocal(err.strerror))
107 encoding.strtolocal(err.strerror))
108 req.ui.ferr.flush()
108 req.ui.ferr.flush()
109 # There's not much we can do about an I/O error here. So (possibly)
109 # There's not much we can do about an I/O error here. So (possibly)
110 # change the status code and move on.
110 # change the status code and move on.
111 except IOError:
111 except IOError:
112 status = -1
112 status = -1
113
113
114 _silencestdio()
114 _silencestdio()
115 sys.exit(status & 255)
115 sys.exit(status & 255)
116
116
117 if pycompat.ispy3:
117 if pycompat.ispy3:
118 def _initstdio():
118 def _initstdio():
119 pass
119 pass
120
120
121 def _silencestdio():
121 def _silencestdio():
122 for fp in (sys.stdout, sys.stderr):
122 for fp in (sys.stdout, sys.stderr):
123 # Check if the file is okay
123 # Check if the file is okay
124 try:
124 try:
125 fp.flush()
125 fp.flush()
126 continue
126 continue
127 except IOError:
127 except IOError:
128 pass
128 pass
129 # Otherwise mark it as closed to silence "Exception ignored in"
129 # Otherwise mark it as closed to silence "Exception ignored in"
130 # message emitted by the interpreter finalizer. Be careful to
130 # message emitted by the interpreter finalizer. Be careful to
131 # not close procutil.stdout, which may be a fdopen-ed file object
131 # not close procutil.stdout, which may be a fdopen-ed file object
132 # and its close() actually closes the underlying file descriptor.
132 # and its close() actually closes the underlying file descriptor.
133 try:
133 try:
134 fp.close()
134 fp.close()
135 except IOError:
135 except IOError:
136 pass
136 pass
137 else:
137 else:
138 def _initstdio():
138 def _initstdio():
139 for fp in (sys.stdin, sys.stdout, sys.stderr):
139 for fp in (sys.stdin, sys.stdout, sys.stderr):
140 procutil.setbinary(fp)
140 procutil.setbinary(fp)
141
141
142 def _silencestdio():
142 def _silencestdio():
143 pass
143 pass
144
144
145 def _getsimilar(symbols, value):
145 def _getsimilar(symbols, value):
146 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
146 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
147 # The cutoff for similarity here is pretty arbitrary. It should
147 # The cutoff for similarity here is pretty arbitrary. It should
148 # probably be investigated and tweaked.
148 # probably be investigated and tweaked.
149 return [s for s in symbols if sim(s) > 0.6]
149 return [s for s in symbols if sim(s) > 0.6]
150
150
151 def _reportsimilar(write, similar):
151 def _reportsimilar(write, similar):
152 if len(similar) == 1:
152 if len(similar) == 1:
153 write(_("(did you mean %s?)\n") % similar[0])
153 write(_("(did you mean %s?)\n") % similar[0])
154 elif similar:
154 elif similar:
155 ss = ", ".join(sorted(similar))
155 ss = ", ".join(sorted(similar))
156 write(_("(did you mean one of %s?)\n") % ss)
156 write(_("(did you mean one of %s?)\n") % ss)
157
157
158 def _formatparse(write, inst):
158 def _formatparse(write, inst):
159 similar = []
159 similar = []
160 if isinstance(inst, error.UnknownIdentifier):
160 if isinstance(inst, error.UnknownIdentifier):
161 # make sure to check fileset first, as revset can invoke fileset
161 # make sure to check fileset first, as revset can invoke fileset
162 similar = _getsimilar(inst.symbols, inst.function)
162 similar = _getsimilar(inst.symbols, inst.function)
163 if len(inst.args) > 1:
163 if len(inst.args) > 1:
164 write(_("hg: parse error at %s: %s\n") %
164 write(_("hg: parse error at %s: %s\n") %
165 (pycompat.bytestr(inst.args[1]), inst.args[0]))
165 (pycompat.bytestr(inst.args[1]), inst.args[0]))
166 if inst.args[0].startswith(' '):
166 if inst.args[0].startswith(' '):
167 write(_("unexpected leading whitespace\n"))
167 write(_("unexpected leading whitespace\n"))
168 else:
168 else:
169 write(_("hg: parse error: %s\n") % inst.args[0])
169 write(_("hg: parse error: %s\n") % inst.args[0])
170 _reportsimilar(write, similar)
170 _reportsimilar(write, similar)
171 if inst.hint:
171 if inst.hint:
172 write(_("(%s)\n") % inst.hint)
172 write(_("(%s)\n") % inst.hint)
173
173
174 def _formatargs(args):
174 def _formatargs(args):
175 return ' '.join(procutil.shellquote(a) for a in args)
175 return ' '.join(procutil.shellquote(a) for a in args)
176
176
177 def dispatch(req):
177 def dispatch(req):
178 "run the command specified in req.args"
178 "run the command specified in req.args"
179 if req.ferr:
179 if req.ferr:
180 ferr = req.ferr
180 ferr = req.ferr
181 elif req.ui:
181 elif req.ui:
182 ferr = req.ui.ferr
182 ferr = req.ui.ferr
183 else:
183 else:
184 ferr = procutil.stderr
184 ferr = procutil.stderr
185
185
186 try:
186 try:
187 if not req.ui:
187 if not req.ui:
188 req.ui = uimod.ui.load()
188 req.ui = uimod.ui.load()
189 req.earlyoptions.update(_earlyparseopts(req.ui, req.args))
189 req.earlyoptions.update(_earlyparseopts(req.ui, req.args))
190 if req.earlyoptions['traceback']:
190 if req.earlyoptions['traceback']:
191 req.ui.setconfig('ui', 'traceback', 'on', '--traceback')
191 req.ui.setconfig('ui', 'traceback', 'on', '--traceback')
192
192
193 # set ui streams from the request
193 # set ui streams from the request
194 if req.fin:
194 if req.fin:
195 req.ui.fin = req.fin
195 req.ui.fin = req.fin
196 if req.fout:
196 if req.fout:
197 req.ui.fout = req.fout
197 req.ui.fout = req.fout
198 if req.ferr:
198 if req.ferr:
199 req.ui.ferr = req.ferr
199 req.ui.ferr = req.ferr
200 except error.Abort as inst:
200 except error.Abort as inst:
201 ferr.write(_("abort: %s\n") % inst)
201 ferr.write(_("abort: %s\n") % inst)
202 if inst.hint:
202 if inst.hint:
203 ferr.write(_("(%s)\n") % inst.hint)
203 ferr.write(_("(%s)\n") % inst.hint)
204 return -1
204 return -1
205 except error.ParseError as inst:
205 except error.ParseError as inst:
206 _formatparse(ferr.write, inst)
206 _formatparse(ferr.write, inst)
207 return -1
207 return -1
208
208
209 msg = _formatargs(req.args)
209 msg = _formatargs(req.args)
210 starttime = util.timer()
210 starttime = util.timer()
211 ret = None
211 ret = None
212 try:
212 try:
213 ret = _runcatch(req)
213 ret = _runcatch(req)
214 except error.ProgrammingError as inst:
214 except error.ProgrammingError as inst:
215 req.ui.warn(_('** ProgrammingError: %s\n') % inst)
215 req.ui.warn(_('** ProgrammingError: %s\n') % inst)
216 if inst.hint:
216 if inst.hint:
217 req.ui.warn(_('** (%s)\n') % inst.hint)
217 req.ui.warn(_('** (%s)\n') % inst.hint)
218 raise
218 raise
219 except KeyboardInterrupt as inst:
219 except KeyboardInterrupt as inst:
220 try:
220 try:
221 if isinstance(inst, error.SignalInterrupt):
221 if isinstance(inst, error.SignalInterrupt):
222 msg = _("killed!\n")
222 msg = _("killed!\n")
223 else:
223 else:
224 msg = _("interrupted!\n")
224 msg = _("interrupted!\n")
225 req.ui.warn(msg)
225 req.ui.warn(msg)
226 except error.SignalInterrupt:
226 except error.SignalInterrupt:
227 # maybe pager would quit without consuming all the output, and
227 # maybe pager would quit without consuming all the output, and
228 # SIGPIPE was raised. we cannot print anything in this case.
228 # SIGPIPE was raised. we cannot print anything in this case.
229 pass
229 pass
230 except IOError as inst:
230 except IOError as inst:
231 if inst.errno != errno.EPIPE:
231 if inst.errno != errno.EPIPE:
232 raise
232 raise
233 ret = -1
233 ret = -1
234 finally:
234 finally:
235 duration = util.timer() - starttime
235 duration = util.timer() - starttime
236 req.ui.flush()
236 req.ui.flush()
237 if req.ui.logblockedtimes:
237 if req.ui.logblockedtimes:
238 req.ui._blockedtimes['command_duration'] = duration * 1000
238 req.ui._blockedtimes['command_duration'] = duration * 1000
239 req.ui.log('uiblocked', 'ui blocked ms',
239 req.ui.log('uiblocked', 'ui blocked ms',
240 **pycompat.strkwargs(req.ui._blockedtimes))
240 **pycompat.strkwargs(req.ui._blockedtimes))
241 req.ui.log("commandfinish", "%s exited %d after %0.2f seconds\n",
241 req.ui.log("commandfinish", "%s exited %d after %0.2f seconds\n",
242 msg, ret or 0, duration)
242 msg, ret or 0, duration)
243 try:
243 try:
244 req._runexithandlers()
244 req._runexithandlers()
245 except: # exiting, so no re-raises
245 except: # exiting, so no re-raises
246 ret = ret or -1
246 ret = ret or -1
247 return ret
247 return ret
248
248
249 def _runcatch(req):
249 def _runcatch(req):
250 def catchterm(*args):
250 def catchterm(*args):
251 raise error.SignalInterrupt
251 raise error.SignalInterrupt
252
252
253 ui = req.ui
253 ui = req.ui
254 try:
254 try:
255 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
255 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
256 num = getattr(signal, name, None)
256 num = getattr(signal, name, None)
257 if num:
257 if num:
258 signal.signal(num, catchterm)
258 signal.signal(num, catchterm)
259 except ValueError:
259 except ValueError:
260 pass # happens if called in a thread
260 pass # happens if called in a thread
261
261
262 def _runcatchfunc():
262 def _runcatchfunc():
263 realcmd = None
263 realcmd = None
264 try:
264 try:
265 cmdargs = fancyopts.fancyopts(req.args[:], commands.globalopts, {})
265 cmdargs = fancyopts.fancyopts(req.args[:], commands.globalopts, {})
266 cmd = cmdargs[0]
266 cmd = cmdargs[0]
267 aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
267 aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
268 realcmd = aliases[0]
268 realcmd = aliases[0]
269 except (error.UnknownCommand, error.AmbiguousCommand,
269 except (error.UnknownCommand, error.AmbiguousCommand,
270 IndexError, getopt.GetoptError):
270 IndexError, getopt.GetoptError):
271 # Don't handle this here. We know the command is
271 # Don't handle this here. We know the command is
272 # invalid, but all we're worried about for now is that
272 # invalid, but all we're worried about for now is that
273 # it's not a command that server operators expect to
273 # it's not a command that server operators expect to
274 # be safe to offer to users in a sandbox.
274 # be safe to offer to users in a sandbox.
275 pass
275 pass
276 if realcmd == 'serve' and '--stdio' in cmdargs:
276 if realcmd == 'serve' and '--stdio' in cmdargs:
277 # We want to constrain 'hg serve --stdio' instances pretty
277 # We want to constrain 'hg serve --stdio' instances pretty
278 # closely, as many shared-ssh access tools want to grant
278 # closely, as many shared-ssh access tools want to grant
279 # access to run *only* 'hg -R $repo serve --stdio'. We
279 # access to run *only* 'hg -R $repo serve --stdio'. We
280 # restrict to exactly that set of arguments, and prohibit
280 # restrict to exactly that set of arguments, and prohibit
281 # any repo name that starts with '--' to prevent
281 # any repo name that starts with '--' to prevent
282 # shenanigans wherein a user does something like pass
282 # shenanigans wherein a user does something like pass
283 # --debugger or --config=ui.debugger=1 as a repo
283 # --debugger or --config=ui.debugger=1 as a repo
284 # name. This used to actually run the debugger.
284 # name. This used to actually run the debugger.
285 if (len(req.args) != 4 or
285 if (len(req.args) != 4 or
286 req.args[0] != '-R' or
286 req.args[0] != '-R' or
287 req.args[1].startswith('--') or
287 req.args[1].startswith('--') or
288 req.args[2] != 'serve' or
288 req.args[2] != 'serve' or
289 req.args[3] != '--stdio'):
289 req.args[3] != '--stdio'):
290 raise error.Abort(
290 raise error.Abort(
291 _('potentially unsafe serve --stdio invocation: %r') %
291 _('potentially unsafe serve --stdio invocation: %r') %
292 (req.args,))
292 (req.args,))
293
293
294 try:
294 try:
295 debugger = 'pdb'
295 debugger = 'pdb'
296 debugtrace = {
296 debugtrace = {
297 'pdb': pdb.set_trace
297 'pdb': pdb.set_trace
298 }
298 }
299 debugmortem = {
299 debugmortem = {
300 'pdb': pdb.post_mortem
300 'pdb': pdb.post_mortem
301 }
301 }
302
302
303 # read --config before doing anything else
303 # read --config before doing anything else
304 # (e.g. to change trust settings for reading .hg/hgrc)
304 # (e.g. to change trust settings for reading .hg/hgrc)
305 cfgs = _parseconfig(req.ui, req.earlyoptions['config'])
305 cfgs = _parseconfig(req.ui, req.earlyoptions['config'])
306
306
307 if req.repo:
307 if req.repo:
308 # copy configs that were passed on the cmdline (--config) to
308 # copy configs that were passed on the cmdline (--config) to
309 # the repo ui
309 # the repo ui
310 for sec, name, val in cfgs:
310 for sec, name, val in cfgs:
311 req.repo.ui.setconfig(sec, name, val, source='--config')
311 req.repo.ui.setconfig(sec, name, val, source='--config')
312
312
313 # developer config: ui.debugger
313 # developer config: ui.debugger
314 debugger = ui.config("ui", "debugger")
314 debugger = ui.config("ui", "debugger")
315 debugmod = pdb
315 debugmod = pdb
316 if not debugger or ui.plain():
316 if not debugger or ui.plain():
317 # if we are in HGPLAIN mode, then disable custom debugging
317 # if we are in HGPLAIN mode, then disable custom debugging
318 debugger = 'pdb'
318 debugger = 'pdb'
319 elif req.earlyoptions['debugger']:
319 elif req.earlyoptions['debugger']:
320 # This import can be slow for fancy debuggers, so only
320 # This import can be slow for fancy debuggers, so only
321 # do it when absolutely necessary, i.e. when actual
321 # do it when absolutely necessary, i.e. when actual
322 # debugging has been requested
322 # debugging has been requested
323 with demandimport.deactivated():
323 with demandimport.deactivated():
324 try:
324 try:
325 debugmod = __import__(debugger)
325 debugmod = __import__(debugger)
326 except ImportError:
326 except ImportError:
327 pass # Leave debugmod = pdb
327 pass # Leave debugmod = pdb
328
328
329 debugtrace[debugger] = debugmod.set_trace
329 debugtrace[debugger] = debugmod.set_trace
330 debugmortem[debugger] = debugmod.post_mortem
330 debugmortem[debugger] = debugmod.post_mortem
331
331
332 # enter the debugger before command execution
332 # enter the debugger before command execution
333 if req.earlyoptions['debugger']:
333 if req.earlyoptions['debugger']:
334 ui.warn(_("entering debugger - "
334 ui.warn(_("entering debugger - "
335 "type c to continue starting hg or h for help\n"))
335 "type c to continue starting hg or h for help\n"))
336
336
337 if (debugger != 'pdb' and
337 if (debugger != 'pdb' and
338 debugtrace[debugger] == debugtrace['pdb']):
338 debugtrace[debugger] == debugtrace['pdb']):
339 ui.warn(_("%s debugger specified "
339 ui.warn(_("%s debugger specified "
340 "but its module was not found\n") % debugger)
340 "but its module was not found\n") % debugger)
341 with demandimport.deactivated():
341 with demandimport.deactivated():
342 debugtrace[debugger]()
342 debugtrace[debugger]()
343 try:
343 try:
344 return _dispatch(req)
344 return _dispatch(req)
345 finally:
345 finally:
346 ui.flush()
346 ui.flush()
347 except: # re-raises
347 except: # re-raises
348 # enter the debugger when we hit an exception
348 # enter the debugger when we hit an exception
349 if req.earlyoptions['debugger']:
349 if req.earlyoptions['debugger']:
350 traceback.print_exc()
350 traceback.print_exc()
351 debugmortem[debugger](sys.exc_info()[2])
351 debugmortem[debugger](sys.exc_info()[2])
352 raise
352 raise
353
353
354 return _callcatch(ui, _runcatchfunc)
354 return _callcatch(ui, _runcatchfunc)
355
355
356 def _callcatch(ui, func):
356 def _callcatch(ui, func):
357 """like scmutil.callcatch but handles more high-level exceptions about
357 """like scmutil.callcatch but handles more high-level exceptions about
358 config parsing and commands. besides, use handlecommandexception to handle
358 config parsing and commands. besides, use handlecommandexception to handle
359 uncaught exceptions.
359 uncaught exceptions.
360 """
360 """
361 try:
361 try:
362 return scmutil.callcatch(ui, func)
362 return scmutil.callcatch(ui, func)
363 except error.AmbiguousCommand as inst:
363 except error.AmbiguousCommand as inst:
364 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
364 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
365 (inst.args[0], " ".join(inst.args[1])))
365 (inst.args[0], " ".join(inst.args[1])))
366 except error.CommandError as inst:
366 except error.CommandError as inst:
367 if inst.args[0]:
367 if inst.args[0]:
368 ui.pager('help')
368 ui.pager('help')
369 msgbytes = pycompat.bytestr(inst.args[1])
369 msgbytes = pycompat.bytestr(inst.args[1])
370 ui.warn(_("hg %s: %s\n") % (inst.args[0], msgbytes))
370 ui.warn(_("hg %s: %s\n") % (inst.args[0], msgbytes))
371 commands.help_(ui, inst.args[0], full=False, command=True)
371 commands.help_(ui, inst.args[0], full=False, command=True)
372 else:
372 else:
373 ui.pager('help')
373 ui.pager('help')
374 ui.warn(_("hg: %s\n") % inst.args[1])
374 ui.warn(_("hg: %s\n") % inst.args[1])
375 commands.help_(ui, 'shortlist')
375 commands.help_(ui, 'shortlist')
376 except error.ParseError as inst:
376 except error.ParseError as inst:
377 _formatparse(ui.warn, inst)
377 _formatparse(ui.warn, inst)
378 return -1
378 return -1
379 except error.UnknownCommand as inst:
379 except error.UnknownCommand as inst:
380 nocmdmsg = _("hg: unknown command '%s'\n") % inst.args[0]
380 nocmdmsg = _("hg: unknown command '%s'\n") % inst.args[0]
381 try:
381 try:
382 # check if the command is in a disabled extension
382 # check if the command is in a disabled extension
383 # (but don't check for extensions themselves)
383 # (but don't check for extensions themselves)
384 formatted = help.formattedhelp(ui, commands, inst.args[0],
384 formatted = help.formattedhelp(ui, commands, inst.args[0],
385 unknowncmd=True)
385 unknowncmd=True)
386 ui.warn(nocmdmsg)
386 ui.warn(nocmdmsg)
387 ui.write(formatted)
387 ui.write(formatted)
388 except (error.UnknownCommand, error.Abort):
388 except (error.UnknownCommand, error.Abort):
389 suggested = False
389 suggested = False
390 if len(inst.args) == 2:
390 if len(inst.args) == 2:
391 sim = _getsimilar(inst.args[1], inst.args[0])
391 sim = _getsimilar(inst.args[1], inst.args[0])
392 if sim:
392 if sim:
393 ui.warn(nocmdmsg)
393 ui.warn(nocmdmsg)
394 _reportsimilar(ui.warn, sim)
394 _reportsimilar(ui.warn, sim)
395 suggested = True
395 suggested = True
396 if not suggested:
396 if not suggested:
397 ui.pager('help')
397 ui.pager('help')
398 ui.warn(nocmdmsg)
398 ui.warn(nocmdmsg)
399 commands.help_(ui, 'shortlist')
399 commands.help_(ui, 'shortlist')
400 except IOError:
400 except IOError:
401 raise
401 raise
402 except KeyboardInterrupt:
402 except KeyboardInterrupt:
403 raise
403 raise
404 except: # probably re-raises
404 except: # probably re-raises
405 if not handlecommandexception(ui):
405 if not handlecommandexception(ui):
406 raise
406 raise
407
407
408 return -1
408 return -1
409
409
410 def aliasargs(fn, givenargs):
410 def aliasargs(fn, givenargs):
411 args = []
411 args = []
412 # only care about alias 'args', ignore 'args' set by extensions.wrapfunction
412 # only care about alias 'args', ignore 'args' set by extensions.wrapfunction
413 if not util.safehasattr(fn, '_origfunc'):
413 if not util.safehasattr(fn, '_origfunc'):
414 args = getattr(fn, 'args', args)
414 args = getattr(fn, 'args', args)
415 if args:
415 if args:
416 cmd = ' '.join(map(procutil.shellquote, args))
416 cmd = ' '.join(map(procutil.shellquote, args))
417
417
418 nums = []
418 nums = []
419 def replacer(m):
419 def replacer(m):
420 num = int(m.group(1)) - 1
420 num = int(m.group(1)) - 1
421 nums.append(num)
421 nums.append(num)
422 if num < len(givenargs):
422 if num < len(givenargs):
423 return givenargs[num]
423 return givenargs[num]
424 raise error.Abort(_('too few arguments for command alias'))
424 raise error.Abort(_('too few arguments for command alias'))
425 cmd = re.sub(br'\$(\d+|\$)', replacer, cmd)
425 cmd = re.sub(br'\$(\d+|\$)', replacer, cmd)
426 givenargs = [x for i, x in enumerate(givenargs)
426 givenargs = [x for i, x in enumerate(givenargs)
427 if i not in nums]
427 if i not in nums]
428 args = pycompat.shlexsplit(cmd)
428 args = pycompat.shlexsplit(cmd)
429 return args + givenargs
429 return args + givenargs
430
430
431 def aliasinterpolate(name, args, cmd):
431 def aliasinterpolate(name, args, cmd):
432 '''interpolate args into cmd for shell aliases
432 '''interpolate args into cmd for shell aliases
433
433
434 This also handles $0, $@ and "$@".
434 This also handles $0, $@ and "$@".
435 '''
435 '''
436 # util.interpolate can't deal with "$@" (with quotes) because it's only
436 # util.interpolate can't deal with "$@" (with quotes) because it's only
437 # built to match prefix + patterns.
437 # built to match prefix + patterns.
438 replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args))
438 replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args))
439 replacemap['$0'] = name
439 replacemap['$0'] = name
440 replacemap['$$'] = '$'
440 replacemap['$$'] = '$'
441 replacemap['$@'] = ' '.join(args)
441 replacemap['$@'] = ' '.join(args)
442 # Typical Unix shells interpolate "$@" (with quotes) as all the positional
442 # Typical Unix shells interpolate "$@" (with quotes) as all the positional
443 # parameters, separated out into words. Emulate the same behavior here by
443 # parameters, separated out into words. Emulate the same behavior here by
444 # quoting the arguments individually. POSIX shells will then typically
444 # quoting the arguments individually. POSIX shells will then typically
445 # tokenize each argument into exactly one word.
445 # tokenize each argument into exactly one word.
446 replacemap['"$@"'] = ' '.join(procutil.shellquote(arg) for arg in args)
446 replacemap['"$@"'] = ' '.join(procutil.shellquote(arg) for arg in args)
447 # escape '\$' for regex
447 # escape '\$' for regex
448 regex = '|'.join(replacemap.keys()).replace('$', br'\$')
448 regex = '|'.join(replacemap.keys()).replace('$', br'\$')
449 r = re.compile(regex)
449 r = re.compile(regex)
450 return r.sub(lambda x: replacemap[x.group()], cmd)
450 return r.sub(lambda x: replacemap[x.group()], cmd)
451
451
452 class cmdalias(object):
452 class cmdalias(object):
453 def __init__(self, name, definition, cmdtable, source):
453 def __init__(self, ui, name, definition, cmdtable, source):
454 self.name = self.cmd = name
454 self.name = self.cmd = name
455 self.cmdname = ''
455 self.cmdname = ''
456 self.definition = definition
456 self.definition = definition
457 self.fn = None
457 self.fn = None
458 self.givenargs = []
458 self.givenargs = []
459 self.opts = []
459 self.opts = []
460 self.help = ''
460 self.help = ''
461 self.badalias = None
461 self.badalias = None
462 self.unknowncmd = False
462 self.unknowncmd = False
463 self.source = source
463 self.source = source
464
464
465 try:
465 try:
466 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
466 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
467 for alias, e in cmdtable.iteritems():
467 for alias, e in cmdtable.iteritems():
468 if e is entry:
468 if e is entry:
469 self.cmd = alias
469 self.cmd = alias
470 break
470 break
471 self.shadows = True
471 self.shadows = True
472 except error.UnknownCommand:
472 except error.UnknownCommand:
473 self.shadows = False
473 self.shadows = False
474
474
475 if not self.definition:
475 if not self.definition:
476 self.badalias = _("no definition for alias '%s'") % self.name
476 self.badalias = _("no definition for alias '%s'") % self.name
477 return
477 return
478
478
479 if self.definition.startswith('!'):
479 if self.definition.startswith('!'):
480 shdef = self.definition[1:]
480 self.shell = True
481 self.shell = True
481 def fn(ui, *args):
482 def fn(ui, *args):
482 env = {'HG_ARGS': ' '.join((self.name,) + args)}
483 env = {'HG_ARGS': ' '.join((self.name,) + args)}
483 def _checkvar(m):
484 def _checkvar(m):
484 if m.groups()[0] == '$':
485 if m.groups()[0] == '$':
485 return m.group()
486 return m.group()
486 elif int(m.groups()[0]) <= len(args):
487 elif int(m.groups()[0]) <= len(args):
487 return m.group()
488 return m.group()
488 else:
489 else:
489 ui.debug("No argument found for substitution "
490 ui.debug("No argument found for substitution "
490 "of %i variable in alias '%s' definition.\n"
491 "of %i variable in alias '%s' definition.\n"
491 % (int(m.groups()[0]), self.name))
492 % (int(m.groups()[0]), self.name))
492 return ''
493 return ''
493 cmd = re.sub(br'\$(\d+|\$)', _checkvar, self.definition[1:])
494 cmd = re.sub(br'\$(\d+|\$)', _checkvar, shdef)
494 cmd = aliasinterpolate(self.name, args, cmd)
495 cmd = aliasinterpolate(self.name, args, cmd)
495 return ui.system(cmd, environ=env,
496 return ui.system(cmd, environ=env,
496 blockedtag='alias_%s' % self.name)
497 blockedtag='alias_%s' % self.name)
497 self.fn = fn
498 self.fn = fn
499 self._populatehelp(ui, name, shdef, self.fn)
498 return
500 return
499
501
500 try:
502 try:
501 args = pycompat.shlexsplit(self.definition)
503 args = pycompat.shlexsplit(self.definition)
502 except ValueError as inst:
504 except ValueError as inst:
503 self.badalias = (_("error in definition for alias '%s': %s")
505 self.badalias = (_("error in definition for alias '%s': %s")
504 % (self.name, stringutil.forcebytestr(inst)))
506 % (self.name, stringutil.forcebytestr(inst)))
505 return
507 return
506 earlyopts, args = _earlysplitopts(args)
508 earlyopts, args = _earlysplitopts(args)
507 if earlyopts:
509 if earlyopts:
508 self.badalias = (_("error in definition for alias '%s': %s may "
510 self.badalias = (_("error in definition for alias '%s': %s may "
509 "only be given on the command line")
511 "only be given on the command line")
510 % (self.name, '/'.join(pycompat.ziplist(*earlyopts)
512 % (self.name, '/'.join(pycompat.ziplist(*earlyopts)
511 [0])))
513 [0])))
512 return
514 return
513 self.cmdname = cmd = args.pop(0)
515 self.cmdname = cmd = args.pop(0)
514 self.givenargs = args
516 self.givenargs = args
515
517
516 try:
518 try:
517 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
519 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
518 if len(tableentry) > 2:
520 if len(tableentry) > 2:
519 self.fn, self.opts, self.help = tableentry
521 self.fn, self.opts, cmdhelp = tableentry
520 else:
522 else:
521 self.fn, self.opts = tableentry
523 self.fn, self.opts = tableentry
524 cmdhelp = None
522
525
523 if self.help.startswith("hg " + cmd):
526 self._populatehelp(ui, name, cmd, self.fn, cmdhelp)
524 # drop prefix in old-style help lines so hg shows the alias
525 self.help = self.help[4 + len(cmd):]
526 self.__doc__ = self.fn.__doc__
527
527
528 except error.UnknownCommand:
528 except error.UnknownCommand:
529 self.badalias = (_("alias '%s' resolves to unknown command '%s'")
529 self.badalias = (_("alias '%s' resolves to unknown command '%s'")
530 % (self.name, cmd))
530 % (self.name, cmd))
531 self.unknowncmd = True
531 self.unknowncmd = True
532 except error.AmbiguousCommand:
532 except error.AmbiguousCommand:
533 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
533 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
534 % (self.name, cmd))
534 % (self.name, cmd))
535
535
536 def _populatehelp(self, ui, name, cmd, fn, defaulthelp=None):
537 self.help = ui.config('alias', '%s:help' % name, defaulthelp or '')
538 if self.help and self.help.startswith("hg " + cmd):
539 # drop prefix in old-style help lines so hg shows the alias
540 self.help = self.help[4 + len(cmd):]
541
542 self.__doc__ = ui.config('alias', '%s:doc' % name, fn.__doc__)
543
536 @property
544 @property
537 def args(self):
545 def args(self):
538 args = pycompat.maplist(util.expandpath, self.givenargs)
546 args = pycompat.maplist(util.expandpath, self.givenargs)
539 return aliasargs(self.fn, args)
547 return aliasargs(self.fn, args)
540
548
541 def __getattr__(self, name):
549 def __getattr__(self, name):
542 adefaults = {r'norepo': True, r'cmdtype': unrecoverablewrite,
550 adefaults = {r'norepo': True, r'cmdtype': unrecoverablewrite,
543 r'optionalrepo': False, r'inferrepo': False}
551 r'optionalrepo': False, r'inferrepo': False}
544 if name not in adefaults:
552 if name not in adefaults:
545 raise AttributeError(name)
553 raise AttributeError(name)
546 if self.badalias or util.safehasattr(self, 'shell'):
554 if self.badalias or util.safehasattr(self, 'shell'):
547 return adefaults[name]
555 return adefaults[name]
548 return getattr(self.fn, name)
556 return getattr(self.fn, name)
549
557
550 def __call__(self, ui, *args, **opts):
558 def __call__(self, ui, *args, **opts):
551 if self.badalias:
559 if self.badalias:
552 hint = None
560 hint = None
553 if self.unknowncmd:
561 if self.unknowncmd:
554 try:
562 try:
555 # check if the command is in a disabled extension
563 # check if the command is in a disabled extension
556 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2]
564 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2]
557 hint = _("'%s' is provided by '%s' extension") % (cmd, ext)
565 hint = _("'%s' is provided by '%s' extension") % (cmd, ext)
558 except error.UnknownCommand:
566 except error.UnknownCommand:
559 pass
567 pass
560 raise error.Abort(self.badalias, hint=hint)
568 raise error.Abort(self.badalias, hint=hint)
561 if self.shadows:
569 if self.shadows:
562 ui.debug("alias '%s' shadows command '%s'\n" %
570 ui.debug("alias '%s' shadows command '%s'\n" %
563 (self.name, self.cmdname))
571 (self.name, self.cmdname))
564
572
565 ui.log('commandalias', "alias '%s' expands to '%s'\n",
573 ui.log('commandalias', "alias '%s' expands to '%s'\n",
566 self.name, self.definition)
574 self.name, self.definition)
567 if util.safehasattr(self, 'shell'):
575 if util.safehasattr(self, 'shell'):
568 return self.fn(ui, *args, **opts)
576 return self.fn(ui, *args, **opts)
569 else:
577 else:
570 try:
578 try:
571 return util.checksignature(self.fn)(ui, *args, **opts)
579 return util.checksignature(self.fn)(ui, *args, **opts)
572 except error.SignatureError:
580 except error.SignatureError:
573 args = ' '.join([self.cmdname] + self.args)
581 args = ' '.join([self.cmdname] + self.args)
574 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
582 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
575 raise
583 raise
576
584
577 class lazyaliasentry(object):
585 class lazyaliasentry(object):
578 """like a typical command entry (func, opts, help), but is lazy"""
586 """like a typical command entry (func, opts, help), but is lazy"""
579
587
580 def __init__(self, name, definition, cmdtable, source):
588 def __init__(self, ui, name, definition, cmdtable, source):
589 self.ui = ui
581 self.name = name
590 self.name = name
582 self.definition = definition
591 self.definition = definition
583 self.cmdtable = cmdtable.copy()
592 self.cmdtable = cmdtable.copy()
584 self.source = source
593 self.source = source
585
594
586 @util.propertycache
595 @util.propertycache
587 def _aliasdef(self):
596 def _aliasdef(self):
588 return cmdalias(self.name, self.definition, self.cmdtable, self.source)
597 return cmdalias(self.ui, self.name, self.definition, self.cmdtable,
598 self.source)
589
599
590 def __getitem__(self, n):
600 def __getitem__(self, n):
591 aliasdef = self._aliasdef
601 aliasdef = self._aliasdef
592 if n == 0:
602 if n == 0:
593 return aliasdef
603 return aliasdef
594 elif n == 1:
604 elif n == 1:
595 return aliasdef.opts
605 return aliasdef.opts
596 elif n == 2:
606 elif n == 2:
597 return aliasdef.help
607 return aliasdef.help
598 else:
608 else:
599 raise IndexError
609 raise IndexError
600
610
601 def __iter__(self):
611 def __iter__(self):
602 for i in range(3):
612 for i in range(3):
603 yield self[i]
613 yield self[i]
604
614
605 def __len__(self):
615 def __len__(self):
606 return 3
616 return 3
607
617
608 def addaliases(ui, cmdtable):
618 def addaliases(ui, cmdtable):
609 # aliases are processed after extensions have been loaded, so they
619 # aliases are processed after extensions have been loaded, so they
610 # may use extension commands. Aliases can also use other alias definitions,
620 # may use extension commands. Aliases can also use other alias definitions,
611 # but only if they have been defined prior to the current definition.
621 # but only if they have been defined prior to the current definition.
612 for alias, definition in ui.configitems('alias'):
622 for alias, definition in ui.configitems('alias', ignoresub=True):
613 try:
623 try:
614 if cmdtable[alias].definition == definition:
624 if cmdtable[alias].definition == definition:
615 continue
625 continue
616 except (KeyError, AttributeError):
626 except (KeyError, AttributeError):
617 # definition might not exist or it might not be a cmdalias
627 # definition might not exist or it might not be a cmdalias
618 pass
628 pass
619
629
620 source = ui.configsource('alias', alias)
630 source = ui.configsource('alias', alias)
621 entry = lazyaliasentry(alias, definition, cmdtable, source)
631 entry = lazyaliasentry(ui, alias, definition, cmdtable, source)
622 cmdtable[alias] = entry
632 cmdtable[alias] = entry
623
633
624 def _parse(ui, args):
634 def _parse(ui, args):
625 options = {}
635 options = {}
626 cmdoptions = {}
636 cmdoptions = {}
627
637
628 try:
638 try:
629 args = fancyopts.fancyopts(args, commands.globalopts, options)
639 args = fancyopts.fancyopts(args, commands.globalopts, options)
630 except getopt.GetoptError as inst:
640 except getopt.GetoptError as inst:
631 raise error.CommandError(None, stringutil.forcebytestr(inst))
641 raise error.CommandError(None, stringutil.forcebytestr(inst))
632
642
633 if args:
643 if args:
634 cmd, args = args[0], args[1:]
644 cmd, args = args[0], args[1:]
635 aliases, entry = cmdutil.findcmd(cmd, commands.table,
645 aliases, entry = cmdutil.findcmd(cmd, commands.table,
636 ui.configbool("ui", "strict"))
646 ui.configbool("ui", "strict"))
637 cmd = aliases[0]
647 cmd = aliases[0]
638 args = aliasargs(entry[0], args)
648 args = aliasargs(entry[0], args)
639 defaults = ui.config("defaults", cmd)
649 defaults = ui.config("defaults", cmd)
640 if defaults:
650 if defaults:
641 args = pycompat.maplist(
651 args = pycompat.maplist(
642 util.expandpath, pycompat.shlexsplit(defaults)) + args
652 util.expandpath, pycompat.shlexsplit(defaults)) + args
643 c = list(entry[1])
653 c = list(entry[1])
644 else:
654 else:
645 cmd = None
655 cmd = None
646 c = []
656 c = []
647
657
648 # combine global options into local
658 # combine global options into local
649 for o in commands.globalopts:
659 for o in commands.globalopts:
650 c.append((o[0], o[1], options[o[1]], o[3]))
660 c.append((o[0], o[1], options[o[1]], o[3]))
651
661
652 try:
662 try:
653 args = fancyopts.fancyopts(args, c, cmdoptions, gnu=True)
663 args = fancyopts.fancyopts(args, c, cmdoptions, gnu=True)
654 except getopt.GetoptError as inst:
664 except getopt.GetoptError as inst:
655 raise error.CommandError(cmd, stringutil.forcebytestr(inst))
665 raise error.CommandError(cmd, stringutil.forcebytestr(inst))
656
666
657 # separate global options back out
667 # separate global options back out
658 for o in commands.globalopts:
668 for o in commands.globalopts:
659 n = o[1]
669 n = o[1]
660 options[n] = cmdoptions[n]
670 options[n] = cmdoptions[n]
661 del cmdoptions[n]
671 del cmdoptions[n]
662
672
663 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
673 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
664
674
665 def _parseconfig(ui, config):
675 def _parseconfig(ui, config):
666 """parse the --config options from the command line"""
676 """parse the --config options from the command line"""
667 configs = []
677 configs = []
668
678
669 for cfg in config:
679 for cfg in config:
670 try:
680 try:
671 name, value = [cfgelem.strip()
681 name, value = [cfgelem.strip()
672 for cfgelem in cfg.split('=', 1)]
682 for cfgelem in cfg.split('=', 1)]
673 section, name = name.split('.', 1)
683 section, name = name.split('.', 1)
674 if not section or not name:
684 if not section or not name:
675 raise IndexError
685 raise IndexError
676 ui.setconfig(section, name, value, '--config')
686 ui.setconfig(section, name, value, '--config')
677 configs.append((section, name, value))
687 configs.append((section, name, value))
678 except (IndexError, ValueError):
688 except (IndexError, ValueError):
679 raise error.Abort(_('malformed --config option: %r '
689 raise error.Abort(_('malformed --config option: %r '
680 '(use --config section.name=value)')
690 '(use --config section.name=value)')
681 % pycompat.bytestr(cfg))
691 % pycompat.bytestr(cfg))
682
692
683 return configs
693 return configs
684
694
685 def _earlyparseopts(ui, args):
695 def _earlyparseopts(ui, args):
686 options = {}
696 options = {}
687 fancyopts.fancyopts(args, commands.globalopts, options,
697 fancyopts.fancyopts(args, commands.globalopts, options,
688 gnu=not ui.plain('strictflags'), early=True,
698 gnu=not ui.plain('strictflags'), early=True,
689 optaliases={'repository': ['repo']})
699 optaliases={'repository': ['repo']})
690 return options
700 return options
691
701
692 def _earlysplitopts(args):
702 def _earlysplitopts(args):
693 """Split args into a list of possible early options and remainder args"""
703 """Split args into a list of possible early options and remainder args"""
694 shortoptions = 'R:'
704 shortoptions = 'R:'
695 # TODO: perhaps 'debugger' should be included
705 # TODO: perhaps 'debugger' should be included
696 longoptions = ['cwd=', 'repository=', 'repo=', 'config=']
706 longoptions = ['cwd=', 'repository=', 'repo=', 'config=']
697 return fancyopts.earlygetopt(args, shortoptions, longoptions,
707 return fancyopts.earlygetopt(args, shortoptions, longoptions,
698 gnu=True, keepsep=True)
708 gnu=True, keepsep=True)
699
709
700 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
710 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
701 # run pre-hook, and abort if it fails
711 # run pre-hook, and abort if it fails
702 hook.hook(lui, repo, "pre-%s" % cmd, True, args=" ".join(fullargs),
712 hook.hook(lui, repo, "pre-%s" % cmd, True, args=" ".join(fullargs),
703 pats=cmdpats, opts=cmdoptions)
713 pats=cmdpats, opts=cmdoptions)
704 try:
714 try:
705 ret = _runcommand(ui, options, cmd, d)
715 ret = _runcommand(ui, options, cmd, d)
706 # run post-hook, passing command result
716 # run post-hook, passing command result
707 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
717 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
708 result=ret, pats=cmdpats, opts=cmdoptions)
718 result=ret, pats=cmdpats, opts=cmdoptions)
709 except Exception:
719 except Exception:
710 # run failure hook and re-raise
720 # run failure hook and re-raise
711 hook.hook(lui, repo, "fail-%s" % cmd, False, args=" ".join(fullargs),
721 hook.hook(lui, repo, "fail-%s" % cmd, False, args=" ".join(fullargs),
712 pats=cmdpats, opts=cmdoptions)
722 pats=cmdpats, opts=cmdoptions)
713 raise
723 raise
714 return ret
724 return ret
715
725
716 def _getlocal(ui, rpath, wd=None):
726 def _getlocal(ui, rpath, wd=None):
717 """Return (path, local ui object) for the given target path.
727 """Return (path, local ui object) for the given target path.
718
728
719 Takes paths in [cwd]/.hg/hgrc into account."
729 Takes paths in [cwd]/.hg/hgrc into account."
720 """
730 """
721 if wd is None:
731 if wd is None:
722 try:
732 try:
723 wd = pycompat.getcwd()
733 wd = pycompat.getcwd()
724 except OSError as e:
734 except OSError as e:
725 raise error.Abort(_("error getting current working directory: %s") %
735 raise error.Abort(_("error getting current working directory: %s") %
726 encoding.strtolocal(e.strerror))
736 encoding.strtolocal(e.strerror))
727 path = cmdutil.findrepo(wd) or ""
737 path = cmdutil.findrepo(wd) or ""
728 if not path:
738 if not path:
729 lui = ui
739 lui = ui
730 else:
740 else:
731 lui = ui.copy()
741 lui = ui.copy()
732 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
742 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
733
743
734 if rpath:
744 if rpath:
735 path = lui.expandpath(rpath)
745 path = lui.expandpath(rpath)
736 lui = ui.copy()
746 lui = ui.copy()
737 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
747 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
738
748
739 return path, lui
749 return path, lui
740
750
741 def _checkshellalias(lui, ui, args):
751 def _checkshellalias(lui, ui, args):
742 """Return the function to run the shell alias, if it is required"""
752 """Return the function to run the shell alias, if it is required"""
743 options = {}
753 options = {}
744
754
745 try:
755 try:
746 args = fancyopts.fancyopts(args, commands.globalopts, options)
756 args = fancyopts.fancyopts(args, commands.globalopts, options)
747 except getopt.GetoptError:
757 except getopt.GetoptError:
748 return
758 return
749
759
750 if not args:
760 if not args:
751 return
761 return
752
762
753 cmdtable = commands.table
763 cmdtable = commands.table
754
764
755 cmd = args[0]
765 cmd = args[0]
756 try:
766 try:
757 strict = ui.configbool("ui", "strict")
767 strict = ui.configbool("ui", "strict")
758 aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
768 aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
759 except (error.AmbiguousCommand, error.UnknownCommand):
769 except (error.AmbiguousCommand, error.UnknownCommand):
760 return
770 return
761
771
762 cmd = aliases[0]
772 cmd = aliases[0]
763 fn = entry[0]
773 fn = entry[0]
764
774
765 if cmd and util.safehasattr(fn, 'shell'):
775 if cmd and util.safehasattr(fn, 'shell'):
766 # shell alias shouldn't receive early options which are consumed by hg
776 # shell alias shouldn't receive early options which are consumed by hg
767 _earlyopts, args = _earlysplitopts(args)
777 _earlyopts, args = _earlysplitopts(args)
768 d = lambda: fn(ui, *args[1:])
778 d = lambda: fn(ui, *args[1:])
769 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
779 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
770 [], {})
780 [], {})
771
781
772 def _dispatch(req):
782 def _dispatch(req):
773 args = req.args
783 args = req.args
774 ui = req.ui
784 ui = req.ui
775
785
776 # check for cwd
786 # check for cwd
777 cwd = req.earlyoptions['cwd']
787 cwd = req.earlyoptions['cwd']
778 if cwd:
788 if cwd:
779 os.chdir(cwd)
789 os.chdir(cwd)
780
790
781 rpath = req.earlyoptions['repository']
791 rpath = req.earlyoptions['repository']
782 path, lui = _getlocal(ui, rpath)
792 path, lui = _getlocal(ui, rpath)
783
793
784 uis = {ui, lui}
794 uis = {ui, lui}
785
795
786 if req.repo:
796 if req.repo:
787 uis.add(req.repo.ui)
797 uis.add(req.repo.ui)
788
798
789 if req.earlyoptions['profile']:
799 if req.earlyoptions['profile']:
790 for ui_ in uis:
800 for ui_ in uis:
791 ui_.setconfig('profiling', 'enabled', 'true', '--profile')
801 ui_.setconfig('profiling', 'enabled', 'true', '--profile')
792
802
793 profile = lui.configbool('profiling', 'enabled')
803 profile = lui.configbool('profiling', 'enabled')
794 with profiling.profile(lui, enabled=profile) as profiler:
804 with profiling.profile(lui, enabled=profile) as profiler:
795 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
805 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
796 # reposetup
806 # reposetup
797 extensions.loadall(lui)
807 extensions.loadall(lui)
798 # Propagate any changes to lui.__class__ by extensions
808 # Propagate any changes to lui.__class__ by extensions
799 ui.__class__ = lui.__class__
809 ui.__class__ = lui.__class__
800
810
801 # (uisetup and extsetup are handled in extensions.loadall)
811 # (uisetup and extsetup are handled in extensions.loadall)
802
812
803 # (reposetup is handled in hg.repository)
813 # (reposetup is handled in hg.repository)
804
814
805 addaliases(lui, commands.table)
815 addaliases(lui, commands.table)
806
816
807 # All aliases and commands are completely defined, now.
817 # All aliases and commands are completely defined, now.
808 # Check abbreviation/ambiguity of shell alias.
818 # Check abbreviation/ambiguity of shell alias.
809 shellaliasfn = _checkshellalias(lui, ui, args)
819 shellaliasfn = _checkshellalias(lui, ui, args)
810 if shellaliasfn:
820 if shellaliasfn:
811 return shellaliasfn()
821 return shellaliasfn()
812
822
813 # check for fallback encoding
823 # check for fallback encoding
814 fallback = lui.config('ui', 'fallbackencoding')
824 fallback = lui.config('ui', 'fallbackencoding')
815 if fallback:
825 if fallback:
816 encoding.fallbackencoding = fallback
826 encoding.fallbackencoding = fallback
817
827
818 fullargs = args
828 fullargs = args
819 cmd, func, args, options, cmdoptions = _parse(lui, args)
829 cmd, func, args, options, cmdoptions = _parse(lui, args)
820
830
821 if options["config"] != req.earlyoptions["config"]:
831 if options["config"] != req.earlyoptions["config"]:
822 raise error.Abort(_("option --config may not be abbreviated!"))
832 raise error.Abort(_("option --config may not be abbreviated!"))
823 if options["cwd"] != req.earlyoptions["cwd"]:
833 if options["cwd"] != req.earlyoptions["cwd"]:
824 raise error.Abort(_("option --cwd may not be abbreviated!"))
834 raise error.Abort(_("option --cwd may not be abbreviated!"))
825 if options["repository"] != req.earlyoptions["repository"]:
835 if options["repository"] != req.earlyoptions["repository"]:
826 raise error.Abort(_(
836 raise error.Abort(_(
827 "option -R has to be separated from other options (e.g. not "
837 "option -R has to be separated from other options (e.g. not "
828 "-qR) and --repository may only be abbreviated as --repo!"))
838 "-qR) and --repository may only be abbreviated as --repo!"))
829 if options["debugger"] != req.earlyoptions["debugger"]:
839 if options["debugger"] != req.earlyoptions["debugger"]:
830 raise error.Abort(_("option --debugger may not be abbreviated!"))
840 raise error.Abort(_("option --debugger may not be abbreviated!"))
831 # don't validate --profile/--traceback, which can be enabled from now
841 # don't validate --profile/--traceback, which can be enabled from now
832
842
833 if options["encoding"]:
843 if options["encoding"]:
834 encoding.encoding = options["encoding"]
844 encoding.encoding = options["encoding"]
835 if options["encodingmode"]:
845 if options["encodingmode"]:
836 encoding.encodingmode = options["encodingmode"]
846 encoding.encodingmode = options["encodingmode"]
837 if options["time"]:
847 if options["time"]:
838 def get_times():
848 def get_times():
839 t = os.times()
849 t = os.times()
840 if t[4] == 0.0:
850 if t[4] == 0.0:
841 # Windows leaves this as zero, so use time.clock()
851 # Windows leaves this as zero, so use time.clock()
842 t = (t[0], t[1], t[2], t[3], time.clock())
852 t = (t[0], t[1], t[2], t[3], time.clock())
843 return t
853 return t
844 s = get_times()
854 s = get_times()
845 def print_time():
855 def print_time():
846 t = get_times()
856 t = get_times()
847 ui.warn(
857 ui.warn(
848 _("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
858 _("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
849 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
859 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
850 ui.atexit(print_time)
860 ui.atexit(print_time)
851 if options["profile"]:
861 if options["profile"]:
852 profiler.start()
862 profiler.start()
853
863
854 if options['verbose'] or options['debug'] or options['quiet']:
864 if options['verbose'] or options['debug'] or options['quiet']:
855 for opt in ('verbose', 'debug', 'quiet'):
865 for opt in ('verbose', 'debug', 'quiet'):
856 val = pycompat.bytestr(bool(options[opt]))
866 val = pycompat.bytestr(bool(options[opt]))
857 for ui_ in uis:
867 for ui_ in uis:
858 ui_.setconfig('ui', opt, val, '--' + opt)
868 ui_.setconfig('ui', opt, val, '--' + opt)
859
869
860 if options['traceback']:
870 if options['traceback']:
861 for ui_ in uis:
871 for ui_ in uis:
862 ui_.setconfig('ui', 'traceback', 'on', '--traceback')
872 ui_.setconfig('ui', 'traceback', 'on', '--traceback')
863
873
864 if options['noninteractive']:
874 if options['noninteractive']:
865 for ui_ in uis:
875 for ui_ in uis:
866 ui_.setconfig('ui', 'interactive', 'off', '-y')
876 ui_.setconfig('ui', 'interactive', 'off', '-y')
867
877
868 if cmdoptions.get('insecure', False):
878 if cmdoptions.get('insecure', False):
869 for ui_ in uis:
879 for ui_ in uis:
870 ui_.insecureconnections = True
880 ui_.insecureconnections = True
871
881
872 # setup color handling before pager, because setting up pager
882 # setup color handling before pager, because setting up pager
873 # might cause incorrect console information
883 # might cause incorrect console information
874 coloropt = options['color']
884 coloropt = options['color']
875 for ui_ in uis:
885 for ui_ in uis:
876 if coloropt:
886 if coloropt:
877 ui_.setconfig('ui', 'color', coloropt, '--color')
887 ui_.setconfig('ui', 'color', coloropt, '--color')
878 color.setup(ui_)
888 color.setup(ui_)
879
889
880 if stringutil.parsebool(options['pager']):
890 if stringutil.parsebool(options['pager']):
881 # ui.pager() expects 'internal-always-' prefix in this case
891 # ui.pager() expects 'internal-always-' prefix in this case
882 ui.pager('internal-always-' + cmd)
892 ui.pager('internal-always-' + cmd)
883 elif options['pager'] != 'auto':
893 elif options['pager'] != 'auto':
884 for ui_ in uis:
894 for ui_ in uis:
885 ui_.disablepager()
895 ui_.disablepager()
886
896
887 if options['version']:
897 if options['version']:
888 return commands.version_(ui)
898 return commands.version_(ui)
889 if options['help']:
899 if options['help']:
890 return commands.help_(ui, cmd, command=cmd is not None)
900 return commands.help_(ui, cmd, command=cmd is not None)
891 elif not cmd:
901 elif not cmd:
892 return commands.help_(ui, 'shortlist')
902 return commands.help_(ui, 'shortlist')
893
903
894 repo = None
904 repo = None
895 cmdpats = args[:]
905 cmdpats = args[:]
896 if not func.norepo:
906 if not func.norepo:
897 # use the repo from the request only if we don't have -R
907 # use the repo from the request only if we don't have -R
898 if not rpath and not cwd:
908 if not rpath and not cwd:
899 repo = req.repo
909 repo = req.repo
900
910
901 if repo:
911 if repo:
902 # set the descriptors of the repo ui to those of ui
912 # set the descriptors of the repo ui to those of ui
903 repo.ui.fin = ui.fin
913 repo.ui.fin = ui.fin
904 repo.ui.fout = ui.fout
914 repo.ui.fout = ui.fout
905 repo.ui.ferr = ui.ferr
915 repo.ui.ferr = ui.ferr
906 else:
916 else:
907 try:
917 try:
908 repo = hg.repository(ui, path=path,
918 repo = hg.repository(ui, path=path,
909 presetupfuncs=req.prereposetups)
919 presetupfuncs=req.prereposetups)
910 if not repo.local():
920 if not repo.local():
911 raise error.Abort(_("repository '%s' is not local")
921 raise error.Abort(_("repository '%s' is not local")
912 % path)
922 % path)
913 repo.ui.setconfig("bundle", "mainreporoot", repo.root,
923 repo.ui.setconfig("bundle", "mainreporoot", repo.root,
914 'repo')
924 'repo')
915 except error.RequirementError:
925 except error.RequirementError:
916 raise
926 raise
917 except error.RepoError:
927 except error.RepoError:
918 if rpath: # invalid -R path
928 if rpath: # invalid -R path
919 raise
929 raise
920 if not func.optionalrepo:
930 if not func.optionalrepo:
921 if func.inferrepo and args and not path:
931 if func.inferrepo and args and not path:
922 # try to infer -R from command args
932 # try to infer -R from command args
923 repos = pycompat.maplist(cmdutil.findrepo, args)
933 repos = pycompat.maplist(cmdutil.findrepo, args)
924 guess = repos[0]
934 guess = repos[0]
925 if guess and repos.count(guess) == len(repos):
935 if guess and repos.count(guess) == len(repos):
926 req.args = ['--repository', guess] + fullargs
936 req.args = ['--repository', guess] + fullargs
927 req.earlyoptions['repository'] = guess
937 req.earlyoptions['repository'] = guess
928 return _dispatch(req)
938 return _dispatch(req)
929 if not path:
939 if not path:
930 raise error.RepoError(_("no repository found in"
940 raise error.RepoError(_("no repository found in"
931 " '%s' (.hg not found)")
941 " '%s' (.hg not found)")
932 % pycompat.getcwd())
942 % pycompat.getcwd())
933 raise
943 raise
934 if repo:
944 if repo:
935 ui = repo.ui
945 ui = repo.ui
936 if options['hidden']:
946 if options['hidden']:
937 repo = repo.unfiltered()
947 repo = repo.unfiltered()
938 args.insert(0, repo)
948 args.insert(0, repo)
939 elif rpath:
949 elif rpath:
940 ui.warn(_("warning: --repository ignored\n"))
950 ui.warn(_("warning: --repository ignored\n"))
941
951
942 msg = _formatargs(fullargs)
952 msg = _formatargs(fullargs)
943 ui.log("command", '%s\n', msg)
953 ui.log("command", '%s\n', msg)
944 strcmdopt = pycompat.strkwargs(cmdoptions)
954 strcmdopt = pycompat.strkwargs(cmdoptions)
945 d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
955 d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
946 try:
956 try:
947 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
957 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
948 cmdpats, cmdoptions)
958 cmdpats, cmdoptions)
949 finally:
959 finally:
950 if repo and repo != req.repo:
960 if repo and repo != req.repo:
951 repo.close()
961 repo.close()
952
962
953 def _runcommand(ui, options, cmd, cmdfunc):
963 def _runcommand(ui, options, cmd, cmdfunc):
954 """Run a command function, possibly with profiling enabled."""
964 """Run a command function, possibly with profiling enabled."""
955 try:
965 try:
956 return cmdfunc()
966 return cmdfunc()
957 except error.SignatureError:
967 except error.SignatureError:
958 raise error.CommandError(cmd, _('invalid arguments'))
968 raise error.CommandError(cmd, _('invalid arguments'))
959
969
960 def _exceptionwarning(ui):
970 def _exceptionwarning(ui):
961 """Produce a warning message for the current active exception"""
971 """Produce a warning message for the current active exception"""
962
972
963 # For compatibility checking, we discard the portion of the hg
973 # For compatibility checking, we discard the portion of the hg
964 # version after the + on the assumption that if a "normal
974 # version after the + on the assumption that if a "normal
965 # user" is running a build with a + in it the packager
975 # user" is running a build with a + in it the packager
966 # probably built from fairly close to a tag and anyone with a
976 # probably built from fairly close to a tag and anyone with a
967 # 'make local' copy of hg (where the version number can be out
977 # 'make local' copy of hg (where the version number can be out
968 # of date) will be clueful enough to notice the implausible
978 # of date) will be clueful enough to notice the implausible
969 # version number and try updating.
979 # version number and try updating.
970 ct = util.versiontuple(n=2)
980 ct = util.versiontuple(n=2)
971 worst = None, ct, ''
981 worst = None, ct, ''
972 if ui.config('ui', 'supportcontact') is None:
982 if ui.config('ui', 'supportcontact') is None:
973 for name, mod in extensions.extensions():
983 for name, mod in extensions.extensions():
974 # 'testedwith' should be bytes, but not all extensions are ported
984 # 'testedwith' should be bytes, but not all extensions are ported
975 # to py3 and we don't want UnicodeException because of that.
985 # to py3 and we don't want UnicodeException because of that.
976 testedwith = stringutil.forcebytestr(getattr(mod, 'testedwith', ''))
986 testedwith = stringutil.forcebytestr(getattr(mod, 'testedwith', ''))
977 report = getattr(mod, 'buglink', _('the extension author.'))
987 report = getattr(mod, 'buglink', _('the extension author.'))
978 if not testedwith.strip():
988 if not testedwith.strip():
979 # We found an untested extension. It's likely the culprit.
989 # We found an untested extension. It's likely the culprit.
980 worst = name, 'unknown', report
990 worst = name, 'unknown', report
981 break
991 break
982
992
983 # Never blame on extensions bundled with Mercurial.
993 # Never blame on extensions bundled with Mercurial.
984 if extensions.ismoduleinternal(mod):
994 if extensions.ismoduleinternal(mod):
985 continue
995 continue
986
996
987 tested = [util.versiontuple(t, 2) for t in testedwith.split()]
997 tested = [util.versiontuple(t, 2) for t in testedwith.split()]
988 if ct in tested:
998 if ct in tested:
989 continue
999 continue
990
1000
991 lower = [t for t in tested if t < ct]
1001 lower = [t for t in tested if t < ct]
992 nearest = max(lower or tested)
1002 nearest = max(lower or tested)
993 if worst[0] is None or nearest < worst[1]:
1003 if worst[0] is None or nearest < worst[1]:
994 worst = name, nearest, report
1004 worst = name, nearest, report
995 if worst[0] is not None:
1005 if worst[0] is not None:
996 name, testedwith, report = worst
1006 name, testedwith, report = worst
997 if not isinstance(testedwith, (bytes, str)):
1007 if not isinstance(testedwith, (bytes, str)):
998 testedwith = '.'.join([stringutil.forcebytestr(c)
1008 testedwith = '.'.join([stringutil.forcebytestr(c)
999 for c in testedwith])
1009 for c in testedwith])
1000 warning = (_('** Unknown exception encountered with '
1010 warning = (_('** Unknown exception encountered with '
1001 'possibly-broken third-party extension %s\n'
1011 'possibly-broken third-party extension %s\n'
1002 '** which supports versions %s of Mercurial.\n'
1012 '** which supports versions %s of Mercurial.\n'
1003 '** Please disable %s and try your action again.\n'
1013 '** Please disable %s and try your action again.\n'
1004 '** If that fixes the bug please report it to %s\n')
1014 '** If that fixes the bug please report it to %s\n')
1005 % (name, testedwith, name, report))
1015 % (name, testedwith, name, report))
1006 else:
1016 else:
1007 bugtracker = ui.config('ui', 'supportcontact')
1017 bugtracker = ui.config('ui', 'supportcontact')
1008 if bugtracker is None:
1018 if bugtracker is None:
1009 bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
1019 bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
1010 warning = (_("** unknown exception encountered, "
1020 warning = (_("** unknown exception encountered, "
1011 "please report by visiting\n** ") + bugtracker + '\n')
1021 "please report by visiting\n** ") + bugtracker + '\n')
1012 sysversion = pycompat.sysbytes(sys.version).replace('\n', '')
1022 sysversion = pycompat.sysbytes(sys.version).replace('\n', '')
1013 warning += ((_("** Python %s\n") % sysversion) +
1023 warning += ((_("** Python %s\n") % sysversion) +
1014 (_("** Mercurial Distributed SCM (version %s)\n") %
1024 (_("** Mercurial Distributed SCM (version %s)\n") %
1015 util.version()) +
1025 util.version()) +
1016 (_("** Extensions loaded: %s\n") %
1026 (_("** Extensions loaded: %s\n") %
1017 ", ".join([x[0] for x in extensions.extensions()])))
1027 ", ".join([x[0] for x in extensions.extensions()])))
1018 return warning
1028 return warning
1019
1029
1020 def handlecommandexception(ui):
1030 def handlecommandexception(ui):
1021 """Produce a warning message for broken commands
1031 """Produce a warning message for broken commands
1022
1032
1023 Called when handling an exception; the exception is reraised if
1033 Called when handling an exception; the exception is reraised if
1024 this function returns False, ignored otherwise.
1034 this function returns False, ignored otherwise.
1025 """
1035 """
1026 warning = _exceptionwarning(ui)
1036 warning = _exceptionwarning(ui)
1027 ui.log("commandexception", "%s\n%s\n", warning,
1037 ui.log("commandexception", "%s\n%s\n", warning,
1028 pycompat.sysbytes(traceback.format_exc()))
1038 pycompat.sysbytes(traceback.format_exc()))
1029 ui.warn(warning)
1039 ui.warn(warning)
1030 return False # re-raise the exception
1040 return False # re-raise the exception
@@ -1,689 +1,689 b''
1 # help.py - help data for mercurial
1 # help.py - help data for mercurial
2 #
2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 Matt Mackall <mpm@selenic.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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import itertools
10 import itertools
11 import os
11 import os
12 import textwrap
12 import textwrap
13
13
14 from .i18n import (
14 from .i18n import (
15 _,
15 _,
16 gettext,
16 gettext,
17 )
17 )
18 from . import (
18 from . import (
19 cmdutil,
19 cmdutil,
20 encoding,
20 encoding,
21 error,
21 error,
22 extensions,
22 extensions,
23 fancyopts,
23 fancyopts,
24 filemerge,
24 filemerge,
25 fileset,
25 fileset,
26 minirst,
26 minirst,
27 pycompat,
27 pycompat,
28 revset,
28 revset,
29 templatefilters,
29 templatefilters,
30 templatefuncs,
30 templatefuncs,
31 templatekw,
31 templatekw,
32 util,
32 util,
33 )
33 )
34 from .hgweb import (
34 from .hgweb import (
35 webcommands,
35 webcommands,
36 )
36 )
37
37
38 _exclkeywords = {
38 _exclkeywords = {
39 "(ADVANCED)",
39 "(ADVANCED)",
40 "(DEPRECATED)",
40 "(DEPRECATED)",
41 "(EXPERIMENTAL)",
41 "(EXPERIMENTAL)",
42 # i18n: "(ADVANCED)" is a keyword, must be translated consistently
42 # i18n: "(ADVANCED)" is a keyword, must be translated consistently
43 _("(ADVANCED)"),
43 _("(ADVANCED)"),
44 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
44 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
45 _("(DEPRECATED)"),
45 _("(DEPRECATED)"),
46 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
46 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
47 _("(EXPERIMENTAL)"),
47 _("(EXPERIMENTAL)"),
48 }
48 }
49
49
50 def listexts(header, exts, indent=1, showdeprecated=False):
50 def listexts(header, exts, indent=1, showdeprecated=False):
51 '''return a text listing of the given extensions'''
51 '''return a text listing of the given extensions'''
52 rst = []
52 rst = []
53 if exts:
53 if exts:
54 for name, desc in sorted(exts.iteritems()):
54 for name, desc in sorted(exts.iteritems()):
55 if not showdeprecated and any(w in desc for w in _exclkeywords):
55 if not showdeprecated and any(w in desc for w in _exclkeywords):
56 continue
56 continue
57 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
57 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
58 if rst:
58 if rst:
59 rst.insert(0, '\n%s\n\n' % header)
59 rst.insert(0, '\n%s\n\n' % header)
60 return rst
60 return rst
61
61
62 def extshelp(ui):
62 def extshelp(ui):
63 rst = loaddoc('extensions')(ui).splitlines(True)
63 rst = loaddoc('extensions')(ui).splitlines(True)
64 rst.extend(listexts(
64 rst.extend(listexts(
65 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
65 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
66 rst.extend(listexts(_('disabled extensions:'), extensions.disabled(),
66 rst.extend(listexts(_('disabled extensions:'), extensions.disabled(),
67 showdeprecated=ui.verbose))
67 showdeprecated=ui.verbose))
68 doc = ''.join(rst)
68 doc = ''.join(rst)
69 return doc
69 return doc
70
70
71 def optrst(header, options, verbose):
71 def optrst(header, options, verbose):
72 data = []
72 data = []
73 multioccur = False
73 multioccur = False
74 for option in options:
74 for option in options:
75 if len(option) == 5:
75 if len(option) == 5:
76 shortopt, longopt, default, desc, optlabel = option
76 shortopt, longopt, default, desc, optlabel = option
77 else:
77 else:
78 shortopt, longopt, default, desc = option
78 shortopt, longopt, default, desc = option
79 optlabel = _("VALUE") # default label
79 optlabel = _("VALUE") # default label
80
80
81 if not verbose and any(w in desc for w in _exclkeywords):
81 if not verbose and any(w in desc for w in _exclkeywords):
82 continue
82 continue
83
83
84 so = ''
84 so = ''
85 if shortopt:
85 if shortopt:
86 so = '-' + shortopt
86 so = '-' + shortopt
87 lo = '--' + longopt
87 lo = '--' + longopt
88
88
89 if isinstance(default, fancyopts.customopt):
89 if isinstance(default, fancyopts.customopt):
90 default = default.getdefaultvalue()
90 default = default.getdefaultvalue()
91 if default and not callable(default):
91 if default and not callable(default):
92 # default is of unknown type, and in Python 2 we abused
92 # default is of unknown type, and in Python 2 we abused
93 # the %s-shows-repr property to handle integers etc. To
93 # the %s-shows-repr property to handle integers etc. To
94 # match that behavior on Python 3, we do str(default) and
94 # match that behavior on Python 3, we do str(default) and
95 # then convert it to bytes.
95 # then convert it to bytes.
96 desc += _(" (default: %s)") % pycompat.bytestr(default)
96 desc += _(" (default: %s)") % pycompat.bytestr(default)
97
97
98 if isinstance(default, list):
98 if isinstance(default, list):
99 lo += " %s [+]" % optlabel
99 lo += " %s [+]" % optlabel
100 multioccur = True
100 multioccur = True
101 elif (default is not None) and not isinstance(default, bool):
101 elif (default is not None) and not isinstance(default, bool):
102 lo += " %s" % optlabel
102 lo += " %s" % optlabel
103
103
104 data.append((so, lo, desc))
104 data.append((so, lo, desc))
105
105
106 if multioccur:
106 if multioccur:
107 header += (_(" ([+] can be repeated)"))
107 header += (_(" ([+] can be repeated)"))
108
108
109 rst = ['\n%s:\n\n' % header]
109 rst = ['\n%s:\n\n' % header]
110 rst.extend(minirst.maketable(data, 1))
110 rst.extend(minirst.maketable(data, 1))
111
111
112 return ''.join(rst)
112 return ''.join(rst)
113
113
114 def indicateomitted(rst, omitted, notomitted=None):
114 def indicateomitted(rst, omitted, notomitted=None):
115 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
115 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
116 if notomitted:
116 if notomitted:
117 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
117 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
118
118
119 def filtercmd(ui, cmd, kw, doc):
119 def filtercmd(ui, cmd, kw, doc):
120 if not ui.debugflag and cmd.startswith("debug") and kw != "debug":
120 if not ui.debugflag and cmd.startswith("debug") and kw != "debug":
121 return True
121 return True
122 if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
122 if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
123 return True
123 return True
124 return False
124 return False
125
125
126 def topicmatch(ui, commands, kw):
126 def topicmatch(ui, commands, kw):
127 """Return help topics matching kw.
127 """Return help topics matching kw.
128
128
129 Returns {'section': [(name, summary), ...], ...} where section is
129 Returns {'section': [(name, summary), ...], ...} where section is
130 one of topics, commands, extensions, or extensioncommands.
130 one of topics, commands, extensions, or extensioncommands.
131 """
131 """
132 kw = encoding.lower(kw)
132 kw = encoding.lower(kw)
133 def lowercontains(container):
133 def lowercontains(container):
134 return kw in encoding.lower(container) # translated in helptable
134 return kw in encoding.lower(container) # translated in helptable
135 results = {'topics': [],
135 results = {'topics': [],
136 'commands': [],
136 'commands': [],
137 'extensions': [],
137 'extensions': [],
138 'extensioncommands': [],
138 'extensioncommands': [],
139 }
139 }
140 for names, header, doc in helptable:
140 for names, header, doc in helptable:
141 # Old extensions may use a str as doc.
141 # Old extensions may use a str as doc.
142 if (sum(map(lowercontains, names))
142 if (sum(map(lowercontains, names))
143 or lowercontains(header)
143 or lowercontains(header)
144 or (callable(doc) and lowercontains(doc(ui)))):
144 or (callable(doc) and lowercontains(doc(ui)))):
145 results['topics'].append((names[0], header))
145 results['topics'].append((names[0], header))
146 for cmd, entry in commands.table.iteritems():
146 for cmd, entry in commands.table.iteritems():
147 if len(entry) == 3:
147 if len(entry) == 3:
148 summary = entry[2]
148 summary = entry[2]
149 else:
149 else:
150 summary = ''
150 summary = ''
151 # translate docs *before* searching there
151 # translate docs *before* searching there
152 docs = _(pycompat.getdoc(entry[0])) or ''
152 docs = _(pycompat.getdoc(entry[0])) or ''
153 if kw in cmd or lowercontains(summary) or lowercontains(docs):
153 if kw in cmd or lowercontains(summary) or lowercontains(docs):
154 doclines = docs.splitlines()
154 doclines = docs.splitlines()
155 if doclines:
155 if doclines:
156 summary = doclines[0]
156 summary = doclines[0]
157 cmdname = cmdutil.parsealiases(cmd)[0]
157 cmdname = cmdutil.parsealiases(cmd)[0]
158 if filtercmd(ui, cmdname, kw, docs):
158 if filtercmd(ui, cmdname, kw, docs):
159 continue
159 continue
160 results['commands'].append((cmdname, summary))
160 results['commands'].append((cmdname, summary))
161 for name, docs in itertools.chain(
161 for name, docs in itertools.chain(
162 extensions.enabled(False).iteritems(),
162 extensions.enabled(False).iteritems(),
163 extensions.disabled().iteritems()):
163 extensions.disabled().iteritems()):
164 if not docs:
164 if not docs:
165 continue
165 continue
166 name = name.rpartition('.')[-1]
166 name = name.rpartition('.')[-1]
167 if lowercontains(name) or lowercontains(docs):
167 if lowercontains(name) or lowercontains(docs):
168 # extension docs are already translated
168 # extension docs are already translated
169 results['extensions'].append((name, docs.splitlines()[0]))
169 results['extensions'].append((name, docs.splitlines()[0]))
170 try:
170 try:
171 mod = extensions.load(ui, name, '')
171 mod = extensions.load(ui, name, '')
172 except ImportError:
172 except ImportError:
173 # debug message would be printed in extensions.load()
173 # debug message would be printed in extensions.load()
174 continue
174 continue
175 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
175 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
176 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
176 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
177 cmdname = cmdutil.parsealiases(cmd)[0]
177 cmdname = cmdutil.parsealiases(cmd)[0]
178 cmddoc = pycompat.getdoc(entry[0])
178 cmddoc = pycompat.getdoc(entry[0])
179 if cmddoc:
179 if cmddoc:
180 cmddoc = gettext(cmddoc).splitlines()[0]
180 cmddoc = gettext(cmddoc).splitlines()[0]
181 else:
181 else:
182 cmddoc = _('(no help text available)')
182 cmddoc = _('(no help text available)')
183 if filtercmd(ui, cmdname, kw, cmddoc):
183 if filtercmd(ui, cmdname, kw, cmddoc):
184 continue
184 continue
185 results['extensioncommands'].append((cmdname, cmddoc))
185 results['extensioncommands'].append((cmdname, cmddoc))
186 return results
186 return results
187
187
188 def loaddoc(topic, subdir=None):
188 def loaddoc(topic, subdir=None):
189 """Return a delayed loader for help/topic.txt."""
189 """Return a delayed loader for help/topic.txt."""
190
190
191 def loader(ui):
191 def loader(ui):
192 docdir = os.path.join(util.datapath, 'help')
192 docdir = os.path.join(util.datapath, 'help')
193 if subdir:
193 if subdir:
194 docdir = os.path.join(docdir, subdir)
194 docdir = os.path.join(docdir, subdir)
195 path = os.path.join(docdir, topic + ".txt")
195 path = os.path.join(docdir, topic + ".txt")
196 doc = gettext(util.readfile(path))
196 doc = gettext(util.readfile(path))
197 for rewriter in helphooks.get(topic, []):
197 for rewriter in helphooks.get(topic, []):
198 doc = rewriter(ui, topic, doc)
198 doc = rewriter(ui, topic, doc)
199 return doc
199 return doc
200
200
201 return loader
201 return loader
202
202
203 internalstable = sorted([
203 internalstable = sorted([
204 (['bundle2'], _('Bundle2'),
204 (['bundle2'], _('Bundle2'),
205 loaddoc('bundle2', subdir='internals')),
205 loaddoc('bundle2', subdir='internals')),
206 (['bundles'], _('Bundles'),
206 (['bundles'], _('Bundles'),
207 loaddoc('bundles', subdir='internals')),
207 loaddoc('bundles', subdir='internals')),
208 (['censor'], _('Censor'),
208 (['censor'], _('Censor'),
209 loaddoc('censor', subdir='internals')),
209 loaddoc('censor', subdir='internals')),
210 (['changegroups'], _('Changegroups'),
210 (['changegroups'], _('Changegroups'),
211 loaddoc('changegroups', subdir='internals')),
211 loaddoc('changegroups', subdir='internals')),
212 (['config'], _('Config Registrar'),
212 (['config'], _('Config Registrar'),
213 loaddoc('config', subdir='internals')),
213 loaddoc('config', subdir='internals')),
214 (['requirements'], _('Repository Requirements'),
214 (['requirements'], _('Repository Requirements'),
215 loaddoc('requirements', subdir='internals')),
215 loaddoc('requirements', subdir='internals')),
216 (['revlogs'], _('Revision Logs'),
216 (['revlogs'], _('Revision Logs'),
217 loaddoc('revlogs', subdir='internals')),
217 loaddoc('revlogs', subdir='internals')),
218 (['wireprotocol'], _('Wire Protocol'),
218 (['wireprotocol'], _('Wire Protocol'),
219 loaddoc('wireprotocol', subdir='internals')),
219 loaddoc('wireprotocol', subdir='internals')),
220 ])
220 ])
221
221
222 def internalshelp(ui):
222 def internalshelp(ui):
223 """Generate the index for the "internals" topic."""
223 """Generate the index for the "internals" topic."""
224 lines = ['To access a subtopic, use "hg help internals.{subtopic-name}"\n',
224 lines = ['To access a subtopic, use "hg help internals.{subtopic-name}"\n',
225 '\n']
225 '\n']
226 for names, header, doc in internalstable:
226 for names, header, doc in internalstable:
227 lines.append(' :%s: %s\n' % (names[0], header))
227 lines.append(' :%s: %s\n' % (names[0], header))
228
228
229 return ''.join(lines)
229 return ''.join(lines)
230
230
231 helptable = sorted([
231 helptable = sorted([
232 (['bundlespec'], _("Bundle File Formats"), loaddoc('bundlespec')),
232 (['bundlespec'], _("Bundle File Formats"), loaddoc('bundlespec')),
233 (['color'], _("Colorizing Outputs"), loaddoc('color')),
233 (['color'], _("Colorizing Outputs"), loaddoc('color')),
234 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
234 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
235 (["dates"], _("Date Formats"), loaddoc('dates')),
235 (["dates"], _("Date Formats"), loaddoc('dates')),
236 (["flags"], _("Command-line flags"), loaddoc('flags')),
236 (["flags"], _("Command-line flags"), loaddoc('flags')),
237 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
237 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
238 (['environment', 'env'], _('Environment Variables'),
238 (['environment', 'env'], _('Environment Variables'),
239 loaddoc('environment')),
239 loaddoc('environment')),
240 (['revisions', 'revs', 'revsets', 'revset', 'multirevs', 'mrevs'],
240 (['revisions', 'revs', 'revsets', 'revset', 'multirevs', 'mrevs'],
241 _('Specifying Revisions'), loaddoc('revisions')),
241 _('Specifying Revisions'), loaddoc('revisions')),
242 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
242 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
243 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
243 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
244 (['merge-tools', 'mergetools', 'mergetool'], _('Merge Tools'),
244 (['merge-tools', 'mergetools', 'mergetool'], _('Merge Tools'),
245 loaddoc('merge-tools')),
245 loaddoc('merge-tools')),
246 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
246 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
247 loaddoc('templates')),
247 loaddoc('templates')),
248 (['urls'], _('URL Paths'), loaddoc('urls')),
248 (['urls'], _('URL Paths'), loaddoc('urls')),
249 (["extensions"], _("Using Additional Features"), extshelp),
249 (["extensions"], _("Using Additional Features"), extshelp),
250 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
250 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
251 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
251 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
252 (["glossary"], _("Glossary"), loaddoc('glossary')),
252 (["glossary"], _("Glossary"), loaddoc('glossary')),
253 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
253 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
254 loaddoc('hgignore')),
254 loaddoc('hgignore')),
255 (["phases"], _("Working with Phases"), loaddoc('phases')),
255 (["phases"], _("Working with Phases"), loaddoc('phases')),
256 (['scripting'], _('Using Mercurial from scripts and automation'),
256 (['scripting'], _('Using Mercurial from scripts and automation'),
257 loaddoc('scripting')),
257 loaddoc('scripting')),
258 (['internals'], _("Technical implementation topics"),
258 (['internals'], _("Technical implementation topics"),
259 internalshelp),
259 internalshelp),
260 (['pager'], _("Pager Support"), loaddoc('pager')),
260 (['pager'], _("Pager Support"), loaddoc('pager')),
261 ])
261 ])
262
262
263 # Maps topics with sub-topics to a list of their sub-topics.
263 # Maps topics with sub-topics to a list of their sub-topics.
264 subtopics = {
264 subtopics = {
265 'internals': internalstable,
265 'internals': internalstable,
266 }
266 }
267
267
268 # Map topics to lists of callable taking the current topic help and
268 # Map topics to lists of callable taking the current topic help and
269 # returning the updated version
269 # returning the updated version
270 helphooks = {}
270 helphooks = {}
271
271
272 def addtopichook(topic, rewriter):
272 def addtopichook(topic, rewriter):
273 helphooks.setdefault(topic, []).append(rewriter)
273 helphooks.setdefault(topic, []).append(rewriter)
274
274
275 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
275 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
276 """Extract docstring from the items key to function mapping, build a
276 """Extract docstring from the items key to function mapping, build a
277 single documentation block and use it to overwrite the marker in doc.
277 single documentation block and use it to overwrite the marker in doc.
278 """
278 """
279 entries = []
279 entries = []
280 for name in sorted(items):
280 for name in sorted(items):
281 text = (pycompat.getdoc(items[name]) or '').rstrip()
281 text = (pycompat.getdoc(items[name]) or '').rstrip()
282 if (not text
282 if (not text
283 or not ui.verbose and any(w in text for w in _exclkeywords)):
283 or not ui.verbose and any(w in text for w in _exclkeywords)):
284 continue
284 continue
285 text = gettext(text)
285 text = gettext(text)
286 if dedent:
286 if dedent:
287 # Abuse latin1 to use textwrap.dedent() on bytes.
287 # Abuse latin1 to use textwrap.dedent() on bytes.
288 text = textwrap.dedent(text.decode('latin1')).encode('latin1')
288 text = textwrap.dedent(text.decode('latin1')).encode('latin1')
289 lines = text.splitlines()
289 lines = text.splitlines()
290 doclines = [(lines[0])]
290 doclines = [(lines[0])]
291 for l in lines[1:]:
291 for l in lines[1:]:
292 # Stop once we find some Python doctest
292 # Stop once we find some Python doctest
293 if l.strip().startswith('>>>'):
293 if l.strip().startswith('>>>'):
294 break
294 break
295 if dedent:
295 if dedent:
296 doclines.append(l.rstrip())
296 doclines.append(l.rstrip())
297 else:
297 else:
298 doclines.append(' ' + l.strip())
298 doclines.append(' ' + l.strip())
299 entries.append('\n'.join(doclines))
299 entries.append('\n'.join(doclines))
300 entries = '\n\n'.join(entries)
300 entries = '\n\n'.join(entries)
301 return doc.replace(marker, entries)
301 return doc.replace(marker, entries)
302
302
303 def addtopicsymbols(topic, marker, symbols, dedent=False):
303 def addtopicsymbols(topic, marker, symbols, dedent=False):
304 def add(ui, topic, doc):
304 def add(ui, topic, doc):
305 return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
305 return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
306 addtopichook(topic, add)
306 addtopichook(topic, add)
307
307
308 addtopicsymbols('bundlespec', '.. bundlecompressionmarker',
308 addtopicsymbols('bundlespec', '.. bundlecompressionmarker',
309 util.bundlecompressiontopics())
309 util.bundlecompressiontopics())
310 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
310 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
311 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
311 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
312 filemerge.internalsdoc)
312 filemerge.internalsdoc)
313 addtopicsymbols('revisions', '.. predicatesmarker', revset.symbols)
313 addtopicsymbols('revisions', '.. predicatesmarker', revset.symbols)
314 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
314 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
315 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
315 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
316 addtopicsymbols('templates', '.. functionsmarker', templatefuncs.funcs)
316 addtopicsymbols('templates', '.. functionsmarker', templatefuncs.funcs)
317 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
317 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
318 dedent=True)
318 dedent=True)
319
319
320 def help_(ui, commands, name, unknowncmd=False, full=True, subtopic=None,
320 def help_(ui, commands, name, unknowncmd=False, full=True, subtopic=None,
321 **opts):
321 **opts):
322 '''
322 '''
323 Generate the help for 'name' as unformatted restructured text. If
323 Generate the help for 'name' as unformatted restructured text. If
324 'name' is None, describe the commands available.
324 'name' is None, describe the commands available.
325 '''
325 '''
326
326
327 opts = pycompat.byteskwargs(opts)
327 opts = pycompat.byteskwargs(opts)
328
328
329 def helpcmd(name, subtopic=None):
329 def helpcmd(name, subtopic=None):
330 try:
330 try:
331 aliases, entry = cmdutil.findcmd(name, commands.table,
331 aliases, entry = cmdutil.findcmd(name, commands.table,
332 strict=unknowncmd)
332 strict=unknowncmd)
333 except error.AmbiguousCommand as inst:
333 except error.AmbiguousCommand as inst:
334 # py3k fix: except vars can't be used outside the scope of the
334 # py3k fix: except vars can't be used outside the scope of the
335 # except block, nor can be used inside a lambda. python issue4617
335 # except block, nor can be used inside a lambda. python issue4617
336 prefix = inst.args[0]
336 prefix = inst.args[0]
337 select = lambda c: cmdutil.parsealiases(c)[0].startswith(prefix)
337 select = lambda c: cmdutil.parsealiases(c)[0].startswith(prefix)
338 rst = helplist(select)
338 rst = helplist(select)
339 return rst
339 return rst
340
340
341 rst = []
341 rst = []
342
342
343 # check if it's an invalid alias and display its error if it is
343 # check if it's an invalid alias and display its error if it is
344 if getattr(entry[0], 'badalias', None):
344 if getattr(entry[0], 'badalias', None):
345 rst.append(entry[0].badalias + '\n')
345 rst.append(entry[0].badalias + '\n')
346 if entry[0].unknowncmd:
346 if entry[0].unknowncmd:
347 try:
347 try:
348 rst.extend(helpextcmd(entry[0].cmdname))
348 rst.extend(helpextcmd(entry[0].cmdname))
349 except error.UnknownCommand:
349 except error.UnknownCommand:
350 pass
350 pass
351 return rst
351 return rst
352
352
353 # synopsis
353 # synopsis
354 if len(entry) > 2:
354 if len(entry) > 2:
355 if entry[2].startswith('hg'):
355 if entry[2].startswith('hg'):
356 rst.append("%s\n" % entry[2])
356 rst.append("%s\n" % entry[2])
357 else:
357 else:
358 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
358 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
359 else:
359 else:
360 rst.append('hg %s\n' % aliases[0])
360 rst.append('hg %s\n' % aliases[0])
361 # aliases
361 # aliases
362 if full and not ui.quiet and len(aliases) > 1:
362 if full and not ui.quiet and len(aliases) > 1:
363 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
363 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
364 rst.append('\n')
364 rst.append('\n')
365
365
366 # description
366 # description
367 doc = gettext(pycompat.getdoc(entry[0]))
367 doc = gettext(pycompat.getdoc(entry[0]))
368 if not doc:
368 if not doc:
369 doc = _("(no help text available)")
369 doc = _("(no help text available)")
370 if util.safehasattr(entry[0], 'definition'): # aliased command
370 if util.safehasattr(entry[0], 'definition'): # aliased command
371 source = entry[0].source
371 source = entry[0].source
372 if entry[0].definition.startswith('!'): # shell alias
372 if entry[0].definition.startswith('!'): # shell alias
373 doc = (_('shell alias for::\n\n %s\n\ndefined by: %s\n') %
373 doc = (_('shell alias for: %s\n\n%s\n\ndefined by: %s\n') %
374 (entry[0].definition[1:], source))
374 (entry[0].definition[1:], doc, source))
375 else:
375 else:
376 doc = (_('alias for: hg %s\n\n%s\n\ndefined by: %s\n') %
376 doc = (_('alias for: hg %s\n\n%s\n\ndefined by: %s\n') %
377 (entry[0].definition, doc, source))
377 (entry[0].definition, doc, source))
378 doc = doc.splitlines(True)
378 doc = doc.splitlines(True)
379 if ui.quiet or not full:
379 if ui.quiet or not full:
380 rst.append(doc[0])
380 rst.append(doc[0])
381 else:
381 else:
382 rst.extend(doc)
382 rst.extend(doc)
383 rst.append('\n')
383 rst.append('\n')
384
384
385 # check if this command shadows a non-trivial (multi-line)
385 # check if this command shadows a non-trivial (multi-line)
386 # extension help text
386 # extension help text
387 try:
387 try:
388 mod = extensions.find(name)
388 mod = extensions.find(name)
389 doc = gettext(pycompat.getdoc(mod)) or ''
389 doc = gettext(pycompat.getdoc(mod)) or ''
390 if '\n' in doc.strip():
390 if '\n' in doc.strip():
391 msg = _("(use 'hg help -e %s' to show help for "
391 msg = _("(use 'hg help -e %s' to show help for "
392 "the %s extension)") % (name, name)
392 "the %s extension)") % (name, name)
393 rst.append('\n%s\n' % msg)
393 rst.append('\n%s\n' % msg)
394 except KeyError:
394 except KeyError:
395 pass
395 pass
396
396
397 # options
397 # options
398 if not ui.quiet and entry[1]:
398 if not ui.quiet and entry[1]:
399 rst.append(optrst(_("options"), entry[1], ui.verbose))
399 rst.append(optrst(_("options"), entry[1], ui.verbose))
400
400
401 if ui.verbose:
401 if ui.verbose:
402 rst.append(optrst(_("global options"),
402 rst.append(optrst(_("global options"),
403 commands.globalopts, ui.verbose))
403 commands.globalopts, ui.verbose))
404
404
405 if not ui.verbose:
405 if not ui.verbose:
406 if not full:
406 if not full:
407 rst.append(_("\n(use 'hg %s -h' to show more help)\n")
407 rst.append(_("\n(use 'hg %s -h' to show more help)\n")
408 % name)
408 % name)
409 elif not ui.quiet:
409 elif not ui.quiet:
410 rst.append(_('\n(some details hidden, use --verbose '
410 rst.append(_('\n(some details hidden, use --verbose '
411 'to show complete help)'))
411 'to show complete help)'))
412
412
413 return rst
413 return rst
414
414
415
415
416 def helplist(select=None, **opts):
416 def helplist(select=None, **opts):
417 # list of commands
417 # list of commands
418 if name == "shortlist":
418 if name == "shortlist":
419 header = _('basic commands:\n\n')
419 header = _('basic commands:\n\n')
420 elif name == "debug":
420 elif name == "debug":
421 header = _('debug commands (internal and unsupported):\n\n')
421 header = _('debug commands (internal and unsupported):\n\n')
422 else:
422 else:
423 header = _('list of commands:\n\n')
423 header = _('list of commands:\n\n')
424
424
425 h = {}
425 h = {}
426 cmds = {}
426 cmds = {}
427 for c, e in commands.table.iteritems():
427 for c, e in commands.table.iteritems():
428 fs = cmdutil.parsealiases(c)
428 fs = cmdutil.parsealiases(c)
429 f = fs[0]
429 f = fs[0]
430 p = ''
430 p = ''
431 if c.startswith("^"):
431 if c.startswith("^"):
432 p = '^'
432 p = '^'
433 if select and not select(p + f):
433 if select and not select(p + f):
434 continue
434 continue
435 if (not select and name != 'shortlist' and
435 if (not select and name != 'shortlist' and
436 e[0].__module__ != commands.__name__):
436 e[0].__module__ != commands.__name__):
437 continue
437 continue
438 if name == "shortlist" and not p:
438 if name == "shortlist" and not p:
439 continue
439 continue
440 doc = pycompat.getdoc(e[0])
440 doc = pycompat.getdoc(e[0])
441 if filtercmd(ui, f, name, doc):
441 if filtercmd(ui, f, name, doc):
442 continue
442 continue
443 doc = gettext(doc)
443 doc = gettext(doc)
444 if not doc:
444 if not doc:
445 doc = _("(no help text available)")
445 doc = _("(no help text available)")
446 h[f] = doc.splitlines()[0].rstrip()
446 h[f] = doc.splitlines()[0].rstrip()
447 cmds[f] = '|'.join(fs)
447 cmds[f] = '|'.join(fs)
448
448
449 rst = []
449 rst = []
450 if not h:
450 if not h:
451 if not ui.quiet:
451 if not ui.quiet:
452 rst.append(_('no commands defined\n'))
452 rst.append(_('no commands defined\n'))
453 return rst
453 return rst
454
454
455 if not ui.quiet:
455 if not ui.quiet:
456 rst.append(header)
456 rst.append(header)
457 fns = sorted(h)
457 fns = sorted(h)
458 for f in fns:
458 for f in fns:
459 if ui.verbose:
459 if ui.verbose:
460 commacmds = cmds[f].replace("|",", ")
460 commacmds = cmds[f].replace("|",", ")
461 rst.append(" :%s: %s\n" % (commacmds, h[f]))
461 rst.append(" :%s: %s\n" % (commacmds, h[f]))
462 else:
462 else:
463 rst.append(' :%s: %s\n' % (f, h[f]))
463 rst.append(' :%s: %s\n' % (f, h[f]))
464
464
465 ex = opts.get
465 ex = opts.get
466 anyopts = (ex(r'keyword') or not (ex(r'command') or ex(r'extension')))
466 anyopts = (ex(r'keyword') or not (ex(r'command') or ex(r'extension')))
467 if not name and anyopts:
467 if not name and anyopts:
468 exts = listexts(_('enabled extensions:'), extensions.enabled())
468 exts = listexts(_('enabled extensions:'), extensions.enabled())
469 if exts:
469 if exts:
470 rst.append('\n')
470 rst.append('\n')
471 rst.extend(exts)
471 rst.extend(exts)
472
472
473 rst.append(_("\nadditional help topics:\n\n"))
473 rst.append(_("\nadditional help topics:\n\n"))
474 topics = []
474 topics = []
475 for names, header, doc in helptable:
475 for names, header, doc in helptable:
476 topics.append((names[0], header))
476 topics.append((names[0], header))
477 for t, desc in topics:
477 for t, desc in topics:
478 rst.append(" :%s: %s\n" % (t, desc))
478 rst.append(" :%s: %s\n" % (t, desc))
479
479
480 if ui.quiet:
480 if ui.quiet:
481 pass
481 pass
482 elif ui.verbose:
482 elif ui.verbose:
483 rst.append('\n%s\n' % optrst(_("global options"),
483 rst.append('\n%s\n' % optrst(_("global options"),
484 commands.globalopts, ui.verbose))
484 commands.globalopts, ui.verbose))
485 if name == 'shortlist':
485 if name == 'shortlist':
486 rst.append(_("\n(use 'hg help' for the full list "
486 rst.append(_("\n(use 'hg help' for the full list "
487 "of commands)\n"))
487 "of commands)\n"))
488 else:
488 else:
489 if name == 'shortlist':
489 if name == 'shortlist':
490 rst.append(_("\n(use 'hg help' for the full list of commands "
490 rst.append(_("\n(use 'hg help' for the full list of commands "
491 "or 'hg -v' for details)\n"))
491 "or 'hg -v' for details)\n"))
492 elif name and not full:
492 elif name and not full:
493 rst.append(_("\n(use 'hg help %s' to show the full help "
493 rst.append(_("\n(use 'hg help %s' to show the full help "
494 "text)\n") % name)
494 "text)\n") % name)
495 elif name and cmds and name in cmds.keys():
495 elif name and cmds and name in cmds.keys():
496 rst.append(_("\n(use 'hg help -v -e %s' to show built-in "
496 rst.append(_("\n(use 'hg help -v -e %s' to show built-in "
497 "aliases and global options)\n") % name)
497 "aliases and global options)\n") % name)
498 else:
498 else:
499 rst.append(_("\n(use 'hg help -v%s' to show built-in aliases "
499 rst.append(_("\n(use 'hg help -v%s' to show built-in aliases "
500 "and global options)\n")
500 "and global options)\n")
501 % (name and " " + name or ""))
501 % (name and " " + name or ""))
502 return rst
502 return rst
503
503
504 def helptopic(name, subtopic=None):
504 def helptopic(name, subtopic=None):
505 # Look for sub-topic entry first.
505 # Look for sub-topic entry first.
506 header, doc = None, None
506 header, doc = None, None
507 if subtopic and name in subtopics:
507 if subtopic and name in subtopics:
508 for names, header, doc in subtopics[name]:
508 for names, header, doc in subtopics[name]:
509 if subtopic in names:
509 if subtopic in names:
510 break
510 break
511
511
512 if not header:
512 if not header:
513 for names, header, doc in helptable:
513 for names, header, doc in helptable:
514 if name in names:
514 if name in names:
515 break
515 break
516 else:
516 else:
517 raise error.UnknownCommand(name)
517 raise error.UnknownCommand(name)
518
518
519 rst = [minirst.section(header)]
519 rst = [minirst.section(header)]
520
520
521 # description
521 # description
522 if not doc:
522 if not doc:
523 rst.append(" %s\n" % _("(no help text available)"))
523 rst.append(" %s\n" % _("(no help text available)"))
524 if callable(doc):
524 if callable(doc):
525 rst += [" %s\n" % l for l in doc(ui).splitlines()]
525 rst += [" %s\n" % l for l in doc(ui).splitlines()]
526
526
527 if not ui.verbose:
527 if not ui.verbose:
528 omitted = _('(some details hidden, use --verbose'
528 omitted = _('(some details hidden, use --verbose'
529 ' to show complete help)')
529 ' to show complete help)')
530 indicateomitted(rst, omitted)
530 indicateomitted(rst, omitted)
531
531
532 try:
532 try:
533 cmdutil.findcmd(name, commands.table)
533 cmdutil.findcmd(name, commands.table)
534 rst.append(_("\nuse 'hg help -c %s' to see help for "
534 rst.append(_("\nuse 'hg help -c %s' to see help for "
535 "the %s command\n") % (name, name))
535 "the %s command\n") % (name, name))
536 except error.UnknownCommand:
536 except error.UnknownCommand:
537 pass
537 pass
538 return rst
538 return rst
539
539
540 def helpext(name, subtopic=None):
540 def helpext(name, subtopic=None):
541 try:
541 try:
542 mod = extensions.find(name)
542 mod = extensions.find(name)
543 doc = gettext(pycompat.getdoc(mod)) or _('no help text available')
543 doc = gettext(pycompat.getdoc(mod)) or _('no help text available')
544 except KeyError:
544 except KeyError:
545 mod = None
545 mod = None
546 doc = extensions.disabledext(name)
546 doc = extensions.disabledext(name)
547 if not doc:
547 if not doc:
548 raise error.UnknownCommand(name)
548 raise error.UnknownCommand(name)
549
549
550 if '\n' not in doc:
550 if '\n' not in doc:
551 head, tail = doc, ""
551 head, tail = doc, ""
552 else:
552 else:
553 head, tail = doc.split('\n', 1)
553 head, tail = doc.split('\n', 1)
554 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
554 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
555 if tail:
555 if tail:
556 rst.extend(tail.splitlines(True))
556 rst.extend(tail.splitlines(True))
557 rst.append('\n')
557 rst.append('\n')
558
558
559 if not ui.verbose:
559 if not ui.verbose:
560 omitted = _('(some details hidden, use --verbose'
560 omitted = _('(some details hidden, use --verbose'
561 ' to show complete help)')
561 ' to show complete help)')
562 indicateomitted(rst, omitted)
562 indicateomitted(rst, omitted)
563
563
564 if mod:
564 if mod:
565 try:
565 try:
566 ct = mod.cmdtable
566 ct = mod.cmdtable
567 except AttributeError:
567 except AttributeError:
568 ct = {}
568 ct = {}
569 modcmds = set([c.partition('|')[0] for c in ct])
569 modcmds = set([c.partition('|')[0] for c in ct])
570 rst.extend(helplist(modcmds.__contains__))
570 rst.extend(helplist(modcmds.__contains__))
571 else:
571 else:
572 rst.append(_("(use 'hg help extensions' for information on enabling"
572 rst.append(_("(use 'hg help extensions' for information on enabling"
573 " extensions)\n"))
573 " extensions)\n"))
574 return rst
574 return rst
575
575
576 def helpextcmd(name, subtopic=None):
576 def helpextcmd(name, subtopic=None):
577 cmd, ext, mod = extensions.disabledcmd(ui, name,
577 cmd, ext, mod = extensions.disabledcmd(ui, name,
578 ui.configbool('ui', 'strict'))
578 ui.configbool('ui', 'strict'))
579 doc = gettext(pycompat.getdoc(mod)).splitlines()[0]
579 doc = gettext(pycompat.getdoc(mod)).splitlines()[0]
580
580
581 rst = listexts(_("'%s' is provided by the following "
581 rst = listexts(_("'%s' is provided by the following "
582 "extension:") % cmd, {ext: doc}, indent=4,
582 "extension:") % cmd, {ext: doc}, indent=4,
583 showdeprecated=True)
583 showdeprecated=True)
584 rst.append('\n')
584 rst.append('\n')
585 rst.append(_("(use 'hg help extensions' for information on enabling "
585 rst.append(_("(use 'hg help extensions' for information on enabling "
586 "extensions)\n"))
586 "extensions)\n"))
587 return rst
587 return rst
588
588
589
589
590 rst = []
590 rst = []
591 kw = opts.get('keyword')
591 kw = opts.get('keyword')
592 if kw or name is None and any(opts[o] for o in opts):
592 if kw or name is None and any(opts[o] for o in opts):
593 matches = topicmatch(ui, commands, name or '')
593 matches = topicmatch(ui, commands, name or '')
594 helpareas = []
594 helpareas = []
595 if opts.get('extension'):
595 if opts.get('extension'):
596 helpareas += [('extensions', _('Extensions'))]
596 helpareas += [('extensions', _('Extensions'))]
597 if opts.get('command'):
597 if opts.get('command'):
598 helpareas += [('commands', _('Commands'))]
598 helpareas += [('commands', _('Commands'))]
599 if not helpareas:
599 if not helpareas:
600 helpareas = [('topics', _('Topics')),
600 helpareas = [('topics', _('Topics')),
601 ('commands', _('Commands')),
601 ('commands', _('Commands')),
602 ('extensions', _('Extensions')),
602 ('extensions', _('Extensions')),
603 ('extensioncommands', _('Extension Commands'))]
603 ('extensioncommands', _('Extension Commands'))]
604 for t, title in helpareas:
604 for t, title in helpareas:
605 if matches[t]:
605 if matches[t]:
606 rst.append('%s:\n\n' % title)
606 rst.append('%s:\n\n' % title)
607 rst.extend(minirst.maketable(sorted(matches[t]), 1))
607 rst.extend(minirst.maketable(sorted(matches[t]), 1))
608 rst.append('\n')
608 rst.append('\n')
609 if not rst:
609 if not rst:
610 msg = _('no matches')
610 msg = _('no matches')
611 hint = _("try 'hg help' for a list of topics")
611 hint = _("try 'hg help' for a list of topics")
612 raise error.Abort(msg, hint=hint)
612 raise error.Abort(msg, hint=hint)
613 elif name and name != 'shortlist':
613 elif name and name != 'shortlist':
614 queries = []
614 queries = []
615 if unknowncmd:
615 if unknowncmd:
616 queries += [helpextcmd]
616 queries += [helpextcmd]
617 if opts.get('extension'):
617 if opts.get('extension'):
618 queries += [helpext]
618 queries += [helpext]
619 if opts.get('command'):
619 if opts.get('command'):
620 queries += [helpcmd]
620 queries += [helpcmd]
621 if not queries:
621 if not queries:
622 queries = (helptopic, helpcmd, helpext, helpextcmd)
622 queries = (helptopic, helpcmd, helpext, helpextcmd)
623 for f in queries:
623 for f in queries:
624 try:
624 try:
625 rst = f(name, subtopic)
625 rst = f(name, subtopic)
626 break
626 break
627 except error.UnknownCommand:
627 except error.UnknownCommand:
628 pass
628 pass
629 else:
629 else:
630 if unknowncmd:
630 if unknowncmd:
631 raise error.UnknownCommand(name)
631 raise error.UnknownCommand(name)
632 else:
632 else:
633 msg = _('no such help topic: %s') % name
633 msg = _('no such help topic: %s') % name
634 hint = _("try 'hg help --keyword %s'") % name
634 hint = _("try 'hg help --keyword %s'") % name
635 raise error.Abort(msg, hint=hint)
635 raise error.Abort(msg, hint=hint)
636 else:
636 else:
637 # program name
637 # program name
638 if not ui.quiet:
638 if not ui.quiet:
639 rst = [_("Mercurial Distributed SCM\n"), '\n']
639 rst = [_("Mercurial Distributed SCM\n"), '\n']
640 rst.extend(helplist(None, **pycompat.strkwargs(opts)))
640 rst.extend(helplist(None, **pycompat.strkwargs(opts)))
641
641
642 return ''.join(rst)
642 return ''.join(rst)
643
643
644 def formattedhelp(ui, commands, name, keep=None, unknowncmd=False, full=True,
644 def formattedhelp(ui, commands, name, keep=None, unknowncmd=False, full=True,
645 **opts):
645 **opts):
646 """get help for a given topic (as a dotted name) as rendered rst
646 """get help for a given topic (as a dotted name) as rendered rst
647
647
648 Either returns the rendered help text or raises an exception.
648 Either returns the rendered help text or raises an exception.
649 """
649 """
650 if keep is None:
650 if keep is None:
651 keep = []
651 keep = []
652 else:
652 else:
653 keep = list(keep) # make a copy so we can mutate this later
653 keep = list(keep) # make a copy so we can mutate this later
654 fullname = name
654 fullname = name
655 section = None
655 section = None
656 subtopic = None
656 subtopic = None
657 if name and '.' in name:
657 if name and '.' in name:
658 name, remaining = name.split('.', 1)
658 name, remaining = name.split('.', 1)
659 remaining = encoding.lower(remaining)
659 remaining = encoding.lower(remaining)
660 if '.' in remaining:
660 if '.' in remaining:
661 subtopic, section = remaining.split('.', 1)
661 subtopic, section = remaining.split('.', 1)
662 else:
662 else:
663 if name in subtopics:
663 if name in subtopics:
664 subtopic = remaining
664 subtopic = remaining
665 else:
665 else:
666 section = remaining
666 section = remaining
667 textwidth = ui.configint('ui', 'textwidth')
667 textwidth = ui.configint('ui', 'textwidth')
668 termwidth = ui.termwidth() - 2
668 termwidth = ui.termwidth() - 2
669 if textwidth <= 0 or termwidth < textwidth:
669 if textwidth <= 0 or termwidth < textwidth:
670 textwidth = termwidth
670 textwidth = termwidth
671 text = help_(ui, commands, name,
671 text = help_(ui, commands, name,
672 subtopic=subtopic, unknowncmd=unknowncmd, full=full, **opts)
672 subtopic=subtopic, unknowncmd=unknowncmd, full=full, **opts)
673
673
674 formatted, pruned = minirst.format(text, textwidth, keep=keep,
674 formatted, pruned = minirst.format(text, textwidth, keep=keep,
675 section=section)
675 section=section)
676
676
677 # We could have been given a weird ".foo" section without a name
677 # We could have been given a weird ".foo" section without a name
678 # to look for, or we could have simply failed to found "foo.bar"
678 # to look for, or we could have simply failed to found "foo.bar"
679 # because bar isn't a section of foo
679 # because bar isn't a section of foo
680 if section and not (formatted and name):
680 if section and not (formatted and name):
681 raise error.Abort(_("help section not found: %s") % fullname)
681 raise error.Abort(_("help section not found: %s") % fullname)
682
682
683 if 'verbose' in pruned:
683 if 'verbose' in pruned:
684 keep.append('omitted')
684 keep.append('omitted')
685 else:
685 else:
686 keep.append('notomitted')
686 keep.append('notomitted')
687 formatted, pruned = minirst.format(text, textwidth, keep=keep,
687 formatted, pruned = minirst.format(text, textwidth, keep=keep,
688 section=section)
688 section=section)
689 return formatted
689 return formatted
@@ -1,1874 +1,1870 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import collections
10 import collections
11 import contextlib
11 import contextlib
12 import errno
12 import errno
13 import getpass
13 import getpass
14 import inspect
14 import inspect
15 import os
15 import os
16 import re
16 import re
17 import signal
17 import signal
18 import socket
18 import socket
19 import subprocess
19 import subprocess
20 import sys
20 import sys
21 import tempfile
21 import tempfile
22 import traceback
22 import traceback
23
23
24 from .i18n import _
24 from .i18n import _
25 from .node import hex
25 from .node import hex
26
26
27 from . import (
27 from . import (
28 color,
28 color,
29 config,
29 config,
30 configitems,
30 configitems,
31 encoding,
31 encoding,
32 error,
32 error,
33 formatter,
33 formatter,
34 progress,
34 progress,
35 pycompat,
35 pycompat,
36 rcutil,
36 rcutil,
37 scmutil,
37 scmutil,
38 util,
38 util,
39 )
39 )
40 from .utils import (
40 from .utils import (
41 dateutil,
41 dateutil,
42 procutil,
42 procutil,
43 stringutil,
43 stringutil,
44 )
44 )
45
45
46 urlreq = util.urlreq
46 urlreq = util.urlreq
47
47
48 # for use with str.translate(None, _keepalnum), to keep just alphanumerics
48 # for use with str.translate(None, _keepalnum), to keep just alphanumerics
49 _keepalnum = ''.join(c for c in map(pycompat.bytechr, range(256))
49 _keepalnum = ''.join(c for c in map(pycompat.bytechr, range(256))
50 if not c.isalnum())
50 if not c.isalnum())
51
51
52 # The config knobs that will be altered (if unset) by ui.tweakdefaults.
52 # The config knobs that will be altered (if unset) by ui.tweakdefaults.
53 tweakrc = b"""
53 tweakrc = b"""
54 [ui]
54 [ui]
55 # The rollback command is dangerous. As a rule, don't use it.
55 # The rollback command is dangerous. As a rule, don't use it.
56 rollback = False
56 rollback = False
57 # Make `hg status` report copy information
57 # Make `hg status` report copy information
58 statuscopies = yes
58 statuscopies = yes
59 # Prefer curses UIs when available. Revert to plain-text with `text`.
59 # Prefer curses UIs when available. Revert to plain-text with `text`.
60 interface = curses
60 interface = curses
61
61
62 [commands]
62 [commands]
63 # Make `hg status` emit cwd-relative paths by default.
63 # Make `hg status` emit cwd-relative paths by default.
64 status.relative = yes
64 status.relative = yes
65 # Refuse to perform an `hg update` that would cause a file content merge
65 # Refuse to perform an `hg update` that would cause a file content merge
66 update.check = noconflict
66 update.check = noconflict
67 # Show conflicts information in `hg status`
67 # Show conflicts information in `hg status`
68 status.verbose = True
68 status.verbose = True
69 # Skip the bisect state in conflicts information in `hg status`
69 # Skip the bisect state in conflicts information in `hg status`
70 status.skipstates = bisect
70 status.skipstates = bisect
71
71
72 [diff]
72 [diff]
73 git = 1
73 git = 1
74 showfunc = 1
74 showfunc = 1
75 """
75 """
76
76
77 samplehgrcs = {
77 samplehgrcs = {
78 'user':
78 'user':
79 b"""# example user config (see 'hg help config' for more info)
79 b"""# example user config (see 'hg help config' for more info)
80 [ui]
80 [ui]
81 # name and email, e.g.
81 # name and email, e.g.
82 # username = Jane Doe <jdoe@example.com>
82 # username = Jane Doe <jdoe@example.com>
83 username =
83 username =
84
84
85 # We recommend enabling tweakdefaults to get slight improvements to
85 # We recommend enabling tweakdefaults to get slight improvements to
86 # the UI over time. Make sure to set HGPLAIN in the environment when
86 # the UI over time. Make sure to set HGPLAIN in the environment when
87 # writing scripts!
87 # writing scripts!
88 # tweakdefaults = True
88 # tweakdefaults = True
89
89
90 # uncomment to disable color in command output
90 # uncomment to disable color in command output
91 # (see 'hg help color' for details)
91 # (see 'hg help color' for details)
92 # color = never
92 # color = never
93
93
94 # uncomment to disable command output pagination
94 # uncomment to disable command output pagination
95 # (see 'hg help pager' for details)
95 # (see 'hg help pager' for details)
96 # paginate = never
96 # paginate = never
97
97
98 [extensions]
98 [extensions]
99 # uncomment these lines to enable some popular extensions
99 # uncomment these lines to enable some popular extensions
100 # (see 'hg help extensions' for more info)
100 # (see 'hg help extensions' for more info)
101 #
101 #
102 # churn =
102 # churn =
103 """,
103 """,
104
104
105 'cloned':
105 'cloned':
106 b"""# example repository config (see 'hg help config' for more info)
106 b"""# example repository config (see 'hg help config' for more info)
107 [paths]
107 [paths]
108 default = %s
108 default = %s
109
109
110 # path aliases to other clones of this repo in URLs or filesystem paths
110 # path aliases to other clones of this repo in URLs or filesystem paths
111 # (see 'hg help config.paths' for more info)
111 # (see 'hg help config.paths' for more info)
112 #
112 #
113 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
113 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
114 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
114 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
115 # my-clone = /home/jdoe/jdoes-clone
115 # my-clone = /home/jdoe/jdoes-clone
116
116
117 [ui]
117 [ui]
118 # name and email (local to this repository, optional), e.g.
118 # name and email (local to this repository, optional), e.g.
119 # username = Jane Doe <jdoe@example.com>
119 # username = Jane Doe <jdoe@example.com>
120 """,
120 """,
121
121
122 'local':
122 'local':
123 b"""# example repository config (see 'hg help config' for more info)
123 b"""# example repository config (see 'hg help config' for more info)
124 [paths]
124 [paths]
125 # path aliases to other clones of this repo in URLs or filesystem paths
125 # path aliases to other clones of this repo in URLs or filesystem paths
126 # (see 'hg help config.paths' for more info)
126 # (see 'hg help config.paths' for more info)
127 #
127 #
128 # default = http://example.com/hg/example-repo
128 # default = http://example.com/hg/example-repo
129 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
129 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
130 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
130 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
131 # my-clone = /home/jdoe/jdoes-clone
131 # my-clone = /home/jdoe/jdoes-clone
132
132
133 [ui]
133 [ui]
134 # name and email (local to this repository, optional), e.g.
134 # name and email (local to this repository, optional), e.g.
135 # username = Jane Doe <jdoe@example.com>
135 # username = Jane Doe <jdoe@example.com>
136 """,
136 """,
137
137
138 'global':
138 'global':
139 b"""# example system-wide hg config (see 'hg help config' for more info)
139 b"""# example system-wide hg config (see 'hg help config' for more info)
140
140
141 [ui]
141 [ui]
142 # uncomment to disable color in command output
142 # uncomment to disable color in command output
143 # (see 'hg help color' for details)
143 # (see 'hg help color' for details)
144 # color = never
144 # color = never
145
145
146 # uncomment to disable command output pagination
146 # uncomment to disable command output pagination
147 # (see 'hg help pager' for details)
147 # (see 'hg help pager' for details)
148 # paginate = never
148 # paginate = never
149
149
150 [extensions]
150 [extensions]
151 # uncomment these lines to enable some popular extensions
151 # uncomment these lines to enable some popular extensions
152 # (see 'hg help extensions' for more info)
152 # (see 'hg help extensions' for more info)
153 #
153 #
154 # blackbox =
154 # blackbox =
155 # churn =
155 # churn =
156 """,
156 """,
157 }
157 }
158
158
159 def _maybestrurl(maybebytes):
159 def _maybestrurl(maybebytes):
160 return util.rapply(pycompat.strurl, maybebytes)
160 return util.rapply(pycompat.strurl, maybebytes)
161
161
162 def _maybebytesurl(maybestr):
162 def _maybebytesurl(maybestr):
163 return util.rapply(pycompat.bytesurl, maybestr)
163 return util.rapply(pycompat.bytesurl, maybestr)
164
164
165 class httppasswordmgrdbproxy(object):
165 class httppasswordmgrdbproxy(object):
166 """Delays loading urllib2 until it's needed."""
166 """Delays loading urllib2 until it's needed."""
167 def __init__(self):
167 def __init__(self):
168 self._mgr = None
168 self._mgr = None
169
169
170 def _get_mgr(self):
170 def _get_mgr(self):
171 if self._mgr is None:
171 if self._mgr is None:
172 self._mgr = urlreq.httppasswordmgrwithdefaultrealm()
172 self._mgr = urlreq.httppasswordmgrwithdefaultrealm()
173 return self._mgr
173 return self._mgr
174
174
175 def add_password(self, realm, uris, user, passwd):
175 def add_password(self, realm, uris, user, passwd):
176 return self._get_mgr().add_password(
176 return self._get_mgr().add_password(
177 _maybestrurl(realm), _maybestrurl(uris),
177 _maybestrurl(realm), _maybestrurl(uris),
178 _maybestrurl(user), _maybestrurl(passwd))
178 _maybestrurl(user), _maybestrurl(passwd))
179
179
180 def find_user_password(self, realm, uri):
180 def find_user_password(self, realm, uri):
181 mgr = self._get_mgr()
181 mgr = self._get_mgr()
182 return _maybebytesurl(mgr.find_user_password(_maybestrurl(realm),
182 return _maybebytesurl(mgr.find_user_password(_maybestrurl(realm),
183 _maybestrurl(uri)))
183 _maybestrurl(uri)))
184
184
185 def _catchterm(*args):
185 def _catchterm(*args):
186 raise error.SignalInterrupt
186 raise error.SignalInterrupt
187
187
188 # unique object used to detect no default value has been provided when
188 # unique object used to detect no default value has been provided when
189 # retrieving configuration value.
189 # retrieving configuration value.
190 _unset = object()
190 _unset = object()
191
191
192 # _reqexithandlers: callbacks run at the end of a request
192 # _reqexithandlers: callbacks run at the end of a request
193 _reqexithandlers = []
193 _reqexithandlers = []
194
194
195 class ui(object):
195 class ui(object):
196 def __init__(self, src=None):
196 def __init__(self, src=None):
197 """Create a fresh new ui object if no src given
197 """Create a fresh new ui object if no src given
198
198
199 Use uimod.ui.load() to create a ui which knows global and user configs.
199 Use uimod.ui.load() to create a ui which knows global and user configs.
200 In most cases, you should use ui.copy() to create a copy of an existing
200 In most cases, you should use ui.copy() to create a copy of an existing
201 ui object.
201 ui object.
202 """
202 """
203 # _buffers: used for temporary capture of output
203 # _buffers: used for temporary capture of output
204 self._buffers = []
204 self._buffers = []
205 # 3-tuple describing how each buffer in the stack behaves.
205 # 3-tuple describing how each buffer in the stack behaves.
206 # Values are (capture stderr, capture subprocesses, apply labels).
206 # Values are (capture stderr, capture subprocesses, apply labels).
207 self._bufferstates = []
207 self._bufferstates = []
208 # When a buffer is active, defines whether we are expanding labels.
208 # When a buffer is active, defines whether we are expanding labels.
209 # This exists to prevent an extra list lookup.
209 # This exists to prevent an extra list lookup.
210 self._bufferapplylabels = None
210 self._bufferapplylabels = None
211 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
211 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
212 self._reportuntrusted = True
212 self._reportuntrusted = True
213 self._knownconfig = configitems.coreitems
213 self._knownconfig = configitems.coreitems
214 self._ocfg = config.config() # overlay
214 self._ocfg = config.config() # overlay
215 self._tcfg = config.config() # trusted
215 self._tcfg = config.config() # trusted
216 self._ucfg = config.config() # untrusted
216 self._ucfg = config.config() # untrusted
217 self._trustusers = set()
217 self._trustusers = set()
218 self._trustgroups = set()
218 self._trustgroups = set()
219 self.callhooks = True
219 self.callhooks = True
220 # Insecure server connections requested.
220 # Insecure server connections requested.
221 self.insecureconnections = False
221 self.insecureconnections = False
222 # Blocked time
222 # Blocked time
223 self.logblockedtimes = False
223 self.logblockedtimes = False
224 # color mode: see mercurial/color.py for possible value
224 # color mode: see mercurial/color.py for possible value
225 self._colormode = None
225 self._colormode = None
226 self._terminfoparams = {}
226 self._terminfoparams = {}
227 self._styles = {}
227 self._styles = {}
228
228
229 if src:
229 if src:
230 self.fout = src.fout
230 self.fout = src.fout
231 self.ferr = src.ferr
231 self.ferr = src.ferr
232 self.fin = src.fin
232 self.fin = src.fin
233 self.pageractive = src.pageractive
233 self.pageractive = src.pageractive
234 self._disablepager = src._disablepager
234 self._disablepager = src._disablepager
235 self._tweaked = src._tweaked
235 self._tweaked = src._tweaked
236
236
237 self._tcfg = src._tcfg.copy()
237 self._tcfg = src._tcfg.copy()
238 self._ucfg = src._ucfg.copy()
238 self._ucfg = src._ucfg.copy()
239 self._ocfg = src._ocfg.copy()
239 self._ocfg = src._ocfg.copy()
240 self._trustusers = src._trustusers.copy()
240 self._trustusers = src._trustusers.copy()
241 self._trustgroups = src._trustgroups.copy()
241 self._trustgroups = src._trustgroups.copy()
242 self.environ = src.environ
242 self.environ = src.environ
243 self.callhooks = src.callhooks
243 self.callhooks = src.callhooks
244 self.insecureconnections = src.insecureconnections
244 self.insecureconnections = src.insecureconnections
245 self._colormode = src._colormode
245 self._colormode = src._colormode
246 self._terminfoparams = src._terminfoparams.copy()
246 self._terminfoparams = src._terminfoparams.copy()
247 self._styles = src._styles.copy()
247 self._styles = src._styles.copy()
248
248
249 self.fixconfig()
249 self.fixconfig()
250
250
251 self.httppasswordmgrdb = src.httppasswordmgrdb
251 self.httppasswordmgrdb = src.httppasswordmgrdb
252 self._blockedtimes = src._blockedtimes
252 self._blockedtimes = src._blockedtimes
253 else:
253 else:
254 self.fout = procutil.stdout
254 self.fout = procutil.stdout
255 self.ferr = procutil.stderr
255 self.ferr = procutil.stderr
256 self.fin = procutil.stdin
256 self.fin = procutil.stdin
257 self.pageractive = False
257 self.pageractive = False
258 self._disablepager = False
258 self._disablepager = False
259 self._tweaked = False
259 self._tweaked = False
260
260
261 # shared read-only environment
261 # shared read-only environment
262 self.environ = encoding.environ
262 self.environ = encoding.environ
263
263
264 self.httppasswordmgrdb = httppasswordmgrdbproxy()
264 self.httppasswordmgrdb = httppasswordmgrdbproxy()
265 self._blockedtimes = collections.defaultdict(int)
265 self._blockedtimes = collections.defaultdict(int)
266
266
267 allowed = self.configlist('experimental', 'exportableenviron')
267 allowed = self.configlist('experimental', 'exportableenviron')
268 if '*' in allowed:
268 if '*' in allowed:
269 self._exportableenviron = self.environ
269 self._exportableenviron = self.environ
270 else:
270 else:
271 self._exportableenviron = {}
271 self._exportableenviron = {}
272 for k in allowed:
272 for k in allowed:
273 if k in self.environ:
273 if k in self.environ:
274 self._exportableenviron[k] = self.environ[k]
274 self._exportableenviron[k] = self.environ[k]
275
275
276 @classmethod
276 @classmethod
277 def load(cls):
277 def load(cls):
278 """Create a ui and load global and user configs"""
278 """Create a ui and load global and user configs"""
279 u = cls()
279 u = cls()
280 # we always trust global config files and environment variables
280 # we always trust global config files and environment variables
281 for t, f in rcutil.rccomponents():
281 for t, f in rcutil.rccomponents():
282 if t == 'path':
282 if t == 'path':
283 u.readconfig(f, trust=True)
283 u.readconfig(f, trust=True)
284 elif t == 'items':
284 elif t == 'items':
285 sections = set()
285 sections = set()
286 for section, name, value, source in f:
286 for section, name, value, source in f:
287 # do not set u._ocfg
287 # do not set u._ocfg
288 # XXX clean this up once immutable config object is a thing
288 # XXX clean this up once immutable config object is a thing
289 u._tcfg.set(section, name, value, source)
289 u._tcfg.set(section, name, value, source)
290 u._ucfg.set(section, name, value, source)
290 u._ucfg.set(section, name, value, source)
291 sections.add(section)
291 sections.add(section)
292 for section in sections:
292 for section in sections:
293 u.fixconfig(section=section)
293 u.fixconfig(section=section)
294 else:
294 else:
295 raise error.ProgrammingError('unknown rctype: %s' % t)
295 raise error.ProgrammingError('unknown rctype: %s' % t)
296 u._maybetweakdefaults()
296 u._maybetweakdefaults()
297 return u
297 return u
298
298
299 def _maybetweakdefaults(self):
299 def _maybetweakdefaults(self):
300 if not self.configbool('ui', 'tweakdefaults'):
300 if not self.configbool('ui', 'tweakdefaults'):
301 return
301 return
302 if self._tweaked or self.plain('tweakdefaults'):
302 if self._tweaked or self.plain('tweakdefaults'):
303 return
303 return
304
304
305 # Note: it is SUPER IMPORTANT that you set self._tweaked to
305 # Note: it is SUPER IMPORTANT that you set self._tweaked to
306 # True *before* any calls to setconfig(), otherwise you'll get
306 # True *before* any calls to setconfig(), otherwise you'll get
307 # infinite recursion between setconfig and this method.
307 # infinite recursion between setconfig and this method.
308 #
308 #
309 # TODO: We should extract an inner method in setconfig() to
309 # TODO: We should extract an inner method in setconfig() to
310 # avoid this weirdness.
310 # avoid this weirdness.
311 self._tweaked = True
311 self._tweaked = True
312 tmpcfg = config.config()
312 tmpcfg = config.config()
313 tmpcfg.parse('<tweakdefaults>', tweakrc)
313 tmpcfg.parse('<tweakdefaults>', tweakrc)
314 for section in tmpcfg:
314 for section in tmpcfg:
315 for name, value in tmpcfg.items(section):
315 for name, value in tmpcfg.items(section):
316 if not self.hasconfig(section, name):
316 if not self.hasconfig(section, name):
317 self.setconfig(section, name, value, "<tweakdefaults>")
317 self.setconfig(section, name, value, "<tweakdefaults>")
318
318
319 def copy(self):
319 def copy(self):
320 return self.__class__(self)
320 return self.__class__(self)
321
321
322 def resetstate(self):
322 def resetstate(self):
323 """Clear internal state that shouldn't persist across commands"""
323 """Clear internal state that shouldn't persist across commands"""
324 if self._progbar:
324 if self._progbar:
325 self._progbar.resetstate() # reset last-print time of progress bar
325 self._progbar.resetstate() # reset last-print time of progress bar
326 self.httppasswordmgrdb = httppasswordmgrdbproxy()
326 self.httppasswordmgrdb = httppasswordmgrdbproxy()
327
327
328 @contextlib.contextmanager
328 @contextlib.contextmanager
329 def timeblockedsection(self, key):
329 def timeblockedsection(self, key):
330 # this is open-coded below - search for timeblockedsection to find them
330 # this is open-coded below - search for timeblockedsection to find them
331 starttime = util.timer()
331 starttime = util.timer()
332 try:
332 try:
333 yield
333 yield
334 finally:
334 finally:
335 self._blockedtimes[key + '_blocked'] += \
335 self._blockedtimes[key + '_blocked'] += \
336 (util.timer() - starttime) * 1000
336 (util.timer() - starttime) * 1000
337
337
338 def formatter(self, topic, opts):
338 def formatter(self, topic, opts):
339 return formatter.formatter(self, self, topic, opts)
339 return formatter.formatter(self, self, topic, opts)
340
340
341 def _trusted(self, fp, f):
341 def _trusted(self, fp, f):
342 st = util.fstat(fp)
342 st = util.fstat(fp)
343 if util.isowner(st):
343 if util.isowner(st):
344 return True
344 return True
345
345
346 tusers, tgroups = self._trustusers, self._trustgroups
346 tusers, tgroups = self._trustusers, self._trustgroups
347 if '*' in tusers or '*' in tgroups:
347 if '*' in tusers or '*' in tgroups:
348 return True
348 return True
349
349
350 user = util.username(st.st_uid)
350 user = util.username(st.st_uid)
351 group = util.groupname(st.st_gid)
351 group = util.groupname(st.st_gid)
352 if user in tusers or group in tgroups or user == util.username():
352 if user in tusers or group in tgroups or user == util.username():
353 return True
353 return True
354
354
355 if self._reportuntrusted:
355 if self._reportuntrusted:
356 self.warn(_('not trusting file %s from untrusted '
356 self.warn(_('not trusting file %s from untrusted '
357 'user %s, group %s\n') % (f, user, group))
357 'user %s, group %s\n') % (f, user, group))
358 return False
358 return False
359
359
360 def readconfig(self, filename, root=None, trust=False,
360 def readconfig(self, filename, root=None, trust=False,
361 sections=None, remap=None):
361 sections=None, remap=None):
362 try:
362 try:
363 fp = open(filename, u'rb')
363 fp = open(filename, u'rb')
364 except IOError:
364 except IOError:
365 if not sections: # ignore unless we were looking for something
365 if not sections: # ignore unless we were looking for something
366 return
366 return
367 raise
367 raise
368
368
369 cfg = config.config()
369 cfg = config.config()
370 trusted = sections or trust or self._trusted(fp, filename)
370 trusted = sections or trust or self._trusted(fp, filename)
371
371
372 try:
372 try:
373 cfg.read(filename, fp, sections=sections, remap=remap)
373 cfg.read(filename, fp, sections=sections, remap=remap)
374 fp.close()
374 fp.close()
375 except error.ConfigError as inst:
375 except error.ConfigError as inst:
376 if trusted:
376 if trusted:
377 raise
377 raise
378 self.warn(_("ignored: %s\n") % stringutil.forcebytestr(inst))
378 self.warn(_("ignored: %s\n") % stringutil.forcebytestr(inst))
379
379
380 if self.plain():
380 if self.plain():
381 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
381 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
382 'logtemplate', 'statuscopies', 'style',
382 'logtemplate', 'statuscopies', 'style',
383 'traceback', 'verbose'):
383 'traceback', 'verbose'):
384 if k in cfg['ui']:
384 if k in cfg['ui']:
385 del cfg['ui'][k]
385 del cfg['ui'][k]
386 for k, v in cfg.items('defaults'):
386 for k, v in cfg.items('defaults'):
387 del cfg['defaults'][k]
387 del cfg['defaults'][k]
388 for k, v in cfg.items('commands'):
388 for k, v in cfg.items('commands'):
389 del cfg['commands'][k]
389 del cfg['commands'][k]
390 # Don't remove aliases from the configuration if in the exceptionlist
390 # Don't remove aliases from the configuration if in the exceptionlist
391 if self.plain('alias'):
391 if self.plain('alias'):
392 for k, v in cfg.items('alias'):
392 for k, v in cfg.items('alias'):
393 del cfg['alias'][k]
393 del cfg['alias'][k]
394 if self.plain('revsetalias'):
394 if self.plain('revsetalias'):
395 for k, v in cfg.items('revsetalias'):
395 for k, v in cfg.items('revsetalias'):
396 del cfg['revsetalias'][k]
396 del cfg['revsetalias'][k]
397 if self.plain('templatealias'):
397 if self.plain('templatealias'):
398 for k, v in cfg.items('templatealias'):
398 for k, v in cfg.items('templatealias'):
399 del cfg['templatealias'][k]
399 del cfg['templatealias'][k]
400
400
401 if trusted:
401 if trusted:
402 self._tcfg.update(cfg)
402 self._tcfg.update(cfg)
403 self._tcfg.update(self._ocfg)
403 self._tcfg.update(self._ocfg)
404 self._ucfg.update(cfg)
404 self._ucfg.update(cfg)
405 self._ucfg.update(self._ocfg)
405 self._ucfg.update(self._ocfg)
406
406
407 if root is None:
407 if root is None:
408 root = os.path.expanduser('~')
408 root = os.path.expanduser('~')
409 self.fixconfig(root=root)
409 self.fixconfig(root=root)
410
410
411 def fixconfig(self, root=None, section=None):
411 def fixconfig(self, root=None, section=None):
412 if section in (None, 'paths'):
412 if section in (None, 'paths'):
413 # expand vars and ~
413 # expand vars and ~
414 # translate paths relative to root (or home) into absolute paths
414 # translate paths relative to root (or home) into absolute paths
415 root = root or pycompat.getcwd()
415 root = root or pycompat.getcwd()
416 for c in self._tcfg, self._ucfg, self._ocfg:
416 for c in self._tcfg, self._ucfg, self._ocfg:
417 for n, p in c.items('paths'):
417 for n, p in c.items('paths'):
418 # Ignore sub-options.
418 # Ignore sub-options.
419 if ':' in n:
419 if ':' in n:
420 continue
420 continue
421 if not p:
421 if not p:
422 continue
422 continue
423 if '%%' in p:
423 if '%%' in p:
424 s = self.configsource('paths', n) or 'none'
424 s = self.configsource('paths', n) or 'none'
425 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
425 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
426 % (n, p, s))
426 % (n, p, s))
427 p = p.replace('%%', '%')
427 p = p.replace('%%', '%')
428 p = util.expandpath(p)
428 p = util.expandpath(p)
429 if not util.hasscheme(p) and not os.path.isabs(p):
429 if not util.hasscheme(p) and not os.path.isabs(p):
430 p = os.path.normpath(os.path.join(root, p))
430 p = os.path.normpath(os.path.join(root, p))
431 c.set("paths", n, p)
431 c.set("paths", n, p)
432
432
433 if section in (None, 'ui'):
433 if section in (None, 'ui'):
434 # update ui options
434 # update ui options
435 self.debugflag = self.configbool('ui', 'debug')
435 self.debugflag = self.configbool('ui', 'debug')
436 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
436 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
437 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
437 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
438 if self.verbose and self.quiet:
438 if self.verbose and self.quiet:
439 self.quiet = self.verbose = False
439 self.quiet = self.verbose = False
440 self._reportuntrusted = self.debugflag or self.configbool("ui",
440 self._reportuntrusted = self.debugflag or self.configbool("ui",
441 "report_untrusted")
441 "report_untrusted")
442 self.tracebackflag = self.configbool('ui', 'traceback')
442 self.tracebackflag = self.configbool('ui', 'traceback')
443 self.logblockedtimes = self.configbool('ui', 'logblockedtimes')
443 self.logblockedtimes = self.configbool('ui', 'logblockedtimes')
444
444
445 if section in (None, 'trusted'):
445 if section in (None, 'trusted'):
446 # update trust information
446 # update trust information
447 self._trustusers.update(self.configlist('trusted', 'users'))
447 self._trustusers.update(self.configlist('trusted', 'users'))
448 self._trustgroups.update(self.configlist('trusted', 'groups'))
448 self._trustgroups.update(self.configlist('trusted', 'groups'))
449
449
450 def backupconfig(self, section, item):
450 def backupconfig(self, section, item):
451 return (self._ocfg.backup(section, item),
451 return (self._ocfg.backup(section, item),
452 self._tcfg.backup(section, item),
452 self._tcfg.backup(section, item),
453 self._ucfg.backup(section, item),)
453 self._ucfg.backup(section, item),)
454 def restoreconfig(self, data):
454 def restoreconfig(self, data):
455 self._ocfg.restore(data[0])
455 self._ocfg.restore(data[0])
456 self._tcfg.restore(data[1])
456 self._tcfg.restore(data[1])
457 self._ucfg.restore(data[2])
457 self._ucfg.restore(data[2])
458
458
459 def setconfig(self, section, name, value, source=''):
459 def setconfig(self, section, name, value, source=''):
460 for cfg in (self._ocfg, self._tcfg, self._ucfg):
460 for cfg in (self._ocfg, self._tcfg, self._ucfg):
461 cfg.set(section, name, value, source)
461 cfg.set(section, name, value, source)
462 self.fixconfig(section=section)
462 self.fixconfig(section=section)
463 self._maybetweakdefaults()
463 self._maybetweakdefaults()
464
464
465 def _data(self, untrusted):
465 def _data(self, untrusted):
466 return untrusted and self._ucfg or self._tcfg
466 return untrusted and self._ucfg or self._tcfg
467
467
468 def configsource(self, section, name, untrusted=False):
468 def configsource(self, section, name, untrusted=False):
469 return self._data(untrusted).source(section, name)
469 return self._data(untrusted).source(section, name)
470
470
471 def config(self, section, name, default=_unset, untrusted=False):
471 def config(self, section, name, default=_unset, untrusted=False):
472 """return the plain string version of a config"""
472 """return the plain string version of a config"""
473 value = self._config(section, name, default=default,
473 value = self._config(section, name, default=default,
474 untrusted=untrusted)
474 untrusted=untrusted)
475 if value is _unset:
475 if value is _unset:
476 return None
476 return None
477 return value
477 return value
478
478
479 def _config(self, section, name, default=_unset, untrusted=False):
479 def _config(self, section, name, default=_unset, untrusted=False):
480 value = itemdefault = default
480 value = itemdefault = default
481 item = self._knownconfig.get(section, {}).get(name)
481 item = self._knownconfig.get(section, {}).get(name)
482 alternates = [(section, name)]
482 alternates = [(section, name)]
483
483
484 if item is not None:
484 if item is not None:
485 alternates.extend(item.alias)
485 alternates.extend(item.alias)
486 if callable(item.default):
486 if callable(item.default):
487 itemdefault = item.default()
487 itemdefault = item.default()
488 else:
488 else:
489 itemdefault = item.default
489 itemdefault = item.default
490 else:
490 else:
491 msg = ("accessing unregistered config item: '%s.%s'")
491 msg = ("accessing unregistered config item: '%s.%s'")
492 msg %= (section, name)
492 msg %= (section, name)
493 self.develwarn(msg, 2, 'warn-config-unknown')
493 self.develwarn(msg, 2, 'warn-config-unknown')
494
494
495 if default is _unset:
495 if default is _unset:
496 if item is None:
496 if item is None:
497 value = default
497 value = default
498 elif item.default is configitems.dynamicdefault:
498 elif item.default is configitems.dynamicdefault:
499 value = None
499 value = None
500 msg = "config item requires an explicit default value: '%s.%s'"
500 msg = "config item requires an explicit default value: '%s.%s'"
501 msg %= (section, name)
501 msg %= (section, name)
502 self.develwarn(msg, 2, 'warn-config-default')
502 self.develwarn(msg, 2, 'warn-config-default')
503 else:
503 else:
504 value = itemdefault
504 value = itemdefault
505 elif (item is not None
505 elif (item is not None
506 and item.default is not configitems.dynamicdefault
506 and item.default is not configitems.dynamicdefault
507 and default != itemdefault):
507 and default != itemdefault):
508 msg = ("specifying a mismatched default value for a registered "
508 msg = ("specifying a mismatched default value for a registered "
509 "config item: '%s.%s' '%s'")
509 "config item: '%s.%s' '%s'")
510 msg %= (section, name, pycompat.bytestr(default))
510 msg %= (section, name, pycompat.bytestr(default))
511 self.develwarn(msg, 2, 'warn-config-default')
511 self.develwarn(msg, 2, 'warn-config-default')
512
512
513 for s, n in alternates:
513 for s, n in alternates:
514 candidate = self._data(untrusted).get(s, n, None)
514 candidate = self._data(untrusted).get(s, n, None)
515 if candidate is not None:
515 if candidate is not None:
516 value = candidate
516 value = candidate
517 section = s
517 section = s
518 name = n
518 name = n
519 break
519 break
520
520
521 if self.debugflag and not untrusted and self._reportuntrusted:
521 if self.debugflag and not untrusted and self._reportuntrusted:
522 for s, n in alternates:
522 for s, n in alternates:
523 uvalue = self._ucfg.get(s, n)
523 uvalue = self._ucfg.get(s, n)
524 if uvalue is not None and uvalue != value:
524 if uvalue is not None and uvalue != value:
525 self.debug("ignoring untrusted configuration option "
525 self.debug("ignoring untrusted configuration option "
526 "%s.%s = %s\n" % (s, n, uvalue))
526 "%s.%s = %s\n" % (s, n, uvalue))
527 return value
527 return value
528
528
529 def configsuboptions(self, section, name, default=_unset, untrusted=False):
529 def configsuboptions(self, section, name, default=_unset, untrusted=False):
530 """Get a config option and all sub-options.
530 """Get a config option and all sub-options.
531
531
532 Some config options have sub-options that are declared with the
532 Some config options have sub-options that are declared with the
533 format "key:opt = value". This method is used to return the main
533 format "key:opt = value". This method is used to return the main
534 option and all its declared sub-options.
534 option and all its declared sub-options.
535
535
536 Returns a 2-tuple of ``(option, sub-options)``, where `sub-options``
536 Returns a 2-tuple of ``(option, sub-options)``, where `sub-options``
537 is a dict of defined sub-options where keys and values are strings.
537 is a dict of defined sub-options where keys and values are strings.
538 """
538 """
539 main = self.config(section, name, default, untrusted=untrusted)
539 main = self.config(section, name, default, untrusted=untrusted)
540 data = self._data(untrusted)
540 data = self._data(untrusted)
541 sub = {}
541 sub = {}
542 prefix = '%s:' % name
542 prefix = '%s:' % name
543 for k, v in data.items(section):
543 for k, v in data.items(section):
544 if k.startswith(prefix):
544 if k.startswith(prefix):
545 sub[k[len(prefix):]] = v
545 sub[k[len(prefix):]] = v
546
546
547 if self.debugflag and not untrusted and self._reportuntrusted:
547 if self.debugflag and not untrusted and self._reportuntrusted:
548 for k, v in sub.items():
548 for k, v in sub.items():
549 uvalue = self._ucfg.get(section, '%s:%s' % (name, k))
549 uvalue = self._ucfg.get(section, '%s:%s' % (name, k))
550 if uvalue is not None and uvalue != v:
550 if uvalue is not None and uvalue != v:
551 self.debug('ignoring untrusted configuration option '
551 self.debug('ignoring untrusted configuration option '
552 '%s:%s.%s = %s\n' % (section, name, k, uvalue))
552 '%s:%s.%s = %s\n' % (section, name, k, uvalue))
553
553
554 return main, sub
554 return main, sub
555
555
556 def configpath(self, section, name, default=_unset, untrusted=False):
556 def configpath(self, section, name, default=_unset, untrusted=False):
557 'get a path config item, expanded relative to repo root or config file'
557 'get a path config item, expanded relative to repo root or config file'
558 v = self.config(section, name, default, untrusted)
558 v = self.config(section, name, default, untrusted)
559 if v is None:
559 if v is None:
560 return None
560 return None
561 if not os.path.isabs(v) or "://" not in v:
561 if not os.path.isabs(v) or "://" not in v:
562 src = self.configsource(section, name, untrusted)
562 src = self.configsource(section, name, untrusted)
563 if ':' in src:
563 if ':' in src:
564 base = os.path.dirname(src.rsplit(':')[0])
564 base = os.path.dirname(src.rsplit(':')[0])
565 v = os.path.join(base, os.path.expanduser(v))
565 v = os.path.join(base, os.path.expanduser(v))
566 return v
566 return v
567
567
568 def configbool(self, section, name, default=_unset, untrusted=False):
568 def configbool(self, section, name, default=_unset, untrusted=False):
569 """parse a configuration element as a boolean
569 """parse a configuration element as a boolean
570
570
571 >>> u = ui(); s = b'foo'
571 >>> u = ui(); s = b'foo'
572 >>> u.setconfig(s, b'true', b'yes')
572 >>> u.setconfig(s, b'true', b'yes')
573 >>> u.configbool(s, b'true')
573 >>> u.configbool(s, b'true')
574 True
574 True
575 >>> u.setconfig(s, b'false', b'no')
575 >>> u.setconfig(s, b'false', b'no')
576 >>> u.configbool(s, b'false')
576 >>> u.configbool(s, b'false')
577 False
577 False
578 >>> u.configbool(s, b'unknown')
578 >>> u.configbool(s, b'unknown')
579 False
579 False
580 >>> u.configbool(s, b'unknown', True)
580 >>> u.configbool(s, b'unknown', True)
581 True
581 True
582 >>> u.setconfig(s, b'invalid', b'somevalue')
582 >>> u.setconfig(s, b'invalid', b'somevalue')
583 >>> u.configbool(s, b'invalid')
583 >>> u.configbool(s, b'invalid')
584 Traceback (most recent call last):
584 Traceback (most recent call last):
585 ...
585 ...
586 ConfigError: foo.invalid is not a boolean ('somevalue')
586 ConfigError: foo.invalid is not a boolean ('somevalue')
587 """
587 """
588
588
589 v = self._config(section, name, default, untrusted=untrusted)
589 v = self._config(section, name, default, untrusted=untrusted)
590 if v is None:
590 if v is None:
591 return v
591 return v
592 if v is _unset:
592 if v is _unset:
593 if default is _unset:
593 if default is _unset:
594 return False
594 return False
595 return default
595 return default
596 if isinstance(v, bool):
596 if isinstance(v, bool):
597 return v
597 return v
598 b = stringutil.parsebool(v)
598 b = stringutil.parsebool(v)
599 if b is None:
599 if b is None:
600 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
600 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
601 % (section, name, v))
601 % (section, name, v))
602 return b
602 return b
603
603
604 def configwith(self, convert, section, name, default=_unset,
604 def configwith(self, convert, section, name, default=_unset,
605 desc=None, untrusted=False):
605 desc=None, untrusted=False):
606 """parse a configuration element with a conversion function
606 """parse a configuration element with a conversion function
607
607
608 >>> u = ui(); s = b'foo'
608 >>> u = ui(); s = b'foo'
609 >>> u.setconfig(s, b'float1', b'42')
609 >>> u.setconfig(s, b'float1', b'42')
610 >>> u.configwith(float, s, b'float1')
610 >>> u.configwith(float, s, b'float1')
611 42.0
611 42.0
612 >>> u.setconfig(s, b'float2', b'-4.25')
612 >>> u.setconfig(s, b'float2', b'-4.25')
613 >>> u.configwith(float, s, b'float2')
613 >>> u.configwith(float, s, b'float2')
614 -4.25
614 -4.25
615 >>> u.configwith(float, s, b'unknown', 7)
615 >>> u.configwith(float, s, b'unknown', 7)
616 7.0
616 7.0
617 >>> u.setconfig(s, b'invalid', b'somevalue')
617 >>> u.setconfig(s, b'invalid', b'somevalue')
618 >>> u.configwith(float, s, b'invalid')
618 >>> u.configwith(float, s, b'invalid')
619 Traceback (most recent call last):
619 Traceback (most recent call last):
620 ...
620 ...
621 ConfigError: foo.invalid is not a valid float ('somevalue')
621 ConfigError: foo.invalid is not a valid float ('somevalue')
622 >>> u.configwith(float, s, b'invalid', desc=b'womble')
622 >>> u.configwith(float, s, b'invalid', desc=b'womble')
623 Traceback (most recent call last):
623 Traceback (most recent call last):
624 ...
624 ...
625 ConfigError: foo.invalid is not a valid womble ('somevalue')
625 ConfigError: foo.invalid is not a valid womble ('somevalue')
626 """
626 """
627
627
628 v = self.config(section, name, default, untrusted)
628 v = self.config(section, name, default, untrusted)
629 if v is None:
629 if v is None:
630 return v # do not attempt to convert None
630 return v # do not attempt to convert None
631 try:
631 try:
632 return convert(v)
632 return convert(v)
633 except (ValueError, error.ParseError):
633 except (ValueError, error.ParseError):
634 if desc is None:
634 if desc is None:
635 desc = pycompat.sysbytes(convert.__name__)
635 desc = pycompat.sysbytes(convert.__name__)
636 raise error.ConfigError(_("%s.%s is not a valid %s ('%s')")
636 raise error.ConfigError(_("%s.%s is not a valid %s ('%s')")
637 % (section, name, desc, v))
637 % (section, name, desc, v))
638
638
639 def configint(self, section, name, default=_unset, untrusted=False):
639 def configint(self, section, name, default=_unset, untrusted=False):
640 """parse a configuration element as an integer
640 """parse a configuration element as an integer
641
641
642 >>> u = ui(); s = b'foo'
642 >>> u = ui(); s = b'foo'
643 >>> u.setconfig(s, b'int1', b'42')
643 >>> u.setconfig(s, b'int1', b'42')
644 >>> u.configint(s, b'int1')
644 >>> u.configint(s, b'int1')
645 42
645 42
646 >>> u.setconfig(s, b'int2', b'-42')
646 >>> u.setconfig(s, b'int2', b'-42')
647 >>> u.configint(s, b'int2')
647 >>> u.configint(s, b'int2')
648 -42
648 -42
649 >>> u.configint(s, b'unknown', 7)
649 >>> u.configint(s, b'unknown', 7)
650 7
650 7
651 >>> u.setconfig(s, b'invalid', b'somevalue')
651 >>> u.setconfig(s, b'invalid', b'somevalue')
652 >>> u.configint(s, b'invalid')
652 >>> u.configint(s, b'invalid')
653 Traceback (most recent call last):
653 Traceback (most recent call last):
654 ...
654 ...
655 ConfigError: foo.invalid is not a valid integer ('somevalue')
655 ConfigError: foo.invalid is not a valid integer ('somevalue')
656 """
656 """
657
657
658 return self.configwith(int, section, name, default, 'integer',
658 return self.configwith(int, section, name, default, 'integer',
659 untrusted)
659 untrusted)
660
660
661 def configbytes(self, section, name, default=_unset, untrusted=False):
661 def configbytes(self, section, name, default=_unset, untrusted=False):
662 """parse a configuration element as a quantity in bytes
662 """parse a configuration element as a quantity in bytes
663
663
664 Units can be specified as b (bytes), k or kb (kilobytes), m or
664 Units can be specified as b (bytes), k or kb (kilobytes), m or
665 mb (megabytes), g or gb (gigabytes).
665 mb (megabytes), g or gb (gigabytes).
666
666
667 >>> u = ui(); s = b'foo'
667 >>> u = ui(); s = b'foo'
668 >>> u.setconfig(s, b'val1', b'42')
668 >>> u.setconfig(s, b'val1', b'42')
669 >>> u.configbytes(s, b'val1')
669 >>> u.configbytes(s, b'val1')
670 42
670 42
671 >>> u.setconfig(s, b'val2', b'42.5 kb')
671 >>> u.setconfig(s, b'val2', b'42.5 kb')
672 >>> u.configbytes(s, b'val2')
672 >>> u.configbytes(s, b'val2')
673 43520
673 43520
674 >>> u.configbytes(s, b'unknown', b'7 MB')
674 >>> u.configbytes(s, b'unknown', b'7 MB')
675 7340032
675 7340032
676 >>> u.setconfig(s, b'invalid', b'somevalue')
676 >>> u.setconfig(s, b'invalid', b'somevalue')
677 >>> u.configbytes(s, b'invalid')
677 >>> u.configbytes(s, b'invalid')
678 Traceback (most recent call last):
678 Traceback (most recent call last):
679 ...
679 ...
680 ConfigError: foo.invalid is not a byte quantity ('somevalue')
680 ConfigError: foo.invalid is not a byte quantity ('somevalue')
681 """
681 """
682
682
683 value = self._config(section, name, default, untrusted)
683 value = self._config(section, name, default, untrusted)
684 if value is _unset:
684 if value is _unset:
685 if default is _unset:
685 if default is _unset:
686 default = 0
686 default = 0
687 value = default
687 value = default
688 if not isinstance(value, bytes):
688 if not isinstance(value, bytes):
689 return value
689 return value
690 try:
690 try:
691 return util.sizetoint(value)
691 return util.sizetoint(value)
692 except error.ParseError:
692 except error.ParseError:
693 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
693 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
694 % (section, name, value))
694 % (section, name, value))
695
695
696 def configlist(self, section, name, default=_unset, untrusted=False):
696 def configlist(self, section, name, default=_unset, untrusted=False):
697 """parse a configuration element as a list of comma/space separated
697 """parse a configuration element as a list of comma/space separated
698 strings
698 strings
699
699
700 >>> u = ui(); s = b'foo'
700 >>> u = ui(); s = b'foo'
701 >>> u.setconfig(s, b'list1', b'this,is "a small" ,test')
701 >>> u.setconfig(s, b'list1', b'this,is "a small" ,test')
702 >>> u.configlist(s, b'list1')
702 >>> u.configlist(s, b'list1')
703 ['this', 'is', 'a small', 'test']
703 ['this', 'is', 'a small', 'test']
704 >>> u.setconfig(s, b'list2', b'this, is "a small" , test ')
704 >>> u.setconfig(s, b'list2', b'this, is "a small" , test ')
705 >>> u.configlist(s, b'list2')
705 >>> u.configlist(s, b'list2')
706 ['this', 'is', 'a small', 'test']
706 ['this', 'is', 'a small', 'test']
707 """
707 """
708 # default is not always a list
708 # default is not always a list
709 v = self.configwith(config.parselist, section, name, default,
709 v = self.configwith(config.parselist, section, name, default,
710 'list', untrusted)
710 'list', untrusted)
711 if isinstance(v, bytes):
711 if isinstance(v, bytes):
712 return config.parselist(v)
712 return config.parselist(v)
713 elif v is None:
713 elif v is None:
714 return []
714 return []
715 return v
715 return v
716
716
717 def configdate(self, section, name, default=_unset, untrusted=False):
717 def configdate(self, section, name, default=_unset, untrusted=False):
718 """parse a configuration element as a tuple of ints
718 """parse a configuration element as a tuple of ints
719
719
720 >>> u = ui(); s = b'foo'
720 >>> u = ui(); s = b'foo'
721 >>> u.setconfig(s, b'date', b'0 0')
721 >>> u.setconfig(s, b'date', b'0 0')
722 >>> u.configdate(s, b'date')
722 >>> u.configdate(s, b'date')
723 (0, 0)
723 (0, 0)
724 """
724 """
725 if self.config(section, name, default, untrusted):
725 if self.config(section, name, default, untrusted):
726 return self.configwith(dateutil.parsedate, section, name, default,
726 return self.configwith(dateutil.parsedate, section, name, default,
727 'date', untrusted)
727 'date', untrusted)
728 if default is _unset:
728 if default is _unset:
729 return None
729 return None
730 return default
730 return default
731
731
732 def hasconfig(self, section, name, untrusted=False):
732 def hasconfig(self, section, name, untrusted=False):
733 return self._data(untrusted).hasitem(section, name)
733 return self._data(untrusted).hasitem(section, name)
734
734
735 def has_section(self, section, untrusted=False):
735 def has_section(self, section, untrusted=False):
736 '''tell whether section exists in config.'''
736 '''tell whether section exists in config.'''
737 return section in self._data(untrusted)
737 return section in self._data(untrusted)
738
738
739 def configitems(self, section, untrusted=False, ignoresub=False):
739 def configitems(self, section, untrusted=False, ignoresub=False):
740 items = self._data(untrusted).items(section)
740 items = self._data(untrusted).items(section)
741 if ignoresub:
741 if ignoresub:
742 newitems = {}
742 items = [i for i in items if ':' not in i[0]]
743 for k, v in items:
744 if ':' not in k:
745 newitems[k] = v
746 items = list(newitems.iteritems())
747 if self.debugflag and not untrusted and self._reportuntrusted:
743 if self.debugflag and not untrusted and self._reportuntrusted:
748 for k, v in self._ucfg.items(section):
744 for k, v in self._ucfg.items(section):
749 if self._tcfg.get(section, k) != v:
745 if self._tcfg.get(section, k) != v:
750 self.debug("ignoring untrusted configuration option "
746 self.debug("ignoring untrusted configuration option "
751 "%s.%s = %s\n" % (section, k, v))
747 "%s.%s = %s\n" % (section, k, v))
752 return items
748 return items
753
749
754 def walkconfig(self, untrusted=False):
750 def walkconfig(self, untrusted=False):
755 cfg = self._data(untrusted)
751 cfg = self._data(untrusted)
756 for section in cfg.sections():
752 for section in cfg.sections():
757 for name, value in self.configitems(section, untrusted):
753 for name, value in self.configitems(section, untrusted):
758 yield section, name, value
754 yield section, name, value
759
755
760 def plain(self, feature=None):
756 def plain(self, feature=None):
761 '''is plain mode active?
757 '''is plain mode active?
762
758
763 Plain mode means that all configuration variables which affect
759 Plain mode means that all configuration variables which affect
764 the behavior and output of Mercurial should be
760 the behavior and output of Mercurial should be
765 ignored. Additionally, the output should be stable,
761 ignored. Additionally, the output should be stable,
766 reproducible and suitable for use in scripts or applications.
762 reproducible and suitable for use in scripts or applications.
767
763
768 The only way to trigger plain mode is by setting either the
764 The only way to trigger plain mode is by setting either the
769 `HGPLAIN' or `HGPLAINEXCEPT' environment variables.
765 `HGPLAIN' or `HGPLAINEXCEPT' environment variables.
770
766
771 The return value can either be
767 The return value can either be
772 - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
768 - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
773 - False if feature is disabled by default and not included in HGPLAIN
769 - False if feature is disabled by default and not included in HGPLAIN
774 - True otherwise
770 - True otherwise
775 '''
771 '''
776 if ('HGPLAIN' not in encoding.environ and
772 if ('HGPLAIN' not in encoding.environ and
777 'HGPLAINEXCEPT' not in encoding.environ):
773 'HGPLAINEXCEPT' not in encoding.environ):
778 return False
774 return False
779 exceptions = encoding.environ.get('HGPLAINEXCEPT',
775 exceptions = encoding.environ.get('HGPLAINEXCEPT',
780 '').strip().split(',')
776 '').strip().split(',')
781 # TODO: add support for HGPLAIN=+feature,-feature syntax
777 # TODO: add support for HGPLAIN=+feature,-feature syntax
782 if '+strictflags' not in encoding.environ.get('HGPLAIN', '').split(','):
778 if '+strictflags' not in encoding.environ.get('HGPLAIN', '').split(','):
783 exceptions.append('strictflags')
779 exceptions.append('strictflags')
784 if feature and exceptions:
780 if feature and exceptions:
785 return feature not in exceptions
781 return feature not in exceptions
786 return True
782 return True
787
783
788 def username(self, acceptempty=False):
784 def username(self, acceptempty=False):
789 """Return default username to be used in commits.
785 """Return default username to be used in commits.
790
786
791 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
787 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
792 and stop searching if one of these is set.
788 and stop searching if one of these is set.
793 If not found and acceptempty is True, returns None.
789 If not found and acceptempty is True, returns None.
794 If not found and ui.askusername is True, ask the user, else use
790 If not found and ui.askusername is True, ask the user, else use
795 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
791 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
796 If no username could be found, raise an Abort error.
792 If no username could be found, raise an Abort error.
797 """
793 """
798 user = encoding.environ.get("HGUSER")
794 user = encoding.environ.get("HGUSER")
799 if user is None:
795 if user is None:
800 user = self.config("ui", "username")
796 user = self.config("ui", "username")
801 if user is not None:
797 if user is not None:
802 user = os.path.expandvars(user)
798 user = os.path.expandvars(user)
803 if user is None:
799 if user is None:
804 user = encoding.environ.get("EMAIL")
800 user = encoding.environ.get("EMAIL")
805 if user is None and acceptempty:
801 if user is None and acceptempty:
806 return user
802 return user
807 if user is None and self.configbool("ui", "askusername"):
803 if user is None and self.configbool("ui", "askusername"):
808 user = self.prompt(_("enter a commit username:"), default=None)
804 user = self.prompt(_("enter a commit username:"), default=None)
809 if user is None and not self.interactive():
805 if user is None and not self.interactive():
810 try:
806 try:
811 user = '%s@%s' % (procutil.getuser(),
807 user = '%s@%s' % (procutil.getuser(),
812 encoding.strtolocal(socket.getfqdn()))
808 encoding.strtolocal(socket.getfqdn()))
813 self.warn(_("no username found, using '%s' instead\n") % user)
809 self.warn(_("no username found, using '%s' instead\n") % user)
814 except KeyError:
810 except KeyError:
815 pass
811 pass
816 if not user:
812 if not user:
817 raise error.Abort(_('no username supplied'),
813 raise error.Abort(_('no username supplied'),
818 hint=_("use 'hg config --edit' "
814 hint=_("use 'hg config --edit' "
819 'to set your username'))
815 'to set your username'))
820 if "\n" in user:
816 if "\n" in user:
821 raise error.Abort(_("username %r contains a newline\n")
817 raise error.Abort(_("username %r contains a newline\n")
822 % pycompat.bytestr(user))
818 % pycompat.bytestr(user))
823 return user
819 return user
824
820
825 def shortuser(self, user):
821 def shortuser(self, user):
826 """Return a short representation of a user name or email address."""
822 """Return a short representation of a user name or email address."""
827 if not self.verbose:
823 if not self.verbose:
828 user = stringutil.shortuser(user)
824 user = stringutil.shortuser(user)
829 return user
825 return user
830
826
831 def expandpath(self, loc, default=None):
827 def expandpath(self, loc, default=None):
832 """Return repository location relative to cwd or from [paths]"""
828 """Return repository location relative to cwd or from [paths]"""
833 try:
829 try:
834 p = self.paths.getpath(loc)
830 p = self.paths.getpath(loc)
835 if p:
831 if p:
836 return p.rawloc
832 return p.rawloc
837 except error.RepoError:
833 except error.RepoError:
838 pass
834 pass
839
835
840 if default:
836 if default:
841 try:
837 try:
842 p = self.paths.getpath(default)
838 p = self.paths.getpath(default)
843 if p:
839 if p:
844 return p.rawloc
840 return p.rawloc
845 except error.RepoError:
841 except error.RepoError:
846 pass
842 pass
847
843
848 return loc
844 return loc
849
845
850 @util.propertycache
846 @util.propertycache
851 def paths(self):
847 def paths(self):
852 return paths(self)
848 return paths(self)
853
849
854 def pushbuffer(self, error=False, subproc=False, labeled=False):
850 def pushbuffer(self, error=False, subproc=False, labeled=False):
855 """install a buffer to capture standard output of the ui object
851 """install a buffer to capture standard output of the ui object
856
852
857 If error is True, the error output will be captured too.
853 If error is True, the error output will be captured too.
858
854
859 If subproc is True, output from subprocesses (typically hooks) will be
855 If subproc is True, output from subprocesses (typically hooks) will be
860 captured too.
856 captured too.
861
857
862 If labeled is True, any labels associated with buffered
858 If labeled is True, any labels associated with buffered
863 output will be handled. By default, this has no effect
859 output will be handled. By default, this has no effect
864 on the output returned, but extensions and GUI tools may
860 on the output returned, but extensions and GUI tools may
865 handle this argument and returned styled output. If output
861 handle this argument and returned styled output. If output
866 is being buffered so it can be captured and parsed or
862 is being buffered so it can be captured and parsed or
867 processed, labeled should not be set to True.
863 processed, labeled should not be set to True.
868 """
864 """
869 self._buffers.append([])
865 self._buffers.append([])
870 self._bufferstates.append((error, subproc, labeled))
866 self._bufferstates.append((error, subproc, labeled))
871 self._bufferapplylabels = labeled
867 self._bufferapplylabels = labeled
872
868
873 def popbuffer(self):
869 def popbuffer(self):
874 '''pop the last buffer and return the buffered output'''
870 '''pop the last buffer and return the buffered output'''
875 self._bufferstates.pop()
871 self._bufferstates.pop()
876 if self._bufferstates:
872 if self._bufferstates:
877 self._bufferapplylabels = self._bufferstates[-1][2]
873 self._bufferapplylabels = self._bufferstates[-1][2]
878 else:
874 else:
879 self._bufferapplylabels = None
875 self._bufferapplylabels = None
880
876
881 return "".join(self._buffers.pop())
877 return "".join(self._buffers.pop())
882
878
883 def canwritewithoutlabels(self):
879 def canwritewithoutlabels(self):
884 '''check if write skips the label'''
880 '''check if write skips the label'''
885 if self._buffers and not self._bufferapplylabels:
881 if self._buffers and not self._bufferapplylabels:
886 return True
882 return True
887 return self._colormode is None
883 return self._colormode is None
888
884
889 def canbatchlabeledwrites(self):
885 def canbatchlabeledwrites(self):
890 '''check if write calls with labels are batchable'''
886 '''check if write calls with labels are batchable'''
891 # Windows color printing is special, see ``write``.
887 # Windows color printing is special, see ``write``.
892 return self._colormode != 'win32'
888 return self._colormode != 'win32'
893
889
894 def write(self, *args, **opts):
890 def write(self, *args, **opts):
895 '''write args to output
891 '''write args to output
896
892
897 By default, this method simply writes to the buffer or stdout.
893 By default, this method simply writes to the buffer or stdout.
898 Color mode can be set on the UI class to have the output decorated
894 Color mode can be set on the UI class to have the output decorated
899 with color modifier before being written to stdout.
895 with color modifier before being written to stdout.
900
896
901 The color used is controlled by an optional keyword argument, "label".
897 The color used is controlled by an optional keyword argument, "label".
902 This should be a string containing label names separated by space.
898 This should be a string containing label names separated by space.
903 Label names take the form of "topic.type". For example, ui.debug()
899 Label names take the form of "topic.type". For example, ui.debug()
904 issues a label of "ui.debug".
900 issues a label of "ui.debug".
905
901
906 When labeling output for a specific command, a label of
902 When labeling output for a specific command, a label of
907 "cmdname.type" is recommended. For example, status issues
903 "cmdname.type" is recommended. For example, status issues
908 a label of "status.modified" for modified files.
904 a label of "status.modified" for modified files.
909 '''
905 '''
910 if self._buffers:
906 if self._buffers:
911 if self._bufferapplylabels:
907 if self._bufferapplylabels:
912 label = opts.get(r'label', '')
908 label = opts.get(r'label', '')
913 self._buffers[-1].extend(self.label(a, label) for a in args)
909 self._buffers[-1].extend(self.label(a, label) for a in args)
914 else:
910 else:
915 self._buffers[-1].extend(args)
911 self._buffers[-1].extend(args)
916 else:
912 else:
917 self._writenobuf(*args, **opts)
913 self._writenobuf(*args, **opts)
918
914
919 def _writenobuf(self, *args, **opts):
915 def _writenobuf(self, *args, **opts):
920 if self._colormode == 'win32':
916 if self._colormode == 'win32':
921 # windows color printing is its own can of crab, defer to
917 # windows color printing is its own can of crab, defer to
922 # the color module and that is it.
918 # the color module and that is it.
923 color.win32print(self, self._write, *args, **opts)
919 color.win32print(self, self._write, *args, **opts)
924 else:
920 else:
925 msgs = args
921 msgs = args
926 if self._colormode is not None:
922 if self._colormode is not None:
927 label = opts.get(r'label', '')
923 label = opts.get(r'label', '')
928 msgs = [self.label(a, label) for a in args]
924 msgs = [self.label(a, label) for a in args]
929 self._write(*msgs, **opts)
925 self._write(*msgs, **opts)
930
926
931 def _write(self, *msgs, **opts):
927 def _write(self, *msgs, **opts):
932 self._progclear()
928 self._progclear()
933 # opencode timeblockedsection because this is a critical path
929 # opencode timeblockedsection because this is a critical path
934 starttime = util.timer()
930 starttime = util.timer()
935 try:
931 try:
936 self.fout.write(''.join(msgs))
932 self.fout.write(''.join(msgs))
937 except IOError as err:
933 except IOError as err:
938 raise error.StdioError(err)
934 raise error.StdioError(err)
939 finally:
935 finally:
940 self._blockedtimes['stdio_blocked'] += \
936 self._blockedtimes['stdio_blocked'] += \
941 (util.timer() - starttime) * 1000
937 (util.timer() - starttime) * 1000
942
938
943 def write_err(self, *args, **opts):
939 def write_err(self, *args, **opts):
944 self._progclear()
940 self._progclear()
945 if self._bufferstates and self._bufferstates[-1][0]:
941 if self._bufferstates and self._bufferstates[-1][0]:
946 self.write(*args, **opts)
942 self.write(*args, **opts)
947 elif self._colormode == 'win32':
943 elif self._colormode == 'win32':
948 # windows color printing is its own can of crab, defer to
944 # windows color printing is its own can of crab, defer to
949 # the color module and that is it.
945 # the color module and that is it.
950 color.win32print(self, self._write_err, *args, **opts)
946 color.win32print(self, self._write_err, *args, **opts)
951 else:
947 else:
952 msgs = args
948 msgs = args
953 if self._colormode is not None:
949 if self._colormode is not None:
954 label = opts.get(r'label', '')
950 label = opts.get(r'label', '')
955 msgs = [self.label(a, label) for a in args]
951 msgs = [self.label(a, label) for a in args]
956 self._write_err(*msgs, **opts)
952 self._write_err(*msgs, **opts)
957
953
958 def _write_err(self, *msgs, **opts):
954 def _write_err(self, *msgs, **opts):
959 try:
955 try:
960 with self.timeblockedsection('stdio'):
956 with self.timeblockedsection('stdio'):
961 if not getattr(self.fout, 'closed', False):
957 if not getattr(self.fout, 'closed', False):
962 self.fout.flush()
958 self.fout.flush()
963 for a in msgs:
959 for a in msgs:
964 self.ferr.write(a)
960 self.ferr.write(a)
965 # stderr may be buffered under win32 when redirected to files,
961 # stderr may be buffered under win32 when redirected to files,
966 # including stdout.
962 # including stdout.
967 if not getattr(self.ferr, 'closed', False):
963 if not getattr(self.ferr, 'closed', False):
968 self.ferr.flush()
964 self.ferr.flush()
969 except IOError as inst:
965 except IOError as inst:
970 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
966 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
971 raise error.StdioError(inst)
967 raise error.StdioError(inst)
972
968
973 def flush(self):
969 def flush(self):
974 # opencode timeblockedsection because this is a critical path
970 # opencode timeblockedsection because this is a critical path
975 starttime = util.timer()
971 starttime = util.timer()
976 try:
972 try:
977 try:
973 try:
978 self.fout.flush()
974 self.fout.flush()
979 except IOError as err:
975 except IOError as err:
980 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
976 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
981 raise error.StdioError(err)
977 raise error.StdioError(err)
982 finally:
978 finally:
983 try:
979 try:
984 self.ferr.flush()
980 self.ferr.flush()
985 except IOError as err:
981 except IOError as err:
986 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
982 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
987 raise error.StdioError(err)
983 raise error.StdioError(err)
988 finally:
984 finally:
989 self._blockedtimes['stdio_blocked'] += \
985 self._blockedtimes['stdio_blocked'] += \
990 (util.timer() - starttime) * 1000
986 (util.timer() - starttime) * 1000
991
987
992 def _isatty(self, fh):
988 def _isatty(self, fh):
993 if self.configbool('ui', 'nontty'):
989 if self.configbool('ui', 'nontty'):
994 return False
990 return False
995 return procutil.isatty(fh)
991 return procutil.isatty(fh)
996
992
997 def disablepager(self):
993 def disablepager(self):
998 self._disablepager = True
994 self._disablepager = True
999
995
1000 def pager(self, command):
996 def pager(self, command):
1001 """Start a pager for subsequent command output.
997 """Start a pager for subsequent command output.
1002
998
1003 Commands which produce a long stream of output should call
999 Commands which produce a long stream of output should call
1004 this function to activate the user's preferred pagination
1000 this function to activate the user's preferred pagination
1005 mechanism (which may be no pager). Calling this function
1001 mechanism (which may be no pager). Calling this function
1006 precludes any future use of interactive functionality, such as
1002 precludes any future use of interactive functionality, such as
1007 prompting the user or activating curses.
1003 prompting the user or activating curses.
1008
1004
1009 Args:
1005 Args:
1010 command: The full, non-aliased name of the command. That is, "log"
1006 command: The full, non-aliased name of the command. That is, "log"
1011 not "history, "summary" not "summ", etc.
1007 not "history, "summary" not "summ", etc.
1012 """
1008 """
1013 if (self._disablepager
1009 if (self._disablepager
1014 or self.pageractive):
1010 or self.pageractive):
1015 # how pager should do is already determined
1011 # how pager should do is already determined
1016 return
1012 return
1017
1013
1018 if not command.startswith('internal-always-') and (
1014 if not command.startswith('internal-always-') and (
1019 # explicit --pager=on (= 'internal-always-' prefix) should
1015 # explicit --pager=on (= 'internal-always-' prefix) should
1020 # take precedence over disabling factors below
1016 # take precedence over disabling factors below
1021 command in self.configlist('pager', 'ignore')
1017 command in self.configlist('pager', 'ignore')
1022 or not self.configbool('ui', 'paginate')
1018 or not self.configbool('ui', 'paginate')
1023 or not self.configbool('pager', 'attend-' + command, True)
1019 or not self.configbool('pager', 'attend-' + command, True)
1024 # TODO: if we want to allow HGPLAINEXCEPT=pager,
1020 # TODO: if we want to allow HGPLAINEXCEPT=pager,
1025 # formatted() will need some adjustment.
1021 # formatted() will need some adjustment.
1026 or not self.formatted()
1022 or not self.formatted()
1027 or self.plain()
1023 or self.plain()
1028 or self._buffers
1024 or self._buffers
1029 # TODO: expose debugger-enabled on the UI object
1025 # TODO: expose debugger-enabled on the UI object
1030 or '--debugger' in pycompat.sysargv):
1026 or '--debugger' in pycompat.sysargv):
1031 # We only want to paginate if the ui appears to be
1027 # We only want to paginate if the ui appears to be
1032 # interactive, the user didn't say HGPLAIN or
1028 # interactive, the user didn't say HGPLAIN or
1033 # HGPLAINEXCEPT=pager, and the user didn't specify --debug.
1029 # HGPLAINEXCEPT=pager, and the user didn't specify --debug.
1034 return
1030 return
1035
1031
1036 pagercmd = self.config('pager', 'pager', rcutil.fallbackpager)
1032 pagercmd = self.config('pager', 'pager', rcutil.fallbackpager)
1037 if not pagercmd:
1033 if not pagercmd:
1038 return
1034 return
1039
1035
1040 pagerenv = {}
1036 pagerenv = {}
1041 for name, value in rcutil.defaultpagerenv().items():
1037 for name, value in rcutil.defaultpagerenv().items():
1042 if name not in encoding.environ:
1038 if name not in encoding.environ:
1043 pagerenv[name] = value
1039 pagerenv[name] = value
1044
1040
1045 self.debug('starting pager for command %r\n' % command)
1041 self.debug('starting pager for command %r\n' % command)
1046 self.flush()
1042 self.flush()
1047
1043
1048 wasformatted = self.formatted()
1044 wasformatted = self.formatted()
1049 if util.safehasattr(signal, "SIGPIPE"):
1045 if util.safehasattr(signal, "SIGPIPE"):
1050 signal.signal(signal.SIGPIPE, _catchterm)
1046 signal.signal(signal.SIGPIPE, _catchterm)
1051 if self._runpager(pagercmd, pagerenv):
1047 if self._runpager(pagercmd, pagerenv):
1052 self.pageractive = True
1048 self.pageractive = True
1053 # Preserve the formatted-ness of the UI. This is important
1049 # Preserve the formatted-ness of the UI. This is important
1054 # because we mess with stdout, which might confuse
1050 # because we mess with stdout, which might confuse
1055 # auto-detection of things being formatted.
1051 # auto-detection of things being formatted.
1056 self.setconfig('ui', 'formatted', wasformatted, 'pager')
1052 self.setconfig('ui', 'formatted', wasformatted, 'pager')
1057 self.setconfig('ui', 'interactive', False, 'pager')
1053 self.setconfig('ui', 'interactive', False, 'pager')
1058
1054
1059 # If pagermode differs from color.mode, reconfigure color now that
1055 # If pagermode differs from color.mode, reconfigure color now that
1060 # pageractive is set.
1056 # pageractive is set.
1061 cm = self._colormode
1057 cm = self._colormode
1062 if cm != self.config('color', 'pagermode', cm):
1058 if cm != self.config('color', 'pagermode', cm):
1063 color.setup(self)
1059 color.setup(self)
1064 else:
1060 else:
1065 # If the pager can't be spawned in dispatch when --pager=on is
1061 # If the pager can't be spawned in dispatch when --pager=on is
1066 # given, don't try again when the command runs, to avoid a duplicate
1062 # given, don't try again when the command runs, to avoid a duplicate
1067 # warning about a missing pager command.
1063 # warning about a missing pager command.
1068 self.disablepager()
1064 self.disablepager()
1069
1065
1070 def _runpager(self, command, env=None):
1066 def _runpager(self, command, env=None):
1071 """Actually start the pager and set up file descriptors.
1067 """Actually start the pager and set up file descriptors.
1072
1068
1073 This is separate in part so that extensions (like chg) can
1069 This is separate in part so that extensions (like chg) can
1074 override how a pager is invoked.
1070 override how a pager is invoked.
1075 """
1071 """
1076 if command == 'cat':
1072 if command == 'cat':
1077 # Save ourselves some work.
1073 # Save ourselves some work.
1078 return False
1074 return False
1079 # If the command doesn't contain any of these characters, we
1075 # If the command doesn't contain any of these characters, we
1080 # assume it's a binary and exec it directly. This means for
1076 # assume it's a binary and exec it directly. This means for
1081 # simple pager command configurations, we can degrade
1077 # simple pager command configurations, we can degrade
1082 # gracefully and tell the user about their broken pager.
1078 # gracefully and tell the user about their broken pager.
1083 shell = any(c in command for c in "|&;<>()$`\\\"' \t\n*?[#~=%")
1079 shell = any(c in command for c in "|&;<>()$`\\\"' \t\n*?[#~=%")
1084
1080
1085 if pycompat.iswindows and not shell:
1081 if pycompat.iswindows and not shell:
1086 # Window's built-in `more` cannot be invoked with shell=False, but
1082 # Window's built-in `more` cannot be invoked with shell=False, but
1087 # its `more.com` can. Hide this implementation detail from the
1083 # its `more.com` can. Hide this implementation detail from the
1088 # user so we can also get sane bad PAGER behavior. MSYS has
1084 # user so we can also get sane bad PAGER behavior. MSYS has
1089 # `more.exe`, so do a cmd.exe style resolution of the executable to
1085 # `more.exe`, so do a cmd.exe style resolution of the executable to
1090 # determine which one to use.
1086 # determine which one to use.
1091 fullcmd = procutil.findexe(command)
1087 fullcmd = procutil.findexe(command)
1092 if not fullcmd:
1088 if not fullcmd:
1093 self.warn(_("missing pager command '%s', skipping pager\n")
1089 self.warn(_("missing pager command '%s', skipping pager\n")
1094 % command)
1090 % command)
1095 return False
1091 return False
1096
1092
1097 command = fullcmd
1093 command = fullcmd
1098
1094
1099 try:
1095 try:
1100 pager = subprocess.Popen(
1096 pager = subprocess.Popen(
1101 command, shell=shell, bufsize=-1,
1097 command, shell=shell, bufsize=-1,
1102 close_fds=procutil.closefds, stdin=subprocess.PIPE,
1098 close_fds=procutil.closefds, stdin=subprocess.PIPE,
1103 stdout=procutil.stdout, stderr=procutil.stderr,
1099 stdout=procutil.stdout, stderr=procutil.stderr,
1104 env=procutil.shellenviron(env))
1100 env=procutil.shellenviron(env))
1105 except OSError as e:
1101 except OSError as e:
1106 if e.errno == errno.ENOENT and not shell:
1102 if e.errno == errno.ENOENT and not shell:
1107 self.warn(_("missing pager command '%s', skipping pager\n")
1103 self.warn(_("missing pager command '%s', skipping pager\n")
1108 % command)
1104 % command)
1109 return False
1105 return False
1110 raise
1106 raise
1111
1107
1112 # back up original file descriptors
1108 # back up original file descriptors
1113 stdoutfd = os.dup(procutil.stdout.fileno())
1109 stdoutfd = os.dup(procutil.stdout.fileno())
1114 stderrfd = os.dup(procutil.stderr.fileno())
1110 stderrfd = os.dup(procutil.stderr.fileno())
1115
1111
1116 os.dup2(pager.stdin.fileno(), procutil.stdout.fileno())
1112 os.dup2(pager.stdin.fileno(), procutil.stdout.fileno())
1117 if self._isatty(procutil.stderr):
1113 if self._isatty(procutil.stderr):
1118 os.dup2(pager.stdin.fileno(), procutil.stderr.fileno())
1114 os.dup2(pager.stdin.fileno(), procutil.stderr.fileno())
1119
1115
1120 @self.atexit
1116 @self.atexit
1121 def killpager():
1117 def killpager():
1122 if util.safehasattr(signal, "SIGINT"):
1118 if util.safehasattr(signal, "SIGINT"):
1123 signal.signal(signal.SIGINT, signal.SIG_IGN)
1119 signal.signal(signal.SIGINT, signal.SIG_IGN)
1124 # restore original fds, closing pager.stdin copies in the process
1120 # restore original fds, closing pager.stdin copies in the process
1125 os.dup2(stdoutfd, procutil.stdout.fileno())
1121 os.dup2(stdoutfd, procutil.stdout.fileno())
1126 os.dup2(stderrfd, procutil.stderr.fileno())
1122 os.dup2(stderrfd, procutil.stderr.fileno())
1127 pager.stdin.close()
1123 pager.stdin.close()
1128 pager.wait()
1124 pager.wait()
1129
1125
1130 return True
1126 return True
1131
1127
1132 @property
1128 @property
1133 def _exithandlers(self):
1129 def _exithandlers(self):
1134 return _reqexithandlers
1130 return _reqexithandlers
1135
1131
1136 def atexit(self, func, *args, **kwargs):
1132 def atexit(self, func, *args, **kwargs):
1137 '''register a function to run after dispatching a request
1133 '''register a function to run after dispatching a request
1138
1134
1139 Handlers do not stay registered across request boundaries.'''
1135 Handlers do not stay registered across request boundaries.'''
1140 self._exithandlers.append((func, args, kwargs))
1136 self._exithandlers.append((func, args, kwargs))
1141 return func
1137 return func
1142
1138
1143 def interface(self, feature):
1139 def interface(self, feature):
1144 """what interface to use for interactive console features?
1140 """what interface to use for interactive console features?
1145
1141
1146 The interface is controlled by the value of `ui.interface` but also by
1142 The interface is controlled by the value of `ui.interface` but also by
1147 the value of feature-specific configuration. For example:
1143 the value of feature-specific configuration. For example:
1148
1144
1149 ui.interface.histedit = text
1145 ui.interface.histedit = text
1150 ui.interface.chunkselector = curses
1146 ui.interface.chunkselector = curses
1151
1147
1152 Here the features are "histedit" and "chunkselector".
1148 Here the features are "histedit" and "chunkselector".
1153
1149
1154 The configuration above means that the default interfaces for commands
1150 The configuration above means that the default interfaces for commands
1155 is curses, the interface for histedit is text and the interface for
1151 is curses, the interface for histedit is text and the interface for
1156 selecting chunk is crecord (the best curses interface available).
1152 selecting chunk is crecord (the best curses interface available).
1157
1153
1158 Consider the following example:
1154 Consider the following example:
1159 ui.interface = curses
1155 ui.interface = curses
1160 ui.interface.histedit = text
1156 ui.interface.histedit = text
1161
1157
1162 Then histedit will use the text interface and chunkselector will use
1158 Then histedit will use the text interface and chunkselector will use
1163 the default curses interface (crecord at the moment).
1159 the default curses interface (crecord at the moment).
1164 """
1160 """
1165 alldefaults = frozenset(["text", "curses"])
1161 alldefaults = frozenset(["text", "curses"])
1166
1162
1167 featureinterfaces = {
1163 featureinterfaces = {
1168 "chunkselector": [
1164 "chunkselector": [
1169 "text",
1165 "text",
1170 "curses",
1166 "curses",
1171 ]
1167 ]
1172 }
1168 }
1173
1169
1174 # Feature-specific interface
1170 # Feature-specific interface
1175 if feature not in featureinterfaces.keys():
1171 if feature not in featureinterfaces.keys():
1176 # Programming error, not user error
1172 # Programming error, not user error
1177 raise ValueError("Unknown feature requested %s" % feature)
1173 raise ValueError("Unknown feature requested %s" % feature)
1178
1174
1179 availableinterfaces = frozenset(featureinterfaces[feature])
1175 availableinterfaces = frozenset(featureinterfaces[feature])
1180 if alldefaults > availableinterfaces:
1176 if alldefaults > availableinterfaces:
1181 # Programming error, not user error. We need a use case to
1177 # Programming error, not user error. We need a use case to
1182 # define the right thing to do here.
1178 # define the right thing to do here.
1183 raise ValueError(
1179 raise ValueError(
1184 "Feature %s does not handle all default interfaces" %
1180 "Feature %s does not handle all default interfaces" %
1185 feature)
1181 feature)
1186
1182
1187 if self.plain():
1183 if self.plain():
1188 return "text"
1184 return "text"
1189
1185
1190 # Default interface for all the features
1186 # Default interface for all the features
1191 defaultinterface = "text"
1187 defaultinterface = "text"
1192 i = self.config("ui", "interface")
1188 i = self.config("ui", "interface")
1193 if i in alldefaults:
1189 if i in alldefaults:
1194 defaultinterface = i
1190 defaultinterface = i
1195
1191
1196 choseninterface = defaultinterface
1192 choseninterface = defaultinterface
1197 f = self.config("ui", "interface.%s" % feature)
1193 f = self.config("ui", "interface.%s" % feature)
1198 if f in availableinterfaces:
1194 if f in availableinterfaces:
1199 choseninterface = f
1195 choseninterface = f
1200
1196
1201 if i is not None and defaultinterface != i:
1197 if i is not None and defaultinterface != i:
1202 if f is not None:
1198 if f is not None:
1203 self.warn(_("invalid value for ui.interface: %s\n") %
1199 self.warn(_("invalid value for ui.interface: %s\n") %
1204 (i,))
1200 (i,))
1205 else:
1201 else:
1206 self.warn(_("invalid value for ui.interface: %s (using %s)\n") %
1202 self.warn(_("invalid value for ui.interface: %s (using %s)\n") %
1207 (i, choseninterface))
1203 (i, choseninterface))
1208 if f is not None and choseninterface != f:
1204 if f is not None and choseninterface != f:
1209 self.warn(_("invalid value for ui.interface.%s: %s (using %s)\n") %
1205 self.warn(_("invalid value for ui.interface.%s: %s (using %s)\n") %
1210 (feature, f, choseninterface))
1206 (feature, f, choseninterface))
1211
1207
1212 return choseninterface
1208 return choseninterface
1213
1209
1214 def interactive(self):
1210 def interactive(self):
1215 '''is interactive input allowed?
1211 '''is interactive input allowed?
1216
1212
1217 An interactive session is a session where input can be reasonably read
1213 An interactive session is a session where input can be reasonably read
1218 from `sys.stdin'. If this function returns false, any attempt to read
1214 from `sys.stdin'. If this function returns false, any attempt to read
1219 from stdin should fail with an error, unless a sensible default has been
1215 from stdin should fail with an error, unless a sensible default has been
1220 specified.
1216 specified.
1221
1217
1222 Interactiveness is triggered by the value of the `ui.interactive'
1218 Interactiveness is triggered by the value of the `ui.interactive'
1223 configuration variable or - if it is unset - when `sys.stdin' points
1219 configuration variable or - if it is unset - when `sys.stdin' points
1224 to a terminal device.
1220 to a terminal device.
1225
1221
1226 This function refers to input only; for output, see `ui.formatted()'.
1222 This function refers to input only; for output, see `ui.formatted()'.
1227 '''
1223 '''
1228 i = self.configbool("ui", "interactive")
1224 i = self.configbool("ui", "interactive")
1229 if i is None:
1225 if i is None:
1230 # some environments replace stdin without implementing isatty
1226 # some environments replace stdin without implementing isatty
1231 # usually those are non-interactive
1227 # usually those are non-interactive
1232 return self._isatty(self.fin)
1228 return self._isatty(self.fin)
1233
1229
1234 return i
1230 return i
1235
1231
1236 def termwidth(self):
1232 def termwidth(self):
1237 '''how wide is the terminal in columns?
1233 '''how wide is the terminal in columns?
1238 '''
1234 '''
1239 if 'COLUMNS' in encoding.environ:
1235 if 'COLUMNS' in encoding.environ:
1240 try:
1236 try:
1241 return int(encoding.environ['COLUMNS'])
1237 return int(encoding.environ['COLUMNS'])
1242 except ValueError:
1238 except ValueError:
1243 pass
1239 pass
1244 return scmutil.termsize(self)[0]
1240 return scmutil.termsize(self)[0]
1245
1241
1246 def formatted(self):
1242 def formatted(self):
1247 '''should formatted output be used?
1243 '''should formatted output be used?
1248
1244
1249 It is often desirable to format the output to suite the output medium.
1245 It is often desirable to format the output to suite the output medium.
1250 Examples of this are truncating long lines or colorizing messages.
1246 Examples of this are truncating long lines or colorizing messages.
1251 However, this is not often not desirable when piping output into other
1247 However, this is not often not desirable when piping output into other
1252 utilities, e.g. `grep'.
1248 utilities, e.g. `grep'.
1253
1249
1254 Formatted output is triggered by the value of the `ui.formatted'
1250 Formatted output is triggered by the value of the `ui.formatted'
1255 configuration variable or - if it is unset - when `sys.stdout' points
1251 configuration variable or - if it is unset - when `sys.stdout' points
1256 to a terminal device. Please note that `ui.formatted' should be
1252 to a terminal device. Please note that `ui.formatted' should be
1257 considered an implementation detail; it is not intended for use outside
1253 considered an implementation detail; it is not intended for use outside
1258 Mercurial or its extensions.
1254 Mercurial or its extensions.
1259
1255
1260 This function refers to output only; for input, see `ui.interactive()'.
1256 This function refers to output only; for input, see `ui.interactive()'.
1261 This function always returns false when in plain mode, see `ui.plain()'.
1257 This function always returns false when in plain mode, see `ui.plain()'.
1262 '''
1258 '''
1263 if self.plain():
1259 if self.plain():
1264 return False
1260 return False
1265
1261
1266 i = self.configbool("ui", "formatted")
1262 i = self.configbool("ui", "formatted")
1267 if i is None:
1263 if i is None:
1268 # some environments replace stdout without implementing isatty
1264 # some environments replace stdout without implementing isatty
1269 # usually those are non-interactive
1265 # usually those are non-interactive
1270 return self._isatty(self.fout)
1266 return self._isatty(self.fout)
1271
1267
1272 return i
1268 return i
1273
1269
1274 def _readline(self):
1270 def _readline(self):
1275 # Replacing stdin/stdout temporarily is a hard problem on Python 3
1271 # Replacing stdin/stdout temporarily is a hard problem on Python 3
1276 # because they have to be text streams with *no buffering*. Instead,
1272 # because they have to be text streams with *no buffering*. Instead,
1277 # we use rawinput() only if call_readline() will be invoked by
1273 # we use rawinput() only if call_readline() will be invoked by
1278 # PyOS_Readline(), so no I/O will be made at Python layer.
1274 # PyOS_Readline(), so no I/O will be made at Python layer.
1279 usereadline = (self._isatty(self.fin) and self._isatty(self.fout)
1275 usereadline = (self._isatty(self.fin) and self._isatty(self.fout)
1280 and procutil.isstdin(self.fin)
1276 and procutil.isstdin(self.fin)
1281 and procutil.isstdout(self.fout))
1277 and procutil.isstdout(self.fout))
1282 if usereadline:
1278 if usereadline:
1283 try:
1279 try:
1284 # magically add command line editing support, where
1280 # magically add command line editing support, where
1285 # available
1281 # available
1286 import readline
1282 import readline
1287 # force demandimport to really load the module
1283 # force demandimport to really load the module
1288 readline.read_history_file
1284 readline.read_history_file
1289 # windows sometimes raises something other than ImportError
1285 # windows sometimes raises something other than ImportError
1290 except Exception:
1286 except Exception:
1291 usereadline = False
1287 usereadline = False
1292
1288
1293 # prompt ' ' must exist; otherwise readline may delete entire line
1289 # prompt ' ' must exist; otherwise readline may delete entire line
1294 # - http://bugs.python.org/issue12833
1290 # - http://bugs.python.org/issue12833
1295 with self.timeblockedsection('stdio'):
1291 with self.timeblockedsection('stdio'):
1296 if usereadline:
1292 if usereadline:
1297 line = encoding.strtolocal(pycompat.rawinput(r' '))
1293 line = encoding.strtolocal(pycompat.rawinput(r' '))
1298 # When stdin is in binary mode on Windows, it can cause
1294 # When stdin is in binary mode on Windows, it can cause
1299 # raw_input() to emit an extra trailing carriage return
1295 # raw_input() to emit an extra trailing carriage return
1300 if pycompat.oslinesep == b'\r\n' and line.endswith(b'\r'):
1296 if pycompat.oslinesep == b'\r\n' and line.endswith(b'\r'):
1301 line = line[:-1]
1297 line = line[:-1]
1302 else:
1298 else:
1303 self.fout.write(b' ')
1299 self.fout.write(b' ')
1304 self.fout.flush()
1300 self.fout.flush()
1305 line = self.fin.readline()
1301 line = self.fin.readline()
1306 if not line:
1302 if not line:
1307 raise EOFError
1303 raise EOFError
1308 line = line.rstrip(pycompat.oslinesep)
1304 line = line.rstrip(pycompat.oslinesep)
1309
1305
1310 return line
1306 return line
1311
1307
1312 def prompt(self, msg, default="y"):
1308 def prompt(self, msg, default="y"):
1313 """Prompt user with msg, read response.
1309 """Prompt user with msg, read response.
1314 If ui is not interactive, the default is returned.
1310 If ui is not interactive, the default is returned.
1315 """
1311 """
1316 if not self.interactive():
1312 if not self.interactive():
1317 self.write(msg, ' ', default or '', "\n")
1313 self.write(msg, ' ', default or '', "\n")
1318 return default
1314 return default
1319 self._writenobuf(msg, label='ui.prompt')
1315 self._writenobuf(msg, label='ui.prompt')
1320 self.flush()
1316 self.flush()
1321 try:
1317 try:
1322 r = self._readline()
1318 r = self._readline()
1323 if not r:
1319 if not r:
1324 r = default
1320 r = default
1325 if self.configbool('ui', 'promptecho'):
1321 if self.configbool('ui', 'promptecho'):
1326 self.write(r, "\n")
1322 self.write(r, "\n")
1327 return r
1323 return r
1328 except EOFError:
1324 except EOFError:
1329 raise error.ResponseExpected()
1325 raise error.ResponseExpected()
1330
1326
1331 @staticmethod
1327 @staticmethod
1332 def extractchoices(prompt):
1328 def extractchoices(prompt):
1333 """Extract prompt message and list of choices from specified prompt.
1329 """Extract prompt message and list of choices from specified prompt.
1334
1330
1335 This returns tuple "(message, choices)", and "choices" is the
1331 This returns tuple "(message, choices)", and "choices" is the
1336 list of tuple "(response character, text without &)".
1332 list of tuple "(response character, text without &)".
1337
1333
1338 >>> ui.extractchoices(b"awake? $$ &Yes $$ &No")
1334 >>> ui.extractchoices(b"awake? $$ &Yes $$ &No")
1339 ('awake? ', [('y', 'Yes'), ('n', 'No')])
1335 ('awake? ', [('y', 'Yes'), ('n', 'No')])
1340 >>> ui.extractchoices(b"line\\nbreak? $$ &Yes $$ &No")
1336 >>> ui.extractchoices(b"line\\nbreak? $$ &Yes $$ &No")
1341 ('line\\nbreak? ', [('y', 'Yes'), ('n', 'No')])
1337 ('line\\nbreak? ', [('y', 'Yes'), ('n', 'No')])
1342 >>> ui.extractchoices(b"want lots of $$money$$?$$Ye&s$$N&o")
1338 >>> ui.extractchoices(b"want lots of $$money$$?$$Ye&s$$N&o")
1343 ('want lots of $$money$$?', [('s', 'Yes'), ('o', 'No')])
1339 ('want lots of $$money$$?', [('s', 'Yes'), ('o', 'No')])
1344 """
1340 """
1345
1341
1346 # Sadly, the prompt string may have been built with a filename
1342 # Sadly, the prompt string may have been built with a filename
1347 # containing "$$" so let's try to find the first valid-looking
1343 # containing "$$" so let's try to find the first valid-looking
1348 # prompt to start parsing. Sadly, we also can't rely on
1344 # prompt to start parsing. Sadly, we also can't rely on
1349 # choices containing spaces, ASCII, or basically anything
1345 # choices containing spaces, ASCII, or basically anything
1350 # except an ampersand followed by a character.
1346 # except an ampersand followed by a character.
1351 m = re.match(br'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt)
1347 m = re.match(br'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt)
1352 msg = m.group(1)
1348 msg = m.group(1)
1353 choices = [p.strip(' ') for p in m.group(2).split('$$')]
1349 choices = [p.strip(' ') for p in m.group(2).split('$$')]
1354 def choicetuple(s):
1350 def choicetuple(s):
1355 ampidx = s.index('&')
1351 ampidx = s.index('&')
1356 return s[ampidx + 1:ampidx + 2].lower(), s.replace('&', '', 1)
1352 return s[ampidx + 1:ampidx + 2].lower(), s.replace('&', '', 1)
1357 return (msg, [choicetuple(s) for s in choices])
1353 return (msg, [choicetuple(s) for s in choices])
1358
1354
1359 def promptchoice(self, prompt, default=0):
1355 def promptchoice(self, prompt, default=0):
1360 """Prompt user with a message, read response, and ensure it matches
1356 """Prompt user with a message, read response, and ensure it matches
1361 one of the provided choices. The prompt is formatted as follows:
1357 one of the provided choices. The prompt is formatted as follows:
1362
1358
1363 "would you like fries with that (Yn)? $$ &Yes $$ &No"
1359 "would you like fries with that (Yn)? $$ &Yes $$ &No"
1364
1360
1365 The index of the choice is returned. Responses are case
1361 The index of the choice is returned. Responses are case
1366 insensitive. If ui is not interactive, the default is
1362 insensitive. If ui is not interactive, the default is
1367 returned.
1363 returned.
1368 """
1364 """
1369
1365
1370 msg, choices = self.extractchoices(prompt)
1366 msg, choices = self.extractchoices(prompt)
1371 resps = [r for r, t in choices]
1367 resps = [r for r, t in choices]
1372 while True:
1368 while True:
1373 r = self.prompt(msg, resps[default])
1369 r = self.prompt(msg, resps[default])
1374 if r.lower() in resps:
1370 if r.lower() in resps:
1375 return resps.index(r.lower())
1371 return resps.index(r.lower())
1376 self.write(_("unrecognized response\n"))
1372 self.write(_("unrecognized response\n"))
1377
1373
1378 def getpass(self, prompt=None, default=None):
1374 def getpass(self, prompt=None, default=None):
1379 if not self.interactive():
1375 if not self.interactive():
1380 return default
1376 return default
1381 try:
1377 try:
1382 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
1378 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
1383 # disable getpass() only if explicitly specified. it's still valid
1379 # disable getpass() only if explicitly specified. it's still valid
1384 # to interact with tty even if fin is not a tty.
1380 # to interact with tty even if fin is not a tty.
1385 with self.timeblockedsection('stdio'):
1381 with self.timeblockedsection('stdio'):
1386 if self.configbool('ui', 'nontty'):
1382 if self.configbool('ui', 'nontty'):
1387 l = self.fin.readline()
1383 l = self.fin.readline()
1388 if not l:
1384 if not l:
1389 raise EOFError
1385 raise EOFError
1390 return l.rstrip('\n')
1386 return l.rstrip('\n')
1391 else:
1387 else:
1392 return getpass.getpass('')
1388 return getpass.getpass('')
1393 except EOFError:
1389 except EOFError:
1394 raise error.ResponseExpected()
1390 raise error.ResponseExpected()
1395 def status(self, *msg, **opts):
1391 def status(self, *msg, **opts):
1396 '''write status message to output (if ui.quiet is False)
1392 '''write status message to output (if ui.quiet is False)
1397
1393
1398 This adds an output label of "ui.status".
1394 This adds an output label of "ui.status".
1399 '''
1395 '''
1400 if not self.quiet:
1396 if not self.quiet:
1401 opts[r'label'] = opts.get(r'label', '') + ' ui.status'
1397 opts[r'label'] = opts.get(r'label', '') + ' ui.status'
1402 self.write(*msg, **opts)
1398 self.write(*msg, **opts)
1403 def warn(self, *msg, **opts):
1399 def warn(self, *msg, **opts):
1404 '''write warning message to output (stderr)
1400 '''write warning message to output (stderr)
1405
1401
1406 This adds an output label of "ui.warning".
1402 This adds an output label of "ui.warning".
1407 '''
1403 '''
1408 opts[r'label'] = opts.get(r'label', '') + ' ui.warning'
1404 opts[r'label'] = opts.get(r'label', '') + ' ui.warning'
1409 self.write_err(*msg, **opts)
1405 self.write_err(*msg, **opts)
1410 def note(self, *msg, **opts):
1406 def note(self, *msg, **opts):
1411 '''write note to output (if ui.verbose is True)
1407 '''write note to output (if ui.verbose is True)
1412
1408
1413 This adds an output label of "ui.note".
1409 This adds an output label of "ui.note".
1414 '''
1410 '''
1415 if self.verbose:
1411 if self.verbose:
1416 opts[r'label'] = opts.get(r'label', '') + ' ui.note'
1412 opts[r'label'] = opts.get(r'label', '') + ' ui.note'
1417 self.write(*msg, **opts)
1413 self.write(*msg, **opts)
1418 def debug(self, *msg, **opts):
1414 def debug(self, *msg, **opts):
1419 '''write debug message to output (if ui.debugflag is True)
1415 '''write debug message to output (if ui.debugflag is True)
1420
1416
1421 This adds an output label of "ui.debug".
1417 This adds an output label of "ui.debug".
1422 '''
1418 '''
1423 if self.debugflag:
1419 if self.debugflag:
1424 opts[r'label'] = opts.get(r'label', '') + ' ui.debug'
1420 opts[r'label'] = opts.get(r'label', '') + ' ui.debug'
1425 self.write(*msg, **opts)
1421 self.write(*msg, **opts)
1426
1422
1427 def edit(self, text, user, extra=None, editform=None, pending=None,
1423 def edit(self, text, user, extra=None, editform=None, pending=None,
1428 repopath=None, action=None):
1424 repopath=None, action=None):
1429 if action is None:
1425 if action is None:
1430 self.develwarn('action is None but will soon be a required '
1426 self.develwarn('action is None but will soon be a required '
1431 'parameter to ui.edit()')
1427 'parameter to ui.edit()')
1432 extra_defaults = {
1428 extra_defaults = {
1433 'prefix': 'editor',
1429 'prefix': 'editor',
1434 'suffix': '.txt',
1430 'suffix': '.txt',
1435 }
1431 }
1436 if extra is not None:
1432 if extra is not None:
1437 if extra.get('suffix') is not None:
1433 if extra.get('suffix') is not None:
1438 self.develwarn('extra.suffix is not None but will soon be '
1434 self.develwarn('extra.suffix is not None but will soon be '
1439 'ignored by ui.edit()')
1435 'ignored by ui.edit()')
1440 extra_defaults.update(extra)
1436 extra_defaults.update(extra)
1441 extra = extra_defaults
1437 extra = extra_defaults
1442
1438
1443 if action == 'diff':
1439 if action == 'diff':
1444 suffix = '.diff'
1440 suffix = '.diff'
1445 elif action:
1441 elif action:
1446 suffix = '.%s.hg.txt' % action
1442 suffix = '.%s.hg.txt' % action
1447 else:
1443 else:
1448 suffix = extra['suffix']
1444 suffix = extra['suffix']
1449
1445
1450 rdir = None
1446 rdir = None
1451 if self.configbool('experimental', 'editortmpinhg'):
1447 if self.configbool('experimental', 'editortmpinhg'):
1452 rdir = repopath
1448 rdir = repopath
1453 (fd, name) = tempfile.mkstemp(prefix='hg-' + extra['prefix'] + '-',
1449 (fd, name) = tempfile.mkstemp(prefix='hg-' + extra['prefix'] + '-',
1454 suffix=suffix,
1450 suffix=suffix,
1455 dir=rdir)
1451 dir=rdir)
1456 try:
1452 try:
1457 f = os.fdopen(fd, r'wb')
1453 f = os.fdopen(fd, r'wb')
1458 f.write(util.tonativeeol(text))
1454 f.write(util.tonativeeol(text))
1459 f.close()
1455 f.close()
1460
1456
1461 environ = {'HGUSER': user}
1457 environ = {'HGUSER': user}
1462 if 'transplant_source' in extra:
1458 if 'transplant_source' in extra:
1463 environ.update({'HGREVISION': hex(extra['transplant_source'])})
1459 environ.update({'HGREVISION': hex(extra['transplant_source'])})
1464 for label in ('intermediate-source', 'source', 'rebase_source'):
1460 for label in ('intermediate-source', 'source', 'rebase_source'):
1465 if label in extra:
1461 if label in extra:
1466 environ.update({'HGREVISION': extra[label]})
1462 environ.update({'HGREVISION': extra[label]})
1467 break
1463 break
1468 if editform:
1464 if editform:
1469 environ.update({'HGEDITFORM': editform})
1465 environ.update({'HGEDITFORM': editform})
1470 if pending:
1466 if pending:
1471 environ.update({'HG_PENDING': pending})
1467 environ.update({'HG_PENDING': pending})
1472
1468
1473 editor = self.geteditor()
1469 editor = self.geteditor()
1474
1470
1475 self.system("%s \"%s\"" % (editor, name),
1471 self.system("%s \"%s\"" % (editor, name),
1476 environ=environ,
1472 environ=environ,
1477 onerr=error.Abort, errprefix=_("edit failed"),
1473 onerr=error.Abort, errprefix=_("edit failed"),
1478 blockedtag='editor')
1474 blockedtag='editor')
1479
1475
1480 f = open(name, r'rb')
1476 f = open(name, r'rb')
1481 t = util.fromnativeeol(f.read())
1477 t = util.fromnativeeol(f.read())
1482 f.close()
1478 f.close()
1483 finally:
1479 finally:
1484 os.unlink(name)
1480 os.unlink(name)
1485
1481
1486 return t
1482 return t
1487
1483
1488 def system(self, cmd, environ=None, cwd=None, onerr=None, errprefix=None,
1484 def system(self, cmd, environ=None, cwd=None, onerr=None, errprefix=None,
1489 blockedtag=None):
1485 blockedtag=None):
1490 '''execute shell command with appropriate output stream. command
1486 '''execute shell command with appropriate output stream. command
1491 output will be redirected if fout is not stdout.
1487 output will be redirected if fout is not stdout.
1492
1488
1493 if command fails and onerr is None, return status, else raise onerr
1489 if command fails and onerr is None, return status, else raise onerr
1494 object as exception.
1490 object as exception.
1495 '''
1491 '''
1496 if blockedtag is None:
1492 if blockedtag is None:
1497 # Long cmds tend to be because of an absolute path on cmd. Keep
1493 # Long cmds tend to be because of an absolute path on cmd. Keep
1498 # the tail end instead
1494 # the tail end instead
1499 cmdsuffix = cmd.translate(None, _keepalnum)[-85:]
1495 cmdsuffix = cmd.translate(None, _keepalnum)[-85:]
1500 blockedtag = 'unknown_system_' + cmdsuffix
1496 blockedtag = 'unknown_system_' + cmdsuffix
1501 out = self.fout
1497 out = self.fout
1502 if any(s[1] for s in self._bufferstates):
1498 if any(s[1] for s in self._bufferstates):
1503 out = self
1499 out = self
1504 with self.timeblockedsection(blockedtag):
1500 with self.timeblockedsection(blockedtag):
1505 rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out)
1501 rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out)
1506 if rc and onerr:
1502 if rc and onerr:
1507 errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
1503 errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
1508 procutil.explainexit(rc)[0])
1504 procutil.explainexit(rc)[0])
1509 if errprefix:
1505 if errprefix:
1510 errmsg = '%s: %s' % (errprefix, errmsg)
1506 errmsg = '%s: %s' % (errprefix, errmsg)
1511 raise onerr(errmsg)
1507 raise onerr(errmsg)
1512 return rc
1508 return rc
1513
1509
1514 def _runsystem(self, cmd, environ, cwd, out):
1510 def _runsystem(self, cmd, environ, cwd, out):
1515 """actually execute the given shell command (can be overridden by
1511 """actually execute the given shell command (can be overridden by
1516 extensions like chg)"""
1512 extensions like chg)"""
1517 return procutil.system(cmd, environ=environ, cwd=cwd, out=out)
1513 return procutil.system(cmd, environ=environ, cwd=cwd, out=out)
1518
1514
1519 def traceback(self, exc=None, force=False):
1515 def traceback(self, exc=None, force=False):
1520 '''print exception traceback if traceback printing enabled or forced.
1516 '''print exception traceback if traceback printing enabled or forced.
1521 only to call in exception handler. returns true if traceback
1517 only to call in exception handler. returns true if traceback
1522 printed.'''
1518 printed.'''
1523 if self.tracebackflag or force:
1519 if self.tracebackflag or force:
1524 if exc is None:
1520 if exc is None:
1525 exc = sys.exc_info()
1521 exc = sys.exc_info()
1526 cause = getattr(exc[1], 'cause', None)
1522 cause = getattr(exc[1], 'cause', None)
1527
1523
1528 if cause is not None:
1524 if cause is not None:
1529 causetb = traceback.format_tb(cause[2])
1525 causetb = traceback.format_tb(cause[2])
1530 exctb = traceback.format_tb(exc[2])
1526 exctb = traceback.format_tb(exc[2])
1531 exconly = traceback.format_exception_only(cause[0], cause[1])
1527 exconly = traceback.format_exception_only(cause[0], cause[1])
1532
1528
1533 # exclude frame where 'exc' was chained and rethrown from exctb
1529 # exclude frame where 'exc' was chained and rethrown from exctb
1534 self.write_err('Traceback (most recent call last):\n',
1530 self.write_err('Traceback (most recent call last):\n',
1535 ''.join(exctb[:-1]),
1531 ''.join(exctb[:-1]),
1536 ''.join(causetb),
1532 ''.join(causetb),
1537 ''.join(exconly))
1533 ''.join(exconly))
1538 else:
1534 else:
1539 output = traceback.format_exception(exc[0], exc[1], exc[2])
1535 output = traceback.format_exception(exc[0], exc[1], exc[2])
1540 self.write_err(encoding.strtolocal(r''.join(output)))
1536 self.write_err(encoding.strtolocal(r''.join(output)))
1541 return self.tracebackflag or force
1537 return self.tracebackflag or force
1542
1538
1543 def geteditor(self):
1539 def geteditor(self):
1544 '''return editor to use'''
1540 '''return editor to use'''
1545 if pycompat.sysplatform == 'plan9':
1541 if pycompat.sysplatform == 'plan9':
1546 # vi is the MIPS instruction simulator on Plan 9. We
1542 # vi is the MIPS instruction simulator on Plan 9. We
1547 # instead default to E to plumb commit messages to
1543 # instead default to E to plumb commit messages to
1548 # avoid confusion.
1544 # avoid confusion.
1549 editor = 'E'
1545 editor = 'E'
1550 else:
1546 else:
1551 editor = 'vi'
1547 editor = 'vi'
1552 return (encoding.environ.get("HGEDITOR") or
1548 return (encoding.environ.get("HGEDITOR") or
1553 self.config("ui", "editor", editor))
1549 self.config("ui", "editor", editor))
1554
1550
1555 @util.propertycache
1551 @util.propertycache
1556 def _progbar(self):
1552 def _progbar(self):
1557 """setup the progbar singleton to the ui object"""
1553 """setup the progbar singleton to the ui object"""
1558 if (self.quiet or self.debugflag
1554 if (self.quiet or self.debugflag
1559 or self.configbool('progress', 'disable')
1555 or self.configbool('progress', 'disable')
1560 or not progress.shouldprint(self)):
1556 or not progress.shouldprint(self)):
1561 return None
1557 return None
1562 return getprogbar(self)
1558 return getprogbar(self)
1563
1559
1564 def _progclear(self):
1560 def _progclear(self):
1565 """clear progress bar output if any. use it before any output"""
1561 """clear progress bar output if any. use it before any output"""
1566 if not haveprogbar(): # nothing loaded yet
1562 if not haveprogbar(): # nothing loaded yet
1567 return
1563 return
1568 if self._progbar is not None and self._progbar.printed:
1564 if self._progbar is not None and self._progbar.printed:
1569 self._progbar.clear()
1565 self._progbar.clear()
1570
1566
1571 def progress(self, topic, pos, item="", unit="", total=None):
1567 def progress(self, topic, pos, item="", unit="", total=None):
1572 '''show a progress message
1568 '''show a progress message
1573
1569
1574 By default a textual progress bar will be displayed if an operation
1570 By default a textual progress bar will be displayed if an operation
1575 takes too long. 'topic' is the current operation, 'item' is a
1571 takes too long. 'topic' is the current operation, 'item' is a
1576 non-numeric marker of the current position (i.e. the currently
1572 non-numeric marker of the current position (i.e. the currently
1577 in-process file), 'pos' is the current numeric position (i.e.
1573 in-process file), 'pos' is the current numeric position (i.e.
1578 revision, bytes, etc.), unit is a corresponding unit label,
1574 revision, bytes, etc.), unit is a corresponding unit label,
1579 and total is the highest expected pos.
1575 and total is the highest expected pos.
1580
1576
1581 Multiple nested topics may be active at a time.
1577 Multiple nested topics may be active at a time.
1582
1578
1583 All topics should be marked closed by setting pos to None at
1579 All topics should be marked closed by setting pos to None at
1584 termination.
1580 termination.
1585 '''
1581 '''
1586 if self._progbar is not None:
1582 if self._progbar is not None:
1587 self._progbar.progress(topic, pos, item=item, unit=unit,
1583 self._progbar.progress(topic, pos, item=item, unit=unit,
1588 total=total)
1584 total=total)
1589 if pos is None or not self.configbool('progress', 'debug'):
1585 if pos is None or not self.configbool('progress', 'debug'):
1590 return
1586 return
1591
1587
1592 if unit:
1588 if unit:
1593 unit = ' ' + unit
1589 unit = ' ' + unit
1594 if item:
1590 if item:
1595 item = ' ' + item
1591 item = ' ' + item
1596
1592
1597 if total:
1593 if total:
1598 pct = 100.0 * pos / total
1594 pct = 100.0 * pos / total
1599 self.debug('%s:%s %d/%d%s (%4.2f%%)\n'
1595 self.debug('%s:%s %d/%d%s (%4.2f%%)\n'
1600 % (topic, item, pos, total, unit, pct))
1596 % (topic, item, pos, total, unit, pct))
1601 else:
1597 else:
1602 self.debug('%s:%s %d%s\n' % (topic, item, pos, unit))
1598 self.debug('%s:%s %d%s\n' % (topic, item, pos, unit))
1603
1599
1604 def log(self, service, *msg, **opts):
1600 def log(self, service, *msg, **opts):
1605 '''hook for logging facility extensions
1601 '''hook for logging facility extensions
1606
1602
1607 service should be a readily-identifiable subsystem, which will
1603 service should be a readily-identifiable subsystem, which will
1608 allow filtering.
1604 allow filtering.
1609
1605
1610 *msg should be a newline-terminated format string to log, and
1606 *msg should be a newline-terminated format string to log, and
1611 then any values to %-format into that format string.
1607 then any values to %-format into that format string.
1612
1608
1613 **opts currently has no defined meanings.
1609 **opts currently has no defined meanings.
1614 '''
1610 '''
1615
1611
1616 def label(self, msg, label):
1612 def label(self, msg, label):
1617 '''style msg based on supplied label
1613 '''style msg based on supplied label
1618
1614
1619 If some color mode is enabled, this will add the necessary control
1615 If some color mode is enabled, this will add the necessary control
1620 characters to apply such color. In addition, 'debug' color mode adds
1616 characters to apply such color. In addition, 'debug' color mode adds
1621 markup showing which label affects a piece of text.
1617 markup showing which label affects a piece of text.
1622
1618
1623 ui.write(s, 'label') is equivalent to
1619 ui.write(s, 'label') is equivalent to
1624 ui.write(ui.label(s, 'label')).
1620 ui.write(ui.label(s, 'label')).
1625 '''
1621 '''
1626 if self._colormode is not None:
1622 if self._colormode is not None:
1627 return color.colorlabel(self, msg, label)
1623 return color.colorlabel(self, msg, label)
1628 return msg
1624 return msg
1629
1625
1630 def develwarn(self, msg, stacklevel=1, config=None):
1626 def develwarn(self, msg, stacklevel=1, config=None):
1631 """issue a developer warning message
1627 """issue a developer warning message
1632
1628
1633 Use 'stacklevel' to report the offender some layers further up in the
1629 Use 'stacklevel' to report the offender some layers further up in the
1634 stack.
1630 stack.
1635 """
1631 """
1636 if not self.configbool('devel', 'all-warnings'):
1632 if not self.configbool('devel', 'all-warnings'):
1637 if config is None or not self.configbool('devel', config):
1633 if config is None or not self.configbool('devel', config):
1638 return
1634 return
1639 msg = 'devel-warn: ' + msg
1635 msg = 'devel-warn: ' + msg
1640 stacklevel += 1 # get in develwarn
1636 stacklevel += 1 # get in develwarn
1641 if self.tracebackflag:
1637 if self.tracebackflag:
1642 util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
1638 util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
1643 self.log('develwarn', '%s at:\n%s' %
1639 self.log('develwarn', '%s at:\n%s' %
1644 (msg, ''.join(util.getstackframes(stacklevel))))
1640 (msg, ''.join(util.getstackframes(stacklevel))))
1645 else:
1641 else:
1646 curframe = inspect.currentframe()
1642 curframe = inspect.currentframe()
1647 calframe = inspect.getouterframes(curframe, 2)
1643 calframe = inspect.getouterframes(curframe, 2)
1648 fname, lineno, fmsg = calframe[stacklevel][1:4]
1644 fname, lineno, fmsg = calframe[stacklevel][1:4]
1649 fname, fmsg = pycompat.sysbytes(fname), pycompat.sysbytes(fmsg)
1645 fname, fmsg = pycompat.sysbytes(fname), pycompat.sysbytes(fmsg)
1650 self.write_err('%s at: %s:%d (%s)\n'
1646 self.write_err('%s at: %s:%d (%s)\n'
1651 % (msg, fname, lineno, fmsg))
1647 % (msg, fname, lineno, fmsg))
1652 self.log('develwarn', '%s at: %s:%d (%s)\n',
1648 self.log('develwarn', '%s at: %s:%d (%s)\n',
1653 msg, fname, lineno, fmsg)
1649 msg, fname, lineno, fmsg)
1654 curframe = calframe = None # avoid cycles
1650 curframe = calframe = None # avoid cycles
1655
1651
1656 def deprecwarn(self, msg, version, stacklevel=2):
1652 def deprecwarn(self, msg, version, stacklevel=2):
1657 """issue a deprecation warning
1653 """issue a deprecation warning
1658
1654
1659 - msg: message explaining what is deprecated and how to upgrade,
1655 - msg: message explaining what is deprecated and how to upgrade,
1660 - version: last version where the API will be supported,
1656 - version: last version where the API will be supported,
1661 """
1657 """
1662 if not (self.configbool('devel', 'all-warnings')
1658 if not (self.configbool('devel', 'all-warnings')
1663 or self.configbool('devel', 'deprec-warn')):
1659 or self.configbool('devel', 'deprec-warn')):
1664 return
1660 return
1665 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
1661 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
1666 " update your code.)") % version
1662 " update your code.)") % version
1667 self.develwarn(msg, stacklevel=stacklevel, config='deprec-warn')
1663 self.develwarn(msg, stacklevel=stacklevel, config='deprec-warn')
1668
1664
1669 def exportableenviron(self):
1665 def exportableenviron(self):
1670 """The environment variables that are safe to export, e.g. through
1666 """The environment variables that are safe to export, e.g. through
1671 hgweb.
1667 hgweb.
1672 """
1668 """
1673 return self._exportableenviron
1669 return self._exportableenviron
1674
1670
1675 @contextlib.contextmanager
1671 @contextlib.contextmanager
1676 def configoverride(self, overrides, source=""):
1672 def configoverride(self, overrides, source=""):
1677 """Context manager for temporary config overrides
1673 """Context manager for temporary config overrides
1678 `overrides` must be a dict of the following structure:
1674 `overrides` must be a dict of the following structure:
1679 {(section, name) : value}"""
1675 {(section, name) : value}"""
1680 backups = {}
1676 backups = {}
1681 try:
1677 try:
1682 for (section, name), value in overrides.items():
1678 for (section, name), value in overrides.items():
1683 backups[(section, name)] = self.backupconfig(section, name)
1679 backups[(section, name)] = self.backupconfig(section, name)
1684 self.setconfig(section, name, value, source)
1680 self.setconfig(section, name, value, source)
1685 yield
1681 yield
1686 finally:
1682 finally:
1687 for __, backup in backups.items():
1683 for __, backup in backups.items():
1688 self.restoreconfig(backup)
1684 self.restoreconfig(backup)
1689 # just restoring ui.quiet config to the previous value is not enough
1685 # just restoring ui.quiet config to the previous value is not enough
1690 # as it does not update ui.quiet class member
1686 # as it does not update ui.quiet class member
1691 if ('ui', 'quiet') in overrides:
1687 if ('ui', 'quiet') in overrides:
1692 self.fixconfig(section='ui')
1688 self.fixconfig(section='ui')
1693
1689
1694 class paths(dict):
1690 class paths(dict):
1695 """Represents a collection of paths and their configs.
1691 """Represents a collection of paths and their configs.
1696
1692
1697 Data is initially derived from ui instances and the config files they have
1693 Data is initially derived from ui instances and the config files they have
1698 loaded.
1694 loaded.
1699 """
1695 """
1700 def __init__(self, ui):
1696 def __init__(self, ui):
1701 dict.__init__(self)
1697 dict.__init__(self)
1702
1698
1703 for name, loc in ui.configitems('paths', ignoresub=True):
1699 for name, loc in ui.configitems('paths', ignoresub=True):
1704 # No location is the same as not existing.
1700 # No location is the same as not existing.
1705 if not loc:
1701 if not loc:
1706 continue
1702 continue
1707 loc, sub = ui.configsuboptions('paths', name)
1703 loc, sub = ui.configsuboptions('paths', name)
1708 self[name] = path(ui, name, rawloc=loc, suboptions=sub)
1704 self[name] = path(ui, name, rawloc=loc, suboptions=sub)
1709
1705
1710 def getpath(self, name, default=None):
1706 def getpath(self, name, default=None):
1711 """Return a ``path`` from a string, falling back to default.
1707 """Return a ``path`` from a string, falling back to default.
1712
1708
1713 ``name`` can be a named path or locations. Locations are filesystem
1709 ``name`` can be a named path or locations. Locations are filesystem
1714 paths or URIs.
1710 paths or URIs.
1715
1711
1716 Returns None if ``name`` is not a registered path, a URI, or a local
1712 Returns None if ``name`` is not a registered path, a URI, or a local
1717 path to a repo.
1713 path to a repo.
1718 """
1714 """
1719 # Only fall back to default if no path was requested.
1715 # Only fall back to default if no path was requested.
1720 if name is None:
1716 if name is None:
1721 if not default:
1717 if not default:
1722 default = ()
1718 default = ()
1723 elif not isinstance(default, (tuple, list)):
1719 elif not isinstance(default, (tuple, list)):
1724 default = (default,)
1720 default = (default,)
1725 for k in default:
1721 for k in default:
1726 try:
1722 try:
1727 return self[k]
1723 return self[k]
1728 except KeyError:
1724 except KeyError:
1729 continue
1725 continue
1730 return None
1726 return None
1731
1727
1732 # Most likely empty string.
1728 # Most likely empty string.
1733 # This may need to raise in the future.
1729 # This may need to raise in the future.
1734 if not name:
1730 if not name:
1735 return None
1731 return None
1736
1732
1737 try:
1733 try:
1738 return self[name]
1734 return self[name]
1739 except KeyError:
1735 except KeyError:
1740 # Try to resolve as a local path or URI.
1736 # Try to resolve as a local path or URI.
1741 try:
1737 try:
1742 # We don't pass sub-options in, so no need to pass ui instance.
1738 # We don't pass sub-options in, so no need to pass ui instance.
1743 return path(None, None, rawloc=name)
1739 return path(None, None, rawloc=name)
1744 except ValueError:
1740 except ValueError:
1745 raise error.RepoError(_('repository %s does not exist') %
1741 raise error.RepoError(_('repository %s does not exist') %
1746 name)
1742 name)
1747
1743
1748 _pathsuboptions = {}
1744 _pathsuboptions = {}
1749
1745
1750 def pathsuboption(option, attr):
1746 def pathsuboption(option, attr):
1751 """Decorator used to declare a path sub-option.
1747 """Decorator used to declare a path sub-option.
1752
1748
1753 Arguments are the sub-option name and the attribute it should set on
1749 Arguments are the sub-option name and the attribute it should set on
1754 ``path`` instances.
1750 ``path`` instances.
1755
1751
1756 The decorated function will receive as arguments a ``ui`` instance,
1752 The decorated function will receive as arguments a ``ui`` instance,
1757 ``path`` instance, and the string value of this option from the config.
1753 ``path`` instance, and the string value of this option from the config.
1758 The function should return the value that will be set on the ``path``
1754 The function should return the value that will be set on the ``path``
1759 instance.
1755 instance.
1760
1756
1761 This decorator can be used to perform additional verification of
1757 This decorator can be used to perform additional verification of
1762 sub-options and to change the type of sub-options.
1758 sub-options and to change the type of sub-options.
1763 """
1759 """
1764 def register(func):
1760 def register(func):
1765 _pathsuboptions[option] = (attr, func)
1761 _pathsuboptions[option] = (attr, func)
1766 return func
1762 return func
1767 return register
1763 return register
1768
1764
1769 @pathsuboption('pushurl', 'pushloc')
1765 @pathsuboption('pushurl', 'pushloc')
1770 def pushurlpathoption(ui, path, value):
1766 def pushurlpathoption(ui, path, value):
1771 u = util.url(value)
1767 u = util.url(value)
1772 # Actually require a URL.
1768 # Actually require a URL.
1773 if not u.scheme:
1769 if not u.scheme:
1774 ui.warn(_('(paths.%s:pushurl not a URL; ignoring)\n') % path.name)
1770 ui.warn(_('(paths.%s:pushurl not a URL; ignoring)\n') % path.name)
1775 return None
1771 return None
1776
1772
1777 # Don't support the #foo syntax in the push URL to declare branch to
1773 # Don't support the #foo syntax in the push URL to declare branch to
1778 # push.
1774 # push.
1779 if u.fragment:
1775 if u.fragment:
1780 ui.warn(_('("#fragment" in paths.%s:pushurl not supported; '
1776 ui.warn(_('("#fragment" in paths.%s:pushurl not supported; '
1781 'ignoring)\n') % path.name)
1777 'ignoring)\n') % path.name)
1782 u.fragment = None
1778 u.fragment = None
1783
1779
1784 return bytes(u)
1780 return bytes(u)
1785
1781
1786 @pathsuboption('pushrev', 'pushrev')
1782 @pathsuboption('pushrev', 'pushrev')
1787 def pushrevpathoption(ui, path, value):
1783 def pushrevpathoption(ui, path, value):
1788 return value
1784 return value
1789
1785
1790 class path(object):
1786 class path(object):
1791 """Represents an individual path and its configuration."""
1787 """Represents an individual path and its configuration."""
1792
1788
1793 def __init__(self, ui, name, rawloc=None, suboptions=None):
1789 def __init__(self, ui, name, rawloc=None, suboptions=None):
1794 """Construct a path from its config options.
1790 """Construct a path from its config options.
1795
1791
1796 ``ui`` is the ``ui`` instance the path is coming from.
1792 ``ui`` is the ``ui`` instance the path is coming from.
1797 ``name`` is the symbolic name of the path.
1793 ``name`` is the symbolic name of the path.
1798 ``rawloc`` is the raw location, as defined in the config.
1794 ``rawloc`` is the raw location, as defined in the config.
1799 ``pushloc`` is the raw locations pushes should be made to.
1795 ``pushloc`` is the raw locations pushes should be made to.
1800
1796
1801 If ``name`` is not defined, we require that the location be a) a local
1797 If ``name`` is not defined, we require that the location be a) a local
1802 filesystem path with a .hg directory or b) a URL. If not,
1798 filesystem path with a .hg directory or b) a URL. If not,
1803 ``ValueError`` is raised.
1799 ``ValueError`` is raised.
1804 """
1800 """
1805 if not rawloc:
1801 if not rawloc:
1806 raise ValueError('rawloc must be defined')
1802 raise ValueError('rawloc must be defined')
1807
1803
1808 # Locations may define branches via syntax <base>#<branch>.
1804 # Locations may define branches via syntax <base>#<branch>.
1809 u = util.url(rawloc)
1805 u = util.url(rawloc)
1810 branch = None
1806 branch = None
1811 if u.fragment:
1807 if u.fragment:
1812 branch = u.fragment
1808 branch = u.fragment
1813 u.fragment = None
1809 u.fragment = None
1814
1810
1815 self.url = u
1811 self.url = u
1816 self.branch = branch
1812 self.branch = branch
1817
1813
1818 self.name = name
1814 self.name = name
1819 self.rawloc = rawloc
1815 self.rawloc = rawloc
1820 self.loc = '%s' % u
1816 self.loc = '%s' % u
1821
1817
1822 # When given a raw location but not a symbolic name, validate the
1818 # When given a raw location but not a symbolic name, validate the
1823 # location is valid.
1819 # location is valid.
1824 if not name and not u.scheme and not self._isvalidlocalpath(self.loc):
1820 if not name and not u.scheme and not self._isvalidlocalpath(self.loc):
1825 raise ValueError('location is not a URL or path to a local '
1821 raise ValueError('location is not a URL or path to a local '
1826 'repo: %s' % rawloc)
1822 'repo: %s' % rawloc)
1827
1823
1828 suboptions = suboptions or {}
1824 suboptions = suboptions or {}
1829
1825
1830 # Now process the sub-options. If a sub-option is registered, its
1826 # Now process the sub-options. If a sub-option is registered, its
1831 # attribute will always be present. The value will be None if there
1827 # attribute will always be present. The value will be None if there
1832 # was no valid sub-option.
1828 # was no valid sub-option.
1833 for suboption, (attr, func) in _pathsuboptions.iteritems():
1829 for suboption, (attr, func) in _pathsuboptions.iteritems():
1834 if suboption not in suboptions:
1830 if suboption not in suboptions:
1835 setattr(self, attr, None)
1831 setattr(self, attr, None)
1836 continue
1832 continue
1837
1833
1838 value = func(ui, self, suboptions[suboption])
1834 value = func(ui, self, suboptions[suboption])
1839 setattr(self, attr, value)
1835 setattr(self, attr, value)
1840
1836
1841 def _isvalidlocalpath(self, path):
1837 def _isvalidlocalpath(self, path):
1842 """Returns True if the given path is a potentially valid repository.
1838 """Returns True if the given path is a potentially valid repository.
1843 This is its own function so that extensions can change the definition of
1839 This is its own function so that extensions can change the definition of
1844 'valid' in this case (like when pulling from a git repo into a hg
1840 'valid' in this case (like when pulling from a git repo into a hg
1845 one)."""
1841 one)."""
1846 return os.path.isdir(os.path.join(path, '.hg'))
1842 return os.path.isdir(os.path.join(path, '.hg'))
1847
1843
1848 @property
1844 @property
1849 def suboptions(self):
1845 def suboptions(self):
1850 """Return sub-options and their values for this path.
1846 """Return sub-options and their values for this path.
1851
1847
1852 This is intended to be used for presentation purposes.
1848 This is intended to be used for presentation purposes.
1853 """
1849 """
1854 d = {}
1850 d = {}
1855 for subopt, (attr, _func) in _pathsuboptions.iteritems():
1851 for subopt, (attr, _func) in _pathsuboptions.iteritems():
1856 value = getattr(self, attr)
1852 value = getattr(self, attr)
1857 if value is not None:
1853 if value is not None:
1858 d[subopt] = value
1854 d[subopt] = value
1859 return d
1855 return d
1860
1856
1861 # we instantiate one globally shared progress bar to avoid
1857 # we instantiate one globally shared progress bar to avoid
1862 # competing progress bars when multiple UI objects get created
1858 # competing progress bars when multiple UI objects get created
1863 _progresssingleton = None
1859 _progresssingleton = None
1864
1860
1865 def getprogbar(ui):
1861 def getprogbar(ui):
1866 global _progresssingleton
1862 global _progresssingleton
1867 if _progresssingleton is None:
1863 if _progresssingleton is None:
1868 # passing 'ui' object to the singleton is fishy,
1864 # passing 'ui' object to the singleton is fishy,
1869 # this is how the extension used to work but feel free to rework it.
1865 # this is how the extension used to work but feel free to rework it.
1870 _progresssingleton = progress.progbar(ui)
1866 _progresssingleton = progress.progbar(ui)
1871 return _progresssingleton
1867 return _progresssingleton
1872
1868
1873 def haveprogbar():
1869 def haveprogbar():
1874 return _progresssingleton is not None
1870 return _progresssingleton is not None
@@ -1,596 +1,763 b''
1 $ HGFOO=BAR; export HGFOO
1 $ HGFOO=BAR; export HGFOO
2 $ cat >> $HGRCPATH <<EOF
2 $ cat >> $HGRCPATH <<EOF
3 > [alias]
3 > [alias]
4 > # should clobber ci but not commit (issue2993)
4 > # should clobber ci but not commit (issue2993)
5 > ci = version
5 > ci = version
6 > myinit = init
6 > myinit = init
7 > myinit:doc = This is my documented alias for init.
8 > myinit:help = [OPTIONS] [BLA] [BLE]
7 > mycommit = commit
9 > mycommit = commit
10 > mycommit:doc = This is my alias with only doc.
8 > optionalrepo = showconfig alias.myinit
11 > optionalrepo = showconfig alias.myinit
9 > cleanstatus = status -c
12 > cleanstatus = status -c
13 > cleanstatus:help = [ONLYHELPHERE]
10 > unknown = bargle
14 > unknown = bargle
11 > ambiguous = s
15 > ambiguous = s
12 > recursive = recursive
16 > recursive = recursive
13 > disabled = email
17 > disabled = email
14 > nodefinition =
18 > nodefinition =
15 > noclosingquotation = '
19 > noclosingquotation = '
16 > no--cwd = status --cwd elsewhere
20 > no--cwd = status --cwd elsewhere
17 > no-R = status -R elsewhere
21 > no-R = status -R elsewhere
18 > no--repo = status --repo elsewhere
22 > no--repo = status --repo elsewhere
19 > no--repository = status --repository elsewhere
23 > no--repository = status --repository elsewhere
20 > no--config = status --config a.config=1
24 > no--config = status --config a.config=1
21 > mylog = log
25 > mylog = log
22 > lognull = log -r null
26 > lognull = log -r null
27 > lognull:doc = Logs the null rev
28 > lognull:help = foo bar baz
23 > shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
29 > shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
24 > positional = log --template '{\$2} {\$1} | {date|isodate}\n'
30 > positional = log --template '{\$2} {\$1} | {date|isodate}\n'
25 > dln = lognull --debug
31 > dln = lognull --debug
32 > recursivedoc = dln
33 > recursivedoc:doc = Logs the null rev in debug mode
26 > nousage = rollback
34 > nousage = rollback
27 > put = export -r 0 -o "\$FOO/%R.diff"
35 > put = export -r 0 -o "\$FOO/%R.diff"
28 > blank = !printf '\n'
36 > blank = !printf '\n'
29 > self = !printf '\$0\n'
37 > self = !printf '\$0\n'
30 > echoall = !printf '\$@\n'
38 > echoall = !printf '\$@\n'
31 > echo1 = !printf '\$1\n'
39 > echo1 = !printf '\$1\n'
32 > echo2 = !printf '\$2\n'
40 > echo2 = !printf '\$2\n'
33 > echo13 = !printf '\$1 \$3\n'
41 > echo13 = !printf '\$1 \$3\n'
34 > echotokens = !printf "%s\n" "\$@"
42 > echotokens = !printf "%s\n" "\$@"
35 > count = !hg log -r "\$@" --template=. | wc -c | sed -e 's/ //g'
43 > count = !hg log -r "\$@" --template=. | wc -c | sed -e 's/ //g'
36 > mcount = !hg log \$@ --template=. | wc -c | sed -e 's/ //g'
44 > mcount = !hg log \$@ --template=. | wc -c | sed -e 's/ //g'
37 > rt = root
45 > rt = root
38 > tglog = log -G --template "{rev}:{node|short}: '{desc}' {branches}\n"
46 > tglog = log -G --template "{rev}:{node|short}: '{desc}' {branches}\n"
39 > idalias = id
47 > idalias = id
40 > idaliaslong = id
48 > idaliaslong = id
41 > idaliasshell = !echo test
49 > idaliasshell = !echo test
42 > parentsshell1 = !echo one
50 > parentsshell1 = !echo one
43 > parentsshell2 = !echo two
51 > parentsshell2 = !echo two
44 > escaped1 = !printf 'test\$\$test\n'
52 > escaped1 = !printf 'test\$\$test\n'
45 > escaped2 = !sh -c 'echo "HGFOO is \$\$HGFOO"'
53 > escaped2 = !sh -c 'echo "HGFOO is \$\$HGFOO"'
46 > escaped3 = !sh -c 'echo "\$1 is \$\$\$1"'
54 > escaped3 = !sh -c 'echo "\$1 is \$\$\$1"'
47 > escaped4 = !printf '\$\$0 \$\$@\n'
55 > escaped4 = !printf '\$\$0 \$\$@\n'
48 > exit1 = !sh -c 'exit 1'
56 > exit1 = !sh -c 'exit 1'
49 >
57 >
50 > [defaults]
58 > [defaults]
51 > mylog = -q
59 > mylog = -q
52 > lognull = -q
60 > lognull = -q
53 > log = -v
61 > log = -v
54 > EOF
62 > EOF
55
63
56
57 basic
64 basic
58
65
59 $ hg myinit alias
66 $ hg myinit alias
60
67
68 help
69
70 $ hg help -c | grep myinit
71 myinit This is my documented alias for init.
72 $ hg help -c | grep mycommit
73 mycommit This is my alias with only doc.
74 $ hg help -c | grep cleanstatus
75 cleanstatus show changed files in the working directory
76 $ hg help -c | grep lognull
77 lognull Logs the null rev
78 $ hg help -c | grep dln
79 dln Logs the null rev
80 $ hg help -c | grep recursivedoc
81 recursivedoc Logs the null rev in debug mode
82 $ hg help myinit
83 hg myinit [OPTIONS] [BLA] [BLE]
84
85 alias for: hg init
86
87 This is my documented alias for init.
88
89 defined by: * (glob)
90 */* (glob) (?)
91 */* (glob) (?)
92 */* (glob) (?)
93
94 options:
95
96 -e --ssh CMD specify ssh command to use
97 --remotecmd CMD specify hg command to run on the remote side
98 --insecure do not verify server certificate (ignoring web.cacerts
99 config)
100
101 (some details hidden, use --verbose to show complete help)
102
103 $ hg help mycommit
104 hg mycommit [OPTION]... [FILE]...
105
106 alias for: hg commit
107
108 This is my alias with only doc.
109
110 defined by: * (glob)
111 */* (glob) (?)
112 */* (glob) (?)
113 */* (glob) (?)
114
115 options ([+] can be repeated):
116
117 -A --addremove mark new/missing files as added/removed before
118 committing
119 --close-branch mark a branch head as closed
120 --amend amend the parent of the working directory
121 -s --secret use the secret phase for committing
122 -e --edit invoke editor on commit messages
123 -i --interactive use interactive mode
124 -I --include PATTERN [+] include names matching the given patterns
125 -X --exclude PATTERN [+] exclude names matching the given patterns
126 -m --message TEXT use text as commit message
127 -l --logfile FILE read commit message from file
128 -d --date DATE record the specified date as commit date
129 -u --user USER record the specified user as committer
130 -S --subrepos recurse into subrepositories
131
132 (some details hidden, use --verbose to show complete help)
133
134 $ hg help cleanstatus
135 hg cleanstatus [ONLYHELPHERE]
136
137 alias for: hg status -c
138
139 show changed files in the working directory
140
141 Show status of files in the repository. If names are given, only files
142 that match are shown. Files that are clean or ignored or the source of a
143 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
144 -C/--copies or -A/--all are given. Unless options described with "show
145 only ..." are given, the options -mardu are used.
146
147 Option -q/--quiet hides untracked (unknown and ignored) files unless
148 explicitly requested with -u/--unknown or -i/--ignored.
149
150 Note:
151 'hg status' may appear to disagree with diff if permissions have
152 changed or a merge has occurred. The standard diff format does not
153 report permission changes and diff only reports changes relative to one
154 merge parent.
155
156 If one revision is given, it is used as the base revision. If two
157 revisions are given, the differences between them are shown. The --change
158 option can also be used as a shortcut to list the changed files of a
159 revision from its first parent.
160
161 The codes used to show the status of files are:
162
163 M = modified
164 A = added
165 R = removed
166 C = clean
167 ! = missing (deleted by non-hg command, but still tracked)
168 ? = not tracked
169 I = ignored
170 = origin of the previous file (with --copies)
171
172 Returns 0 on success.
173
174 defined by: * (glob)
175 */* (glob) (?)
176 */* (glob) (?)
177 */* (glob) (?)
178
179 options ([+] can be repeated):
180
181 -A --all show status of all files
182 -m --modified show only modified files
183 -a --added show only added files
184 -r --removed show only removed files
185 -d --deleted show only deleted (but tracked) files
186 -c --clean show only files without changes
187 -u --unknown show only unknown (not tracked) files
188 -i --ignored show only ignored files
189 -n --no-status hide status prefix
190 -C --copies show source of copied files
191 -0 --print0 end filenames with NUL, for use with xargs
192 --rev REV [+] show difference from revision
193 --change REV list the changed files of a revision
194 -I --include PATTERN [+] include names matching the given patterns
195 -X --exclude PATTERN [+] exclude names matching the given patterns
196 -S --subrepos recurse into subrepositories
197
198 (some details hidden, use --verbose to show complete help)
199
200 $ hg help recursivedoc | head -n 5
201 hg recursivedoc foo bar baz
202
203 alias for: hg dln
204
205 Logs the null rev in debug mode
61
206
62 unknown
207 unknown
63
208
64 $ hg unknown
209 $ hg unknown
65 abort: alias 'unknown' resolves to unknown command 'bargle'
210 abort: alias 'unknown' resolves to unknown command 'bargle'
66 [255]
211 [255]
67 $ hg help unknown
212 $ hg help unknown
68 alias 'unknown' resolves to unknown command 'bargle'
213 alias 'unknown' resolves to unknown command 'bargle'
69
214
70
215
71 ambiguous
216 ambiguous
72
217
73 $ hg ambiguous
218 $ hg ambiguous
74 abort: alias 'ambiguous' resolves to ambiguous command 's'
219 abort: alias 'ambiguous' resolves to ambiguous command 's'
75 [255]
220 [255]
76 $ hg help ambiguous
221 $ hg help ambiguous
77 alias 'ambiguous' resolves to ambiguous command 's'
222 alias 'ambiguous' resolves to ambiguous command 's'
78
223
79
224
80 recursive
225 recursive
81
226
82 $ hg recursive
227 $ hg recursive
83 abort: alias 'recursive' resolves to unknown command 'recursive'
228 abort: alias 'recursive' resolves to unknown command 'recursive'
84 [255]
229 [255]
85 $ hg help recursive
230 $ hg help recursive
86 alias 'recursive' resolves to unknown command 'recursive'
231 alias 'recursive' resolves to unknown command 'recursive'
87
232
88
233
89 disabled
234 disabled
90
235
91 $ hg disabled
236 $ hg disabled
92 abort: alias 'disabled' resolves to unknown command 'email'
237 abort: alias 'disabled' resolves to unknown command 'email'
93 ('email' is provided by 'patchbomb' extension)
238 ('email' is provided by 'patchbomb' extension)
94 [255]
239 [255]
95 $ hg help disabled
240 $ hg help disabled
96 alias 'disabled' resolves to unknown command 'email'
241 alias 'disabled' resolves to unknown command 'email'
97
242
98 'email' is provided by the following extension:
243 'email' is provided by the following extension:
99
244
100 patchbomb command to send changesets as (a series of) patch emails
245 patchbomb command to send changesets as (a series of) patch emails
101
246
102 (use 'hg help extensions' for information on enabling extensions)
247 (use 'hg help extensions' for information on enabling extensions)
103
248
104
249
105 no definition
250 no definition
106
251
107 $ hg nodef
252 $ hg nodef
108 abort: no definition for alias 'nodefinition'
253 abort: no definition for alias 'nodefinition'
109 [255]
254 [255]
110 $ hg help nodef
255 $ hg help nodef
111 no definition for alias 'nodefinition'
256 no definition for alias 'nodefinition'
112
257
113
258
114 no closing quotation
259 no closing quotation
115
260
116 $ hg noclosing
261 $ hg noclosing
117 abort: error in definition for alias 'noclosingquotation': No closing quotation
262 abort: error in definition for alias 'noclosingquotation': No closing quotation
118 [255]
263 [255]
119 $ hg help noclosing
264 $ hg help noclosing
120 error in definition for alias 'noclosingquotation': No closing quotation
265 error in definition for alias 'noclosingquotation': No closing quotation
121
266
122 "--" in alias definition should be preserved
267 "--" in alias definition should be preserved
123
268
124 $ hg --config alias.dash='cat --' -R alias dash -r0
269 $ hg --config alias.dash='cat --' -R alias dash -r0
125 abort: -r0 not under root '$TESTTMP/alias'
270 abort: -r0 not under root '$TESTTMP/alias'
126 (consider using '--cwd alias')
271 (consider using '--cwd alias')
127 [255]
272 [255]
128
273
129 invalid options
274 invalid options
130
275
131 $ hg no--cwd
276 $ hg no--cwd
132 abort: error in definition for alias 'no--cwd': --cwd may only be given on the command line
277 abort: error in definition for alias 'no--cwd': --cwd may only be given on the command line
133 [255]
278 [255]
134 $ hg help no--cwd
279 $ hg help no--cwd
135 error in definition for alias 'no--cwd': --cwd may only be given on the
280 error in definition for alias 'no--cwd': --cwd may only be given on the
136 command line
281 command line
137 $ hg no-R
282 $ hg no-R
138 abort: error in definition for alias 'no-R': -R may only be given on the command line
283 abort: error in definition for alias 'no-R': -R may only be given on the command line
139 [255]
284 [255]
140 $ hg help no-R
285 $ hg help no-R
141 error in definition for alias 'no-R': -R may only be given on the command line
286 error in definition for alias 'no-R': -R may only be given on the command line
142 $ hg no--repo
287 $ hg no--repo
143 abort: error in definition for alias 'no--repo': --repo may only be given on the command line
288 abort: error in definition for alias 'no--repo': --repo may only be given on the command line
144 [255]
289 [255]
145 $ hg help no--repo
290 $ hg help no--repo
146 error in definition for alias 'no--repo': --repo may only be given on the
291 error in definition for alias 'no--repo': --repo may only be given on the
147 command line
292 command line
148 $ hg no--repository
293 $ hg no--repository
149 abort: error in definition for alias 'no--repository': --repository may only be given on the command line
294 abort: error in definition for alias 'no--repository': --repository may only be given on the command line
150 [255]
295 [255]
151 $ hg help no--repository
296 $ hg help no--repository
152 error in definition for alias 'no--repository': --repository may only be given
297 error in definition for alias 'no--repository': --repository may only be given
153 on the command line
298 on the command line
154 $ hg no--config
299 $ hg no--config
155 abort: error in definition for alias 'no--config': --config may only be given on the command line
300 abort: error in definition for alias 'no--config': --config may only be given on the command line
156 [255]
301 [255]
157 $ hg no --config alias.no='--repo elsewhere --cwd elsewhere status'
302 $ hg no --config alias.no='--repo elsewhere --cwd elsewhere status'
158 abort: error in definition for alias 'no': --repo/--cwd may only be given on the command line
303 abort: error in definition for alias 'no': --repo/--cwd may only be given on the command line
159 [255]
304 [255]
160 $ hg no --config alias.no='--repo elsewhere'
305 $ hg no --config alias.no='--repo elsewhere'
161 abort: error in definition for alias 'no': --repo may only be given on the command line
306 abort: error in definition for alias 'no': --repo may only be given on the command line
162 [255]
307 [255]
163
308
164 optional repository
309 optional repository
165
310
166 #if no-outer-repo
311 #if no-outer-repo
167 $ hg optionalrepo
312 $ hg optionalrepo
168 init
313 init
169 #endif
314 #endif
170 $ cd alias
315 $ cd alias
171 $ cat > .hg/hgrc <<EOF
316 $ cat > .hg/hgrc <<EOF
172 > [alias]
317 > [alias]
173 > myinit = init -q
318 > myinit = init -q
174 > EOF
319 > EOF
175 $ hg optionalrepo
320 $ hg optionalrepo
176 init -q
321 init -q
177
322
178 no usage
323 no usage
179
324
180 $ hg nousage
325 $ hg nousage
181 no rollback information available
326 no rollback information available
182 [1]
327 [1]
183
328
184 $ echo foo > foo
329 $ echo foo > foo
185 $ hg commit -Amfoo
330 $ hg commit -Amfoo
186 adding foo
331 adding foo
187
332
188 infer repository
333 infer repository
189
334
190 $ cd ..
335 $ cd ..
191
336
192 #if no-outer-repo
337 #if no-outer-repo
193 $ hg shortlog alias/foo
338 $ hg shortlog alias/foo
194 0 e63c23eaa88a | 1970-01-01 00:00 +0000
339 0 e63c23eaa88a | 1970-01-01 00:00 +0000
195 #endif
340 #endif
196
341
197 $ cd alias
342 $ cd alias
198
343
199 with opts
344 with opts
200
345
201 $ hg cleanst
346 $ hg cleanst
202 C foo
347 C foo
203
348
204
349
205 with opts and whitespace
350 with opts and whitespace
206
351
207 $ hg shortlog
352 $ hg shortlog
208 0 e63c23eaa88a | 1970-01-01 00:00 +0000
353 0 e63c23eaa88a | 1970-01-01 00:00 +0000
209
354
210 positional arguments
355 positional arguments
211
356
212 $ hg positional
357 $ hg positional
213 abort: too few arguments for command alias
358 abort: too few arguments for command alias
214 [255]
359 [255]
215 $ hg positional a
360 $ hg positional a
216 abort: too few arguments for command alias
361 abort: too few arguments for command alias
217 [255]
362 [255]
218 $ hg positional 'node|short' rev
363 $ hg positional 'node|short' rev
219 0 e63c23eaa88a | 1970-01-01 00:00 +0000
364 0 e63c23eaa88a | 1970-01-01 00:00 +0000
220
365
221 interaction with defaults
366 interaction with defaults
222
367
223 $ hg mylog
368 $ hg mylog
224 0:e63c23eaa88a
369 0:e63c23eaa88a
225 $ hg lognull
370 $ hg lognull
226 -1:000000000000
371 -1:000000000000
227
372
228
373
229 properly recursive
374 properly recursive
230
375
231 $ hg dln
376 $ hg dln
232 changeset: -1:0000000000000000000000000000000000000000
377 changeset: -1:0000000000000000000000000000000000000000
233 phase: public
378 phase: public
234 parent: -1:0000000000000000000000000000000000000000
379 parent: -1:0000000000000000000000000000000000000000
235 parent: -1:0000000000000000000000000000000000000000
380 parent: -1:0000000000000000000000000000000000000000
236 manifest: -1:0000000000000000000000000000000000000000
381 manifest: -1:0000000000000000000000000000000000000000
237 user:
382 user:
238 date: Thu Jan 01 00:00:00 1970 +0000
383 date: Thu Jan 01 00:00:00 1970 +0000
239 extra: branch=default
384 extra: branch=default
240
385
241
386
242
387
243 path expanding
388 path expanding
244
389
245 $ FOO=`pwd` hg put
390 $ FOO=`pwd` hg put
246 $ cat 0.diff
391 $ cat 0.diff
247 # HG changeset patch
392 # HG changeset patch
248 # User test
393 # User test
249 # Date 0 0
394 # Date 0 0
250 # Thu Jan 01 00:00:00 1970 +0000
395 # Thu Jan 01 00:00:00 1970 +0000
251 # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
396 # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
252 # Parent 0000000000000000000000000000000000000000
397 # Parent 0000000000000000000000000000000000000000
253 foo
398 foo
254
399
255 diff -r 000000000000 -r e63c23eaa88a foo
400 diff -r 000000000000 -r e63c23eaa88a foo
256 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
401 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
257 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
402 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
258 @@ -0,0 +1,1 @@
403 @@ -0,0 +1,1 @@
259 +foo
404 +foo
260
405
261
406
262 simple shell aliases
407 simple shell aliases
263
408
264 $ hg blank
409 $ hg blank
265
410
266 $ hg blank foo
411 $ hg blank foo
267
412
268 $ hg self
413 $ hg self
269 self
414 self
270 $ hg echoall
415 $ hg echoall
271
416
272 $ hg echoall foo
417 $ hg echoall foo
273 foo
418 foo
274 $ hg echoall 'test $2' foo
419 $ hg echoall 'test $2' foo
275 test $2 foo
420 test $2 foo
276 $ hg echoall 'test $@' foo '$@'
421 $ hg echoall 'test $@' foo '$@'
277 test $@ foo $@
422 test $@ foo $@
278 $ hg echoall 'test "$@"' foo '"$@"'
423 $ hg echoall 'test "$@"' foo '"$@"'
279 test "$@" foo "$@"
424 test "$@" foo "$@"
280 $ hg echo1 foo bar baz
425 $ hg echo1 foo bar baz
281 foo
426 foo
282 $ hg echo2 foo bar baz
427 $ hg echo2 foo bar baz
283 bar
428 bar
284 $ hg echo13 foo bar baz test
429 $ hg echo13 foo bar baz test
285 foo baz
430 foo baz
286 $ hg echo2 foo
431 $ hg echo2 foo
287
432
288 $ hg echotokens
433 $ hg echotokens
289
434
290 $ hg echotokens foo 'bar $1 baz'
435 $ hg echotokens foo 'bar $1 baz'
291 foo
436 foo
292 bar $1 baz
437 bar $1 baz
293 $ hg echotokens 'test $2' foo
438 $ hg echotokens 'test $2' foo
294 test $2
439 test $2
295 foo
440 foo
296 $ hg echotokens 'test $@' foo '$@'
441 $ hg echotokens 'test $@' foo '$@'
297 test $@
442 test $@
298 foo
443 foo
299 $@
444 $@
300 $ hg echotokens 'test "$@"' foo '"$@"'
445 $ hg echotokens 'test "$@"' foo '"$@"'
301 test "$@"
446 test "$@"
302 foo
447 foo
303 "$@"
448 "$@"
304 $ echo bar > bar
449 $ echo bar > bar
305 $ hg commit -qA -m bar
450 $ hg commit -qA -m bar
306 $ hg count .
451 $ hg count .
307 1
452 1
308 $ hg count 'branch(default)'
453 $ hg count 'branch(default)'
309 2
454 2
310 $ hg mcount -r '"branch(default)"'
455 $ hg mcount -r '"branch(default)"'
311 2
456 2
312
457
313 $ hg tglog
458 $ hg tglog
314 @ 1:042423737847: 'bar'
459 @ 1:042423737847: 'bar'
315 |
460 |
316 o 0:e63c23eaa88a: 'foo'
461 o 0:e63c23eaa88a: 'foo'
317
462
318
463
319
464
320 shadowing
465 shadowing
321
466
322 $ hg i
467 $ hg i
323 hg: command 'i' is ambiguous:
468 hg: command 'i' is ambiguous:
324 idalias idaliaslong idaliasshell identify import incoming init
469 idalias idaliaslong idaliasshell identify import incoming init
325 [255]
470 [255]
326 $ hg id
471 $ hg id
327 042423737847 tip
472 042423737847 tip
328 $ hg ida
473 $ hg ida
329 hg: command 'ida' is ambiguous:
474 hg: command 'ida' is ambiguous:
330 idalias idaliaslong idaliasshell
475 idalias idaliaslong idaliasshell
331 [255]
476 [255]
332 $ hg idalias
477 $ hg idalias
333 042423737847 tip
478 042423737847 tip
334 $ hg idaliasl
479 $ hg idaliasl
335 042423737847 tip
480 042423737847 tip
336 $ hg idaliass
481 $ hg idaliass
337 test
482 test
338 $ hg parentsshell
483 $ hg parentsshell
339 hg: command 'parentsshell' is ambiguous:
484 hg: command 'parentsshell' is ambiguous:
340 parentsshell1 parentsshell2
485 parentsshell1 parentsshell2
341 [255]
486 [255]
342 $ hg parentsshell1
487 $ hg parentsshell1
343 one
488 one
344 $ hg parentsshell2
489 $ hg parentsshell2
345 two
490 two
346
491
347
492
348 shell aliases with global options
493 shell aliases with global options
349
494
350 $ hg init sub
495 $ hg init sub
351 $ cd sub
496 $ cd sub
352 $ hg count 'branch(default)'
497 $ hg count 'branch(default)'
353 abort: unknown revision 'default'!
498 abort: unknown revision 'default'!
354 0
499 0
355 $ hg -v count 'branch(default)'
500 $ hg -v count 'branch(default)'
356 abort: unknown revision 'default'!
501 abort: unknown revision 'default'!
357 0
502 0
358 $ hg -R .. count 'branch(default)'
503 $ hg -R .. count 'branch(default)'
359 abort: unknown revision 'default'!
504 abort: unknown revision 'default'!
360 0
505 0
361 $ hg --cwd .. count 'branch(default)'
506 $ hg --cwd .. count 'branch(default)'
362 2
507 2
363 $ hg echoall --cwd ..
508 $ hg echoall --cwd ..
364
509
365
510
366 "--" passed to shell alias should be preserved
511 "--" passed to shell alias should be preserved
367
512
368 $ hg --config alias.printf='!printf "$@"' printf '%s %s %s\n' -- --cwd ..
513 $ hg --config alias.printf='!printf "$@"' printf '%s %s %s\n' -- --cwd ..
369 -- --cwd ..
514 -- --cwd ..
370
515
371 repo specific shell aliases
516 repo specific shell aliases
372
517
373 $ cat >> .hg/hgrc <<EOF
518 $ cat >> .hg/hgrc <<EOF
374 > [alias]
519 > [alias]
375 > subalias = !echo sub
520 > subalias = !echo sub
376 > EOF
521 > EOF
377 $ cat >> ../.hg/hgrc <<EOF
522 $ cat >> ../.hg/hgrc <<EOF
378 > [alias]
523 > [alias]
379 > mainalias = !echo main
524 > mainalias = !echo main
380 > EOF
525 > EOF
381
526
382
527
383 shell alias defined in current repo
528 shell alias defined in current repo
384
529
385 $ hg subalias
530 $ hg subalias
386 sub
531 sub
387 $ hg --cwd .. subalias > /dev/null
532 $ hg --cwd .. subalias > /dev/null
388 hg: unknown command 'subalias'
533 hg: unknown command 'subalias'
389 (did you mean idalias?)
534 (did you mean idalias?)
390 [255]
535 [255]
391 $ hg -R .. subalias > /dev/null
536 $ hg -R .. subalias > /dev/null
392 hg: unknown command 'subalias'
537 hg: unknown command 'subalias'
393 (did you mean idalias?)
538 (did you mean idalias?)
394 [255]
539 [255]
395
540
396
541
397 shell alias defined in other repo
542 shell alias defined in other repo
398
543
399 $ hg mainalias > /dev/null
544 $ hg mainalias > /dev/null
400 hg: unknown command 'mainalias'
545 hg: unknown command 'mainalias'
401 (did you mean idalias?)
546 (did you mean idalias?)
402 [255]
547 [255]
403 $ hg -R .. mainalias
548 $ hg -R .. mainalias
404 main
549 main
405 $ hg --cwd .. mainalias
550 $ hg --cwd .. mainalias
406 main
551 main
407
552
408 typos get useful suggestions
553 typos get useful suggestions
409 $ hg --cwd .. manalias
554 $ hg --cwd .. manalias
410 hg: unknown command 'manalias'
555 hg: unknown command 'manalias'
411 (did you mean one of idalias, mainalias, manifest?)
556 (did you mean one of idalias, mainalias, manifest?)
412 [255]
557 [255]
413
558
414 shell aliases with escaped $ chars
559 shell aliases with escaped $ chars
415
560
416 $ hg escaped1
561 $ hg escaped1
417 test$test
562 test$test
418 $ hg escaped2
563 $ hg escaped2
419 HGFOO is BAR
564 HGFOO is BAR
420 $ hg escaped3 HGFOO
565 $ hg escaped3 HGFOO
421 HGFOO is BAR
566 HGFOO is BAR
422 $ hg escaped4 test
567 $ hg escaped4 test
423 $0 $@
568 $0 $@
424
569
425 abbreviated name, which matches against both shell alias and the
570 abbreviated name, which matches against both shell alias and the
426 command provided extension, should be aborted.
571 command provided extension, should be aborted.
427
572
428 $ cat >> .hg/hgrc <<EOF
573 $ cat >> .hg/hgrc <<EOF
429 > [extensions]
574 > [extensions]
430 > hgext.rebase =
575 > hgext.rebase =
431 > EOF
576 > EOF
432 #if windows
577 #if windows
433 $ cat >> .hg/hgrc <<EOF
578 $ cat >> .hg/hgrc <<EOF
434 > [alias]
579 > [alias]
435 > rebate = !echo this is %HG_ARGS%
580 > rebate = !echo this is %HG_ARGS%
436 > EOF
581 > EOF
437 #else
582 #else
438 $ cat >> .hg/hgrc <<EOF
583 $ cat >> .hg/hgrc <<EOF
439 > [alias]
584 > [alias]
440 > rebate = !echo this is \$HG_ARGS
585 > rebate = !echo this is \$HG_ARGS
441 > EOF
586 > EOF
442 #endif
587 #endif
588 $ cat >> .hg/hgrc <<EOF
589 > rebate:doc = This is my alias which just prints something.
590 > rebate:help = [MYARGS]
591 > EOF
443 $ hg reba
592 $ hg reba
444 hg: command 'reba' is ambiguous:
593 hg: command 'reba' is ambiguous:
445 rebase rebate
594 rebase rebate
446 [255]
595 [255]
447 $ hg rebat
596 $ hg rebat
448 this is rebate
597 this is rebate
449 $ hg rebat --foo-bar
598 $ hg rebat --foo-bar
450 this is rebate --foo-bar
599 this is rebate --foo-bar
451
600
601 help for a shell alias
602
603 $ hg help -c | grep rebate
604 rebate This is my alias which just prints something.
605 $ hg help rebate
606 hg rebate [MYARGS]
607
608 shell alias for: echo this is $HG_ARGS
609
610 This is my alias which just prints something.
611
612 defined by:* (glob)
613 */* (glob) (?)
614 */* (glob) (?)
615 */* (glob) (?)
616
617 (some details hidden, use --verbose to show complete help)
618
452 invalid arguments
619 invalid arguments
453
620
454 $ hg rt foo
621 $ hg rt foo
455 hg rt: invalid arguments
622 hg rt: invalid arguments
456 hg rt
623 hg rt
457
624
458 alias for: hg root
625 alias for: hg root
459
626
460 (use 'hg rt -h' to show more help)
627 (use 'hg rt -h' to show more help)
461 [255]
628 [255]
462
629
463 invalid global arguments for normal commands, aliases, and shell aliases
630 invalid global arguments for normal commands, aliases, and shell aliases
464
631
465 $ hg --invalid root
632 $ hg --invalid root
466 hg: option --invalid not recognized
633 hg: option --invalid not recognized
467 Mercurial Distributed SCM
634 Mercurial Distributed SCM
468
635
469 basic commands:
636 basic commands:
470
637
471 add add the specified files on the next commit
638 add add the specified files on the next commit
472 annotate show changeset information by line for each file
639 annotate show changeset information by line for each file
473 clone make a copy of an existing repository
640 clone make a copy of an existing repository
474 commit commit the specified files or all outstanding changes
641 commit commit the specified files or all outstanding changes
475 diff diff repository (or selected files)
642 diff diff repository (or selected files)
476 export dump the header and diffs for one or more changesets
643 export dump the header and diffs for one or more changesets
477 forget forget the specified files on the next commit
644 forget forget the specified files on the next commit
478 init create a new repository in the given directory
645 init create a new repository in the given directory
479 log show revision history of entire repository or files
646 log show revision history of entire repository or files
480 merge merge another revision into working directory
647 merge merge another revision into working directory
481 pull pull changes from the specified source
648 pull pull changes from the specified source
482 push push changes to the specified destination
649 push push changes to the specified destination
483 remove remove the specified files on the next commit
650 remove remove the specified files on the next commit
484 serve start stand-alone webserver
651 serve start stand-alone webserver
485 status show changed files in the working directory
652 status show changed files in the working directory
486 summary summarize working directory state
653 summary summarize working directory state
487 update update working directory (or switch revisions)
654 update update working directory (or switch revisions)
488
655
489 (use 'hg help' for the full list of commands or 'hg -v' for details)
656 (use 'hg help' for the full list of commands or 'hg -v' for details)
490 [255]
657 [255]
491 $ hg --invalid mylog
658 $ hg --invalid mylog
492 hg: option --invalid not recognized
659 hg: option --invalid not recognized
493 Mercurial Distributed SCM
660 Mercurial Distributed SCM
494
661
495 basic commands:
662 basic commands:
496
663
497 add add the specified files on the next commit
664 add add the specified files on the next commit
498 annotate show changeset information by line for each file
665 annotate show changeset information by line for each file
499 clone make a copy of an existing repository
666 clone make a copy of an existing repository
500 commit commit the specified files or all outstanding changes
667 commit commit the specified files or all outstanding changes
501 diff diff repository (or selected files)
668 diff diff repository (or selected files)
502 export dump the header and diffs for one or more changesets
669 export dump the header and diffs for one or more changesets
503 forget forget the specified files on the next commit
670 forget forget the specified files on the next commit
504 init create a new repository in the given directory
671 init create a new repository in the given directory
505 log show revision history of entire repository or files
672 log show revision history of entire repository or files
506 merge merge another revision into working directory
673 merge merge another revision into working directory
507 pull pull changes from the specified source
674 pull pull changes from the specified source
508 push push changes to the specified destination
675 push push changes to the specified destination
509 remove remove the specified files on the next commit
676 remove remove the specified files on the next commit
510 serve start stand-alone webserver
677 serve start stand-alone webserver
511 status show changed files in the working directory
678 status show changed files in the working directory
512 summary summarize working directory state
679 summary summarize working directory state
513 update update working directory (or switch revisions)
680 update update working directory (or switch revisions)
514
681
515 (use 'hg help' for the full list of commands or 'hg -v' for details)
682 (use 'hg help' for the full list of commands or 'hg -v' for details)
516 [255]
683 [255]
517 $ hg --invalid blank
684 $ hg --invalid blank
518 hg: option --invalid not recognized
685 hg: option --invalid not recognized
519 Mercurial Distributed SCM
686 Mercurial Distributed SCM
520
687
521 basic commands:
688 basic commands:
522
689
523 add add the specified files on the next commit
690 add add the specified files on the next commit
524 annotate show changeset information by line for each file
691 annotate show changeset information by line for each file
525 clone make a copy of an existing repository
692 clone make a copy of an existing repository
526 commit commit the specified files or all outstanding changes
693 commit commit the specified files or all outstanding changes
527 diff diff repository (or selected files)
694 diff diff repository (or selected files)
528 export dump the header and diffs for one or more changesets
695 export dump the header and diffs for one or more changesets
529 forget forget the specified files on the next commit
696 forget forget the specified files on the next commit
530 init create a new repository in the given directory
697 init create a new repository in the given directory
531 log show revision history of entire repository or files
698 log show revision history of entire repository or files
532 merge merge another revision into working directory
699 merge merge another revision into working directory
533 pull pull changes from the specified source
700 pull pull changes from the specified source
534 push push changes to the specified destination
701 push push changes to the specified destination
535 remove remove the specified files on the next commit
702 remove remove the specified files on the next commit
536 serve start stand-alone webserver
703 serve start stand-alone webserver
537 status show changed files in the working directory
704 status show changed files in the working directory
538 summary summarize working directory state
705 summary summarize working directory state
539 update update working directory (or switch revisions)
706 update update working directory (or switch revisions)
540
707
541 (use 'hg help' for the full list of commands or 'hg -v' for details)
708 (use 'hg help' for the full list of commands or 'hg -v' for details)
542 [255]
709 [255]
543
710
544 environment variable changes in alias commands
711 environment variable changes in alias commands
545
712
546 $ cat > $TESTTMP/expandalias.py <<EOF
713 $ cat > $TESTTMP/expandalias.py <<EOF
547 > import os
714 > import os
548 > from mercurial import cmdutil, commands, registrar
715 > from mercurial import cmdutil, commands, registrar
549 > cmdtable = {}
716 > cmdtable = {}
550 > command = registrar.command(cmdtable)
717 > command = registrar.command(cmdtable)
551 > @command(b'expandalias')
718 > @command(b'expandalias')
552 > def expandalias(ui, repo, name):
719 > def expandalias(ui, repo, name):
553 > alias = cmdutil.findcmd(name, commands.table)[1][0]
720 > alias = cmdutil.findcmd(name, commands.table)[1][0]
554 > ui.write(b'%s args: %s\n' % (name, b' '.join(alias.args)))
721 > ui.write(b'%s args: %s\n' % (name, b' '.join(alias.args)))
555 > os.environ['COUNT'] = '2'
722 > os.environ['COUNT'] = '2'
556 > ui.write(b'%s args: %s (with COUNT=2)\n' % (name, b' '.join(alias.args)))
723 > ui.write(b'%s args: %s (with COUNT=2)\n' % (name, b' '.join(alias.args)))
557 > EOF
724 > EOF
558
725
559 $ cat >> $HGRCPATH <<'EOF'
726 $ cat >> $HGRCPATH <<'EOF'
560 > [extensions]
727 > [extensions]
561 > expandalias = $TESTTMP/expandalias.py
728 > expandalias = $TESTTMP/expandalias.py
562 > [alias]
729 > [alias]
563 > showcount = log -T "$COUNT" -r .
730 > showcount = log -T "$COUNT" -r .
564 > EOF
731 > EOF
565
732
566 $ COUNT=1 hg expandalias showcount
733 $ COUNT=1 hg expandalias showcount
567 showcount args: -T 1 -r .
734 showcount args: -T 1 -r .
568 showcount args: -T 2 -r . (with COUNT=2)
735 showcount args: -T 2 -r . (with COUNT=2)
569
736
570 This should show id:
737 This should show id:
571
738
572 $ hg --config alias.log='id' log
739 $ hg --config alias.log='id' log
573 000000000000 tip
740 000000000000 tip
574
741
575 This shouldn't:
742 This shouldn't:
576
743
577 $ hg --config alias.log='id' history
744 $ hg --config alias.log='id' history
578
745
579 $ cd ../..
746 $ cd ../..
580
747
581 return code of command and shell aliases:
748 return code of command and shell aliases:
582
749
583 $ hg mycommit -R alias
750 $ hg mycommit -R alias
584 nothing changed
751 nothing changed
585 [1]
752 [1]
586 $ hg exit1
753 $ hg exit1
587 [1]
754 [1]
588
755
589 #if no-outer-repo
756 #if no-outer-repo
590 $ hg root
757 $ hg root
591 abort: no repository found in '$TESTTMP' (.hg not found)!
758 abort: no repository found in '$TESTTMP' (.hg not found)!
592 [255]
759 [255]
593 $ hg --config alias.hgroot='!hg root' hgroot
760 $ hg --config alias.hgroot='!hg root' hgroot
594 abort: no repository found in '$TESTTMP' (.hg not found)!
761 abort: no repository found in '$TESTTMP' (.hg not found)!
595 [255]
762 [255]
596 #endif
763 #endif
@@ -1,3494 +1,3494 b''
1 Short help:
1 Short help:
2
2
3 $ hg
3 $ hg
4 Mercurial Distributed SCM
4 Mercurial Distributed SCM
5
5
6 basic commands:
6 basic commands:
7
7
8 add add the specified files on the next commit
8 add add the specified files on the next commit
9 annotate show changeset information by line for each file
9 annotate show changeset information by line for each file
10 clone make a copy of an existing repository
10 clone make a copy of an existing repository
11 commit commit the specified files or all outstanding changes
11 commit commit the specified files or all outstanding changes
12 diff diff repository (or selected files)
12 diff diff repository (or selected files)
13 export dump the header and diffs for one or more changesets
13 export dump the header and diffs for one or more changesets
14 forget forget the specified files on the next commit
14 forget forget the specified files on the next commit
15 init create a new repository in the given directory
15 init create a new repository in the given directory
16 log show revision history of entire repository or files
16 log show revision history of entire repository or files
17 merge merge another revision into working directory
17 merge merge another revision into working directory
18 pull pull changes from the specified source
18 pull pull changes from the specified source
19 push push changes to the specified destination
19 push push changes to the specified destination
20 remove remove the specified files on the next commit
20 remove remove the specified files on the next commit
21 serve start stand-alone webserver
21 serve start stand-alone webserver
22 status show changed files in the working directory
22 status show changed files in the working directory
23 summary summarize working directory state
23 summary summarize working directory state
24 update update working directory (or switch revisions)
24 update update working directory (or switch revisions)
25
25
26 (use 'hg help' for the full list of commands or 'hg -v' for details)
26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27
27
28 $ hg -q
28 $ hg -q
29 add add the specified files on the next commit
29 add add the specified files on the next commit
30 annotate show changeset information by line for each file
30 annotate show changeset information by line for each file
31 clone make a copy of an existing repository
31 clone make a copy of an existing repository
32 commit commit the specified files or all outstanding changes
32 commit commit the specified files or all outstanding changes
33 diff diff repository (or selected files)
33 diff diff repository (or selected files)
34 export dump the header and diffs for one or more changesets
34 export dump the header and diffs for one or more changesets
35 forget forget the specified files on the next commit
35 forget forget the specified files on the next commit
36 init create a new repository in the given directory
36 init create a new repository in the given directory
37 log show revision history of entire repository or files
37 log show revision history of entire repository or files
38 merge merge another revision into working directory
38 merge merge another revision into working directory
39 pull pull changes from the specified source
39 pull pull changes from the specified source
40 push push changes to the specified destination
40 push push changes to the specified destination
41 remove remove the specified files on the next commit
41 remove remove the specified files on the next commit
42 serve start stand-alone webserver
42 serve start stand-alone webserver
43 status show changed files in the working directory
43 status show changed files in the working directory
44 summary summarize working directory state
44 summary summarize working directory state
45 update update working directory (or switch revisions)
45 update update working directory (or switch revisions)
46
46
47 $ hg help
47 $ hg help
48 Mercurial Distributed SCM
48 Mercurial Distributed SCM
49
49
50 list of commands:
50 list of commands:
51
51
52 add add the specified files on the next commit
52 add add the specified files on the next commit
53 addremove add all new files, delete all missing files
53 addremove add all new files, delete all missing files
54 annotate show changeset information by line for each file
54 annotate show changeset information by line for each file
55 archive create an unversioned archive of a repository revision
55 archive create an unversioned archive of a repository revision
56 backout reverse effect of earlier changeset
56 backout reverse effect of earlier changeset
57 bisect subdivision search of changesets
57 bisect subdivision search of changesets
58 bookmarks create a new bookmark or list existing bookmarks
58 bookmarks create a new bookmark or list existing bookmarks
59 branch set or show the current branch name
59 branch set or show the current branch name
60 branches list repository named branches
60 branches list repository named branches
61 bundle create a bundle file
61 bundle create a bundle file
62 cat output the current or given revision of files
62 cat output the current or given revision of files
63 clone make a copy of an existing repository
63 clone make a copy of an existing repository
64 commit commit the specified files or all outstanding changes
64 commit commit the specified files or all outstanding changes
65 config show combined config settings from all hgrc files
65 config show combined config settings from all hgrc files
66 copy mark files as copied for the next commit
66 copy mark files as copied for the next commit
67 diff diff repository (or selected files)
67 diff diff repository (or selected files)
68 export dump the header and diffs for one or more changesets
68 export dump the header and diffs for one or more changesets
69 files list tracked files
69 files list tracked files
70 forget forget the specified files on the next commit
70 forget forget the specified files on the next commit
71 graft copy changes from other branches onto the current branch
71 graft copy changes from other branches onto the current branch
72 grep search revision history for a pattern in specified files
72 grep search revision history for a pattern in specified files
73 heads show branch heads
73 heads show branch heads
74 help show help for a given topic or a help overview
74 help show help for a given topic or a help overview
75 identify identify the working directory or specified revision
75 identify identify the working directory or specified revision
76 import import an ordered set of patches
76 import import an ordered set of patches
77 incoming show new changesets found in source
77 incoming show new changesets found in source
78 init create a new repository in the given directory
78 init create a new repository in the given directory
79 log show revision history of entire repository or files
79 log show revision history of entire repository or files
80 manifest output the current or given revision of the project manifest
80 manifest output the current or given revision of the project manifest
81 merge merge another revision into working directory
81 merge merge another revision into working directory
82 outgoing show changesets not found in the destination
82 outgoing show changesets not found in the destination
83 paths show aliases for remote repositories
83 paths show aliases for remote repositories
84 phase set or show the current phase name
84 phase set or show the current phase name
85 pull pull changes from the specified source
85 pull pull changes from the specified source
86 push push changes to the specified destination
86 push push changes to the specified destination
87 recover roll back an interrupted transaction
87 recover roll back an interrupted transaction
88 remove remove the specified files on the next commit
88 remove remove the specified files on the next commit
89 rename rename files; equivalent of copy + remove
89 rename rename files; equivalent of copy + remove
90 resolve redo merges or set/view the merge status of files
90 resolve redo merges or set/view the merge status of files
91 revert restore files to their checkout state
91 revert restore files to their checkout state
92 root print the root (top) of the current working directory
92 root print the root (top) of the current working directory
93 serve start stand-alone webserver
93 serve start stand-alone webserver
94 status show changed files in the working directory
94 status show changed files in the working directory
95 summary summarize working directory state
95 summary summarize working directory state
96 tag add one or more tags for the current or given revision
96 tag add one or more tags for the current or given revision
97 tags list repository tags
97 tags list repository tags
98 unbundle apply one or more bundle files
98 unbundle apply one or more bundle files
99 update update working directory (or switch revisions)
99 update update working directory (or switch revisions)
100 verify verify the integrity of the repository
100 verify verify the integrity of the repository
101 version output version and copyright information
101 version output version and copyright information
102
102
103 additional help topics:
103 additional help topics:
104
104
105 bundlespec Bundle File Formats
105 bundlespec Bundle File Formats
106 color Colorizing Outputs
106 color Colorizing Outputs
107 config Configuration Files
107 config Configuration Files
108 dates Date Formats
108 dates Date Formats
109 diffs Diff Formats
109 diffs Diff Formats
110 environment Environment Variables
110 environment Environment Variables
111 extensions Using Additional Features
111 extensions Using Additional Features
112 filesets Specifying File Sets
112 filesets Specifying File Sets
113 flags Command-line flags
113 flags Command-line flags
114 glossary Glossary
114 glossary Glossary
115 hgignore Syntax for Mercurial Ignore Files
115 hgignore Syntax for Mercurial Ignore Files
116 hgweb Configuring hgweb
116 hgweb Configuring hgweb
117 internals Technical implementation topics
117 internals Technical implementation topics
118 merge-tools Merge Tools
118 merge-tools Merge Tools
119 pager Pager Support
119 pager Pager Support
120 patterns File Name Patterns
120 patterns File Name Patterns
121 phases Working with Phases
121 phases Working with Phases
122 revisions Specifying Revisions
122 revisions Specifying Revisions
123 scripting Using Mercurial from scripts and automation
123 scripting Using Mercurial from scripts and automation
124 subrepos Subrepositories
124 subrepos Subrepositories
125 templating Template Usage
125 templating Template Usage
126 urls URL Paths
126 urls URL Paths
127
127
128 (use 'hg help -v' to show built-in aliases and global options)
128 (use 'hg help -v' to show built-in aliases and global options)
129
129
130 $ hg -q help
130 $ hg -q help
131 add add the specified files on the next commit
131 add add the specified files on the next commit
132 addremove add all new files, delete all missing files
132 addremove add all new files, delete all missing files
133 annotate show changeset information by line for each file
133 annotate show changeset information by line for each file
134 archive create an unversioned archive of a repository revision
134 archive create an unversioned archive of a repository revision
135 backout reverse effect of earlier changeset
135 backout reverse effect of earlier changeset
136 bisect subdivision search of changesets
136 bisect subdivision search of changesets
137 bookmarks create a new bookmark or list existing bookmarks
137 bookmarks create a new bookmark or list existing bookmarks
138 branch set or show the current branch name
138 branch set or show the current branch name
139 branches list repository named branches
139 branches list repository named branches
140 bundle create a bundle file
140 bundle create a bundle file
141 cat output the current or given revision of files
141 cat output the current or given revision of files
142 clone make a copy of an existing repository
142 clone make a copy of an existing repository
143 commit commit the specified files or all outstanding changes
143 commit commit the specified files or all outstanding changes
144 config show combined config settings from all hgrc files
144 config show combined config settings from all hgrc files
145 copy mark files as copied for the next commit
145 copy mark files as copied for the next commit
146 diff diff repository (or selected files)
146 diff diff repository (or selected files)
147 export dump the header and diffs for one or more changesets
147 export dump the header and diffs for one or more changesets
148 files list tracked files
148 files list tracked files
149 forget forget the specified files on the next commit
149 forget forget the specified files on the next commit
150 graft copy changes from other branches onto the current branch
150 graft copy changes from other branches onto the current branch
151 grep search revision history for a pattern in specified files
151 grep search revision history for a pattern in specified files
152 heads show branch heads
152 heads show branch heads
153 help show help for a given topic or a help overview
153 help show help for a given topic or a help overview
154 identify identify the working directory or specified revision
154 identify identify the working directory or specified revision
155 import import an ordered set of patches
155 import import an ordered set of patches
156 incoming show new changesets found in source
156 incoming show new changesets found in source
157 init create a new repository in the given directory
157 init create a new repository in the given directory
158 log show revision history of entire repository or files
158 log show revision history of entire repository or files
159 manifest output the current or given revision of the project manifest
159 manifest output the current or given revision of the project manifest
160 merge merge another revision into working directory
160 merge merge another revision into working directory
161 outgoing show changesets not found in the destination
161 outgoing show changesets not found in the destination
162 paths show aliases for remote repositories
162 paths show aliases for remote repositories
163 phase set or show the current phase name
163 phase set or show the current phase name
164 pull pull changes from the specified source
164 pull pull changes from the specified source
165 push push changes to the specified destination
165 push push changes to the specified destination
166 recover roll back an interrupted transaction
166 recover roll back an interrupted transaction
167 remove remove the specified files on the next commit
167 remove remove the specified files on the next commit
168 rename rename files; equivalent of copy + remove
168 rename rename files; equivalent of copy + remove
169 resolve redo merges or set/view the merge status of files
169 resolve redo merges or set/view the merge status of files
170 revert restore files to their checkout state
170 revert restore files to their checkout state
171 root print the root (top) of the current working directory
171 root print the root (top) of the current working directory
172 serve start stand-alone webserver
172 serve start stand-alone webserver
173 status show changed files in the working directory
173 status show changed files in the working directory
174 summary summarize working directory state
174 summary summarize working directory state
175 tag add one or more tags for the current or given revision
175 tag add one or more tags for the current or given revision
176 tags list repository tags
176 tags list repository tags
177 unbundle apply one or more bundle files
177 unbundle apply one or more bundle files
178 update update working directory (or switch revisions)
178 update update working directory (or switch revisions)
179 verify verify the integrity of the repository
179 verify verify the integrity of the repository
180 version output version and copyright information
180 version output version and copyright information
181
181
182 additional help topics:
182 additional help topics:
183
183
184 bundlespec Bundle File Formats
184 bundlespec Bundle File Formats
185 color Colorizing Outputs
185 color Colorizing Outputs
186 config Configuration Files
186 config Configuration Files
187 dates Date Formats
187 dates Date Formats
188 diffs Diff Formats
188 diffs Diff Formats
189 environment Environment Variables
189 environment Environment Variables
190 extensions Using Additional Features
190 extensions Using Additional Features
191 filesets Specifying File Sets
191 filesets Specifying File Sets
192 flags Command-line flags
192 flags Command-line flags
193 glossary Glossary
193 glossary Glossary
194 hgignore Syntax for Mercurial Ignore Files
194 hgignore Syntax for Mercurial Ignore Files
195 hgweb Configuring hgweb
195 hgweb Configuring hgweb
196 internals Technical implementation topics
196 internals Technical implementation topics
197 merge-tools Merge Tools
197 merge-tools Merge Tools
198 pager Pager Support
198 pager Pager Support
199 patterns File Name Patterns
199 patterns File Name Patterns
200 phases Working with Phases
200 phases Working with Phases
201 revisions Specifying Revisions
201 revisions Specifying Revisions
202 scripting Using Mercurial from scripts and automation
202 scripting Using Mercurial from scripts and automation
203 subrepos Subrepositories
203 subrepos Subrepositories
204 templating Template Usage
204 templating Template Usage
205 urls URL Paths
205 urls URL Paths
206
206
207 Test extension help:
207 Test extension help:
208 $ hg help extensions --config extensions.rebase= --config extensions.children=
208 $ hg help extensions --config extensions.rebase= --config extensions.children=
209 Using Additional Features
209 Using Additional Features
210 """""""""""""""""""""""""
210 """""""""""""""""""""""""
211
211
212 Mercurial has the ability to add new features through the use of
212 Mercurial has the ability to add new features through the use of
213 extensions. Extensions may add new commands, add options to existing
213 extensions. Extensions may add new commands, add options to existing
214 commands, change the default behavior of commands, or implement hooks.
214 commands, change the default behavior of commands, or implement hooks.
215
215
216 To enable the "foo" extension, either shipped with Mercurial or in the
216 To enable the "foo" extension, either shipped with Mercurial or in the
217 Python search path, create an entry for it in your configuration file,
217 Python search path, create an entry for it in your configuration file,
218 like this:
218 like this:
219
219
220 [extensions]
220 [extensions]
221 foo =
221 foo =
222
222
223 You may also specify the full path to an extension:
223 You may also specify the full path to an extension:
224
224
225 [extensions]
225 [extensions]
226 myfeature = ~/.hgext/myfeature.py
226 myfeature = ~/.hgext/myfeature.py
227
227
228 See 'hg help config' for more information on configuration files.
228 See 'hg help config' for more information on configuration files.
229
229
230 Extensions are not loaded by default for a variety of reasons: they can
230 Extensions are not loaded by default for a variety of reasons: they can
231 increase startup overhead; they may be meant for advanced usage only; they
231 increase startup overhead; they may be meant for advanced usage only; they
232 may provide potentially dangerous abilities (such as letting you destroy
232 may provide potentially dangerous abilities (such as letting you destroy
233 or modify history); they might not be ready for prime time; or they may
233 or modify history); they might not be ready for prime time; or they may
234 alter some usual behaviors of stock Mercurial. It is thus up to the user
234 alter some usual behaviors of stock Mercurial. It is thus up to the user
235 to activate extensions as needed.
235 to activate extensions as needed.
236
236
237 To explicitly disable an extension enabled in a configuration file of
237 To explicitly disable an extension enabled in a configuration file of
238 broader scope, prepend its path with !:
238 broader scope, prepend its path with !:
239
239
240 [extensions]
240 [extensions]
241 # disabling extension bar residing in /path/to/extension/bar.py
241 # disabling extension bar residing in /path/to/extension/bar.py
242 bar = !/path/to/extension/bar.py
242 bar = !/path/to/extension/bar.py
243 # ditto, but no path was supplied for extension baz
243 # ditto, but no path was supplied for extension baz
244 baz = !
244 baz = !
245
245
246 enabled extensions:
246 enabled extensions:
247
247
248 children command to display child changesets (DEPRECATED)
248 children command to display child changesets (DEPRECATED)
249 rebase command to move sets of revisions to a different ancestor
249 rebase command to move sets of revisions to a different ancestor
250
250
251 disabled extensions:
251 disabled extensions:
252
252
253 acl hooks for controlling repository access
253 acl hooks for controlling repository access
254 blackbox log repository events to a blackbox for debugging
254 blackbox log repository events to a blackbox for debugging
255 bugzilla hooks for integrating with the Bugzilla bug tracker
255 bugzilla hooks for integrating with the Bugzilla bug tracker
256 censor erase file content at a given revision
256 censor erase file content at a given revision
257 churn command to display statistics about repository history
257 churn command to display statistics about repository history
258 clonebundles advertise pre-generated bundles to seed clones
258 clonebundles advertise pre-generated bundles to seed clones
259 convert import revisions from foreign VCS repositories into
259 convert import revisions from foreign VCS repositories into
260 Mercurial
260 Mercurial
261 eol automatically manage newlines in repository files
261 eol automatically manage newlines in repository files
262 extdiff command to allow external programs to compare revisions
262 extdiff command to allow external programs to compare revisions
263 factotum http authentication with factotum
263 factotum http authentication with factotum
264 githelp try mapping git commands to Mercurial commands
264 githelp try mapping git commands to Mercurial commands
265 gpg commands to sign and verify changesets
265 gpg commands to sign and verify changesets
266 hgk browse the repository in a graphical way
266 hgk browse the repository in a graphical way
267 highlight syntax highlighting for hgweb (requires Pygments)
267 highlight syntax highlighting for hgweb (requires Pygments)
268 histedit interactive history editing
268 histedit interactive history editing
269 keyword expand keywords in tracked files
269 keyword expand keywords in tracked files
270 largefiles track large binary files
270 largefiles track large binary files
271 mq manage a stack of patches
271 mq manage a stack of patches
272 notify hooks for sending email push notifications
272 notify hooks for sending email push notifications
273 patchbomb command to send changesets as (a series of) patch emails
273 patchbomb command to send changesets as (a series of) patch emails
274 purge command to delete untracked files from the working
274 purge command to delete untracked files from the working
275 directory
275 directory
276 relink recreates hardlinks between repository clones
276 relink recreates hardlinks between repository clones
277 remotenames showing remotebookmarks and remotebranches in UI
277 remotenames showing remotebookmarks and remotebranches in UI
278 schemes extend schemes with shortcuts to repository swarms
278 schemes extend schemes with shortcuts to repository swarms
279 share share a common history between several working directories
279 share share a common history between several working directories
280 shelve save and restore changes to the working directory
280 shelve save and restore changes to the working directory
281 strip strip changesets and their descendants from history
281 strip strip changesets and their descendants from history
282 transplant command to transplant changesets from another branch
282 transplant command to transplant changesets from another branch
283 win32mbcs allow the use of MBCS paths with problematic encodings
283 win32mbcs allow the use of MBCS paths with problematic encodings
284 zeroconf discover and advertise repositories on the local network
284 zeroconf discover and advertise repositories on the local network
285
285
286 Verify that deprecated extensions are included if --verbose:
286 Verify that deprecated extensions are included if --verbose:
287
287
288 $ hg -v help extensions | grep children
288 $ hg -v help extensions | grep children
289 children command to display child changesets (DEPRECATED)
289 children command to display child changesets (DEPRECATED)
290
290
291 Verify that extension keywords appear in help templates
291 Verify that extension keywords appear in help templates
292
292
293 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
293 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
294
294
295 Test short command list with verbose option
295 Test short command list with verbose option
296
296
297 $ hg -v help shortlist
297 $ hg -v help shortlist
298 Mercurial Distributed SCM
298 Mercurial Distributed SCM
299
299
300 basic commands:
300 basic commands:
301
301
302 add add the specified files on the next commit
302 add add the specified files on the next commit
303 annotate, blame
303 annotate, blame
304 show changeset information by line for each file
304 show changeset information by line for each file
305 clone make a copy of an existing repository
305 clone make a copy of an existing repository
306 commit, ci commit the specified files or all outstanding changes
306 commit, ci commit the specified files or all outstanding changes
307 diff diff repository (or selected files)
307 diff diff repository (or selected files)
308 export dump the header and diffs for one or more changesets
308 export dump the header and diffs for one or more changesets
309 forget forget the specified files on the next commit
309 forget forget the specified files on the next commit
310 init create a new repository in the given directory
310 init create a new repository in the given directory
311 log, history show revision history of entire repository or files
311 log, history show revision history of entire repository or files
312 merge merge another revision into working directory
312 merge merge another revision into working directory
313 pull pull changes from the specified source
313 pull pull changes from the specified source
314 push push changes to the specified destination
314 push push changes to the specified destination
315 remove, rm remove the specified files on the next commit
315 remove, rm remove the specified files on the next commit
316 serve start stand-alone webserver
316 serve start stand-alone webserver
317 status, st show changed files in the working directory
317 status, st show changed files in the working directory
318 summary, sum summarize working directory state
318 summary, sum summarize working directory state
319 update, up, checkout, co
319 update, up, checkout, co
320 update working directory (or switch revisions)
320 update working directory (or switch revisions)
321
321
322 global options ([+] can be repeated):
322 global options ([+] can be repeated):
323
323
324 -R --repository REPO repository root directory or name of overlay bundle
324 -R --repository REPO repository root directory or name of overlay bundle
325 file
325 file
326 --cwd DIR change working directory
326 --cwd DIR change working directory
327 -y --noninteractive do not prompt, automatically pick the first choice for
327 -y --noninteractive do not prompt, automatically pick the first choice for
328 all prompts
328 all prompts
329 -q --quiet suppress output
329 -q --quiet suppress output
330 -v --verbose enable additional output
330 -v --verbose enable additional output
331 --color TYPE when to colorize (boolean, always, auto, never, or
331 --color TYPE when to colorize (boolean, always, auto, never, or
332 debug)
332 debug)
333 --config CONFIG [+] set/override config option (use 'section.name=value')
333 --config CONFIG [+] set/override config option (use 'section.name=value')
334 --debug enable debugging output
334 --debug enable debugging output
335 --debugger start debugger
335 --debugger start debugger
336 --encoding ENCODE set the charset encoding (default: ascii)
336 --encoding ENCODE set the charset encoding (default: ascii)
337 --encodingmode MODE set the charset encoding mode (default: strict)
337 --encodingmode MODE set the charset encoding mode (default: strict)
338 --traceback always print a traceback on exception
338 --traceback always print a traceback on exception
339 --time time how long the command takes
339 --time time how long the command takes
340 --profile print command execution profile
340 --profile print command execution profile
341 --version output version information and exit
341 --version output version information and exit
342 -h --help display help and exit
342 -h --help display help and exit
343 --hidden consider hidden changesets
343 --hidden consider hidden changesets
344 --pager TYPE when to paginate (boolean, always, auto, or never)
344 --pager TYPE when to paginate (boolean, always, auto, or never)
345 (default: auto)
345 (default: auto)
346
346
347 (use 'hg help' for the full list of commands)
347 (use 'hg help' for the full list of commands)
348
348
349 $ hg add -h
349 $ hg add -h
350 hg add [OPTION]... [FILE]...
350 hg add [OPTION]... [FILE]...
351
351
352 add the specified files on the next commit
352 add the specified files on the next commit
353
353
354 Schedule files to be version controlled and added to the repository.
354 Schedule files to be version controlled and added to the repository.
355
355
356 The files will be added to the repository at the next commit. To undo an
356 The files will be added to the repository at the next commit. To undo an
357 add before that, see 'hg forget'.
357 add before that, see 'hg forget'.
358
358
359 If no names are given, add all files to the repository (except files
359 If no names are given, add all files to the repository (except files
360 matching ".hgignore").
360 matching ".hgignore").
361
361
362 Returns 0 if all files are successfully added.
362 Returns 0 if all files are successfully added.
363
363
364 options ([+] can be repeated):
364 options ([+] can be repeated):
365
365
366 -I --include PATTERN [+] include names matching the given patterns
366 -I --include PATTERN [+] include names matching the given patterns
367 -X --exclude PATTERN [+] exclude names matching the given patterns
367 -X --exclude PATTERN [+] exclude names matching the given patterns
368 -S --subrepos recurse into subrepositories
368 -S --subrepos recurse into subrepositories
369 -n --dry-run do not perform actions, just print output
369 -n --dry-run do not perform actions, just print output
370
370
371 (some details hidden, use --verbose to show complete help)
371 (some details hidden, use --verbose to show complete help)
372
372
373 Verbose help for add
373 Verbose help for add
374
374
375 $ hg add -hv
375 $ hg add -hv
376 hg add [OPTION]... [FILE]...
376 hg add [OPTION]... [FILE]...
377
377
378 add the specified files on the next commit
378 add the specified files on the next commit
379
379
380 Schedule files to be version controlled and added to the repository.
380 Schedule files to be version controlled and added to the repository.
381
381
382 The files will be added to the repository at the next commit. To undo an
382 The files will be added to the repository at the next commit. To undo an
383 add before that, see 'hg forget'.
383 add before that, see 'hg forget'.
384
384
385 If no names are given, add all files to the repository (except files
385 If no names are given, add all files to the repository (except files
386 matching ".hgignore").
386 matching ".hgignore").
387
387
388 Examples:
388 Examples:
389
389
390 - New (unknown) files are added automatically by 'hg add':
390 - New (unknown) files are added automatically by 'hg add':
391
391
392 $ ls
392 $ ls
393 foo.c
393 foo.c
394 $ hg status
394 $ hg status
395 ? foo.c
395 ? foo.c
396 $ hg add
396 $ hg add
397 adding foo.c
397 adding foo.c
398 $ hg status
398 $ hg status
399 A foo.c
399 A foo.c
400
400
401 - Specific files to be added can be specified:
401 - Specific files to be added can be specified:
402
402
403 $ ls
403 $ ls
404 bar.c foo.c
404 bar.c foo.c
405 $ hg status
405 $ hg status
406 ? bar.c
406 ? bar.c
407 ? foo.c
407 ? foo.c
408 $ hg add bar.c
408 $ hg add bar.c
409 $ hg status
409 $ hg status
410 A bar.c
410 A bar.c
411 ? foo.c
411 ? foo.c
412
412
413 Returns 0 if all files are successfully added.
413 Returns 0 if all files are successfully added.
414
414
415 options ([+] can be repeated):
415 options ([+] can be repeated):
416
416
417 -I --include PATTERN [+] include names matching the given patterns
417 -I --include PATTERN [+] include names matching the given patterns
418 -X --exclude PATTERN [+] exclude names matching the given patterns
418 -X --exclude PATTERN [+] exclude names matching the given patterns
419 -S --subrepos recurse into subrepositories
419 -S --subrepos recurse into subrepositories
420 -n --dry-run do not perform actions, just print output
420 -n --dry-run do not perform actions, just print output
421
421
422 global options ([+] can be repeated):
422 global options ([+] can be repeated):
423
423
424 -R --repository REPO repository root directory or name of overlay bundle
424 -R --repository REPO repository root directory or name of overlay bundle
425 file
425 file
426 --cwd DIR change working directory
426 --cwd DIR change working directory
427 -y --noninteractive do not prompt, automatically pick the first choice for
427 -y --noninteractive do not prompt, automatically pick the first choice for
428 all prompts
428 all prompts
429 -q --quiet suppress output
429 -q --quiet suppress output
430 -v --verbose enable additional output
430 -v --verbose enable additional output
431 --color TYPE when to colorize (boolean, always, auto, never, or
431 --color TYPE when to colorize (boolean, always, auto, never, or
432 debug)
432 debug)
433 --config CONFIG [+] set/override config option (use 'section.name=value')
433 --config CONFIG [+] set/override config option (use 'section.name=value')
434 --debug enable debugging output
434 --debug enable debugging output
435 --debugger start debugger
435 --debugger start debugger
436 --encoding ENCODE set the charset encoding (default: ascii)
436 --encoding ENCODE set the charset encoding (default: ascii)
437 --encodingmode MODE set the charset encoding mode (default: strict)
437 --encodingmode MODE set the charset encoding mode (default: strict)
438 --traceback always print a traceback on exception
438 --traceback always print a traceback on exception
439 --time time how long the command takes
439 --time time how long the command takes
440 --profile print command execution profile
440 --profile print command execution profile
441 --version output version information and exit
441 --version output version information and exit
442 -h --help display help and exit
442 -h --help display help and exit
443 --hidden consider hidden changesets
443 --hidden consider hidden changesets
444 --pager TYPE when to paginate (boolean, always, auto, or never)
444 --pager TYPE when to paginate (boolean, always, auto, or never)
445 (default: auto)
445 (default: auto)
446
446
447 Test the textwidth config option
447 Test the textwidth config option
448
448
449 $ hg root -h --config ui.textwidth=50
449 $ hg root -h --config ui.textwidth=50
450 hg root
450 hg root
451
451
452 print the root (top) of the current working
452 print the root (top) of the current working
453 directory
453 directory
454
454
455 Print the root directory of the current
455 Print the root directory of the current
456 repository.
456 repository.
457
457
458 Returns 0 on success.
458 Returns 0 on success.
459
459
460 (some details hidden, use --verbose to show
460 (some details hidden, use --verbose to show
461 complete help)
461 complete help)
462
462
463 Test help option with version option
463 Test help option with version option
464
464
465 $ hg add -h --version
465 $ hg add -h --version
466 Mercurial Distributed SCM (version *) (glob)
466 Mercurial Distributed SCM (version *) (glob)
467 (see https://mercurial-scm.org for more information)
467 (see https://mercurial-scm.org for more information)
468
468
469 Copyright (C) 2005-* Matt Mackall and others (glob)
469 Copyright (C) 2005-* Matt Mackall and others (glob)
470 This is free software; see the source for copying conditions. There is NO
470 This is free software; see the source for copying conditions. There is NO
471 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
471 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
472
472
473 $ hg add --skjdfks
473 $ hg add --skjdfks
474 hg add: option --skjdfks not recognized
474 hg add: option --skjdfks not recognized
475 hg add [OPTION]... [FILE]...
475 hg add [OPTION]... [FILE]...
476
476
477 add the specified files on the next commit
477 add the specified files on the next commit
478
478
479 options ([+] can be repeated):
479 options ([+] can be repeated):
480
480
481 -I --include PATTERN [+] include names matching the given patterns
481 -I --include PATTERN [+] include names matching the given patterns
482 -X --exclude PATTERN [+] exclude names matching the given patterns
482 -X --exclude PATTERN [+] exclude names matching the given patterns
483 -S --subrepos recurse into subrepositories
483 -S --subrepos recurse into subrepositories
484 -n --dry-run do not perform actions, just print output
484 -n --dry-run do not perform actions, just print output
485
485
486 (use 'hg add -h' to show more help)
486 (use 'hg add -h' to show more help)
487 [255]
487 [255]
488
488
489 Test ambiguous command help
489 Test ambiguous command help
490
490
491 $ hg help ad
491 $ hg help ad
492 list of commands:
492 list of commands:
493
493
494 add add the specified files on the next commit
494 add add the specified files on the next commit
495 addremove add all new files, delete all missing files
495 addremove add all new files, delete all missing files
496
496
497 (use 'hg help -v ad' to show built-in aliases and global options)
497 (use 'hg help -v ad' to show built-in aliases and global options)
498
498
499 Test command without options
499 Test command without options
500
500
501 $ hg help verify
501 $ hg help verify
502 hg verify
502 hg verify
503
503
504 verify the integrity of the repository
504 verify the integrity of the repository
505
505
506 Verify the integrity of the current repository.
506 Verify the integrity of the current repository.
507
507
508 This will perform an extensive check of the repository's integrity,
508 This will perform an extensive check of the repository's integrity,
509 validating the hashes and checksums of each entry in the changelog,
509 validating the hashes and checksums of each entry in the changelog,
510 manifest, and tracked files, as well as the integrity of their crosslinks
510 manifest, and tracked files, as well as the integrity of their crosslinks
511 and indices.
511 and indices.
512
512
513 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
513 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
514 information about recovery from corruption of the repository.
514 information about recovery from corruption of the repository.
515
515
516 Returns 0 on success, 1 if errors are encountered.
516 Returns 0 on success, 1 if errors are encountered.
517
517
518 (some details hidden, use --verbose to show complete help)
518 (some details hidden, use --verbose to show complete help)
519
519
520 $ hg help diff
520 $ hg help diff
521 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
521 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
522
522
523 diff repository (or selected files)
523 diff repository (or selected files)
524
524
525 Show differences between revisions for the specified files.
525 Show differences between revisions for the specified files.
526
526
527 Differences between files are shown using the unified diff format.
527 Differences between files are shown using the unified diff format.
528
528
529 Note:
529 Note:
530 'hg diff' may generate unexpected results for merges, as it will
530 'hg diff' may generate unexpected results for merges, as it will
531 default to comparing against the working directory's first parent
531 default to comparing against the working directory's first parent
532 changeset if no revisions are specified.
532 changeset if no revisions are specified.
533
533
534 When two revision arguments are given, then changes are shown between
534 When two revision arguments are given, then changes are shown between
535 those revisions. If only one revision is specified then that revision is
535 those revisions. If only one revision is specified then that revision is
536 compared to the working directory, and, when no revisions are specified,
536 compared to the working directory, and, when no revisions are specified,
537 the working directory files are compared to its first parent.
537 the working directory files are compared to its first parent.
538
538
539 Alternatively you can specify -c/--change with a revision to see the
539 Alternatively you can specify -c/--change with a revision to see the
540 changes in that changeset relative to its first parent.
540 changes in that changeset relative to its first parent.
541
541
542 Without the -a/--text option, diff will avoid generating diffs of files it
542 Without the -a/--text option, diff will avoid generating diffs of files it
543 detects as binary. With -a, diff will generate a diff anyway, probably
543 detects as binary. With -a, diff will generate a diff anyway, probably
544 with undesirable results.
544 with undesirable results.
545
545
546 Use the -g/--git option to generate diffs in the git extended diff format.
546 Use the -g/--git option to generate diffs in the git extended diff format.
547 For more information, read 'hg help diffs'.
547 For more information, read 'hg help diffs'.
548
548
549 Returns 0 on success.
549 Returns 0 on success.
550
550
551 options ([+] can be repeated):
551 options ([+] can be repeated):
552
552
553 -r --rev REV [+] revision
553 -r --rev REV [+] revision
554 -c --change REV change made by revision
554 -c --change REV change made by revision
555 -a --text treat all files as text
555 -a --text treat all files as text
556 -g --git use git extended diff format
556 -g --git use git extended diff format
557 --binary generate binary diffs in git mode (default)
557 --binary generate binary diffs in git mode (default)
558 --nodates omit dates from diff headers
558 --nodates omit dates from diff headers
559 --noprefix omit a/ and b/ prefixes from filenames
559 --noprefix omit a/ and b/ prefixes from filenames
560 -p --show-function show which function each change is in
560 -p --show-function show which function each change is in
561 --reverse produce a diff that undoes the changes
561 --reverse produce a diff that undoes the changes
562 -w --ignore-all-space ignore white space when comparing lines
562 -w --ignore-all-space ignore white space when comparing lines
563 -b --ignore-space-change ignore changes in the amount of white space
563 -b --ignore-space-change ignore changes in the amount of white space
564 -B --ignore-blank-lines ignore changes whose lines are all blank
564 -B --ignore-blank-lines ignore changes whose lines are all blank
565 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
565 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
566 -U --unified NUM number of lines of context to show
566 -U --unified NUM number of lines of context to show
567 --stat output diffstat-style summary of changes
567 --stat output diffstat-style summary of changes
568 --root DIR produce diffs relative to subdirectory
568 --root DIR produce diffs relative to subdirectory
569 -I --include PATTERN [+] include names matching the given patterns
569 -I --include PATTERN [+] include names matching the given patterns
570 -X --exclude PATTERN [+] exclude names matching the given patterns
570 -X --exclude PATTERN [+] exclude names matching the given patterns
571 -S --subrepos recurse into subrepositories
571 -S --subrepos recurse into subrepositories
572
572
573 (some details hidden, use --verbose to show complete help)
573 (some details hidden, use --verbose to show complete help)
574
574
575 $ hg help status
575 $ hg help status
576 hg status [OPTION]... [FILE]...
576 hg status [OPTION]... [FILE]...
577
577
578 aliases: st
578 aliases: st
579
579
580 show changed files in the working directory
580 show changed files in the working directory
581
581
582 Show status of files in the repository. If names are given, only files
582 Show status of files in the repository. If names are given, only files
583 that match are shown. Files that are clean or ignored or the source of a
583 that match are shown. Files that are clean or ignored or the source of a
584 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
584 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
585 -C/--copies or -A/--all are given. Unless options described with "show
585 -C/--copies or -A/--all are given. Unless options described with "show
586 only ..." are given, the options -mardu are used.
586 only ..." are given, the options -mardu are used.
587
587
588 Option -q/--quiet hides untracked (unknown and ignored) files unless
588 Option -q/--quiet hides untracked (unknown and ignored) files unless
589 explicitly requested with -u/--unknown or -i/--ignored.
589 explicitly requested with -u/--unknown or -i/--ignored.
590
590
591 Note:
591 Note:
592 'hg status' may appear to disagree with diff if permissions have
592 'hg status' may appear to disagree with diff if permissions have
593 changed or a merge has occurred. The standard diff format does not
593 changed or a merge has occurred. The standard diff format does not
594 report permission changes and diff only reports changes relative to one
594 report permission changes and diff only reports changes relative to one
595 merge parent.
595 merge parent.
596
596
597 If one revision is given, it is used as the base revision. If two
597 If one revision is given, it is used as the base revision. If two
598 revisions are given, the differences between them are shown. The --change
598 revisions are given, the differences between them are shown. The --change
599 option can also be used as a shortcut to list the changed files of a
599 option can also be used as a shortcut to list the changed files of a
600 revision from its first parent.
600 revision from its first parent.
601
601
602 The codes used to show the status of files are:
602 The codes used to show the status of files are:
603
603
604 M = modified
604 M = modified
605 A = added
605 A = added
606 R = removed
606 R = removed
607 C = clean
607 C = clean
608 ! = missing (deleted by non-hg command, but still tracked)
608 ! = missing (deleted by non-hg command, but still tracked)
609 ? = not tracked
609 ? = not tracked
610 I = ignored
610 I = ignored
611 = origin of the previous file (with --copies)
611 = origin of the previous file (with --copies)
612
612
613 Returns 0 on success.
613 Returns 0 on success.
614
614
615 options ([+] can be repeated):
615 options ([+] can be repeated):
616
616
617 -A --all show status of all files
617 -A --all show status of all files
618 -m --modified show only modified files
618 -m --modified show only modified files
619 -a --added show only added files
619 -a --added show only added files
620 -r --removed show only removed files
620 -r --removed show only removed files
621 -d --deleted show only deleted (but tracked) files
621 -d --deleted show only deleted (but tracked) files
622 -c --clean show only files without changes
622 -c --clean show only files without changes
623 -u --unknown show only unknown (not tracked) files
623 -u --unknown show only unknown (not tracked) files
624 -i --ignored show only ignored files
624 -i --ignored show only ignored files
625 -n --no-status hide status prefix
625 -n --no-status hide status prefix
626 -C --copies show source of copied files
626 -C --copies show source of copied files
627 -0 --print0 end filenames with NUL, for use with xargs
627 -0 --print0 end filenames with NUL, for use with xargs
628 --rev REV [+] show difference from revision
628 --rev REV [+] show difference from revision
629 --change REV list the changed files of a revision
629 --change REV list the changed files of a revision
630 -I --include PATTERN [+] include names matching the given patterns
630 -I --include PATTERN [+] include names matching the given patterns
631 -X --exclude PATTERN [+] exclude names matching the given patterns
631 -X --exclude PATTERN [+] exclude names matching the given patterns
632 -S --subrepos recurse into subrepositories
632 -S --subrepos recurse into subrepositories
633
633
634 (some details hidden, use --verbose to show complete help)
634 (some details hidden, use --verbose to show complete help)
635
635
636 $ hg -q help status
636 $ hg -q help status
637 hg status [OPTION]... [FILE]...
637 hg status [OPTION]... [FILE]...
638
638
639 show changed files in the working directory
639 show changed files in the working directory
640
640
641 $ hg help foo
641 $ hg help foo
642 abort: no such help topic: foo
642 abort: no such help topic: foo
643 (try 'hg help --keyword foo')
643 (try 'hg help --keyword foo')
644 [255]
644 [255]
645
645
646 $ hg skjdfks
646 $ hg skjdfks
647 hg: unknown command 'skjdfks'
647 hg: unknown command 'skjdfks'
648 Mercurial Distributed SCM
648 Mercurial Distributed SCM
649
649
650 basic commands:
650 basic commands:
651
651
652 add add the specified files on the next commit
652 add add the specified files on the next commit
653 annotate show changeset information by line for each file
653 annotate show changeset information by line for each file
654 clone make a copy of an existing repository
654 clone make a copy of an existing repository
655 commit commit the specified files or all outstanding changes
655 commit commit the specified files or all outstanding changes
656 diff diff repository (or selected files)
656 diff diff repository (or selected files)
657 export dump the header and diffs for one or more changesets
657 export dump the header and diffs for one or more changesets
658 forget forget the specified files on the next commit
658 forget forget the specified files on the next commit
659 init create a new repository in the given directory
659 init create a new repository in the given directory
660 log show revision history of entire repository or files
660 log show revision history of entire repository or files
661 merge merge another revision into working directory
661 merge merge another revision into working directory
662 pull pull changes from the specified source
662 pull pull changes from the specified source
663 push push changes to the specified destination
663 push push changes to the specified destination
664 remove remove the specified files on the next commit
664 remove remove the specified files on the next commit
665 serve start stand-alone webserver
665 serve start stand-alone webserver
666 status show changed files in the working directory
666 status show changed files in the working directory
667 summary summarize working directory state
667 summary summarize working directory state
668 update update working directory (or switch revisions)
668 update update working directory (or switch revisions)
669
669
670 (use 'hg help' for the full list of commands or 'hg -v' for details)
670 (use 'hg help' for the full list of commands or 'hg -v' for details)
671 [255]
671 [255]
672
672
673 Typoed command gives suggestion
673 Typoed command gives suggestion
674 $ hg puls
674 $ hg puls
675 hg: unknown command 'puls'
675 hg: unknown command 'puls'
676 (did you mean one of pull, push?)
676 (did you mean one of pull, push?)
677 [255]
677 [255]
678
678
679 Not enabled extension gets suggested
679 Not enabled extension gets suggested
680
680
681 $ hg rebase
681 $ hg rebase
682 hg: unknown command 'rebase'
682 hg: unknown command 'rebase'
683 'rebase' is provided by the following extension:
683 'rebase' is provided by the following extension:
684
684
685 rebase command to move sets of revisions to a different ancestor
685 rebase command to move sets of revisions to a different ancestor
686
686
687 (use 'hg help extensions' for information on enabling extensions)
687 (use 'hg help extensions' for information on enabling extensions)
688 [255]
688 [255]
689
689
690 Disabled extension gets suggested
690 Disabled extension gets suggested
691 $ hg --config extensions.rebase=! rebase
691 $ hg --config extensions.rebase=! rebase
692 hg: unknown command 'rebase'
692 hg: unknown command 'rebase'
693 'rebase' is provided by the following extension:
693 'rebase' is provided by the following extension:
694
694
695 rebase command to move sets of revisions to a different ancestor
695 rebase command to move sets of revisions to a different ancestor
696
696
697 (use 'hg help extensions' for information on enabling extensions)
697 (use 'hg help extensions' for information on enabling extensions)
698 [255]
698 [255]
699
699
700 Make sure that we don't run afoul of the help system thinking that
700 Make sure that we don't run afoul of the help system thinking that
701 this is a section and erroring out weirdly.
701 this is a section and erroring out weirdly.
702
702
703 $ hg .log
703 $ hg .log
704 hg: unknown command '.log'
704 hg: unknown command '.log'
705 (did you mean log?)
705 (did you mean log?)
706 [255]
706 [255]
707
707
708 $ hg log.
708 $ hg log.
709 hg: unknown command 'log.'
709 hg: unknown command 'log.'
710 (did you mean log?)
710 (did you mean log?)
711 [255]
711 [255]
712 $ hg pu.lh
712 $ hg pu.lh
713 hg: unknown command 'pu.lh'
713 hg: unknown command 'pu.lh'
714 (did you mean one of pull, push?)
714 (did you mean one of pull, push?)
715 [255]
715 [255]
716
716
717 $ cat > helpext.py <<EOF
717 $ cat > helpext.py <<EOF
718 > import os
718 > import os
719 > from mercurial import commands, fancyopts, registrar
719 > from mercurial import commands, fancyopts, registrar
720 >
720 >
721 > def func(arg):
721 > def func(arg):
722 > return '%sfoo' % arg
722 > return '%sfoo' % arg
723 > class customopt(fancyopts.customopt):
723 > class customopt(fancyopts.customopt):
724 > def newstate(self, oldstate, newparam, abort):
724 > def newstate(self, oldstate, newparam, abort):
725 > return '%sbar' % oldstate
725 > return '%sbar' % oldstate
726 > cmdtable = {}
726 > cmdtable = {}
727 > command = registrar.command(cmdtable)
727 > command = registrar.command(cmdtable)
728 >
728 >
729 > @command(b'nohelp',
729 > @command(b'nohelp',
730 > [(b'', b'longdesc', 3, b'x'*67),
730 > [(b'', b'longdesc', 3, b'x'*67),
731 > (b'n', b'', None, b'normal desc'),
731 > (b'n', b'', None, b'normal desc'),
732 > (b'', b'newline', b'', b'line1\nline2'),
732 > (b'', b'newline', b'', b'line1\nline2'),
733 > (b'', b'callableopt', func, b'adds foo'),
733 > (b'', b'callableopt', func, b'adds foo'),
734 > (b'', b'customopt', customopt(''), b'adds bar'),
734 > (b'', b'customopt', customopt(''), b'adds bar'),
735 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
735 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
736 > b'hg nohelp',
736 > b'hg nohelp',
737 > norepo=True)
737 > norepo=True)
738 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
738 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
739 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
739 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
740 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
740 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
741 > def nohelp(ui, *args, **kwargs):
741 > def nohelp(ui, *args, **kwargs):
742 > pass
742 > pass
743 >
743 >
744 > def uisetup(ui):
744 > def uisetup(ui):
745 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
745 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
746 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
746 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
747 >
747 >
748 > EOF
748 > EOF
749 $ echo '[extensions]' >> $HGRCPATH
749 $ echo '[extensions]' >> $HGRCPATH
750 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
750 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
751
751
752 Test for aliases
752 Test for aliases
753
753
754 $ hg help hgalias
754 $ hg help hgalias
755 hg hgalias [--remote]
755 hg hgalias [--remote]
756
756
757 alias for: hg summary
757 alias for: hg summary
758
758
759 summarize working directory state
759 summarize working directory state
760
760
761 This generates a brief summary of the working directory state, including
761 This generates a brief summary of the working directory state, including
762 parents, branch, commit status, phase and available updates.
762 parents, branch, commit status, phase and available updates.
763
763
764 With the --remote option, this will check the default paths for incoming
764 With the --remote option, this will check the default paths for incoming
765 and outgoing changes. This can be time-consuming.
765 and outgoing changes. This can be time-consuming.
766
766
767 Returns 0 on success.
767 Returns 0 on success.
768
768
769 defined by: helpext
769 defined by: helpext
770
770
771 options:
771 options:
772
772
773 --remote check for push and pull
773 --remote check for push and pull
774
774
775 (some details hidden, use --verbose to show complete help)
775 (some details hidden, use --verbose to show complete help)
776
776
777 $ hg help shellalias
777 $ hg help shellalias
778 hg shellalias
778 hg shellalias
779
779
780 shell alias for:
780 shell alias for: echo hi
781
781
782 echo hi
782 (no help text available)
783
783
784 defined by: helpext
784 defined by: helpext
785
785
786 (some details hidden, use --verbose to show complete help)
786 (some details hidden, use --verbose to show complete help)
787
787
788 Test command with no help text
788 Test command with no help text
789
789
790 $ hg help nohelp
790 $ hg help nohelp
791 hg nohelp
791 hg nohelp
792
792
793 (no help text available)
793 (no help text available)
794
794
795 options:
795 options:
796
796
797 --longdesc VALUE
797 --longdesc VALUE
798 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
798 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
799 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
799 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
800 -n -- normal desc
800 -n -- normal desc
801 --newline VALUE line1 line2
801 --newline VALUE line1 line2
802 --callableopt VALUE adds foo
802 --callableopt VALUE adds foo
803 --customopt VALUE adds bar
803 --customopt VALUE adds bar
804 --customopt-withdefault VALUE adds bar (default: foo)
804 --customopt-withdefault VALUE adds bar (default: foo)
805
805
806 (some details hidden, use --verbose to show complete help)
806 (some details hidden, use --verbose to show complete help)
807
807
808 $ hg help -k nohelp
808 $ hg help -k nohelp
809 Commands:
809 Commands:
810
810
811 nohelp hg nohelp
811 nohelp hg nohelp
812
812
813 Extension Commands:
813 Extension Commands:
814
814
815 nohelp (no help text available)
815 nohelp (no help text available)
816
816
817 Test that default list of commands omits extension commands
817 Test that default list of commands omits extension commands
818
818
819 $ hg help
819 $ hg help
820 Mercurial Distributed SCM
820 Mercurial Distributed SCM
821
821
822 list of commands:
822 list of commands:
823
823
824 add add the specified files on the next commit
824 add add the specified files on the next commit
825 addremove add all new files, delete all missing files
825 addremove add all new files, delete all missing files
826 annotate show changeset information by line for each file
826 annotate show changeset information by line for each file
827 archive create an unversioned archive of a repository revision
827 archive create an unversioned archive of a repository revision
828 backout reverse effect of earlier changeset
828 backout reverse effect of earlier changeset
829 bisect subdivision search of changesets
829 bisect subdivision search of changesets
830 bookmarks create a new bookmark or list existing bookmarks
830 bookmarks create a new bookmark or list existing bookmarks
831 branch set or show the current branch name
831 branch set or show the current branch name
832 branches list repository named branches
832 branches list repository named branches
833 bundle create a bundle file
833 bundle create a bundle file
834 cat output the current or given revision of files
834 cat output the current or given revision of files
835 clone make a copy of an existing repository
835 clone make a copy of an existing repository
836 commit commit the specified files or all outstanding changes
836 commit commit the specified files or all outstanding changes
837 config show combined config settings from all hgrc files
837 config show combined config settings from all hgrc files
838 copy mark files as copied for the next commit
838 copy mark files as copied for the next commit
839 diff diff repository (or selected files)
839 diff diff repository (or selected files)
840 export dump the header and diffs for one or more changesets
840 export dump the header and diffs for one or more changesets
841 files list tracked files
841 files list tracked files
842 forget forget the specified files on the next commit
842 forget forget the specified files on the next commit
843 graft copy changes from other branches onto the current branch
843 graft copy changes from other branches onto the current branch
844 grep search revision history for a pattern in specified files
844 grep search revision history for a pattern in specified files
845 heads show branch heads
845 heads show branch heads
846 help show help for a given topic or a help overview
846 help show help for a given topic or a help overview
847 identify identify the working directory or specified revision
847 identify identify the working directory or specified revision
848 import import an ordered set of patches
848 import import an ordered set of patches
849 incoming show new changesets found in source
849 incoming show new changesets found in source
850 init create a new repository in the given directory
850 init create a new repository in the given directory
851 log show revision history of entire repository or files
851 log show revision history of entire repository or files
852 manifest output the current or given revision of the project manifest
852 manifest output the current or given revision of the project manifest
853 merge merge another revision into working directory
853 merge merge another revision into working directory
854 outgoing show changesets not found in the destination
854 outgoing show changesets not found in the destination
855 paths show aliases for remote repositories
855 paths show aliases for remote repositories
856 phase set or show the current phase name
856 phase set or show the current phase name
857 pull pull changes from the specified source
857 pull pull changes from the specified source
858 push push changes to the specified destination
858 push push changes to the specified destination
859 recover roll back an interrupted transaction
859 recover roll back an interrupted transaction
860 remove remove the specified files on the next commit
860 remove remove the specified files on the next commit
861 rename rename files; equivalent of copy + remove
861 rename rename files; equivalent of copy + remove
862 resolve redo merges or set/view the merge status of files
862 resolve redo merges or set/view the merge status of files
863 revert restore files to their checkout state
863 revert restore files to their checkout state
864 root print the root (top) of the current working directory
864 root print the root (top) of the current working directory
865 serve start stand-alone webserver
865 serve start stand-alone webserver
866 status show changed files in the working directory
866 status show changed files in the working directory
867 summary summarize working directory state
867 summary summarize working directory state
868 tag add one or more tags for the current or given revision
868 tag add one or more tags for the current or given revision
869 tags list repository tags
869 tags list repository tags
870 unbundle apply one or more bundle files
870 unbundle apply one or more bundle files
871 update update working directory (or switch revisions)
871 update update working directory (or switch revisions)
872 verify verify the integrity of the repository
872 verify verify the integrity of the repository
873 version output version and copyright information
873 version output version and copyright information
874
874
875 enabled extensions:
875 enabled extensions:
876
876
877 helpext (no help text available)
877 helpext (no help text available)
878
878
879 additional help topics:
879 additional help topics:
880
880
881 bundlespec Bundle File Formats
881 bundlespec Bundle File Formats
882 color Colorizing Outputs
882 color Colorizing Outputs
883 config Configuration Files
883 config Configuration Files
884 dates Date Formats
884 dates Date Formats
885 diffs Diff Formats
885 diffs Diff Formats
886 environment Environment Variables
886 environment Environment Variables
887 extensions Using Additional Features
887 extensions Using Additional Features
888 filesets Specifying File Sets
888 filesets Specifying File Sets
889 flags Command-line flags
889 flags Command-line flags
890 glossary Glossary
890 glossary Glossary
891 hgignore Syntax for Mercurial Ignore Files
891 hgignore Syntax for Mercurial Ignore Files
892 hgweb Configuring hgweb
892 hgweb Configuring hgweb
893 internals Technical implementation topics
893 internals Technical implementation topics
894 merge-tools Merge Tools
894 merge-tools Merge Tools
895 pager Pager Support
895 pager Pager Support
896 patterns File Name Patterns
896 patterns File Name Patterns
897 phases Working with Phases
897 phases Working with Phases
898 revisions Specifying Revisions
898 revisions Specifying Revisions
899 scripting Using Mercurial from scripts and automation
899 scripting Using Mercurial from scripts and automation
900 subrepos Subrepositories
900 subrepos Subrepositories
901 templating Template Usage
901 templating Template Usage
902 urls URL Paths
902 urls URL Paths
903
903
904 (use 'hg help -v' to show built-in aliases and global options)
904 (use 'hg help -v' to show built-in aliases and global options)
905
905
906
906
907 Test list of internal help commands
907 Test list of internal help commands
908
908
909 $ hg help debug
909 $ hg help debug
910 debug commands (internal and unsupported):
910 debug commands (internal and unsupported):
911
911
912 debugancestor
912 debugancestor
913 find the ancestor revision of two revisions in a given index
913 find the ancestor revision of two revisions in a given index
914 debugapplystreamclonebundle
914 debugapplystreamclonebundle
915 apply a stream clone bundle file
915 apply a stream clone bundle file
916 debugbuilddag
916 debugbuilddag
917 builds a repo with a given DAG from scratch in the current
917 builds a repo with a given DAG from scratch in the current
918 empty repo
918 empty repo
919 debugbundle lists the contents of a bundle
919 debugbundle lists the contents of a bundle
920 debugcapabilities
920 debugcapabilities
921 lists the capabilities of a remote peer
921 lists the capabilities of a remote peer
922 debugcheckstate
922 debugcheckstate
923 validate the correctness of the current dirstate
923 validate the correctness of the current dirstate
924 debugcolor show available color, effects or style
924 debugcolor show available color, effects or style
925 debugcommands
925 debugcommands
926 list all available commands and options
926 list all available commands and options
927 debugcomplete
927 debugcomplete
928 returns the completion list associated with the given command
928 returns the completion list associated with the given command
929 debugcreatestreamclonebundle
929 debugcreatestreamclonebundle
930 create a stream clone bundle file
930 create a stream clone bundle file
931 debugdag format the changelog or an index DAG as a concise textual
931 debugdag format the changelog or an index DAG as a concise textual
932 description
932 description
933 debugdata dump the contents of a data file revision
933 debugdata dump the contents of a data file revision
934 debugdate parse and display a date
934 debugdate parse and display a date
935 debugdeltachain
935 debugdeltachain
936 dump information about delta chains in a revlog
936 dump information about delta chains in a revlog
937 debugdirstate
937 debugdirstate
938 show the contents of the current dirstate
938 show the contents of the current dirstate
939 debugdiscovery
939 debugdiscovery
940 runs the changeset discovery protocol in isolation
940 runs the changeset discovery protocol in isolation
941 debugdownload
941 debugdownload
942 download a resource using Mercurial logic and config
942 download a resource using Mercurial logic and config
943 debugextensions
943 debugextensions
944 show information about active extensions
944 show information about active extensions
945 debugfileset parse and apply a fileset specification
945 debugfileset parse and apply a fileset specification
946 debugformat display format information about the current repository
946 debugformat display format information about the current repository
947 debugfsinfo show information detected about current filesystem
947 debugfsinfo show information detected about current filesystem
948 debuggetbundle
948 debuggetbundle
949 retrieves a bundle from a repo
949 retrieves a bundle from a repo
950 debugignore display the combined ignore pattern and information about
950 debugignore display the combined ignore pattern and information about
951 ignored files
951 ignored files
952 debugindex dump the contents of an index file
952 debugindex dump the contents of an index file
953 debugindexdot
953 debugindexdot
954 dump an index DAG as a graphviz dot file
954 dump an index DAG as a graphviz dot file
955 debuginstall test Mercurial installation
955 debuginstall test Mercurial installation
956 debugknown test whether node ids are known to a repo
956 debugknown test whether node ids are known to a repo
957 debuglocks show or modify state of locks
957 debuglocks show or modify state of locks
958 debugmergestate
958 debugmergestate
959 print merge state
959 print merge state
960 debugnamecomplete
960 debugnamecomplete
961 complete "names" - tags, open branch names, bookmark names
961 complete "names" - tags, open branch names, bookmark names
962 debugobsolete
962 debugobsolete
963 create arbitrary obsolete marker
963 create arbitrary obsolete marker
964 debugoptADV (no help text available)
964 debugoptADV (no help text available)
965 debugoptDEP (no help text available)
965 debugoptDEP (no help text available)
966 debugoptEXP (no help text available)
966 debugoptEXP (no help text available)
967 debugpathcomplete
967 debugpathcomplete
968 complete part or all of a tracked path
968 complete part or all of a tracked path
969 debugpeer establish a connection to a peer repository
969 debugpeer establish a connection to a peer repository
970 debugpickmergetool
970 debugpickmergetool
971 examine which merge tool is chosen for specified file
971 examine which merge tool is chosen for specified file
972 debugpushkey access the pushkey key/value protocol
972 debugpushkey access the pushkey key/value protocol
973 debugpvec (no help text available)
973 debugpvec (no help text available)
974 debugrebuilddirstate
974 debugrebuilddirstate
975 rebuild the dirstate as it would look like for the given
975 rebuild the dirstate as it would look like for the given
976 revision
976 revision
977 debugrebuildfncache
977 debugrebuildfncache
978 rebuild the fncache file
978 rebuild the fncache file
979 debugrename dump rename information
979 debugrename dump rename information
980 debugrevlog show data and statistics about a revlog
980 debugrevlog show data and statistics about a revlog
981 debugrevspec parse and apply a revision specification
981 debugrevspec parse and apply a revision specification
982 debugserve run a server with advanced settings
982 debugserve run a server with advanced settings
983 debugsetparents
983 debugsetparents
984 manually set the parents of the current working directory
984 manually set the parents of the current working directory
985 debugssl test a secure connection to a server
985 debugssl test a secure connection to a server
986 debugsub (no help text available)
986 debugsub (no help text available)
987 debugsuccessorssets
987 debugsuccessorssets
988 show set of successors for revision
988 show set of successors for revision
989 debugtemplate
989 debugtemplate
990 parse and apply a template
990 parse and apply a template
991 debuguigetpass
991 debuguigetpass
992 show prompt to type password
992 show prompt to type password
993 debuguiprompt
993 debuguiprompt
994 show plain prompt
994 show plain prompt
995 debugupdatecaches
995 debugupdatecaches
996 warm all known caches in the repository
996 warm all known caches in the repository
997 debugupgraderepo
997 debugupgraderepo
998 upgrade a repository to use different features
998 upgrade a repository to use different features
999 debugwalk show how files match on given patterns
999 debugwalk show how files match on given patterns
1000 debugwhyunstable
1000 debugwhyunstable
1001 explain instabilities of a changeset
1001 explain instabilities of a changeset
1002 debugwireargs
1002 debugwireargs
1003 (no help text available)
1003 (no help text available)
1004 debugwireproto
1004 debugwireproto
1005 send wire protocol commands to a server
1005 send wire protocol commands to a server
1006
1006
1007 (use 'hg help -v debug' to show built-in aliases and global options)
1007 (use 'hg help -v debug' to show built-in aliases and global options)
1008
1008
1009 internals topic renders index of available sub-topics
1009 internals topic renders index of available sub-topics
1010
1010
1011 $ hg help internals
1011 $ hg help internals
1012 Technical implementation topics
1012 Technical implementation topics
1013 """""""""""""""""""""""""""""""
1013 """""""""""""""""""""""""""""""
1014
1014
1015 To access a subtopic, use "hg help internals.{subtopic-name}"
1015 To access a subtopic, use "hg help internals.{subtopic-name}"
1016
1016
1017 bundle2 Bundle2
1017 bundle2 Bundle2
1018 bundles Bundles
1018 bundles Bundles
1019 censor Censor
1019 censor Censor
1020 changegroups Changegroups
1020 changegroups Changegroups
1021 config Config Registrar
1021 config Config Registrar
1022 requirements Repository Requirements
1022 requirements Repository Requirements
1023 revlogs Revision Logs
1023 revlogs Revision Logs
1024 wireprotocol Wire Protocol
1024 wireprotocol Wire Protocol
1025
1025
1026 sub-topics can be accessed
1026 sub-topics can be accessed
1027
1027
1028 $ hg help internals.changegroups
1028 $ hg help internals.changegroups
1029 Changegroups
1029 Changegroups
1030 """"""""""""
1030 """"""""""""
1031
1031
1032 Changegroups are representations of repository revlog data, specifically
1032 Changegroups are representations of repository revlog data, specifically
1033 the changelog data, root/flat manifest data, treemanifest data, and
1033 the changelog data, root/flat manifest data, treemanifest data, and
1034 filelogs.
1034 filelogs.
1035
1035
1036 There are 3 versions of changegroups: "1", "2", and "3". From a high-
1036 There are 3 versions of changegroups: "1", "2", and "3". From a high-
1037 level, versions "1" and "2" are almost exactly the same, with the only
1037 level, versions "1" and "2" are almost exactly the same, with the only
1038 difference being an additional item in the *delta header*. Version "3"
1038 difference being an additional item in the *delta header*. Version "3"
1039 adds support for revlog flags in the *delta header* and optionally
1039 adds support for revlog flags in the *delta header* and optionally
1040 exchanging treemanifests (enabled by setting an option on the
1040 exchanging treemanifests (enabled by setting an option on the
1041 "changegroup" part in the bundle2).
1041 "changegroup" part in the bundle2).
1042
1042
1043 Changegroups when not exchanging treemanifests consist of 3 logical
1043 Changegroups when not exchanging treemanifests consist of 3 logical
1044 segments:
1044 segments:
1045
1045
1046 +---------------------------------+
1046 +---------------------------------+
1047 | | | |
1047 | | | |
1048 | changeset | manifest | filelogs |
1048 | changeset | manifest | filelogs |
1049 | | | |
1049 | | | |
1050 | | | |
1050 | | | |
1051 +---------------------------------+
1051 +---------------------------------+
1052
1052
1053 When exchanging treemanifests, there are 4 logical segments:
1053 When exchanging treemanifests, there are 4 logical segments:
1054
1054
1055 +-------------------------------------------------+
1055 +-------------------------------------------------+
1056 | | | | |
1056 | | | | |
1057 | changeset | root | treemanifests | filelogs |
1057 | changeset | root | treemanifests | filelogs |
1058 | | manifest | | |
1058 | | manifest | | |
1059 | | | | |
1059 | | | | |
1060 +-------------------------------------------------+
1060 +-------------------------------------------------+
1061
1061
1062 The principle building block of each segment is a *chunk*. A *chunk* is a
1062 The principle building block of each segment is a *chunk*. A *chunk* is a
1063 framed piece of data:
1063 framed piece of data:
1064
1064
1065 +---------------------------------------+
1065 +---------------------------------------+
1066 | | |
1066 | | |
1067 | length | data |
1067 | length | data |
1068 | (4 bytes) | (<length - 4> bytes) |
1068 | (4 bytes) | (<length - 4> bytes) |
1069 | | |
1069 | | |
1070 +---------------------------------------+
1070 +---------------------------------------+
1071
1071
1072 All integers are big-endian signed integers. Each chunk starts with a
1072 All integers are big-endian signed integers. Each chunk starts with a
1073 32-bit integer indicating the length of the entire chunk (including the
1073 32-bit integer indicating the length of the entire chunk (including the
1074 length field itself).
1074 length field itself).
1075
1075
1076 There is a special case chunk that has a value of 0 for the length
1076 There is a special case chunk that has a value of 0 for the length
1077 ("0x00000000"). We call this an *empty chunk*.
1077 ("0x00000000"). We call this an *empty chunk*.
1078
1078
1079 Delta Groups
1079 Delta Groups
1080 ============
1080 ============
1081
1081
1082 A *delta group* expresses the content of a revlog as a series of deltas,
1082 A *delta group* expresses the content of a revlog as a series of deltas,
1083 or patches against previous revisions.
1083 or patches against previous revisions.
1084
1084
1085 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1085 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1086 to signal the end of the delta group:
1086 to signal the end of the delta group:
1087
1087
1088 +------------------------------------------------------------------------+
1088 +------------------------------------------------------------------------+
1089 | | | | | |
1089 | | | | | |
1090 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1090 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1091 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1091 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1092 | | | | | |
1092 | | | | | |
1093 +------------------------------------------------------------------------+
1093 +------------------------------------------------------------------------+
1094
1094
1095 Each *chunk*'s data consists of the following:
1095 Each *chunk*'s data consists of the following:
1096
1096
1097 +---------------------------------------+
1097 +---------------------------------------+
1098 | | |
1098 | | |
1099 | delta header | delta data |
1099 | delta header | delta data |
1100 | (various by version) | (various) |
1100 | (various by version) | (various) |
1101 | | |
1101 | | |
1102 +---------------------------------------+
1102 +---------------------------------------+
1103
1103
1104 The *delta data* is a series of *delta*s that describe a diff from an
1104 The *delta data* is a series of *delta*s that describe a diff from an
1105 existing entry (either that the recipient already has, or previously
1105 existing entry (either that the recipient already has, or previously
1106 specified in the bundle/changegroup).
1106 specified in the bundle/changegroup).
1107
1107
1108 The *delta header* is different between versions "1", "2", and "3" of the
1108 The *delta header* is different between versions "1", "2", and "3" of the
1109 changegroup format.
1109 changegroup format.
1110
1110
1111 Version 1 (headerlen=80):
1111 Version 1 (headerlen=80):
1112
1112
1113 +------------------------------------------------------+
1113 +------------------------------------------------------+
1114 | | | | |
1114 | | | | |
1115 | node | p1 node | p2 node | link node |
1115 | node | p1 node | p2 node | link node |
1116 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1116 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1117 | | | | |
1117 | | | | |
1118 +------------------------------------------------------+
1118 +------------------------------------------------------+
1119
1119
1120 Version 2 (headerlen=100):
1120 Version 2 (headerlen=100):
1121
1121
1122 +------------------------------------------------------------------+
1122 +------------------------------------------------------------------+
1123 | | | | | |
1123 | | | | | |
1124 | node | p1 node | p2 node | base node | link node |
1124 | node | p1 node | p2 node | base node | link node |
1125 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1125 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1126 | | | | | |
1126 | | | | | |
1127 +------------------------------------------------------------------+
1127 +------------------------------------------------------------------+
1128
1128
1129 Version 3 (headerlen=102):
1129 Version 3 (headerlen=102):
1130
1130
1131 +------------------------------------------------------------------------------+
1131 +------------------------------------------------------------------------------+
1132 | | | | | | |
1132 | | | | | | |
1133 | node | p1 node | p2 node | base node | link node | flags |
1133 | node | p1 node | p2 node | base node | link node | flags |
1134 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1134 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1135 | | | | | | |
1135 | | | | | | |
1136 +------------------------------------------------------------------------------+
1136 +------------------------------------------------------------------------------+
1137
1137
1138 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1138 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1139 contain a series of *delta*s, densely packed (no separators). These deltas
1139 contain a series of *delta*s, densely packed (no separators). These deltas
1140 describe a diff from an existing entry (either that the recipient already
1140 describe a diff from an existing entry (either that the recipient already
1141 has, or previously specified in the bundle/changegroup). The format is
1141 has, or previously specified in the bundle/changegroup). The format is
1142 described more fully in "hg help internals.bdiff", but briefly:
1142 described more fully in "hg help internals.bdiff", but briefly:
1143
1143
1144 +---------------------------------------------------------------+
1144 +---------------------------------------------------------------+
1145 | | | | |
1145 | | | | |
1146 | start offset | end offset | new length | content |
1146 | start offset | end offset | new length | content |
1147 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1147 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1148 | | | | |
1148 | | | | |
1149 +---------------------------------------------------------------+
1149 +---------------------------------------------------------------+
1150
1150
1151 Please note that the length field in the delta data does *not* include
1151 Please note that the length field in the delta data does *not* include
1152 itself.
1152 itself.
1153
1153
1154 In version 1, the delta is always applied against the previous node from
1154 In version 1, the delta is always applied against the previous node from
1155 the changegroup or the first parent if this is the first entry in the
1155 the changegroup or the first parent if this is the first entry in the
1156 changegroup.
1156 changegroup.
1157
1157
1158 In version 2 and up, the delta base node is encoded in the entry in the
1158 In version 2 and up, the delta base node is encoded in the entry in the
1159 changegroup. This allows the delta to be expressed against any parent,
1159 changegroup. This allows the delta to be expressed against any parent,
1160 which can result in smaller deltas and more efficient encoding of data.
1160 which can result in smaller deltas and more efficient encoding of data.
1161
1161
1162 Changeset Segment
1162 Changeset Segment
1163 =================
1163 =================
1164
1164
1165 The *changeset segment* consists of a single *delta group* holding
1165 The *changeset segment* consists of a single *delta group* holding
1166 changelog data. The *empty chunk* at the end of the *delta group* denotes
1166 changelog data. The *empty chunk* at the end of the *delta group* denotes
1167 the boundary to the *manifest segment*.
1167 the boundary to the *manifest segment*.
1168
1168
1169 Manifest Segment
1169 Manifest Segment
1170 ================
1170 ================
1171
1171
1172 The *manifest segment* consists of a single *delta group* holding manifest
1172 The *manifest segment* consists of a single *delta group* holding manifest
1173 data. If treemanifests are in use, it contains only the manifest for the
1173 data. If treemanifests are in use, it contains only the manifest for the
1174 root directory of the repository. Otherwise, it contains the entire
1174 root directory of the repository. Otherwise, it contains the entire
1175 manifest data. The *empty chunk* at the end of the *delta group* denotes
1175 manifest data. The *empty chunk* at the end of the *delta group* denotes
1176 the boundary to the next segment (either the *treemanifests segment* or
1176 the boundary to the next segment (either the *treemanifests segment* or
1177 the *filelogs segment*, depending on version and the request options).
1177 the *filelogs segment*, depending on version and the request options).
1178
1178
1179 Treemanifests Segment
1179 Treemanifests Segment
1180 ---------------------
1180 ---------------------
1181
1181
1182 The *treemanifests segment* only exists in changegroup version "3", and
1182 The *treemanifests segment* only exists in changegroup version "3", and
1183 only if the 'treemanifest' param is part of the bundle2 changegroup part
1183 only if the 'treemanifest' param is part of the bundle2 changegroup part
1184 (it is not possible to use changegroup version 3 outside of bundle2).
1184 (it is not possible to use changegroup version 3 outside of bundle2).
1185 Aside from the filenames in the *treemanifests segment* containing a
1185 Aside from the filenames in the *treemanifests segment* containing a
1186 trailing "/" character, it behaves identically to the *filelogs segment*
1186 trailing "/" character, it behaves identically to the *filelogs segment*
1187 (see below). The final sub-segment is followed by an *empty chunk*
1187 (see below). The final sub-segment is followed by an *empty chunk*
1188 (logically, a sub-segment with filename size 0). This denotes the boundary
1188 (logically, a sub-segment with filename size 0). This denotes the boundary
1189 to the *filelogs segment*.
1189 to the *filelogs segment*.
1190
1190
1191 Filelogs Segment
1191 Filelogs Segment
1192 ================
1192 ================
1193
1193
1194 The *filelogs segment* consists of multiple sub-segments, each
1194 The *filelogs segment* consists of multiple sub-segments, each
1195 corresponding to an individual file whose data is being described:
1195 corresponding to an individual file whose data is being described:
1196
1196
1197 +--------------------------------------------------+
1197 +--------------------------------------------------+
1198 | | | | | |
1198 | | | | | |
1199 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1199 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1200 | | | | | (4 bytes) |
1200 | | | | | (4 bytes) |
1201 | | | | | |
1201 | | | | | |
1202 +--------------------------------------------------+
1202 +--------------------------------------------------+
1203
1203
1204 The final filelog sub-segment is followed by an *empty chunk* (logically,
1204 The final filelog sub-segment is followed by an *empty chunk* (logically,
1205 a sub-segment with filename size 0). This denotes the end of the segment
1205 a sub-segment with filename size 0). This denotes the end of the segment
1206 and of the overall changegroup.
1206 and of the overall changegroup.
1207
1207
1208 Each filelog sub-segment consists of the following:
1208 Each filelog sub-segment consists of the following:
1209
1209
1210 +------------------------------------------------------+
1210 +------------------------------------------------------+
1211 | | | |
1211 | | | |
1212 | filename length | filename | delta group |
1212 | filename length | filename | delta group |
1213 | (4 bytes) | (<length - 4> bytes) | (various) |
1213 | (4 bytes) | (<length - 4> bytes) | (various) |
1214 | | | |
1214 | | | |
1215 +------------------------------------------------------+
1215 +------------------------------------------------------+
1216
1216
1217 That is, a *chunk* consisting of the filename (not terminated or padded)
1217 That is, a *chunk* consisting of the filename (not terminated or padded)
1218 followed by N chunks constituting the *delta group* for this file. The
1218 followed by N chunks constituting the *delta group* for this file. The
1219 *empty chunk* at the end of each *delta group* denotes the boundary to the
1219 *empty chunk* at the end of each *delta group* denotes the boundary to the
1220 next filelog sub-segment.
1220 next filelog sub-segment.
1221
1221
1222 Test list of commands with command with no help text
1222 Test list of commands with command with no help text
1223
1223
1224 $ hg help helpext
1224 $ hg help helpext
1225 helpext extension - no help text available
1225 helpext extension - no help text available
1226
1226
1227 list of commands:
1227 list of commands:
1228
1228
1229 nohelp (no help text available)
1229 nohelp (no help text available)
1230
1230
1231 (use 'hg help -v helpext' to show built-in aliases and global options)
1231 (use 'hg help -v helpext' to show built-in aliases and global options)
1232
1232
1233
1233
1234 test advanced, deprecated and experimental options are hidden in command help
1234 test advanced, deprecated and experimental options are hidden in command help
1235 $ hg help debugoptADV
1235 $ hg help debugoptADV
1236 hg debugoptADV
1236 hg debugoptADV
1237
1237
1238 (no help text available)
1238 (no help text available)
1239
1239
1240 options:
1240 options:
1241
1241
1242 (some details hidden, use --verbose to show complete help)
1242 (some details hidden, use --verbose to show complete help)
1243 $ hg help debugoptDEP
1243 $ hg help debugoptDEP
1244 hg debugoptDEP
1244 hg debugoptDEP
1245
1245
1246 (no help text available)
1246 (no help text available)
1247
1247
1248 options:
1248 options:
1249
1249
1250 (some details hidden, use --verbose to show complete help)
1250 (some details hidden, use --verbose to show complete help)
1251
1251
1252 $ hg help debugoptEXP
1252 $ hg help debugoptEXP
1253 hg debugoptEXP
1253 hg debugoptEXP
1254
1254
1255 (no help text available)
1255 (no help text available)
1256
1256
1257 options:
1257 options:
1258
1258
1259 (some details hidden, use --verbose to show complete help)
1259 (some details hidden, use --verbose to show complete help)
1260
1260
1261 test advanced, deprecated and experimental options are shown with -v
1261 test advanced, deprecated and experimental options are shown with -v
1262 $ hg help -v debugoptADV | grep aopt
1262 $ hg help -v debugoptADV | grep aopt
1263 --aopt option is (ADVANCED)
1263 --aopt option is (ADVANCED)
1264 $ hg help -v debugoptDEP | grep dopt
1264 $ hg help -v debugoptDEP | grep dopt
1265 --dopt option is (DEPRECATED)
1265 --dopt option is (DEPRECATED)
1266 $ hg help -v debugoptEXP | grep eopt
1266 $ hg help -v debugoptEXP | grep eopt
1267 --eopt option is (EXPERIMENTAL)
1267 --eopt option is (EXPERIMENTAL)
1268
1268
1269 #if gettext
1269 #if gettext
1270 test deprecated option is hidden with translation with untranslated description
1270 test deprecated option is hidden with translation with untranslated description
1271 (use many globy for not failing on changed transaction)
1271 (use many globy for not failing on changed transaction)
1272 $ LANGUAGE=sv hg help debugoptDEP
1272 $ LANGUAGE=sv hg help debugoptDEP
1273 hg debugoptDEP
1273 hg debugoptDEP
1274
1274
1275 (*) (glob)
1275 (*) (glob)
1276
1276
1277 options:
1277 options:
1278
1278
1279 (some details hidden, use --verbose to show complete help)
1279 (some details hidden, use --verbose to show complete help)
1280 #endif
1280 #endif
1281
1281
1282 Test commands that collide with topics (issue4240)
1282 Test commands that collide with topics (issue4240)
1283
1283
1284 $ hg config -hq
1284 $ hg config -hq
1285 hg config [-u] [NAME]...
1285 hg config [-u] [NAME]...
1286
1286
1287 show combined config settings from all hgrc files
1287 show combined config settings from all hgrc files
1288 $ hg showconfig -hq
1288 $ hg showconfig -hq
1289 hg config [-u] [NAME]...
1289 hg config [-u] [NAME]...
1290
1290
1291 show combined config settings from all hgrc files
1291 show combined config settings from all hgrc files
1292
1292
1293 Test a help topic
1293 Test a help topic
1294
1294
1295 $ hg help dates
1295 $ hg help dates
1296 Date Formats
1296 Date Formats
1297 """"""""""""
1297 """"""""""""
1298
1298
1299 Some commands allow the user to specify a date, e.g.:
1299 Some commands allow the user to specify a date, e.g.:
1300
1300
1301 - backout, commit, import, tag: Specify the commit date.
1301 - backout, commit, import, tag: Specify the commit date.
1302 - log, revert, update: Select revision(s) by date.
1302 - log, revert, update: Select revision(s) by date.
1303
1303
1304 Many date formats are valid. Here are some examples:
1304 Many date formats are valid. Here are some examples:
1305
1305
1306 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1306 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1307 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1307 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1308 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1308 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1309 - "Dec 6" (midnight)
1309 - "Dec 6" (midnight)
1310 - "13:18" (today assumed)
1310 - "13:18" (today assumed)
1311 - "3:39" (3:39AM assumed)
1311 - "3:39" (3:39AM assumed)
1312 - "3:39pm" (15:39)
1312 - "3:39pm" (15:39)
1313 - "2006-12-06 13:18:29" (ISO 8601 format)
1313 - "2006-12-06 13:18:29" (ISO 8601 format)
1314 - "2006-12-6 13:18"
1314 - "2006-12-6 13:18"
1315 - "2006-12-6"
1315 - "2006-12-6"
1316 - "12-6"
1316 - "12-6"
1317 - "12/6"
1317 - "12/6"
1318 - "12/6/6" (Dec 6 2006)
1318 - "12/6/6" (Dec 6 2006)
1319 - "today" (midnight)
1319 - "today" (midnight)
1320 - "yesterday" (midnight)
1320 - "yesterday" (midnight)
1321 - "now" - right now
1321 - "now" - right now
1322
1322
1323 Lastly, there is Mercurial's internal format:
1323 Lastly, there is Mercurial's internal format:
1324
1324
1325 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1325 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1326
1326
1327 This is the internal representation format for dates. The first number is
1327 This is the internal representation format for dates. The first number is
1328 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1328 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1329 is the offset of the local timezone, in seconds west of UTC (negative if
1329 is the offset of the local timezone, in seconds west of UTC (negative if
1330 the timezone is east of UTC).
1330 the timezone is east of UTC).
1331
1331
1332 The log command also accepts date ranges:
1332 The log command also accepts date ranges:
1333
1333
1334 - "<DATE" - at or before a given date/time
1334 - "<DATE" - at or before a given date/time
1335 - ">DATE" - on or after a given date/time
1335 - ">DATE" - on or after a given date/time
1336 - "DATE to DATE" - a date range, inclusive
1336 - "DATE to DATE" - a date range, inclusive
1337 - "-DAYS" - within a given number of days of today
1337 - "-DAYS" - within a given number of days of today
1338
1338
1339 Test repeated config section name
1339 Test repeated config section name
1340
1340
1341 $ hg help config.host
1341 $ hg help config.host
1342 "http_proxy.host"
1342 "http_proxy.host"
1343 Host name and (optional) port of the proxy server, for example
1343 Host name and (optional) port of the proxy server, for example
1344 "myproxy:8000".
1344 "myproxy:8000".
1345
1345
1346 "smtp.host"
1346 "smtp.host"
1347 Host name of mail server, e.g. "mail.example.com".
1347 Host name of mail server, e.g. "mail.example.com".
1348
1348
1349 Unrelated trailing paragraphs shouldn't be included
1349 Unrelated trailing paragraphs shouldn't be included
1350
1350
1351 $ hg help config.extramsg | grep '^$'
1351 $ hg help config.extramsg | grep '^$'
1352
1352
1353
1353
1354 Test capitalized section name
1354 Test capitalized section name
1355
1355
1356 $ hg help scripting.HGPLAIN > /dev/null
1356 $ hg help scripting.HGPLAIN > /dev/null
1357
1357
1358 Help subsection:
1358 Help subsection:
1359
1359
1360 $ hg help config.charsets |grep "Email example:" > /dev/null
1360 $ hg help config.charsets |grep "Email example:" > /dev/null
1361 [1]
1361 [1]
1362
1362
1363 Show nested definitions
1363 Show nested definitions
1364 ("profiling.type"[break]"ls"[break]"stat"[break])
1364 ("profiling.type"[break]"ls"[break]"stat"[break])
1365
1365
1366 $ hg help config.type | egrep '^$'|wc -l
1366 $ hg help config.type | egrep '^$'|wc -l
1367 \s*3 (re)
1367 \s*3 (re)
1368
1368
1369 Separate sections from subsections
1369 Separate sections from subsections
1370
1370
1371 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1371 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1372 "format"
1372 "format"
1373 --------
1373 --------
1374
1374
1375 "usegeneraldelta"
1375 "usegeneraldelta"
1376
1376
1377 "dotencode"
1377 "dotencode"
1378
1378
1379 "usefncache"
1379 "usefncache"
1380
1380
1381 "usestore"
1381 "usestore"
1382
1382
1383 "profiling"
1383 "profiling"
1384 -----------
1384 -----------
1385
1385
1386 "format"
1386 "format"
1387
1387
1388 "progress"
1388 "progress"
1389 ----------
1389 ----------
1390
1390
1391 "format"
1391 "format"
1392
1392
1393
1393
1394 Last item in help config.*:
1394 Last item in help config.*:
1395
1395
1396 $ hg help config.`hg help config|grep '^ "'| \
1396 $ hg help config.`hg help config|grep '^ "'| \
1397 > tail -1|sed 's![ "]*!!g'`| \
1397 > tail -1|sed 's![ "]*!!g'`| \
1398 > grep 'hg help -c config' > /dev/null
1398 > grep 'hg help -c config' > /dev/null
1399 [1]
1399 [1]
1400
1400
1401 note to use help -c for general hg help config:
1401 note to use help -c for general hg help config:
1402
1402
1403 $ hg help config |grep 'hg help -c config' > /dev/null
1403 $ hg help config |grep 'hg help -c config' > /dev/null
1404
1404
1405 Test templating help
1405 Test templating help
1406
1406
1407 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1407 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1408 desc String. The text of the changeset description.
1408 desc String. The text of the changeset description.
1409 diffstat String. Statistics of changes with the following format:
1409 diffstat String. Statistics of changes with the following format:
1410 firstline Any text. Returns the first line of text.
1410 firstline Any text. Returns the first line of text.
1411 nonempty Any text. Returns '(none)' if the string is empty.
1411 nonempty Any text. Returns '(none)' if the string is empty.
1412
1412
1413 Test deprecated items
1413 Test deprecated items
1414
1414
1415 $ hg help -v templating | grep currentbookmark
1415 $ hg help -v templating | grep currentbookmark
1416 currentbookmark
1416 currentbookmark
1417 $ hg help templating | (grep currentbookmark || true)
1417 $ hg help templating | (grep currentbookmark || true)
1418
1418
1419 Test help hooks
1419 Test help hooks
1420
1420
1421 $ cat > helphook1.py <<EOF
1421 $ cat > helphook1.py <<EOF
1422 > from mercurial import help
1422 > from mercurial import help
1423 >
1423 >
1424 > def rewrite(ui, topic, doc):
1424 > def rewrite(ui, topic, doc):
1425 > return doc + '\nhelphook1\n'
1425 > return doc + '\nhelphook1\n'
1426 >
1426 >
1427 > def extsetup(ui):
1427 > def extsetup(ui):
1428 > help.addtopichook('revisions', rewrite)
1428 > help.addtopichook('revisions', rewrite)
1429 > EOF
1429 > EOF
1430 $ cat > helphook2.py <<EOF
1430 $ cat > helphook2.py <<EOF
1431 > from mercurial import help
1431 > from mercurial import help
1432 >
1432 >
1433 > def rewrite(ui, topic, doc):
1433 > def rewrite(ui, topic, doc):
1434 > return doc + '\nhelphook2\n'
1434 > return doc + '\nhelphook2\n'
1435 >
1435 >
1436 > def extsetup(ui):
1436 > def extsetup(ui):
1437 > help.addtopichook('revisions', rewrite)
1437 > help.addtopichook('revisions', rewrite)
1438 > EOF
1438 > EOF
1439 $ echo '[extensions]' >> $HGRCPATH
1439 $ echo '[extensions]' >> $HGRCPATH
1440 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1440 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1441 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1441 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1442 $ hg help revsets | grep helphook
1442 $ hg help revsets | grep helphook
1443 helphook1
1443 helphook1
1444 helphook2
1444 helphook2
1445
1445
1446 help -c should only show debug --debug
1446 help -c should only show debug --debug
1447
1447
1448 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1448 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1449 [1]
1449 [1]
1450
1450
1451 help -c should only show deprecated for -v
1451 help -c should only show deprecated for -v
1452
1452
1453 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1453 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1454 [1]
1454 [1]
1455
1455
1456 Test -s / --system
1456 Test -s / --system
1457
1457
1458 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1458 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1459 > wc -l | sed -e 's/ //g'
1459 > wc -l | sed -e 's/ //g'
1460 0
1460 0
1461 $ hg help config.files --system unix | grep 'USER' | \
1461 $ hg help config.files --system unix | grep 'USER' | \
1462 > wc -l | sed -e 's/ //g'
1462 > wc -l | sed -e 's/ //g'
1463 0
1463 0
1464
1464
1465 Test -e / -c / -k combinations
1465 Test -e / -c / -k combinations
1466
1466
1467 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1467 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1468 Commands:
1468 Commands:
1469 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1469 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1470 Extensions:
1470 Extensions:
1471 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1471 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1472 Topics:
1472 Topics:
1473 Commands:
1473 Commands:
1474 Extensions:
1474 Extensions:
1475 Extension Commands:
1475 Extension Commands:
1476 $ hg help -c schemes
1476 $ hg help -c schemes
1477 abort: no such help topic: schemes
1477 abort: no such help topic: schemes
1478 (try 'hg help --keyword schemes')
1478 (try 'hg help --keyword schemes')
1479 [255]
1479 [255]
1480 $ hg help -e schemes |head -1
1480 $ hg help -e schemes |head -1
1481 schemes extension - extend schemes with shortcuts to repository swarms
1481 schemes extension - extend schemes with shortcuts to repository swarms
1482 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1482 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1483 Commands:
1483 Commands:
1484 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1484 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1485 Extensions:
1485 Extensions:
1486 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1486 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1487 Extensions:
1487 Extensions:
1488 Commands:
1488 Commands:
1489 $ hg help -c commit > /dev/null
1489 $ hg help -c commit > /dev/null
1490 $ hg help -e -c commit > /dev/null
1490 $ hg help -e -c commit > /dev/null
1491 $ hg help -e commit > /dev/null
1491 $ hg help -e commit > /dev/null
1492 abort: no such help topic: commit
1492 abort: no such help topic: commit
1493 (try 'hg help --keyword commit')
1493 (try 'hg help --keyword commit')
1494 [255]
1494 [255]
1495
1495
1496 Test keyword search help
1496 Test keyword search help
1497
1497
1498 $ cat > prefixedname.py <<EOF
1498 $ cat > prefixedname.py <<EOF
1499 > '''matched against word "clone"
1499 > '''matched against word "clone"
1500 > '''
1500 > '''
1501 > EOF
1501 > EOF
1502 $ echo '[extensions]' >> $HGRCPATH
1502 $ echo '[extensions]' >> $HGRCPATH
1503 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1503 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1504 $ hg help -k clone
1504 $ hg help -k clone
1505 Topics:
1505 Topics:
1506
1506
1507 config Configuration Files
1507 config Configuration Files
1508 extensions Using Additional Features
1508 extensions Using Additional Features
1509 glossary Glossary
1509 glossary Glossary
1510 phases Working with Phases
1510 phases Working with Phases
1511 subrepos Subrepositories
1511 subrepos Subrepositories
1512 urls URL Paths
1512 urls URL Paths
1513
1513
1514 Commands:
1514 Commands:
1515
1515
1516 bookmarks create a new bookmark or list existing bookmarks
1516 bookmarks create a new bookmark or list existing bookmarks
1517 clone make a copy of an existing repository
1517 clone make a copy of an existing repository
1518 paths show aliases for remote repositories
1518 paths show aliases for remote repositories
1519 update update working directory (or switch revisions)
1519 update update working directory (or switch revisions)
1520
1520
1521 Extensions:
1521 Extensions:
1522
1522
1523 clonebundles advertise pre-generated bundles to seed clones
1523 clonebundles advertise pre-generated bundles to seed clones
1524 narrow create clones which fetch history data for subset of files
1524 narrow create clones which fetch history data for subset of files
1525 (EXPERIMENTAL)
1525 (EXPERIMENTAL)
1526 prefixedname matched against word "clone"
1526 prefixedname matched against word "clone"
1527 relink recreates hardlinks between repository clones
1527 relink recreates hardlinks between repository clones
1528
1528
1529 Extension Commands:
1529 Extension Commands:
1530
1530
1531 qclone clone main and patch repository at same time
1531 qclone clone main and patch repository at same time
1532
1532
1533 Test unfound topic
1533 Test unfound topic
1534
1534
1535 $ hg help nonexistingtopicthatwillneverexisteverever
1535 $ hg help nonexistingtopicthatwillneverexisteverever
1536 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1536 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1537 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1537 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1538 [255]
1538 [255]
1539
1539
1540 Test unfound keyword
1540 Test unfound keyword
1541
1541
1542 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1542 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1543 abort: no matches
1543 abort: no matches
1544 (try 'hg help' for a list of topics)
1544 (try 'hg help' for a list of topics)
1545 [255]
1545 [255]
1546
1546
1547 Test omit indicating for help
1547 Test omit indicating for help
1548
1548
1549 $ cat > addverboseitems.py <<EOF
1549 $ cat > addverboseitems.py <<EOF
1550 > '''extension to test omit indicating.
1550 > '''extension to test omit indicating.
1551 >
1551 >
1552 > This paragraph is never omitted (for extension)
1552 > This paragraph is never omitted (for extension)
1553 >
1553 >
1554 > .. container:: verbose
1554 > .. container:: verbose
1555 >
1555 >
1556 > This paragraph is omitted,
1556 > This paragraph is omitted,
1557 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1557 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1558 >
1558 >
1559 > This paragraph is never omitted, too (for extension)
1559 > This paragraph is never omitted, too (for extension)
1560 > '''
1560 > '''
1561 > from __future__ import absolute_import
1561 > from __future__ import absolute_import
1562 > from mercurial import commands, help
1562 > from mercurial import commands, help
1563 > testtopic = """This paragraph is never omitted (for topic).
1563 > testtopic = """This paragraph is never omitted (for topic).
1564 >
1564 >
1565 > .. container:: verbose
1565 > .. container:: verbose
1566 >
1566 >
1567 > This paragraph is omitted,
1567 > This paragraph is omitted,
1568 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1568 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1569 >
1569 >
1570 > This paragraph is never omitted, too (for topic)
1570 > This paragraph is never omitted, too (for topic)
1571 > """
1571 > """
1572 > def extsetup(ui):
1572 > def extsetup(ui):
1573 > help.helptable.append((["topic-containing-verbose"],
1573 > help.helptable.append((["topic-containing-verbose"],
1574 > "This is the topic to test omit indicating.",
1574 > "This is the topic to test omit indicating.",
1575 > lambda ui: testtopic))
1575 > lambda ui: testtopic))
1576 > EOF
1576 > EOF
1577 $ echo '[extensions]' >> $HGRCPATH
1577 $ echo '[extensions]' >> $HGRCPATH
1578 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1578 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1579 $ hg help addverboseitems
1579 $ hg help addverboseitems
1580 addverboseitems extension - extension to test omit indicating.
1580 addverboseitems extension - extension to test omit indicating.
1581
1581
1582 This paragraph is never omitted (for extension)
1582 This paragraph is never omitted (for extension)
1583
1583
1584 This paragraph is never omitted, too (for extension)
1584 This paragraph is never omitted, too (for extension)
1585
1585
1586 (some details hidden, use --verbose to show complete help)
1586 (some details hidden, use --verbose to show complete help)
1587
1587
1588 no commands defined
1588 no commands defined
1589 $ hg help -v addverboseitems
1589 $ hg help -v addverboseitems
1590 addverboseitems extension - extension to test omit indicating.
1590 addverboseitems extension - extension to test omit indicating.
1591
1591
1592 This paragraph is never omitted (for extension)
1592 This paragraph is never omitted (for extension)
1593
1593
1594 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1594 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1595 extension)
1595 extension)
1596
1596
1597 This paragraph is never omitted, too (for extension)
1597 This paragraph is never omitted, too (for extension)
1598
1598
1599 no commands defined
1599 no commands defined
1600 $ hg help topic-containing-verbose
1600 $ hg help topic-containing-verbose
1601 This is the topic to test omit indicating.
1601 This is the topic to test omit indicating.
1602 """"""""""""""""""""""""""""""""""""""""""
1602 """"""""""""""""""""""""""""""""""""""""""
1603
1603
1604 This paragraph is never omitted (for topic).
1604 This paragraph is never omitted (for topic).
1605
1605
1606 This paragraph is never omitted, too (for topic)
1606 This paragraph is never omitted, too (for topic)
1607
1607
1608 (some details hidden, use --verbose to show complete help)
1608 (some details hidden, use --verbose to show complete help)
1609 $ hg help -v topic-containing-verbose
1609 $ hg help -v topic-containing-verbose
1610 This is the topic to test omit indicating.
1610 This is the topic to test omit indicating.
1611 """"""""""""""""""""""""""""""""""""""""""
1611 """"""""""""""""""""""""""""""""""""""""""
1612
1612
1613 This paragraph is never omitted (for topic).
1613 This paragraph is never omitted (for topic).
1614
1614
1615 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1615 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1616 topic)
1616 topic)
1617
1617
1618 This paragraph is never omitted, too (for topic)
1618 This paragraph is never omitted, too (for topic)
1619
1619
1620 Test section lookup
1620 Test section lookup
1621
1621
1622 $ hg help revset.merge
1622 $ hg help revset.merge
1623 "merge()"
1623 "merge()"
1624 Changeset is a merge changeset.
1624 Changeset is a merge changeset.
1625
1625
1626 $ hg help glossary.dag
1626 $ hg help glossary.dag
1627 DAG
1627 DAG
1628 The repository of changesets of a distributed version control system
1628 The repository of changesets of a distributed version control system
1629 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1629 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1630 of nodes and edges, where nodes correspond to changesets and edges
1630 of nodes and edges, where nodes correspond to changesets and edges
1631 imply a parent -> child relation. This graph can be visualized by
1631 imply a parent -> child relation. This graph can be visualized by
1632 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1632 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1633 limited by the requirement for children to have at most two parents.
1633 limited by the requirement for children to have at most two parents.
1634
1634
1635
1635
1636 $ hg help hgrc.paths
1636 $ hg help hgrc.paths
1637 "paths"
1637 "paths"
1638 -------
1638 -------
1639
1639
1640 Assigns symbolic names and behavior to repositories.
1640 Assigns symbolic names and behavior to repositories.
1641
1641
1642 Options are symbolic names defining the URL or directory that is the
1642 Options are symbolic names defining the URL or directory that is the
1643 location of the repository. Example:
1643 location of the repository. Example:
1644
1644
1645 [paths]
1645 [paths]
1646 my_server = https://example.com/my_repo
1646 my_server = https://example.com/my_repo
1647 local_path = /home/me/repo
1647 local_path = /home/me/repo
1648
1648
1649 These symbolic names can be used from the command line. To pull from
1649 These symbolic names can be used from the command line. To pull from
1650 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1650 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1651 local_path'.
1651 local_path'.
1652
1652
1653 Options containing colons (":") denote sub-options that can influence
1653 Options containing colons (":") denote sub-options that can influence
1654 behavior for that specific path. Example:
1654 behavior for that specific path. Example:
1655
1655
1656 [paths]
1656 [paths]
1657 my_server = https://example.com/my_path
1657 my_server = https://example.com/my_path
1658 my_server:pushurl = ssh://example.com/my_path
1658 my_server:pushurl = ssh://example.com/my_path
1659
1659
1660 The following sub-options can be defined:
1660 The following sub-options can be defined:
1661
1661
1662 "pushurl"
1662 "pushurl"
1663 The URL to use for push operations. If not defined, the location
1663 The URL to use for push operations. If not defined, the location
1664 defined by the path's main entry is used.
1664 defined by the path's main entry is used.
1665
1665
1666 "pushrev"
1666 "pushrev"
1667 A revset defining which revisions to push by default.
1667 A revset defining which revisions to push by default.
1668
1668
1669 When 'hg push' is executed without a "-r" argument, the revset defined
1669 When 'hg push' is executed without a "-r" argument, the revset defined
1670 by this sub-option is evaluated to determine what to push.
1670 by this sub-option is evaluated to determine what to push.
1671
1671
1672 For example, a value of "." will push the working directory's revision
1672 For example, a value of "." will push the working directory's revision
1673 by default.
1673 by default.
1674
1674
1675 Revsets specifying bookmarks will not result in the bookmark being
1675 Revsets specifying bookmarks will not result in the bookmark being
1676 pushed.
1676 pushed.
1677
1677
1678 The following special named paths exist:
1678 The following special named paths exist:
1679
1679
1680 "default"
1680 "default"
1681 The URL or directory to use when no source or remote is specified.
1681 The URL or directory to use when no source or remote is specified.
1682
1682
1683 'hg clone' will automatically define this path to the location the
1683 'hg clone' will automatically define this path to the location the
1684 repository was cloned from.
1684 repository was cloned from.
1685
1685
1686 "default-push"
1686 "default-push"
1687 (deprecated) The URL or directory for the default 'hg push' location.
1687 (deprecated) The URL or directory for the default 'hg push' location.
1688 "default:pushurl" should be used instead.
1688 "default:pushurl" should be used instead.
1689
1689
1690 $ hg help glossary.mcguffin
1690 $ hg help glossary.mcguffin
1691 abort: help section not found: glossary.mcguffin
1691 abort: help section not found: glossary.mcguffin
1692 [255]
1692 [255]
1693
1693
1694 $ hg help glossary.mc.guffin
1694 $ hg help glossary.mc.guffin
1695 abort: help section not found: glossary.mc.guffin
1695 abort: help section not found: glossary.mc.guffin
1696 [255]
1696 [255]
1697
1697
1698 $ hg help template.files
1698 $ hg help template.files
1699 files List of strings. All files modified, added, or removed by
1699 files List of strings. All files modified, added, or removed by
1700 this changeset.
1700 this changeset.
1701 files(pattern)
1701 files(pattern)
1702 All files of the current changeset matching the pattern. See
1702 All files of the current changeset matching the pattern. See
1703 'hg help patterns'.
1703 'hg help patterns'.
1704
1704
1705 Test section lookup by translated message
1705 Test section lookup by translated message
1706
1706
1707 str.lower() instead of encoding.lower(str) on translated message might
1707 str.lower() instead of encoding.lower(str) on translated message might
1708 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1708 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1709 as the second or later byte of multi-byte character.
1709 as the second or later byte of multi-byte character.
1710
1710
1711 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1711 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1712 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1712 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1713 replacement makes message meaningless.
1713 replacement makes message meaningless.
1714
1714
1715 This tests that section lookup by translated string isn't broken by
1715 This tests that section lookup by translated string isn't broken by
1716 such str.lower().
1716 such str.lower().
1717
1717
1718 $ $PYTHON <<EOF
1718 $ $PYTHON <<EOF
1719 > def escape(s):
1719 > def escape(s):
1720 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1720 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1721 > # translation of "record" in ja_JP.cp932
1721 > # translation of "record" in ja_JP.cp932
1722 > upper = "\x8bL\x98^"
1722 > upper = "\x8bL\x98^"
1723 > # str.lower()-ed section name should be treated as different one
1723 > # str.lower()-ed section name should be treated as different one
1724 > lower = "\x8bl\x98^"
1724 > lower = "\x8bl\x98^"
1725 > with open('ambiguous.py', 'w') as fp:
1725 > with open('ambiguous.py', 'w') as fp:
1726 > fp.write("""# ambiguous section names in ja_JP.cp932
1726 > fp.write("""# ambiguous section names in ja_JP.cp932
1727 > u'''summary of extension
1727 > u'''summary of extension
1728 >
1728 >
1729 > %s
1729 > %s
1730 > ----
1730 > ----
1731 >
1731 >
1732 > Upper name should show only this message
1732 > Upper name should show only this message
1733 >
1733 >
1734 > %s
1734 > %s
1735 > ----
1735 > ----
1736 >
1736 >
1737 > Lower name should show only this message
1737 > Lower name should show only this message
1738 >
1738 >
1739 > subsequent section
1739 > subsequent section
1740 > ------------------
1740 > ------------------
1741 >
1741 >
1742 > This should be hidden at 'hg help ambiguous' with section name.
1742 > This should be hidden at 'hg help ambiguous' with section name.
1743 > '''
1743 > '''
1744 > """ % (escape(upper), escape(lower)))
1744 > """ % (escape(upper), escape(lower)))
1745 > EOF
1745 > EOF
1746
1746
1747 $ cat >> $HGRCPATH <<EOF
1747 $ cat >> $HGRCPATH <<EOF
1748 > [extensions]
1748 > [extensions]
1749 > ambiguous = ./ambiguous.py
1749 > ambiguous = ./ambiguous.py
1750 > EOF
1750 > EOF
1751
1751
1752 $ $PYTHON <<EOF | sh
1752 $ $PYTHON <<EOF | sh
1753 > upper = "\x8bL\x98^"
1753 > upper = "\x8bL\x98^"
1754 > print("hg --encoding cp932 help -e ambiguous.%s" % upper)
1754 > print("hg --encoding cp932 help -e ambiguous.%s" % upper)
1755 > EOF
1755 > EOF
1756 \x8bL\x98^ (esc)
1756 \x8bL\x98^ (esc)
1757 ----
1757 ----
1758
1758
1759 Upper name should show only this message
1759 Upper name should show only this message
1760
1760
1761
1761
1762 $ $PYTHON <<EOF | sh
1762 $ $PYTHON <<EOF | sh
1763 > lower = "\x8bl\x98^"
1763 > lower = "\x8bl\x98^"
1764 > print("hg --encoding cp932 help -e ambiguous.%s" % lower)
1764 > print("hg --encoding cp932 help -e ambiguous.%s" % lower)
1765 > EOF
1765 > EOF
1766 \x8bl\x98^ (esc)
1766 \x8bl\x98^ (esc)
1767 ----
1767 ----
1768
1768
1769 Lower name should show only this message
1769 Lower name should show only this message
1770
1770
1771
1771
1772 $ cat >> $HGRCPATH <<EOF
1772 $ cat >> $HGRCPATH <<EOF
1773 > [extensions]
1773 > [extensions]
1774 > ambiguous = !
1774 > ambiguous = !
1775 > EOF
1775 > EOF
1776
1776
1777 Show help content of disabled extensions
1777 Show help content of disabled extensions
1778
1778
1779 $ cat >> $HGRCPATH <<EOF
1779 $ cat >> $HGRCPATH <<EOF
1780 > [extensions]
1780 > [extensions]
1781 > ambiguous = !./ambiguous.py
1781 > ambiguous = !./ambiguous.py
1782 > EOF
1782 > EOF
1783 $ hg help -e ambiguous
1783 $ hg help -e ambiguous
1784 ambiguous extension - (no help text available)
1784 ambiguous extension - (no help text available)
1785
1785
1786 (use 'hg help extensions' for information on enabling extensions)
1786 (use 'hg help extensions' for information on enabling extensions)
1787
1787
1788 Test dynamic list of merge tools only shows up once
1788 Test dynamic list of merge tools only shows up once
1789 $ hg help merge-tools
1789 $ hg help merge-tools
1790 Merge Tools
1790 Merge Tools
1791 """""""""""
1791 """""""""""
1792
1792
1793 To merge files Mercurial uses merge tools.
1793 To merge files Mercurial uses merge tools.
1794
1794
1795 A merge tool combines two different versions of a file into a merged file.
1795 A merge tool combines two different versions of a file into a merged file.
1796 Merge tools are given the two files and the greatest common ancestor of
1796 Merge tools are given the two files and the greatest common ancestor of
1797 the two file versions, so they can determine the changes made on both
1797 the two file versions, so they can determine the changes made on both
1798 branches.
1798 branches.
1799
1799
1800 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1800 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1801 backout' and in several extensions.
1801 backout' and in several extensions.
1802
1802
1803 Usually, the merge tool tries to automatically reconcile the files by
1803 Usually, the merge tool tries to automatically reconcile the files by
1804 combining all non-overlapping changes that occurred separately in the two
1804 combining all non-overlapping changes that occurred separately in the two
1805 different evolutions of the same initial base file. Furthermore, some
1805 different evolutions of the same initial base file. Furthermore, some
1806 interactive merge programs make it easier to manually resolve conflicting
1806 interactive merge programs make it easier to manually resolve conflicting
1807 merges, either in a graphical way, or by inserting some conflict markers.
1807 merges, either in a graphical way, or by inserting some conflict markers.
1808 Mercurial does not include any interactive merge programs but relies on
1808 Mercurial does not include any interactive merge programs but relies on
1809 external tools for that.
1809 external tools for that.
1810
1810
1811 Available merge tools
1811 Available merge tools
1812 =====================
1812 =====================
1813
1813
1814 External merge tools and their properties are configured in the merge-
1814 External merge tools and their properties are configured in the merge-
1815 tools configuration section - see hgrc(5) - but they can often just be
1815 tools configuration section - see hgrc(5) - but they can often just be
1816 named by their executable.
1816 named by their executable.
1817
1817
1818 A merge tool is generally usable if its executable can be found on the
1818 A merge tool is generally usable if its executable can be found on the
1819 system and if it can handle the merge. The executable is found if it is an
1819 system and if it can handle the merge. The executable is found if it is an
1820 absolute or relative executable path or the name of an application in the
1820 absolute or relative executable path or the name of an application in the
1821 executable search path. The tool is assumed to be able to handle the merge
1821 executable search path. The tool is assumed to be able to handle the merge
1822 if it can handle symlinks if the file is a symlink, if it can handle
1822 if it can handle symlinks if the file is a symlink, if it can handle
1823 binary files if the file is binary, and if a GUI is available if the tool
1823 binary files if the file is binary, and if a GUI is available if the tool
1824 requires a GUI.
1824 requires a GUI.
1825
1825
1826 There are some internal merge tools which can be used. The internal merge
1826 There are some internal merge tools which can be used. The internal merge
1827 tools are:
1827 tools are:
1828
1828
1829 ":dump"
1829 ":dump"
1830 Creates three versions of the files to merge, containing the contents of
1830 Creates three versions of the files to merge, containing the contents of
1831 local, other and base. These files can then be used to perform a merge
1831 local, other and base. These files can then be used to perform a merge
1832 manually. If the file to be merged is named "a.txt", these files will
1832 manually. If the file to be merged is named "a.txt", these files will
1833 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1833 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1834 they will be placed in the same directory as "a.txt".
1834 they will be placed in the same directory as "a.txt".
1835
1835
1836 This implies premerge. Therefore, files aren't dumped, if premerge runs
1836 This implies premerge. Therefore, files aren't dumped, if premerge runs
1837 successfully. Use :forcedump to forcibly write files out.
1837 successfully. Use :forcedump to forcibly write files out.
1838
1838
1839 ":fail"
1839 ":fail"
1840 Rather than attempting to merge files that were modified on both
1840 Rather than attempting to merge files that were modified on both
1841 branches, it marks them as unresolved. The resolve command must be used
1841 branches, it marks them as unresolved. The resolve command must be used
1842 to resolve these conflicts.
1842 to resolve these conflicts.
1843
1843
1844 ":forcedump"
1844 ":forcedump"
1845 Creates three versions of the files as same as :dump, but omits
1845 Creates three versions of the files as same as :dump, but omits
1846 premerge.
1846 premerge.
1847
1847
1848 ":local"
1848 ":local"
1849 Uses the local 'p1()' version of files as the merged version.
1849 Uses the local 'p1()' version of files as the merged version.
1850
1850
1851 ":merge"
1851 ":merge"
1852 Uses the internal non-interactive simple merge algorithm for merging
1852 Uses the internal non-interactive simple merge algorithm for merging
1853 files. It will fail if there are any conflicts and leave markers in the
1853 files. It will fail if there are any conflicts and leave markers in the
1854 partially merged file. Markers will have two sections, one for each side
1854 partially merged file. Markers will have two sections, one for each side
1855 of merge.
1855 of merge.
1856
1856
1857 ":merge-local"
1857 ":merge-local"
1858 Like :merge, but resolve all conflicts non-interactively in favor of the
1858 Like :merge, but resolve all conflicts non-interactively in favor of the
1859 local 'p1()' changes.
1859 local 'p1()' changes.
1860
1860
1861 ":merge-other"
1861 ":merge-other"
1862 Like :merge, but resolve all conflicts non-interactively in favor of the
1862 Like :merge, but resolve all conflicts non-interactively in favor of the
1863 other 'p2()' changes.
1863 other 'p2()' changes.
1864
1864
1865 ":merge3"
1865 ":merge3"
1866 Uses the internal non-interactive simple merge algorithm for merging
1866 Uses the internal non-interactive simple merge algorithm for merging
1867 files. It will fail if there are any conflicts and leave markers in the
1867 files. It will fail if there are any conflicts and leave markers in the
1868 partially merged file. Marker will have three sections, one from each
1868 partially merged file. Marker will have three sections, one from each
1869 side of the merge and one for the base content.
1869 side of the merge and one for the base content.
1870
1870
1871 ":other"
1871 ":other"
1872 Uses the other 'p2()' version of files as the merged version.
1872 Uses the other 'p2()' version of files as the merged version.
1873
1873
1874 ":prompt"
1874 ":prompt"
1875 Asks the user which of the local 'p1()' or the other 'p2()' version to
1875 Asks the user which of the local 'p1()' or the other 'p2()' version to
1876 keep as the merged version.
1876 keep as the merged version.
1877
1877
1878 ":tagmerge"
1878 ":tagmerge"
1879 Uses the internal tag merge algorithm (experimental).
1879 Uses the internal tag merge algorithm (experimental).
1880
1880
1881 ":union"
1881 ":union"
1882 Uses the internal non-interactive simple merge algorithm for merging
1882 Uses the internal non-interactive simple merge algorithm for merging
1883 files. It will use both left and right sides for conflict regions. No
1883 files. It will use both left and right sides for conflict regions. No
1884 markers are inserted.
1884 markers are inserted.
1885
1885
1886 Internal tools are always available and do not require a GUI but will by
1886 Internal tools are always available and do not require a GUI but will by
1887 default not handle symlinks or binary files.
1887 default not handle symlinks or binary files.
1888
1888
1889 Choosing a merge tool
1889 Choosing a merge tool
1890 =====================
1890 =====================
1891
1891
1892 Mercurial uses these rules when deciding which merge tool to use:
1892 Mercurial uses these rules when deciding which merge tool to use:
1893
1893
1894 1. If a tool has been specified with the --tool option to merge or
1894 1. If a tool has been specified with the --tool option to merge or
1895 resolve, it is used. If it is the name of a tool in the merge-tools
1895 resolve, it is used. If it is the name of a tool in the merge-tools
1896 configuration, its configuration is used. Otherwise the specified tool
1896 configuration, its configuration is used. Otherwise the specified tool
1897 must be executable by the shell.
1897 must be executable by the shell.
1898 2. If the "HGMERGE" environment variable is present, its value is used and
1898 2. If the "HGMERGE" environment variable is present, its value is used and
1899 must be executable by the shell.
1899 must be executable by the shell.
1900 3. If the filename of the file to be merged matches any of the patterns in
1900 3. If the filename of the file to be merged matches any of the patterns in
1901 the merge-patterns configuration section, the first usable merge tool
1901 the merge-patterns configuration section, the first usable merge tool
1902 corresponding to a matching pattern is used. Here, binary capabilities
1902 corresponding to a matching pattern is used. Here, binary capabilities
1903 of the merge tool are not considered.
1903 of the merge tool are not considered.
1904 4. If ui.merge is set it will be considered next. If the value is not the
1904 4. If ui.merge is set it will be considered next. If the value is not the
1905 name of a configured tool, the specified value is used and must be
1905 name of a configured tool, the specified value is used and must be
1906 executable by the shell. Otherwise the named tool is used if it is
1906 executable by the shell. Otherwise the named tool is used if it is
1907 usable.
1907 usable.
1908 5. If any usable merge tools are present in the merge-tools configuration
1908 5. If any usable merge tools are present in the merge-tools configuration
1909 section, the one with the highest priority is used.
1909 section, the one with the highest priority is used.
1910 6. If a program named "hgmerge" can be found on the system, it is used -
1910 6. If a program named "hgmerge" can be found on the system, it is used -
1911 but it will by default not be used for symlinks and binary files.
1911 but it will by default not be used for symlinks and binary files.
1912 7. If the file to be merged is not binary and is not a symlink, then
1912 7. If the file to be merged is not binary and is not a symlink, then
1913 internal ":merge" is used.
1913 internal ":merge" is used.
1914 8. Otherwise, ":prompt" is used.
1914 8. Otherwise, ":prompt" is used.
1915
1915
1916 Note:
1916 Note:
1917 After selecting a merge program, Mercurial will by default attempt to
1917 After selecting a merge program, Mercurial will by default attempt to
1918 merge the files using a simple merge algorithm first. Only if it
1918 merge the files using a simple merge algorithm first. Only if it
1919 doesn't succeed because of conflicting changes will Mercurial actually
1919 doesn't succeed because of conflicting changes will Mercurial actually
1920 execute the merge program. Whether to use the simple merge algorithm
1920 execute the merge program. Whether to use the simple merge algorithm
1921 first can be controlled by the premerge setting of the merge tool.
1921 first can be controlled by the premerge setting of the merge tool.
1922 Premerge is enabled by default unless the file is binary or a symlink.
1922 Premerge is enabled by default unless the file is binary or a symlink.
1923
1923
1924 See the merge-tools and ui sections of hgrc(5) for details on the
1924 See the merge-tools and ui sections of hgrc(5) for details on the
1925 configuration of merge tools.
1925 configuration of merge tools.
1926
1926
1927 Compression engines listed in `hg help bundlespec`
1927 Compression engines listed in `hg help bundlespec`
1928
1928
1929 $ hg help bundlespec | grep gzip
1929 $ hg help bundlespec | grep gzip
1930 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
1930 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
1931 An algorithm that produces smaller bundles than "gzip".
1931 An algorithm that produces smaller bundles than "gzip".
1932 This engine will likely produce smaller bundles than "gzip" but will be
1932 This engine will likely produce smaller bundles than "gzip" but will be
1933 "gzip"
1933 "gzip"
1934 better compression than "gzip". It also frequently yields better (?)
1934 better compression than "gzip". It also frequently yields better (?)
1935
1935
1936 Test usage of section marks in help documents
1936 Test usage of section marks in help documents
1937
1937
1938 $ cd "$TESTDIR"/../doc
1938 $ cd "$TESTDIR"/../doc
1939 $ $PYTHON check-seclevel.py
1939 $ $PYTHON check-seclevel.py
1940 $ cd $TESTTMP
1940 $ cd $TESTTMP
1941
1941
1942 #if serve
1942 #if serve
1943
1943
1944 Test the help pages in hgweb.
1944 Test the help pages in hgweb.
1945
1945
1946 Dish up an empty repo; serve it cold.
1946 Dish up an empty repo; serve it cold.
1947
1947
1948 $ hg init "$TESTTMP/test"
1948 $ hg init "$TESTTMP/test"
1949 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1949 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1950 $ cat hg.pid >> $DAEMON_PIDS
1950 $ cat hg.pid >> $DAEMON_PIDS
1951
1951
1952 $ get-with-headers.py $LOCALIP:$HGPORT "help"
1952 $ get-with-headers.py $LOCALIP:$HGPORT "help"
1953 200 Script output follows
1953 200 Script output follows
1954
1954
1955 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1955 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1956 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1956 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1957 <head>
1957 <head>
1958 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1958 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1959 <meta name="robots" content="index, nofollow" />
1959 <meta name="robots" content="index, nofollow" />
1960 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1960 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1961 <script type="text/javascript" src="/static/mercurial.js"></script>
1961 <script type="text/javascript" src="/static/mercurial.js"></script>
1962
1962
1963 <title>Help: Index</title>
1963 <title>Help: Index</title>
1964 </head>
1964 </head>
1965 <body>
1965 <body>
1966
1966
1967 <div class="container">
1967 <div class="container">
1968 <div class="menu">
1968 <div class="menu">
1969 <div class="logo">
1969 <div class="logo">
1970 <a href="https://mercurial-scm.org/">
1970 <a href="https://mercurial-scm.org/">
1971 <img src="/static/hglogo.png" alt="mercurial" /></a>
1971 <img src="/static/hglogo.png" alt="mercurial" /></a>
1972 </div>
1972 </div>
1973 <ul>
1973 <ul>
1974 <li><a href="/shortlog">log</a></li>
1974 <li><a href="/shortlog">log</a></li>
1975 <li><a href="/graph">graph</a></li>
1975 <li><a href="/graph">graph</a></li>
1976 <li><a href="/tags">tags</a></li>
1976 <li><a href="/tags">tags</a></li>
1977 <li><a href="/bookmarks">bookmarks</a></li>
1977 <li><a href="/bookmarks">bookmarks</a></li>
1978 <li><a href="/branches">branches</a></li>
1978 <li><a href="/branches">branches</a></li>
1979 </ul>
1979 </ul>
1980 <ul>
1980 <ul>
1981 <li class="active">help</li>
1981 <li class="active">help</li>
1982 </ul>
1982 </ul>
1983 </div>
1983 </div>
1984
1984
1985 <div class="main">
1985 <div class="main">
1986 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1986 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1987
1987
1988 <form class="search" action="/log">
1988 <form class="search" action="/log">
1989
1989
1990 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
1990 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
1991 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1991 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1992 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1992 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1993 </form>
1993 </form>
1994 <table class="bigtable">
1994 <table class="bigtable">
1995 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
1995 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
1996
1996
1997 <tr><td>
1997 <tr><td>
1998 <a href="/help/bundlespec">
1998 <a href="/help/bundlespec">
1999 bundlespec
1999 bundlespec
2000 </a>
2000 </a>
2001 </td><td>
2001 </td><td>
2002 Bundle File Formats
2002 Bundle File Formats
2003 </td></tr>
2003 </td></tr>
2004 <tr><td>
2004 <tr><td>
2005 <a href="/help/color">
2005 <a href="/help/color">
2006 color
2006 color
2007 </a>
2007 </a>
2008 </td><td>
2008 </td><td>
2009 Colorizing Outputs
2009 Colorizing Outputs
2010 </td></tr>
2010 </td></tr>
2011 <tr><td>
2011 <tr><td>
2012 <a href="/help/config">
2012 <a href="/help/config">
2013 config
2013 config
2014 </a>
2014 </a>
2015 </td><td>
2015 </td><td>
2016 Configuration Files
2016 Configuration Files
2017 </td></tr>
2017 </td></tr>
2018 <tr><td>
2018 <tr><td>
2019 <a href="/help/dates">
2019 <a href="/help/dates">
2020 dates
2020 dates
2021 </a>
2021 </a>
2022 </td><td>
2022 </td><td>
2023 Date Formats
2023 Date Formats
2024 </td></tr>
2024 </td></tr>
2025 <tr><td>
2025 <tr><td>
2026 <a href="/help/diffs">
2026 <a href="/help/diffs">
2027 diffs
2027 diffs
2028 </a>
2028 </a>
2029 </td><td>
2029 </td><td>
2030 Diff Formats
2030 Diff Formats
2031 </td></tr>
2031 </td></tr>
2032 <tr><td>
2032 <tr><td>
2033 <a href="/help/environment">
2033 <a href="/help/environment">
2034 environment
2034 environment
2035 </a>
2035 </a>
2036 </td><td>
2036 </td><td>
2037 Environment Variables
2037 Environment Variables
2038 </td></tr>
2038 </td></tr>
2039 <tr><td>
2039 <tr><td>
2040 <a href="/help/extensions">
2040 <a href="/help/extensions">
2041 extensions
2041 extensions
2042 </a>
2042 </a>
2043 </td><td>
2043 </td><td>
2044 Using Additional Features
2044 Using Additional Features
2045 </td></tr>
2045 </td></tr>
2046 <tr><td>
2046 <tr><td>
2047 <a href="/help/filesets">
2047 <a href="/help/filesets">
2048 filesets
2048 filesets
2049 </a>
2049 </a>
2050 </td><td>
2050 </td><td>
2051 Specifying File Sets
2051 Specifying File Sets
2052 </td></tr>
2052 </td></tr>
2053 <tr><td>
2053 <tr><td>
2054 <a href="/help/flags">
2054 <a href="/help/flags">
2055 flags
2055 flags
2056 </a>
2056 </a>
2057 </td><td>
2057 </td><td>
2058 Command-line flags
2058 Command-line flags
2059 </td></tr>
2059 </td></tr>
2060 <tr><td>
2060 <tr><td>
2061 <a href="/help/glossary">
2061 <a href="/help/glossary">
2062 glossary
2062 glossary
2063 </a>
2063 </a>
2064 </td><td>
2064 </td><td>
2065 Glossary
2065 Glossary
2066 </td></tr>
2066 </td></tr>
2067 <tr><td>
2067 <tr><td>
2068 <a href="/help/hgignore">
2068 <a href="/help/hgignore">
2069 hgignore
2069 hgignore
2070 </a>
2070 </a>
2071 </td><td>
2071 </td><td>
2072 Syntax for Mercurial Ignore Files
2072 Syntax for Mercurial Ignore Files
2073 </td></tr>
2073 </td></tr>
2074 <tr><td>
2074 <tr><td>
2075 <a href="/help/hgweb">
2075 <a href="/help/hgweb">
2076 hgweb
2076 hgweb
2077 </a>
2077 </a>
2078 </td><td>
2078 </td><td>
2079 Configuring hgweb
2079 Configuring hgweb
2080 </td></tr>
2080 </td></tr>
2081 <tr><td>
2081 <tr><td>
2082 <a href="/help/internals">
2082 <a href="/help/internals">
2083 internals
2083 internals
2084 </a>
2084 </a>
2085 </td><td>
2085 </td><td>
2086 Technical implementation topics
2086 Technical implementation topics
2087 </td></tr>
2087 </td></tr>
2088 <tr><td>
2088 <tr><td>
2089 <a href="/help/merge-tools">
2089 <a href="/help/merge-tools">
2090 merge-tools
2090 merge-tools
2091 </a>
2091 </a>
2092 </td><td>
2092 </td><td>
2093 Merge Tools
2093 Merge Tools
2094 </td></tr>
2094 </td></tr>
2095 <tr><td>
2095 <tr><td>
2096 <a href="/help/pager">
2096 <a href="/help/pager">
2097 pager
2097 pager
2098 </a>
2098 </a>
2099 </td><td>
2099 </td><td>
2100 Pager Support
2100 Pager Support
2101 </td></tr>
2101 </td></tr>
2102 <tr><td>
2102 <tr><td>
2103 <a href="/help/patterns">
2103 <a href="/help/patterns">
2104 patterns
2104 patterns
2105 </a>
2105 </a>
2106 </td><td>
2106 </td><td>
2107 File Name Patterns
2107 File Name Patterns
2108 </td></tr>
2108 </td></tr>
2109 <tr><td>
2109 <tr><td>
2110 <a href="/help/phases">
2110 <a href="/help/phases">
2111 phases
2111 phases
2112 </a>
2112 </a>
2113 </td><td>
2113 </td><td>
2114 Working with Phases
2114 Working with Phases
2115 </td></tr>
2115 </td></tr>
2116 <tr><td>
2116 <tr><td>
2117 <a href="/help/revisions">
2117 <a href="/help/revisions">
2118 revisions
2118 revisions
2119 </a>
2119 </a>
2120 </td><td>
2120 </td><td>
2121 Specifying Revisions
2121 Specifying Revisions
2122 </td></tr>
2122 </td></tr>
2123 <tr><td>
2123 <tr><td>
2124 <a href="/help/scripting">
2124 <a href="/help/scripting">
2125 scripting
2125 scripting
2126 </a>
2126 </a>
2127 </td><td>
2127 </td><td>
2128 Using Mercurial from scripts and automation
2128 Using Mercurial from scripts and automation
2129 </td></tr>
2129 </td></tr>
2130 <tr><td>
2130 <tr><td>
2131 <a href="/help/subrepos">
2131 <a href="/help/subrepos">
2132 subrepos
2132 subrepos
2133 </a>
2133 </a>
2134 </td><td>
2134 </td><td>
2135 Subrepositories
2135 Subrepositories
2136 </td></tr>
2136 </td></tr>
2137 <tr><td>
2137 <tr><td>
2138 <a href="/help/templating">
2138 <a href="/help/templating">
2139 templating
2139 templating
2140 </a>
2140 </a>
2141 </td><td>
2141 </td><td>
2142 Template Usage
2142 Template Usage
2143 </td></tr>
2143 </td></tr>
2144 <tr><td>
2144 <tr><td>
2145 <a href="/help/urls">
2145 <a href="/help/urls">
2146 urls
2146 urls
2147 </a>
2147 </a>
2148 </td><td>
2148 </td><td>
2149 URL Paths
2149 URL Paths
2150 </td></tr>
2150 </td></tr>
2151 <tr><td>
2151 <tr><td>
2152 <a href="/help/topic-containing-verbose">
2152 <a href="/help/topic-containing-verbose">
2153 topic-containing-verbose
2153 topic-containing-verbose
2154 </a>
2154 </a>
2155 </td><td>
2155 </td><td>
2156 This is the topic to test omit indicating.
2156 This is the topic to test omit indicating.
2157 </td></tr>
2157 </td></tr>
2158
2158
2159
2159
2160 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2160 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2161
2161
2162 <tr><td>
2162 <tr><td>
2163 <a href="/help/add">
2163 <a href="/help/add">
2164 add
2164 add
2165 </a>
2165 </a>
2166 </td><td>
2166 </td><td>
2167 add the specified files on the next commit
2167 add the specified files on the next commit
2168 </td></tr>
2168 </td></tr>
2169 <tr><td>
2169 <tr><td>
2170 <a href="/help/annotate">
2170 <a href="/help/annotate">
2171 annotate
2171 annotate
2172 </a>
2172 </a>
2173 </td><td>
2173 </td><td>
2174 show changeset information by line for each file
2174 show changeset information by line for each file
2175 </td></tr>
2175 </td></tr>
2176 <tr><td>
2176 <tr><td>
2177 <a href="/help/clone">
2177 <a href="/help/clone">
2178 clone
2178 clone
2179 </a>
2179 </a>
2180 </td><td>
2180 </td><td>
2181 make a copy of an existing repository
2181 make a copy of an existing repository
2182 </td></tr>
2182 </td></tr>
2183 <tr><td>
2183 <tr><td>
2184 <a href="/help/commit">
2184 <a href="/help/commit">
2185 commit
2185 commit
2186 </a>
2186 </a>
2187 </td><td>
2187 </td><td>
2188 commit the specified files or all outstanding changes
2188 commit the specified files or all outstanding changes
2189 </td></tr>
2189 </td></tr>
2190 <tr><td>
2190 <tr><td>
2191 <a href="/help/diff">
2191 <a href="/help/diff">
2192 diff
2192 diff
2193 </a>
2193 </a>
2194 </td><td>
2194 </td><td>
2195 diff repository (or selected files)
2195 diff repository (or selected files)
2196 </td></tr>
2196 </td></tr>
2197 <tr><td>
2197 <tr><td>
2198 <a href="/help/export">
2198 <a href="/help/export">
2199 export
2199 export
2200 </a>
2200 </a>
2201 </td><td>
2201 </td><td>
2202 dump the header and diffs for one or more changesets
2202 dump the header and diffs for one or more changesets
2203 </td></tr>
2203 </td></tr>
2204 <tr><td>
2204 <tr><td>
2205 <a href="/help/forget">
2205 <a href="/help/forget">
2206 forget
2206 forget
2207 </a>
2207 </a>
2208 </td><td>
2208 </td><td>
2209 forget the specified files on the next commit
2209 forget the specified files on the next commit
2210 </td></tr>
2210 </td></tr>
2211 <tr><td>
2211 <tr><td>
2212 <a href="/help/init">
2212 <a href="/help/init">
2213 init
2213 init
2214 </a>
2214 </a>
2215 </td><td>
2215 </td><td>
2216 create a new repository in the given directory
2216 create a new repository in the given directory
2217 </td></tr>
2217 </td></tr>
2218 <tr><td>
2218 <tr><td>
2219 <a href="/help/log">
2219 <a href="/help/log">
2220 log
2220 log
2221 </a>
2221 </a>
2222 </td><td>
2222 </td><td>
2223 show revision history of entire repository or files
2223 show revision history of entire repository or files
2224 </td></tr>
2224 </td></tr>
2225 <tr><td>
2225 <tr><td>
2226 <a href="/help/merge">
2226 <a href="/help/merge">
2227 merge
2227 merge
2228 </a>
2228 </a>
2229 </td><td>
2229 </td><td>
2230 merge another revision into working directory
2230 merge another revision into working directory
2231 </td></tr>
2231 </td></tr>
2232 <tr><td>
2232 <tr><td>
2233 <a href="/help/pull">
2233 <a href="/help/pull">
2234 pull
2234 pull
2235 </a>
2235 </a>
2236 </td><td>
2236 </td><td>
2237 pull changes from the specified source
2237 pull changes from the specified source
2238 </td></tr>
2238 </td></tr>
2239 <tr><td>
2239 <tr><td>
2240 <a href="/help/push">
2240 <a href="/help/push">
2241 push
2241 push
2242 </a>
2242 </a>
2243 </td><td>
2243 </td><td>
2244 push changes to the specified destination
2244 push changes to the specified destination
2245 </td></tr>
2245 </td></tr>
2246 <tr><td>
2246 <tr><td>
2247 <a href="/help/remove">
2247 <a href="/help/remove">
2248 remove
2248 remove
2249 </a>
2249 </a>
2250 </td><td>
2250 </td><td>
2251 remove the specified files on the next commit
2251 remove the specified files on the next commit
2252 </td></tr>
2252 </td></tr>
2253 <tr><td>
2253 <tr><td>
2254 <a href="/help/serve">
2254 <a href="/help/serve">
2255 serve
2255 serve
2256 </a>
2256 </a>
2257 </td><td>
2257 </td><td>
2258 start stand-alone webserver
2258 start stand-alone webserver
2259 </td></tr>
2259 </td></tr>
2260 <tr><td>
2260 <tr><td>
2261 <a href="/help/status">
2261 <a href="/help/status">
2262 status
2262 status
2263 </a>
2263 </a>
2264 </td><td>
2264 </td><td>
2265 show changed files in the working directory
2265 show changed files in the working directory
2266 </td></tr>
2266 </td></tr>
2267 <tr><td>
2267 <tr><td>
2268 <a href="/help/summary">
2268 <a href="/help/summary">
2269 summary
2269 summary
2270 </a>
2270 </a>
2271 </td><td>
2271 </td><td>
2272 summarize working directory state
2272 summarize working directory state
2273 </td></tr>
2273 </td></tr>
2274 <tr><td>
2274 <tr><td>
2275 <a href="/help/update">
2275 <a href="/help/update">
2276 update
2276 update
2277 </a>
2277 </a>
2278 </td><td>
2278 </td><td>
2279 update working directory (or switch revisions)
2279 update working directory (or switch revisions)
2280 </td></tr>
2280 </td></tr>
2281
2281
2282
2282
2283
2283
2284 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2284 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2285
2285
2286 <tr><td>
2286 <tr><td>
2287 <a href="/help/addremove">
2287 <a href="/help/addremove">
2288 addremove
2288 addremove
2289 </a>
2289 </a>
2290 </td><td>
2290 </td><td>
2291 add all new files, delete all missing files
2291 add all new files, delete all missing files
2292 </td></tr>
2292 </td></tr>
2293 <tr><td>
2293 <tr><td>
2294 <a href="/help/archive">
2294 <a href="/help/archive">
2295 archive
2295 archive
2296 </a>
2296 </a>
2297 </td><td>
2297 </td><td>
2298 create an unversioned archive of a repository revision
2298 create an unversioned archive of a repository revision
2299 </td></tr>
2299 </td></tr>
2300 <tr><td>
2300 <tr><td>
2301 <a href="/help/backout">
2301 <a href="/help/backout">
2302 backout
2302 backout
2303 </a>
2303 </a>
2304 </td><td>
2304 </td><td>
2305 reverse effect of earlier changeset
2305 reverse effect of earlier changeset
2306 </td></tr>
2306 </td></tr>
2307 <tr><td>
2307 <tr><td>
2308 <a href="/help/bisect">
2308 <a href="/help/bisect">
2309 bisect
2309 bisect
2310 </a>
2310 </a>
2311 </td><td>
2311 </td><td>
2312 subdivision search of changesets
2312 subdivision search of changesets
2313 </td></tr>
2313 </td></tr>
2314 <tr><td>
2314 <tr><td>
2315 <a href="/help/bookmarks">
2315 <a href="/help/bookmarks">
2316 bookmarks
2316 bookmarks
2317 </a>
2317 </a>
2318 </td><td>
2318 </td><td>
2319 create a new bookmark or list existing bookmarks
2319 create a new bookmark or list existing bookmarks
2320 </td></tr>
2320 </td></tr>
2321 <tr><td>
2321 <tr><td>
2322 <a href="/help/branch">
2322 <a href="/help/branch">
2323 branch
2323 branch
2324 </a>
2324 </a>
2325 </td><td>
2325 </td><td>
2326 set or show the current branch name
2326 set or show the current branch name
2327 </td></tr>
2327 </td></tr>
2328 <tr><td>
2328 <tr><td>
2329 <a href="/help/branches">
2329 <a href="/help/branches">
2330 branches
2330 branches
2331 </a>
2331 </a>
2332 </td><td>
2332 </td><td>
2333 list repository named branches
2333 list repository named branches
2334 </td></tr>
2334 </td></tr>
2335 <tr><td>
2335 <tr><td>
2336 <a href="/help/bundle">
2336 <a href="/help/bundle">
2337 bundle
2337 bundle
2338 </a>
2338 </a>
2339 </td><td>
2339 </td><td>
2340 create a bundle file
2340 create a bundle file
2341 </td></tr>
2341 </td></tr>
2342 <tr><td>
2342 <tr><td>
2343 <a href="/help/cat">
2343 <a href="/help/cat">
2344 cat
2344 cat
2345 </a>
2345 </a>
2346 </td><td>
2346 </td><td>
2347 output the current or given revision of files
2347 output the current or given revision of files
2348 </td></tr>
2348 </td></tr>
2349 <tr><td>
2349 <tr><td>
2350 <a href="/help/config">
2350 <a href="/help/config">
2351 config
2351 config
2352 </a>
2352 </a>
2353 </td><td>
2353 </td><td>
2354 show combined config settings from all hgrc files
2354 show combined config settings from all hgrc files
2355 </td></tr>
2355 </td></tr>
2356 <tr><td>
2356 <tr><td>
2357 <a href="/help/copy">
2357 <a href="/help/copy">
2358 copy
2358 copy
2359 </a>
2359 </a>
2360 </td><td>
2360 </td><td>
2361 mark files as copied for the next commit
2361 mark files as copied for the next commit
2362 </td></tr>
2362 </td></tr>
2363 <tr><td>
2363 <tr><td>
2364 <a href="/help/files">
2364 <a href="/help/files">
2365 files
2365 files
2366 </a>
2366 </a>
2367 </td><td>
2367 </td><td>
2368 list tracked files
2368 list tracked files
2369 </td></tr>
2369 </td></tr>
2370 <tr><td>
2370 <tr><td>
2371 <a href="/help/graft">
2371 <a href="/help/graft">
2372 graft
2372 graft
2373 </a>
2373 </a>
2374 </td><td>
2374 </td><td>
2375 copy changes from other branches onto the current branch
2375 copy changes from other branches onto the current branch
2376 </td></tr>
2376 </td></tr>
2377 <tr><td>
2377 <tr><td>
2378 <a href="/help/grep">
2378 <a href="/help/grep">
2379 grep
2379 grep
2380 </a>
2380 </a>
2381 </td><td>
2381 </td><td>
2382 search revision history for a pattern in specified files
2382 search revision history for a pattern in specified files
2383 </td></tr>
2383 </td></tr>
2384 <tr><td>
2384 <tr><td>
2385 <a href="/help/heads">
2385 <a href="/help/heads">
2386 heads
2386 heads
2387 </a>
2387 </a>
2388 </td><td>
2388 </td><td>
2389 show branch heads
2389 show branch heads
2390 </td></tr>
2390 </td></tr>
2391 <tr><td>
2391 <tr><td>
2392 <a href="/help/help">
2392 <a href="/help/help">
2393 help
2393 help
2394 </a>
2394 </a>
2395 </td><td>
2395 </td><td>
2396 show help for a given topic or a help overview
2396 show help for a given topic or a help overview
2397 </td></tr>
2397 </td></tr>
2398 <tr><td>
2398 <tr><td>
2399 <a href="/help/hgalias">
2399 <a href="/help/hgalias">
2400 hgalias
2400 hgalias
2401 </a>
2401 </a>
2402 </td><td>
2402 </td><td>
2403 summarize working directory state
2403 summarize working directory state
2404 </td></tr>
2404 </td></tr>
2405 <tr><td>
2405 <tr><td>
2406 <a href="/help/identify">
2406 <a href="/help/identify">
2407 identify
2407 identify
2408 </a>
2408 </a>
2409 </td><td>
2409 </td><td>
2410 identify the working directory or specified revision
2410 identify the working directory or specified revision
2411 </td></tr>
2411 </td></tr>
2412 <tr><td>
2412 <tr><td>
2413 <a href="/help/import">
2413 <a href="/help/import">
2414 import
2414 import
2415 </a>
2415 </a>
2416 </td><td>
2416 </td><td>
2417 import an ordered set of patches
2417 import an ordered set of patches
2418 </td></tr>
2418 </td></tr>
2419 <tr><td>
2419 <tr><td>
2420 <a href="/help/incoming">
2420 <a href="/help/incoming">
2421 incoming
2421 incoming
2422 </a>
2422 </a>
2423 </td><td>
2423 </td><td>
2424 show new changesets found in source
2424 show new changesets found in source
2425 </td></tr>
2425 </td></tr>
2426 <tr><td>
2426 <tr><td>
2427 <a href="/help/manifest">
2427 <a href="/help/manifest">
2428 manifest
2428 manifest
2429 </a>
2429 </a>
2430 </td><td>
2430 </td><td>
2431 output the current or given revision of the project manifest
2431 output the current or given revision of the project manifest
2432 </td></tr>
2432 </td></tr>
2433 <tr><td>
2433 <tr><td>
2434 <a href="/help/nohelp">
2434 <a href="/help/nohelp">
2435 nohelp
2435 nohelp
2436 </a>
2436 </a>
2437 </td><td>
2437 </td><td>
2438 (no help text available)
2438 (no help text available)
2439 </td></tr>
2439 </td></tr>
2440 <tr><td>
2440 <tr><td>
2441 <a href="/help/outgoing">
2441 <a href="/help/outgoing">
2442 outgoing
2442 outgoing
2443 </a>
2443 </a>
2444 </td><td>
2444 </td><td>
2445 show changesets not found in the destination
2445 show changesets not found in the destination
2446 </td></tr>
2446 </td></tr>
2447 <tr><td>
2447 <tr><td>
2448 <a href="/help/paths">
2448 <a href="/help/paths">
2449 paths
2449 paths
2450 </a>
2450 </a>
2451 </td><td>
2451 </td><td>
2452 show aliases for remote repositories
2452 show aliases for remote repositories
2453 </td></tr>
2453 </td></tr>
2454 <tr><td>
2454 <tr><td>
2455 <a href="/help/phase">
2455 <a href="/help/phase">
2456 phase
2456 phase
2457 </a>
2457 </a>
2458 </td><td>
2458 </td><td>
2459 set or show the current phase name
2459 set or show the current phase name
2460 </td></tr>
2460 </td></tr>
2461 <tr><td>
2461 <tr><td>
2462 <a href="/help/recover">
2462 <a href="/help/recover">
2463 recover
2463 recover
2464 </a>
2464 </a>
2465 </td><td>
2465 </td><td>
2466 roll back an interrupted transaction
2466 roll back an interrupted transaction
2467 </td></tr>
2467 </td></tr>
2468 <tr><td>
2468 <tr><td>
2469 <a href="/help/rename">
2469 <a href="/help/rename">
2470 rename
2470 rename
2471 </a>
2471 </a>
2472 </td><td>
2472 </td><td>
2473 rename files; equivalent of copy + remove
2473 rename files; equivalent of copy + remove
2474 </td></tr>
2474 </td></tr>
2475 <tr><td>
2475 <tr><td>
2476 <a href="/help/resolve">
2476 <a href="/help/resolve">
2477 resolve
2477 resolve
2478 </a>
2478 </a>
2479 </td><td>
2479 </td><td>
2480 redo merges or set/view the merge status of files
2480 redo merges or set/view the merge status of files
2481 </td></tr>
2481 </td></tr>
2482 <tr><td>
2482 <tr><td>
2483 <a href="/help/revert">
2483 <a href="/help/revert">
2484 revert
2484 revert
2485 </a>
2485 </a>
2486 </td><td>
2486 </td><td>
2487 restore files to their checkout state
2487 restore files to their checkout state
2488 </td></tr>
2488 </td></tr>
2489 <tr><td>
2489 <tr><td>
2490 <a href="/help/root">
2490 <a href="/help/root">
2491 root
2491 root
2492 </a>
2492 </a>
2493 </td><td>
2493 </td><td>
2494 print the root (top) of the current working directory
2494 print the root (top) of the current working directory
2495 </td></tr>
2495 </td></tr>
2496 <tr><td>
2496 <tr><td>
2497 <a href="/help/shellalias">
2497 <a href="/help/shellalias">
2498 shellalias
2498 shellalias
2499 </a>
2499 </a>
2500 </td><td>
2500 </td><td>
2501 (no help text available)
2501 (no help text available)
2502 </td></tr>
2502 </td></tr>
2503 <tr><td>
2503 <tr><td>
2504 <a href="/help/tag">
2504 <a href="/help/tag">
2505 tag
2505 tag
2506 </a>
2506 </a>
2507 </td><td>
2507 </td><td>
2508 add one or more tags for the current or given revision
2508 add one or more tags for the current or given revision
2509 </td></tr>
2509 </td></tr>
2510 <tr><td>
2510 <tr><td>
2511 <a href="/help/tags">
2511 <a href="/help/tags">
2512 tags
2512 tags
2513 </a>
2513 </a>
2514 </td><td>
2514 </td><td>
2515 list repository tags
2515 list repository tags
2516 </td></tr>
2516 </td></tr>
2517 <tr><td>
2517 <tr><td>
2518 <a href="/help/unbundle">
2518 <a href="/help/unbundle">
2519 unbundle
2519 unbundle
2520 </a>
2520 </a>
2521 </td><td>
2521 </td><td>
2522 apply one or more bundle files
2522 apply one or more bundle files
2523 </td></tr>
2523 </td></tr>
2524 <tr><td>
2524 <tr><td>
2525 <a href="/help/verify">
2525 <a href="/help/verify">
2526 verify
2526 verify
2527 </a>
2527 </a>
2528 </td><td>
2528 </td><td>
2529 verify the integrity of the repository
2529 verify the integrity of the repository
2530 </td></tr>
2530 </td></tr>
2531 <tr><td>
2531 <tr><td>
2532 <a href="/help/version">
2532 <a href="/help/version">
2533 version
2533 version
2534 </a>
2534 </a>
2535 </td><td>
2535 </td><td>
2536 output version and copyright information
2536 output version and copyright information
2537 </td></tr>
2537 </td></tr>
2538
2538
2539
2539
2540 </table>
2540 </table>
2541 </div>
2541 </div>
2542 </div>
2542 </div>
2543
2543
2544
2544
2545
2545
2546 </body>
2546 </body>
2547 </html>
2547 </html>
2548
2548
2549
2549
2550 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2550 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2551 200 Script output follows
2551 200 Script output follows
2552
2552
2553 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2553 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2554 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2554 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2555 <head>
2555 <head>
2556 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2556 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2557 <meta name="robots" content="index, nofollow" />
2557 <meta name="robots" content="index, nofollow" />
2558 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2558 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2559 <script type="text/javascript" src="/static/mercurial.js"></script>
2559 <script type="text/javascript" src="/static/mercurial.js"></script>
2560
2560
2561 <title>Help: add</title>
2561 <title>Help: add</title>
2562 </head>
2562 </head>
2563 <body>
2563 <body>
2564
2564
2565 <div class="container">
2565 <div class="container">
2566 <div class="menu">
2566 <div class="menu">
2567 <div class="logo">
2567 <div class="logo">
2568 <a href="https://mercurial-scm.org/">
2568 <a href="https://mercurial-scm.org/">
2569 <img src="/static/hglogo.png" alt="mercurial" /></a>
2569 <img src="/static/hglogo.png" alt="mercurial" /></a>
2570 </div>
2570 </div>
2571 <ul>
2571 <ul>
2572 <li><a href="/shortlog">log</a></li>
2572 <li><a href="/shortlog">log</a></li>
2573 <li><a href="/graph">graph</a></li>
2573 <li><a href="/graph">graph</a></li>
2574 <li><a href="/tags">tags</a></li>
2574 <li><a href="/tags">tags</a></li>
2575 <li><a href="/bookmarks">bookmarks</a></li>
2575 <li><a href="/bookmarks">bookmarks</a></li>
2576 <li><a href="/branches">branches</a></li>
2576 <li><a href="/branches">branches</a></li>
2577 </ul>
2577 </ul>
2578 <ul>
2578 <ul>
2579 <li class="active"><a href="/help">help</a></li>
2579 <li class="active"><a href="/help">help</a></li>
2580 </ul>
2580 </ul>
2581 </div>
2581 </div>
2582
2582
2583 <div class="main">
2583 <div class="main">
2584 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2584 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2585 <h3>Help: add</h3>
2585 <h3>Help: add</h3>
2586
2586
2587 <form class="search" action="/log">
2587 <form class="search" action="/log">
2588
2588
2589 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2589 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2590 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2590 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2591 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2591 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2592 </form>
2592 </form>
2593 <div id="doc">
2593 <div id="doc">
2594 <p>
2594 <p>
2595 hg add [OPTION]... [FILE]...
2595 hg add [OPTION]... [FILE]...
2596 </p>
2596 </p>
2597 <p>
2597 <p>
2598 add the specified files on the next commit
2598 add the specified files on the next commit
2599 </p>
2599 </p>
2600 <p>
2600 <p>
2601 Schedule files to be version controlled and added to the
2601 Schedule files to be version controlled and added to the
2602 repository.
2602 repository.
2603 </p>
2603 </p>
2604 <p>
2604 <p>
2605 The files will be added to the repository at the next commit. To
2605 The files will be added to the repository at the next commit. To
2606 undo an add before that, see 'hg forget'.
2606 undo an add before that, see 'hg forget'.
2607 </p>
2607 </p>
2608 <p>
2608 <p>
2609 If no names are given, add all files to the repository (except
2609 If no names are given, add all files to the repository (except
2610 files matching &quot;.hgignore&quot;).
2610 files matching &quot;.hgignore&quot;).
2611 </p>
2611 </p>
2612 <p>
2612 <p>
2613 Examples:
2613 Examples:
2614 </p>
2614 </p>
2615 <ul>
2615 <ul>
2616 <li> New (unknown) files are added automatically by 'hg add':
2616 <li> New (unknown) files are added automatically by 'hg add':
2617 <pre>
2617 <pre>
2618 \$ ls (re)
2618 \$ ls (re)
2619 foo.c
2619 foo.c
2620 \$ hg status (re)
2620 \$ hg status (re)
2621 ? foo.c
2621 ? foo.c
2622 \$ hg add (re)
2622 \$ hg add (re)
2623 adding foo.c
2623 adding foo.c
2624 \$ hg status (re)
2624 \$ hg status (re)
2625 A foo.c
2625 A foo.c
2626 </pre>
2626 </pre>
2627 <li> Specific files to be added can be specified:
2627 <li> Specific files to be added can be specified:
2628 <pre>
2628 <pre>
2629 \$ ls (re)
2629 \$ ls (re)
2630 bar.c foo.c
2630 bar.c foo.c
2631 \$ hg status (re)
2631 \$ hg status (re)
2632 ? bar.c
2632 ? bar.c
2633 ? foo.c
2633 ? foo.c
2634 \$ hg add bar.c (re)
2634 \$ hg add bar.c (re)
2635 \$ hg status (re)
2635 \$ hg status (re)
2636 A bar.c
2636 A bar.c
2637 ? foo.c
2637 ? foo.c
2638 </pre>
2638 </pre>
2639 </ul>
2639 </ul>
2640 <p>
2640 <p>
2641 Returns 0 if all files are successfully added.
2641 Returns 0 if all files are successfully added.
2642 </p>
2642 </p>
2643 <p>
2643 <p>
2644 options ([+] can be repeated):
2644 options ([+] can be repeated):
2645 </p>
2645 </p>
2646 <table>
2646 <table>
2647 <tr><td>-I</td>
2647 <tr><td>-I</td>
2648 <td>--include PATTERN [+]</td>
2648 <td>--include PATTERN [+]</td>
2649 <td>include names matching the given patterns</td></tr>
2649 <td>include names matching the given patterns</td></tr>
2650 <tr><td>-X</td>
2650 <tr><td>-X</td>
2651 <td>--exclude PATTERN [+]</td>
2651 <td>--exclude PATTERN [+]</td>
2652 <td>exclude names matching the given patterns</td></tr>
2652 <td>exclude names matching the given patterns</td></tr>
2653 <tr><td>-S</td>
2653 <tr><td>-S</td>
2654 <td>--subrepos</td>
2654 <td>--subrepos</td>
2655 <td>recurse into subrepositories</td></tr>
2655 <td>recurse into subrepositories</td></tr>
2656 <tr><td>-n</td>
2656 <tr><td>-n</td>
2657 <td>--dry-run</td>
2657 <td>--dry-run</td>
2658 <td>do not perform actions, just print output</td></tr>
2658 <td>do not perform actions, just print output</td></tr>
2659 </table>
2659 </table>
2660 <p>
2660 <p>
2661 global options ([+] can be repeated):
2661 global options ([+] can be repeated):
2662 </p>
2662 </p>
2663 <table>
2663 <table>
2664 <tr><td>-R</td>
2664 <tr><td>-R</td>
2665 <td>--repository REPO</td>
2665 <td>--repository REPO</td>
2666 <td>repository root directory or name of overlay bundle file</td></tr>
2666 <td>repository root directory or name of overlay bundle file</td></tr>
2667 <tr><td></td>
2667 <tr><td></td>
2668 <td>--cwd DIR</td>
2668 <td>--cwd DIR</td>
2669 <td>change working directory</td></tr>
2669 <td>change working directory</td></tr>
2670 <tr><td>-y</td>
2670 <tr><td>-y</td>
2671 <td>--noninteractive</td>
2671 <td>--noninteractive</td>
2672 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2672 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2673 <tr><td>-q</td>
2673 <tr><td>-q</td>
2674 <td>--quiet</td>
2674 <td>--quiet</td>
2675 <td>suppress output</td></tr>
2675 <td>suppress output</td></tr>
2676 <tr><td>-v</td>
2676 <tr><td>-v</td>
2677 <td>--verbose</td>
2677 <td>--verbose</td>
2678 <td>enable additional output</td></tr>
2678 <td>enable additional output</td></tr>
2679 <tr><td></td>
2679 <tr><td></td>
2680 <td>--color TYPE</td>
2680 <td>--color TYPE</td>
2681 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2681 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2682 <tr><td></td>
2682 <tr><td></td>
2683 <td>--config CONFIG [+]</td>
2683 <td>--config CONFIG [+]</td>
2684 <td>set/override config option (use 'section.name=value')</td></tr>
2684 <td>set/override config option (use 'section.name=value')</td></tr>
2685 <tr><td></td>
2685 <tr><td></td>
2686 <td>--debug</td>
2686 <td>--debug</td>
2687 <td>enable debugging output</td></tr>
2687 <td>enable debugging output</td></tr>
2688 <tr><td></td>
2688 <tr><td></td>
2689 <td>--debugger</td>
2689 <td>--debugger</td>
2690 <td>start debugger</td></tr>
2690 <td>start debugger</td></tr>
2691 <tr><td></td>
2691 <tr><td></td>
2692 <td>--encoding ENCODE</td>
2692 <td>--encoding ENCODE</td>
2693 <td>set the charset encoding (default: ascii)</td></tr>
2693 <td>set the charset encoding (default: ascii)</td></tr>
2694 <tr><td></td>
2694 <tr><td></td>
2695 <td>--encodingmode MODE</td>
2695 <td>--encodingmode MODE</td>
2696 <td>set the charset encoding mode (default: strict)</td></tr>
2696 <td>set the charset encoding mode (default: strict)</td></tr>
2697 <tr><td></td>
2697 <tr><td></td>
2698 <td>--traceback</td>
2698 <td>--traceback</td>
2699 <td>always print a traceback on exception</td></tr>
2699 <td>always print a traceback on exception</td></tr>
2700 <tr><td></td>
2700 <tr><td></td>
2701 <td>--time</td>
2701 <td>--time</td>
2702 <td>time how long the command takes</td></tr>
2702 <td>time how long the command takes</td></tr>
2703 <tr><td></td>
2703 <tr><td></td>
2704 <td>--profile</td>
2704 <td>--profile</td>
2705 <td>print command execution profile</td></tr>
2705 <td>print command execution profile</td></tr>
2706 <tr><td></td>
2706 <tr><td></td>
2707 <td>--version</td>
2707 <td>--version</td>
2708 <td>output version information and exit</td></tr>
2708 <td>output version information and exit</td></tr>
2709 <tr><td>-h</td>
2709 <tr><td>-h</td>
2710 <td>--help</td>
2710 <td>--help</td>
2711 <td>display help and exit</td></tr>
2711 <td>display help and exit</td></tr>
2712 <tr><td></td>
2712 <tr><td></td>
2713 <td>--hidden</td>
2713 <td>--hidden</td>
2714 <td>consider hidden changesets</td></tr>
2714 <td>consider hidden changesets</td></tr>
2715 <tr><td></td>
2715 <tr><td></td>
2716 <td>--pager TYPE</td>
2716 <td>--pager TYPE</td>
2717 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2717 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2718 </table>
2718 </table>
2719
2719
2720 </div>
2720 </div>
2721 </div>
2721 </div>
2722 </div>
2722 </div>
2723
2723
2724
2724
2725
2725
2726 </body>
2726 </body>
2727 </html>
2727 </html>
2728
2728
2729
2729
2730 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2730 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2731 200 Script output follows
2731 200 Script output follows
2732
2732
2733 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2733 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2734 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2734 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2735 <head>
2735 <head>
2736 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2736 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2737 <meta name="robots" content="index, nofollow" />
2737 <meta name="robots" content="index, nofollow" />
2738 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2738 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2739 <script type="text/javascript" src="/static/mercurial.js"></script>
2739 <script type="text/javascript" src="/static/mercurial.js"></script>
2740
2740
2741 <title>Help: remove</title>
2741 <title>Help: remove</title>
2742 </head>
2742 </head>
2743 <body>
2743 <body>
2744
2744
2745 <div class="container">
2745 <div class="container">
2746 <div class="menu">
2746 <div class="menu">
2747 <div class="logo">
2747 <div class="logo">
2748 <a href="https://mercurial-scm.org/">
2748 <a href="https://mercurial-scm.org/">
2749 <img src="/static/hglogo.png" alt="mercurial" /></a>
2749 <img src="/static/hglogo.png" alt="mercurial" /></a>
2750 </div>
2750 </div>
2751 <ul>
2751 <ul>
2752 <li><a href="/shortlog">log</a></li>
2752 <li><a href="/shortlog">log</a></li>
2753 <li><a href="/graph">graph</a></li>
2753 <li><a href="/graph">graph</a></li>
2754 <li><a href="/tags">tags</a></li>
2754 <li><a href="/tags">tags</a></li>
2755 <li><a href="/bookmarks">bookmarks</a></li>
2755 <li><a href="/bookmarks">bookmarks</a></li>
2756 <li><a href="/branches">branches</a></li>
2756 <li><a href="/branches">branches</a></li>
2757 </ul>
2757 </ul>
2758 <ul>
2758 <ul>
2759 <li class="active"><a href="/help">help</a></li>
2759 <li class="active"><a href="/help">help</a></li>
2760 </ul>
2760 </ul>
2761 </div>
2761 </div>
2762
2762
2763 <div class="main">
2763 <div class="main">
2764 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2764 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2765 <h3>Help: remove</h3>
2765 <h3>Help: remove</h3>
2766
2766
2767 <form class="search" action="/log">
2767 <form class="search" action="/log">
2768
2768
2769 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2769 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2770 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2770 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2771 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2771 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2772 </form>
2772 </form>
2773 <div id="doc">
2773 <div id="doc">
2774 <p>
2774 <p>
2775 hg remove [OPTION]... FILE...
2775 hg remove [OPTION]... FILE...
2776 </p>
2776 </p>
2777 <p>
2777 <p>
2778 aliases: rm
2778 aliases: rm
2779 </p>
2779 </p>
2780 <p>
2780 <p>
2781 remove the specified files on the next commit
2781 remove the specified files on the next commit
2782 </p>
2782 </p>
2783 <p>
2783 <p>
2784 Schedule the indicated files for removal from the current branch.
2784 Schedule the indicated files for removal from the current branch.
2785 </p>
2785 </p>
2786 <p>
2786 <p>
2787 This command schedules the files to be removed at the next commit.
2787 This command schedules the files to be removed at the next commit.
2788 To undo a remove before that, see 'hg revert'. To undo added
2788 To undo a remove before that, see 'hg revert'. To undo added
2789 files, see 'hg forget'.
2789 files, see 'hg forget'.
2790 </p>
2790 </p>
2791 <p>
2791 <p>
2792 -A/--after can be used to remove only files that have already
2792 -A/--after can be used to remove only files that have already
2793 been deleted, -f/--force can be used to force deletion, and -Af
2793 been deleted, -f/--force can be used to force deletion, and -Af
2794 can be used to remove files from the next revision without
2794 can be used to remove files from the next revision without
2795 deleting them from the working directory.
2795 deleting them from the working directory.
2796 </p>
2796 </p>
2797 <p>
2797 <p>
2798 The following table details the behavior of remove for different
2798 The following table details the behavior of remove for different
2799 file states (columns) and option combinations (rows). The file
2799 file states (columns) and option combinations (rows). The file
2800 states are Added [A], Clean [C], Modified [M] and Missing [!]
2800 states are Added [A], Clean [C], Modified [M] and Missing [!]
2801 (as reported by 'hg status'). The actions are Warn, Remove
2801 (as reported by 'hg status'). The actions are Warn, Remove
2802 (from branch) and Delete (from disk):
2802 (from branch) and Delete (from disk):
2803 </p>
2803 </p>
2804 <table>
2804 <table>
2805 <tr><td>opt/state</td>
2805 <tr><td>opt/state</td>
2806 <td>A</td>
2806 <td>A</td>
2807 <td>C</td>
2807 <td>C</td>
2808 <td>M</td>
2808 <td>M</td>
2809 <td>!</td></tr>
2809 <td>!</td></tr>
2810 <tr><td>none</td>
2810 <tr><td>none</td>
2811 <td>W</td>
2811 <td>W</td>
2812 <td>RD</td>
2812 <td>RD</td>
2813 <td>W</td>
2813 <td>W</td>
2814 <td>R</td></tr>
2814 <td>R</td></tr>
2815 <tr><td>-f</td>
2815 <tr><td>-f</td>
2816 <td>R</td>
2816 <td>R</td>
2817 <td>RD</td>
2817 <td>RD</td>
2818 <td>RD</td>
2818 <td>RD</td>
2819 <td>R</td></tr>
2819 <td>R</td></tr>
2820 <tr><td>-A</td>
2820 <tr><td>-A</td>
2821 <td>W</td>
2821 <td>W</td>
2822 <td>W</td>
2822 <td>W</td>
2823 <td>W</td>
2823 <td>W</td>
2824 <td>R</td></tr>
2824 <td>R</td></tr>
2825 <tr><td>-Af</td>
2825 <tr><td>-Af</td>
2826 <td>R</td>
2826 <td>R</td>
2827 <td>R</td>
2827 <td>R</td>
2828 <td>R</td>
2828 <td>R</td>
2829 <td>R</td></tr>
2829 <td>R</td></tr>
2830 </table>
2830 </table>
2831 <p>
2831 <p>
2832 <b>Note:</b>
2832 <b>Note:</b>
2833 </p>
2833 </p>
2834 <p>
2834 <p>
2835 'hg remove' never deletes files in Added [A] state from the
2835 'hg remove' never deletes files in Added [A] state from the
2836 working directory, not even if &quot;--force&quot; is specified.
2836 working directory, not even if &quot;--force&quot; is specified.
2837 </p>
2837 </p>
2838 <p>
2838 <p>
2839 Returns 0 on success, 1 if any warnings encountered.
2839 Returns 0 on success, 1 if any warnings encountered.
2840 </p>
2840 </p>
2841 <p>
2841 <p>
2842 options ([+] can be repeated):
2842 options ([+] can be repeated):
2843 </p>
2843 </p>
2844 <table>
2844 <table>
2845 <tr><td>-A</td>
2845 <tr><td>-A</td>
2846 <td>--after</td>
2846 <td>--after</td>
2847 <td>record delete for missing files</td></tr>
2847 <td>record delete for missing files</td></tr>
2848 <tr><td>-f</td>
2848 <tr><td>-f</td>
2849 <td>--force</td>
2849 <td>--force</td>
2850 <td>forget added files, delete modified files</td></tr>
2850 <td>forget added files, delete modified files</td></tr>
2851 <tr><td>-S</td>
2851 <tr><td>-S</td>
2852 <td>--subrepos</td>
2852 <td>--subrepos</td>
2853 <td>recurse into subrepositories</td></tr>
2853 <td>recurse into subrepositories</td></tr>
2854 <tr><td>-I</td>
2854 <tr><td>-I</td>
2855 <td>--include PATTERN [+]</td>
2855 <td>--include PATTERN [+]</td>
2856 <td>include names matching the given patterns</td></tr>
2856 <td>include names matching the given patterns</td></tr>
2857 <tr><td>-X</td>
2857 <tr><td>-X</td>
2858 <td>--exclude PATTERN [+]</td>
2858 <td>--exclude PATTERN [+]</td>
2859 <td>exclude names matching the given patterns</td></tr>
2859 <td>exclude names matching the given patterns</td></tr>
2860 </table>
2860 </table>
2861 <p>
2861 <p>
2862 global options ([+] can be repeated):
2862 global options ([+] can be repeated):
2863 </p>
2863 </p>
2864 <table>
2864 <table>
2865 <tr><td>-R</td>
2865 <tr><td>-R</td>
2866 <td>--repository REPO</td>
2866 <td>--repository REPO</td>
2867 <td>repository root directory or name of overlay bundle file</td></tr>
2867 <td>repository root directory or name of overlay bundle file</td></tr>
2868 <tr><td></td>
2868 <tr><td></td>
2869 <td>--cwd DIR</td>
2869 <td>--cwd DIR</td>
2870 <td>change working directory</td></tr>
2870 <td>change working directory</td></tr>
2871 <tr><td>-y</td>
2871 <tr><td>-y</td>
2872 <td>--noninteractive</td>
2872 <td>--noninteractive</td>
2873 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2873 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2874 <tr><td>-q</td>
2874 <tr><td>-q</td>
2875 <td>--quiet</td>
2875 <td>--quiet</td>
2876 <td>suppress output</td></tr>
2876 <td>suppress output</td></tr>
2877 <tr><td>-v</td>
2877 <tr><td>-v</td>
2878 <td>--verbose</td>
2878 <td>--verbose</td>
2879 <td>enable additional output</td></tr>
2879 <td>enable additional output</td></tr>
2880 <tr><td></td>
2880 <tr><td></td>
2881 <td>--color TYPE</td>
2881 <td>--color TYPE</td>
2882 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2882 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2883 <tr><td></td>
2883 <tr><td></td>
2884 <td>--config CONFIG [+]</td>
2884 <td>--config CONFIG [+]</td>
2885 <td>set/override config option (use 'section.name=value')</td></tr>
2885 <td>set/override config option (use 'section.name=value')</td></tr>
2886 <tr><td></td>
2886 <tr><td></td>
2887 <td>--debug</td>
2887 <td>--debug</td>
2888 <td>enable debugging output</td></tr>
2888 <td>enable debugging output</td></tr>
2889 <tr><td></td>
2889 <tr><td></td>
2890 <td>--debugger</td>
2890 <td>--debugger</td>
2891 <td>start debugger</td></tr>
2891 <td>start debugger</td></tr>
2892 <tr><td></td>
2892 <tr><td></td>
2893 <td>--encoding ENCODE</td>
2893 <td>--encoding ENCODE</td>
2894 <td>set the charset encoding (default: ascii)</td></tr>
2894 <td>set the charset encoding (default: ascii)</td></tr>
2895 <tr><td></td>
2895 <tr><td></td>
2896 <td>--encodingmode MODE</td>
2896 <td>--encodingmode MODE</td>
2897 <td>set the charset encoding mode (default: strict)</td></tr>
2897 <td>set the charset encoding mode (default: strict)</td></tr>
2898 <tr><td></td>
2898 <tr><td></td>
2899 <td>--traceback</td>
2899 <td>--traceback</td>
2900 <td>always print a traceback on exception</td></tr>
2900 <td>always print a traceback on exception</td></tr>
2901 <tr><td></td>
2901 <tr><td></td>
2902 <td>--time</td>
2902 <td>--time</td>
2903 <td>time how long the command takes</td></tr>
2903 <td>time how long the command takes</td></tr>
2904 <tr><td></td>
2904 <tr><td></td>
2905 <td>--profile</td>
2905 <td>--profile</td>
2906 <td>print command execution profile</td></tr>
2906 <td>print command execution profile</td></tr>
2907 <tr><td></td>
2907 <tr><td></td>
2908 <td>--version</td>
2908 <td>--version</td>
2909 <td>output version information and exit</td></tr>
2909 <td>output version information and exit</td></tr>
2910 <tr><td>-h</td>
2910 <tr><td>-h</td>
2911 <td>--help</td>
2911 <td>--help</td>
2912 <td>display help and exit</td></tr>
2912 <td>display help and exit</td></tr>
2913 <tr><td></td>
2913 <tr><td></td>
2914 <td>--hidden</td>
2914 <td>--hidden</td>
2915 <td>consider hidden changesets</td></tr>
2915 <td>consider hidden changesets</td></tr>
2916 <tr><td></td>
2916 <tr><td></td>
2917 <td>--pager TYPE</td>
2917 <td>--pager TYPE</td>
2918 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2918 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2919 </table>
2919 </table>
2920
2920
2921 </div>
2921 </div>
2922 </div>
2922 </div>
2923 </div>
2923 </div>
2924
2924
2925
2925
2926
2926
2927 </body>
2927 </body>
2928 </html>
2928 </html>
2929
2929
2930
2930
2931 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
2931 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
2932 200 Script output follows
2932 200 Script output follows
2933
2933
2934 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2934 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2935 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2935 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2936 <head>
2936 <head>
2937 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2937 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2938 <meta name="robots" content="index, nofollow" />
2938 <meta name="robots" content="index, nofollow" />
2939 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2939 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2940 <script type="text/javascript" src="/static/mercurial.js"></script>
2940 <script type="text/javascript" src="/static/mercurial.js"></script>
2941
2941
2942 <title>Help: dates</title>
2942 <title>Help: dates</title>
2943 </head>
2943 </head>
2944 <body>
2944 <body>
2945
2945
2946 <div class="container">
2946 <div class="container">
2947 <div class="menu">
2947 <div class="menu">
2948 <div class="logo">
2948 <div class="logo">
2949 <a href="https://mercurial-scm.org/">
2949 <a href="https://mercurial-scm.org/">
2950 <img src="/static/hglogo.png" alt="mercurial" /></a>
2950 <img src="/static/hglogo.png" alt="mercurial" /></a>
2951 </div>
2951 </div>
2952 <ul>
2952 <ul>
2953 <li><a href="/shortlog">log</a></li>
2953 <li><a href="/shortlog">log</a></li>
2954 <li><a href="/graph">graph</a></li>
2954 <li><a href="/graph">graph</a></li>
2955 <li><a href="/tags">tags</a></li>
2955 <li><a href="/tags">tags</a></li>
2956 <li><a href="/bookmarks">bookmarks</a></li>
2956 <li><a href="/bookmarks">bookmarks</a></li>
2957 <li><a href="/branches">branches</a></li>
2957 <li><a href="/branches">branches</a></li>
2958 </ul>
2958 </ul>
2959 <ul>
2959 <ul>
2960 <li class="active"><a href="/help">help</a></li>
2960 <li class="active"><a href="/help">help</a></li>
2961 </ul>
2961 </ul>
2962 </div>
2962 </div>
2963
2963
2964 <div class="main">
2964 <div class="main">
2965 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2965 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2966 <h3>Help: dates</h3>
2966 <h3>Help: dates</h3>
2967
2967
2968 <form class="search" action="/log">
2968 <form class="search" action="/log">
2969
2969
2970 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2970 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2971 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2971 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2972 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2972 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2973 </form>
2973 </form>
2974 <div id="doc">
2974 <div id="doc">
2975 <h1>Date Formats</h1>
2975 <h1>Date Formats</h1>
2976 <p>
2976 <p>
2977 Some commands allow the user to specify a date, e.g.:
2977 Some commands allow the user to specify a date, e.g.:
2978 </p>
2978 </p>
2979 <ul>
2979 <ul>
2980 <li> backout, commit, import, tag: Specify the commit date.
2980 <li> backout, commit, import, tag: Specify the commit date.
2981 <li> log, revert, update: Select revision(s) by date.
2981 <li> log, revert, update: Select revision(s) by date.
2982 </ul>
2982 </ul>
2983 <p>
2983 <p>
2984 Many date formats are valid. Here are some examples:
2984 Many date formats are valid. Here are some examples:
2985 </p>
2985 </p>
2986 <ul>
2986 <ul>
2987 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
2987 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
2988 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
2988 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
2989 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
2989 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
2990 <li> &quot;Dec 6&quot; (midnight)
2990 <li> &quot;Dec 6&quot; (midnight)
2991 <li> &quot;13:18&quot; (today assumed)
2991 <li> &quot;13:18&quot; (today assumed)
2992 <li> &quot;3:39&quot; (3:39AM assumed)
2992 <li> &quot;3:39&quot; (3:39AM assumed)
2993 <li> &quot;3:39pm&quot; (15:39)
2993 <li> &quot;3:39pm&quot; (15:39)
2994 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
2994 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
2995 <li> &quot;2006-12-6 13:18&quot;
2995 <li> &quot;2006-12-6 13:18&quot;
2996 <li> &quot;2006-12-6&quot;
2996 <li> &quot;2006-12-6&quot;
2997 <li> &quot;12-6&quot;
2997 <li> &quot;12-6&quot;
2998 <li> &quot;12/6&quot;
2998 <li> &quot;12/6&quot;
2999 <li> &quot;12/6/6&quot; (Dec 6 2006)
2999 <li> &quot;12/6/6&quot; (Dec 6 2006)
3000 <li> &quot;today&quot; (midnight)
3000 <li> &quot;today&quot; (midnight)
3001 <li> &quot;yesterday&quot; (midnight)
3001 <li> &quot;yesterday&quot; (midnight)
3002 <li> &quot;now&quot; - right now
3002 <li> &quot;now&quot; - right now
3003 </ul>
3003 </ul>
3004 <p>
3004 <p>
3005 Lastly, there is Mercurial's internal format:
3005 Lastly, there is Mercurial's internal format:
3006 </p>
3006 </p>
3007 <ul>
3007 <ul>
3008 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3008 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3009 </ul>
3009 </ul>
3010 <p>
3010 <p>
3011 This is the internal representation format for dates. The first number
3011 This is the internal representation format for dates. The first number
3012 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3012 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3013 second is the offset of the local timezone, in seconds west of UTC
3013 second is the offset of the local timezone, in seconds west of UTC
3014 (negative if the timezone is east of UTC).
3014 (negative if the timezone is east of UTC).
3015 </p>
3015 </p>
3016 <p>
3016 <p>
3017 The log command also accepts date ranges:
3017 The log command also accepts date ranges:
3018 </p>
3018 </p>
3019 <ul>
3019 <ul>
3020 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3020 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3021 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3021 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3022 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3022 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3023 <li> &quot;-DAYS&quot; - within a given number of days of today
3023 <li> &quot;-DAYS&quot; - within a given number of days of today
3024 </ul>
3024 </ul>
3025
3025
3026 </div>
3026 </div>
3027 </div>
3027 </div>
3028 </div>
3028 </div>
3029
3029
3030
3030
3031
3031
3032 </body>
3032 </body>
3033 </html>
3033 </html>
3034
3034
3035
3035
3036 Sub-topic indexes rendered properly
3036 Sub-topic indexes rendered properly
3037
3037
3038 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3038 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3039 200 Script output follows
3039 200 Script output follows
3040
3040
3041 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3041 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3042 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3042 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3043 <head>
3043 <head>
3044 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3044 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3045 <meta name="robots" content="index, nofollow" />
3045 <meta name="robots" content="index, nofollow" />
3046 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3046 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3047 <script type="text/javascript" src="/static/mercurial.js"></script>
3047 <script type="text/javascript" src="/static/mercurial.js"></script>
3048
3048
3049 <title>Help: internals</title>
3049 <title>Help: internals</title>
3050 </head>
3050 </head>
3051 <body>
3051 <body>
3052
3052
3053 <div class="container">
3053 <div class="container">
3054 <div class="menu">
3054 <div class="menu">
3055 <div class="logo">
3055 <div class="logo">
3056 <a href="https://mercurial-scm.org/">
3056 <a href="https://mercurial-scm.org/">
3057 <img src="/static/hglogo.png" alt="mercurial" /></a>
3057 <img src="/static/hglogo.png" alt="mercurial" /></a>
3058 </div>
3058 </div>
3059 <ul>
3059 <ul>
3060 <li><a href="/shortlog">log</a></li>
3060 <li><a href="/shortlog">log</a></li>
3061 <li><a href="/graph">graph</a></li>
3061 <li><a href="/graph">graph</a></li>
3062 <li><a href="/tags">tags</a></li>
3062 <li><a href="/tags">tags</a></li>
3063 <li><a href="/bookmarks">bookmarks</a></li>
3063 <li><a href="/bookmarks">bookmarks</a></li>
3064 <li><a href="/branches">branches</a></li>
3064 <li><a href="/branches">branches</a></li>
3065 </ul>
3065 </ul>
3066 <ul>
3066 <ul>
3067 <li><a href="/help">help</a></li>
3067 <li><a href="/help">help</a></li>
3068 </ul>
3068 </ul>
3069 </div>
3069 </div>
3070
3070
3071 <div class="main">
3071 <div class="main">
3072 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3072 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3073
3073
3074 <form class="search" action="/log">
3074 <form class="search" action="/log">
3075
3075
3076 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3076 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3077 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3077 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3078 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3078 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3079 </form>
3079 </form>
3080 <table class="bigtable">
3080 <table class="bigtable">
3081 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3081 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3082
3082
3083 <tr><td>
3083 <tr><td>
3084 <a href="/help/internals.bundle2">
3084 <a href="/help/internals.bundle2">
3085 bundle2
3085 bundle2
3086 </a>
3086 </a>
3087 </td><td>
3087 </td><td>
3088 Bundle2
3088 Bundle2
3089 </td></tr>
3089 </td></tr>
3090 <tr><td>
3090 <tr><td>
3091 <a href="/help/internals.bundles">
3091 <a href="/help/internals.bundles">
3092 bundles
3092 bundles
3093 </a>
3093 </a>
3094 </td><td>
3094 </td><td>
3095 Bundles
3095 Bundles
3096 </td></tr>
3096 </td></tr>
3097 <tr><td>
3097 <tr><td>
3098 <a href="/help/internals.censor">
3098 <a href="/help/internals.censor">
3099 censor
3099 censor
3100 </a>
3100 </a>
3101 </td><td>
3101 </td><td>
3102 Censor
3102 Censor
3103 </td></tr>
3103 </td></tr>
3104 <tr><td>
3104 <tr><td>
3105 <a href="/help/internals.changegroups">
3105 <a href="/help/internals.changegroups">
3106 changegroups
3106 changegroups
3107 </a>
3107 </a>
3108 </td><td>
3108 </td><td>
3109 Changegroups
3109 Changegroups
3110 </td></tr>
3110 </td></tr>
3111 <tr><td>
3111 <tr><td>
3112 <a href="/help/internals.config">
3112 <a href="/help/internals.config">
3113 config
3113 config
3114 </a>
3114 </a>
3115 </td><td>
3115 </td><td>
3116 Config Registrar
3116 Config Registrar
3117 </td></tr>
3117 </td></tr>
3118 <tr><td>
3118 <tr><td>
3119 <a href="/help/internals.requirements">
3119 <a href="/help/internals.requirements">
3120 requirements
3120 requirements
3121 </a>
3121 </a>
3122 </td><td>
3122 </td><td>
3123 Repository Requirements
3123 Repository Requirements
3124 </td></tr>
3124 </td></tr>
3125 <tr><td>
3125 <tr><td>
3126 <a href="/help/internals.revlogs">
3126 <a href="/help/internals.revlogs">
3127 revlogs
3127 revlogs
3128 </a>
3128 </a>
3129 </td><td>
3129 </td><td>
3130 Revision Logs
3130 Revision Logs
3131 </td></tr>
3131 </td></tr>
3132 <tr><td>
3132 <tr><td>
3133 <a href="/help/internals.wireprotocol">
3133 <a href="/help/internals.wireprotocol">
3134 wireprotocol
3134 wireprotocol
3135 </a>
3135 </a>
3136 </td><td>
3136 </td><td>
3137 Wire Protocol
3137 Wire Protocol
3138 </td></tr>
3138 </td></tr>
3139
3139
3140
3140
3141
3141
3142
3142
3143
3143
3144 </table>
3144 </table>
3145 </div>
3145 </div>
3146 </div>
3146 </div>
3147
3147
3148
3148
3149
3149
3150 </body>
3150 </body>
3151 </html>
3151 </html>
3152
3152
3153
3153
3154 Sub-topic topics rendered properly
3154 Sub-topic topics rendered properly
3155
3155
3156 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3156 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3157 200 Script output follows
3157 200 Script output follows
3158
3158
3159 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3159 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3160 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3160 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3161 <head>
3161 <head>
3162 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3162 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3163 <meta name="robots" content="index, nofollow" />
3163 <meta name="robots" content="index, nofollow" />
3164 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3164 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3165 <script type="text/javascript" src="/static/mercurial.js"></script>
3165 <script type="text/javascript" src="/static/mercurial.js"></script>
3166
3166
3167 <title>Help: internals.changegroups</title>
3167 <title>Help: internals.changegroups</title>
3168 </head>
3168 </head>
3169 <body>
3169 <body>
3170
3170
3171 <div class="container">
3171 <div class="container">
3172 <div class="menu">
3172 <div class="menu">
3173 <div class="logo">
3173 <div class="logo">
3174 <a href="https://mercurial-scm.org/">
3174 <a href="https://mercurial-scm.org/">
3175 <img src="/static/hglogo.png" alt="mercurial" /></a>
3175 <img src="/static/hglogo.png" alt="mercurial" /></a>
3176 </div>
3176 </div>
3177 <ul>
3177 <ul>
3178 <li><a href="/shortlog">log</a></li>
3178 <li><a href="/shortlog">log</a></li>
3179 <li><a href="/graph">graph</a></li>
3179 <li><a href="/graph">graph</a></li>
3180 <li><a href="/tags">tags</a></li>
3180 <li><a href="/tags">tags</a></li>
3181 <li><a href="/bookmarks">bookmarks</a></li>
3181 <li><a href="/bookmarks">bookmarks</a></li>
3182 <li><a href="/branches">branches</a></li>
3182 <li><a href="/branches">branches</a></li>
3183 </ul>
3183 </ul>
3184 <ul>
3184 <ul>
3185 <li class="active"><a href="/help">help</a></li>
3185 <li class="active"><a href="/help">help</a></li>
3186 </ul>
3186 </ul>
3187 </div>
3187 </div>
3188
3188
3189 <div class="main">
3189 <div class="main">
3190 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3190 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3191 <h3>Help: internals.changegroups</h3>
3191 <h3>Help: internals.changegroups</h3>
3192
3192
3193 <form class="search" action="/log">
3193 <form class="search" action="/log">
3194
3194
3195 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3195 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3196 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3196 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3197 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3197 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3198 </form>
3198 </form>
3199 <div id="doc">
3199 <div id="doc">
3200 <h1>Changegroups</h1>
3200 <h1>Changegroups</h1>
3201 <p>
3201 <p>
3202 Changegroups are representations of repository revlog data, specifically
3202 Changegroups are representations of repository revlog data, specifically
3203 the changelog data, root/flat manifest data, treemanifest data, and
3203 the changelog data, root/flat manifest data, treemanifest data, and
3204 filelogs.
3204 filelogs.
3205 </p>
3205 </p>
3206 <p>
3206 <p>
3207 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3207 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3208 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3208 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3209 only difference being an additional item in the *delta header*. Version
3209 only difference being an additional item in the *delta header*. Version
3210 &quot;3&quot; adds support for revlog flags in the *delta header* and optionally
3210 &quot;3&quot; adds support for revlog flags in the *delta header* and optionally
3211 exchanging treemanifests (enabled by setting an option on the
3211 exchanging treemanifests (enabled by setting an option on the
3212 &quot;changegroup&quot; part in the bundle2).
3212 &quot;changegroup&quot; part in the bundle2).
3213 </p>
3213 </p>
3214 <p>
3214 <p>
3215 Changegroups when not exchanging treemanifests consist of 3 logical
3215 Changegroups when not exchanging treemanifests consist of 3 logical
3216 segments:
3216 segments:
3217 </p>
3217 </p>
3218 <pre>
3218 <pre>
3219 +---------------------------------+
3219 +---------------------------------+
3220 | | | |
3220 | | | |
3221 | changeset | manifest | filelogs |
3221 | changeset | manifest | filelogs |
3222 | | | |
3222 | | | |
3223 | | | |
3223 | | | |
3224 +---------------------------------+
3224 +---------------------------------+
3225 </pre>
3225 </pre>
3226 <p>
3226 <p>
3227 When exchanging treemanifests, there are 4 logical segments:
3227 When exchanging treemanifests, there are 4 logical segments:
3228 </p>
3228 </p>
3229 <pre>
3229 <pre>
3230 +-------------------------------------------------+
3230 +-------------------------------------------------+
3231 | | | | |
3231 | | | | |
3232 | changeset | root | treemanifests | filelogs |
3232 | changeset | root | treemanifests | filelogs |
3233 | | manifest | | |
3233 | | manifest | | |
3234 | | | | |
3234 | | | | |
3235 +-------------------------------------------------+
3235 +-------------------------------------------------+
3236 </pre>
3236 </pre>
3237 <p>
3237 <p>
3238 The principle building block of each segment is a *chunk*. A *chunk*
3238 The principle building block of each segment is a *chunk*. A *chunk*
3239 is a framed piece of data:
3239 is a framed piece of data:
3240 </p>
3240 </p>
3241 <pre>
3241 <pre>
3242 +---------------------------------------+
3242 +---------------------------------------+
3243 | | |
3243 | | |
3244 | length | data |
3244 | length | data |
3245 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3245 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3246 | | |
3246 | | |
3247 +---------------------------------------+
3247 +---------------------------------------+
3248 </pre>
3248 </pre>
3249 <p>
3249 <p>
3250 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3250 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3251 integer indicating the length of the entire chunk (including the length field
3251 integer indicating the length of the entire chunk (including the length field
3252 itself).
3252 itself).
3253 </p>
3253 </p>
3254 <p>
3254 <p>
3255 There is a special case chunk that has a value of 0 for the length
3255 There is a special case chunk that has a value of 0 for the length
3256 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3256 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3257 </p>
3257 </p>
3258 <h2>Delta Groups</h2>
3258 <h2>Delta Groups</h2>
3259 <p>
3259 <p>
3260 A *delta group* expresses the content of a revlog as a series of deltas,
3260 A *delta group* expresses the content of a revlog as a series of deltas,
3261 or patches against previous revisions.
3261 or patches against previous revisions.
3262 </p>
3262 </p>
3263 <p>
3263 <p>
3264 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3264 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3265 to signal the end of the delta group:
3265 to signal the end of the delta group:
3266 </p>
3266 </p>
3267 <pre>
3267 <pre>
3268 +------------------------------------------------------------------------+
3268 +------------------------------------------------------------------------+
3269 | | | | | |
3269 | | | | | |
3270 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3270 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3271 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3271 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3272 | | | | | |
3272 | | | | | |
3273 +------------------------------------------------------------------------+
3273 +------------------------------------------------------------------------+
3274 </pre>
3274 </pre>
3275 <p>
3275 <p>
3276 Each *chunk*'s data consists of the following:
3276 Each *chunk*'s data consists of the following:
3277 </p>
3277 </p>
3278 <pre>
3278 <pre>
3279 +---------------------------------------+
3279 +---------------------------------------+
3280 | | |
3280 | | |
3281 | delta header | delta data |
3281 | delta header | delta data |
3282 | (various by version) | (various) |
3282 | (various by version) | (various) |
3283 | | |
3283 | | |
3284 +---------------------------------------+
3284 +---------------------------------------+
3285 </pre>
3285 </pre>
3286 <p>
3286 <p>
3287 The *delta data* is a series of *delta*s that describe a diff from an existing
3287 The *delta data* is a series of *delta*s that describe a diff from an existing
3288 entry (either that the recipient already has, or previously specified in the
3288 entry (either that the recipient already has, or previously specified in the
3289 bundle/changegroup).
3289 bundle/changegroup).
3290 </p>
3290 </p>
3291 <p>
3291 <p>
3292 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3292 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3293 &quot;3&quot; of the changegroup format.
3293 &quot;3&quot; of the changegroup format.
3294 </p>
3294 </p>
3295 <p>
3295 <p>
3296 Version 1 (headerlen=80):
3296 Version 1 (headerlen=80):
3297 </p>
3297 </p>
3298 <pre>
3298 <pre>
3299 +------------------------------------------------------+
3299 +------------------------------------------------------+
3300 | | | | |
3300 | | | | |
3301 | node | p1 node | p2 node | link node |
3301 | node | p1 node | p2 node | link node |
3302 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3302 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3303 | | | | |
3303 | | | | |
3304 +------------------------------------------------------+
3304 +------------------------------------------------------+
3305 </pre>
3305 </pre>
3306 <p>
3306 <p>
3307 Version 2 (headerlen=100):
3307 Version 2 (headerlen=100):
3308 </p>
3308 </p>
3309 <pre>
3309 <pre>
3310 +------------------------------------------------------------------+
3310 +------------------------------------------------------------------+
3311 | | | | | |
3311 | | | | | |
3312 | node | p1 node | p2 node | base node | link node |
3312 | node | p1 node | p2 node | base node | link node |
3313 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3313 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3314 | | | | | |
3314 | | | | | |
3315 +------------------------------------------------------------------+
3315 +------------------------------------------------------------------+
3316 </pre>
3316 </pre>
3317 <p>
3317 <p>
3318 Version 3 (headerlen=102):
3318 Version 3 (headerlen=102):
3319 </p>
3319 </p>
3320 <pre>
3320 <pre>
3321 +------------------------------------------------------------------------------+
3321 +------------------------------------------------------------------------------+
3322 | | | | | | |
3322 | | | | | | |
3323 | node | p1 node | p2 node | base node | link node | flags |
3323 | node | p1 node | p2 node | base node | link node | flags |
3324 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3324 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3325 | | | | | | |
3325 | | | | | | |
3326 +------------------------------------------------------------------------------+
3326 +------------------------------------------------------------------------------+
3327 </pre>
3327 </pre>
3328 <p>
3328 <p>
3329 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3329 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3330 series of *delta*s, densely packed (no separators). These deltas describe a diff
3330 series of *delta*s, densely packed (no separators). These deltas describe a diff
3331 from an existing entry (either that the recipient already has, or previously
3331 from an existing entry (either that the recipient already has, or previously
3332 specified in the bundle/changegroup). The format is described more fully in
3332 specified in the bundle/changegroup). The format is described more fully in
3333 &quot;hg help internals.bdiff&quot;, but briefly:
3333 &quot;hg help internals.bdiff&quot;, but briefly:
3334 </p>
3334 </p>
3335 <pre>
3335 <pre>
3336 +---------------------------------------------------------------+
3336 +---------------------------------------------------------------+
3337 | | | | |
3337 | | | | |
3338 | start offset | end offset | new length | content |
3338 | start offset | end offset | new length | content |
3339 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3339 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3340 | | | | |
3340 | | | | |
3341 +---------------------------------------------------------------+
3341 +---------------------------------------------------------------+
3342 </pre>
3342 </pre>
3343 <p>
3343 <p>
3344 Please note that the length field in the delta data does *not* include itself.
3344 Please note that the length field in the delta data does *not* include itself.
3345 </p>
3345 </p>
3346 <p>
3346 <p>
3347 In version 1, the delta is always applied against the previous node from
3347 In version 1, the delta is always applied against the previous node from
3348 the changegroup or the first parent if this is the first entry in the
3348 the changegroup or the first parent if this is the first entry in the
3349 changegroup.
3349 changegroup.
3350 </p>
3350 </p>
3351 <p>
3351 <p>
3352 In version 2 and up, the delta base node is encoded in the entry in the
3352 In version 2 and up, the delta base node is encoded in the entry in the
3353 changegroup. This allows the delta to be expressed against any parent,
3353 changegroup. This allows the delta to be expressed against any parent,
3354 which can result in smaller deltas and more efficient encoding of data.
3354 which can result in smaller deltas and more efficient encoding of data.
3355 </p>
3355 </p>
3356 <h2>Changeset Segment</h2>
3356 <h2>Changeset Segment</h2>
3357 <p>
3357 <p>
3358 The *changeset segment* consists of a single *delta group* holding
3358 The *changeset segment* consists of a single *delta group* holding
3359 changelog data. The *empty chunk* at the end of the *delta group* denotes
3359 changelog data. The *empty chunk* at the end of the *delta group* denotes
3360 the boundary to the *manifest segment*.
3360 the boundary to the *manifest segment*.
3361 </p>
3361 </p>
3362 <h2>Manifest Segment</h2>
3362 <h2>Manifest Segment</h2>
3363 <p>
3363 <p>
3364 The *manifest segment* consists of a single *delta group* holding manifest
3364 The *manifest segment* consists of a single *delta group* holding manifest
3365 data. If treemanifests are in use, it contains only the manifest for the
3365 data. If treemanifests are in use, it contains only the manifest for the
3366 root directory of the repository. Otherwise, it contains the entire
3366 root directory of the repository. Otherwise, it contains the entire
3367 manifest data. The *empty chunk* at the end of the *delta group* denotes
3367 manifest data. The *empty chunk* at the end of the *delta group* denotes
3368 the boundary to the next segment (either the *treemanifests segment* or the
3368 the boundary to the next segment (either the *treemanifests segment* or the
3369 *filelogs segment*, depending on version and the request options).
3369 *filelogs segment*, depending on version and the request options).
3370 </p>
3370 </p>
3371 <h3>Treemanifests Segment</h3>
3371 <h3>Treemanifests Segment</h3>
3372 <p>
3372 <p>
3373 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3373 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3374 only if the 'treemanifest' param is part of the bundle2 changegroup part
3374 only if the 'treemanifest' param is part of the bundle2 changegroup part
3375 (it is not possible to use changegroup version 3 outside of bundle2).
3375 (it is not possible to use changegroup version 3 outside of bundle2).
3376 Aside from the filenames in the *treemanifests segment* containing a
3376 Aside from the filenames in the *treemanifests segment* containing a
3377 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3377 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3378 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3378 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3379 a sub-segment with filename size 0). This denotes the boundary to the
3379 a sub-segment with filename size 0). This denotes the boundary to the
3380 *filelogs segment*.
3380 *filelogs segment*.
3381 </p>
3381 </p>
3382 <h2>Filelogs Segment</h2>
3382 <h2>Filelogs Segment</h2>
3383 <p>
3383 <p>
3384 The *filelogs segment* consists of multiple sub-segments, each
3384 The *filelogs segment* consists of multiple sub-segments, each
3385 corresponding to an individual file whose data is being described:
3385 corresponding to an individual file whose data is being described:
3386 </p>
3386 </p>
3387 <pre>
3387 <pre>
3388 +--------------------------------------------------+
3388 +--------------------------------------------------+
3389 | | | | | |
3389 | | | | | |
3390 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3390 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3391 | | | | | (4 bytes) |
3391 | | | | | (4 bytes) |
3392 | | | | | |
3392 | | | | | |
3393 +--------------------------------------------------+
3393 +--------------------------------------------------+
3394 </pre>
3394 </pre>
3395 <p>
3395 <p>
3396 The final filelog sub-segment is followed by an *empty chunk* (logically,
3396 The final filelog sub-segment is followed by an *empty chunk* (logically,
3397 a sub-segment with filename size 0). This denotes the end of the segment
3397 a sub-segment with filename size 0). This denotes the end of the segment
3398 and of the overall changegroup.
3398 and of the overall changegroup.
3399 </p>
3399 </p>
3400 <p>
3400 <p>
3401 Each filelog sub-segment consists of the following:
3401 Each filelog sub-segment consists of the following:
3402 </p>
3402 </p>
3403 <pre>
3403 <pre>
3404 +------------------------------------------------------+
3404 +------------------------------------------------------+
3405 | | | |
3405 | | | |
3406 | filename length | filename | delta group |
3406 | filename length | filename | delta group |
3407 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3407 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3408 | | | |
3408 | | | |
3409 +------------------------------------------------------+
3409 +------------------------------------------------------+
3410 </pre>
3410 </pre>
3411 <p>
3411 <p>
3412 That is, a *chunk* consisting of the filename (not terminated or padded)
3412 That is, a *chunk* consisting of the filename (not terminated or padded)
3413 followed by N chunks constituting the *delta group* for this file. The
3413 followed by N chunks constituting the *delta group* for this file. The
3414 *empty chunk* at the end of each *delta group* denotes the boundary to the
3414 *empty chunk* at the end of each *delta group* denotes the boundary to the
3415 next filelog sub-segment.
3415 next filelog sub-segment.
3416 </p>
3416 </p>
3417
3417
3418 </div>
3418 </div>
3419 </div>
3419 </div>
3420 </div>
3420 </div>
3421
3421
3422
3422
3423
3423
3424 </body>
3424 </body>
3425 </html>
3425 </html>
3426
3426
3427
3427
3428 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3428 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3429 404 Not Found
3429 404 Not Found
3430
3430
3431 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3431 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3432 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3432 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3433 <head>
3433 <head>
3434 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3434 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3435 <meta name="robots" content="index, nofollow" />
3435 <meta name="robots" content="index, nofollow" />
3436 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3436 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3437 <script type="text/javascript" src="/static/mercurial.js"></script>
3437 <script type="text/javascript" src="/static/mercurial.js"></script>
3438
3438
3439 <title>test: error</title>
3439 <title>test: error</title>
3440 </head>
3440 </head>
3441 <body>
3441 <body>
3442
3442
3443 <div class="container">
3443 <div class="container">
3444 <div class="menu">
3444 <div class="menu">
3445 <div class="logo">
3445 <div class="logo">
3446 <a href="https://mercurial-scm.org/">
3446 <a href="https://mercurial-scm.org/">
3447 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3447 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3448 </div>
3448 </div>
3449 <ul>
3449 <ul>
3450 <li><a href="/shortlog">log</a></li>
3450 <li><a href="/shortlog">log</a></li>
3451 <li><a href="/graph">graph</a></li>
3451 <li><a href="/graph">graph</a></li>
3452 <li><a href="/tags">tags</a></li>
3452 <li><a href="/tags">tags</a></li>
3453 <li><a href="/bookmarks">bookmarks</a></li>
3453 <li><a href="/bookmarks">bookmarks</a></li>
3454 <li><a href="/branches">branches</a></li>
3454 <li><a href="/branches">branches</a></li>
3455 </ul>
3455 </ul>
3456 <ul>
3456 <ul>
3457 <li><a href="/help">help</a></li>
3457 <li><a href="/help">help</a></li>
3458 </ul>
3458 </ul>
3459 </div>
3459 </div>
3460
3460
3461 <div class="main">
3461 <div class="main">
3462
3462
3463 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3463 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3464 <h3>error</h3>
3464 <h3>error</h3>
3465
3465
3466
3466
3467 <form class="search" action="/log">
3467 <form class="search" action="/log">
3468
3468
3469 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3469 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3470 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3470 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3471 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3471 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3472 </form>
3472 </form>
3473
3473
3474 <div class="description">
3474 <div class="description">
3475 <p>
3475 <p>
3476 An error occurred while processing your request:
3476 An error occurred while processing your request:
3477 </p>
3477 </p>
3478 <p>
3478 <p>
3479 Not Found
3479 Not Found
3480 </p>
3480 </p>
3481 </div>
3481 </div>
3482 </div>
3482 </div>
3483 </div>
3483 </div>
3484
3484
3485
3485
3486
3486
3487 </body>
3487 </body>
3488 </html>
3488 </html>
3489
3489
3490 [1]
3490 [1]
3491
3491
3492 $ killdaemons.py
3492 $ killdaemons.py
3493
3493
3494 #endif
3494 #endif
General Comments 0
You need to be logged in to leave comments. Login now