##// END OF EJS Templates
formatter: remove experimental marker from -T option...
Yuya Nishihara -
r39967:0d703063 default
parent child Browse files
Show More
@@ -1,3313 +1,3312 b''
1 # cmdutil.py - help for command processing in mercurial
1 # cmdutil.py - help for command processing in 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 errno
10 import errno
11 import os
11 import os
12 import re
12 import re
13
13
14 from .i18n import _
14 from .i18n import _
15 from .node import (
15 from .node import (
16 hex,
16 hex,
17 nullid,
17 nullid,
18 nullrev,
18 nullrev,
19 short,
19 short,
20 )
20 )
21
21
22 from . import (
22 from . import (
23 bookmarks,
23 bookmarks,
24 changelog,
24 changelog,
25 copies,
25 copies,
26 crecord as crecordmod,
26 crecord as crecordmod,
27 dirstateguard,
27 dirstateguard,
28 encoding,
28 encoding,
29 error,
29 error,
30 formatter,
30 formatter,
31 logcmdutil,
31 logcmdutil,
32 match as matchmod,
32 match as matchmod,
33 merge as mergemod,
33 merge as mergemod,
34 mergeutil,
34 mergeutil,
35 obsolete,
35 obsolete,
36 patch,
36 patch,
37 pathutil,
37 pathutil,
38 phases,
38 phases,
39 pycompat,
39 pycompat,
40 revlog,
40 revlog,
41 rewriteutil,
41 rewriteutil,
42 scmutil,
42 scmutil,
43 smartset,
43 smartset,
44 subrepoutil,
44 subrepoutil,
45 templatekw,
45 templatekw,
46 templater,
46 templater,
47 util,
47 util,
48 vfs as vfsmod,
48 vfs as vfsmod,
49 )
49 )
50
50
51 from .utils import (
51 from .utils import (
52 dateutil,
52 dateutil,
53 stringutil,
53 stringutil,
54 )
54 )
55
55
56 stringio = util.stringio
56 stringio = util.stringio
57
57
58 # templates of common command options
58 # templates of common command options
59
59
60 dryrunopts = [
60 dryrunopts = [
61 ('n', 'dry-run', None,
61 ('n', 'dry-run', None,
62 _('do not perform actions, just print output')),
62 _('do not perform actions, just print output')),
63 ]
63 ]
64
64
65 confirmopts = [
65 confirmopts = [
66 ('', 'confirm', None,
66 ('', 'confirm', None,
67 _('ask before applying actions')),
67 _('ask before applying actions')),
68 ]
68 ]
69
69
70 remoteopts = [
70 remoteopts = [
71 ('e', 'ssh', '',
71 ('e', 'ssh', '',
72 _('specify ssh command to use'), _('CMD')),
72 _('specify ssh command to use'), _('CMD')),
73 ('', 'remotecmd', '',
73 ('', 'remotecmd', '',
74 _('specify hg command to run on the remote side'), _('CMD')),
74 _('specify hg command to run on the remote side'), _('CMD')),
75 ('', 'insecure', None,
75 ('', 'insecure', None,
76 _('do not verify server certificate (ignoring web.cacerts config)')),
76 _('do not verify server certificate (ignoring web.cacerts config)')),
77 ]
77 ]
78
78
79 walkopts = [
79 walkopts = [
80 ('I', 'include', [],
80 ('I', 'include', [],
81 _('include names matching the given patterns'), _('PATTERN')),
81 _('include names matching the given patterns'), _('PATTERN')),
82 ('X', 'exclude', [],
82 ('X', 'exclude', [],
83 _('exclude names matching the given patterns'), _('PATTERN')),
83 _('exclude names matching the given patterns'), _('PATTERN')),
84 ]
84 ]
85
85
86 commitopts = [
86 commitopts = [
87 ('m', 'message', '',
87 ('m', 'message', '',
88 _('use text as commit message'), _('TEXT')),
88 _('use text as commit message'), _('TEXT')),
89 ('l', 'logfile', '',
89 ('l', 'logfile', '',
90 _('read commit message from file'), _('FILE')),
90 _('read commit message from file'), _('FILE')),
91 ]
91 ]
92
92
93 commitopts2 = [
93 commitopts2 = [
94 ('d', 'date', '',
94 ('d', 'date', '',
95 _('record the specified date as commit date'), _('DATE')),
95 _('record the specified date as commit date'), _('DATE')),
96 ('u', 'user', '',
96 ('u', 'user', '',
97 _('record the specified user as committer'), _('USER')),
97 _('record the specified user as committer'), _('USER')),
98 ]
98 ]
99
99
100 # hidden for now
101 formatteropts = [
100 formatteropts = [
102 ('T', 'template', '',
101 ('T', 'template', '',
103 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
102 _('display with template'), _('TEMPLATE')),
104 ]
103 ]
105
104
106 templateopts = [
105 templateopts = [
107 ('', 'style', '',
106 ('', 'style', '',
108 _('display using template map file (DEPRECATED)'), _('STYLE')),
107 _('display using template map file (DEPRECATED)'), _('STYLE')),
109 ('T', 'template', '',
108 ('T', 'template', '',
110 _('display with template'), _('TEMPLATE')),
109 _('display with template'), _('TEMPLATE')),
111 ]
110 ]
112
111
113 logopts = [
112 logopts = [
114 ('p', 'patch', None, _('show patch')),
113 ('p', 'patch', None, _('show patch')),
115 ('g', 'git', None, _('use git extended diff format')),
114 ('g', 'git', None, _('use git extended diff format')),
116 ('l', 'limit', '',
115 ('l', 'limit', '',
117 _('limit number of changes displayed'), _('NUM')),
116 _('limit number of changes displayed'), _('NUM')),
118 ('M', 'no-merges', None, _('do not show merges')),
117 ('M', 'no-merges', None, _('do not show merges')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
118 ('', 'stat', None, _('output diffstat-style summary of changes')),
120 ('G', 'graph', None, _("show the revision DAG")),
119 ('G', 'graph', None, _("show the revision DAG")),
121 ] + templateopts
120 ] + templateopts
122
121
123 diffopts = [
122 diffopts = [
124 ('a', 'text', None, _('treat all files as text')),
123 ('a', 'text', None, _('treat all files as text')),
125 ('g', 'git', None, _('use git extended diff format')),
124 ('g', 'git', None, _('use git extended diff format')),
126 ('', 'binary', None, _('generate binary diffs in git mode (default)')),
125 ('', 'binary', None, _('generate binary diffs in git mode (default)')),
127 ('', 'nodates', None, _('omit dates from diff headers'))
126 ('', 'nodates', None, _('omit dates from diff headers'))
128 ]
127 ]
129
128
130 diffwsopts = [
129 diffwsopts = [
131 ('w', 'ignore-all-space', None,
130 ('w', 'ignore-all-space', None,
132 _('ignore white space when comparing lines')),
131 _('ignore white space when comparing lines')),
133 ('b', 'ignore-space-change', None,
132 ('b', 'ignore-space-change', None,
134 _('ignore changes in the amount of white space')),
133 _('ignore changes in the amount of white space')),
135 ('B', 'ignore-blank-lines', None,
134 ('B', 'ignore-blank-lines', None,
136 _('ignore changes whose lines are all blank')),
135 _('ignore changes whose lines are all blank')),
137 ('Z', 'ignore-space-at-eol', None,
136 ('Z', 'ignore-space-at-eol', None,
138 _('ignore changes in whitespace at EOL')),
137 _('ignore changes in whitespace at EOL')),
139 ]
138 ]
140
139
141 diffopts2 = [
140 diffopts2 = [
142 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
141 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
143 ('p', 'show-function', None, _('show which function each change is in')),
142 ('p', 'show-function', None, _('show which function each change is in')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
143 ('', 'reverse', None, _('produce a diff that undoes the changes')),
145 ] + diffwsopts + [
144 ] + diffwsopts + [
146 ('U', 'unified', '',
145 ('U', 'unified', '',
147 _('number of lines of context to show'), _('NUM')),
146 _('number of lines of context to show'), _('NUM')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
147 ('', 'stat', None, _('output diffstat-style summary of changes')),
149 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
148 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
150 ]
149 ]
151
150
152 mergetoolopts = [
151 mergetoolopts = [
153 ('t', 'tool', '', _('specify merge tool')),
152 ('t', 'tool', '', _('specify merge tool')),
154 ]
153 ]
155
154
156 similarityopts = [
155 similarityopts = [
157 ('s', 'similarity', '',
156 ('s', 'similarity', '',
158 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
159 ]
158 ]
160
159
161 subrepoopts = [
160 subrepoopts = [
162 ('S', 'subrepos', None,
161 ('S', 'subrepos', None,
163 _('recurse into subrepositories'))
162 _('recurse into subrepositories'))
164 ]
163 ]
165
164
166 debugrevlogopts = [
165 debugrevlogopts = [
167 ('c', 'changelog', False, _('open changelog')),
166 ('c', 'changelog', False, _('open changelog')),
168 ('m', 'manifest', False, _('open manifest')),
167 ('m', 'manifest', False, _('open manifest')),
169 ('', 'dir', '', _('open directory manifest')),
168 ('', 'dir', '', _('open directory manifest')),
170 ]
169 ]
171
170
172 # special string such that everything below this line will be ingored in the
171 # special string such that everything below this line will be ingored in the
173 # editor text
172 # editor text
174 _linebelow = "^HG: ------------------------ >8 ------------------------$"
173 _linebelow = "^HG: ------------------------ >8 ------------------------$"
175
174
176 def ishunk(x):
175 def ishunk(x):
177 hunkclasses = (crecordmod.uihunk, patch.recordhunk)
176 hunkclasses = (crecordmod.uihunk, patch.recordhunk)
178 return isinstance(x, hunkclasses)
177 return isinstance(x, hunkclasses)
179
178
180 def newandmodified(chunks, originalchunks):
179 def newandmodified(chunks, originalchunks):
181 newlyaddedandmodifiedfiles = set()
180 newlyaddedandmodifiedfiles = set()
182 for chunk in chunks:
181 for chunk in chunks:
183 if ishunk(chunk) and chunk.header.isnewfile() and chunk not in \
182 if ishunk(chunk) and chunk.header.isnewfile() and chunk not in \
184 originalchunks:
183 originalchunks:
185 newlyaddedandmodifiedfiles.add(chunk.header.filename())
184 newlyaddedandmodifiedfiles.add(chunk.header.filename())
186 return newlyaddedandmodifiedfiles
185 return newlyaddedandmodifiedfiles
187
186
188 def parsealiases(cmd):
187 def parsealiases(cmd):
189 return cmd.lstrip("^").split("|")
188 return cmd.lstrip("^").split("|")
190
189
191 def setupwrapcolorwrite(ui):
190 def setupwrapcolorwrite(ui):
192 # wrap ui.write so diff output can be labeled/colorized
191 # wrap ui.write so diff output can be labeled/colorized
193 def wrapwrite(orig, *args, **kw):
192 def wrapwrite(orig, *args, **kw):
194 label = kw.pop(r'label', '')
193 label = kw.pop(r'label', '')
195 for chunk, l in patch.difflabel(lambda: args):
194 for chunk, l in patch.difflabel(lambda: args):
196 orig(chunk, label=label + l)
195 orig(chunk, label=label + l)
197
196
198 oldwrite = ui.write
197 oldwrite = ui.write
199 def wrap(*args, **kwargs):
198 def wrap(*args, **kwargs):
200 return wrapwrite(oldwrite, *args, **kwargs)
199 return wrapwrite(oldwrite, *args, **kwargs)
201 setattr(ui, 'write', wrap)
200 setattr(ui, 'write', wrap)
202 return oldwrite
201 return oldwrite
203
202
204 def filterchunks(ui, originalhunks, usecurses, testfile, operation=None):
203 def filterchunks(ui, originalhunks, usecurses, testfile, operation=None):
205 try:
204 try:
206 if usecurses:
205 if usecurses:
207 if testfile:
206 if testfile:
208 recordfn = crecordmod.testdecorator(
207 recordfn = crecordmod.testdecorator(
209 testfile, crecordmod.testchunkselector)
208 testfile, crecordmod.testchunkselector)
210 else:
209 else:
211 recordfn = crecordmod.chunkselector
210 recordfn = crecordmod.chunkselector
212
211
213 return crecordmod.filterpatch(ui, originalhunks, recordfn,
212 return crecordmod.filterpatch(ui, originalhunks, recordfn,
214 operation)
213 operation)
215 except crecordmod.fallbackerror as e:
214 except crecordmod.fallbackerror as e:
216 ui.warn('%s\n' % e.message)
215 ui.warn('%s\n' % e.message)
217 ui.warn(_('falling back to text mode\n'))
216 ui.warn(_('falling back to text mode\n'))
218
217
219 return patch.filterpatch(ui, originalhunks, operation)
218 return patch.filterpatch(ui, originalhunks, operation)
220
219
221 def recordfilter(ui, originalhunks, operation=None):
220 def recordfilter(ui, originalhunks, operation=None):
222 """ Prompts the user to filter the originalhunks and return a list of
221 """ Prompts the user to filter the originalhunks and return a list of
223 selected hunks.
222 selected hunks.
224 *operation* is used for to build ui messages to indicate the user what
223 *operation* is used for to build ui messages to indicate the user what
225 kind of filtering they are doing: reverting, committing, shelving, etc.
224 kind of filtering they are doing: reverting, committing, shelving, etc.
226 (see patch.filterpatch).
225 (see patch.filterpatch).
227 """
226 """
228 usecurses = crecordmod.checkcurses(ui)
227 usecurses = crecordmod.checkcurses(ui)
229 testfile = ui.config('experimental', 'crecordtest')
228 testfile = ui.config('experimental', 'crecordtest')
230 oldwrite = setupwrapcolorwrite(ui)
229 oldwrite = setupwrapcolorwrite(ui)
231 try:
230 try:
232 newchunks, newopts = filterchunks(ui, originalhunks, usecurses,
231 newchunks, newopts = filterchunks(ui, originalhunks, usecurses,
233 testfile, operation)
232 testfile, operation)
234 finally:
233 finally:
235 ui.write = oldwrite
234 ui.write = oldwrite
236 return newchunks, newopts
235 return newchunks, newopts
237
236
238 def dorecord(ui, repo, commitfunc, cmdsuggest, backupall,
237 def dorecord(ui, repo, commitfunc, cmdsuggest, backupall,
239 filterfn, *pats, **opts):
238 filterfn, *pats, **opts):
240 opts = pycompat.byteskwargs(opts)
239 opts = pycompat.byteskwargs(opts)
241 if not ui.interactive():
240 if not ui.interactive():
242 if cmdsuggest:
241 if cmdsuggest:
243 msg = _('running non-interactively, use %s instead') % cmdsuggest
242 msg = _('running non-interactively, use %s instead') % cmdsuggest
244 else:
243 else:
245 msg = _('running non-interactively')
244 msg = _('running non-interactively')
246 raise error.Abort(msg)
245 raise error.Abort(msg)
247
246
248 # make sure username is set before going interactive
247 # make sure username is set before going interactive
249 if not opts.get('user'):
248 if not opts.get('user'):
250 ui.username() # raise exception, username not provided
249 ui.username() # raise exception, username not provided
251
250
252 def recordfunc(ui, repo, message, match, opts):
251 def recordfunc(ui, repo, message, match, opts):
253 """This is generic record driver.
252 """This is generic record driver.
254
253
255 Its job is to interactively filter local changes, and
254 Its job is to interactively filter local changes, and
256 accordingly prepare working directory into a state in which the
255 accordingly prepare working directory into a state in which the
257 job can be delegated to a non-interactive commit command such as
256 job can be delegated to a non-interactive commit command such as
258 'commit' or 'qrefresh'.
257 'commit' or 'qrefresh'.
259
258
260 After the actual job is done by non-interactive command, the
259 After the actual job is done by non-interactive command, the
261 working directory is restored to its original state.
260 working directory is restored to its original state.
262
261
263 In the end we'll record interesting changes, and everything else
262 In the end we'll record interesting changes, and everything else
264 will be left in place, so the user can continue working.
263 will be left in place, so the user can continue working.
265 """
264 """
266
265
267 checkunfinished(repo, commit=True)
266 checkunfinished(repo, commit=True)
268 wctx = repo[None]
267 wctx = repo[None]
269 merge = len(wctx.parents()) > 1
268 merge = len(wctx.parents()) > 1
270 if merge:
269 if merge:
271 raise error.Abort(_('cannot partially commit a merge '
270 raise error.Abort(_('cannot partially commit a merge '
272 '(use "hg commit" instead)'))
271 '(use "hg commit" instead)'))
273
272
274 def fail(f, msg):
273 def fail(f, msg):
275 raise error.Abort('%s: %s' % (f, msg))
274 raise error.Abort('%s: %s' % (f, msg))
276
275
277 force = opts.get('force')
276 force = opts.get('force')
278 if not force:
277 if not force:
279 vdirs = []
278 vdirs = []
280 match.explicitdir = vdirs.append
279 match.explicitdir = vdirs.append
281 match.bad = fail
280 match.bad = fail
282
281
283 status = repo.status(match=match)
282 status = repo.status(match=match)
284 if not force:
283 if not force:
285 repo.checkcommitpatterns(wctx, vdirs, match, status, fail)
284 repo.checkcommitpatterns(wctx, vdirs, match, status, fail)
286 diffopts = patch.difffeatureopts(ui, opts=opts, whitespace=True)
285 diffopts = patch.difffeatureopts(ui, opts=opts, whitespace=True)
287 diffopts.nodates = True
286 diffopts.nodates = True
288 diffopts.git = True
287 diffopts.git = True
289 diffopts.showfunc = True
288 diffopts.showfunc = True
290 originaldiff = patch.diff(repo, changes=status, opts=diffopts)
289 originaldiff = patch.diff(repo, changes=status, opts=diffopts)
291 originalchunks = patch.parsepatch(originaldiff)
290 originalchunks = patch.parsepatch(originaldiff)
292
291
293 # 1. filter patch, since we are intending to apply subset of it
292 # 1. filter patch, since we are intending to apply subset of it
294 try:
293 try:
295 chunks, newopts = filterfn(ui, originalchunks)
294 chunks, newopts = filterfn(ui, originalchunks)
296 except error.PatchError as err:
295 except error.PatchError as err:
297 raise error.Abort(_('error parsing patch: %s') % err)
296 raise error.Abort(_('error parsing patch: %s') % err)
298 opts.update(newopts)
297 opts.update(newopts)
299
298
300 # We need to keep a backup of files that have been newly added and
299 # We need to keep a backup of files that have been newly added and
301 # modified during the recording process because there is a previous
300 # modified during the recording process because there is a previous
302 # version without the edit in the workdir
301 # version without the edit in the workdir
303 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
302 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
304 contenders = set()
303 contenders = set()
305 for h in chunks:
304 for h in chunks:
306 try:
305 try:
307 contenders.update(set(h.files()))
306 contenders.update(set(h.files()))
308 except AttributeError:
307 except AttributeError:
309 pass
308 pass
310
309
311 changed = status.modified + status.added + status.removed
310 changed = status.modified + status.added + status.removed
312 newfiles = [f for f in changed if f in contenders]
311 newfiles = [f for f in changed if f in contenders]
313 if not newfiles:
312 if not newfiles:
314 ui.status(_('no changes to record\n'))
313 ui.status(_('no changes to record\n'))
315 return 0
314 return 0
316
315
317 modified = set(status.modified)
316 modified = set(status.modified)
318
317
319 # 2. backup changed files, so we can restore them in the end
318 # 2. backup changed files, so we can restore them in the end
320
319
321 if backupall:
320 if backupall:
322 tobackup = changed
321 tobackup = changed
323 else:
322 else:
324 tobackup = [f for f in newfiles if f in modified or f in \
323 tobackup = [f for f in newfiles if f in modified or f in \
325 newlyaddedandmodifiedfiles]
324 newlyaddedandmodifiedfiles]
326 backups = {}
325 backups = {}
327 if tobackup:
326 if tobackup:
328 backupdir = repo.vfs.join('record-backups')
327 backupdir = repo.vfs.join('record-backups')
329 try:
328 try:
330 os.mkdir(backupdir)
329 os.mkdir(backupdir)
331 except OSError as err:
330 except OSError as err:
332 if err.errno != errno.EEXIST:
331 if err.errno != errno.EEXIST:
333 raise
332 raise
334 try:
333 try:
335 # backup continues
334 # backup continues
336 for f in tobackup:
335 for f in tobackup:
337 fd, tmpname = pycompat.mkstemp(prefix=f.replace('/', '_') + '.',
336 fd, tmpname = pycompat.mkstemp(prefix=f.replace('/', '_') + '.',
338 dir=backupdir)
337 dir=backupdir)
339 os.close(fd)
338 os.close(fd)
340 ui.debug('backup %r as %r\n' % (f, tmpname))
339 ui.debug('backup %r as %r\n' % (f, tmpname))
341 util.copyfile(repo.wjoin(f), tmpname, copystat=True)
340 util.copyfile(repo.wjoin(f), tmpname, copystat=True)
342 backups[f] = tmpname
341 backups[f] = tmpname
343
342
344 fp = stringio()
343 fp = stringio()
345 for c in chunks:
344 for c in chunks:
346 fname = c.filename()
345 fname = c.filename()
347 if fname in backups:
346 if fname in backups:
348 c.write(fp)
347 c.write(fp)
349 dopatch = fp.tell()
348 dopatch = fp.tell()
350 fp.seek(0)
349 fp.seek(0)
351
350
352 # 2.5 optionally review / modify patch in text editor
351 # 2.5 optionally review / modify patch in text editor
353 if opts.get('review', False):
352 if opts.get('review', False):
354 patchtext = (crecordmod.diffhelptext
353 patchtext = (crecordmod.diffhelptext
355 + crecordmod.patchhelptext
354 + crecordmod.patchhelptext
356 + fp.read())
355 + fp.read())
357 reviewedpatch = ui.edit(patchtext, "",
356 reviewedpatch = ui.edit(patchtext, "",
358 action="diff",
357 action="diff",
359 repopath=repo.path)
358 repopath=repo.path)
360 fp.truncate(0)
359 fp.truncate(0)
361 fp.write(reviewedpatch)
360 fp.write(reviewedpatch)
362 fp.seek(0)
361 fp.seek(0)
363
362
364 [os.unlink(repo.wjoin(c)) for c in newlyaddedandmodifiedfiles]
363 [os.unlink(repo.wjoin(c)) for c in newlyaddedandmodifiedfiles]
365 # 3a. apply filtered patch to clean repo (clean)
364 # 3a. apply filtered patch to clean repo (clean)
366 if backups:
365 if backups:
367 # Equivalent to hg.revert
366 # Equivalent to hg.revert
368 m = scmutil.matchfiles(repo, backups.keys())
367 m = scmutil.matchfiles(repo, backups.keys())
369 mergemod.update(repo, repo.dirstate.p1(),
368 mergemod.update(repo, repo.dirstate.p1(),
370 False, True, matcher=m)
369 False, True, matcher=m)
371
370
372 # 3b. (apply)
371 # 3b. (apply)
373 if dopatch:
372 if dopatch:
374 try:
373 try:
375 ui.debug('applying patch\n')
374 ui.debug('applying patch\n')
376 ui.debug(fp.getvalue())
375 ui.debug(fp.getvalue())
377 patch.internalpatch(ui, repo, fp, 1, eolmode=None)
376 patch.internalpatch(ui, repo, fp, 1, eolmode=None)
378 except error.PatchError as err:
377 except error.PatchError as err:
379 raise error.Abort(pycompat.bytestr(err))
378 raise error.Abort(pycompat.bytestr(err))
380 del fp
379 del fp
381
380
382 # 4. We prepared working directory according to filtered
381 # 4. We prepared working directory according to filtered
383 # patch. Now is the time to delegate the job to
382 # patch. Now is the time to delegate the job to
384 # commit/qrefresh or the like!
383 # commit/qrefresh or the like!
385
384
386 # Make all of the pathnames absolute.
385 # Make all of the pathnames absolute.
387 newfiles = [repo.wjoin(nf) for nf in newfiles]
386 newfiles = [repo.wjoin(nf) for nf in newfiles]
388 return commitfunc(ui, repo, *newfiles, **pycompat.strkwargs(opts))
387 return commitfunc(ui, repo, *newfiles, **pycompat.strkwargs(opts))
389 finally:
388 finally:
390 # 5. finally restore backed-up files
389 # 5. finally restore backed-up files
391 try:
390 try:
392 dirstate = repo.dirstate
391 dirstate = repo.dirstate
393 for realname, tmpname in backups.iteritems():
392 for realname, tmpname in backups.iteritems():
394 ui.debug('restoring %r to %r\n' % (tmpname, realname))
393 ui.debug('restoring %r to %r\n' % (tmpname, realname))
395
394
396 if dirstate[realname] == 'n':
395 if dirstate[realname] == 'n':
397 # without normallookup, restoring timestamp
396 # without normallookup, restoring timestamp
398 # may cause partially committed files
397 # may cause partially committed files
399 # to be treated as unmodified
398 # to be treated as unmodified
400 dirstate.normallookup(realname)
399 dirstate.normallookup(realname)
401
400
402 # copystat=True here and above are a hack to trick any
401 # copystat=True here and above are a hack to trick any
403 # editors that have f open that we haven't modified them.
402 # editors that have f open that we haven't modified them.
404 #
403 #
405 # Also note that this racy as an editor could notice the
404 # Also note that this racy as an editor could notice the
406 # file's mtime before we've finished writing it.
405 # file's mtime before we've finished writing it.
407 util.copyfile(tmpname, repo.wjoin(realname), copystat=True)
406 util.copyfile(tmpname, repo.wjoin(realname), copystat=True)
408 os.unlink(tmpname)
407 os.unlink(tmpname)
409 if tobackup:
408 if tobackup:
410 os.rmdir(backupdir)
409 os.rmdir(backupdir)
411 except OSError:
410 except OSError:
412 pass
411 pass
413
412
414 def recordinwlock(ui, repo, message, match, opts):
413 def recordinwlock(ui, repo, message, match, opts):
415 with repo.wlock():
414 with repo.wlock():
416 return recordfunc(ui, repo, message, match, opts)
415 return recordfunc(ui, repo, message, match, opts)
417
416
418 return commit(ui, repo, recordinwlock, pats, opts)
417 return commit(ui, repo, recordinwlock, pats, opts)
419
418
420 class dirnode(object):
419 class dirnode(object):
421 """
420 """
422 Represent a directory in user working copy with information required for
421 Represent a directory in user working copy with information required for
423 the purpose of tersing its status.
422 the purpose of tersing its status.
424
423
425 path is the path to the directory, without a trailing '/'
424 path is the path to the directory, without a trailing '/'
426
425
427 statuses is a set of statuses of all files in this directory (this includes
426 statuses is a set of statuses of all files in this directory (this includes
428 all the files in all the subdirectories too)
427 all the files in all the subdirectories too)
429
428
430 files is a list of files which are direct child of this directory
429 files is a list of files which are direct child of this directory
431
430
432 subdirs is a dictionary of sub-directory name as the key and it's own
431 subdirs is a dictionary of sub-directory name as the key and it's own
433 dirnode object as the value
432 dirnode object as the value
434 """
433 """
435
434
436 def __init__(self, dirpath):
435 def __init__(self, dirpath):
437 self.path = dirpath
436 self.path = dirpath
438 self.statuses = set([])
437 self.statuses = set([])
439 self.files = []
438 self.files = []
440 self.subdirs = {}
439 self.subdirs = {}
441
440
442 def _addfileindir(self, filename, status):
441 def _addfileindir(self, filename, status):
443 """Add a file in this directory as a direct child."""
442 """Add a file in this directory as a direct child."""
444 self.files.append((filename, status))
443 self.files.append((filename, status))
445
444
446 def addfile(self, filename, status):
445 def addfile(self, filename, status):
447 """
446 """
448 Add a file to this directory or to its direct parent directory.
447 Add a file to this directory or to its direct parent directory.
449
448
450 If the file is not direct child of this directory, we traverse to the
449 If the file is not direct child of this directory, we traverse to the
451 directory of which this file is a direct child of and add the file
450 directory of which this file is a direct child of and add the file
452 there.
451 there.
453 """
452 """
454
453
455 # the filename contains a path separator, it means it's not the direct
454 # the filename contains a path separator, it means it's not the direct
456 # child of this directory
455 # child of this directory
457 if '/' in filename:
456 if '/' in filename:
458 subdir, filep = filename.split('/', 1)
457 subdir, filep = filename.split('/', 1)
459
458
460 # does the dirnode object for subdir exists
459 # does the dirnode object for subdir exists
461 if subdir not in self.subdirs:
460 if subdir not in self.subdirs:
462 subdirpath = pathutil.join(self.path, subdir)
461 subdirpath = pathutil.join(self.path, subdir)
463 self.subdirs[subdir] = dirnode(subdirpath)
462 self.subdirs[subdir] = dirnode(subdirpath)
464
463
465 # try adding the file in subdir
464 # try adding the file in subdir
466 self.subdirs[subdir].addfile(filep, status)
465 self.subdirs[subdir].addfile(filep, status)
467
466
468 else:
467 else:
469 self._addfileindir(filename, status)
468 self._addfileindir(filename, status)
470
469
471 if status not in self.statuses:
470 if status not in self.statuses:
472 self.statuses.add(status)
471 self.statuses.add(status)
473
472
474 def iterfilepaths(self):
473 def iterfilepaths(self):
475 """Yield (status, path) for files directly under this directory."""
474 """Yield (status, path) for files directly under this directory."""
476 for f, st in self.files:
475 for f, st in self.files:
477 yield st, pathutil.join(self.path, f)
476 yield st, pathutil.join(self.path, f)
478
477
479 def tersewalk(self, terseargs):
478 def tersewalk(self, terseargs):
480 """
479 """
481 Yield (status, path) obtained by processing the status of this
480 Yield (status, path) obtained by processing the status of this
482 dirnode.
481 dirnode.
483
482
484 terseargs is the string of arguments passed by the user with `--terse`
483 terseargs is the string of arguments passed by the user with `--terse`
485 flag.
484 flag.
486
485
487 Following are the cases which can happen:
486 Following are the cases which can happen:
488
487
489 1) All the files in the directory (including all the files in its
488 1) All the files in the directory (including all the files in its
490 subdirectories) share the same status and the user has asked us to terse
489 subdirectories) share the same status and the user has asked us to terse
491 that status. -> yield (status, dirpath). dirpath will end in '/'.
490 that status. -> yield (status, dirpath). dirpath will end in '/'.
492
491
493 2) Otherwise, we do following:
492 2) Otherwise, we do following:
494
493
495 a) Yield (status, filepath) for all the files which are in this
494 a) Yield (status, filepath) for all the files which are in this
496 directory (only the ones in this directory, not the subdirs)
495 directory (only the ones in this directory, not the subdirs)
497
496
498 b) Recurse the function on all the subdirectories of this
497 b) Recurse the function on all the subdirectories of this
499 directory
498 directory
500 """
499 """
501
500
502 if len(self.statuses) == 1:
501 if len(self.statuses) == 1:
503 onlyst = self.statuses.pop()
502 onlyst = self.statuses.pop()
504
503
505 # Making sure we terse only when the status abbreviation is
504 # Making sure we terse only when the status abbreviation is
506 # passed as terse argument
505 # passed as terse argument
507 if onlyst in terseargs:
506 if onlyst in terseargs:
508 yield onlyst, self.path + '/'
507 yield onlyst, self.path + '/'
509 return
508 return
510
509
511 # add the files to status list
510 # add the files to status list
512 for st, fpath in self.iterfilepaths():
511 for st, fpath in self.iterfilepaths():
513 yield st, fpath
512 yield st, fpath
514
513
515 #recurse on the subdirs
514 #recurse on the subdirs
516 for dirobj in self.subdirs.values():
515 for dirobj in self.subdirs.values():
517 for st, fpath in dirobj.tersewalk(terseargs):
516 for st, fpath in dirobj.tersewalk(terseargs):
518 yield st, fpath
517 yield st, fpath
519
518
520 def tersedir(statuslist, terseargs):
519 def tersedir(statuslist, terseargs):
521 """
520 """
522 Terse the status if all the files in a directory shares the same status.
521 Terse the status if all the files in a directory shares the same status.
523
522
524 statuslist is scmutil.status() object which contains a list of files for
523 statuslist is scmutil.status() object which contains a list of files for
525 each status.
524 each status.
526 terseargs is string which is passed by the user as the argument to `--terse`
525 terseargs is string which is passed by the user as the argument to `--terse`
527 flag.
526 flag.
528
527
529 The function makes a tree of objects of dirnode class, and at each node it
528 The function makes a tree of objects of dirnode class, and at each node it
530 stores the information required to know whether we can terse a certain
529 stores the information required to know whether we can terse a certain
531 directory or not.
530 directory or not.
532 """
531 """
533 # the order matters here as that is used to produce final list
532 # the order matters here as that is used to produce final list
534 allst = ('m', 'a', 'r', 'd', 'u', 'i', 'c')
533 allst = ('m', 'a', 'r', 'd', 'u', 'i', 'c')
535
534
536 # checking the argument validity
535 # checking the argument validity
537 for s in pycompat.bytestr(terseargs):
536 for s in pycompat.bytestr(terseargs):
538 if s not in allst:
537 if s not in allst:
539 raise error.Abort(_("'%s' not recognized") % s)
538 raise error.Abort(_("'%s' not recognized") % s)
540
539
541 # creating a dirnode object for the root of the repo
540 # creating a dirnode object for the root of the repo
542 rootobj = dirnode('')
541 rootobj = dirnode('')
543 pstatus = ('modified', 'added', 'deleted', 'clean', 'unknown',
542 pstatus = ('modified', 'added', 'deleted', 'clean', 'unknown',
544 'ignored', 'removed')
543 'ignored', 'removed')
545
544
546 tersedict = {}
545 tersedict = {}
547 for attrname in pstatus:
546 for attrname in pstatus:
548 statuschar = attrname[0:1]
547 statuschar = attrname[0:1]
549 for f in getattr(statuslist, attrname):
548 for f in getattr(statuslist, attrname):
550 rootobj.addfile(f, statuschar)
549 rootobj.addfile(f, statuschar)
551 tersedict[statuschar] = []
550 tersedict[statuschar] = []
552
551
553 # we won't be tersing the root dir, so add files in it
552 # we won't be tersing the root dir, so add files in it
554 for st, fpath in rootobj.iterfilepaths():
553 for st, fpath in rootobj.iterfilepaths():
555 tersedict[st].append(fpath)
554 tersedict[st].append(fpath)
556
555
557 # process each sub-directory and build tersedict
556 # process each sub-directory and build tersedict
558 for subdir in rootobj.subdirs.values():
557 for subdir in rootobj.subdirs.values():
559 for st, f in subdir.tersewalk(terseargs):
558 for st, f in subdir.tersewalk(terseargs):
560 tersedict[st].append(f)
559 tersedict[st].append(f)
561
560
562 tersedlist = []
561 tersedlist = []
563 for st in allst:
562 for st in allst:
564 tersedict[st].sort()
563 tersedict[st].sort()
565 tersedlist.append(tersedict[st])
564 tersedlist.append(tersedict[st])
566
565
567 return tersedlist
566 return tersedlist
568
567
569 def _commentlines(raw):
568 def _commentlines(raw):
570 '''Surround lineswith a comment char and a new line'''
569 '''Surround lineswith a comment char and a new line'''
571 lines = raw.splitlines()
570 lines = raw.splitlines()
572 commentedlines = ['# %s' % line for line in lines]
571 commentedlines = ['# %s' % line for line in lines]
573 return '\n'.join(commentedlines) + '\n'
572 return '\n'.join(commentedlines) + '\n'
574
573
575 def _conflictsmsg(repo):
574 def _conflictsmsg(repo):
576 mergestate = mergemod.mergestate.read(repo)
575 mergestate = mergemod.mergestate.read(repo)
577 if not mergestate.active():
576 if not mergestate.active():
578 return
577 return
579
578
580 m = scmutil.match(repo[None])
579 m = scmutil.match(repo[None])
581 unresolvedlist = [f for f in mergestate.unresolved() if m(f)]
580 unresolvedlist = [f for f in mergestate.unresolved() if m(f)]
582 if unresolvedlist:
581 if unresolvedlist:
583 mergeliststr = '\n'.join(
582 mergeliststr = '\n'.join(
584 [' %s' % util.pathto(repo.root, encoding.getcwd(), path)
583 [' %s' % util.pathto(repo.root, encoding.getcwd(), path)
585 for path in unresolvedlist])
584 for path in unresolvedlist])
586 msg = _('''Unresolved merge conflicts:
585 msg = _('''Unresolved merge conflicts:
587
586
588 %s
587 %s
589
588
590 To mark files as resolved: hg resolve --mark FILE''') % mergeliststr
589 To mark files as resolved: hg resolve --mark FILE''') % mergeliststr
591 else:
590 else:
592 msg = _('No unresolved merge conflicts.')
591 msg = _('No unresolved merge conflicts.')
593
592
594 return _commentlines(msg)
593 return _commentlines(msg)
595
594
596 def _helpmessage(continuecmd, abortcmd):
595 def _helpmessage(continuecmd, abortcmd):
597 msg = _('To continue: %s\n'
596 msg = _('To continue: %s\n'
598 'To abort: %s') % (continuecmd, abortcmd)
597 'To abort: %s') % (continuecmd, abortcmd)
599 return _commentlines(msg)
598 return _commentlines(msg)
600
599
601 def _rebasemsg():
600 def _rebasemsg():
602 return _helpmessage('hg rebase --continue', 'hg rebase --abort')
601 return _helpmessage('hg rebase --continue', 'hg rebase --abort')
603
602
604 def _histeditmsg():
603 def _histeditmsg():
605 return _helpmessage('hg histedit --continue', 'hg histedit --abort')
604 return _helpmessage('hg histedit --continue', 'hg histedit --abort')
606
605
607 def _unshelvemsg():
606 def _unshelvemsg():
608 return _helpmessage('hg unshelve --continue', 'hg unshelve --abort')
607 return _helpmessage('hg unshelve --continue', 'hg unshelve --abort')
609
608
610 def _graftmsg():
609 def _graftmsg():
611 # tweakdefaults requires `update` to have a rev hence the `.`
610 # tweakdefaults requires `update` to have a rev hence the `.`
612 return _helpmessage('hg graft --continue', 'hg graft --abort')
611 return _helpmessage('hg graft --continue', 'hg graft --abort')
613
612
614 def _mergemsg():
613 def _mergemsg():
615 # tweakdefaults requires `update` to have a rev hence the `.`
614 # tweakdefaults requires `update` to have a rev hence the `.`
616 return _helpmessage('hg commit', 'hg merge --abort')
615 return _helpmessage('hg commit', 'hg merge --abort')
617
616
618 def _bisectmsg():
617 def _bisectmsg():
619 msg = _('To mark the changeset good: hg bisect --good\n'
618 msg = _('To mark the changeset good: hg bisect --good\n'
620 'To mark the changeset bad: hg bisect --bad\n'
619 'To mark the changeset bad: hg bisect --bad\n'
621 'To abort: hg bisect --reset\n')
620 'To abort: hg bisect --reset\n')
622 return _commentlines(msg)
621 return _commentlines(msg)
623
622
624 def fileexistspredicate(filename):
623 def fileexistspredicate(filename):
625 return lambda repo: repo.vfs.exists(filename)
624 return lambda repo: repo.vfs.exists(filename)
626
625
627 def _mergepredicate(repo):
626 def _mergepredicate(repo):
628 return len(repo[None].parents()) > 1
627 return len(repo[None].parents()) > 1
629
628
630 STATES = (
629 STATES = (
631 # (state, predicate to detect states, helpful message function)
630 # (state, predicate to detect states, helpful message function)
632 ('histedit', fileexistspredicate('histedit-state'), _histeditmsg),
631 ('histedit', fileexistspredicate('histedit-state'), _histeditmsg),
633 ('bisect', fileexistspredicate('bisect.state'), _bisectmsg),
632 ('bisect', fileexistspredicate('bisect.state'), _bisectmsg),
634 ('graft', fileexistspredicate('graftstate'), _graftmsg),
633 ('graft', fileexistspredicate('graftstate'), _graftmsg),
635 ('unshelve', fileexistspredicate('shelvedstate'), _unshelvemsg),
634 ('unshelve', fileexistspredicate('shelvedstate'), _unshelvemsg),
636 ('rebase', fileexistspredicate('rebasestate'), _rebasemsg),
635 ('rebase', fileexistspredicate('rebasestate'), _rebasemsg),
637 # The merge state is part of a list that will be iterated over.
636 # The merge state is part of a list that will be iterated over.
638 # They need to be last because some of the other unfinished states may also
637 # They need to be last because some of the other unfinished states may also
639 # be in a merge or update state (eg. rebase, histedit, graft, etc).
638 # be in a merge or update state (eg. rebase, histedit, graft, etc).
640 # We want those to have priority.
639 # We want those to have priority.
641 ('merge', _mergepredicate, _mergemsg),
640 ('merge', _mergepredicate, _mergemsg),
642 )
641 )
643
642
644 def _getrepostate(repo):
643 def _getrepostate(repo):
645 # experimental config: commands.status.skipstates
644 # experimental config: commands.status.skipstates
646 skip = set(repo.ui.configlist('commands', 'status.skipstates'))
645 skip = set(repo.ui.configlist('commands', 'status.skipstates'))
647 for state, statedetectionpredicate, msgfn in STATES:
646 for state, statedetectionpredicate, msgfn in STATES:
648 if state in skip:
647 if state in skip:
649 continue
648 continue
650 if statedetectionpredicate(repo):
649 if statedetectionpredicate(repo):
651 return (state, statedetectionpredicate, msgfn)
650 return (state, statedetectionpredicate, msgfn)
652
651
653 def morestatus(repo, fm):
652 def morestatus(repo, fm):
654 statetuple = _getrepostate(repo)
653 statetuple = _getrepostate(repo)
655 label = 'status.morestatus'
654 label = 'status.morestatus'
656 if statetuple:
655 if statetuple:
657 state, statedetectionpredicate, helpfulmsg = statetuple
656 state, statedetectionpredicate, helpfulmsg = statetuple
658 statemsg = _('The repository is in an unfinished *%s* state.') % state
657 statemsg = _('The repository is in an unfinished *%s* state.') % state
659 fm.plain('%s\n' % _commentlines(statemsg), label=label)
658 fm.plain('%s\n' % _commentlines(statemsg), label=label)
660 conmsg = _conflictsmsg(repo)
659 conmsg = _conflictsmsg(repo)
661 if conmsg:
660 if conmsg:
662 fm.plain('%s\n' % conmsg, label=label)
661 fm.plain('%s\n' % conmsg, label=label)
663 if helpfulmsg:
662 if helpfulmsg:
664 helpmsg = helpfulmsg()
663 helpmsg = helpfulmsg()
665 fm.plain('%s\n' % helpmsg, label=label)
664 fm.plain('%s\n' % helpmsg, label=label)
666
665
667 def findpossible(cmd, table, strict=False):
666 def findpossible(cmd, table, strict=False):
668 """
667 """
669 Return cmd -> (aliases, command table entry)
668 Return cmd -> (aliases, command table entry)
670 for each matching command.
669 for each matching command.
671 Return debug commands (or their aliases) only if no normal command matches.
670 Return debug commands (or their aliases) only if no normal command matches.
672 """
671 """
673 choice = {}
672 choice = {}
674 debugchoice = {}
673 debugchoice = {}
675
674
676 if cmd in table:
675 if cmd in table:
677 # short-circuit exact matches, "log" alias beats "^log|history"
676 # short-circuit exact matches, "log" alias beats "^log|history"
678 keys = [cmd]
677 keys = [cmd]
679 else:
678 else:
680 keys = table.keys()
679 keys = table.keys()
681
680
682 allcmds = []
681 allcmds = []
683 for e in keys:
682 for e in keys:
684 aliases = parsealiases(e)
683 aliases = parsealiases(e)
685 allcmds.extend(aliases)
684 allcmds.extend(aliases)
686 found = None
685 found = None
687 if cmd in aliases:
686 if cmd in aliases:
688 found = cmd
687 found = cmd
689 elif not strict:
688 elif not strict:
690 for a in aliases:
689 for a in aliases:
691 if a.startswith(cmd):
690 if a.startswith(cmd):
692 found = a
691 found = a
693 break
692 break
694 if found is not None:
693 if found is not None:
695 if aliases[0].startswith("debug") or found.startswith("debug"):
694 if aliases[0].startswith("debug") or found.startswith("debug"):
696 debugchoice[found] = (aliases, table[e])
695 debugchoice[found] = (aliases, table[e])
697 else:
696 else:
698 choice[found] = (aliases, table[e])
697 choice[found] = (aliases, table[e])
699
698
700 if not choice and debugchoice:
699 if not choice and debugchoice:
701 choice = debugchoice
700 choice = debugchoice
702
701
703 return choice, allcmds
702 return choice, allcmds
704
703
705 def findcmd(cmd, table, strict=True):
704 def findcmd(cmd, table, strict=True):
706 """Return (aliases, command table entry) for command string."""
705 """Return (aliases, command table entry) for command string."""
707 choice, allcmds = findpossible(cmd, table, strict)
706 choice, allcmds = findpossible(cmd, table, strict)
708
707
709 if cmd in choice:
708 if cmd in choice:
710 return choice[cmd]
709 return choice[cmd]
711
710
712 if len(choice) > 1:
711 if len(choice) > 1:
713 clist = sorted(choice)
712 clist = sorted(choice)
714 raise error.AmbiguousCommand(cmd, clist)
713 raise error.AmbiguousCommand(cmd, clist)
715
714
716 if choice:
715 if choice:
717 return list(choice.values())[0]
716 return list(choice.values())[0]
718
717
719 raise error.UnknownCommand(cmd, allcmds)
718 raise error.UnknownCommand(cmd, allcmds)
720
719
721 def changebranch(ui, repo, revs, label):
720 def changebranch(ui, repo, revs, label):
722 """ Change the branch name of given revs to label """
721 """ Change the branch name of given revs to label """
723
722
724 with repo.wlock(), repo.lock(), repo.transaction('branches'):
723 with repo.wlock(), repo.lock(), repo.transaction('branches'):
725 # abort in case of uncommitted merge or dirty wdir
724 # abort in case of uncommitted merge or dirty wdir
726 bailifchanged(repo)
725 bailifchanged(repo)
727 revs = scmutil.revrange(repo, revs)
726 revs = scmutil.revrange(repo, revs)
728 if not revs:
727 if not revs:
729 raise error.Abort("empty revision set")
728 raise error.Abort("empty revision set")
730 roots = repo.revs('roots(%ld)', revs)
729 roots = repo.revs('roots(%ld)', revs)
731 if len(roots) > 1:
730 if len(roots) > 1:
732 raise error.Abort(_("cannot change branch of non-linear revisions"))
731 raise error.Abort(_("cannot change branch of non-linear revisions"))
733 rewriteutil.precheck(repo, revs, 'change branch of')
732 rewriteutil.precheck(repo, revs, 'change branch of')
734
733
735 root = repo[roots.first()]
734 root = repo[roots.first()]
736 if not root.p1().branch() == label and label in repo.branchmap():
735 if not root.p1().branch() == label and label in repo.branchmap():
737 raise error.Abort(_("a branch of the same name already exists"))
736 raise error.Abort(_("a branch of the same name already exists"))
738
737
739 if repo.revs('merge() and %ld', revs):
738 if repo.revs('merge() and %ld', revs):
740 raise error.Abort(_("cannot change branch of a merge commit"))
739 raise error.Abort(_("cannot change branch of a merge commit"))
741 if repo.revs('obsolete() and %ld', revs):
740 if repo.revs('obsolete() and %ld', revs):
742 raise error.Abort(_("cannot change branch of a obsolete changeset"))
741 raise error.Abort(_("cannot change branch of a obsolete changeset"))
743
742
744 # make sure only topological heads
743 # make sure only topological heads
745 if repo.revs('heads(%ld) - head()', revs):
744 if repo.revs('heads(%ld) - head()', revs):
746 raise error.Abort(_("cannot change branch in middle of a stack"))
745 raise error.Abort(_("cannot change branch in middle of a stack"))
747
746
748 replacements = {}
747 replacements = {}
749 # avoid import cycle mercurial.cmdutil -> mercurial.context ->
748 # avoid import cycle mercurial.cmdutil -> mercurial.context ->
750 # mercurial.subrepo -> mercurial.cmdutil
749 # mercurial.subrepo -> mercurial.cmdutil
751 from . import context
750 from . import context
752 for rev in revs:
751 for rev in revs:
753 ctx = repo[rev]
752 ctx = repo[rev]
754 oldbranch = ctx.branch()
753 oldbranch = ctx.branch()
755 # check if ctx has same branch
754 # check if ctx has same branch
756 if oldbranch == label:
755 if oldbranch == label:
757 continue
756 continue
758
757
759 def filectxfn(repo, newctx, path):
758 def filectxfn(repo, newctx, path):
760 try:
759 try:
761 return ctx[path]
760 return ctx[path]
762 except error.ManifestLookupError:
761 except error.ManifestLookupError:
763 return None
762 return None
764
763
765 ui.debug("changing branch of '%s' from '%s' to '%s'\n"
764 ui.debug("changing branch of '%s' from '%s' to '%s'\n"
766 % (hex(ctx.node()), oldbranch, label))
765 % (hex(ctx.node()), oldbranch, label))
767 extra = ctx.extra()
766 extra = ctx.extra()
768 extra['branch_change'] = hex(ctx.node())
767 extra['branch_change'] = hex(ctx.node())
769 # While changing branch of set of linear commits, make sure that
768 # While changing branch of set of linear commits, make sure that
770 # we base our commits on new parent rather than old parent which
769 # we base our commits on new parent rather than old parent which
771 # was obsoleted while changing the branch
770 # was obsoleted while changing the branch
772 p1 = ctx.p1().node()
771 p1 = ctx.p1().node()
773 p2 = ctx.p2().node()
772 p2 = ctx.p2().node()
774 if p1 in replacements:
773 if p1 in replacements:
775 p1 = replacements[p1][0]
774 p1 = replacements[p1][0]
776 if p2 in replacements:
775 if p2 in replacements:
777 p2 = replacements[p2][0]
776 p2 = replacements[p2][0]
778
777
779 mc = context.memctx(repo, (p1, p2),
778 mc = context.memctx(repo, (p1, p2),
780 ctx.description(),
779 ctx.description(),
781 ctx.files(),
780 ctx.files(),
782 filectxfn,
781 filectxfn,
783 user=ctx.user(),
782 user=ctx.user(),
784 date=ctx.date(),
783 date=ctx.date(),
785 extra=extra,
784 extra=extra,
786 branch=label)
785 branch=label)
787
786
788 newnode = repo.commitctx(mc)
787 newnode = repo.commitctx(mc)
789 replacements[ctx.node()] = (newnode,)
788 replacements[ctx.node()] = (newnode,)
790 ui.debug('new node id is %s\n' % hex(newnode))
789 ui.debug('new node id is %s\n' % hex(newnode))
791
790
792 # create obsmarkers and move bookmarks
791 # create obsmarkers and move bookmarks
793 scmutil.cleanupnodes(repo, replacements, 'branch-change', fixphase=True)
792 scmutil.cleanupnodes(repo, replacements, 'branch-change', fixphase=True)
794
793
795 # move the working copy too
794 # move the working copy too
796 wctx = repo[None]
795 wctx = repo[None]
797 # in-progress merge is a bit too complex for now.
796 # in-progress merge is a bit too complex for now.
798 if len(wctx.parents()) == 1:
797 if len(wctx.parents()) == 1:
799 newid = replacements.get(wctx.p1().node())
798 newid = replacements.get(wctx.p1().node())
800 if newid is not None:
799 if newid is not None:
801 # avoid import cycle mercurial.cmdutil -> mercurial.hg ->
800 # avoid import cycle mercurial.cmdutil -> mercurial.hg ->
802 # mercurial.cmdutil
801 # mercurial.cmdutil
803 from . import hg
802 from . import hg
804 hg.update(repo, newid[0], quietempty=True)
803 hg.update(repo, newid[0], quietempty=True)
805
804
806 ui.status(_("changed branch on %d changesets\n") % len(replacements))
805 ui.status(_("changed branch on %d changesets\n") % len(replacements))
807
806
808 def findrepo(p):
807 def findrepo(p):
809 while not os.path.isdir(os.path.join(p, ".hg")):
808 while not os.path.isdir(os.path.join(p, ".hg")):
810 oldp, p = p, os.path.dirname(p)
809 oldp, p = p, os.path.dirname(p)
811 if p == oldp:
810 if p == oldp:
812 return None
811 return None
813
812
814 return p
813 return p
815
814
816 def bailifchanged(repo, merge=True, hint=None):
815 def bailifchanged(repo, merge=True, hint=None):
817 """ enforce the precondition that working directory must be clean.
816 """ enforce the precondition that working directory must be clean.
818
817
819 'merge' can be set to false if a pending uncommitted merge should be
818 'merge' can be set to false if a pending uncommitted merge should be
820 ignored (such as when 'update --check' runs).
819 ignored (such as when 'update --check' runs).
821
820
822 'hint' is the usual hint given to Abort exception.
821 'hint' is the usual hint given to Abort exception.
823 """
822 """
824
823
825 if merge and repo.dirstate.p2() != nullid:
824 if merge and repo.dirstate.p2() != nullid:
826 raise error.Abort(_('outstanding uncommitted merge'), hint=hint)
825 raise error.Abort(_('outstanding uncommitted merge'), hint=hint)
827 modified, added, removed, deleted = repo.status()[:4]
826 modified, added, removed, deleted = repo.status()[:4]
828 if modified or added or removed or deleted:
827 if modified or added or removed or deleted:
829 raise error.Abort(_('uncommitted changes'), hint=hint)
828 raise error.Abort(_('uncommitted changes'), hint=hint)
830 ctx = repo[None]
829 ctx = repo[None]
831 for s in sorted(ctx.substate):
830 for s in sorted(ctx.substate):
832 ctx.sub(s).bailifchanged(hint=hint)
831 ctx.sub(s).bailifchanged(hint=hint)
833
832
834 def logmessage(ui, opts):
833 def logmessage(ui, opts):
835 """ get the log message according to -m and -l option """
834 """ get the log message according to -m and -l option """
836 message = opts.get('message')
835 message = opts.get('message')
837 logfile = opts.get('logfile')
836 logfile = opts.get('logfile')
838
837
839 if message and logfile:
838 if message and logfile:
840 raise error.Abort(_('options --message and --logfile are mutually '
839 raise error.Abort(_('options --message and --logfile are mutually '
841 'exclusive'))
840 'exclusive'))
842 if not message and logfile:
841 if not message and logfile:
843 try:
842 try:
844 if isstdiofilename(logfile):
843 if isstdiofilename(logfile):
845 message = ui.fin.read()
844 message = ui.fin.read()
846 else:
845 else:
847 message = '\n'.join(util.readfile(logfile).splitlines())
846 message = '\n'.join(util.readfile(logfile).splitlines())
848 except IOError as inst:
847 except IOError as inst:
849 raise error.Abort(_("can't read commit message '%s': %s") %
848 raise error.Abort(_("can't read commit message '%s': %s") %
850 (logfile, encoding.strtolocal(inst.strerror)))
849 (logfile, encoding.strtolocal(inst.strerror)))
851 return message
850 return message
852
851
853 def mergeeditform(ctxorbool, baseformname):
852 def mergeeditform(ctxorbool, baseformname):
854 """return appropriate editform name (referencing a committemplate)
853 """return appropriate editform name (referencing a committemplate)
855
854
856 'ctxorbool' is either a ctx to be committed, or a bool indicating whether
855 'ctxorbool' is either a ctx to be committed, or a bool indicating whether
857 merging is committed.
856 merging is committed.
858
857
859 This returns baseformname with '.merge' appended if it is a merge,
858 This returns baseformname with '.merge' appended if it is a merge,
860 otherwise '.normal' is appended.
859 otherwise '.normal' is appended.
861 """
860 """
862 if isinstance(ctxorbool, bool):
861 if isinstance(ctxorbool, bool):
863 if ctxorbool:
862 if ctxorbool:
864 return baseformname + ".merge"
863 return baseformname + ".merge"
865 elif 1 < len(ctxorbool.parents()):
864 elif 1 < len(ctxorbool.parents()):
866 return baseformname + ".merge"
865 return baseformname + ".merge"
867
866
868 return baseformname + ".normal"
867 return baseformname + ".normal"
869
868
870 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
869 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
871 editform='', **opts):
870 editform='', **opts):
872 """get appropriate commit message editor according to '--edit' option
871 """get appropriate commit message editor according to '--edit' option
873
872
874 'finishdesc' is a function to be called with edited commit message
873 'finishdesc' is a function to be called with edited commit message
875 (= 'description' of the new changeset) just after editing, but
874 (= 'description' of the new changeset) just after editing, but
876 before checking empty-ness. It should return actual text to be
875 before checking empty-ness. It should return actual text to be
877 stored into history. This allows to change description before
876 stored into history. This allows to change description before
878 storing.
877 storing.
879
878
880 'extramsg' is a extra message to be shown in the editor instead of
879 'extramsg' is a extra message to be shown in the editor instead of
881 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
880 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
882 is automatically added.
881 is automatically added.
883
882
884 'editform' is a dot-separated list of names, to distinguish
883 'editform' is a dot-separated list of names, to distinguish
885 the purpose of commit text editing.
884 the purpose of commit text editing.
886
885
887 'getcommiteditor' returns 'commitforceeditor' regardless of
886 'getcommiteditor' returns 'commitforceeditor' regardless of
888 'edit', if one of 'finishdesc' or 'extramsg' is specified, because
887 'edit', if one of 'finishdesc' or 'extramsg' is specified, because
889 they are specific for usage in MQ.
888 they are specific for usage in MQ.
890 """
889 """
891 if edit or finishdesc or extramsg:
890 if edit or finishdesc or extramsg:
892 return lambda r, c, s: commitforceeditor(r, c, s,
891 return lambda r, c, s: commitforceeditor(r, c, s,
893 finishdesc=finishdesc,
892 finishdesc=finishdesc,
894 extramsg=extramsg,
893 extramsg=extramsg,
895 editform=editform)
894 editform=editform)
896 elif editform:
895 elif editform:
897 return lambda r, c, s: commiteditor(r, c, s, editform=editform)
896 return lambda r, c, s: commiteditor(r, c, s, editform=editform)
898 else:
897 else:
899 return commiteditor
898 return commiteditor
900
899
901 def _escapecommandtemplate(tmpl):
900 def _escapecommandtemplate(tmpl):
902 parts = []
901 parts = []
903 for typ, start, end in templater.scantemplate(tmpl, raw=True):
902 for typ, start, end in templater.scantemplate(tmpl, raw=True):
904 if typ == b'string':
903 if typ == b'string':
905 parts.append(stringutil.escapestr(tmpl[start:end]))
904 parts.append(stringutil.escapestr(tmpl[start:end]))
906 else:
905 else:
907 parts.append(tmpl[start:end])
906 parts.append(tmpl[start:end])
908 return b''.join(parts)
907 return b''.join(parts)
909
908
910 def rendercommandtemplate(ui, tmpl, props):
909 def rendercommandtemplate(ui, tmpl, props):
911 r"""Expand a literal template 'tmpl' in a way suitable for command line
910 r"""Expand a literal template 'tmpl' in a way suitable for command line
912
911
913 '\' in outermost string is not taken as an escape character because it
912 '\' in outermost string is not taken as an escape character because it
914 is a directory separator on Windows.
913 is a directory separator on Windows.
915
914
916 >>> from . import ui as uimod
915 >>> from . import ui as uimod
917 >>> ui = uimod.ui()
916 >>> ui = uimod.ui()
918 >>> rendercommandtemplate(ui, b'c:\\{path}', {b'path': b'foo'})
917 >>> rendercommandtemplate(ui, b'c:\\{path}', {b'path': b'foo'})
919 'c:\\foo'
918 'c:\\foo'
920 >>> rendercommandtemplate(ui, b'{"c:\\{path}"}', {'path': b'foo'})
919 >>> rendercommandtemplate(ui, b'{"c:\\{path}"}', {'path': b'foo'})
921 'c:{path}'
920 'c:{path}'
922 """
921 """
923 if not tmpl:
922 if not tmpl:
924 return tmpl
923 return tmpl
925 t = formatter.maketemplater(ui, _escapecommandtemplate(tmpl))
924 t = formatter.maketemplater(ui, _escapecommandtemplate(tmpl))
926 return t.renderdefault(props)
925 return t.renderdefault(props)
927
926
928 def rendertemplate(ctx, tmpl, props=None):
927 def rendertemplate(ctx, tmpl, props=None):
929 """Expand a literal template 'tmpl' byte-string against one changeset
928 """Expand a literal template 'tmpl' byte-string against one changeset
930
929
931 Each props item must be a stringify-able value or a callable returning
930 Each props item must be a stringify-able value or a callable returning
932 such value, i.e. no bare list nor dict should be passed.
931 such value, i.e. no bare list nor dict should be passed.
933 """
932 """
934 repo = ctx.repo()
933 repo = ctx.repo()
935 tres = formatter.templateresources(repo.ui, repo)
934 tres = formatter.templateresources(repo.ui, repo)
936 t = formatter.maketemplater(repo.ui, tmpl, defaults=templatekw.keywords,
935 t = formatter.maketemplater(repo.ui, tmpl, defaults=templatekw.keywords,
937 resources=tres)
936 resources=tres)
938 mapping = {'ctx': ctx}
937 mapping = {'ctx': ctx}
939 if props:
938 if props:
940 mapping.update(props)
939 mapping.update(props)
941 return t.renderdefault(mapping)
940 return t.renderdefault(mapping)
942
941
943 def _buildfntemplate(pat, total=None, seqno=None, revwidth=None, pathname=None):
942 def _buildfntemplate(pat, total=None, seqno=None, revwidth=None, pathname=None):
944 r"""Convert old-style filename format string to template string
943 r"""Convert old-style filename format string to template string
945
944
946 >>> _buildfntemplate(b'foo-%b-%n.patch', seqno=0)
945 >>> _buildfntemplate(b'foo-%b-%n.patch', seqno=0)
947 'foo-{reporoot|basename}-{seqno}.patch'
946 'foo-{reporoot|basename}-{seqno}.patch'
948 >>> _buildfntemplate(b'%R{tags % "{tag}"}%H')
947 >>> _buildfntemplate(b'%R{tags % "{tag}"}%H')
949 '{rev}{tags % "{tag}"}{node}'
948 '{rev}{tags % "{tag}"}{node}'
950
949
951 '\' in outermost strings has to be escaped because it is a directory
950 '\' in outermost strings has to be escaped because it is a directory
952 separator on Windows:
951 separator on Windows:
953
952
954 >>> _buildfntemplate(b'c:\\tmp\\%R\\%n.patch', seqno=0)
953 >>> _buildfntemplate(b'c:\\tmp\\%R\\%n.patch', seqno=0)
955 'c:\\\\tmp\\\\{rev}\\\\{seqno}.patch'
954 'c:\\\\tmp\\\\{rev}\\\\{seqno}.patch'
956 >>> _buildfntemplate(b'\\\\foo\\bar.patch')
955 >>> _buildfntemplate(b'\\\\foo\\bar.patch')
957 '\\\\\\\\foo\\\\bar.patch'
956 '\\\\\\\\foo\\\\bar.patch'
958 >>> _buildfntemplate(b'\\{tags % "{tag}"}')
957 >>> _buildfntemplate(b'\\{tags % "{tag}"}')
959 '\\\\{tags % "{tag}"}'
958 '\\\\{tags % "{tag}"}'
960
959
961 but inner strings follow the template rules (i.e. '\' is taken as an
960 but inner strings follow the template rules (i.e. '\' is taken as an
962 escape character):
961 escape character):
963
962
964 >>> _buildfntemplate(br'{"c:\tmp"}', seqno=0)
963 >>> _buildfntemplate(br'{"c:\tmp"}', seqno=0)
965 '{"c:\\tmp"}'
964 '{"c:\\tmp"}'
966 """
965 """
967 expander = {
966 expander = {
968 b'H': b'{node}',
967 b'H': b'{node}',
969 b'R': b'{rev}',
968 b'R': b'{rev}',
970 b'h': b'{node|short}',
969 b'h': b'{node|short}',
971 b'm': br'{sub(r"[^\w]", "_", desc|firstline)}',
970 b'm': br'{sub(r"[^\w]", "_", desc|firstline)}',
972 b'r': b'{if(revwidth, pad(rev, revwidth, "0", left=True), rev)}',
971 b'r': b'{if(revwidth, pad(rev, revwidth, "0", left=True), rev)}',
973 b'%': b'%',
972 b'%': b'%',
974 b'b': b'{reporoot|basename}',
973 b'b': b'{reporoot|basename}',
975 }
974 }
976 if total is not None:
975 if total is not None:
977 expander[b'N'] = b'{total}'
976 expander[b'N'] = b'{total}'
978 if seqno is not None:
977 if seqno is not None:
979 expander[b'n'] = b'{seqno}'
978 expander[b'n'] = b'{seqno}'
980 if total is not None and seqno is not None:
979 if total is not None and seqno is not None:
981 expander[b'n'] = b'{pad(seqno, total|stringify|count, "0", left=True)}'
980 expander[b'n'] = b'{pad(seqno, total|stringify|count, "0", left=True)}'
982 if pathname is not None:
981 if pathname is not None:
983 expander[b's'] = b'{pathname|basename}'
982 expander[b's'] = b'{pathname|basename}'
984 expander[b'd'] = b'{if(pathname|dirname, pathname|dirname, ".")}'
983 expander[b'd'] = b'{if(pathname|dirname, pathname|dirname, ".")}'
985 expander[b'p'] = b'{pathname}'
984 expander[b'p'] = b'{pathname}'
986
985
987 newname = []
986 newname = []
988 for typ, start, end in templater.scantemplate(pat, raw=True):
987 for typ, start, end in templater.scantemplate(pat, raw=True):
989 if typ != b'string':
988 if typ != b'string':
990 newname.append(pat[start:end])
989 newname.append(pat[start:end])
991 continue
990 continue
992 i = start
991 i = start
993 while i < end:
992 while i < end:
994 n = pat.find(b'%', i, end)
993 n = pat.find(b'%', i, end)
995 if n < 0:
994 if n < 0:
996 newname.append(stringutil.escapestr(pat[i:end]))
995 newname.append(stringutil.escapestr(pat[i:end]))
997 break
996 break
998 newname.append(stringutil.escapestr(pat[i:n]))
997 newname.append(stringutil.escapestr(pat[i:n]))
999 if n + 2 > end:
998 if n + 2 > end:
1000 raise error.Abort(_("incomplete format spec in output "
999 raise error.Abort(_("incomplete format spec in output "
1001 "filename"))
1000 "filename"))
1002 c = pat[n + 1:n + 2]
1001 c = pat[n + 1:n + 2]
1003 i = n + 2
1002 i = n + 2
1004 try:
1003 try:
1005 newname.append(expander[c])
1004 newname.append(expander[c])
1006 except KeyError:
1005 except KeyError:
1007 raise error.Abort(_("invalid format spec '%%%s' in output "
1006 raise error.Abort(_("invalid format spec '%%%s' in output "
1008 "filename") % c)
1007 "filename") % c)
1009 return ''.join(newname)
1008 return ''.join(newname)
1010
1009
1011 def makefilename(ctx, pat, **props):
1010 def makefilename(ctx, pat, **props):
1012 if not pat:
1011 if not pat:
1013 return pat
1012 return pat
1014 tmpl = _buildfntemplate(pat, **props)
1013 tmpl = _buildfntemplate(pat, **props)
1015 # BUG: alias expansion shouldn't be made against template fragments
1014 # BUG: alias expansion shouldn't be made against template fragments
1016 # rewritten from %-format strings, but we have no easy way to partially
1015 # rewritten from %-format strings, but we have no easy way to partially
1017 # disable the expansion.
1016 # disable the expansion.
1018 return rendertemplate(ctx, tmpl, pycompat.byteskwargs(props))
1017 return rendertemplate(ctx, tmpl, pycompat.byteskwargs(props))
1019
1018
1020 def isstdiofilename(pat):
1019 def isstdiofilename(pat):
1021 """True if the given pat looks like a filename denoting stdin/stdout"""
1020 """True if the given pat looks like a filename denoting stdin/stdout"""
1022 return not pat or pat == '-'
1021 return not pat or pat == '-'
1023
1022
1024 class _unclosablefile(object):
1023 class _unclosablefile(object):
1025 def __init__(self, fp):
1024 def __init__(self, fp):
1026 self._fp = fp
1025 self._fp = fp
1027
1026
1028 def close(self):
1027 def close(self):
1029 pass
1028 pass
1030
1029
1031 def __iter__(self):
1030 def __iter__(self):
1032 return iter(self._fp)
1031 return iter(self._fp)
1033
1032
1034 def __getattr__(self, attr):
1033 def __getattr__(self, attr):
1035 return getattr(self._fp, attr)
1034 return getattr(self._fp, attr)
1036
1035
1037 def __enter__(self):
1036 def __enter__(self):
1038 return self
1037 return self
1039
1038
1040 def __exit__(self, exc_type, exc_value, exc_tb):
1039 def __exit__(self, exc_type, exc_value, exc_tb):
1041 pass
1040 pass
1042
1041
1043 def makefileobj(ctx, pat, mode='wb', **props):
1042 def makefileobj(ctx, pat, mode='wb', **props):
1044 writable = mode not in ('r', 'rb')
1043 writable = mode not in ('r', 'rb')
1045
1044
1046 if isstdiofilename(pat):
1045 if isstdiofilename(pat):
1047 repo = ctx.repo()
1046 repo = ctx.repo()
1048 if writable:
1047 if writable:
1049 fp = repo.ui.fout
1048 fp = repo.ui.fout
1050 else:
1049 else:
1051 fp = repo.ui.fin
1050 fp = repo.ui.fin
1052 return _unclosablefile(fp)
1051 return _unclosablefile(fp)
1053 fn = makefilename(ctx, pat, **props)
1052 fn = makefilename(ctx, pat, **props)
1054 return open(fn, mode)
1053 return open(fn, mode)
1055
1054
1056 def openstorage(repo, cmd, file_, opts, returnrevlog=False):
1055 def openstorage(repo, cmd, file_, opts, returnrevlog=False):
1057 """opens the changelog, manifest, a filelog or a given revlog"""
1056 """opens the changelog, manifest, a filelog or a given revlog"""
1058 cl = opts['changelog']
1057 cl = opts['changelog']
1059 mf = opts['manifest']
1058 mf = opts['manifest']
1060 dir = opts['dir']
1059 dir = opts['dir']
1061 msg = None
1060 msg = None
1062 if cl and mf:
1061 if cl and mf:
1063 msg = _('cannot specify --changelog and --manifest at the same time')
1062 msg = _('cannot specify --changelog and --manifest at the same time')
1064 elif cl and dir:
1063 elif cl and dir:
1065 msg = _('cannot specify --changelog and --dir at the same time')
1064 msg = _('cannot specify --changelog and --dir at the same time')
1066 elif cl or mf or dir:
1065 elif cl or mf or dir:
1067 if file_:
1066 if file_:
1068 msg = _('cannot specify filename with --changelog or --manifest')
1067 msg = _('cannot specify filename with --changelog or --manifest')
1069 elif not repo:
1068 elif not repo:
1070 msg = _('cannot specify --changelog or --manifest or --dir '
1069 msg = _('cannot specify --changelog or --manifest or --dir '
1071 'without a repository')
1070 'without a repository')
1072 if msg:
1071 if msg:
1073 raise error.Abort(msg)
1072 raise error.Abort(msg)
1074
1073
1075 r = None
1074 r = None
1076 if repo:
1075 if repo:
1077 if cl:
1076 if cl:
1078 r = repo.unfiltered().changelog
1077 r = repo.unfiltered().changelog
1079 elif dir:
1078 elif dir:
1080 if 'treemanifest' not in repo.requirements:
1079 if 'treemanifest' not in repo.requirements:
1081 raise error.Abort(_("--dir can only be used on repos with "
1080 raise error.Abort(_("--dir can only be used on repos with "
1082 "treemanifest enabled"))
1081 "treemanifest enabled"))
1083 if not dir.endswith('/'):
1082 if not dir.endswith('/'):
1084 dir = dir + '/'
1083 dir = dir + '/'
1085 dirlog = repo.manifestlog.getstorage(dir)
1084 dirlog = repo.manifestlog.getstorage(dir)
1086 if len(dirlog):
1085 if len(dirlog):
1087 r = dirlog
1086 r = dirlog
1088 elif mf:
1087 elif mf:
1089 r = repo.manifestlog.getstorage(b'')
1088 r = repo.manifestlog.getstorage(b'')
1090 elif file_:
1089 elif file_:
1091 filelog = repo.file(file_)
1090 filelog = repo.file(file_)
1092 if len(filelog):
1091 if len(filelog):
1093 r = filelog
1092 r = filelog
1094
1093
1095 # Not all storage may be revlogs. If requested, try to return an actual
1094 # Not all storage may be revlogs. If requested, try to return an actual
1096 # revlog instance.
1095 # revlog instance.
1097 if returnrevlog:
1096 if returnrevlog:
1098 if isinstance(r, revlog.revlog):
1097 if isinstance(r, revlog.revlog):
1099 pass
1098 pass
1100 elif util.safehasattr(r, '_revlog'):
1099 elif util.safehasattr(r, '_revlog'):
1101 r = r._revlog
1100 r = r._revlog
1102 elif r is not None:
1101 elif r is not None:
1103 raise error.Abort(_('%r does not appear to be a revlog') % r)
1102 raise error.Abort(_('%r does not appear to be a revlog') % r)
1104
1103
1105 if not r:
1104 if not r:
1106 if not returnrevlog:
1105 if not returnrevlog:
1107 raise error.Abort(_('cannot give path to non-revlog'))
1106 raise error.Abort(_('cannot give path to non-revlog'))
1108
1107
1109 if not file_:
1108 if not file_:
1110 raise error.CommandError(cmd, _('invalid arguments'))
1109 raise error.CommandError(cmd, _('invalid arguments'))
1111 if not os.path.isfile(file_):
1110 if not os.path.isfile(file_):
1112 raise error.Abort(_("revlog '%s' not found") % file_)
1111 raise error.Abort(_("revlog '%s' not found") % file_)
1113 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False),
1112 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False),
1114 file_[:-2] + ".i")
1113 file_[:-2] + ".i")
1115 return r
1114 return r
1116
1115
1117 def openrevlog(repo, cmd, file_, opts):
1116 def openrevlog(repo, cmd, file_, opts):
1118 """Obtain a revlog backing storage of an item.
1117 """Obtain a revlog backing storage of an item.
1119
1118
1120 This is similar to ``openstorage()`` except it always returns a revlog.
1119 This is similar to ``openstorage()`` except it always returns a revlog.
1121
1120
1122 In most cases, a caller cares about the main storage object - not the
1121 In most cases, a caller cares about the main storage object - not the
1123 revlog backing it. Therefore, this function should only be used by code
1122 revlog backing it. Therefore, this function should only be used by code
1124 that needs to examine low-level revlog implementation details. e.g. debug
1123 that needs to examine low-level revlog implementation details. e.g. debug
1125 commands.
1124 commands.
1126 """
1125 """
1127 return openstorage(repo, cmd, file_, opts, returnrevlog=True)
1126 return openstorage(repo, cmd, file_, opts, returnrevlog=True)
1128
1127
1129 def copy(ui, repo, pats, opts, rename=False):
1128 def copy(ui, repo, pats, opts, rename=False):
1130 # called with the repo lock held
1129 # called with the repo lock held
1131 #
1130 #
1132 # hgsep => pathname that uses "/" to separate directories
1131 # hgsep => pathname that uses "/" to separate directories
1133 # ossep => pathname that uses os.sep to separate directories
1132 # ossep => pathname that uses os.sep to separate directories
1134 cwd = repo.getcwd()
1133 cwd = repo.getcwd()
1135 targets = {}
1134 targets = {}
1136 after = opts.get("after")
1135 after = opts.get("after")
1137 dryrun = opts.get("dry_run")
1136 dryrun = opts.get("dry_run")
1138 wctx = repo[None]
1137 wctx = repo[None]
1139
1138
1140 def walkpat(pat):
1139 def walkpat(pat):
1141 srcs = []
1140 srcs = []
1142 if after:
1141 if after:
1143 badstates = '?'
1142 badstates = '?'
1144 else:
1143 else:
1145 badstates = '?r'
1144 badstates = '?r'
1146 m = scmutil.match(wctx, [pat], opts, globbed=True)
1145 m = scmutil.match(wctx, [pat], opts, globbed=True)
1147 for abs in wctx.walk(m):
1146 for abs in wctx.walk(m):
1148 state = repo.dirstate[abs]
1147 state = repo.dirstate[abs]
1149 rel = m.rel(abs)
1148 rel = m.rel(abs)
1150 exact = m.exact(abs)
1149 exact = m.exact(abs)
1151 if state in badstates:
1150 if state in badstates:
1152 if exact and state == '?':
1151 if exact and state == '?':
1153 ui.warn(_('%s: not copying - file is not managed\n') % rel)
1152 ui.warn(_('%s: not copying - file is not managed\n') % rel)
1154 if exact and state == 'r':
1153 if exact and state == 'r':
1155 ui.warn(_('%s: not copying - file has been marked for'
1154 ui.warn(_('%s: not copying - file has been marked for'
1156 ' remove\n') % rel)
1155 ' remove\n') % rel)
1157 continue
1156 continue
1158 # abs: hgsep
1157 # abs: hgsep
1159 # rel: ossep
1158 # rel: ossep
1160 srcs.append((abs, rel, exact))
1159 srcs.append((abs, rel, exact))
1161 return srcs
1160 return srcs
1162
1161
1163 # abssrc: hgsep
1162 # abssrc: hgsep
1164 # relsrc: ossep
1163 # relsrc: ossep
1165 # otarget: ossep
1164 # otarget: ossep
1166 def copyfile(abssrc, relsrc, otarget, exact):
1165 def copyfile(abssrc, relsrc, otarget, exact):
1167 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
1166 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
1168 if '/' in abstarget:
1167 if '/' in abstarget:
1169 # We cannot normalize abstarget itself, this would prevent
1168 # We cannot normalize abstarget itself, this would prevent
1170 # case only renames, like a => A.
1169 # case only renames, like a => A.
1171 abspath, absname = abstarget.rsplit('/', 1)
1170 abspath, absname = abstarget.rsplit('/', 1)
1172 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
1171 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
1173 reltarget = repo.pathto(abstarget, cwd)
1172 reltarget = repo.pathto(abstarget, cwd)
1174 target = repo.wjoin(abstarget)
1173 target = repo.wjoin(abstarget)
1175 src = repo.wjoin(abssrc)
1174 src = repo.wjoin(abssrc)
1176 state = repo.dirstate[abstarget]
1175 state = repo.dirstate[abstarget]
1177
1176
1178 scmutil.checkportable(ui, abstarget)
1177 scmutil.checkportable(ui, abstarget)
1179
1178
1180 # check for collisions
1179 # check for collisions
1181 prevsrc = targets.get(abstarget)
1180 prevsrc = targets.get(abstarget)
1182 if prevsrc is not None:
1181 if prevsrc is not None:
1183 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
1182 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
1184 (reltarget, repo.pathto(abssrc, cwd),
1183 (reltarget, repo.pathto(abssrc, cwd),
1185 repo.pathto(prevsrc, cwd)))
1184 repo.pathto(prevsrc, cwd)))
1186 return True # report a failure
1185 return True # report a failure
1187
1186
1188 # check for overwrites
1187 # check for overwrites
1189 exists = os.path.lexists(target)
1188 exists = os.path.lexists(target)
1190 samefile = False
1189 samefile = False
1191 if exists and abssrc != abstarget:
1190 if exists and abssrc != abstarget:
1192 if (repo.dirstate.normalize(abssrc) ==
1191 if (repo.dirstate.normalize(abssrc) ==
1193 repo.dirstate.normalize(abstarget)):
1192 repo.dirstate.normalize(abstarget)):
1194 if not rename:
1193 if not rename:
1195 ui.warn(_("%s: can't copy - same file\n") % reltarget)
1194 ui.warn(_("%s: can't copy - same file\n") % reltarget)
1196 return True # report a failure
1195 return True # report a failure
1197 exists = False
1196 exists = False
1198 samefile = True
1197 samefile = True
1199
1198
1200 if not after and exists or after and state in 'mn':
1199 if not after and exists or after and state in 'mn':
1201 if not opts['force']:
1200 if not opts['force']:
1202 if state in 'mn':
1201 if state in 'mn':
1203 msg = _('%s: not overwriting - file already committed\n')
1202 msg = _('%s: not overwriting - file already committed\n')
1204 if after:
1203 if after:
1205 flags = '--after --force'
1204 flags = '--after --force'
1206 else:
1205 else:
1207 flags = '--force'
1206 flags = '--force'
1208 if rename:
1207 if rename:
1209 hint = _("('hg rename %s' to replace the file by "
1208 hint = _("('hg rename %s' to replace the file by "
1210 'recording a rename)\n') % flags
1209 'recording a rename)\n') % flags
1211 else:
1210 else:
1212 hint = _("('hg copy %s' to replace the file by "
1211 hint = _("('hg copy %s' to replace the file by "
1213 'recording a copy)\n') % flags
1212 'recording a copy)\n') % flags
1214 else:
1213 else:
1215 msg = _('%s: not overwriting - file exists\n')
1214 msg = _('%s: not overwriting - file exists\n')
1216 if rename:
1215 if rename:
1217 hint = _("('hg rename --after' to record the rename)\n")
1216 hint = _("('hg rename --after' to record the rename)\n")
1218 else:
1217 else:
1219 hint = _("('hg copy --after' to record the copy)\n")
1218 hint = _("('hg copy --after' to record the copy)\n")
1220 ui.warn(msg % reltarget)
1219 ui.warn(msg % reltarget)
1221 ui.warn(hint)
1220 ui.warn(hint)
1222 return True # report a failure
1221 return True # report a failure
1223
1222
1224 if after:
1223 if after:
1225 if not exists:
1224 if not exists:
1226 if rename:
1225 if rename:
1227 ui.warn(_('%s: not recording move - %s does not exist\n') %
1226 ui.warn(_('%s: not recording move - %s does not exist\n') %
1228 (relsrc, reltarget))
1227 (relsrc, reltarget))
1229 else:
1228 else:
1230 ui.warn(_('%s: not recording copy - %s does not exist\n') %
1229 ui.warn(_('%s: not recording copy - %s does not exist\n') %
1231 (relsrc, reltarget))
1230 (relsrc, reltarget))
1232 return True # report a failure
1231 return True # report a failure
1233 elif not dryrun:
1232 elif not dryrun:
1234 try:
1233 try:
1235 if exists:
1234 if exists:
1236 os.unlink(target)
1235 os.unlink(target)
1237 targetdir = os.path.dirname(target) or '.'
1236 targetdir = os.path.dirname(target) or '.'
1238 if not os.path.isdir(targetdir):
1237 if not os.path.isdir(targetdir):
1239 os.makedirs(targetdir)
1238 os.makedirs(targetdir)
1240 if samefile:
1239 if samefile:
1241 tmp = target + "~hgrename"
1240 tmp = target + "~hgrename"
1242 os.rename(src, tmp)
1241 os.rename(src, tmp)
1243 os.rename(tmp, target)
1242 os.rename(tmp, target)
1244 else:
1243 else:
1245 # Preserve stat info on renames, not on copies; this matches
1244 # Preserve stat info on renames, not on copies; this matches
1246 # Linux CLI behavior.
1245 # Linux CLI behavior.
1247 util.copyfile(src, target, copystat=rename)
1246 util.copyfile(src, target, copystat=rename)
1248 srcexists = True
1247 srcexists = True
1249 except IOError as inst:
1248 except IOError as inst:
1250 if inst.errno == errno.ENOENT:
1249 if inst.errno == errno.ENOENT:
1251 ui.warn(_('%s: deleted in working directory\n') % relsrc)
1250 ui.warn(_('%s: deleted in working directory\n') % relsrc)
1252 srcexists = False
1251 srcexists = False
1253 else:
1252 else:
1254 ui.warn(_('%s: cannot copy - %s\n') %
1253 ui.warn(_('%s: cannot copy - %s\n') %
1255 (relsrc, encoding.strtolocal(inst.strerror)))
1254 (relsrc, encoding.strtolocal(inst.strerror)))
1256 if rename:
1255 if rename:
1257 hint = _("('hg rename --after' to record the rename)\n")
1256 hint = _("('hg rename --after' to record the rename)\n")
1258 else:
1257 else:
1259 hint = _("('hg copy --after' to record the copy)\n")
1258 hint = _("('hg copy --after' to record the copy)\n")
1260 return True # report a failure
1259 return True # report a failure
1261
1260
1262 if ui.verbose or not exact:
1261 if ui.verbose or not exact:
1263 if rename:
1262 if rename:
1264 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
1263 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
1265 else:
1264 else:
1266 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
1265 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
1267
1266
1268 targets[abstarget] = abssrc
1267 targets[abstarget] = abssrc
1269
1268
1270 # fix up dirstate
1269 # fix up dirstate
1271 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
1270 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
1272 dryrun=dryrun, cwd=cwd)
1271 dryrun=dryrun, cwd=cwd)
1273 if rename and not dryrun:
1272 if rename and not dryrun:
1274 if not after and srcexists and not samefile:
1273 if not after and srcexists and not samefile:
1275 rmdir = repo.ui.configbool('experimental', 'removeemptydirs')
1274 rmdir = repo.ui.configbool('experimental', 'removeemptydirs')
1276 repo.wvfs.unlinkpath(abssrc, rmdir=rmdir)
1275 repo.wvfs.unlinkpath(abssrc, rmdir=rmdir)
1277 wctx.forget([abssrc])
1276 wctx.forget([abssrc])
1278
1277
1279 # pat: ossep
1278 # pat: ossep
1280 # dest ossep
1279 # dest ossep
1281 # srcs: list of (hgsep, hgsep, ossep, bool)
1280 # srcs: list of (hgsep, hgsep, ossep, bool)
1282 # return: function that takes hgsep and returns ossep
1281 # return: function that takes hgsep and returns ossep
1283 def targetpathfn(pat, dest, srcs):
1282 def targetpathfn(pat, dest, srcs):
1284 if os.path.isdir(pat):
1283 if os.path.isdir(pat):
1285 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1284 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1286 abspfx = util.localpath(abspfx)
1285 abspfx = util.localpath(abspfx)
1287 if destdirexists:
1286 if destdirexists:
1288 striplen = len(os.path.split(abspfx)[0])
1287 striplen = len(os.path.split(abspfx)[0])
1289 else:
1288 else:
1290 striplen = len(abspfx)
1289 striplen = len(abspfx)
1291 if striplen:
1290 if striplen:
1292 striplen += len(pycompat.ossep)
1291 striplen += len(pycompat.ossep)
1293 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
1292 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
1294 elif destdirexists:
1293 elif destdirexists:
1295 res = lambda p: os.path.join(dest,
1294 res = lambda p: os.path.join(dest,
1296 os.path.basename(util.localpath(p)))
1295 os.path.basename(util.localpath(p)))
1297 else:
1296 else:
1298 res = lambda p: dest
1297 res = lambda p: dest
1299 return res
1298 return res
1300
1299
1301 # pat: ossep
1300 # pat: ossep
1302 # dest ossep
1301 # dest ossep
1303 # srcs: list of (hgsep, hgsep, ossep, bool)
1302 # srcs: list of (hgsep, hgsep, ossep, bool)
1304 # return: function that takes hgsep and returns ossep
1303 # return: function that takes hgsep and returns ossep
1305 def targetpathafterfn(pat, dest, srcs):
1304 def targetpathafterfn(pat, dest, srcs):
1306 if matchmod.patkind(pat):
1305 if matchmod.patkind(pat):
1307 # a mercurial pattern
1306 # a mercurial pattern
1308 res = lambda p: os.path.join(dest,
1307 res = lambda p: os.path.join(dest,
1309 os.path.basename(util.localpath(p)))
1308 os.path.basename(util.localpath(p)))
1310 else:
1309 else:
1311 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1310 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1312 if len(abspfx) < len(srcs[0][0]):
1311 if len(abspfx) < len(srcs[0][0]):
1313 # A directory. Either the target path contains the last
1312 # A directory. Either the target path contains the last
1314 # component of the source path or it does not.
1313 # component of the source path or it does not.
1315 def evalpath(striplen):
1314 def evalpath(striplen):
1316 score = 0
1315 score = 0
1317 for s in srcs:
1316 for s in srcs:
1318 t = os.path.join(dest, util.localpath(s[0])[striplen:])
1317 t = os.path.join(dest, util.localpath(s[0])[striplen:])
1319 if os.path.lexists(t):
1318 if os.path.lexists(t):
1320 score += 1
1319 score += 1
1321 return score
1320 return score
1322
1321
1323 abspfx = util.localpath(abspfx)
1322 abspfx = util.localpath(abspfx)
1324 striplen = len(abspfx)
1323 striplen = len(abspfx)
1325 if striplen:
1324 if striplen:
1326 striplen += len(pycompat.ossep)
1325 striplen += len(pycompat.ossep)
1327 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
1326 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
1328 score = evalpath(striplen)
1327 score = evalpath(striplen)
1329 striplen1 = len(os.path.split(abspfx)[0])
1328 striplen1 = len(os.path.split(abspfx)[0])
1330 if striplen1:
1329 if striplen1:
1331 striplen1 += len(pycompat.ossep)
1330 striplen1 += len(pycompat.ossep)
1332 if evalpath(striplen1) > score:
1331 if evalpath(striplen1) > score:
1333 striplen = striplen1
1332 striplen = striplen1
1334 res = lambda p: os.path.join(dest,
1333 res = lambda p: os.path.join(dest,
1335 util.localpath(p)[striplen:])
1334 util.localpath(p)[striplen:])
1336 else:
1335 else:
1337 # a file
1336 # a file
1338 if destdirexists:
1337 if destdirexists:
1339 res = lambda p: os.path.join(dest,
1338 res = lambda p: os.path.join(dest,
1340 os.path.basename(util.localpath(p)))
1339 os.path.basename(util.localpath(p)))
1341 else:
1340 else:
1342 res = lambda p: dest
1341 res = lambda p: dest
1343 return res
1342 return res
1344
1343
1345 pats = scmutil.expandpats(pats)
1344 pats = scmutil.expandpats(pats)
1346 if not pats:
1345 if not pats:
1347 raise error.Abort(_('no source or destination specified'))
1346 raise error.Abort(_('no source or destination specified'))
1348 if len(pats) == 1:
1347 if len(pats) == 1:
1349 raise error.Abort(_('no destination specified'))
1348 raise error.Abort(_('no destination specified'))
1350 dest = pats.pop()
1349 dest = pats.pop()
1351 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
1350 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
1352 if not destdirexists:
1351 if not destdirexists:
1353 if len(pats) > 1 or matchmod.patkind(pats[0]):
1352 if len(pats) > 1 or matchmod.patkind(pats[0]):
1354 raise error.Abort(_('with multiple sources, destination must be an '
1353 raise error.Abort(_('with multiple sources, destination must be an '
1355 'existing directory'))
1354 'existing directory'))
1356 if util.endswithsep(dest):
1355 if util.endswithsep(dest):
1357 raise error.Abort(_('destination %s is not a directory') % dest)
1356 raise error.Abort(_('destination %s is not a directory') % dest)
1358
1357
1359 tfn = targetpathfn
1358 tfn = targetpathfn
1360 if after:
1359 if after:
1361 tfn = targetpathafterfn
1360 tfn = targetpathafterfn
1362 copylist = []
1361 copylist = []
1363 for pat in pats:
1362 for pat in pats:
1364 srcs = walkpat(pat)
1363 srcs = walkpat(pat)
1365 if not srcs:
1364 if not srcs:
1366 continue
1365 continue
1367 copylist.append((tfn(pat, dest, srcs), srcs))
1366 copylist.append((tfn(pat, dest, srcs), srcs))
1368 if not copylist:
1367 if not copylist:
1369 raise error.Abort(_('no files to copy'))
1368 raise error.Abort(_('no files to copy'))
1370
1369
1371 errors = 0
1370 errors = 0
1372 for targetpath, srcs in copylist:
1371 for targetpath, srcs in copylist:
1373 for abssrc, relsrc, exact in srcs:
1372 for abssrc, relsrc, exact in srcs:
1374 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
1373 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
1375 errors += 1
1374 errors += 1
1376
1375
1377 return errors != 0
1376 return errors != 0
1378
1377
1379 ## facility to let extension process additional data into an import patch
1378 ## facility to let extension process additional data into an import patch
1380 # list of identifier to be executed in order
1379 # list of identifier to be executed in order
1381 extrapreimport = [] # run before commit
1380 extrapreimport = [] # run before commit
1382 extrapostimport = [] # run after commit
1381 extrapostimport = [] # run after commit
1383 # mapping from identifier to actual import function
1382 # mapping from identifier to actual import function
1384 #
1383 #
1385 # 'preimport' are run before the commit is made and are provided the following
1384 # 'preimport' are run before the commit is made and are provided the following
1386 # arguments:
1385 # arguments:
1387 # - repo: the localrepository instance,
1386 # - repo: the localrepository instance,
1388 # - patchdata: data extracted from patch header (cf m.patch.patchheadermap),
1387 # - patchdata: data extracted from patch header (cf m.patch.patchheadermap),
1389 # - extra: the future extra dictionary of the changeset, please mutate it,
1388 # - extra: the future extra dictionary of the changeset, please mutate it,
1390 # - opts: the import options.
1389 # - opts: the import options.
1391 # XXX ideally, we would just pass an ctx ready to be computed, that would allow
1390 # XXX ideally, we would just pass an ctx ready to be computed, that would allow
1392 # mutation of in memory commit and more. Feel free to rework the code to get
1391 # mutation of in memory commit and more. Feel free to rework the code to get
1393 # there.
1392 # there.
1394 extrapreimportmap = {}
1393 extrapreimportmap = {}
1395 # 'postimport' are run after the commit is made and are provided the following
1394 # 'postimport' are run after the commit is made and are provided the following
1396 # argument:
1395 # argument:
1397 # - ctx: the changectx created by import.
1396 # - ctx: the changectx created by import.
1398 extrapostimportmap = {}
1397 extrapostimportmap = {}
1399
1398
1400 def tryimportone(ui, repo, patchdata, parents, opts, msgs, updatefunc):
1399 def tryimportone(ui, repo, patchdata, parents, opts, msgs, updatefunc):
1401 """Utility function used by commands.import to import a single patch
1400 """Utility function used by commands.import to import a single patch
1402
1401
1403 This function is explicitly defined here to help the evolve extension to
1402 This function is explicitly defined here to help the evolve extension to
1404 wrap this part of the import logic.
1403 wrap this part of the import logic.
1405
1404
1406 The API is currently a bit ugly because it a simple code translation from
1405 The API is currently a bit ugly because it a simple code translation from
1407 the import command. Feel free to make it better.
1406 the import command. Feel free to make it better.
1408
1407
1409 :patchdata: a dictionary containing parsed patch data (such as from
1408 :patchdata: a dictionary containing parsed patch data (such as from
1410 ``patch.extract()``)
1409 ``patch.extract()``)
1411 :parents: nodes that will be parent of the created commit
1410 :parents: nodes that will be parent of the created commit
1412 :opts: the full dict of option passed to the import command
1411 :opts: the full dict of option passed to the import command
1413 :msgs: list to save commit message to.
1412 :msgs: list to save commit message to.
1414 (used in case we need to save it when failing)
1413 (used in case we need to save it when failing)
1415 :updatefunc: a function that update a repo to a given node
1414 :updatefunc: a function that update a repo to a given node
1416 updatefunc(<repo>, <node>)
1415 updatefunc(<repo>, <node>)
1417 """
1416 """
1418 # avoid cycle context -> subrepo -> cmdutil
1417 # avoid cycle context -> subrepo -> cmdutil
1419 from . import context
1418 from . import context
1420
1419
1421 tmpname = patchdata.get('filename')
1420 tmpname = patchdata.get('filename')
1422 message = patchdata.get('message')
1421 message = patchdata.get('message')
1423 user = opts.get('user') or patchdata.get('user')
1422 user = opts.get('user') or patchdata.get('user')
1424 date = opts.get('date') or patchdata.get('date')
1423 date = opts.get('date') or patchdata.get('date')
1425 branch = patchdata.get('branch')
1424 branch = patchdata.get('branch')
1426 nodeid = patchdata.get('nodeid')
1425 nodeid = patchdata.get('nodeid')
1427 p1 = patchdata.get('p1')
1426 p1 = patchdata.get('p1')
1428 p2 = patchdata.get('p2')
1427 p2 = patchdata.get('p2')
1429
1428
1430 nocommit = opts.get('no_commit')
1429 nocommit = opts.get('no_commit')
1431 importbranch = opts.get('import_branch')
1430 importbranch = opts.get('import_branch')
1432 update = not opts.get('bypass')
1431 update = not opts.get('bypass')
1433 strip = opts["strip"]
1432 strip = opts["strip"]
1434 prefix = opts["prefix"]
1433 prefix = opts["prefix"]
1435 sim = float(opts.get('similarity') or 0)
1434 sim = float(opts.get('similarity') or 0)
1436
1435
1437 if not tmpname:
1436 if not tmpname:
1438 return None, None, False
1437 return None, None, False
1439
1438
1440 rejects = False
1439 rejects = False
1441
1440
1442 cmdline_message = logmessage(ui, opts)
1441 cmdline_message = logmessage(ui, opts)
1443 if cmdline_message:
1442 if cmdline_message:
1444 # pickup the cmdline msg
1443 # pickup the cmdline msg
1445 message = cmdline_message
1444 message = cmdline_message
1446 elif message:
1445 elif message:
1447 # pickup the patch msg
1446 # pickup the patch msg
1448 message = message.strip()
1447 message = message.strip()
1449 else:
1448 else:
1450 # launch the editor
1449 # launch the editor
1451 message = None
1450 message = None
1452 ui.debug('message:\n%s\n' % (message or ''))
1451 ui.debug('message:\n%s\n' % (message or ''))
1453
1452
1454 if len(parents) == 1:
1453 if len(parents) == 1:
1455 parents.append(repo[nullid])
1454 parents.append(repo[nullid])
1456 if opts.get('exact'):
1455 if opts.get('exact'):
1457 if not nodeid or not p1:
1456 if not nodeid or not p1:
1458 raise error.Abort(_('not a Mercurial patch'))
1457 raise error.Abort(_('not a Mercurial patch'))
1459 p1 = repo[p1]
1458 p1 = repo[p1]
1460 p2 = repo[p2 or nullid]
1459 p2 = repo[p2 or nullid]
1461 elif p2:
1460 elif p2:
1462 try:
1461 try:
1463 p1 = repo[p1]
1462 p1 = repo[p1]
1464 p2 = repo[p2]
1463 p2 = repo[p2]
1465 # Without any options, consider p2 only if the
1464 # Without any options, consider p2 only if the
1466 # patch is being applied on top of the recorded
1465 # patch is being applied on top of the recorded
1467 # first parent.
1466 # first parent.
1468 if p1 != parents[0]:
1467 if p1 != parents[0]:
1469 p1 = parents[0]
1468 p1 = parents[0]
1470 p2 = repo[nullid]
1469 p2 = repo[nullid]
1471 except error.RepoError:
1470 except error.RepoError:
1472 p1, p2 = parents
1471 p1, p2 = parents
1473 if p2.node() == nullid:
1472 if p2.node() == nullid:
1474 ui.warn(_("warning: import the patch as a normal revision\n"
1473 ui.warn(_("warning: import the patch as a normal revision\n"
1475 "(use --exact to import the patch as a merge)\n"))
1474 "(use --exact to import the patch as a merge)\n"))
1476 else:
1475 else:
1477 p1, p2 = parents
1476 p1, p2 = parents
1478
1477
1479 n = None
1478 n = None
1480 if update:
1479 if update:
1481 if p1 != parents[0]:
1480 if p1 != parents[0]:
1482 updatefunc(repo, p1.node())
1481 updatefunc(repo, p1.node())
1483 if p2 != parents[1]:
1482 if p2 != parents[1]:
1484 repo.setparents(p1.node(), p2.node())
1483 repo.setparents(p1.node(), p2.node())
1485
1484
1486 if opts.get('exact') or importbranch:
1485 if opts.get('exact') or importbranch:
1487 repo.dirstate.setbranch(branch or 'default')
1486 repo.dirstate.setbranch(branch or 'default')
1488
1487
1489 partial = opts.get('partial', False)
1488 partial = opts.get('partial', False)
1490 files = set()
1489 files = set()
1491 try:
1490 try:
1492 patch.patch(ui, repo, tmpname, strip=strip, prefix=prefix,
1491 patch.patch(ui, repo, tmpname, strip=strip, prefix=prefix,
1493 files=files, eolmode=None, similarity=sim / 100.0)
1492 files=files, eolmode=None, similarity=sim / 100.0)
1494 except error.PatchError as e:
1493 except error.PatchError as e:
1495 if not partial:
1494 if not partial:
1496 raise error.Abort(pycompat.bytestr(e))
1495 raise error.Abort(pycompat.bytestr(e))
1497 if partial:
1496 if partial:
1498 rejects = True
1497 rejects = True
1499
1498
1500 files = list(files)
1499 files = list(files)
1501 if nocommit:
1500 if nocommit:
1502 if message:
1501 if message:
1503 msgs.append(message)
1502 msgs.append(message)
1504 else:
1503 else:
1505 if opts.get('exact') or p2:
1504 if opts.get('exact') or p2:
1506 # If you got here, you either use --force and know what
1505 # If you got here, you either use --force and know what
1507 # you are doing or used --exact or a merge patch while
1506 # you are doing or used --exact or a merge patch while
1508 # being updated to its first parent.
1507 # being updated to its first parent.
1509 m = None
1508 m = None
1510 else:
1509 else:
1511 m = scmutil.matchfiles(repo, files or [])
1510 m = scmutil.matchfiles(repo, files or [])
1512 editform = mergeeditform(repo[None], 'import.normal')
1511 editform = mergeeditform(repo[None], 'import.normal')
1513 if opts.get('exact'):
1512 if opts.get('exact'):
1514 editor = None
1513 editor = None
1515 else:
1514 else:
1516 editor = getcommiteditor(editform=editform,
1515 editor = getcommiteditor(editform=editform,
1517 **pycompat.strkwargs(opts))
1516 **pycompat.strkwargs(opts))
1518 extra = {}
1517 extra = {}
1519 for idfunc in extrapreimport:
1518 for idfunc in extrapreimport:
1520 extrapreimportmap[idfunc](repo, patchdata, extra, opts)
1519 extrapreimportmap[idfunc](repo, patchdata, extra, opts)
1521 overrides = {}
1520 overrides = {}
1522 if partial:
1521 if partial:
1523 overrides[('ui', 'allowemptycommit')] = True
1522 overrides[('ui', 'allowemptycommit')] = True
1524 with repo.ui.configoverride(overrides, 'import'):
1523 with repo.ui.configoverride(overrides, 'import'):
1525 n = repo.commit(message, user,
1524 n = repo.commit(message, user,
1526 date, match=m,
1525 date, match=m,
1527 editor=editor, extra=extra)
1526 editor=editor, extra=extra)
1528 for idfunc in extrapostimport:
1527 for idfunc in extrapostimport:
1529 extrapostimportmap[idfunc](repo[n])
1528 extrapostimportmap[idfunc](repo[n])
1530 else:
1529 else:
1531 if opts.get('exact') or importbranch:
1530 if opts.get('exact') or importbranch:
1532 branch = branch or 'default'
1531 branch = branch or 'default'
1533 else:
1532 else:
1534 branch = p1.branch()
1533 branch = p1.branch()
1535 store = patch.filestore()
1534 store = patch.filestore()
1536 try:
1535 try:
1537 files = set()
1536 files = set()
1538 try:
1537 try:
1539 patch.patchrepo(ui, repo, p1, store, tmpname, strip, prefix,
1538 patch.patchrepo(ui, repo, p1, store, tmpname, strip, prefix,
1540 files, eolmode=None)
1539 files, eolmode=None)
1541 except error.PatchError as e:
1540 except error.PatchError as e:
1542 raise error.Abort(stringutil.forcebytestr(e))
1541 raise error.Abort(stringutil.forcebytestr(e))
1543 if opts.get('exact'):
1542 if opts.get('exact'):
1544 editor = None
1543 editor = None
1545 else:
1544 else:
1546 editor = getcommiteditor(editform='import.bypass')
1545 editor = getcommiteditor(editform='import.bypass')
1547 memctx = context.memctx(repo, (p1.node(), p2.node()),
1546 memctx = context.memctx(repo, (p1.node(), p2.node()),
1548 message,
1547 message,
1549 files=files,
1548 files=files,
1550 filectxfn=store,
1549 filectxfn=store,
1551 user=user,
1550 user=user,
1552 date=date,
1551 date=date,
1553 branch=branch,
1552 branch=branch,
1554 editor=editor)
1553 editor=editor)
1555 n = memctx.commit()
1554 n = memctx.commit()
1556 finally:
1555 finally:
1557 store.close()
1556 store.close()
1558 if opts.get('exact') and nocommit:
1557 if opts.get('exact') and nocommit:
1559 # --exact with --no-commit is still useful in that it does merge
1558 # --exact with --no-commit is still useful in that it does merge
1560 # and branch bits
1559 # and branch bits
1561 ui.warn(_("warning: can't check exact import with --no-commit\n"))
1560 ui.warn(_("warning: can't check exact import with --no-commit\n"))
1562 elif opts.get('exact') and (not n or hex(n) != nodeid):
1561 elif opts.get('exact') and (not n or hex(n) != nodeid):
1563 raise error.Abort(_('patch is damaged or loses information'))
1562 raise error.Abort(_('patch is damaged or loses information'))
1564 msg = _('applied to working directory')
1563 msg = _('applied to working directory')
1565 if n:
1564 if n:
1566 # i18n: refers to a short changeset id
1565 # i18n: refers to a short changeset id
1567 msg = _('created %s') % short(n)
1566 msg = _('created %s') % short(n)
1568 return msg, n, rejects
1567 return msg, n, rejects
1569
1568
1570 # facility to let extensions include additional data in an exported patch
1569 # facility to let extensions include additional data in an exported patch
1571 # list of identifiers to be executed in order
1570 # list of identifiers to be executed in order
1572 extraexport = []
1571 extraexport = []
1573 # mapping from identifier to actual export function
1572 # mapping from identifier to actual export function
1574 # function as to return a string to be added to the header or None
1573 # function as to return a string to be added to the header or None
1575 # it is given two arguments (sequencenumber, changectx)
1574 # it is given two arguments (sequencenumber, changectx)
1576 extraexportmap = {}
1575 extraexportmap = {}
1577
1576
1578 def _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts):
1577 def _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts):
1579 node = scmutil.binnode(ctx)
1578 node = scmutil.binnode(ctx)
1580 parents = [p.node() for p in ctx.parents() if p]
1579 parents = [p.node() for p in ctx.parents() if p]
1581 branch = ctx.branch()
1580 branch = ctx.branch()
1582 if switch_parent:
1581 if switch_parent:
1583 parents.reverse()
1582 parents.reverse()
1584
1583
1585 if parents:
1584 if parents:
1586 prev = parents[0]
1585 prev = parents[0]
1587 else:
1586 else:
1588 prev = nullid
1587 prev = nullid
1589
1588
1590 fm.context(ctx=ctx)
1589 fm.context(ctx=ctx)
1591 fm.plain('# HG changeset patch\n')
1590 fm.plain('# HG changeset patch\n')
1592 fm.write('user', '# User %s\n', ctx.user())
1591 fm.write('user', '# User %s\n', ctx.user())
1593 fm.plain('# Date %d %d\n' % ctx.date())
1592 fm.plain('# Date %d %d\n' % ctx.date())
1594 fm.write('date', '# %s\n', fm.formatdate(ctx.date()))
1593 fm.write('date', '# %s\n', fm.formatdate(ctx.date()))
1595 fm.condwrite(branch and branch != 'default',
1594 fm.condwrite(branch and branch != 'default',
1596 'branch', '# Branch %s\n', branch)
1595 'branch', '# Branch %s\n', branch)
1597 fm.write('node', '# Node ID %s\n', hex(node))
1596 fm.write('node', '# Node ID %s\n', hex(node))
1598 fm.plain('# Parent %s\n' % hex(prev))
1597 fm.plain('# Parent %s\n' % hex(prev))
1599 if len(parents) > 1:
1598 if len(parents) > 1:
1600 fm.plain('# Parent %s\n' % hex(parents[1]))
1599 fm.plain('# Parent %s\n' % hex(parents[1]))
1601 fm.data(parents=fm.formatlist(pycompat.maplist(hex, parents), name='node'))
1600 fm.data(parents=fm.formatlist(pycompat.maplist(hex, parents), name='node'))
1602
1601
1603 # TODO: redesign extraexportmap function to support formatter
1602 # TODO: redesign extraexportmap function to support formatter
1604 for headerid in extraexport:
1603 for headerid in extraexport:
1605 header = extraexportmap[headerid](seqno, ctx)
1604 header = extraexportmap[headerid](seqno, ctx)
1606 if header is not None:
1605 if header is not None:
1607 fm.plain('# %s\n' % header)
1606 fm.plain('# %s\n' % header)
1608
1607
1609 fm.write('desc', '%s\n', ctx.description().rstrip())
1608 fm.write('desc', '%s\n', ctx.description().rstrip())
1610 fm.plain('\n')
1609 fm.plain('\n')
1611
1610
1612 if fm.isplain():
1611 if fm.isplain():
1613 chunkiter = patch.diffui(repo, prev, node, match, opts=diffopts)
1612 chunkiter = patch.diffui(repo, prev, node, match, opts=diffopts)
1614 for chunk, label in chunkiter:
1613 for chunk, label in chunkiter:
1615 fm.plain(chunk, label=label)
1614 fm.plain(chunk, label=label)
1616 else:
1615 else:
1617 chunkiter = patch.diff(repo, prev, node, match, opts=diffopts)
1616 chunkiter = patch.diff(repo, prev, node, match, opts=diffopts)
1618 # TODO: make it structured?
1617 # TODO: make it structured?
1619 fm.data(diff=b''.join(chunkiter))
1618 fm.data(diff=b''.join(chunkiter))
1620
1619
1621 def _exportfile(repo, revs, fm, dest, switch_parent, diffopts, match):
1620 def _exportfile(repo, revs, fm, dest, switch_parent, diffopts, match):
1622 """Export changesets to stdout or a single file"""
1621 """Export changesets to stdout or a single file"""
1623 for seqno, rev in enumerate(revs, 1):
1622 for seqno, rev in enumerate(revs, 1):
1624 ctx = repo[rev]
1623 ctx = repo[rev]
1625 if not dest.startswith('<'):
1624 if not dest.startswith('<'):
1626 repo.ui.note("%s\n" % dest)
1625 repo.ui.note("%s\n" % dest)
1627 fm.startitem()
1626 fm.startitem()
1628 _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts)
1627 _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts)
1629
1628
1630 def _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, diffopts,
1629 def _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, diffopts,
1631 match):
1630 match):
1632 """Export changesets to possibly multiple files"""
1631 """Export changesets to possibly multiple files"""
1633 total = len(revs)
1632 total = len(revs)
1634 revwidth = max(len(str(rev)) for rev in revs)
1633 revwidth = max(len(str(rev)) for rev in revs)
1635 filemap = util.sortdict() # filename: [(seqno, rev), ...]
1634 filemap = util.sortdict() # filename: [(seqno, rev), ...]
1636
1635
1637 for seqno, rev in enumerate(revs, 1):
1636 for seqno, rev in enumerate(revs, 1):
1638 ctx = repo[rev]
1637 ctx = repo[rev]
1639 dest = makefilename(ctx, fntemplate,
1638 dest = makefilename(ctx, fntemplate,
1640 total=total, seqno=seqno, revwidth=revwidth)
1639 total=total, seqno=seqno, revwidth=revwidth)
1641 filemap.setdefault(dest, []).append((seqno, rev))
1640 filemap.setdefault(dest, []).append((seqno, rev))
1642
1641
1643 for dest in filemap:
1642 for dest in filemap:
1644 with formatter.maybereopen(basefm, dest) as fm:
1643 with formatter.maybereopen(basefm, dest) as fm:
1645 repo.ui.note("%s\n" % dest)
1644 repo.ui.note("%s\n" % dest)
1646 for seqno, rev in filemap[dest]:
1645 for seqno, rev in filemap[dest]:
1647 fm.startitem()
1646 fm.startitem()
1648 ctx = repo[rev]
1647 ctx = repo[rev]
1649 _exportsingle(repo, ctx, fm, match, switch_parent, seqno,
1648 _exportsingle(repo, ctx, fm, match, switch_parent, seqno,
1650 diffopts)
1649 diffopts)
1651
1650
1652 def export(repo, revs, basefm, fntemplate='hg-%h.patch', switch_parent=False,
1651 def export(repo, revs, basefm, fntemplate='hg-%h.patch', switch_parent=False,
1653 opts=None, match=None):
1652 opts=None, match=None):
1654 '''export changesets as hg patches
1653 '''export changesets as hg patches
1655
1654
1656 Args:
1655 Args:
1657 repo: The repository from which we're exporting revisions.
1656 repo: The repository from which we're exporting revisions.
1658 revs: A list of revisions to export as revision numbers.
1657 revs: A list of revisions to export as revision numbers.
1659 basefm: A formatter to which patches should be written.
1658 basefm: A formatter to which patches should be written.
1660 fntemplate: An optional string to use for generating patch file names.
1659 fntemplate: An optional string to use for generating patch file names.
1661 switch_parent: If True, show diffs against second parent when not nullid.
1660 switch_parent: If True, show diffs against second parent when not nullid.
1662 Default is false, which always shows diff against p1.
1661 Default is false, which always shows diff against p1.
1663 opts: diff options to use for generating the patch.
1662 opts: diff options to use for generating the patch.
1664 match: If specified, only export changes to files matching this matcher.
1663 match: If specified, only export changes to files matching this matcher.
1665
1664
1666 Returns:
1665 Returns:
1667 Nothing.
1666 Nothing.
1668
1667
1669 Side Effect:
1668 Side Effect:
1670 "HG Changeset Patch" data is emitted to one of the following
1669 "HG Changeset Patch" data is emitted to one of the following
1671 destinations:
1670 destinations:
1672 fntemplate specified: Each rev is written to a unique file named using
1671 fntemplate specified: Each rev is written to a unique file named using
1673 the given template.
1672 the given template.
1674 Otherwise: All revs will be written to basefm.
1673 Otherwise: All revs will be written to basefm.
1675 '''
1674 '''
1676 scmutil.prefetchfiles(repo, revs, match)
1675 scmutil.prefetchfiles(repo, revs, match)
1677
1676
1678 if not fntemplate:
1677 if not fntemplate:
1679 _exportfile(repo, revs, basefm, '<unnamed>', switch_parent, opts, match)
1678 _exportfile(repo, revs, basefm, '<unnamed>', switch_parent, opts, match)
1680 else:
1679 else:
1681 _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, opts,
1680 _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, opts,
1682 match)
1681 match)
1683
1682
1684 def exportfile(repo, revs, fp, switch_parent=False, opts=None, match=None):
1683 def exportfile(repo, revs, fp, switch_parent=False, opts=None, match=None):
1685 """Export changesets to the given file stream"""
1684 """Export changesets to the given file stream"""
1686 scmutil.prefetchfiles(repo, revs, match)
1685 scmutil.prefetchfiles(repo, revs, match)
1687
1686
1688 dest = getattr(fp, 'name', '<unnamed>')
1687 dest = getattr(fp, 'name', '<unnamed>')
1689 with formatter.formatter(repo.ui, fp, 'export', {}) as fm:
1688 with formatter.formatter(repo.ui, fp, 'export', {}) as fm:
1690 _exportfile(repo, revs, fm, dest, switch_parent, opts, match)
1689 _exportfile(repo, revs, fm, dest, switch_parent, opts, match)
1691
1690
1692 def showmarker(fm, marker, index=None):
1691 def showmarker(fm, marker, index=None):
1693 """utility function to display obsolescence marker in a readable way
1692 """utility function to display obsolescence marker in a readable way
1694
1693
1695 To be used by debug function."""
1694 To be used by debug function."""
1696 if index is not None:
1695 if index is not None:
1697 fm.write('index', '%i ', index)
1696 fm.write('index', '%i ', index)
1698 fm.write('prednode', '%s ', hex(marker.prednode()))
1697 fm.write('prednode', '%s ', hex(marker.prednode()))
1699 succs = marker.succnodes()
1698 succs = marker.succnodes()
1700 fm.condwrite(succs, 'succnodes', '%s ',
1699 fm.condwrite(succs, 'succnodes', '%s ',
1701 fm.formatlist(map(hex, succs), name='node'))
1700 fm.formatlist(map(hex, succs), name='node'))
1702 fm.write('flag', '%X ', marker.flags())
1701 fm.write('flag', '%X ', marker.flags())
1703 parents = marker.parentnodes()
1702 parents = marker.parentnodes()
1704 if parents is not None:
1703 if parents is not None:
1705 fm.write('parentnodes', '{%s} ',
1704 fm.write('parentnodes', '{%s} ',
1706 fm.formatlist(map(hex, parents), name='node', sep=', '))
1705 fm.formatlist(map(hex, parents), name='node', sep=', '))
1707 fm.write('date', '(%s) ', fm.formatdate(marker.date()))
1706 fm.write('date', '(%s) ', fm.formatdate(marker.date()))
1708 meta = marker.metadata().copy()
1707 meta = marker.metadata().copy()
1709 meta.pop('date', None)
1708 meta.pop('date', None)
1710 smeta = pycompat.rapply(pycompat.maybebytestr, meta)
1709 smeta = pycompat.rapply(pycompat.maybebytestr, meta)
1711 fm.write('metadata', '{%s}', fm.formatdict(smeta, fmt='%r: %r', sep=', '))
1710 fm.write('metadata', '{%s}', fm.formatdict(smeta, fmt='%r: %r', sep=', '))
1712 fm.plain('\n')
1711 fm.plain('\n')
1713
1712
1714 def finddate(ui, repo, date):
1713 def finddate(ui, repo, date):
1715 """Find the tipmost changeset that matches the given date spec"""
1714 """Find the tipmost changeset that matches the given date spec"""
1716
1715
1717 df = dateutil.matchdate(date)
1716 df = dateutil.matchdate(date)
1718 m = scmutil.matchall(repo)
1717 m = scmutil.matchall(repo)
1719 results = {}
1718 results = {}
1720
1719
1721 def prep(ctx, fns):
1720 def prep(ctx, fns):
1722 d = ctx.date()
1721 d = ctx.date()
1723 if df(d[0]):
1722 if df(d[0]):
1724 results[ctx.rev()] = d
1723 results[ctx.rev()] = d
1725
1724
1726 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
1725 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
1727 rev = ctx.rev()
1726 rev = ctx.rev()
1728 if rev in results:
1727 if rev in results:
1729 ui.status(_("found revision %s from %s\n") %
1728 ui.status(_("found revision %s from %s\n") %
1730 (rev, dateutil.datestr(results[rev])))
1729 (rev, dateutil.datestr(results[rev])))
1731 return '%d' % rev
1730 return '%d' % rev
1732
1731
1733 raise error.Abort(_("revision matching date not found"))
1732 raise error.Abort(_("revision matching date not found"))
1734
1733
1735 def increasingwindows(windowsize=8, sizelimit=512):
1734 def increasingwindows(windowsize=8, sizelimit=512):
1736 while True:
1735 while True:
1737 yield windowsize
1736 yield windowsize
1738 if windowsize < sizelimit:
1737 if windowsize < sizelimit:
1739 windowsize *= 2
1738 windowsize *= 2
1740
1739
1741 def _walkrevs(repo, opts):
1740 def _walkrevs(repo, opts):
1742 # Default --rev value depends on --follow but --follow behavior
1741 # Default --rev value depends on --follow but --follow behavior
1743 # depends on revisions resolved from --rev...
1742 # depends on revisions resolved from --rev...
1744 follow = opts.get('follow') or opts.get('follow_first')
1743 follow = opts.get('follow') or opts.get('follow_first')
1745 if opts.get('rev'):
1744 if opts.get('rev'):
1746 revs = scmutil.revrange(repo, opts['rev'])
1745 revs = scmutil.revrange(repo, opts['rev'])
1747 elif follow and repo.dirstate.p1() == nullid:
1746 elif follow and repo.dirstate.p1() == nullid:
1748 revs = smartset.baseset()
1747 revs = smartset.baseset()
1749 elif follow:
1748 elif follow:
1750 revs = repo.revs('reverse(:.)')
1749 revs = repo.revs('reverse(:.)')
1751 else:
1750 else:
1752 revs = smartset.spanset(repo)
1751 revs = smartset.spanset(repo)
1753 revs.reverse()
1752 revs.reverse()
1754 return revs
1753 return revs
1755
1754
1756 class FileWalkError(Exception):
1755 class FileWalkError(Exception):
1757 pass
1756 pass
1758
1757
1759 def walkfilerevs(repo, match, follow, revs, fncache):
1758 def walkfilerevs(repo, match, follow, revs, fncache):
1760 '''Walks the file history for the matched files.
1759 '''Walks the file history for the matched files.
1761
1760
1762 Returns the changeset revs that are involved in the file history.
1761 Returns the changeset revs that are involved in the file history.
1763
1762
1764 Throws FileWalkError if the file history can't be walked using
1763 Throws FileWalkError if the file history can't be walked using
1765 filelogs alone.
1764 filelogs alone.
1766 '''
1765 '''
1767 wanted = set()
1766 wanted = set()
1768 copies = []
1767 copies = []
1769 minrev, maxrev = min(revs), max(revs)
1768 minrev, maxrev = min(revs), max(revs)
1770 def filerevgen(filelog, last):
1769 def filerevgen(filelog, last):
1771 """
1770 """
1772 Only files, no patterns. Check the history of each file.
1771 Only files, no patterns. Check the history of each file.
1773
1772
1774 Examines filelog entries within minrev, maxrev linkrev range
1773 Examines filelog entries within minrev, maxrev linkrev range
1775 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1774 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1776 tuples in backwards order
1775 tuples in backwards order
1777 """
1776 """
1778 cl_count = len(repo)
1777 cl_count = len(repo)
1779 revs = []
1778 revs = []
1780 for j in pycompat.xrange(0, last + 1):
1779 for j in pycompat.xrange(0, last + 1):
1781 linkrev = filelog.linkrev(j)
1780 linkrev = filelog.linkrev(j)
1782 if linkrev < minrev:
1781 if linkrev < minrev:
1783 continue
1782 continue
1784 # only yield rev for which we have the changelog, it can
1783 # only yield rev for which we have the changelog, it can
1785 # happen while doing "hg log" during a pull or commit
1784 # happen while doing "hg log" during a pull or commit
1786 if linkrev >= cl_count:
1785 if linkrev >= cl_count:
1787 break
1786 break
1788
1787
1789 parentlinkrevs = []
1788 parentlinkrevs = []
1790 for p in filelog.parentrevs(j):
1789 for p in filelog.parentrevs(j):
1791 if p != nullrev:
1790 if p != nullrev:
1792 parentlinkrevs.append(filelog.linkrev(p))
1791 parentlinkrevs.append(filelog.linkrev(p))
1793 n = filelog.node(j)
1792 n = filelog.node(j)
1794 revs.append((linkrev, parentlinkrevs,
1793 revs.append((linkrev, parentlinkrevs,
1795 follow and filelog.renamed(n)))
1794 follow and filelog.renamed(n)))
1796
1795
1797 return reversed(revs)
1796 return reversed(revs)
1798 def iterfiles():
1797 def iterfiles():
1799 pctx = repo['.']
1798 pctx = repo['.']
1800 for filename in match.files():
1799 for filename in match.files():
1801 if follow:
1800 if follow:
1802 if filename not in pctx:
1801 if filename not in pctx:
1803 raise error.Abort(_('cannot follow file not in parent '
1802 raise error.Abort(_('cannot follow file not in parent '
1804 'revision: "%s"') % filename)
1803 'revision: "%s"') % filename)
1805 yield filename, pctx[filename].filenode()
1804 yield filename, pctx[filename].filenode()
1806 else:
1805 else:
1807 yield filename, None
1806 yield filename, None
1808 for filename_node in copies:
1807 for filename_node in copies:
1809 yield filename_node
1808 yield filename_node
1810
1809
1811 for file_, node in iterfiles():
1810 for file_, node in iterfiles():
1812 filelog = repo.file(file_)
1811 filelog = repo.file(file_)
1813 if not len(filelog):
1812 if not len(filelog):
1814 if node is None:
1813 if node is None:
1815 # A zero count may be a directory or deleted file, so
1814 # A zero count may be a directory or deleted file, so
1816 # try to find matching entries on the slow path.
1815 # try to find matching entries on the slow path.
1817 if follow:
1816 if follow:
1818 raise error.Abort(
1817 raise error.Abort(
1819 _('cannot follow nonexistent file: "%s"') % file_)
1818 _('cannot follow nonexistent file: "%s"') % file_)
1820 raise FileWalkError("Cannot walk via filelog")
1819 raise FileWalkError("Cannot walk via filelog")
1821 else:
1820 else:
1822 continue
1821 continue
1823
1822
1824 if node is None:
1823 if node is None:
1825 last = len(filelog) - 1
1824 last = len(filelog) - 1
1826 else:
1825 else:
1827 last = filelog.rev(node)
1826 last = filelog.rev(node)
1828
1827
1829 # keep track of all ancestors of the file
1828 # keep track of all ancestors of the file
1830 ancestors = {filelog.linkrev(last)}
1829 ancestors = {filelog.linkrev(last)}
1831
1830
1832 # iterate from latest to oldest revision
1831 # iterate from latest to oldest revision
1833 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1832 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1834 if not follow:
1833 if not follow:
1835 if rev > maxrev:
1834 if rev > maxrev:
1836 continue
1835 continue
1837 else:
1836 else:
1838 # Note that last might not be the first interesting
1837 # Note that last might not be the first interesting
1839 # rev to us:
1838 # rev to us:
1840 # if the file has been changed after maxrev, we'll
1839 # if the file has been changed after maxrev, we'll
1841 # have linkrev(last) > maxrev, and we still need
1840 # have linkrev(last) > maxrev, and we still need
1842 # to explore the file graph
1841 # to explore the file graph
1843 if rev not in ancestors:
1842 if rev not in ancestors:
1844 continue
1843 continue
1845 # XXX insert 1327 fix here
1844 # XXX insert 1327 fix here
1846 if flparentlinkrevs:
1845 if flparentlinkrevs:
1847 ancestors.update(flparentlinkrevs)
1846 ancestors.update(flparentlinkrevs)
1848
1847
1849 fncache.setdefault(rev, []).append(file_)
1848 fncache.setdefault(rev, []).append(file_)
1850 wanted.add(rev)
1849 wanted.add(rev)
1851 if copied:
1850 if copied:
1852 copies.append(copied)
1851 copies.append(copied)
1853
1852
1854 return wanted
1853 return wanted
1855
1854
1856 class _followfilter(object):
1855 class _followfilter(object):
1857 def __init__(self, repo, onlyfirst=False):
1856 def __init__(self, repo, onlyfirst=False):
1858 self.repo = repo
1857 self.repo = repo
1859 self.startrev = nullrev
1858 self.startrev = nullrev
1860 self.roots = set()
1859 self.roots = set()
1861 self.onlyfirst = onlyfirst
1860 self.onlyfirst = onlyfirst
1862
1861
1863 def match(self, rev):
1862 def match(self, rev):
1864 def realparents(rev):
1863 def realparents(rev):
1865 if self.onlyfirst:
1864 if self.onlyfirst:
1866 return self.repo.changelog.parentrevs(rev)[0:1]
1865 return self.repo.changelog.parentrevs(rev)[0:1]
1867 else:
1866 else:
1868 return filter(lambda x: x != nullrev,
1867 return filter(lambda x: x != nullrev,
1869 self.repo.changelog.parentrevs(rev))
1868 self.repo.changelog.parentrevs(rev))
1870
1869
1871 if self.startrev == nullrev:
1870 if self.startrev == nullrev:
1872 self.startrev = rev
1871 self.startrev = rev
1873 return True
1872 return True
1874
1873
1875 if rev > self.startrev:
1874 if rev > self.startrev:
1876 # forward: all descendants
1875 # forward: all descendants
1877 if not self.roots:
1876 if not self.roots:
1878 self.roots.add(self.startrev)
1877 self.roots.add(self.startrev)
1879 for parent in realparents(rev):
1878 for parent in realparents(rev):
1880 if parent in self.roots:
1879 if parent in self.roots:
1881 self.roots.add(rev)
1880 self.roots.add(rev)
1882 return True
1881 return True
1883 else:
1882 else:
1884 # backwards: all parents
1883 # backwards: all parents
1885 if not self.roots:
1884 if not self.roots:
1886 self.roots.update(realparents(self.startrev))
1885 self.roots.update(realparents(self.startrev))
1887 if rev in self.roots:
1886 if rev in self.roots:
1888 self.roots.remove(rev)
1887 self.roots.remove(rev)
1889 self.roots.update(realparents(rev))
1888 self.roots.update(realparents(rev))
1890 return True
1889 return True
1891
1890
1892 return False
1891 return False
1893
1892
1894 def walkchangerevs(repo, match, opts, prepare):
1893 def walkchangerevs(repo, match, opts, prepare):
1895 '''Iterate over files and the revs in which they changed.
1894 '''Iterate over files and the revs in which they changed.
1896
1895
1897 Callers most commonly need to iterate backwards over the history
1896 Callers most commonly need to iterate backwards over the history
1898 in which they are interested. Doing so has awful (quadratic-looking)
1897 in which they are interested. Doing so has awful (quadratic-looking)
1899 performance, so we use iterators in a "windowed" way.
1898 performance, so we use iterators in a "windowed" way.
1900
1899
1901 We walk a window of revisions in the desired order. Within the
1900 We walk a window of revisions in the desired order. Within the
1902 window, we first walk forwards to gather data, then in the desired
1901 window, we first walk forwards to gather data, then in the desired
1903 order (usually backwards) to display it.
1902 order (usually backwards) to display it.
1904
1903
1905 This function returns an iterator yielding contexts. Before
1904 This function returns an iterator yielding contexts. Before
1906 yielding each context, the iterator will first call the prepare
1905 yielding each context, the iterator will first call the prepare
1907 function on each context in the window in forward order.'''
1906 function on each context in the window in forward order.'''
1908
1907
1909 allfiles = opts.get('all_files')
1908 allfiles = opts.get('all_files')
1910 follow = opts.get('follow') or opts.get('follow_first')
1909 follow = opts.get('follow') or opts.get('follow_first')
1911 revs = _walkrevs(repo, opts)
1910 revs = _walkrevs(repo, opts)
1912 if not revs:
1911 if not revs:
1913 return []
1912 return []
1914 wanted = set()
1913 wanted = set()
1915 slowpath = match.anypats() or (not match.always() and opts.get('removed'))
1914 slowpath = match.anypats() or (not match.always() and opts.get('removed'))
1916 fncache = {}
1915 fncache = {}
1917 change = repo.__getitem__
1916 change = repo.__getitem__
1918
1917
1919 # First step is to fill wanted, the set of revisions that we want to yield.
1918 # First step is to fill wanted, the set of revisions that we want to yield.
1920 # When it does not induce extra cost, we also fill fncache for revisions in
1919 # When it does not induce extra cost, we also fill fncache for revisions in
1921 # wanted: a cache of filenames that were changed (ctx.files()) and that
1920 # wanted: a cache of filenames that were changed (ctx.files()) and that
1922 # match the file filtering conditions.
1921 # match the file filtering conditions.
1923
1922
1924 if match.always() or allfiles:
1923 if match.always() or allfiles:
1925 # No files, no patterns. Display all revs.
1924 # No files, no patterns. Display all revs.
1926 wanted = revs
1925 wanted = revs
1927 elif not slowpath:
1926 elif not slowpath:
1928 # We only have to read through the filelog to find wanted revisions
1927 # We only have to read through the filelog to find wanted revisions
1929
1928
1930 try:
1929 try:
1931 wanted = walkfilerevs(repo, match, follow, revs, fncache)
1930 wanted = walkfilerevs(repo, match, follow, revs, fncache)
1932 except FileWalkError:
1931 except FileWalkError:
1933 slowpath = True
1932 slowpath = True
1934
1933
1935 # We decided to fall back to the slowpath because at least one
1934 # We decided to fall back to the slowpath because at least one
1936 # of the paths was not a file. Check to see if at least one of them
1935 # of the paths was not a file. Check to see if at least one of them
1937 # existed in history, otherwise simply return
1936 # existed in history, otherwise simply return
1938 for path in match.files():
1937 for path in match.files():
1939 if path == '.' or path in repo.store:
1938 if path == '.' or path in repo.store:
1940 break
1939 break
1941 else:
1940 else:
1942 return []
1941 return []
1943
1942
1944 if slowpath:
1943 if slowpath:
1945 # We have to read the changelog to match filenames against
1944 # We have to read the changelog to match filenames against
1946 # changed files
1945 # changed files
1947
1946
1948 if follow:
1947 if follow:
1949 raise error.Abort(_('can only follow copies/renames for explicit '
1948 raise error.Abort(_('can only follow copies/renames for explicit '
1950 'filenames'))
1949 'filenames'))
1951
1950
1952 # The slow path checks files modified in every changeset.
1951 # The slow path checks files modified in every changeset.
1953 # This is really slow on large repos, so compute the set lazily.
1952 # This is really slow on large repos, so compute the set lazily.
1954 class lazywantedset(object):
1953 class lazywantedset(object):
1955 def __init__(self):
1954 def __init__(self):
1956 self.set = set()
1955 self.set = set()
1957 self.revs = set(revs)
1956 self.revs = set(revs)
1958
1957
1959 # No need to worry about locality here because it will be accessed
1958 # No need to worry about locality here because it will be accessed
1960 # in the same order as the increasing window below.
1959 # in the same order as the increasing window below.
1961 def __contains__(self, value):
1960 def __contains__(self, value):
1962 if value in self.set:
1961 if value in self.set:
1963 return True
1962 return True
1964 elif not value in self.revs:
1963 elif not value in self.revs:
1965 return False
1964 return False
1966 else:
1965 else:
1967 self.revs.discard(value)
1966 self.revs.discard(value)
1968 ctx = change(value)
1967 ctx = change(value)
1969 matches = [f for f in ctx.files() if match(f)]
1968 matches = [f for f in ctx.files() if match(f)]
1970 if matches:
1969 if matches:
1971 fncache[value] = matches
1970 fncache[value] = matches
1972 self.set.add(value)
1971 self.set.add(value)
1973 return True
1972 return True
1974 return False
1973 return False
1975
1974
1976 def discard(self, value):
1975 def discard(self, value):
1977 self.revs.discard(value)
1976 self.revs.discard(value)
1978 self.set.discard(value)
1977 self.set.discard(value)
1979
1978
1980 wanted = lazywantedset()
1979 wanted = lazywantedset()
1981
1980
1982 # it might be worthwhile to do this in the iterator if the rev range
1981 # it might be worthwhile to do this in the iterator if the rev range
1983 # is descending and the prune args are all within that range
1982 # is descending and the prune args are all within that range
1984 for rev in opts.get('prune', ()):
1983 for rev in opts.get('prune', ()):
1985 rev = repo[rev].rev()
1984 rev = repo[rev].rev()
1986 ff = _followfilter(repo)
1985 ff = _followfilter(repo)
1987 stop = min(revs[0], revs[-1])
1986 stop = min(revs[0], revs[-1])
1988 for x in pycompat.xrange(rev, stop - 1, -1):
1987 for x in pycompat.xrange(rev, stop - 1, -1):
1989 if ff.match(x):
1988 if ff.match(x):
1990 wanted = wanted - [x]
1989 wanted = wanted - [x]
1991
1990
1992 # Now that wanted is correctly initialized, we can iterate over the
1991 # Now that wanted is correctly initialized, we can iterate over the
1993 # revision range, yielding only revisions in wanted.
1992 # revision range, yielding only revisions in wanted.
1994 def iterate():
1993 def iterate():
1995 if follow and match.always():
1994 if follow and match.always():
1996 ff = _followfilter(repo, onlyfirst=opts.get('follow_first'))
1995 ff = _followfilter(repo, onlyfirst=opts.get('follow_first'))
1997 def want(rev):
1996 def want(rev):
1998 return ff.match(rev) and rev in wanted
1997 return ff.match(rev) and rev in wanted
1999 else:
1998 else:
2000 def want(rev):
1999 def want(rev):
2001 return rev in wanted
2000 return rev in wanted
2002
2001
2003 it = iter(revs)
2002 it = iter(revs)
2004 stopiteration = False
2003 stopiteration = False
2005 for windowsize in increasingwindows():
2004 for windowsize in increasingwindows():
2006 nrevs = []
2005 nrevs = []
2007 for i in pycompat.xrange(windowsize):
2006 for i in pycompat.xrange(windowsize):
2008 rev = next(it, None)
2007 rev = next(it, None)
2009 if rev is None:
2008 if rev is None:
2010 stopiteration = True
2009 stopiteration = True
2011 break
2010 break
2012 elif want(rev):
2011 elif want(rev):
2013 nrevs.append(rev)
2012 nrevs.append(rev)
2014 for rev in sorted(nrevs):
2013 for rev in sorted(nrevs):
2015 fns = fncache.get(rev)
2014 fns = fncache.get(rev)
2016 ctx = change(rev)
2015 ctx = change(rev)
2017 if not fns:
2016 if not fns:
2018 def fns_generator():
2017 def fns_generator():
2019 if allfiles:
2018 if allfiles:
2020 fiter = iter(ctx)
2019 fiter = iter(ctx)
2021 else:
2020 else:
2022 fiter = ctx.files()
2021 fiter = ctx.files()
2023 for f in fiter:
2022 for f in fiter:
2024 if match(f):
2023 if match(f):
2025 yield f
2024 yield f
2026 fns = fns_generator()
2025 fns = fns_generator()
2027 prepare(ctx, fns)
2026 prepare(ctx, fns)
2028 for rev in nrevs:
2027 for rev in nrevs:
2029 yield change(rev)
2028 yield change(rev)
2030
2029
2031 if stopiteration:
2030 if stopiteration:
2032 break
2031 break
2033
2032
2034 return iterate()
2033 return iterate()
2035
2034
2036 def add(ui, repo, match, prefix, explicitonly, **opts):
2035 def add(ui, repo, match, prefix, explicitonly, **opts):
2037 join = lambda f: os.path.join(prefix, f)
2036 join = lambda f: os.path.join(prefix, f)
2038 bad = []
2037 bad = []
2039
2038
2040 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2039 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2041 names = []
2040 names = []
2042 wctx = repo[None]
2041 wctx = repo[None]
2043 cca = None
2042 cca = None
2044 abort, warn = scmutil.checkportabilityalert(ui)
2043 abort, warn = scmutil.checkportabilityalert(ui)
2045 if abort or warn:
2044 if abort or warn:
2046 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
2045 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
2047
2046
2048 badmatch = matchmod.badmatch(match, badfn)
2047 badmatch = matchmod.badmatch(match, badfn)
2049 dirstate = repo.dirstate
2048 dirstate = repo.dirstate
2050 # We don't want to just call wctx.walk here, since it would return a lot of
2049 # We don't want to just call wctx.walk here, since it would return a lot of
2051 # clean files, which we aren't interested in and takes time.
2050 # clean files, which we aren't interested in and takes time.
2052 for f in sorted(dirstate.walk(badmatch, subrepos=sorted(wctx.substate),
2051 for f in sorted(dirstate.walk(badmatch, subrepos=sorted(wctx.substate),
2053 unknown=True, ignored=False, full=False)):
2052 unknown=True, ignored=False, full=False)):
2054 exact = match.exact(f)
2053 exact = match.exact(f)
2055 if exact or not explicitonly and f not in wctx and repo.wvfs.lexists(f):
2054 if exact or not explicitonly and f not in wctx and repo.wvfs.lexists(f):
2056 if cca:
2055 if cca:
2057 cca(f)
2056 cca(f)
2058 names.append(f)
2057 names.append(f)
2059 if ui.verbose or not exact:
2058 if ui.verbose or not exact:
2060 ui.status(_('adding %s\n') % match.rel(f),
2059 ui.status(_('adding %s\n') % match.rel(f),
2061 label='addremove.added')
2060 label='addremove.added')
2062
2061
2063 for subpath in sorted(wctx.substate):
2062 for subpath in sorted(wctx.substate):
2064 sub = wctx.sub(subpath)
2063 sub = wctx.sub(subpath)
2065 try:
2064 try:
2066 submatch = matchmod.subdirmatcher(subpath, match)
2065 submatch = matchmod.subdirmatcher(subpath, match)
2067 if opts.get(r'subrepos'):
2066 if opts.get(r'subrepos'):
2068 bad.extend(sub.add(ui, submatch, prefix, False, **opts))
2067 bad.extend(sub.add(ui, submatch, prefix, False, **opts))
2069 else:
2068 else:
2070 bad.extend(sub.add(ui, submatch, prefix, True, **opts))
2069 bad.extend(sub.add(ui, submatch, prefix, True, **opts))
2071 except error.LookupError:
2070 except error.LookupError:
2072 ui.status(_("skipping missing subrepository: %s\n")
2071 ui.status(_("skipping missing subrepository: %s\n")
2073 % join(subpath))
2072 % join(subpath))
2074
2073
2075 if not opts.get(r'dry_run'):
2074 if not opts.get(r'dry_run'):
2076 rejected = wctx.add(names, prefix)
2075 rejected = wctx.add(names, prefix)
2077 bad.extend(f for f in rejected if f in match.files())
2076 bad.extend(f for f in rejected if f in match.files())
2078 return bad
2077 return bad
2079
2078
2080 def addwebdirpath(repo, serverpath, webconf):
2079 def addwebdirpath(repo, serverpath, webconf):
2081 webconf[serverpath] = repo.root
2080 webconf[serverpath] = repo.root
2082 repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root))
2081 repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root))
2083
2082
2084 for r in repo.revs('filelog("path:.hgsub")'):
2083 for r in repo.revs('filelog("path:.hgsub")'):
2085 ctx = repo[r]
2084 ctx = repo[r]
2086 for subpath in ctx.substate:
2085 for subpath in ctx.substate:
2087 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
2086 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
2088
2087
2089 def forget(ui, repo, match, prefix, explicitonly, dryrun, interactive):
2088 def forget(ui, repo, match, prefix, explicitonly, dryrun, interactive):
2090 if dryrun and interactive:
2089 if dryrun and interactive:
2091 raise error.Abort(_("cannot specify both --dry-run and --interactive"))
2090 raise error.Abort(_("cannot specify both --dry-run and --interactive"))
2092 join = lambda f: os.path.join(prefix, f)
2091 join = lambda f: os.path.join(prefix, f)
2093 bad = []
2092 bad = []
2094 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2093 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2095 wctx = repo[None]
2094 wctx = repo[None]
2096 forgot = []
2095 forgot = []
2097
2096
2098 s = repo.status(match=matchmod.badmatch(match, badfn), clean=True)
2097 s = repo.status(match=matchmod.badmatch(match, badfn), clean=True)
2099 forget = sorted(s.modified + s.added + s.deleted + s.clean)
2098 forget = sorted(s.modified + s.added + s.deleted + s.clean)
2100 if explicitonly:
2099 if explicitonly:
2101 forget = [f for f in forget if match.exact(f)]
2100 forget = [f for f in forget if match.exact(f)]
2102
2101
2103 for subpath in sorted(wctx.substate):
2102 for subpath in sorted(wctx.substate):
2104 sub = wctx.sub(subpath)
2103 sub = wctx.sub(subpath)
2105 try:
2104 try:
2106 submatch = matchmod.subdirmatcher(subpath, match)
2105 submatch = matchmod.subdirmatcher(subpath, match)
2107 subbad, subforgot = sub.forget(submatch, prefix, dryrun=dryrun,
2106 subbad, subforgot = sub.forget(submatch, prefix, dryrun=dryrun,
2108 interactive=interactive)
2107 interactive=interactive)
2109 bad.extend([subpath + '/' + f for f in subbad])
2108 bad.extend([subpath + '/' + f for f in subbad])
2110 forgot.extend([subpath + '/' + f for f in subforgot])
2109 forgot.extend([subpath + '/' + f for f in subforgot])
2111 except error.LookupError:
2110 except error.LookupError:
2112 ui.status(_("skipping missing subrepository: %s\n")
2111 ui.status(_("skipping missing subrepository: %s\n")
2113 % join(subpath))
2112 % join(subpath))
2114
2113
2115 if not explicitonly:
2114 if not explicitonly:
2116 for f in match.files():
2115 for f in match.files():
2117 if f not in repo.dirstate and not repo.wvfs.isdir(f):
2116 if f not in repo.dirstate and not repo.wvfs.isdir(f):
2118 if f not in forgot:
2117 if f not in forgot:
2119 if repo.wvfs.exists(f):
2118 if repo.wvfs.exists(f):
2120 # Don't complain if the exact case match wasn't given.
2119 # Don't complain if the exact case match wasn't given.
2121 # But don't do this until after checking 'forgot', so
2120 # But don't do this until after checking 'forgot', so
2122 # that subrepo files aren't normalized, and this op is
2121 # that subrepo files aren't normalized, and this op is
2123 # purely from data cached by the status walk above.
2122 # purely from data cached by the status walk above.
2124 if repo.dirstate.normalize(f) in repo.dirstate:
2123 if repo.dirstate.normalize(f) in repo.dirstate:
2125 continue
2124 continue
2126 ui.warn(_('not removing %s: '
2125 ui.warn(_('not removing %s: '
2127 'file is already untracked\n')
2126 'file is already untracked\n')
2128 % match.rel(f))
2127 % match.rel(f))
2129 bad.append(f)
2128 bad.append(f)
2130
2129
2131 if interactive:
2130 if interactive:
2132 responses = _('[Ynsa?]'
2131 responses = _('[Ynsa?]'
2133 '$$ &Yes, forget this file'
2132 '$$ &Yes, forget this file'
2134 '$$ &No, skip this file'
2133 '$$ &No, skip this file'
2135 '$$ &Skip remaining files'
2134 '$$ &Skip remaining files'
2136 '$$ Include &all remaining files'
2135 '$$ Include &all remaining files'
2137 '$$ &? (display help)')
2136 '$$ &? (display help)')
2138 for filename in forget[:]:
2137 for filename in forget[:]:
2139 r = ui.promptchoice(_('forget %s %s') % (filename, responses))
2138 r = ui.promptchoice(_('forget %s %s') % (filename, responses))
2140 if r == 4: # ?
2139 if r == 4: # ?
2141 while r == 4:
2140 while r == 4:
2142 for c, t in ui.extractchoices(responses)[1]:
2141 for c, t in ui.extractchoices(responses)[1]:
2143 ui.write('%s - %s\n' % (c, encoding.lower(t)))
2142 ui.write('%s - %s\n' % (c, encoding.lower(t)))
2144 r = ui.promptchoice(_('forget %s %s') % (filename,
2143 r = ui.promptchoice(_('forget %s %s') % (filename,
2145 responses))
2144 responses))
2146 if r == 0: # yes
2145 if r == 0: # yes
2147 continue
2146 continue
2148 elif r == 1: # no
2147 elif r == 1: # no
2149 forget.remove(filename)
2148 forget.remove(filename)
2150 elif r == 2: # Skip
2149 elif r == 2: # Skip
2151 fnindex = forget.index(filename)
2150 fnindex = forget.index(filename)
2152 del forget[fnindex:]
2151 del forget[fnindex:]
2153 break
2152 break
2154 elif r == 3: # All
2153 elif r == 3: # All
2155 break
2154 break
2156
2155
2157 for f in forget:
2156 for f in forget:
2158 if ui.verbose or not match.exact(f) or interactive:
2157 if ui.verbose or not match.exact(f) or interactive:
2159 ui.status(_('removing %s\n') % match.rel(f),
2158 ui.status(_('removing %s\n') % match.rel(f),
2160 label='addremove.removed')
2159 label='addremove.removed')
2161
2160
2162 if not dryrun:
2161 if not dryrun:
2163 rejected = wctx.forget(forget, prefix)
2162 rejected = wctx.forget(forget, prefix)
2164 bad.extend(f for f in rejected if f in match.files())
2163 bad.extend(f for f in rejected if f in match.files())
2165 forgot.extend(f for f in forget if f not in rejected)
2164 forgot.extend(f for f in forget if f not in rejected)
2166 return bad, forgot
2165 return bad, forgot
2167
2166
2168 def files(ui, ctx, m, fm, fmt, subrepos):
2167 def files(ui, ctx, m, fm, fmt, subrepos):
2169 ret = 1
2168 ret = 1
2170
2169
2171 needsfctx = ui.verbose or {'size', 'flags'} & fm.datahint()
2170 needsfctx = ui.verbose or {'size', 'flags'} & fm.datahint()
2172 for f in ctx.matches(m):
2171 for f in ctx.matches(m):
2173 fm.startitem()
2172 fm.startitem()
2174 fm.context(ctx=ctx)
2173 fm.context(ctx=ctx)
2175 if needsfctx:
2174 if needsfctx:
2176 fc = ctx[f]
2175 fc = ctx[f]
2177 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
2176 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
2178 fm.data(path=f)
2177 fm.data(path=f)
2179 fm.plain(fmt % m.rel(f))
2178 fm.plain(fmt % m.rel(f))
2180 ret = 0
2179 ret = 0
2181
2180
2182 for subpath in sorted(ctx.substate):
2181 for subpath in sorted(ctx.substate):
2183 submatch = matchmod.subdirmatcher(subpath, m)
2182 submatch = matchmod.subdirmatcher(subpath, m)
2184 if (subrepos or m.exact(subpath) or any(submatch.files())):
2183 if (subrepos or m.exact(subpath) or any(submatch.files())):
2185 sub = ctx.sub(subpath)
2184 sub = ctx.sub(subpath)
2186 try:
2185 try:
2187 recurse = m.exact(subpath) or subrepos
2186 recurse = m.exact(subpath) or subrepos
2188 if sub.printfiles(ui, submatch, fm, fmt, recurse) == 0:
2187 if sub.printfiles(ui, submatch, fm, fmt, recurse) == 0:
2189 ret = 0
2188 ret = 0
2190 except error.LookupError:
2189 except error.LookupError:
2191 ui.status(_("skipping missing subrepository: %s\n")
2190 ui.status(_("skipping missing subrepository: %s\n")
2192 % m.abs(subpath))
2191 % m.abs(subpath))
2193
2192
2194 return ret
2193 return ret
2195
2194
2196 def remove(ui, repo, m, prefix, after, force, subrepos, dryrun, warnings=None):
2195 def remove(ui, repo, m, prefix, after, force, subrepos, dryrun, warnings=None):
2197 join = lambda f: os.path.join(prefix, f)
2196 join = lambda f: os.path.join(prefix, f)
2198 ret = 0
2197 ret = 0
2199 s = repo.status(match=m, clean=True)
2198 s = repo.status(match=m, clean=True)
2200 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2199 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2201
2200
2202 wctx = repo[None]
2201 wctx = repo[None]
2203
2202
2204 if warnings is None:
2203 if warnings is None:
2205 warnings = []
2204 warnings = []
2206 warn = True
2205 warn = True
2207 else:
2206 else:
2208 warn = False
2207 warn = False
2209
2208
2210 subs = sorted(wctx.substate)
2209 subs = sorted(wctx.substate)
2211 progress = ui.makeprogress(_('searching'), total=len(subs),
2210 progress = ui.makeprogress(_('searching'), total=len(subs),
2212 unit=_('subrepos'))
2211 unit=_('subrepos'))
2213 for subpath in subs:
2212 for subpath in subs:
2214 submatch = matchmod.subdirmatcher(subpath, m)
2213 submatch = matchmod.subdirmatcher(subpath, m)
2215 if subrepos or m.exact(subpath) or any(submatch.files()):
2214 if subrepos or m.exact(subpath) or any(submatch.files()):
2216 progress.increment()
2215 progress.increment()
2217 sub = wctx.sub(subpath)
2216 sub = wctx.sub(subpath)
2218 try:
2217 try:
2219 if sub.removefiles(submatch, prefix, after, force, subrepos,
2218 if sub.removefiles(submatch, prefix, after, force, subrepos,
2220 dryrun, warnings):
2219 dryrun, warnings):
2221 ret = 1
2220 ret = 1
2222 except error.LookupError:
2221 except error.LookupError:
2223 warnings.append(_("skipping missing subrepository: %s\n")
2222 warnings.append(_("skipping missing subrepository: %s\n")
2224 % join(subpath))
2223 % join(subpath))
2225 progress.complete()
2224 progress.complete()
2226
2225
2227 # warn about failure to delete explicit files/dirs
2226 # warn about failure to delete explicit files/dirs
2228 deleteddirs = util.dirs(deleted)
2227 deleteddirs = util.dirs(deleted)
2229 files = m.files()
2228 files = m.files()
2230 progress = ui.makeprogress(_('deleting'), total=len(files),
2229 progress = ui.makeprogress(_('deleting'), total=len(files),
2231 unit=_('files'))
2230 unit=_('files'))
2232 for f in files:
2231 for f in files:
2233 def insubrepo():
2232 def insubrepo():
2234 for subpath in wctx.substate:
2233 for subpath in wctx.substate:
2235 if f.startswith(subpath + '/'):
2234 if f.startswith(subpath + '/'):
2236 return True
2235 return True
2237 return False
2236 return False
2238
2237
2239 progress.increment()
2238 progress.increment()
2240 isdir = f in deleteddirs or wctx.hasdir(f)
2239 isdir = f in deleteddirs or wctx.hasdir(f)
2241 if (f in repo.dirstate or isdir or f == '.'
2240 if (f in repo.dirstate or isdir or f == '.'
2242 or insubrepo() or f in subs):
2241 or insubrepo() or f in subs):
2243 continue
2242 continue
2244
2243
2245 if repo.wvfs.exists(f):
2244 if repo.wvfs.exists(f):
2246 if repo.wvfs.isdir(f):
2245 if repo.wvfs.isdir(f):
2247 warnings.append(_('not removing %s: no tracked files\n')
2246 warnings.append(_('not removing %s: no tracked files\n')
2248 % m.rel(f))
2247 % m.rel(f))
2249 else:
2248 else:
2250 warnings.append(_('not removing %s: file is untracked\n')
2249 warnings.append(_('not removing %s: file is untracked\n')
2251 % m.rel(f))
2250 % m.rel(f))
2252 # missing files will generate a warning elsewhere
2251 # missing files will generate a warning elsewhere
2253 ret = 1
2252 ret = 1
2254 progress.complete()
2253 progress.complete()
2255
2254
2256 if force:
2255 if force:
2257 list = modified + deleted + clean + added
2256 list = modified + deleted + clean + added
2258 elif after:
2257 elif after:
2259 list = deleted
2258 list = deleted
2260 remaining = modified + added + clean
2259 remaining = modified + added + clean
2261 progress = ui.makeprogress(_('skipping'), total=len(remaining),
2260 progress = ui.makeprogress(_('skipping'), total=len(remaining),
2262 unit=_('files'))
2261 unit=_('files'))
2263 for f in remaining:
2262 for f in remaining:
2264 progress.increment()
2263 progress.increment()
2265 if ui.verbose or (f in files):
2264 if ui.verbose or (f in files):
2266 warnings.append(_('not removing %s: file still exists\n')
2265 warnings.append(_('not removing %s: file still exists\n')
2267 % m.rel(f))
2266 % m.rel(f))
2268 ret = 1
2267 ret = 1
2269 progress.complete()
2268 progress.complete()
2270 else:
2269 else:
2271 list = deleted + clean
2270 list = deleted + clean
2272 progress = ui.makeprogress(_('skipping'),
2271 progress = ui.makeprogress(_('skipping'),
2273 total=(len(modified) + len(added)),
2272 total=(len(modified) + len(added)),
2274 unit=_('files'))
2273 unit=_('files'))
2275 for f in modified:
2274 for f in modified:
2276 progress.increment()
2275 progress.increment()
2277 warnings.append(_('not removing %s: file is modified (use -f'
2276 warnings.append(_('not removing %s: file is modified (use -f'
2278 ' to force removal)\n') % m.rel(f))
2277 ' to force removal)\n') % m.rel(f))
2279 ret = 1
2278 ret = 1
2280 for f in added:
2279 for f in added:
2281 progress.increment()
2280 progress.increment()
2282 warnings.append(_("not removing %s: file has been marked for add"
2281 warnings.append(_("not removing %s: file has been marked for add"
2283 " (use 'hg forget' to undo add)\n") % m.rel(f))
2282 " (use 'hg forget' to undo add)\n") % m.rel(f))
2284 ret = 1
2283 ret = 1
2285 progress.complete()
2284 progress.complete()
2286
2285
2287 list = sorted(list)
2286 list = sorted(list)
2288 progress = ui.makeprogress(_('deleting'), total=len(list),
2287 progress = ui.makeprogress(_('deleting'), total=len(list),
2289 unit=_('files'))
2288 unit=_('files'))
2290 for f in list:
2289 for f in list:
2291 if ui.verbose or not m.exact(f):
2290 if ui.verbose or not m.exact(f):
2292 progress.increment()
2291 progress.increment()
2293 ui.status(_('removing %s\n') % m.rel(f),
2292 ui.status(_('removing %s\n') % m.rel(f),
2294 label='addremove.removed')
2293 label='addremove.removed')
2295 progress.complete()
2294 progress.complete()
2296
2295
2297 if not dryrun:
2296 if not dryrun:
2298 with repo.wlock():
2297 with repo.wlock():
2299 if not after:
2298 if not after:
2300 for f in list:
2299 for f in list:
2301 if f in added:
2300 if f in added:
2302 continue # we never unlink added files on remove
2301 continue # we never unlink added files on remove
2303 rmdir = repo.ui.configbool('experimental',
2302 rmdir = repo.ui.configbool('experimental',
2304 'removeemptydirs')
2303 'removeemptydirs')
2305 repo.wvfs.unlinkpath(f, ignoremissing=True, rmdir=rmdir)
2304 repo.wvfs.unlinkpath(f, ignoremissing=True, rmdir=rmdir)
2306 repo[None].forget(list)
2305 repo[None].forget(list)
2307
2306
2308 if warn:
2307 if warn:
2309 for warning in warnings:
2308 for warning in warnings:
2310 ui.warn(warning)
2309 ui.warn(warning)
2311
2310
2312 return ret
2311 return ret
2313
2312
2314 def _updatecatformatter(fm, ctx, matcher, path, decode):
2313 def _updatecatformatter(fm, ctx, matcher, path, decode):
2315 """Hook for adding data to the formatter used by ``hg cat``.
2314 """Hook for adding data to the formatter used by ``hg cat``.
2316
2315
2317 Extensions (e.g., lfs) can wrap this to inject keywords/data, but must call
2316 Extensions (e.g., lfs) can wrap this to inject keywords/data, but must call
2318 this method first."""
2317 this method first."""
2319 data = ctx[path].data()
2318 data = ctx[path].data()
2320 if decode:
2319 if decode:
2321 data = ctx.repo().wwritedata(path, data)
2320 data = ctx.repo().wwritedata(path, data)
2322 fm.startitem()
2321 fm.startitem()
2323 fm.context(ctx=ctx)
2322 fm.context(ctx=ctx)
2324 fm.write('data', '%s', data)
2323 fm.write('data', '%s', data)
2325 fm.data(path=path)
2324 fm.data(path=path)
2326
2325
2327 def cat(ui, repo, ctx, matcher, basefm, fntemplate, prefix, **opts):
2326 def cat(ui, repo, ctx, matcher, basefm, fntemplate, prefix, **opts):
2328 err = 1
2327 err = 1
2329 opts = pycompat.byteskwargs(opts)
2328 opts = pycompat.byteskwargs(opts)
2330
2329
2331 def write(path):
2330 def write(path):
2332 filename = None
2331 filename = None
2333 if fntemplate:
2332 if fntemplate:
2334 filename = makefilename(ctx, fntemplate,
2333 filename = makefilename(ctx, fntemplate,
2335 pathname=os.path.join(prefix, path))
2334 pathname=os.path.join(prefix, path))
2336 # attempt to create the directory if it does not already exist
2335 # attempt to create the directory if it does not already exist
2337 try:
2336 try:
2338 os.makedirs(os.path.dirname(filename))
2337 os.makedirs(os.path.dirname(filename))
2339 except OSError:
2338 except OSError:
2340 pass
2339 pass
2341 with formatter.maybereopen(basefm, filename) as fm:
2340 with formatter.maybereopen(basefm, filename) as fm:
2342 _updatecatformatter(fm, ctx, matcher, path, opts.get('decode'))
2341 _updatecatformatter(fm, ctx, matcher, path, opts.get('decode'))
2343
2342
2344 # Automation often uses hg cat on single files, so special case it
2343 # Automation often uses hg cat on single files, so special case it
2345 # for performance to avoid the cost of parsing the manifest.
2344 # for performance to avoid the cost of parsing the manifest.
2346 if len(matcher.files()) == 1 and not matcher.anypats():
2345 if len(matcher.files()) == 1 and not matcher.anypats():
2347 file = matcher.files()[0]
2346 file = matcher.files()[0]
2348 mfl = repo.manifestlog
2347 mfl = repo.manifestlog
2349 mfnode = ctx.manifestnode()
2348 mfnode = ctx.manifestnode()
2350 try:
2349 try:
2351 if mfnode and mfl[mfnode].find(file)[0]:
2350 if mfnode and mfl[mfnode].find(file)[0]:
2352 scmutil.prefetchfiles(repo, [ctx.rev()], matcher)
2351 scmutil.prefetchfiles(repo, [ctx.rev()], matcher)
2353 write(file)
2352 write(file)
2354 return 0
2353 return 0
2355 except KeyError:
2354 except KeyError:
2356 pass
2355 pass
2357
2356
2358 scmutil.prefetchfiles(repo, [ctx.rev()], matcher)
2357 scmutil.prefetchfiles(repo, [ctx.rev()], matcher)
2359
2358
2360 for abs in ctx.walk(matcher):
2359 for abs in ctx.walk(matcher):
2361 write(abs)
2360 write(abs)
2362 err = 0
2361 err = 0
2363
2362
2364 for subpath in sorted(ctx.substate):
2363 for subpath in sorted(ctx.substate):
2365 sub = ctx.sub(subpath)
2364 sub = ctx.sub(subpath)
2366 try:
2365 try:
2367 submatch = matchmod.subdirmatcher(subpath, matcher)
2366 submatch = matchmod.subdirmatcher(subpath, matcher)
2368
2367
2369 if not sub.cat(submatch, basefm, fntemplate,
2368 if not sub.cat(submatch, basefm, fntemplate,
2370 os.path.join(prefix, sub._path),
2369 os.path.join(prefix, sub._path),
2371 **pycompat.strkwargs(opts)):
2370 **pycompat.strkwargs(opts)):
2372 err = 0
2371 err = 0
2373 except error.RepoLookupError:
2372 except error.RepoLookupError:
2374 ui.status(_("skipping missing subrepository: %s\n")
2373 ui.status(_("skipping missing subrepository: %s\n")
2375 % os.path.join(prefix, subpath))
2374 % os.path.join(prefix, subpath))
2376
2375
2377 return err
2376 return err
2378
2377
2379 def commit(ui, repo, commitfunc, pats, opts):
2378 def commit(ui, repo, commitfunc, pats, opts):
2380 '''commit the specified files or all outstanding changes'''
2379 '''commit the specified files or all outstanding changes'''
2381 date = opts.get('date')
2380 date = opts.get('date')
2382 if date:
2381 if date:
2383 opts['date'] = dateutil.parsedate(date)
2382 opts['date'] = dateutil.parsedate(date)
2384 message = logmessage(ui, opts)
2383 message = logmessage(ui, opts)
2385 matcher = scmutil.match(repo[None], pats, opts)
2384 matcher = scmutil.match(repo[None], pats, opts)
2386
2385
2387 dsguard = None
2386 dsguard = None
2388 # extract addremove carefully -- this function can be called from a command
2387 # extract addremove carefully -- this function can be called from a command
2389 # that doesn't support addremove
2388 # that doesn't support addremove
2390 if opts.get('addremove'):
2389 if opts.get('addremove'):
2391 dsguard = dirstateguard.dirstateguard(repo, 'commit')
2390 dsguard = dirstateguard.dirstateguard(repo, 'commit')
2392 with dsguard or util.nullcontextmanager():
2391 with dsguard or util.nullcontextmanager():
2393 if dsguard:
2392 if dsguard:
2394 if scmutil.addremove(repo, matcher, "", opts) != 0:
2393 if scmutil.addremove(repo, matcher, "", opts) != 0:
2395 raise error.Abort(
2394 raise error.Abort(
2396 _("failed to mark all new/missing files as added/removed"))
2395 _("failed to mark all new/missing files as added/removed"))
2397
2396
2398 return commitfunc(ui, repo, message, matcher, opts)
2397 return commitfunc(ui, repo, message, matcher, opts)
2399
2398
2400 def samefile(f, ctx1, ctx2):
2399 def samefile(f, ctx1, ctx2):
2401 if f in ctx1.manifest():
2400 if f in ctx1.manifest():
2402 a = ctx1.filectx(f)
2401 a = ctx1.filectx(f)
2403 if f in ctx2.manifest():
2402 if f in ctx2.manifest():
2404 b = ctx2.filectx(f)
2403 b = ctx2.filectx(f)
2405 return (not a.cmp(b)
2404 return (not a.cmp(b)
2406 and a.flags() == b.flags())
2405 and a.flags() == b.flags())
2407 else:
2406 else:
2408 return False
2407 return False
2409 else:
2408 else:
2410 return f not in ctx2.manifest()
2409 return f not in ctx2.manifest()
2411
2410
2412 def amend(ui, repo, old, extra, pats, opts):
2411 def amend(ui, repo, old, extra, pats, opts):
2413 # avoid cycle context -> subrepo -> cmdutil
2412 # avoid cycle context -> subrepo -> cmdutil
2414 from . import context
2413 from . import context
2415
2414
2416 # amend will reuse the existing user if not specified, but the obsolete
2415 # amend will reuse the existing user if not specified, but the obsolete
2417 # marker creation requires that the current user's name is specified.
2416 # marker creation requires that the current user's name is specified.
2418 if obsolete.isenabled(repo, obsolete.createmarkersopt):
2417 if obsolete.isenabled(repo, obsolete.createmarkersopt):
2419 ui.username() # raise exception if username not set
2418 ui.username() # raise exception if username not set
2420
2419
2421 ui.note(_('amending changeset %s\n') % old)
2420 ui.note(_('amending changeset %s\n') % old)
2422 base = old.p1()
2421 base = old.p1()
2423
2422
2424 with repo.wlock(), repo.lock(), repo.transaction('amend'):
2423 with repo.wlock(), repo.lock(), repo.transaction('amend'):
2425 # Participating changesets:
2424 # Participating changesets:
2426 #
2425 #
2427 # wctx o - workingctx that contains changes from working copy
2426 # wctx o - workingctx that contains changes from working copy
2428 # | to go into amending commit
2427 # | to go into amending commit
2429 # |
2428 # |
2430 # old o - changeset to amend
2429 # old o - changeset to amend
2431 # |
2430 # |
2432 # base o - first parent of the changeset to amend
2431 # base o - first parent of the changeset to amend
2433 wctx = repo[None]
2432 wctx = repo[None]
2434
2433
2435 # Copy to avoid mutating input
2434 # Copy to avoid mutating input
2436 extra = extra.copy()
2435 extra = extra.copy()
2437 # Update extra dict from amended commit (e.g. to preserve graft
2436 # Update extra dict from amended commit (e.g. to preserve graft
2438 # source)
2437 # source)
2439 extra.update(old.extra())
2438 extra.update(old.extra())
2440
2439
2441 # Also update it from the from the wctx
2440 # Also update it from the from the wctx
2442 extra.update(wctx.extra())
2441 extra.update(wctx.extra())
2443
2442
2444 user = opts.get('user') or old.user()
2443 user = opts.get('user') or old.user()
2445 date = opts.get('date') or old.date()
2444 date = opts.get('date') or old.date()
2446
2445
2447 # Parse the date to allow comparison between date and old.date()
2446 # Parse the date to allow comparison between date and old.date()
2448 date = dateutil.parsedate(date)
2447 date = dateutil.parsedate(date)
2449
2448
2450 if len(old.parents()) > 1:
2449 if len(old.parents()) > 1:
2451 # ctx.files() isn't reliable for merges, so fall back to the
2450 # ctx.files() isn't reliable for merges, so fall back to the
2452 # slower repo.status() method
2451 # slower repo.status() method
2453 files = set([fn for st in base.status(old)[:3]
2452 files = set([fn for st in base.status(old)[:3]
2454 for fn in st])
2453 for fn in st])
2455 else:
2454 else:
2456 files = set(old.files())
2455 files = set(old.files())
2457
2456
2458 # add/remove the files to the working copy if the "addremove" option
2457 # add/remove the files to the working copy if the "addremove" option
2459 # was specified.
2458 # was specified.
2460 matcher = scmutil.match(wctx, pats, opts)
2459 matcher = scmutil.match(wctx, pats, opts)
2461 if (opts.get('addremove')
2460 if (opts.get('addremove')
2462 and scmutil.addremove(repo, matcher, "", opts)):
2461 and scmutil.addremove(repo, matcher, "", opts)):
2463 raise error.Abort(
2462 raise error.Abort(
2464 _("failed to mark all new/missing files as added/removed"))
2463 _("failed to mark all new/missing files as added/removed"))
2465
2464
2466 # Check subrepos. This depends on in-place wctx._status update in
2465 # Check subrepos. This depends on in-place wctx._status update in
2467 # subrepo.precommit(). To minimize the risk of this hack, we do
2466 # subrepo.precommit(). To minimize the risk of this hack, we do
2468 # nothing if .hgsub does not exist.
2467 # nothing if .hgsub does not exist.
2469 if '.hgsub' in wctx or '.hgsub' in old:
2468 if '.hgsub' in wctx or '.hgsub' in old:
2470 subs, commitsubs, newsubstate = subrepoutil.precommit(
2469 subs, commitsubs, newsubstate = subrepoutil.precommit(
2471 ui, wctx, wctx._status, matcher)
2470 ui, wctx, wctx._status, matcher)
2472 # amend should abort if commitsubrepos is enabled
2471 # amend should abort if commitsubrepos is enabled
2473 assert not commitsubs
2472 assert not commitsubs
2474 if subs:
2473 if subs:
2475 subrepoutil.writestate(repo, newsubstate)
2474 subrepoutil.writestate(repo, newsubstate)
2476
2475
2477 ms = mergemod.mergestate.read(repo)
2476 ms = mergemod.mergestate.read(repo)
2478 mergeutil.checkunresolved(ms)
2477 mergeutil.checkunresolved(ms)
2479
2478
2480 filestoamend = set(f for f in wctx.files() if matcher(f))
2479 filestoamend = set(f for f in wctx.files() if matcher(f))
2481
2480
2482 changes = (len(filestoamend) > 0)
2481 changes = (len(filestoamend) > 0)
2483 if changes:
2482 if changes:
2484 # Recompute copies (avoid recording a -> b -> a)
2483 # Recompute copies (avoid recording a -> b -> a)
2485 copied = copies.pathcopies(base, wctx, matcher)
2484 copied = copies.pathcopies(base, wctx, matcher)
2486 if old.p2:
2485 if old.p2:
2487 copied.update(copies.pathcopies(old.p2(), wctx, matcher))
2486 copied.update(copies.pathcopies(old.p2(), wctx, matcher))
2488
2487
2489 # Prune files which were reverted by the updates: if old
2488 # Prune files which were reverted by the updates: if old
2490 # introduced file X and the file was renamed in the working
2489 # introduced file X and the file was renamed in the working
2491 # copy, then those two files are the same and
2490 # copy, then those two files are the same and
2492 # we can discard X from our list of files. Likewise if X
2491 # we can discard X from our list of files. Likewise if X
2493 # was removed, it's no longer relevant. If X is missing (aka
2492 # was removed, it's no longer relevant. If X is missing (aka
2494 # deleted), old X must be preserved.
2493 # deleted), old X must be preserved.
2495 files.update(filestoamend)
2494 files.update(filestoamend)
2496 files = [f for f in files if (not samefile(f, wctx, base)
2495 files = [f for f in files if (not samefile(f, wctx, base)
2497 or f in wctx.deleted())]
2496 or f in wctx.deleted())]
2498
2497
2499 def filectxfn(repo, ctx_, path):
2498 def filectxfn(repo, ctx_, path):
2500 try:
2499 try:
2501 # If the file being considered is not amongst the files
2500 # If the file being considered is not amongst the files
2502 # to be amended, we should return the file context from the
2501 # to be amended, we should return the file context from the
2503 # old changeset. This avoids issues when only some files in
2502 # old changeset. This avoids issues when only some files in
2504 # the working copy are being amended but there are also
2503 # the working copy are being amended but there are also
2505 # changes to other files from the old changeset.
2504 # changes to other files from the old changeset.
2506 if path not in filestoamend:
2505 if path not in filestoamend:
2507 return old.filectx(path)
2506 return old.filectx(path)
2508
2507
2509 # Return None for removed files.
2508 # Return None for removed files.
2510 if path in wctx.removed():
2509 if path in wctx.removed():
2511 return None
2510 return None
2512
2511
2513 fctx = wctx[path]
2512 fctx = wctx[path]
2514 flags = fctx.flags()
2513 flags = fctx.flags()
2515 mctx = context.memfilectx(repo, ctx_,
2514 mctx = context.memfilectx(repo, ctx_,
2516 fctx.path(), fctx.data(),
2515 fctx.path(), fctx.data(),
2517 islink='l' in flags,
2516 islink='l' in flags,
2518 isexec='x' in flags,
2517 isexec='x' in flags,
2519 copied=copied.get(path))
2518 copied=copied.get(path))
2520 return mctx
2519 return mctx
2521 except KeyError:
2520 except KeyError:
2522 return None
2521 return None
2523 else:
2522 else:
2524 ui.note(_('copying changeset %s to %s\n') % (old, base))
2523 ui.note(_('copying changeset %s to %s\n') % (old, base))
2525
2524
2526 # Use version of files as in the old cset
2525 # Use version of files as in the old cset
2527 def filectxfn(repo, ctx_, path):
2526 def filectxfn(repo, ctx_, path):
2528 try:
2527 try:
2529 return old.filectx(path)
2528 return old.filectx(path)
2530 except KeyError:
2529 except KeyError:
2531 return None
2530 return None
2532
2531
2533 # See if we got a message from -m or -l, if not, open the editor with
2532 # See if we got a message from -m or -l, if not, open the editor with
2534 # the message of the changeset to amend.
2533 # the message of the changeset to amend.
2535 message = logmessage(ui, opts)
2534 message = logmessage(ui, opts)
2536
2535
2537 editform = mergeeditform(old, 'commit.amend')
2536 editform = mergeeditform(old, 'commit.amend')
2538 editor = getcommiteditor(editform=editform,
2537 editor = getcommiteditor(editform=editform,
2539 **pycompat.strkwargs(opts))
2538 **pycompat.strkwargs(opts))
2540
2539
2541 if not message:
2540 if not message:
2542 editor = getcommiteditor(edit=True, editform=editform)
2541 editor = getcommiteditor(edit=True, editform=editform)
2543 message = old.description()
2542 message = old.description()
2544
2543
2545 pureextra = extra.copy()
2544 pureextra = extra.copy()
2546 extra['amend_source'] = old.hex()
2545 extra['amend_source'] = old.hex()
2547
2546
2548 new = context.memctx(repo,
2547 new = context.memctx(repo,
2549 parents=[base.node(), old.p2().node()],
2548 parents=[base.node(), old.p2().node()],
2550 text=message,
2549 text=message,
2551 files=files,
2550 files=files,
2552 filectxfn=filectxfn,
2551 filectxfn=filectxfn,
2553 user=user,
2552 user=user,
2554 date=date,
2553 date=date,
2555 extra=extra,
2554 extra=extra,
2556 editor=editor)
2555 editor=editor)
2557
2556
2558 newdesc = changelog.stripdesc(new.description())
2557 newdesc = changelog.stripdesc(new.description())
2559 if ((not changes)
2558 if ((not changes)
2560 and newdesc == old.description()
2559 and newdesc == old.description()
2561 and user == old.user()
2560 and user == old.user()
2562 and date == old.date()
2561 and date == old.date()
2563 and pureextra == old.extra()):
2562 and pureextra == old.extra()):
2564 # nothing changed. continuing here would create a new node
2563 # nothing changed. continuing here would create a new node
2565 # anyway because of the amend_source noise.
2564 # anyway because of the amend_source noise.
2566 #
2565 #
2567 # This not what we expect from amend.
2566 # This not what we expect from amend.
2568 return old.node()
2567 return old.node()
2569
2568
2570 commitphase = None
2569 commitphase = None
2571 if opts.get('secret'):
2570 if opts.get('secret'):
2572 commitphase = phases.secret
2571 commitphase = phases.secret
2573 newid = repo.commitctx(new)
2572 newid = repo.commitctx(new)
2574
2573
2575 # Reroute the working copy parent to the new changeset
2574 # Reroute the working copy parent to the new changeset
2576 repo.setparents(newid, nullid)
2575 repo.setparents(newid, nullid)
2577 mapping = {old.node(): (newid,)}
2576 mapping = {old.node(): (newid,)}
2578 obsmetadata = None
2577 obsmetadata = None
2579 if opts.get('note'):
2578 if opts.get('note'):
2580 obsmetadata = {'note': encoding.fromlocal(opts['note'])}
2579 obsmetadata = {'note': encoding.fromlocal(opts['note'])}
2581 backup = ui.configbool('ui', 'history-editing-backup')
2580 backup = ui.configbool('ui', 'history-editing-backup')
2582 scmutil.cleanupnodes(repo, mapping, 'amend', metadata=obsmetadata,
2581 scmutil.cleanupnodes(repo, mapping, 'amend', metadata=obsmetadata,
2583 fixphase=True, targetphase=commitphase,
2582 fixphase=True, targetphase=commitphase,
2584 backup=backup)
2583 backup=backup)
2585
2584
2586 # Fixing the dirstate because localrepo.commitctx does not update
2585 # Fixing the dirstate because localrepo.commitctx does not update
2587 # it. This is rather convenient because we did not need to update
2586 # it. This is rather convenient because we did not need to update
2588 # the dirstate for all the files in the new commit which commitctx
2587 # the dirstate for all the files in the new commit which commitctx
2589 # could have done if it updated the dirstate. Now, we can
2588 # could have done if it updated the dirstate. Now, we can
2590 # selectively update the dirstate only for the amended files.
2589 # selectively update the dirstate only for the amended files.
2591 dirstate = repo.dirstate
2590 dirstate = repo.dirstate
2592
2591
2593 # Update the state of the files which were added and
2592 # Update the state of the files which were added and
2594 # and modified in the amend to "normal" in the dirstate.
2593 # and modified in the amend to "normal" in the dirstate.
2595 normalfiles = set(wctx.modified() + wctx.added()) & filestoamend
2594 normalfiles = set(wctx.modified() + wctx.added()) & filestoamend
2596 for f in normalfiles:
2595 for f in normalfiles:
2597 dirstate.normal(f)
2596 dirstate.normal(f)
2598
2597
2599 # Update the state of files which were removed in the amend
2598 # Update the state of files which were removed in the amend
2600 # to "removed" in the dirstate.
2599 # to "removed" in the dirstate.
2601 removedfiles = set(wctx.removed()) & filestoamend
2600 removedfiles = set(wctx.removed()) & filestoamend
2602 for f in removedfiles:
2601 for f in removedfiles:
2603 dirstate.drop(f)
2602 dirstate.drop(f)
2604
2603
2605 return newid
2604 return newid
2606
2605
2607 def commiteditor(repo, ctx, subs, editform=''):
2606 def commiteditor(repo, ctx, subs, editform=''):
2608 if ctx.description():
2607 if ctx.description():
2609 return ctx.description()
2608 return ctx.description()
2610 return commitforceeditor(repo, ctx, subs, editform=editform,
2609 return commitforceeditor(repo, ctx, subs, editform=editform,
2611 unchangedmessagedetection=True)
2610 unchangedmessagedetection=True)
2612
2611
2613 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
2612 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
2614 editform='', unchangedmessagedetection=False):
2613 editform='', unchangedmessagedetection=False):
2615 if not extramsg:
2614 if not extramsg:
2616 extramsg = _("Leave message empty to abort commit.")
2615 extramsg = _("Leave message empty to abort commit.")
2617
2616
2618 forms = [e for e in editform.split('.') if e]
2617 forms = [e for e in editform.split('.') if e]
2619 forms.insert(0, 'changeset')
2618 forms.insert(0, 'changeset')
2620 templatetext = None
2619 templatetext = None
2621 while forms:
2620 while forms:
2622 ref = '.'.join(forms)
2621 ref = '.'.join(forms)
2623 if repo.ui.config('committemplate', ref):
2622 if repo.ui.config('committemplate', ref):
2624 templatetext = committext = buildcommittemplate(
2623 templatetext = committext = buildcommittemplate(
2625 repo, ctx, subs, extramsg, ref)
2624 repo, ctx, subs, extramsg, ref)
2626 break
2625 break
2627 forms.pop()
2626 forms.pop()
2628 else:
2627 else:
2629 committext = buildcommittext(repo, ctx, subs, extramsg)
2628 committext = buildcommittext(repo, ctx, subs, extramsg)
2630
2629
2631 # run editor in the repository root
2630 # run editor in the repository root
2632 olddir = encoding.getcwd()
2631 olddir = encoding.getcwd()
2633 os.chdir(repo.root)
2632 os.chdir(repo.root)
2634
2633
2635 # make in-memory changes visible to external process
2634 # make in-memory changes visible to external process
2636 tr = repo.currenttransaction()
2635 tr = repo.currenttransaction()
2637 repo.dirstate.write(tr)
2636 repo.dirstate.write(tr)
2638 pending = tr and tr.writepending() and repo.root
2637 pending = tr and tr.writepending() and repo.root
2639
2638
2640 editortext = repo.ui.edit(committext, ctx.user(), ctx.extra(),
2639 editortext = repo.ui.edit(committext, ctx.user(), ctx.extra(),
2641 editform=editform, pending=pending,
2640 editform=editform, pending=pending,
2642 repopath=repo.path, action='commit')
2641 repopath=repo.path, action='commit')
2643 text = editortext
2642 text = editortext
2644
2643
2645 # strip away anything below this special string (used for editors that want
2644 # strip away anything below this special string (used for editors that want
2646 # to display the diff)
2645 # to display the diff)
2647 stripbelow = re.search(_linebelow, text, flags=re.MULTILINE)
2646 stripbelow = re.search(_linebelow, text, flags=re.MULTILINE)
2648 if stripbelow:
2647 if stripbelow:
2649 text = text[:stripbelow.start()]
2648 text = text[:stripbelow.start()]
2650
2649
2651 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
2650 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
2652 os.chdir(olddir)
2651 os.chdir(olddir)
2653
2652
2654 if finishdesc:
2653 if finishdesc:
2655 text = finishdesc(text)
2654 text = finishdesc(text)
2656 if not text.strip():
2655 if not text.strip():
2657 raise error.Abort(_("empty commit message"))
2656 raise error.Abort(_("empty commit message"))
2658 if unchangedmessagedetection and editortext == templatetext:
2657 if unchangedmessagedetection and editortext == templatetext:
2659 raise error.Abort(_("commit message unchanged"))
2658 raise error.Abort(_("commit message unchanged"))
2660
2659
2661 return text
2660 return text
2662
2661
2663 def buildcommittemplate(repo, ctx, subs, extramsg, ref):
2662 def buildcommittemplate(repo, ctx, subs, extramsg, ref):
2664 ui = repo.ui
2663 ui = repo.ui
2665 spec = formatter.templatespec(ref, None, None)
2664 spec = formatter.templatespec(ref, None, None)
2666 t = logcmdutil.changesettemplater(ui, repo, spec)
2665 t = logcmdutil.changesettemplater(ui, repo, spec)
2667 t.t.cache.update((k, templater.unquotestring(v))
2666 t.t.cache.update((k, templater.unquotestring(v))
2668 for k, v in repo.ui.configitems('committemplate'))
2667 for k, v in repo.ui.configitems('committemplate'))
2669
2668
2670 if not extramsg:
2669 if not extramsg:
2671 extramsg = '' # ensure that extramsg is string
2670 extramsg = '' # ensure that extramsg is string
2672
2671
2673 ui.pushbuffer()
2672 ui.pushbuffer()
2674 t.show(ctx, extramsg=extramsg)
2673 t.show(ctx, extramsg=extramsg)
2675 return ui.popbuffer()
2674 return ui.popbuffer()
2676
2675
2677 def hgprefix(msg):
2676 def hgprefix(msg):
2678 return "\n".join(["HG: %s" % a for a in msg.split("\n") if a])
2677 return "\n".join(["HG: %s" % a for a in msg.split("\n") if a])
2679
2678
2680 def buildcommittext(repo, ctx, subs, extramsg):
2679 def buildcommittext(repo, ctx, subs, extramsg):
2681 edittext = []
2680 edittext = []
2682 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
2681 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
2683 if ctx.description():
2682 if ctx.description():
2684 edittext.append(ctx.description())
2683 edittext.append(ctx.description())
2685 edittext.append("")
2684 edittext.append("")
2686 edittext.append("") # Empty line between message and comments.
2685 edittext.append("") # Empty line between message and comments.
2687 edittext.append(hgprefix(_("Enter commit message."
2686 edittext.append(hgprefix(_("Enter commit message."
2688 " Lines beginning with 'HG:' are removed.")))
2687 " Lines beginning with 'HG:' are removed.")))
2689 edittext.append(hgprefix(extramsg))
2688 edittext.append(hgprefix(extramsg))
2690 edittext.append("HG: --")
2689 edittext.append("HG: --")
2691 edittext.append(hgprefix(_("user: %s") % ctx.user()))
2690 edittext.append(hgprefix(_("user: %s") % ctx.user()))
2692 if ctx.p2():
2691 if ctx.p2():
2693 edittext.append(hgprefix(_("branch merge")))
2692 edittext.append(hgprefix(_("branch merge")))
2694 if ctx.branch():
2693 if ctx.branch():
2695 edittext.append(hgprefix(_("branch '%s'") % ctx.branch()))
2694 edittext.append(hgprefix(_("branch '%s'") % ctx.branch()))
2696 if bookmarks.isactivewdirparent(repo):
2695 if bookmarks.isactivewdirparent(repo):
2697 edittext.append(hgprefix(_("bookmark '%s'") % repo._activebookmark))
2696 edittext.append(hgprefix(_("bookmark '%s'") % repo._activebookmark))
2698 edittext.extend([hgprefix(_("subrepo %s") % s) for s in subs])
2697 edittext.extend([hgprefix(_("subrepo %s") % s) for s in subs])
2699 edittext.extend([hgprefix(_("added %s") % f) for f in added])
2698 edittext.extend([hgprefix(_("added %s") % f) for f in added])
2700 edittext.extend([hgprefix(_("changed %s") % f) for f in modified])
2699 edittext.extend([hgprefix(_("changed %s") % f) for f in modified])
2701 edittext.extend([hgprefix(_("removed %s") % f) for f in removed])
2700 edittext.extend([hgprefix(_("removed %s") % f) for f in removed])
2702 if not added and not modified and not removed:
2701 if not added and not modified and not removed:
2703 edittext.append(hgprefix(_("no files changed")))
2702 edittext.append(hgprefix(_("no files changed")))
2704 edittext.append("")
2703 edittext.append("")
2705
2704
2706 return "\n".join(edittext)
2705 return "\n".join(edittext)
2707
2706
2708 def commitstatus(repo, node, branch, bheads=None, opts=None):
2707 def commitstatus(repo, node, branch, bheads=None, opts=None):
2709 if opts is None:
2708 if opts is None:
2710 opts = {}
2709 opts = {}
2711 ctx = repo[node]
2710 ctx = repo[node]
2712 parents = ctx.parents()
2711 parents = ctx.parents()
2713
2712
2714 if (not opts.get('amend') and bheads and node not in bheads and not
2713 if (not opts.get('amend') and bheads and node not in bheads and not
2715 [x for x in parents if x.node() in bheads and x.branch() == branch]):
2714 [x for x in parents if x.node() in bheads and x.branch() == branch]):
2716 repo.ui.status(_('created new head\n'))
2715 repo.ui.status(_('created new head\n'))
2717 # The message is not printed for initial roots. For the other
2716 # The message is not printed for initial roots. For the other
2718 # changesets, it is printed in the following situations:
2717 # changesets, it is printed in the following situations:
2719 #
2718 #
2720 # Par column: for the 2 parents with ...
2719 # Par column: for the 2 parents with ...
2721 # N: null or no parent
2720 # N: null or no parent
2722 # B: parent is on another named branch
2721 # B: parent is on another named branch
2723 # C: parent is a regular non head changeset
2722 # C: parent is a regular non head changeset
2724 # H: parent was a branch head of the current branch
2723 # H: parent was a branch head of the current branch
2725 # Msg column: whether we print "created new head" message
2724 # Msg column: whether we print "created new head" message
2726 # In the following, it is assumed that there already exists some
2725 # In the following, it is assumed that there already exists some
2727 # initial branch heads of the current branch, otherwise nothing is
2726 # initial branch heads of the current branch, otherwise nothing is
2728 # printed anyway.
2727 # printed anyway.
2729 #
2728 #
2730 # Par Msg Comment
2729 # Par Msg Comment
2731 # N N y additional topo root
2730 # N N y additional topo root
2732 #
2731 #
2733 # B N y additional branch root
2732 # B N y additional branch root
2734 # C N y additional topo head
2733 # C N y additional topo head
2735 # H N n usual case
2734 # H N n usual case
2736 #
2735 #
2737 # B B y weird additional branch root
2736 # B B y weird additional branch root
2738 # C B y branch merge
2737 # C B y branch merge
2739 # H B n merge with named branch
2738 # H B n merge with named branch
2740 #
2739 #
2741 # C C y additional head from merge
2740 # C C y additional head from merge
2742 # C H n merge with a head
2741 # C H n merge with a head
2743 #
2742 #
2744 # H H n head merge: head count decreases
2743 # H H n head merge: head count decreases
2745
2744
2746 if not opts.get('close_branch'):
2745 if not opts.get('close_branch'):
2747 for r in parents:
2746 for r in parents:
2748 if r.closesbranch() and r.branch() == branch:
2747 if r.closesbranch() and r.branch() == branch:
2749 repo.ui.status(_('reopening closed branch head %d\n') % r.rev())
2748 repo.ui.status(_('reopening closed branch head %d\n') % r.rev())
2750
2749
2751 if repo.ui.debugflag:
2750 if repo.ui.debugflag:
2752 repo.ui.write(_('committed changeset %d:%s\n') % (ctx.rev(), ctx.hex()))
2751 repo.ui.write(_('committed changeset %d:%s\n') % (ctx.rev(), ctx.hex()))
2753 elif repo.ui.verbose:
2752 elif repo.ui.verbose:
2754 repo.ui.write(_('committed changeset %d:%s\n') % (ctx.rev(), ctx))
2753 repo.ui.write(_('committed changeset %d:%s\n') % (ctx.rev(), ctx))
2755
2754
2756 def postcommitstatus(repo, pats, opts):
2755 def postcommitstatus(repo, pats, opts):
2757 return repo.status(match=scmutil.match(repo[None], pats, opts))
2756 return repo.status(match=scmutil.match(repo[None], pats, opts))
2758
2757
2759 def revert(ui, repo, ctx, parents, *pats, **opts):
2758 def revert(ui, repo, ctx, parents, *pats, **opts):
2760 opts = pycompat.byteskwargs(opts)
2759 opts = pycompat.byteskwargs(opts)
2761 parent, p2 = parents
2760 parent, p2 = parents
2762 node = ctx.node()
2761 node = ctx.node()
2763
2762
2764 mf = ctx.manifest()
2763 mf = ctx.manifest()
2765 if node == p2:
2764 if node == p2:
2766 parent = p2
2765 parent = p2
2767
2766
2768 # need all matching names in dirstate and manifest of target rev,
2767 # need all matching names in dirstate and manifest of target rev,
2769 # so have to walk both. do not print errors if files exist in one
2768 # so have to walk both. do not print errors if files exist in one
2770 # but not other. in both cases, filesets should be evaluated against
2769 # but not other. in both cases, filesets should be evaluated against
2771 # workingctx to get consistent result (issue4497). this means 'set:**'
2770 # workingctx to get consistent result (issue4497). this means 'set:**'
2772 # cannot be used to select missing files from target rev.
2771 # cannot be used to select missing files from target rev.
2773
2772
2774 # `names` is a mapping for all elements in working copy and target revision
2773 # `names` is a mapping for all elements in working copy and target revision
2775 # The mapping is in the form:
2774 # The mapping is in the form:
2776 # <abs path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
2775 # <abs path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
2777 names = {}
2776 names = {}
2778
2777
2779 with repo.wlock():
2778 with repo.wlock():
2780 ## filling of the `names` mapping
2779 ## filling of the `names` mapping
2781 # walk dirstate to fill `names`
2780 # walk dirstate to fill `names`
2782
2781
2783 interactive = opts.get('interactive', False)
2782 interactive = opts.get('interactive', False)
2784 wctx = repo[None]
2783 wctx = repo[None]
2785 m = scmutil.match(wctx, pats, opts)
2784 m = scmutil.match(wctx, pats, opts)
2786
2785
2787 # we'll need this later
2786 # we'll need this later
2788 targetsubs = sorted(s for s in wctx.substate if m(s))
2787 targetsubs = sorted(s for s in wctx.substate if m(s))
2789
2788
2790 if not m.always():
2789 if not m.always():
2791 matcher = matchmod.badmatch(m, lambda x, y: False)
2790 matcher = matchmod.badmatch(m, lambda x, y: False)
2792 for abs in wctx.walk(matcher):
2791 for abs in wctx.walk(matcher):
2793 names[abs] = m.rel(abs), m.exact(abs)
2792 names[abs] = m.rel(abs), m.exact(abs)
2794
2793
2795 # walk target manifest to fill `names`
2794 # walk target manifest to fill `names`
2796
2795
2797 def badfn(path, msg):
2796 def badfn(path, msg):
2798 if path in names:
2797 if path in names:
2799 return
2798 return
2800 if path in ctx.substate:
2799 if path in ctx.substate:
2801 return
2800 return
2802 path_ = path + '/'
2801 path_ = path + '/'
2803 for f in names:
2802 for f in names:
2804 if f.startswith(path_):
2803 if f.startswith(path_):
2805 return
2804 return
2806 ui.warn("%s: %s\n" % (m.rel(path), msg))
2805 ui.warn("%s: %s\n" % (m.rel(path), msg))
2807
2806
2808 for abs in ctx.walk(matchmod.badmatch(m, badfn)):
2807 for abs in ctx.walk(matchmod.badmatch(m, badfn)):
2809 if abs not in names:
2808 if abs not in names:
2810 names[abs] = m.rel(abs), m.exact(abs)
2809 names[abs] = m.rel(abs), m.exact(abs)
2811
2810
2812 # Find status of all file in `names`.
2811 # Find status of all file in `names`.
2813 m = scmutil.matchfiles(repo, names)
2812 m = scmutil.matchfiles(repo, names)
2814
2813
2815 changes = repo.status(node1=node, match=m,
2814 changes = repo.status(node1=node, match=m,
2816 unknown=True, ignored=True, clean=True)
2815 unknown=True, ignored=True, clean=True)
2817 else:
2816 else:
2818 changes = repo.status(node1=node, match=m)
2817 changes = repo.status(node1=node, match=m)
2819 for kind in changes:
2818 for kind in changes:
2820 for abs in kind:
2819 for abs in kind:
2821 names[abs] = m.rel(abs), m.exact(abs)
2820 names[abs] = m.rel(abs), m.exact(abs)
2822
2821
2823 m = scmutil.matchfiles(repo, names)
2822 m = scmutil.matchfiles(repo, names)
2824
2823
2825 modified = set(changes.modified)
2824 modified = set(changes.modified)
2826 added = set(changes.added)
2825 added = set(changes.added)
2827 removed = set(changes.removed)
2826 removed = set(changes.removed)
2828 _deleted = set(changes.deleted)
2827 _deleted = set(changes.deleted)
2829 unknown = set(changes.unknown)
2828 unknown = set(changes.unknown)
2830 unknown.update(changes.ignored)
2829 unknown.update(changes.ignored)
2831 clean = set(changes.clean)
2830 clean = set(changes.clean)
2832 modadded = set()
2831 modadded = set()
2833
2832
2834 # We need to account for the state of the file in the dirstate,
2833 # We need to account for the state of the file in the dirstate,
2835 # even when we revert against something else than parent. This will
2834 # even when we revert against something else than parent. This will
2836 # slightly alter the behavior of revert (doing back up or not, delete
2835 # slightly alter the behavior of revert (doing back up or not, delete
2837 # or just forget etc).
2836 # or just forget etc).
2838 if parent == node:
2837 if parent == node:
2839 dsmodified = modified
2838 dsmodified = modified
2840 dsadded = added
2839 dsadded = added
2841 dsremoved = removed
2840 dsremoved = removed
2842 # store all local modifications, useful later for rename detection
2841 # store all local modifications, useful later for rename detection
2843 localchanges = dsmodified | dsadded
2842 localchanges = dsmodified | dsadded
2844 modified, added, removed = set(), set(), set()
2843 modified, added, removed = set(), set(), set()
2845 else:
2844 else:
2846 changes = repo.status(node1=parent, match=m)
2845 changes = repo.status(node1=parent, match=m)
2847 dsmodified = set(changes.modified)
2846 dsmodified = set(changes.modified)
2848 dsadded = set(changes.added)
2847 dsadded = set(changes.added)
2849 dsremoved = set(changes.removed)
2848 dsremoved = set(changes.removed)
2850 # store all local modifications, useful later for rename detection
2849 # store all local modifications, useful later for rename detection
2851 localchanges = dsmodified | dsadded
2850 localchanges = dsmodified | dsadded
2852
2851
2853 # only take into account for removes between wc and target
2852 # only take into account for removes between wc and target
2854 clean |= dsremoved - removed
2853 clean |= dsremoved - removed
2855 dsremoved &= removed
2854 dsremoved &= removed
2856 # distinct between dirstate remove and other
2855 # distinct between dirstate remove and other
2857 removed -= dsremoved
2856 removed -= dsremoved
2858
2857
2859 modadded = added & dsmodified
2858 modadded = added & dsmodified
2860 added -= modadded
2859 added -= modadded
2861
2860
2862 # tell newly modified apart.
2861 # tell newly modified apart.
2863 dsmodified &= modified
2862 dsmodified &= modified
2864 dsmodified |= modified & dsadded # dirstate added may need backup
2863 dsmodified |= modified & dsadded # dirstate added may need backup
2865 modified -= dsmodified
2864 modified -= dsmodified
2866
2865
2867 # We need to wait for some post-processing to update this set
2866 # We need to wait for some post-processing to update this set
2868 # before making the distinction. The dirstate will be used for
2867 # before making the distinction. The dirstate will be used for
2869 # that purpose.
2868 # that purpose.
2870 dsadded = added
2869 dsadded = added
2871
2870
2872 # in case of merge, files that are actually added can be reported as
2871 # in case of merge, files that are actually added can be reported as
2873 # modified, we need to post process the result
2872 # modified, we need to post process the result
2874 if p2 != nullid:
2873 if p2 != nullid:
2875 mergeadd = set(dsmodified)
2874 mergeadd = set(dsmodified)
2876 for path in dsmodified:
2875 for path in dsmodified:
2877 if path in mf:
2876 if path in mf:
2878 mergeadd.remove(path)
2877 mergeadd.remove(path)
2879 dsadded |= mergeadd
2878 dsadded |= mergeadd
2880 dsmodified -= mergeadd
2879 dsmodified -= mergeadd
2881
2880
2882 # if f is a rename, update `names` to also revert the source
2881 # if f is a rename, update `names` to also revert the source
2883 cwd = repo.getcwd()
2882 cwd = repo.getcwd()
2884 for f in localchanges:
2883 for f in localchanges:
2885 src = repo.dirstate.copied(f)
2884 src = repo.dirstate.copied(f)
2886 # XXX should we check for rename down to target node?
2885 # XXX should we check for rename down to target node?
2887 if src and src not in names and repo.dirstate[src] == 'r':
2886 if src and src not in names and repo.dirstate[src] == 'r':
2888 dsremoved.add(src)
2887 dsremoved.add(src)
2889 names[src] = (repo.pathto(src, cwd), True)
2888 names[src] = (repo.pathto(src, cwd), True)
2890
2889
2891 # determine the exact nature of the deleted changesets
2890 # determine the exact nature of the deleted changesets
2892 deladded = set(_deleted)
2891 deladded = set(_deleted)
2893 for path in _deleted:
2892 for path in _deleted:
2894 if path in mf:
2893 if path in mf:
2895 deladded.remove(path)
2894 deladded.remove(path)
2896 deleted = _deleted - deladded
2895 deleted = _deleted - deladded
2897
2896
2898 # distinguish between file to forget and the other
2897 # distinguish between file to forget and the other
2899 added = set()
2898 added = set()
2900 for abs in dsadded:
2899 for abs in dsadded:
2901 if repo.dirstate[abs] != 'a':
2900 if repo.dirstate[abs] != 'a':
2902 added.add(abs)
2901 added.add(abs)
2903 dsadded -= added
2902 dsadded -= added
2904
2903
2905 for abs in deladded:
2904 for abs in deladded:
2906 if repo.dirstate[abs] == 'a':
2905 if repo.dirstate[abs] == 'a':
2907 dsadded.add(abs)
2906 dsadded.add(abs)
2908 deladded -= dsadded
2907 deladded -= dsadded
2909
2908
2910 # For files marked as removed, we check if an unknown file is present at
2909 # For files marked as removed, we check if an unknown file is present at
2911 # the same path. If a such file exists it may need to be backed up.
2910 # the same path. If a such file exists it may need to be backed up.
2912 # Making the distinction at this stage helps have simpler backup
2911 # Making the distinction at this stage helps have simpler backup
2913 # logic.
2912 # logic.
2914 removunk = set()
2913 removunk = set()
2915 for abs in removed:
2914 for abs in removed:
2916 target = repo.wjoin(abs)
2915 target = repo.wjoin(abs)
2917 if os.path.lexists(target):
2916 if os.path.lexists(target):
2918 removunk.add(abs)
2917 removunk.add(abs)
2919 removed -= removunk
2918 removed -= removunk
2920
2919
2921 dsremovunk = set()
2920 dsremovunk = set()
2922 for abs in dsremoved:
2921 for abs in dsremoved:
2923 target = repo.wjoin(abs)
2922 target = repo.wjoin(abs)
2924 if os.path.lexists(target):
2923 if os.path.lexists(target):
2925 dsremovunk.add(abs)
2924 dsremovunk.add(abs)
2926 dsremoved -= dsremovunk
2925 dsremoved -= dsremovunk
2927
2926
2928 # action to be actually performed by revert
2927 # action to be actually performed by revert
2929 # (<list of file>, message>) tuple
2928 # (<list of file>, message>) tuple
2930 actions = {'revert': ([], _('reverting %s\n')),
2929 actions = {'revert': ([], _('reverting %s\n')),
2931 'add': ([], _('adding %s\n')),
2930 'add': ([], _('adding %s\n')),
2932 'remove': ([], _('removing %s\n')),
2931 'remove': ([], _('removing %s\n')),
2933 'drop': ([], _('removing %s\n')),
2932 'drop': ([], _('removing %s\n')),
2934 'forget': ([], _('forgetting %s\n')),
2933 'forget': ([], _('forgetting %s\n')),
2935 'undelete': ([], _('undeleting %s\n')),
2934 'undelete': ([], _('undeleting %s\n')),
2936 'noop': (None, _('no changes needed to %s\n')),
2935 'noop': (None, _('no changes needed to %s\n')),
2937 'unknown': (None, _('file not managed: %s\n')),
2936 'unknown': (None, _('file not managed: %s\n')),
2938 }
2937 }
2939
2938
2940 # "constant" that convey the backup strategy.
2939 # "constant" that convey the backup strategy.
2941 # All set to `discard` if `no-backup` is set do avoid checking
2940 # All set to `discard` if `no-backup` is set do avoid checking
2942 # no_backup lower in the code.
2941 # no_backup lower in the code.
2943 # These values are ordered for comparison purposes
2942 # These values are ordered for comparison purposes
2944 backupinteractive = 3 # do backup if interactively modified
2943 backupinteractive = 3 # do backup if interactively modified
2945 backup = 2 # unconditionally do backup
2944 backup = 2 # unconditionally do backup
2946 check = 1 # check if the existing file differs from target
2945 check = 1 # check if the existing file differs from target
2947 discard = 0 # never do backup
2946 discard = 0 # never do backup
2948 if opts.get('no_backup'):
2947 if opts.get('no_backup'):
2949 backupinteractive = backup = check = discard
2948 backupinteractive = backup = check = discard
2950 if interactive:
2949 if interactive:
2951 dsmodifiedbackup = backupinteractive
2950 dsmodifiedbackup = backupinteractive
2952 else:
2951 else:
2953 dsmodifiedbackup = backup
2952 dsmodifiedbackup = backup
2954 tobackup = set()
2953 tobackup = set()
2955
2954
2956 backupanddel = actions['remove']
2955 backupanddel = actions['remove']
2957 if not opts.get('no_backup'):
2956 if not opts.get('no_backup'):
2958 backupanddel = actions['drop']
2957 backupanddel = actions['drop']
2959
2958
2960 disptable = (
2959 disptable = (
2961 # dispatch table:
2960 # dispatch table:
2962 # file state
2961 # file state
2963 # action
2962 # action
2964 # make backup
2963 # make backup
2965
2964
2966 ## Sets that results that will change file on disk
2965 ## Sets that results that will change file on disk
2967 # Modified compared to target, no local change
2966 # Modified compared to target, no local change
2968 (modified, actions['revert'], discard),
2967 (modified, actions['revert'], discard),
2969 # Modified compared to target, but local file is deleted
2968 # Modified compared to target, but local file is deleted
2970 (deleted, actions['revert'], discard),
2969 (deleted, actions['revert'], discard),
2971 # Modified compared to target, local change
2970 # Modified compared to target, local change
2972 (dsmodified, actions['revert'], dsmodifiedbackup),
2971 (dsmodified, actions['revert'], dsmodifiedbackup),
2973 # Added since target
2972 # Added since target
2974 (added, actions['remove'], discard),
2973 (added, actions['remove'], discard),
2975 # Added in working directory
2974 # Added in working directory
2976 (dsadded, actions['forget'], discard),
2975 (dsadded, actions['forget'], discard),
2977 # Added since target, have local modification
2976 # Added since target, have local modification
2978 (modadded, backupanddel, backup),
2977 (modadded, backupanddel, backup),
2979 # Added since target but file is missing in working directory
2978 # Added since target but file is missing in working directory
2980 (deladded, actions['drop'], discard),
2979 (deladded, actions['drop'], discard),
2981 # Removed since target, before working copy parent
2980 # Removed since target, before working copy parent
2982 (removed, actions['add'], discard),
2981 (removed, actions['add'], discard),
2983 # Same as `removed` but an unknown file exists at the same path
2982 # Same as `removed` but an unknown file exists at the same path
2984 (removunk, actions['add'], check),
2983 (removunk, actions['add'], check),
2985 # Removed since targe, marked as such in working copy parent
2984 # Removed since targe, marked as such in working copy parent
2986 (dsremoved, actions['undelete'], discard),
2985 (dsremoved, actions['undelete'], discard),
2987 # Same as `dsremoved` but an unknown file exists at the same path
2986 # Same as `dsremoved` but an unknown file exists at the same path
2988 (dsremovunk, actions['undelete'], check),
2987 (dsremovunk, actions['undelete'], check),
2989 ## the following sets does not result in any file changes
2988 ## the following sets does not result in any file changes
2990 # File with no modification
2989 # File with no modification
2991 (clean, actions['noop'], discard),
2990 (clean, actions['noop'], discard),
2992 # Existing file, not tracked anywhere
2991 # Existing file, not tracked anywhere
2993 (unknown, actions['unknown'], discard),
2992 (unknown, actions['unknown'], discard),
2994 )
2993 )
2995
2994
2996 for abs, (rel, exact) in sorted(names.items()):
2995 for abs, (rel, exact) in sorted(names.items()):
2997 # target file to be touch on disk (relative to cwd)
2996 # target file to be touch on disk (relative to cwd)
2998 target = repo.wjoin(abs)
2997 target = repo.wjoin(abs)
2999 # search the entry in the dispatch table.
2998 # search the entry in the dispatch table.
3000 # if the file is in any of these sets, it was touched in the working
2999 # if the file is in any of these sets, it was touched in the working
3001 # directory parent and we are sure it needs to be reverted.
3000 # directory parent and we are sure it needs to be reverted.
3002 for table, (xlist, msg), dobackup in disptable:
3001 for table, (xlist, msg), dobackup in disptable:
3003 if abs not in table:
3002 if abs not in table:
3004 continue
3003 continue
3005 if xlist is not None:
3004 if xlist is not None:
3006 xlist.append(abs)
3005 xlist.append(abs)
3007 if dobackup:
3006 if dobackup:
3008 # If in interactive mode, don't automatically create
3007 # If in interactive mode, don't automatically create
3009 # .orig files (issue4793)
3008 # .orig files (issue4793)
3010 if dobackup == backupinteractive:
3009 if dobackup == backupinteractive:
3011 tobackup.add(abs)
3010 tobackup.add(abs)
3012 elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])):
3011 elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])):
3013 bakname = scmutil.origpath(ui, repo, rel)
3012 bakname = scmutil.origpath(ui, repo, rel)
3014 ui.note(_('saving current version of %s as %s\n') %
3013 ui.note(_('saving current version of %s as %s\n') %
3015 (rel, bakname))
3014 (rel, bakname))
3016 if not opts.get('dry_run'):
3015 if not opts.get('dry_run'):
3017 if interactive:
3016 if interactive:
3018 util.copyfile(target, bakname)
3017 util.copyfile(target, bakname)
3019 else:
3018 else:
3020 util.rename(target, bakname)
3019 util.rename(target, bakname)
3021 if opts.get('dry_run'):
3020 if opts.get('dry_run'):
3022 if ui.verbose or not exact:
3021 if ui.verbose or not exact:
3023 ui.status(msg % rel)
3022 ui.status(msg % rel)
3024 elif exact:
3023 elif exact:
3025 ui.warn(msg % rel)
3024 ui.warn(msg % rel)
3026 break
3025 break
3027
3026
3028 if not opts.get('dry_run'):
3027 if not opts.get('dry_run'):
3029 needdata = ('revert', 'add', 'undelete')
3028 needdata = ('revert', 'add', 'undelete')
3030 oplist = [actions[name][0] for name in needdata]
3029 oplist = [actions[name][0] for name in needdata]
3031 prefetch = scmutil.prefetchfiles
3030 prefetch = scmutil.prefetchfiles
3032 matchfiles = scmutil.matchfiles
3031 matchfiles = scmutil.matchfiles
3033 prefetch(repo, [ctx.rev()],
3032 prefetch(repo, [ctx.rev()],
3034 matchfiles(repo,
3033 matchfiles(repo,
3035 [f for sublist in oplist for f in sublist]))
3034 [f for sublist in oplist for f in sublist]))
3036 _performrevert(repo, parents, ctx, names, actions, interactive,
3035 _performrevert(repo, parents, ctx, names, actions, interactive,
3037 tobackup)
3036 tobackup)
3038
3037
3039 if targetsubs:
3038 if targetsubs:
3040 # Revert the subrepos on the revert list
3039 # Revert the subrepos on the revert list
3041 for sub in targetsubs:
3040 for sub in targetsubs:
3042 try:
3041 try:
3043 wctx.sub(sub).revert(ctx.substate[sub], *pats,
3042 wctx.sub(sub).revert(ctx.substate[sub], *pats,
3044 **pycompat.strkwargs(opts))
3043 **pycompat.strkwargs(opts))
3045 except KeyError:
3044 except KeyError:
3046 raise error.Abort("subrepository '%s' does not exist in %s!"
3045 raise error.Abort("subrepository '%s' does not exist in %s!"
3047 % (sub, short(ctx.node())))
3046 % (sub, short(ctx.node())))
3048
3047
3049 def _performrevert(repo, parents, ctx, names, actions, interactive=False,
3048 def _performrevert(repo, parents, ctx, names, actions, interactive=False,
3050 tobackup=None):
3049 tobackup=None):
3051 """function that actually perform all the actions computed for revert
3050 """function that actually perform all the actions computed for revert
3052
3051
3053 This is an independent function to let extension to plug in and react to
3052 This is an independent function to let extension to plug in and react to
3054 the imminent revert.
3053 the imminent revert.
3055
3054
3056 Make sure you have the working directory locked when calling this function.
3055 Make sure you have the working directory locked when calling this function.
3057 """
3056 """
3058 parent, p2 = parents
3057 parent, p2 = parents
3059 node = ctx.node()
3058 node = ctx.node()
3060 excluded_files = []
3059 excluded_files = []
3061
3060
3062 def checkout(f):
3061 def checkout(f):
3063 fc = ctx[f]
3062 fc = ctx[f]
3064 repo.wwrite(f, fc.data(), fc.flags())
3063 repo.wwrite(f, fc.data(), fc.flags())
3065
3064
3066 def doremove(f):
3065 def doremove(f):
3067 try:
3066 try:
3068 rmdir = repo.ui.configbool('experimental', 'removeemptydirs')
3067 rmdir = repo.ui.configbool('experimental', 'removeemptydirs')
3069 repo.wvfs.unlinkpath(f, rmdir=rmdir)
3068 repo.wvfs.unlinkpath(f, rmdir=rmdir)
3070 except OSError:
3069 except OSError:
3071 pass
3070 pass
3072 repo.dirstate.remove(f)
3071 repo.dirstate.remove(f)
3073
3072
3074 def prntstatusmsg(action, f):
3073 def prntstatusmsg(action, f):
3075 rel, exact = names[f]
3074 rel, exact = names[f]
3076 if repo.ui.verbose or not exact:
3075 if repo.ui.verbose or not exact:
3077 repo.ui.status(actions[action][1] % rel)
3076 repo.ui.status(actions[action][1] % rel)
3078
3077
3079 audit_path = pathutil.pathauditor(repo.root, cached=True)
3078 audit_path = pathutil.pathauditor(repo.root, cached=True)
3080 for f in actions['forget'][0]:
3079 for f in actions['forget'][0]:
3081 if interactive:
3080 if interactive:
3082 choice = repo.ui.promptchoice(
3081 choice = repo.ui.promptchoice(
3083 _("forget added file %s (Yn)?$$ &Yes $$ &No") % f)
3082 _("forget added file %s (Yn)?$$ &Yes $$ &No") % f)
3084 if choice == 0:
3083 if choice == 0:
3085 prntstatusmsg('forget', f)
3084 prntstatusmsg('forget', f)
3086 repo.dirstate.drop(f)
3085 repo.dirstate.drop(f)
3087 else:
3086 else:
3088 excluded_files.append(f)
3087 excluded_files.append(f)
3089 else:
3088 else:
3090 prntstatusmsg('forget', f)
3089 prntstatusmsg('forget', f)
3091 repo.dirstate.drop(f)
3090 repo.dirstate.drop(f)
3092 for f in actions['remove'][0]:
3091 for f in actions['remove'][0]:
3093 audit_path(f)
3092 audit_path(f)
3094 if interactive:
3093 if interactive:
3095 choice = repo.ui.promptchoice(
3094 choice = repo.ui.promptchoice(
3096 _("remove added file %s (Yn)?$$ &Yes $$ &No") % f)
3095 _("remove added file %s (Yn)?$$ &Yes $$ &No") % f)
3097 if choice == 0:
3096 if choice == 0:
3098 prntstatusmsg('remove', f)
3097 prntstatusmsg('remove', f)
3099 doremove(f)
3098 doremove(f)
3100 else:
3099 else:
3101 excluded_files.append(f)
3100 excluded_files.append(f)
3102 else:
3101 else:
3103 prntstatusmsg('remove', f)
3102 prntstatusmsg('remove', f)
3104 doremove(f)
3103 doremove(f)
3105 for f in actions['drop'][0]:
3104 for f in actions['drop'][0]:
3106 audit_path(f)
3105 audit_path(f)
3107 prntstatusmsg('drop', f)
3106 prntstatusmsg('drop', f)
3108 repo.dirstate.remove(f)
3107 repo.dirstate.remove(f)
3109
3108
3110 normal = None
3109 normal = None
3111 if node == parent:
3110 if node == parent:
3112 # We're reverting to our parent. If possible, we'd like status
3111 # We're reverting to our parent. If possible, we'd like status
3113 # to report the file as clean. We have to use normallookup for
3112 # to report the file as clean. We have to use normallookup for
3114 # merges to avoid losing information about merged/dirty files.
3113 # merges to avoid losing information about merged/dirty files.
3115 if p2 != nullid:
3114 if p2 != nullid:
3116 normal = repo.dirstate.normallookup
3115 normal = repo.dirstate.normallookup
3117 else:
3116 else:
3118 normal = repo.dirstate.normal
3117 normal = repo.dirstate.normal
3119
3118
3120 newlyaddedandmodifiedfiles = set()
3119 newlyaddedandmodifiedfiles = set()
3121 if interactive:
3120 if interactive:
3122 # Prompt the user for changes to revert
3121 # Prompt the user for changes to revert
3123 torevert = [f for f in actions['revert'][0] if f not in excluded_files]
3122 torevert = [f for f in actions['revert'][0] if f not in excluded_files]
3124 m = scmutil.matchfiles(repo, torevert)
3123 m = scmutil.matchfiles(repo, torevert)
3125 diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
3124 diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
3126 diffopts.nodates = True
3125 diffopts.nodates = True
3127 diffopts.git = True
3126 diffopts.git = True
3128 operation = 'discard'
3127 operation = 'discard'
3129 reversehunks = True
3128 reversehunks = True
3130 if node != parent:
3129 if node != parent:
3131 operation = 'apply'
3130 operation = 'apply'
3132 reversehunks = False
3131 reversehunks = False
3133 if reversehunks:
3132 if reversehunks:
3134 diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts)
3133 diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts)
3135 else:
3134 else:
3136 diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
3135 diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
3137 originalchunks = patch.parsepatch(diff)
3136 originalchunks = patch.parsepatch(diff)
3138
3137
3139 try:
3138 try:
3140
3139
3141 chunks, opts = recordfilter(repo.ui, originalchunks,
3140 chunks, opts = recordfilter(repo.ui, originalchunks,
3142 operation=operation)
3141 operation=operation)
3143 if reversehunks:
3142 if reversehunks:
3144 chunks = patch.reversehunks(chunks)
3143 chunks = patch.reversehunks(chunks)
3145
3144
3146 except error.PatchError as err:
3145 except error.PatchError as err:
3147 raise error.Abort(_('error parsing patch: %s') % err)
3146 raise error.Abort(_('error parsing patch: %s') % err)
3148
3147
3149 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
3148 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
3150 if tobackup is None:
3149 if tobackup is None:
3151 tobackup = set()
3150 tobackup = set()
3152 # Apply changes
3151 # Apply changes
3153 fp = stringio()
3152 fp = stringio()
3154 # chunks are serialized per file, but files aren't sorted
3153 # chunks are serialized per file, but files aren't sorted
3155 for f in sorted(set(c.header.filename() for c in chunks if ishunk(c))):
3154 for f in sorted(set(c.header.filename() for c in chunks if ishunk(c))):
3156 prntstatusmsg('revert', f)
3155 prntstatusmsg('revert', f)
3157 for c in chunks:
3156 for c in chunks:
3158 if ishunk(c):
3157 if ishunk(c):
3159 abs = c.header.filename()
3158 abs = c.header.filename()
3160 # Create a backup file only if this hunk should be backed up
3159 # Create a backup file only if this hunk should be backed up
3161 if c.header.filename() in tobackup:
3160 if c.header.filename() in tobackup:
3162 target = repo.wjoin(abs)
3161 target = repo.wjoin(abs)
3163 bakname = scmutil.origpath(repo.ui, repo, m.rel(abs))
3162 bakname = scmutil.origpath(repo.ui, repo, m.rel(abs))
3164 util.copyfile(target, bakname)
3163 util.copyfile(target, bakname)
3165 tobackup.remove(abs)
3164 tobackup.remove(abs)
3166 c.write(fp)
3165 c.write(fp)
3167 dopatch = fp.tell()
3166 dopatch = fp.tell()
3168 fp.seek(0)
3167 fp.seek(0)
3169 if dopatch:
3168 if dopatch:
3170 try:
3169 try:
3171 patch.internalpatch(repo.ui, repo, fp, 1, eolmode=None)
3170 patch.internalpatch(repo.ui, repo, fp, 1, eolmode=None)
3172 except error.PatchError as err:
3171 except error.PatchError as err:
3173 raise error.Abort(pycompat.bytestr(err))
3172 raise error.Abort(pycompat.bytestr(err))
3174 del fp
3173 del fp
3175 else:
3174 else:
3176 for f in actions['revert'][0]:
3175 for f in actions['revert'][0]:
3177 prntstatusmsg('revert', f)
3176 prntstatusmsg('revert', f)
3178 checkout(f)
3177 checkout(f)
3179 if normal:
3178 if normal:
3180 normal(f)
3179 normal(f)
3181
3180
3182 for f in actions['add'][0]:
3181 for f in actions['add'][0]:
3183 # Don't checkout modified files, they are already created by the diff
3182 # Don't checkout modified files, they are already created by the diff
3184 if f not in newlyaddedandmodifiedfiles:
3183 if f not in newlyaddedandmodifiedfiles:
3185 prntstatusmsg('add', f)
3184 prntstatusmsg('add', f)
3186 checkout(f)
3185 checkout(f)
3187 repo.dirstate.add(f)
3186 repo.dirstate.add(f)
3188
3187
3189 normal = repo.dirstate.normallookup
3188 normal = repo.dirstate.normallookup
3190 if node == parent and p2 == nullid:
3189 if node == parent and p2 == nullid:
3191 normal = repo.dirstate.normal
3190 normal = repo.dirstate.normal
3192 for f in actions['undelete'][0]:
3191 for f in actions['undelete'][0]:
3193 prntstatusmsg('undelete', f)
3192 prntstatusmsg('undelete', f)
3194 checkout(f)
3193 checkout(f)
3195 normal(f)
3194 normal(f)
3196
3195
3197 copied = copies.pathcopies(repo[parent], ctx)
3196 copied = copies.pathcopies(repo[parent], ctx)
3198
3197
3199 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
3198 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
3200 if f in copied:
3199 if f in copied:
3201 repo.dirstate.copy(copied[f], f)
3200 repo.dirstate.copy(copied[f], f)
3202
3201
3203 # a list of (ui, repo, otherpeer, opts, missing) functions called by
3202 # a list of (ui, repo, otherpeer, opts, missing) functions called by
3204 # commands.outgoing. "missing" is "missing" of the result of
3203 # commands.outgoing. "missing" is "missing" of the result of
3205 # "findcommonoutgoing()"
3204 # "findcommonoutgoing()"
3206 outgoinghooks = util.hooks()
3205 outgoinghooks = util.hooks()
3207
3206
3208 # a list of (ui, repo) functions called by commands.summary
3207 # a list of (ui, repo) functions called by commands.summary
3209 summaryhooks = util.hooks()
3208 summaryhooks = util.hooks()
3210
3209
3211 # a list of (ui, repo, opts, changes) functions called by commands.summary.
3210 # a list of (ui, repo, opts, changes) functions called by commands.summary.
3212 #
3211 #
3213 # functions should return tuple of booleans below, if 'changes' is None:
3212 # functions should return tuple of booleans below, if 'changes' is None:
3214 # (whether-incomings-are-needed, whether-outgoings-are-needed)
3213 # (whether-incomings-are-needed, whether-outgoings-are-needed)
3215 #
3214 #
3216 # otherwise, 'changes' is a tuple of tuples below:
3215 # otherwise, 'changes' is a tuple of tuples below:
3217 # - (sourceurl, sourcebranch, sourcepeer, incoming)
3216 # - (sourceurl, sourcebranch, sourcepeer, incoming)
3218 # - (desturl, destbranch, destpeer, outgoing)
3217 # - (desturl, destbranch, destpeer, outgoing)
3219 summaryremotehooks = util.hooks()
3218 summaryremotehooks = util.hooks()
3220
3219
3221 # A list of state files kept by multistep operations like graft.
3220 # A list of state files kept by multistep operations like graft.
3222 # Since graft cannot be aborted, it is considered 'clearable' by update.
3221 # Since graft cannot be aborted, it is considered 'clearable' by update.
3223 # note: bisect is intentionally excluded
3222 # note: bisect is intentionally excluded
3224 # (state file, clearable, allowcommit, error, hint)
3223 # (state file, clearable, allowcommit, error, hint)
3225 unfinishedstates = [
3224 unfinishedstates = [
3226 ('graftstate', True, False, _('graft in progress'),
3225 ('graftstate', True, False, _('graft in progress'),
3227 _("use 'hg graft --continue' or 'hg graft --stop' to stop")),
3226 _("use 'hg graft --continue' or 'hg graft --stop' to stop")),
3228 ('updatestate', True, False, _('last update was interrupted'),
3227 ('updatestate', True, False, _('last update was interrupted'),
3229 _("use 'hg update' to get a consistent checkout"))
3228 _("use 'hg update' to get a consistent checkout"))
3230 ]
3229 ]
3231
3230
3232 def checkunfinished(repo, commit=False):
3231 def checkunfinished(repo, commit=False):
3233 '''Look for an unfinished multistep operation, like graft, and abort
3232 '''Look for an unfinished multistep operation, like graft, and abort
3234 if found. It's probably good to check this right before
3233 if found. It's probably good to check this right before
3235 bailifchanged().
3234 bailifchanged().
3236 '''
3235 '''
3237 # Check for non-clearable states first, so things like rebase will take
3236 # Check for non-clearable states first, so things like rebase will take
3238 # precedence over update.
3237 # precedence over update.
3239 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3238 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3240 if clearable or (commit and allowcommit):
3239 if clearable or (commit and allowcommit):
3241 continue
3240 continue
3242 if repo.vfs.exists(f):
3241 if repo.vfs.exists(f):
3243 raise error.Abort(msg, hint=hint)
3242 raise error.Abort(msg, hint=hint)
3244
3243
3245 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3244 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3246 if not clearable or (commit and allowcommit):
3245 if not clearable or (commit and allowcommit):
3247 continue
3246 continue
3248 if repo.vfs.exists(f):
3247 if repo.vfs.exists(f):
3249 raise error.Abort(msg, hint=hint)
3248 raise error.Abort(msg, hint=hint)
3250
3249
3251 def clearunfinished(repo):
3250 def clearunfinished(repo):
3252 '''Check for unfinished operations (as above), and clear the ones
3251 '''Check for unfinished operations (as above), and clear the ones
3253 that are clearable.
3252 that are clearable.
3254 '''
3253 '''
3255 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3254 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3256 if not clearable and repo.vfs.exists(f):
3255 if not clearable and repo.vfs.exists(f):
3257 raise error.Abort(msg, hint=hint)
3256 raise error.Abort(msg, hint=hint)
3258 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3257 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3259 if clearable and repo.vfs.exists(f):
3258 if clearable and repo.vfs.exists(f):
3260 util.unlink(repo.vfs.join(f))
3259 util.unlink(repo.vfs.join(f))
3261
3260
3262 afterresolvedstates = [
3261 afterresolvedstates = [
3263 ('graftstate',
3262 ('graftstate',
3264 _('hg graft --continue')),
3263 _('hg graft --continue')),
3265 ]
3264 ]
3266
3265
3267 def howtocontinue(repo):
3266 def howtocontinue(repo):
3268 '''Check for an unfinished operation and return the command to finish
3267 '''Check for an unfinished operation and return the command to finish
3269 it.
3268 it.
3270
3269
3271 afterresolvedstates tuples define a .hg/{file} and the corresponding
3270 afterresolvedstates tuples define a .hg/{file} and the corresponding
3272 command needed to finish it.
3271 command needed to finish it.
3273
3272
3274 Returns a (msg, warning) tuple. 'msg' is a string and 'warning' is
3273 Returns a (msg, warning) tuple. 'msg' is a string and 'warning' is
3275 a boolean.
3274 a boolean.
3276 '''
3275 '''
3277 contmsg = _("continue: %s")
3276 contmsg = _("continue: %s")
3278 for f, msg in afterresolvedstates:
3277 for f, msg in afterresolvedstates:
3279 if repo.vfs.exists(f):
3278 if repo.vfs.exists(f):
3280 return contmsg % msg, True
3279 return contmsg % msg, True
3281 if repo[None].dirty(missing=True, merge=False, branch=False):
3280 if repo[None].dirty(missing=True, merge=False, branch=False):
3282 return contmsg % _("hg commit"), False
3281 return contmsg % _("hg commit"), False
3283 return None, None
3282 return None, None
3284
3283
3285 def checkafterresolved(repo):
3284 def checkafterresolved(repo):
3286 '''Inform the user about the next action after completing hg resolve
3285 '''Inform the user about the next action after completing hg resolve
3287
3286
3288 If there's a matching afterresolvedstates, howtocontinue will yield
3287 If there's a matching afterresolvedstates, howtocontinue will yield
3289 repo.ui.warn as the reporter.
3288 repo.ui.warn as the reporter.
3290
3289
3291 Otherwise, it will yield repo.ui.note.
3290 Otherwise, it will yield repo.ui.note.
3292 '''
3291 '''
3293 msg, warning = howtocontinue(repo)
3292 msg, warning = howtocontinue(repo)
3294 if msg is not None:
3293 if msg is not None:
3295 if warning:
3294 if warning:
3296 repo.ui.warn("%s\n" % msg)
3295 repo.ui.warn("%s\n" % msg)
3297 else:
3296 else:
3298 repo.ui.note("%s\n" % msg)
3297 repo.ui.note("%s\n" % msg)
3299
3298
3300 def wrongtooltocontinue(repo, task):
3299 def wrongtooltocontinue(repo, task):
3301 '''Raise an abort suggesting how to properly continue if there is an
3300 '''Raise an abort suggesting how to properly continue if there is an
3302 active task.
3301 active task.
3303
3302
3304 Uses howtocontinue() to find the active task.
3303 Uses howtocontinue() to find the active task.
3305
3304
3306 If there's no task (repo.ui.note for 'hg commit'), it does not offer
3305 If there's no task (repo.ui.note for 'hg commit'), it does not offer
3307 a hint.
3306 a hint.
3308 '''
3307 '''
3309 after = howtocontinue(repo)
3308 after = howtocontinue(repo)
3310 hint = None
3309 hint = None
3311 if after[1]:
3310 if after[1]:
3312 hint = after[0]
3311 hint = after[0]
3313 raise error.Abort(_('no %s in progress') % task, hint=hint)
3312 raise error.Abort(_('no %s in progress') % task, hint=hint)
@@ -1,717 +1,718 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.
7 > myinit:doc = This is my documented alias for init.
8 > myinit:help = [OPTIONS] [BLA] [BLE]
8 > myinit:help = [OPTIONS] [BLA] [BLE]
9 > mycommit = commit
9 > mycommit = commit
10 > mycommit:doc = This is my alias with only doc.
10 > mycommit:doc = This is my alias with only doc.
11 > optionalrepo = showconfig alias.myinit
11 > optionalrepo = showconfig alias.myinit
12 > cleanstatus = status -c
12 > cleanstatus = status -c
13 > cleanstatus:help = [ONLYHELPHERE]
13 > cleanstatus:help = [ONLYHELPHERE]
14 > unknown = bargle
14 > unknown = bargle
15 > ambiguous = s
15 > ambiguous = s
16 > recursive = recursive
16 > recursive = recursive
17 > disabled = email
17 > disabled = email
18 > nodefinition =
18 > nodefinition =
19 > noclosingquotation = '
19 > noclosingquotation = '
20 > no--cwd = status --cwd elsewhere
20 > no--cwd = status --cwd elsewhere
21 > no-R = status -R elsewhere
21 > no-R = status -R elsewhere
22 > no--repo = status --repo elsewhere
22 > no--repo = status --repo elsewhere
23 > no--repository = status --repository elsewhere
23 > no--repository = status --repository elsewhere
24 > no--config = status --config a.config=1
24 > no--config = status --config a.config=1
25 > mylog = log
25 > mylog = log
26 > lognull = log -r null
26 > lognull = log -r null
27 > lognull:doc = Logs the null rev
27 > lognull:doc = Logs the null rev
28 > lognull:help = foo bar baz
28 > lognull:help = foo bar baz
29 > shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
29 > shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
30 > positional = log --template '{\$2} {\$1} | {date|isodate}\n'
30 > positional = log --template '{\$2} {\$1} | {date|isodate}\n'
31 > dln = lognull --debug
31 > dln = lognull --debug
32 > recursivedoc = dln
32 > recursivedoc = dln
33 > recursivedoc:doc = Logs the null rev in debug mode
33 > recursivedoc:doc = Logs the null rev in debug mode
34 > nousage = rollback
34 > nousage = rollback
35 > put = export -r 0 -o "\$FOO/%R.diff"
35 > put = export -r 0 -o "\$FOO/%R.diff"
36 > blank = !printf '\n'
36 > blank = !printf '\n'
37 > self = !printf '\$0\n'
37 > self = !printf '\$0\n'
38 > echoall = !printf '\$@\n'
38 > echoall = !printf '\$@\n'
39 > echo1 = !printf '\$1\n'
39 > echo1 = !printf '\$1\n'
40 > echo2 = !printf '\$2\n'
40 > echo2 = !printf '\$2\n'
41 > echo13 = !printf '\$1 \$3\n'
41 > echo13 = !printf '\$1 \$3\n'
42 > echotokens = !printf "%s\n" "\$@"
42 > echotokens = !printf "%s\n" "\$@"
43 > count = !hg log -r "\$@" --template=. | wc -c | sed -e 's/ //g'
43 > count = !hg log -r "\$@" --template=. | wc -c | sed -e 's/ //g'
44 > mcount = !hg log \$@ --template=. | wc -c | sed -e 's/ //g'
44 > mcount = !hg log \$@ --template=. | wc -c | sed -e 's/ //g'
45 > rt = root
45 > rt = root
46 > tglog = log -G --template "{rev}:{node|short}: '{desc}' {branches}\n"
46 > tglog = log -G --template "{rev}:{node|short}: '{desc}' {branches}\n"
47 > idalias = id
47 > idalias = id
48 > idaliaslong = id
48 > idaliaslong = id
49 > idaliasshell = !echo test
49 > idaliasshell = !echo test
50 > parentsshell1 = !echo one
50 > parentsshell1 = !echo one
51 > parentsshell2 = !echo two
51 > parentsshell2 = !echo two
52 > escaped1 = !printf 'test\$\$test\n'
52 > escaped1 = !printf 'test\$\$test\n'
53 > escaped2 = !sh -c 'echo "HGFOO is \$\$HGFOO"'
53 > escaped2 = !sh -c 'echo "HGFOO is \$\$HGFOO"'
54 > escaped3 = !sh -c 'echo "\$1 is \$\$\$1"'
54 > escaped3 = !sh -c 'echo "\$1 is \$\$\$1"'
55 > escaped4 = !printf '\$\$0 \$\$@\n'
55 > escaped4 = !printf '\$\$0 \$\$@\n'
56 > exit1 = !sh -c 'exit 1'
56 > exit1 = !sh -c 'exit 1'
57 >
57 >
58 > [defaults]
58 > [defaults]
59 > mylog = -q
59 > mylog = -q
60 > lognull = -q
60 > lognull = -q
61 > log = -v
61 > log = -v
62 > EOF
62 > EOF
63
63
64 basic
64 basic
65
65
66 $ hg myinit alias
66 $ hg myinit alias
67
67
68 help
68 help
69
69
70 $ hg help -c | grep myinit
70 $ hg help -c | grep myinit
71 myinit This is my documented alias for init.
71 myinit This is my documented alias for init.
72 $ hg help -c | grep mycommit
72 $ hg help -c | grep mycommit
73 mycommit This is my alias with only doc.
73 mycommit This is my alias with only doc.
74 $ hg help -c | grep cleanstatus
74 $ hg help -c | grep cleanstatus
75 cleanstatus show changed files in the working directory
75 cleanstatus show changed files in the working directory
76 $ hg help -c | grep lognull
76 $ hg help -c | grep lognull
77 lognull Logs the null rev
77 lognull Logs the null rev
78 $ hg help -c | grep dln
78 $ hg help -c | grep dln
79 dln Logs the null rev
79 dln Logs the null rev
80 $ hg help -c | grep recursivedoc
80 $ hg help -c | grep recursivedoc
81 recursivedoc Logs the null rev in debug mode
81 recursivedoc Logs the null rev in debug mode
82 $ hg help myinit
82 $ hg help myinit
83 hg myinit [OPTIONS] [BLA] [BLE]
83 hg myinit [OPTIONS] [BLA] [BLE]
84
84
85 alias for: hg init
85 alias for: hg init
86
86
87 This is my documented alias for init.
87 This is my documented alias for init.
88
88
89 defined by: * (glob)
89 defined by: * (glob)
90 */* (glob) (?)
90 */* (glob) (?)
91 */* (glob) (?)
91 */* (glob) (?)
92 */* (glob) (?)
92 */* (glob) (?)
93
93
94 options:
94 options:
95
95
96 -e --ssh CMD specify ssh command to use
96 -e --ssh CMD specify ssh command to use
97 --remotecmd CMD specify hg command to run on the remote side
97 --remotecmd CMD specify hg command to run on the remote side
98 --insecure do not verify server certificate (ignoring web.cacerts
98 --insecure do not verify server certificate (ignoring web.cacerts
99 config)
99 config)
100
100
101 (some details hidden, use --verbose to show complete help)
101 (some details hidden, use --verbose to show complete help)
102
102
103 $ hg help mycommit
103 $ hg help mycommit
104 hg mycommit [OPTION]... [FILE]...
104 hg mycommit [OPTION]... [FILE]...
105
105
106 alias for: hg commit
106 alias for: hg commit
107
107
108 This is my alias with only doc.
108 This is my alias with only doc.
109
109
110 defined by: * (glob)
110 defined by: * (glob)
111 */* (glob) (?)
111 */* (glob) (?)
112 */* (glob) (?)
112 */* (glob) (?)
113 */* (glob) (?)
113 */* (glob) (?)
114
114
115 options ([+] can be repeated):
115 options ([+] can be repeated):
116
116
117 -A --addremove mark new/missing files as added/removed before
117 -A --addremove mark new/missing files as added/removed before
118 committing
118 committing
119 --close-branch mark a branch head as closed
119 --close-branch mark a branch head as closed
120 --amend amend the parent of the working directory
120 --amend amend the parent of the working directory
121 -s --secret use the secret phase for committing
121 -s --secret use the secret phase for committing
122 -e --edit invoke editor on commit messages
122 -e --edit invoke editor on commit messages
123 -i --interactive use interactive mode
123 -i --interactive use interactive mode
124 -I --include PATTERN [+] include names matching the given patterns
124 -I --include PATTERN [+] include names matching the given patterns
125 -X --exclude PATTERN [+] exclude names matching the given patterns
125 -X --exclude PATTERN [+] exclude names matching the given patterns
126 -m --message TEXT use text as commit message
126 -m --message TEXT use text as commit message
127 -l --logfile FILE read commit message from file
127 -l --logfile FILE read commit message from file
128 -d --date DATE record the specified date as commit date
128 -d --date DATE record the specified date as commit date
129 -u --user USER record the specified user as committer
129 -u --user USER record the specified user as committer
130 -S --subrepos recurse into subrepositories
130 -S --subrepos recurse into subrepositories
131
131
132 (some details hidden, use --verbose to show complete help)
132 (some details hidden, use --verbose to show complete help)
133
133
134 $ hg help cleanstatus
134 $ hg help cleanstatus
135 hg cleanstatus [ONLYHELPHERE]
135 hg cleanstatus [ONLYHELPHERE]
136
136
137 alias for: hg status -c
137 alias for: hg status -c
138
138
139 show changed files in the working directory
139 show changed files in the working directory
140
140
141 Show status of files in the repository. If names are given, only files
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
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,
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
144 -C/--copies or -A/--all are given. Unless options described with "show
145 only ..." are given, the options -mardu are used.
145 only ..." are given, the options -mardu are used.
146
146
147 Option -q/--quiet hides untracked (unknown and ignored) files unless
147 Option -q/--quiet hides untracked (unknown and ignored) files unless
148 explicitly requested with -u/--unknown or -i/--ignored.
148 explicitly requested with -u/--unknown or -i/--ignored.
149
149
150 Note:
150 Note:
151 'hg status' may appear to disagree with diff if permissions have
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
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
153 report permission changes and diff only reports changes relative to one
154 merge parent.
154 merge parent.
155
155
156 If one revision is given, it is used as the base revision. If two
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
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
158 option can also be used as a shortcut to list the changed files of a
159 revision from its first parent.
159 revision from its first parent.
160
160
161 The codes used to show the status of files are:
161 The codes used to show the status of files are:
162
162
163 M = modified
163 M = modified
164 A = added
164 A = added
165 R = removed
165 R = removed
166 C = clean
166 C = clean
167 ! = missing (deleted by non-hg command, but still tracked)
167 ! = missing (deleted by non-hg command, but still tracked)
168 ? = not tracked
168 ? = not tracked
169 I = ignored
169 I = ignored
170 = origin of the previous file (with --copies)
170 = origin of the previous file (with --copies)
171
171
172 Returns 0 on success.
172 Returns 0 on success.
173
173
174 defined by: * (glob)
174 defined by: * (glob)
175 */* (glob) (?)
175 */* (glob) (?)
176 */* (glob) (?)
176 */* (glob) (?)
177 */* (glob) (?)
177 */* (glob) (?)
178
178
179 options ([+] can be repeated):
179 options ([+] can be repeated):
180
180
181 -A --all show status of all files
181 -A --all show status of all files
182 -m --modified show only modified files
182 -m --modified show only modified files
183 -a --added show only added files
183 -a --added show only added files
184 -r --removed show only removed files
184 -r --removed show only removed files
185 -d --deleted show only deleted (but tracked) files
185 -d --deleted show only deleted (but tracked) files
186 -c --clean show only files without changes
186 -c --clean show only files without changes
187 -u --unknown show only unknown (not tracked) files
187 -u --unknown show only unknown (not tracked) files
188 -i --ignored show only ignored files
188 -i --ignored show only ignored files
189 -n --no-status hide status prefix
189 -n --no-status hide status prefix
190 -C --copies show source of copied files
190 -C --copies show source of copied files
191 -0 --print0 end filenames with NUL, for use with xargs
191 -0 --print0 end filenames with NUL, for use with xargs
192 --rev REV [+] show difference from revision
192 --rev REV [+] show difference from revision
193 --change REV list the changed files of a revision
193 --change REV list the changed files of a revision
194 -I --include PATTERN [+] include names matching the given patterns
194 -I --include PATTERN [+] include names matching the given patterns
195 -X --exclude PATTERN [+] exclude names matching the given patterns
195 -X --exclude PATTERN [+] exclude names matching the given patterns
196 -S --subrepos recurse into subrepositories
196 -S --subrepos recurse into subrepositories
197 -T --template TEMPLATE display with template
197
198
198 (some details hidden, use --verbose to show complete help)
199 (some details hidden, use --verbose to show complete help)
199
200
200 $ hg help recursivedoc | head -n 5
201 $ hg help recursivedoc | head -n 5
201 hg recursivedoc foo bar baz
202 hg recursivedoc foo bar baz
202
203
203 alias for: hg dln
204 alias for: hg dln
204
205
205 Logs the null rev in debug mode
206 Logs the null rev in debug mode
206
207
207 unknown
208 unknown
208
209
209 $ hg unknown
210 $ hg unknown
210 abort: alias 'unknown' resolves to unknown command 'bargle'
211 abort: alias 'unknown' resolves to unknown command 'bargle'
211 [255]
212 [255]
212 $ hg help unknown
213 $ hg help unknown
213 alias 'unknown' resolves to unknown command 'bargle'
214 alias 'unknown' resolves to unknown command 'bargle'
214
215
215
216
216 ambiguous
217 ambiguous
217
218
218 $ hg ambiguous
219 $ hg ambiguous
219 abort: alias 'ambiguous' resolves to ambiguous command 's'
220 abort: alias 'ambiguous' resolves to ambiguous command 's'
220 [255]
221 [255]
221 $ hg help ambiguous
222 $ hg help ambiguous
222 alias 'ambiguous' resolves to ambiguous command 's'
223 alias 'ambiguous' resolves to ambiguous command 's'
223
224
224
225
225 recursive
226 recursive
226
227
227 $ hg recursive
228 $ hg recursive
228 abort: alias 'recursive' resolves to unknown command 'recursive'
229 abort: alias 'recursive' resolves to unknown command 'recursive'
229 [255]
230 [255]
230 $ hg help recursive
231 $ hg help recursive
231 alias 'recursive' resolves to unknown command 'recursive'
232 alias 'recursive' resolves to unknown command 'recursive'
232
233
233
234
234 disabled
235 disabled
235
236
236 $ hg disabled
237 $ hg disabled
237 abort: alias 'disabled' resolves to unknown command 'email'
238 abort: alias 'disabled' resolves to unknown command 'email'
238 ('email' is provided by 'patchbomb' extension)
239 ('email' is provided by 'patchbomb' extension)
239 [255]
240 [255]
240 $ hg help disabled
241 $ hg help disabled
241 alias 'disabled' resolves to unknown command 'email'
242 alias 'disabled' resolves to unknown command 'email'
242
243
243 'email' is provided by the following extension:
244 'email' is provided by the following extension:
244
245
245 patchbomb command to send changesets as (a series of) patch emails
246 patchbomb command to send changesets as (a series of) patch emails
246
247
247 (use 'hg help extensions' for information on enabling extensions)
248 (use 'hg help extensions' for information on enabling extensions)
248
249
249
250
250 no definition
251 no definition
251
252
252 $ hg nodef
253 $ hg nodef
253 abort: no definition for alias 'nodefinition'
254 abort: no definition for alias 'nodefinition'
254 [255]
255 [255]
255 $ hg help nodef
256 $ hg help nodef
256 no definition for alias 'nodefinition'
257 no definition for alias 'nodefinition'
257
258
258
259
259 no closing quotation
260 no closing quotation
260
261
261 $ hg noclosing
262 $ hg noclosing
262 abort: error in definition for alias 'noclosingquotation': No closing quotation
263 abort: error in definition for alias 'noclosingquotation': No closing quotation
263 [255]
264 [255]
264 $ hg help noclosing
265 $ hg help noclosing
265 error in definition for alias 'noclosingquotation': No closing quotation
266 error in definition for alias 'noclosingquotation': No closing quotation
266
267
267 "--" in alias definition should be preserved
268 "--" in alias definition should be preserved
268
269
269 $ hg --config alias.dash='cat --' -R alias dash -r0
270 $ hg --config alias.dash='cat --' -R alias dash -r0
270 abort: -r0 not under root '$TESTTMP/alias'
271 abort: -r0 not under root '$TESTTMP/alias'
271 (consider using '--cwd alias')
272 (consider using '--cwd alias')
272 [255]
273 [255]
273
274
274 invalid options
275 invalid options
275
276
276 $ hg no--cwd
277 $ hg no--cwd
277 abort: error in definition for alias 'no--cwd': --cwd may only be given on the command line
278 abort: error in definition for alias 'no--cwd': --cwd may only be given on the command line
278 [255]
279 [255]
279 $ hg help no--cwd
280 $ hg help no--cwd
280 error in definition for alias 'no--cwd': --cwd may only be given on the
281 error in definition for alias 'no--cwd': --cwd may only be given on the
281 command line
282 command line
282 $ hg no-R
283 $ hg no-R
283 abort: error in definition for alias 'no-R': -R may only be given on the command line
284 abort: error in definition for alias 'no-R': -R may only be given on the command line
284 [255]
285 [255]
285 $ hg help no-R
286 $ hg help no-R
286 error in definition for alias 'no-R': -R may only be given on the command line
287 error in definition for alias 'no-R': -R may only be given on the command line
287 $ hg no--repo
288 $ hg no--repo
288 abort: error in definition for alias 'no--repo': --repo may only be given on the command line
289 abort: error in definition for alias 'no--repo': --repo may only be given on the command line
289 [255]
290 [255]
290 $ hg help no--repo
291 $ hg help no--repo
291 error in definition for alias 'no--repo': --repo may only be given on the
292 error in definition for alias 'no--repo': --repo may only be given on the
292 command line
293 command line
293 $ hg no--repository
294 $ hg no--repository
294 abort: error in definition for alias 'no--repository': --repository may only be given on the command line
295 abort: error in definition for alias 'no--repository': --repository may only be given on the command line
295 [255]
296 [255]
296 $ hg help no--repository
297 $ hg help no--repository
297 error in definition for alias 'no--repository': --repository may only be given
298 error in definition for alias 'no--repository': --repository may only be given
298 on the command line
299 on the command line
299 $ hg no--config
300 $ hg no--config
300 abort: error in definition for alias 'no--config': --config may only be given on the command line
301 abort: error in definition for alias 'no--config': --config may only be given on the command line
301 [255]
302 [255]
302 $ hg no --config alias.no='--repo elsewhere --cwd elsewhere status'
303 $ hg no --config alias.no='--repo elsewhere --cwd elsewhere status'
303 abort: error in definition for alias 'no': --repo/--cwd may only be given on the command line
304 abort: error in definition for alias 'no': --repo/--cwd may only be given on the command line
304 [255]
305 [255]
305 $ hg no --config alias.no='--repo elsewhere'
306 $ hg no --config alias.no='--repo elsewhere'
306 abort: error in definition for alias 'no': --repo may only be given on the command line
307 abort: error in definition for alias 'no': --repo may only be given on the command line
307 [255]
308 [255]
308
309
309 optional repository
310 optional repository
310
311
311 #if no-outer-repo
312 #if no-outer-repo
312 $ hg optionalrepo
313 $ hg optionalrepo
313 init
314 init
314 #endif
315 #endif
315 $ cd alias
316 $ cd alias
316 $ cat > .hg/hgrc <<EOF
317 $ cat > .hg/hgrc <<EOF
317 > [alias]
318 > [alias]
318 > myinit = init -q
319 > myinit = init -q
319 > EOF
320 > EOF
320 $ hg optionalrepo
321 $ hg optionalrepo
321 init -q
322 init -q
322
323
323 no usage
324 no usage
324
325
325 $ hg nousage
326 $ hg nousage
326 no rollback information available
327 no rollback information available
327 [1]
328 [1]
328
329
329 $ echo foo > foo
330 $ echo foo > foo
330 $ hg commit -Amfoo
331 $ hg commit -Amfoo
331 adding foo
332 adding foo
332
333
333 infer repository
334 infer repository
334
335
335 $ cd ..
336 $ cd ..
336
337
337 #if no-outer-repo
338 #if no-outer-repo
338 $ hg shortlog alias/foo
339 $ hg shortlog alias/foo
339 0 e63c23eaa88a | 1970-01-01 00:00 +0000
340 0 e63c23eaa88a | 1970-01-01 00:00 +0000
340 #endif
341 #endif
341
342
342 $ cd alias
343 $ cd alias
343
344
344 with opts
345 with opts
345
346
346 $ hg cleanst
347 $ hg cleanst
347 C foo
348 C foo
348
349
349
350
350 with opts and whitespace
351 with opts and whitespace
351
352
352 $ hg shortlog
353 $ hg shortlog
353 0 e63c23eaa88a | 1970-01-01 00:00 +0000
354 0 e63c23eaa88a | 1970-01-01 00:00 +0000
354
355
355 positional arguments
356 positional arguments
356
357
357 $ hg positional
358 $ hg positional
358 abort: too few arguments for command alias
359 abort: too few arguments for command alias
359 [255]
360 [255]
360 $ hg positional a
361 $ hg positional a
361 abort: too few arguments for command alias
362 abort: too few arguments for command alias
362 [255]
363 [255]
363 $ hg positional 'node|short' rev
364 $ hg positional 'node|short' rev
364 0 e63c23eaa88a | 1970-01-01 00:00 +0000
365 0 e63c23eaa88a | 1970-01-01 00:00 +0000
365
366
366 interaction with defaults
367 interaction with defaults
367
368
368 $ hg mylog
369 $ hg mylog
369 0:e63c23eaa88a
370 0:e63c23eaa88a
370 $ hg lognull
371 $ hg lognull
371 -1:000000000000
372 -1:000000000000
372
373
373
374
374 properly recursive
375 properly recursive
375
376
376 $ hg dln
377 $ hg dln
377 changeset: -1:0000000000000000000000000000000000000000
378 changeset: -1:0000000000000000000000000000000000000000
378 phase: public
379 phase: public
379 parent: -1:0000000000000000000000000000000000000000
380 parent: -1:0000000000000000000000000000000000000000
380 parent: -1:0000000000000000000000000000000000000000
381 parent: -1:0000000000000000000000000000000000000000
381 manifest: -1:0000000000000000000000000000000000000000
382 manifest: -1:0000000000000000000000000000000000000000
382 user:
383 user:
383 date: Thu Jan 01 00:00:00 1970 +0000
384 date: Thu Jan 01 00:00:00 1970 +0000
384 extra: branch=default
385 extra: branch=default
385
386
386
387
387
388
388 path expanding
389 path expanding
389
390
390 $ FOO=`pwd` hg put
391 $ FOO=`pwd` hg put
391 $ cat 0.diff
392 $ cat 0.diff
392 # HG changeset patch
393 # HG changeset patch
393 # User test
394 # User test
394 # Date 0 0
395 # Date 0 0
395 # Thu Jan 01 00:00:00 1970 +0000
396 # Thu Jan 01 00:00:00 1970 +0000
396 # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
397 # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
397 # Parent 0000000000000000000000000000000000000000
398 # Parent 0000000000000000000000000000000000000000
398 foo
399 foo
399
400
400 diff -r 000000000000 -r e63c23eaa88a foo
401 diff -r 000000000000 -r e63c23eaa88a foo
401 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
402 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
402 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
403 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
403 @@ -0,0 +1,1 @@
404 @@ -0,0 +1,1 @@
404 +foo
405 +foo
405
406
406
407
407 simple shell aliases
408 simple shell aliases
408
409
409 $ hg blank
410 $ hg blank
410
411
411 $ hg blank foo
412 $ hg blank foo
412
413
413 $ hg self
414 $ hg self
414 self
415 self
415 $ hg echoall
416 $ hg echoall
416
417
417 $ hg echoall foo
418 $ hg echoall foo
418 foo
419 foo
419 $ hg echoall 'test $2' foo
420 $ hg echoall 'test $2' foo
420 test $2 foo
421 test $2 foo
421 $ hg echoall 'test $@' foo '$@'
422 $ hg echoall 'test $@' foo '$@'
422 test $@ foo $@
423 test $@ foo $@
423 $ hg echoall 'test "$@"' foo '"$@"'
424 $ hg echoall 'test "$@"' foo '"$@"'
424 test "$@" foo "$@"
425 test "$@" foo "$@"
425 $ hg echo1 foo bar baz
426 $ hg echo1 foo bar baz
426 foo
427 foo
427 $ hg echo2 foo bar baz
428 $ hg echo2 foo bar baz
428 bar
429 bar
429 $ hg echo13 foo bar baz test
430 $ hg echo13 foo bar baz test
430 foo baz
431 foo baz
431 $ hg echo2 foo
432 $ hg echo2 foo
432
433
433 $ hg echotokens
434 $ hg echotokens
434
435
435 $ hg echotokens foo 'bar $1 baz'
436 $ hg echotokens foo 'bar $1 baz'
436 foo
437 foo
437 bar $1 baz
438 bar $1 baz
438 $ hg echotokens 'test $2' foo
439 $ hg echotokens 'test $2' foo
439 test $2
440 test $2
440 foo
441 foo
441 $ hg echotokens 'test $@' foo '$@'
442 $ hg echotokens 'test $@' foo '$@'
442 test $@
443 test $@
443 foo
444 foo
444 $@
445 $@
445 $ hg echotokens 'test "$@"' foo '"$@"'
446 $ hg echotokens 'test "$@"' foo '"$@"'
446 test "$@"
447 test "$@"
447 foo
448 foo
448 "$@"
449 "$@"
449 $ echo bar > bar
450 $ echo bar > bar
450 $ hg commit -qA -m bar
451 $ hg commit -qA -m bar
451 $ hg count .
452 $ hg count .
452 1
453 1
453 $ hg count 'branch(default)'
454 $ hg count 'branch(default)'
454 2
455 2
455 $ hg mcount -r '"branch(default)"'
456 $ hg mcount -r '"branch(default)"'
456 2
457 2
457
458
458 $ hg tglog
459 $ hg tglog
459 @ 1:042423737847: 'bar'
460 @ 1:042423737847: 'bar'
460 |
461 |
461 o 0:e63c23eaa88a: 'foo'
462 o 0:e63c23eaa88a: 'foo'
462
463
463
464
464
465
465 shadowing
466 shadowing
466
467
467 $ hg i
468 $ hg i
468 hg: command 'i' is ambiguous:
469 hg: command 'i' is ambiguous:
469 idalias idaliaslong idaliasshell identify import incoming init
470 idalias idaliaslong idaliasshell identify import incoming init
470 [255]
471 [255]
471 $ hg id
472 $ hg id
472 042423737847 tip
473 042423737847 tip
473 $ hg ida
474 $ hg ida
474 hg: command 'ida' is ambiguous:
475 hg: command 'ida' is ambiguous:
475 idalias idaliaslong idaliasshell
476 idalias idaliaslong idaliasshell
476 [255]
477 [255]
477 $ hg idalias
478 $ hg idalias
478 042423737847 tip
479 042423737847 tip
479 $ hg idaliasl
480 $ hg idaliasl
480 042423737847 tip
481 042423737847 tip
481 $ hg idaliass
482 $ hg idaliass
482 test
483 test
483 $ hg parentsshell
484 $ hg parentsshell
484 hg: command 'parentsshell' is ambiguous:
485 hg: command 'parentsshell' is ambiguous:
485 parentsshell1 parentsshell2
486 parentsshell1 parentsshell2
486 [255]
487 [255]
487 $ hg parentsshell1
488 $ hg parentsshell1
488 one
489 one
489 $ hg parentsshell2
490 $ hg parentsshell2
490 two
491 two
491
492
492
493
493 shell aliases with global options
494 shell aliases with global options
494
495
495 $ hg init sub
496 $ hg init sub
496 $ cd sub
497 $ cd sub
497 $ hg count 'branch(default)'
498 $ hg count 'branch(default)'
498 abort: unknown revision 'default'!
499 abort: unknown revision 'default'!
499 0
500 0
500 $ hg -v count 'branch(default)'
501 $ hg -v count 'branch(default)'
501 abort: unknown revision 'default'!
502 abort: unknown revision 'default'!
502 0
503 0
503 $ hg -R .. count 'branch(default)'
504 $ hg -R .. count 'branch(default)'
504 abort: unknown revision 'default'!
505 abort: unknown revision 'default'!
505 0
506 0
506 $ hg --cwd .. count 'branch(default)'
507 $ hg --cwd .. count 'branch(default)'
507 2
508 2
508 $ hg echoall --cwd ..
509 $ hg echoall --cwd ..
509
510
510
511
511 "--" passed to shell alias should be preserved
512 "--" passed to shell alias should be preserved
512
513
513 $ hg --config alias.printf='!printf "$@"' printf '%s %s %s\n' -- --cwd ..
514 $ hg --config alias.printf='!printf "$@"' printf '%s %s %s\n' -- --cwd ..
514 -- --cwd ..
515 -- --cwd ..
515
516
516 repo specific shell aliases
517 repo specific shell aliases
517
518
518 $ cat >> .hg/hgrc <<EOF
519 $ cat >> .hg/hgrc <<EOF
519 > [alias]
520 > [alias]
520 > subalias = !echo sub
521 > subalias = !echo sub
521 > EOF
522 > EOF
522 $ cat >> ../.hg/hgrc <<EOF
523 $ cat >> ../.hg/hgrc <<EOF
523 > [alias]
524 > [alias]
524 > mainalias = !echo main
525 > mainalias = !echo main
525 > EOF
526 > EOF
526
527
527
528
528 shell alias defined in current repo
529 shell alias defined in current repo
529
530
530 $ hg subalias
531 $ hg subalias
531 sub
532 sub
532 $ hg --cwd .. subalias > /dev/null
533 $ hg --cwd .. subalias > /dev/null
533 hg: unknown command 'subalias'
534 hg: unknown command 'subalias'
534 (did you mean idalias?)
535 (did you mean idalias?)
535 [255]
536 [255]
536 $ hg -R .. subalias > /dev/null
537 $ hg -R .. subalias > /dev/null
537 hg: unknown command 'subalias'
538 hg: unknown command 'subalias'
538 (did you mean idalias?)
539 (did you mean idalias?)
539 [255]
540 [255]
540
541
541
542
542 shell alias defined in other repo
543 shell alias defined in other repo
543
544
544 $ hg mainalias > /dev/null
545 $ hg mainalias > /dev/null
545 hg: unknown command 'mainalias'
546 hg: unknown command 'mainalias'
546 (did you mean idalias?)
547 (did you mean idalias?)
547 [255]
548 [255]
548 $ hg -R .. mainalias
549 $ hg -R .. mainalias
549 main
550 main
550 $ hg --cwd .. mainalias
551 $ hg --cwd .. mainalias
551 main
552 main
552
553
553 typos get useful suggestions
554 typos get useful suggestions
554 $ hg --cwd .. manalias
555 $ hg --cwd .. manalias
555 hg: unknown command 'manalias'
556 hg: unknown command 'manalias'
556 (did you mean one of idalias, mainalias, manifest?)
557 (did you mean one of idalias, mainalias, manifest?)
557 [255]
558 [255]
558
559
559 shell aliases with escaped $ chars
560 shell aliases with escaped $ chars
560
561
561 $ hg escaped1
562 $ hg escaped1
562 test$test
563 test$test
563 $ hg escaped2
564 $ hg escaped2
564 HGFOO is BAR
565 HGFOO is BAR
565 $ hg escaped3 HGFOO
566 $ hg escaped3 HGFOO
566 HGFOO is BAR
567 HGFOO is BAR
567 $ hg escaped4 test
568 $ hg escaped4 test
568 $0 $@
569 $0 $@
569
570
570 abbreviated name, which matches against both shell alias and the
571 abbreviated name, which matches against both shell alias and the
571 command provided extension, should be aborted.
572 command provided extension, should be aborted.
572
573
573 $ cat >> .hg/hgrc <<EOF
574 $ cat >> .hg/hgrc <<EOF
574 > [extensions]
575 > [extensions]
575 > hgext.rebase =
576 > hgext.rebase =
576 > EOF
577 > EOF
577 #if windows
578 #if windows
578 $ cat >> .hg/hgrc <<EOF
579 $ cat >> .hg/hgrc <<EOF
579 > [alias]
580 > [alias]
580 > rebate = !echo this is %HG_ARGS%
581 > rebate = !echo this is %HG_ARGS%
581 > EOF
582 > EOF
582 #else
583 #else
583 $ cat >> .hg/hgrc <<EOF
584 $ cat >> .hg/hgrc <<EOF
584 > [alias]
585 > [alias]
585 > rebate = !echo this is \$HG_ARGS
586 > rebate = !echo this is \$HG_ARGS
586 > EOF
587 > EOF
587 #endif
588 #endif
588 $ cat >> .hg/hgrc <<EOF
589 $ cat >> .hg/hgrc <<EOF
589 > rebate:doc = This is my alias which just prints something.
590 > rebate:doc = This is my alias which just prints something.
590 > rebate:help = [MYARGS]
591 > rebate:help = [MYARGS]
591 > EOF
592 > EOF
592 $ hg reba
593 $ hg reba
593 hg: command 'reba' is ambiguous:
594 hg: command 'reba' is ambiguous:
594 rebase rebate
595 rebase rebate
595 [255]
596 [255]
596 $ hg rebat
597 $ hg rebat
597 this is rebate
598 this is rebate
598 $ hg rebat --foo-bar
599 $ hg rebat --foo-bar
599 this is rebate --foo-bar
600 this is rebate --foo-bar
600
601
601 help for a shell alias
602 help for a shell alias
602
603
603 $ hg help -c | grep rebate
604 $ hg help -c | grep rebate
604 rebate This is my alias which just prints something.
605 rebate This is my alias which just prints something.
605 $ hg help rebate
606 $ hg help rebate
606 hg rebate [MYARGS]
607 hg rebate [MYARGS]
607
608
608 shell alias for: echo this is %HG_ARGS% (windows !)
609 shell alias for: echo this is %HG_ARGS% (windows !)
609 shell alias for: echo this is $HG_ARGS (no-windows !)
610 shell alias for: echo this is $HG_ARGS (no-windows !)
610
611
611 This is my alias which just prints something.
612 This is my alias which just prints something.
612
613
613 defined by:* (glob)
614 defined by:* (glob)
614 */* (glob) (?)
615 */* (glob) (?)
615 */* (glob) (?)
616 */* (glob) (?)
616 */* (glob) (?)
617 */* (glob) (?)
617
618
618 (some details hidden, use --verbose to show complete help)
619 (some details hidden, use --verbose to show complete help)
619
620
620 invalid character in user-specified help
621 invalid character in user-specified help
621
622
622 >>> with open('.hg/hgrc', 'ab') as f:
623 >>> with open('.hg/hgrc', 'ab') as f:
623 ... f.write(b'[alias]\n'
624 ... f.write(b'[alias]\n'
624 ... b'invaliddoc = log\n'
625 ... b'invaliddoc = log\n'
625 ... b'invaliddoc:doc = \xc0\n'
626 ... b'invaliddoc:doc = \xc0\n'
626 ... b'invalidhelp = log\n'
627 ... b'invalidhelp = log\n'
627 ... b'invalidhelp:help = \xc0\n') and None
628 ... b'invalidhelp:help = \xc0\n') and None
628 $ hg help invaliddoc
629 $ hg help invaliddoc
629 non-ASCII character in alias definition 'invaliddoc:doc'
630 non-ASCII character in alias definition 'invaliddoc:doc'
630 $ hg help invalidhelp
631 $ hg help invalidhelp
631 non-ASCII character in alias definition 'invalidhelp:help'
632 non-ASCII character in alias definition 'invalidhelp:help'
632 $ hg invaliddoc
633 $ hg invaliddoc
633 abort: non-ASCII character in alias definition 'invaliddoc:doc'
634 abort: non-ASCII character in alias definition 'invaliddoc:doc'
634 [255]
635 [255]
635 $ hg invalidhelp
636 $ hg invalidhelp
636 abort: non-ASCII character in alias definition 'invalidhelp:help'
637 abort: non-ASCII character in alias definition 'invalidhelp:help'
637 [255]
638 [255]
638
639
639 invalid arguments
640 invalid arguments
640
641
641 $ hg rt foo
642 $ hg rt foo
642 hg rt: invalid arguments
643 hg rt: invalid arguments
643 hg rt
644 hg rt
644
645
645 alias for: hg root
646 alias for: hg root
646
647
647 (use 'hg rt -h' to show more help)
648 (use 'hg rt -h' to show more help)
648 [255]
649 [255]
649
650
650 invalid global arguments for normal commands, aliases, and shell aliases
651 invalid global arguments for normal commands, aliases, and shell aliases
651
652
652 $ hg --invalid root
653 $ hg --invalid root
653 hg: option --invalid not recognized
654 hg: option --invalid not recognized
654 (use 'hg help -v' for a list of global options)
655 (use 'hg help -v' for a list of global options)
655 [255]
656 [255]
656 $ hg --invalid mylog
657 $ hg --invalid mylog
657 hg: option --invalid not recognized
658 hg: option --invalid not recognized
658 (use 'hg help -v' for a list of global options)
659 (use 'hg help -v' for a list of global options)
659 [255]
660 [255]
660 $ hg --invalid blank
661 $ hg --invalid blank
661 hg: option --invalid not recognized
662 hg: option --invalid not recognized
662 (use 'hg help -v' for a list of global options)
663 (use 'hg help -v' for a list of global options)
663 [255]
664 [255]
664
665
665 environment variable changes in alias commands
666 environment variable changes in alias commands
666
667
667 $ cat > $TESTTMP/expandalias.py <<EOF
668 $ cat > $TESTTMP/expandalias.py <<EOF
668 > import os
669 > import os
669 > from mercurial import cmdutil, commands, registrar
670 > from mercurial import cmdutil, commands, registrar
670 > cmdtable = {}
671 > cmdtable = {}
671 > command = registrar.command(cmdtable)
672 > command = registrar.command(cmdtable)
672 > @command(b'expandalias')
673 > @command(b'expandalias')
673 > def expandalias(ui, repo, name):
674 > def expandalias(ui, repo, name):
674 > alias = cmdutil.findcmd(name, commands.table)[1][0]
675 > alias = cmdutil.findcmd(name, commands.table)[1][0]
675 > ui.write(b'%s args: %s\n' % (name, b' '.join(alias.args)))
676 > ui.write(b'%s args: %s\n' % (name, b' '.join(alias.args)))
676 > os.environ['COUNT'] = '2'
677 > os.environ['COUNT'] = '2'
677 > ui.write(b'%s args: %s (with COUNT=2)\n' % (name, b' '.join(alias.args)))
678 > ui.write(b'%s args: %s (with COUNT=2)\n' % (name, b' '.join(alias.args)))
678 > EOF
679 > EOF
679
680
680 $ cat >> $HGRCPATH <<'EOF'
681 $ cat >> $HGRCPATH <<'EOF'
681 > [extensions]
682 > [extensions]
682 > expandalias = $TESTTMP/expandalias.py
683 > expandalias = $TESTTMP/expandalias.py
683 > [alias]
684 > [alias]
684 > showcount = log -T "$COUNT" -r .
685 > showcount = log -T "$COUNT" -r .
685 > EOF
686 > EOF
686
687
687 $ COUNT=1 hg expandalias showcount
688 $ COUNT=1 hg expandalias showcount
688 showcount args: -T 1 -r .
689 showcount args: -T 1 -r .
689 showcount args: -T 2 -r . (with COUNT=2)
690 showcount args: -T 2 -r . (with COUNT=2)
690
691
691 This should show id:
692 This should show id:
692
693
693 $ hg --config alias.log='id' log
694 $ hg --config alias.log='id' log
694 000000000000 tip
695 000000000000 tip
695
696
696 This shouldn't:
697 This shouldn't:
697
698
698 $ hg --config alias.log='id' history
699 $ hg --config alias.log='id' history
699
700
700 $ cd ../..
701 $ cd ../..
701
702
702 return code of command and shell aliases:
703 return code of command and shell aliases:
703
704
704 $ hg mycommit -R alias
705 $ hg mycommit -R alias
705 nothing changed
706 nothing changed
706 [1]
707 [1]
707 $ hg exit1
708 $ hg exit1
708 [1]
709 [1]
709
710
710 #if no-outer-repo
711 #if no-outer-repo
711 $ hg root
712 $ hg root
712 abort: no repository found in '$TESTTMP' (.hg not found)!
713 abort: no repository found in '$TESTTMP' (.hg not found)!
713 [255]
714 [255]
714 $ hg --config alias.hgroot='!hg root' hgroot
715 $ hg --config alias.hgroot='!hg root' hgroot
715 abort: no repository found in '$TESTTMP' (.hg not found)!
716 abort: no repository found in '$TESTTMP' (.hg not found)!
716 [255]
717 [255]
717 #endif
718 #endif
@@ -1,219 +1,220 b''
1 test command parsing and dispatch
1 test command parsing and dispatch
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5
5
6 Redundant options used to crash (issue436):
6 Redundant options used to crash (issue436):
7 $ hg -v log -v
7 $ hg -v log -v
8 $ hg -v log -v x
8 $ hg -v log -v x
9
9
10 $ echo a > a
10 $ echo a > a
11 $ hg ci -Ama
11 $ hg ci -Ama
12 adding a
12 adding a
13
13
14 Missing arg:
14 Missing arg:
15
15
16 $ hg cat
16 $ hg cat
17 hg cat: invalid arguments
17 hg cat: invalid arguments
18 hg cat [OPTION]... FILE...
18 hg cat [OPTION]... FILE...
19
19
20 output the current or given revision of files
20 output the current or given revision of files
21
21
22 options ([+] can be repeated):
22 options ([+] can be repeated):
23
23
24 -o --output FORMAT print output to file with formatted name
24 -o --output FORMAT print output to file with formatted name
25 -r --rev REV print the given revision
25 -r --rev REV print the given revision
26 --decode apply any matching decode filter
26 --decode apply any matching decode filter
27 -I --include PATTERN [+] include names matching the given patterns
27 -I --include PATTERN [+] include names matching the given patterns
28 -X --exclude PATTERN [+] exclude names matching the given patterns
28 -X --exclude PATTERN [+] exclude names matching the given patterns
29 -T --template TEMPLATE display with template
29
30
30 (use 'hg cat -h' to show more help)
31 (use 'hg cat -h' to show more help)
31 [255]
32 [255]
32
33
33 Missing parameter for early option:
34 Missing parameter for early option:
34
35
35 $ hg log -R 2>&1 | grep 'hg log'
36 $ hg log -R 2>&1 | grep 'hg log'
36 hg log: option -R requires argument
37 hg log: option -R requires argument
37 hg log [OPTION]... [FILE]
38 hg log [OPTION]... [FILE]
38 (use 'hg log -h' to show more help)
39 (use 'hg log -h' to show more help)
39
40
40 "--" may be an option value:
41 "--" may be an option value:
41
42
42 $ hg -R -- log
43 $ hg -R -- log
43 abort: repository -- not found!
44 abort: repository -- not found!
44 [255]
45 [255]
45 $ hg log -R --
46 $ hg log -R --
46 abort: repository -- not found!
47 abort: repository -- not found!
47 [255]
48 [255]
48 $ hg log -T --
49 $ hg log -T --
49 -- (no-eol)
50 -- (no-eol)
50 $ hg log -T -- -k nomatch
51 $ hg log -T -- -k nomatch
51
52
52 Parsing of early options should stop at "--":
53 Parsing of early options should stop at "--":
53
54
54 $ hg cat -- --config=hooks.pre-cat=false
55 $ hg cat -- --config=hooks.pre-cat=false
55 --config=hooks.pre-cat=false: no such file in rev cb9a9f314b8b
56 --config=hooks.pre-cat=false: no such file in rev cb9a9f314b8b
56 [1]
57 [1]
57 $ hg cat -- --debugger
58 $ hg cat -- --debugger
58 --debugger: no such file in rev cb9a9f314b8b
59 --debugger: no such file in rev cb9a9f314b8b
59 [1]
60 [1]
60
61
61 Unparsable form of early options:
62 Unparsable form of early options:
62
63
63 $ hg cat --debugg
64 $ hg cat --debugg
64 abort: option --debugger may not be abbreviated!
65 abort: option --debugger may not be abbreviated!
65 [255]
66 [255]
66
67
67 Parsing failure of early options should be detected before executing the
68 Parsing failure of early options should be detected before executing the
68 command:
69 command:
69
70
70 $ hg log -b '--config=hooks.pre-log=false' default
71 $ hg log -b '--config=hooks.pre-log=false' default
71 abort: option --config may not be abbreviated!
72 abort: option --config may not be abbreviated!
72 [255]
73 [255]
73 $ hg log -b -R. default
74 $ hg log -b -R. default
74 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
75 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
75 [255]
76 [255]
76 $ hg log --cwd .. -b --cwd=. default
77 $ hg log --cwd .. -b --cwd=. default
77 abort: option --cwd may not be abbreviated!
78 abort: option --cwd may not be abbreviated!
78 [255]
79 [255]
79
80
80 However, we can't prevent it from loading extensions and configs:
81 However, we can't prevent it from loading extensions and configs:
81
82
82 $ cat <<EOF > bad.py
83 $ cat <<EOF > bad.py
83 > raise Exception('bad')
84 > raise Exception('bad')
84 > EOF
85 > EOF
85 $ hg log -b '--config=extensions.bad=bad.py' default
86 $ hg log -b '--config=extensions.bad=bad.py' default
86 *** failed to import extension bad from bad.py: bad
87 *** failed to import extension bad from bad.py: bad
87 abort: option --config may not be abbreviated!
88 abort: option --config may not be abbreviated!
88 [255]
89 [255]
89
90
90 $ mkdir -p badrepo/.hg
91 $ mkdir -p badrepo/.hg
91 $ echo 'invalid-syntax' > badrepo/.hg/hgrc
92 $ echo 'invalid-syntax' > badrepo/.hg/hgrc
92 $ hg log -b -Rbadrepo default
93 $ hg log -b -Rbadrepo default
93 hg: parse error at badrepo/.hg/hgrc:1: invalid-syntax
94 hg: parse error at badrepo/.hg/hgrc:1: invalid-syntax
94 [255]
95 [255]
95
96
96 $ hg log -b --cwd=inexistent default
97 $ hg log -b --cwd=inexistent default
97 abort: $ENOENT$: 'inexistent'
98 abort: $ENOENT$: 'inexistent'
98 [255]
99 [255]
99
100
100 $ hg log -b '--config=ui.traceback=yes' 2>&1 | grep '^Traceback'
101 $ hg log -b '--config=ui.traceback=yes' 2>&1 | grep '^Traceback'
101 Traceback (most recent call last):
102 Traceback (most recent call last):
102 $ hg log -b '--config=profiling.enabled=yes' 2>&1 | grep -i sample
103 $ hg log -b '--config=profiling.enabled=yes' 2>&1 | grep -i sample
103 Sample count: .*|No samples recorded\. (re)
104 Sample count: .*|No samples recorded\. (re)
104
105
105 Early options can't be specified in [aliases] and [defaults] because they are
106 Early options can't be specified in [aliases] and [defaults] because they are
106 applied before the command name is resolved:
107 applied before the command name is resolved:
107
108
108 $ hg log -b '--config=alias.log=log --config=hooks.pre-log=false'
109 $ hg log -b '--config=alias.log=log --config=hooks.pre-log=false'
109 hg log: option -b not recognized
110 hg log: option -b not recognized
110 error in definition for alias 'log': --config may only be given on the command
111 error in definition for alias 'log': --config may only be given on the command
111 line
112 line
112 [255]
113 [255]
113
114
114 $ hg log -b '--config=defaults.log=--config=hooks.pre-log=false'
115 $ hg log -b '--config=defaults.log=--config=hooks.pre-log=false'
115 abort: option --config may not be abbreviated!
116 abort: option --config may not be abbreviated!
116 [255]
117 [255]
117
118
118 Shell aliases bypass any command parsing rules but for the early one:
119 Shell aliases bypass any command parsing rules but for the early one:
119
120
120 $ hg log -b '--config=alias.log=!echo howdy'
121 $ hg log -b '--config=alias.log=!echo howdy'
121 howdy
122 howdy
122
123
123 Early options must come first if HGPLAIN=+strictflags is specified:
124 Early options must come first if HGPLAIN=+strictflags is specified:
124 (BUG: chg cherry-picks early options to pass them as a server command)
125 (BUG: chg cherry-picks early options to pass them as a server command)
125
126
126 #if no-chg
127 #if no-chg
127 $ HGPLAIN=+strictflags hg log -b --config='hooks.pre-log=false' default
128 $ HGPLAIN=+strictflags hg log -b --config='hooks.pre-log=false' default
128 abort: unknown revision '--config=hooks.pre-log=false'!
129 abort: unknown revision '--config=hooks.pre-log=false'!
129 [255]
130 [255]
130 $ HGPLAIN=+strictflags hg log -b -R. default
131 $ HGPLAIN=+strictflags hg log -b -R. default
131 abort: unknown revision '-R.'!
132 abort: unknown revision '-R.'!
132 [255]
133 [255]
133 $ HGPLAIN=+strictflags hg log -b --cwd=. default
134 $ HGPLAIN=+strictflags hg log -b --cwd=. default
134 abort: unknown revision '--cwd=.'!
135 abort: unknown revision '--cwd=.'!
135 [255]
136 [255]
136 #endif
137 #endif
137 $ HGPLAIN=+strictflags hg log -b --debugger default
138 $ HGPLAIN=+strictflags hg log -b --debugger default
138 abort: unknown revision '--debugger'!
139 abort: unknown revision '--debugger'!
139 [255]
140 [255]
140 $ HGPLAIN=+strictflags hg log -b --config='alias.log=!echo pwned' default
141 $ HGPLAIN=+strictflags hg log -b --config='alias.log=!echo pwned' default
141 abort: unknown revision '--config=alias.log=!echo pwned'!
142 abort: unknown revision '--config=alias.log=!echo pwned'!
142 [255]
143 [255]
143
144
144 $ HGPLAIN=+strictflags hg log --config='hooks.pre-log=false' -b default
145 $ HGPLAIN=+strictflags hg log --config='hooks.pre-log=false' -b default
145 abort: option --config may not be abbreviated!
146 abort: option --config may not be abbreviated!
146 [255]
147 [255]
147 $ HGPLAIN=+strictflags hg log -q --cwd=.. -b default
148 $ HGPLAIN=+strictflags hg log -q --cwd=.. -b default
148 abort: option --cwd may not be abbreviated!
149 abort: option --cwd may not be abbreviated!
149 [255]
150 [255]
150 $ HGPLAIN=+strictflags hg log -q -R . -b default
151 $ HGPLAIN=+strictflags hg log -q -R . -b default
151 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
152 abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
152 [255]
153 [255]
153
154
154 $ HGPLAIN=+strictflags hg --config='hooks.pre-log=false' log -b default
155 $ HGPLAIN=+strictflags hg --config='hooks.pre-log=false' log -b default
155 abort: pre-log hook exited with status 1
156 abort: pre-log hook exited with status 1
156 [255]
157 [255]
157 $ HGPLAIN=+strictflags hg --cwd .. -q -Ra log -b default
158 $ HGPLAIN=+strictflags hg --cwd .. -q -Ra log -b default
158 0:cb9a9f314b8b
159 0:cb9a9f314b8b
159 $ HGPLAIN=+strictflags hg --cwd .. -q --repository a log -b default
160 $ HGPLAIN=+strictflags hg --cwd .. -q --repository a log -b default
160 0:cb9a9f314b8b
161 0:cb9a9f314b8b
161 $ HGPLAIN=+strictflags hg --cwd .. -q --repo a log -b default
162 $ HGPLAIN=+strictflags hg --cwd .. -q --repo a log -b default
162 0:cb9a9f314b8b
163 0:cb9a9f314b8b
163
164
164 For compatibility reasons, HGPLAIN=+strictflags is not enabled by plain HGPLAIN:
165 For compatibility reasons, HGPLAIN=+strictflags is not enabled by plain HGPLAIN:
165
166
166 $ HGPLAIN= hg log --config='hooks.pre-log=false' -b default
167 $ HGPLAIN= hg log --config='hooks.pre-log=false' -b default
167 abort: pre-log hook exited with status 1
168 abort: pre-log hook exited with status 1
168 [255]
169 [255]
169 $ HGPLAINEXCEPT= hg log --cwd .. -q -Ra -b default
170 $ HGPLAINEXCEPT= hg log --cwd .. -q -Ra -b default
170 0:cb9a9f314b8b
171 0:cb9a9f314b8b
171
172
172 [defaults]
173 [defaults]
173
174
174 $ hg cat a
175 $ hg cat a
175 a
176 a
176 $ cat >> $HGRCPATH <<EOF
177 $ cat >> $HGRCPATH <<EOF
177 > [defaults]
178 > [defaults]
178 > cat = -r null
179 > cat = -r null
179 > EOF
180 > EOF
180 $ hg cat a
181 $ hg cat a
181 a: no such file in rev 000000000000
182 a: no such file in rev 000000000000
182 [1]
183 [1]
183
184
184 $ cd "$TESTTMP"
185 $ cd "$TESTTMP"
185
186
186 OSError "No such file or directory" / "The system cannot find the path
187 OSError "No such file or directory" / "The system cannot find the path
187 specified" should include filename even when it is empty
188 specified" should include filename even when it is empty
188
189
189 $ hg -R a archive ''
190 $ hg -R a archive ''
190 abort: *: '' (glob)
191 abort: *: '' (glob)
191 [255]
192 [255]
192
193
193 #if no-outer-repo
194 #if no-outer-repo
194
195
195 No repo:
196 No repo:
196
197
197 $ hg cat
198 $ hg cat
198 abort: no repository found in '$TESTTMP' (.hg not found)!
199 abort: no repository found in '$TESTTMP' (.hg not found)!
199 [255]
200 [255]
200
201
201 #endif
202 #endif
202
203
203 #if rmcwd
204 #if rmcwd
204
205
205 Current directory removed:
206 Current directory removed:
206
207
207 $ mkdir $TESTTMP/repo1
208 $ mkdir $TESTTMP/repo1
208 $ cd $TESTTMP/repo1
209 $ cd $TESTTMP/repo1
209 $ rm -rf $TESTTMP/repo1
210 $ rm -rf $TESTTMP/repo1
210
211
211 The output could be one of the following and something else:
212 The output could be one of the following and something else:
212 chg: abort: failed to getcwd (errno = *) (glob)
213 chg: abort: failed to getcwd (errno = *) (glob)
213 abort: error getting current working directory: * (glob)
214 abort: error getting current working directory: * (glob)
214 sh: 0: getcwd() failed: $ENOENT$
215 sh: 0: getcwd() failed: $ENOENT$
215 Since the exact behavior depends on the shell, only check it returns non-zero.
216 Since the exact behavior depends on the shell, only check it returns non-zero.
216 $ HGDEMANDIMPORT=disable hg version -q 2>/dev/null || false
217 $ HGDEMANDIMPORT=disable hg version -q 2>/dev/null || false
217 [1]
218 [1]
218
219
219 #endif
220 #endif
@@ -1,1756 +1,1758 b''
1 Test basic extension support
1 Test basic extension support
2
2
3 $ cat > foobar.py <<EOF
3 $ cat > foobar.py <<EOF
4 > import os
4 > import os
5 > from mercurial import commands, registrar
5 > from mercurial import commands, registrar
6 > cmdtable = {}
6 > cmdtable = {}
7 > command = registrar.command(cmdtable)
7 > command = registrar.command(cmdtable)
8 > configtable = {}
8 > configtable = {}
9 > configitem = registrar.configitem(configtable)
9 > configitem = registrar.configitem(configtable)
10 > configitem(b'tests', b'foo', default=b"Foo")
10 > configitem(b'tests', b'foo', default=b"Foo")
11 > def uisetup(ui):
11 > def uisetup(ui):
12 > ui.debug(b"uisetup called [debug]\\n")
12 > ui.debug(b"uisetup called [debug]\\n")
13 > ui.write(b"uisetup called\\n")
13 > ui.write(b"uisetup called\\n")
14 > ui.status(b"uisetup called [status]\\n")
14 > ui.status(b"uisetup called [status]\\n")
15 > ui.flush()
15 > ui.flush()
16 > def reposetup(ui, repo):
16 > def reposetup(ui, repo):
17 > ui.write(b"reposetup called for %s\\n" % os.path.basename(repo.root))
17 > ui.write(b"reposetup called for %s\\n" % os.path.basename(repo.root))
18 > ui.write(b"ui %s= repo.ui\\n" % (ui == repo.ui and b"=" or b"!"))
18 > ui.write(b"ui %s= repo.ui\\n" % (ui == repo.ui and b"=" or b"!"))
19 > ui.flush()
19 > ui.flush()
20 > @command(b'foo', [], b'hg foo')
20 > @command(b'foo', [], b'hg foo')
21 > def foo(ui, *args, **kwargs):
21 > def foo(ui, *args, **kwargs):
22 > foo = ui.config(b'tests', b'foo')
22 > foo = ui.config(b'tests', b'foo')
23 > ui.write(foo)
23 > ui.write(foo)
24 > ui.write(b"\\n")
24 > ui.write(b"\\n")
25 > @command(b'bar', [], b'hg bar', norepo=True)
25 > @command(b'bar', [], b'hg bar', norepo=True)
26 > def bar(ui, *args, **kwargs):
26 > def bar(ui, *args, **kwargs):
27 > ui.write(b"Bar\\n")
27 > ui.write(b"Bar\\n")
28 > EOF
28 > EOF
29 $ abspath=`pwd`/foobar.py
29 $ abspath=`pwd`/foobar.py
30
30
31 $ mkdir barfoo
31 $ mkdir barfoo
32 $ cp foobar.py barfoo/__init__.py
32 $ cp foobar.py barfoo/__init__.py
33 $ barfoopath=`pwd`/barfoo
33 $ barfoopath=`pwd`/barfoo
34
34
35 $ hg init a
35 $ hg init a
36 $ cd a
36 $ cd a
37 $ echo foo > file
37 $ echo foo > file
38 $ hg add file
38 $ hg add file
39 $ hg commit -m 'add file'
39 $ hg commit -m 'add file'
40
40
41 $ echo '[extensions]' >> $HGRCPATH
41 $ echo '[extensions]' >> $HGRCPATH
42 $ echo "foobar = $abspath" >> $HGRCPATH
42 $ echo "foobar = $abspath" >> $HGRCPATH
43 $ hg foo
43 $ hg foo
44 uisetup called
44 uisetup called
45 uisetup called [status]
45 uisetup called [status]
46 reposetup called for a
46 reposetup called for a
47 ui == repo.ui
47 ui == repo.ui
48 reposetup called for a (chg !)
48 reposetup called for a (chg !)
49 ui == repo.ui (chg !)
49 ui == repo.ui (chg !)
50 Foo
50 Foo
51 $ hg foo --quiet
51 $ hg foo --quiet
52 uisetup called (no-chg !)
52 uisetup called (no-chg !)
53 reposetup called for a (chg !)
53 reposetup called for a (chg !)
54 ui == repo.ui
54 ui == repo.ui
55 Foo
55 Foo
56 $ hg foo --debug
56 $ hg foo --debug
57 uisetup called [debug] (no-chg !)
57 uisetup called [debug] (no-chg !)
58 uisetup called (no-chg !)
58 uisetup called (no-chg !)
59 uisetup called [status] (no-chg !)
59 uisetup called [status] (no-chg !)
60 reposetup called for a (chg !)
60 reposetup called for a (chg !)
61 ui == repo.ui
61 ui == repo.ui
62 Foo
62 Foo
63
63
64 $ cd ..
64 $ cd ..
65 $ hg clone a b
65 $ hg clone a b
66 uisetup called (no-chg !)
66 uisetup called (no-chg !)
67 uisetup called [status] (no-chg !)
67 uisetup called [status] (no-chg !)
68 reposetup called for a
68 reposetup called for a
69 ui == repo.ui
69 ui == repo.ui
70 reposetup called for b
70 reposetup called for b
71 ui == repo.ui
71 ui == repo.ui
72 updating to branch default
72 updating to branch default
73 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
74
74
75 $ hg bar
75 $ hg bar
76 uisetup called (no-chg !)
76 uisetup called (no-chg !)
77 uisetup called [status] (no-chg !)
77 uisetup called [status] (no-chg !)
78 Bar
78 Bar
79 $ echo 'foobar = !' >> $HGRCPATH
79 $ echo 'foobar = !' >> $HGRCPATH
80
80
81 module/__init__.py-style
81 module/__init__.py-style
82
82
83 $ echo "barfoo = $barfoopath" >> $HGRCPATH
83 $ echo "barfoo = $barfoopath" >> $HGRCPATH
84 $ cd a
84 $ cd a
85 $ hg foo
85 $ hg foo
86 uisetup called
86 uisetup called
87 uisetup called [status]
87 uisetup called [status]
88 reposetup called for a
88 reposetup called for a
89 ui == repo.ui
89 ui == repo.ui
90 reposetup called for a (chg !)
90 reposetup called for a (chg !)
91 ui == repo.ui (chg !)
91 ui == repo.ui (chg !)
92 Foo
92 Foo
93 $ echo 'barfoo = !' >> $HGRCPATH
93 $ echo 'barfoo = !' >> $HGRCPATH
94
94
95 Check that extensions are loaded in phases:
95 Check that extensions are loaded in phases:
96
96
97 $ cat > foo.py <<EOF
97 $ cat > foo.py <<EOF
98 > import os
98 > import os
99 > name = os.path.basename(__file__).rsplit('.', 1)[0]
99 > name = os.path.basename(__file__).rsplit('.', 1)[0]
100 > print("1) %s imported" % name)
100 > print("1) %s imported" % name)
101 > def uisetup(ui):
101 > def uisetup(ui):
102 > print("2) %s uisetup" % name)
102 > print("2) %s uisetup" % name)
103 > def extsetup():
103 > def extsetup():
104 > print("3) %s extsetup" % name)
104 > print("3) %s extsetup" % name)
105 > def reposetup(ui, repo):
105 > def reposetup(ui, repo):
106 > print("4) %s reposetup" % name)
106 > print("4) %s reposetup" % name)
107 >
107 >
108 > bytesname = name.encode('utf-8')
108 > bytesname = name.encode('utf-8')
109 > # custom predicate to check registration of functions at loading
109 > # custom predicate to check registration of functions at loading
110 > from mercurial import (
110 > from mercurial import (
111 > registrar,
111 > registrar,
112 > smartset,
112 > smartset,
113 > )
113 > )
114 > revsetpredicate = registrar.revsetpredicate()
114 > revsetpredicate = registrar.revsetpredicate()
115 > @revsetpredicate(bytesname, safe=True) # safe=True for query via hgweb
115 > @revsetpredicate(bytesname, safe=True) # safe=True for query via hgweb
116 > def custompredicate(repo, subset, x):
116 > def custompredicate(repo, subset, x):
117 > return smartset.baseset([r for r in subset if r in {0}])
117 > return smartset.baseset([r for r in subset if r in {0}])
118 > EOF
118 > EOF
119
119
120 $ cp foo.py bar.py
120 $ cp foo.py bar.py
121 $ echo 'foo = foo.py' >> $HGRCPATH
121 $ echo 'foo = foo.py' >> $HGRCPATH
122 $ echo 'bar = bar.py' >> $HGRCPATH
122 $ echo 'bar = bar.py' >> $HGRCPATH
123
123
124 Check normal command's load order of extensions and registration of functions
124 Check normal command's load order of extensions and registration of functions
125
125
126 $ hg log -r "foo() and bar()" -q
126 $ hg log -r "foo() and bar()" -q
127 1) foo imported
127 1) foo imported
128 1) bar imported
128 1) bar imported
129 2) foo uisetup
129 2) foo uisetup
130 2) bar uisetup
130 2) bar uisetup
131 3) foo extsetup
131 3) foo extsetup
132 3) bar extsetup
132 3) bar extsetup
133 4) foo reposetup
133 4) foo reposetup
134 4) bar reposetup
134 4) bar reposetup
135 0:c24b9ac61126
135 0:c24b9ac61126
136
136
137 Check hgweb's load order of extensions and registration of functions
137 Check hgweb's load order of extensions and registration of functions
138
138
139 $ cat > hgweb.cgi <<EOF
139 $ cat > hgweb.cgi <<EOF
140 > #!$PYTHON
140 > #!$PYTHON
141 > from mercurial import demandimport; demandimport.enable()
141 > from mercurial import demandimport; demandimport.enable()
142 > from mercurial.hgweb import hgweb
142 > from mercurial.hgweb import hgweb
143 > from mercurial.hgweb import wsgicgi
143 > from mercurial.hgweb import wsgicgi
144 > application = hgweb(b'.', b'test repo')
144 > application = hgweb(b'.', b'test repo')
145 > wsgicgi.launch(application)
145 > wsgicgi.launch(application)
146 > EOF
146 > EOF
147 $ . "$TESTDIR/cgienv"
147 $ . "$TESTDIR/cgienv"
148
148
149 $ PATH_INFO='/' SCRIPT_NAME='' "$PYTHON" hgweb.cgi \
149 $ PATH_INFO='/' SCRIPT_NAME='' "$PYTHON" hgweb.cgi \
150 > | grep '^[0-9]) ' # ignores HTML output
150 > | grep '^[0-9]) ' # ignores HTML output
151 1) foo imported
151 1) foo imported
152 1) bar imported
152 1) bar imported
153 2) foo uisetup
153 2) foo uisetup
154 2) bar uisetup
154 2) bar uisetup
155 3) foo extsetup
155 3) foo extsetup
156 3) bar extsetup
156 3) bar extsetup
157 4) foo reposetup
157 4) foo reposetup
158 4) bar reposetup
158 4) bar reposetup
159
159
160 (check that revset predicate foo() and bar() are available)
160 (check that revset predicate foo() and bar() are available)
161
161
162 #if msys
162 #if msys
163 $ PATH_INFO='//shortlog'
163 $ PATH_INFO='//shortlog'
164 #else
164 #else
165 $ PATH_INFO='/shortlog'
165 $ PATH_INFO='/shortlog'
166 #endif
166 #endif
167 $ export PATH_INFO
167 $ export PATH_INFO
168 $ SCRIPT_NAME='' QUERY_STRING='rev=foo() and bar()' "$PYTHON" hgweb.cgi \
168 $ SCRIPT_NAME='' QUERY_STRING='rev=foo() and bar()' "$PYTHON" hgweb.cgi \
169 > | grep '<a href="/rev/[0-9a-z]*">'
169 > | grep '<a href="/rev/[0-9a-z]*">'
170 <a href="/rev/c24b9ac61126">add file</a>
170 <a href="/rev/c24b9ac61126">add file</a>
171
171
172 $ echo 'foo = !' >> $HGRCPATH
172 $ echo 'foo = !' >> $HGRCPATH
173 $ echo 'bar = !' >> $HGRCPATH
173 $ echo 'bar = !' >> $HGRCPATH
174
174
175 Check "from __future__ import absolute_import" support for external libraries
175 Check "from __future__ import absolute_import" support for external libraries
176
176
177 #if windows
177 #if windows
178 $ PATHSEP=";"
178 $ PATHSEP=";"
179 #else
179 #else
180 $ PATHSEP=":"
180 $ PATHSEP=":"
181 #endif
181 #endif
182 $ export PATHSEP
182 $ export PATHSEP
183
183
184 $ mkdir $TESTTMP/libroot
184 $ mkdir $TESTTMP/libroot
185 $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
185 $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
186 $ mkdir $TESTTMP/libroot/mod
186 $ mkdir $TESTTMP/libroot/mod
187 $ touch $TESTTMP/libroot/mod/__init__.py
187 $ touch $TESTTMP/libroot/mod/__init__.py
188 $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
188 $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
189
189
190 $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
190 $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
191 > from __future__ import absolute_import
191 > from __future__ import absolute_import
192 > import ambig # should load "libroot/ambig.py"
192 > import ambig # should load "libroot/ambig.py"
193 > s = ambig.s
193 > s = ambig.s
194 > EOF
194 > EOF
195 $ cat > loadabs.py <<EOF
195 $ cat > loadabs.py <<EOF
196 > import mod.ambigabs as ambigabs
196 > import mod.ambigabs as ambigabs
197 > def extsetup():
197 > def extsetup():
198 > print('ambigabs.s=%s' % ambigabs.s)
198 > print('ambigabs.s=%s' % ambigabs.s)
199 > EOF
199 > EOF
200 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadabs=loadabs.py root)
200 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadabs=loadabs.py root)
201 ambigabs.s=libroot/ambig.py
201 ambigabs.s=libroot/ambig.py
202 $TESTTMP/a
202 $TESTTMP/a
203
203
204 #if no-py3k
204 #if no-py3k
205 $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
205 $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
206 > import ambig # should load "libroot/mod/ambig.py"
206 > import ambig # should load "libroot/mod/ambig.py"
207 > s = ambig.s
207 > s = ambig.s
208 > EOF
208 > EOF
209 $ cat > loadrel.py <<EOF
209 $ cat > loadrel.py <<EOF
210 > import mod.ambigrel as ambigrel
210 > import mod.ambigrel as ambigrel
211 > def extsetup():
211 > def extsetup():
212 > print('ambigrel.s=%s' % ambigrel.s)
212 > print('ambigrel.s=%s' % ambigrel.s)
213 > EOF
213 > EOF
214 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root)
214 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root)
215 ambigrel.s=libroot/mod/ambig.py
215 ambigrel.s=libroot/mod/ambig.py
216 $TESTTMP/a
216 $TESTTMP/a
217 #endif
217 #endif
218
218
219 Check absolute/relative import of extension specific modules
219 Check absolute/relative import of extension specific modules
220
220
221 $ mkdir $TESTTMP/extroot
221 $ mkdir $TESTTMP/extroot
222 $ cat > $TESTTMP/extroot/bar.py <<EOF
222 $ cat > $TESTTMP/extroot/bar.py <<EOF
223 > s = 'this is extroot.bar'
223 > s = 'this is extroot.bar'
224 > EOF
224 > EOF
225 $ mkdir $TESTTMP/extroot/sub1
225 $ mkdir $TESTTMP/extroot/sub1
226 $ cat > $TESTTMP/extroot/sub1/__init__.py <<EOF
226 $ cat > $TESTTMP/extroot/sub1/__init__.py <<EOF
227 > s = 'this is extroot.sub1.__init__'
227 > s = 'this is extroot.sub1.__init__'
228 > EOF
228 > EOF
229 $ cat > $TESTTMP/extroot/sub1/baz.py <<EOF
229 $ cat > $TESTTMP/extroot/sub1/baz.py <<EOF
230 > s = 'this is extroot.sub1.baz'
230 > s = 'this is extroot.sub1.baz'
231 > EOF
231 > EOF
232 $ cat > $TESTTMP/extroot/__init__.py <<EOF
232 $ cat > $TESTTMP/extroot/__init__.py <<EOF
233 > s = 'this is extroot.__init__'
233 > s = 'this is extroot.__init__'
234 > import foo
234 > import foo
235 > def extsetup(ui):
235 > def extsetup(ui):
236 > ui.write('(extroot) ', foo.func(), '\n')
236 > ui.write('(extroot) ', foo.func(), '\n')
237 > ui.flush()
237 > ui.flush()
238 > EOF
238 > EOF
239
239
240 $ cat > $TESTTMP/extroot/foo.py <<EOF
240 $ cat > $TESTTMP/extroot/foo.py <<EOF
241 > # test absolute import
241 > # test absolute import
242 > buf = []
242 > buf = []
243 > def func():
243 > def func():
244 > # "not locals" case
244 > # "not locals" case
245 > import extroot.bar
245 > import extroot.bar
246 > buf.append('import extroot.bar in func(): %s' % extroot.bar.s)
246 > buf.append('import extroot.bar in func(): %s' % extroot.bar.s)
247 > return '\n(extroot) '.join(buf)
247 > return '\n(extroot) '.join(buf)
248 > # "fromlist == ('*',)" case
248 > # "fromlist == ('*',)" case
249 > from extroot.bar import *
249 > from extroot.bar import *
250 > buf.append('from extroot.bar import *: %s' % s)
250 > buf.append('from extroot.bar import *: %s' % s)
251 > # "not fromlist" and "if '.' in name" case
251 > # "not fromlist" and "if '.' in name" case
252 > import extroot.sub1.baz
252 > import extroot.sub1.baz
253 > buf.append('import extroot.sub1.baz: %s' % extroot.sub1.baz.s)
253 > buf.append('import extroot.sub1.baz: %s' % extroot.sub1.baz.s)
254 > # "not fromlist" and NOT "if '.' in name" case
254 > # "not fromlist" and NOT "if '.' in name" case
255 > import extroot
255 > import extroot
256 > buf.append('import extroot: %s' % extroot.s)
256 > buf.append('import extroot: %s' % extroot.s)
257 > # NOT "not fromlist" and NOT "level != -1" case
257 > # NOT "not fromlist" and NOT "level != -1" case
258 > from extroot.bar import s
258 > from extroot.bar import s
259 > buf.append('from extroot.bar import s: %s' % s)
259 > buf.append('from extroot.bar import s: %s' % s)
260 > EOF
260 > EOF
261 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.extroot=$TESTTMP/extroot root)
261 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.extroot=$TESTTMP/extroot root)
262 (extroot) from extroot.bar import *: this is extroot.bar
262 (extroot) from extroot.bar import *: this is extroot.bar
263 (extroot) import extroot.sub1.baz: this is extroot.sub1.baz
263 (extroot) import extroot.sub1.baz: this is extroot.sub1.baz
264 (extroot) import extroot: this is extroot.__init__
264 (extroot) import extroot: this is extroot.__init__
265 (extroot) from extroot.bar import s: this is extroot.bar
265 (extroot) from extroot.bar import s: this is extroot.bar
266 (extroot) import extroot.bar in func(): this is extroot.bar
266 (extroot) import extroot.bar in func(): this is extroot.bar
267 $TESTTMP/a
267 $TESTTMP/a
268
268
269 #if no-py3k
269 #if no-py3k
270 $ rm "$TESTTMP"/extroot/foo.*
270 $ rm "$TESTTMP"/extroot/foo.*
271 $ rm -Rf "$TESTTMP/extroot/__pycache__"
271 $ rm -Rf "$TESTTMP/extroot/__pycache__"
272 $ cat > $TESTTMP/extroot/foo.py <<EOF
272 $ cat > $TESTTMP/extroot/foo.py <<EOF
273 > # test relative import
273 > # test relative import
274 > buf = []
274 > buf = []
275 > def func():
275 > def func():
276 > # "not locals" case
276 > # "not locals" case
277 > import bar
277 > import bar
278 > buf.append('import bar in func(): %s' % bar.s)
278 > buf.append('import bar in func(): %s' % bar.s)
279 > return '\n(extroot) '.join(buf)
279 > return '\n(extroot) '.join(buf)
280 > # "fromlist == ('*',)" case
280 > # "fromlist == ('*',)" case
281 > from bar import *
281 > from bar import *
282 > buf.append('from bar import *: %s' % s)
282 > buf.append('from bar import *: %s' % s)
283 > # "not fromlist" and "if '.' in name" case
283 > # "not fromlist" and "if '.' in name" case
284 > import sub1.baz
284 > import sub1.baz
285 > buf.append('import sub1.baz: %s' % sub1.baz.s)
285 > buf.append('import sub1.baz: %s' % sub1.baz.s)
286 > # "not fromlist" and NOT "if '.' in name" case
286 > # "not fromlist" and NOT "if '.' in name" case
287 > import sub1
287 > import sub1
288 > buf.append('import sub1: %s' % sub1.s)
288 > buf.append('import sub1: %s' % sub1.s)
289 > # NOT "not fromlist" and NOT "level != -1" case
289 > # NOT "not fromlist" and NOT "level != -1" case
290 > from bar import s
290 > from bar import s
291 > buf.append('from bar import s: %s' % s)
291 > buf.append('from bar import s: %s' % s)
292 > EOF
292 > EOF
293 $ hg --config extensions.extroot=$TESTTMP/extroot root
293 $ hg --config extensions.extroot=$TESTTMP/extroot root
294 (extroot) from bar import *: this is extroot.bar
294 (extroot) from bar import *: this is extroot.bar
295 (extroot) import sub1.baz: this is extroot.sub1.baz
295 (extroot) import sub1.baz: this is extroot.sub1.baz
296 (extroot) import sub1: this is extroot.sub1.__init__
296 (extroot) import sub1: this is extroot.sub1.__init__
297 (extroot) from bar import s: this is extroot.bar
297 (extroot) from bar import s: this is extroot.bar
298 (extroot) import bar in func(): this is extroot.bar
298 (extroot) import bar in func(): this is extroot.bar
299 $TESTTMP/a
299 $TESTTMP/a
300 #endif
300 #endif
301
301
302 #if demandimport
302 #if demandimport
303
303
304 Examine whether module loading is delayed until actual referring, even
304 Examine whether module loading is delayed until actual referring, even
305 though module is imported with "absolute_import" feature.
305 though module is imported with "absolute_import" feature.
306
306
307 Files below in each packages are used for described purpose:
307 Files below in each packages are used for described purpose:
308
308
309 - "called": examine whether "from MODULE import ATTR" works correctly
309 - "called": examine whether "from MODULE import ATTR" works correctly
310 - "unused": examine whether loading is delayed correctly
310 - "unused": examine whether loading is delayed correctly
311 - "used": examine whether "from PACKAGE import MODULE" works correctly
311 - "used": examine whether "from PACKAGE import MODULE" works correctly
312
312
313 Package hierarchy is needed to examine whether demand importing works
313 Package hierarchy is needed to examine whether demand importing works
314 as expected for "from SUB.PACK.AGE import MODULE".
314 as expected for "from SUB.PACK.AGE import MODULE".
315
315
316 Setup "external library" to be imported with "absolute_import"
316 Setup "external library" to be imported with "absolute_import"
317 feature.
317 feature.
318
318
319 $ mkdir -p $TESTTMP/extlibroot/lsub1/lsub2
319 $ mkdir -p $TESTTMP/extlibroot/lsub1/lsub2
320 $ touch $TESTTMP/extlibroot/__init__.py
320 $ touch $TESTTMP/extlibroot/__init__.py
321 $ touch $TESTTMP/extlibroot/lsub1/__init__.py
321 $ touch $TESTTMP/extlibroot/lsub1/__init__.py
322 $ touch $TESTTMP/extlibroot/lsub1/lsub2/__init__.py
322 $ touch $TESTTMP/extlibroot/lsub1/lsub2/__init__.py
323
323
324 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/called.py <<EOF
324 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/called.py <<EOF
325 > def func():
325 > def func():
326 > return b"this is extlibroot.lsub1.lsub2.called.func()"
326 > return b"this is extlibroot.lsub1.lsub2.called.func()"
327 > EOF
327 > EOF
328 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/unused.py <<EOF
328 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/unused.py <<EOF
329 > raise Exception("extlibroot.lsub1.lsub2.unused is loaded unintentionally")
329 > raise Exception("extlibroot.lsub1.lsub2.unused is loaded unintentionally")
330 > EOF
330 > EOF
331 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/used.py <<EOF
331 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/used.py <<EOF
332 > detail = b"this is extlibroot.lsub1.lsub2.used"
332 > detail = b"this is extlibroot.lsub1.lsub2.used"
333 > EOF
333 > EOF
334
334
335 Setup sub-package of "external library", which causes instantiation of
335 Setup sub-package of "external library", which causes instantiation of
336 demandmod in "recurse down the module chain" code path. Relative
336 demandmod in "recurse down the module chain" code path. Relative
337 importing with "absolute_import" feature isn't tested, because "level
337 importing with "absolute_import" feature isn't tested, because "level
338 >=1 " doesn't cause instantiation of demandmod.
338 >=1 " doesn't cause instantiation of demandmod.
339
339
340 $ mkdir -p $TESTTMP/extlibroot/recursedown/abs
340 $ mkdir -p $TESTTMP/extlibroot/recursedown/abs
341 $ cat > $TESTTMP/extlibroot/recursedown/abs/used.py <<EOF
341 $ cat > $TESTTMP/extlibroot/recursedown/abs/used.py <<EOF
342 > detail = b"this is extlibroot.recursedown.abs.used"
342 > detail = b"this is extlibroot.recursedown.abs.used"
343 > EOF
343 > EOF
344 $ cat > $TESTTMP/extlibroot/recursedown/abs/__init__.py <<EOF
344 $ cat > $TESTTMP/extlibroot/recursedown/abs/__init__.py <<EOF
345 > from __future__ import absolute_import
345 > from __future__ import absolute_import
346 > from extlibroot.recursedown.abs.used import detail
346 > from extlibroot.recursedown.abs.used import detail
347 > EOF
347 > EOF
348
348
349 $ mkdir -p $TESTTMP/extlibroot/recursedown/legacy
349 $ mkdir -p $TESTTMP/extlibroot/recursedown/legacy
350 $ cat > $TESTTMP/extlibroot/recursedown/legacy/used.py <<EOF
350 $ cat > $TESTTMP/extlibroot/recursedown/legacy/used.py <<EOF
351 > detail = b"this is extlibroot.recursedown.legacy.used"
351 > detail = b"this is extlibroot.recursedown.legacy.used"
352 > EOF
352 > EOF
353 $ cat > $TESTTMP/extlibroot/recursedown/legacy/__init__.py <<EOF
353 $ cat > $TESTTMP/extlibroot/recursedown/legacy/__init__.py <<EOF
354 > # legacy style (level == -1) import
354 > # legacy style (level == -1) import
355 > from extlibroot.recursedown.legacy.used import detail
355 > from extlibroot.recursedown.legacy.used import detail
356 > EOF
356 > EOF
357
357
358 $ cat > $TESTTMP/extlibroot/recursedown/__init__.py <<EOF
358 $ cat > $TESTTMP/extlibroot/recursedown/__init__.py <<EOF
359 > from __future__ import absolute_import
359 > from __future__ import absolute_import
360 > from extlibroot.recursedown.abs import detail as absdetail
360 > from extlibroot.recursedown.abs import detail as absdetail
361 > from .legacy import detail as legacydetail
361 > from .legacy import detail as legacydetail
362 > EOF
362 > EOF
363
363
364 Setup package that re-exports an attribute of its submodule as the same
364 Setup package that re-exports an attribute of its submodule as the same
365 name. This leaves 'shadowing.used' pointing to 'used.detail', but still
365 name. This leaves 'shadowing.used' pointing to 'used.detail', but still
366 the submodule 'used' should be somehow accessible. (issue5617)
366 the submodule 'used' should be somehow accessible. (issue5617)
367
367
368 $ mkdir -p $TESTTMP/extlibroot/shadowing
368 $ mkdir -p $TESTTMP/extlibroot/shadowing
369 $ cat > $TESTTMP/extlibroot/shadowing/used.py <<EOF
369 $ cat > $TESTTMP/extlibroot/shadowing/used.py <<EOF
370 > detail = b"this is extlibroot.shadowing.used"
370 > detail = b"this is extlibroot.shadowing.used"
371 > EOF
371 > EOF
372 $ cat > $TESTTMP/extlibroot/shadowing/proxied.py <<EOF
372 $ cat > $TESTTMP/extlibroot/shadowing/proxied.py <<EOF
373 > from __future__ import absolute_import
373 > from __future__ import absolute_import
374 > from extlibroot.shadowing.used import detail
374 > from extlibroot.shadowing.used import detail
375 > EOF
375 > EOF
376 $ cat > $TESTTMP/extlibroot/shadowing/__init__.py <<EOF
376 $ cat > $TESTTMP/extlibroot/shadowing/__init__.py <<EOF
377 > from __future__ import absolute_import
377 > from __future__ import absolute_import
378 > from .used import detail as used
378 > from .used import detail as used
379 > EOF
379 > EOF
380
380
381 Setup extension local modules to be imported with "absolute_import"
381 Setup extension local modules to be imported with "absolute_import"
382 feature.
382 feature.
383
383
384 $ mkdir -p $TESTTMP/absextroot/xsub1/xsub2
384 $ mkdir -p $TESTTMP/absextroot/xsub1/xsub2
385 $ touch $TESTTMP/absextroot/xsub1/__init__.py
385 $ touch $TESTTMP/absextroot/xsub1/__init__.py
386 $ touch $TESTTMP/absextroot/xsub1/xsub2/__init__.py
386 $ touch $TESTTMP/absextroot/xsub1/xsub2/__init__.py
387
387
388 $ cat > $TESTTMP/absextroot/xsub1/xsub2/called.py <<EOF
388 $ cat > $TESTTMP/absextroot/xsub1/xsub2/called.py <<EOF
389 > def func():
389 > def func():
390 > return b"this is absextroot.xsub1.xsub2.called.func()"
390 > return b"this is absextroot.xsub1.xsub2.called.func()"
391 > EOF
391 > EOF
392 $ cat > $TESTTMP/absextroot/xsub1/xsub2/unused.py <<EOF
392 $ cat > $TESTTMP/absextroot/xsub1/xsub2/unused.py <<EOF
393 > raise Exception("absextroot.xsub1.xsub2.unused is loaded unintentionally")
393 > raise Exception("absextroot.xsub1.xsub2.unused is loaded unintentionally")
394 > EOF
394 > EOF
395 $ cat > $TESTTMP/absextroot/xsub1/xsub2/used.py <<EOF
395 $ cat > $TESTTMP/absextroot/xsub1/xsub2/used.py <<EOF
396 > detail = b"this is absextroot.xsub1.xsub2.used"
396 > detail = b"this is absextroot.xsub1.xsub2.used"
397 > EOF
397 > EOF
398
398
399 Setup extension local modules to examine whether demand importing
399 Setup extension local modules to examine whether demand importing
400 works as expected in "level > 1" case.
400 works as expected in "level > 1" case.
401
401
402 $ cat > $TESTTMP/absextroot/relimportee.py <<EOF
402 $ cat > $TESTTMP/absextroot/relimportee.py <<EOF
403 > detail = b"this is absextroot.relimportee"
403 > detail = b"this is absextroot.relimportee"
404 > EOF
404 > EOF
405 $ cat > $TESTTMP/absextroot/xsub1/xsub2/relimporter.py <<EOF
405 $ cat > $TESTTMP/absextroot/xsub1/xsub2/relimporter.py <<EOF
406 > from __future__ import absolute_import
406 > from __future__ import absolute_import
407 > from ... import relimportee
407 > from ... import relimportee
408 > detail = b"this relimporter imports %r" % (relimportee.detail)
408 > detail = b"this relimporter imports %r" % (relimportee.detail)
409 > EOF
409 > EOF
410
410
411 Setup modules, which actually import extension local modules at
411 Setup modules, which actually import extension local modules at
412 runtime.
412 runtime.
413
413
414 $ cat > $TESTTMP/absextroot/absolute.py << EOF
414 $ cat > $TESTTMP/absextroot/absolute.py << EOF
415 > from __future__ import absolute_import
415 > from __future__ import absolute_import
416 >
416 >
417 > # import extension local modules absolutely (level = 0)
417 > # import extension local modules absolutely (level = 0)
418 > from absextroot.xsub1.xsub2 import used, unused
418 > from absextroot.xsub1.xsub2 import used, unused
419 > from absextroot.xsub1.xsub2.called import func
419 > from absextroot.xsub1.xsub2.called import func
420 >
420 >
421 > def getresult():
421 > def getresult():
422 > result = []
422 > result = []
423 > result.append(used.detail)
423 > result.append(used.detail)
424 > result.append(func())
424 > result.append(func())
425 > return result
425 > return result
426 > EOF
426 > EOF
427
427
428 $ cat > $TESTTMP/absextroot/relative.py << EOF
428 $ cat > $TESTTMP/absextroot/relative.py << EOF
429 > from __future__ import absolute_import
429 > from __future__ import absolute_import
430 >
430 >
431 > # import extension local modules relatively (level == 1)
431 > # import extension local modules relatively (level == 1)
432 > from .xsub1.xsub2 import used, unused
432 > from .xsub1.xsub2 import used, unused
433 > from .xsub1.xsub2.called import func
433 > from .xsub1.xsub2.called import func
434 >
434 >
435 > # import a module, which implies "importing with level > 1"
435 > # import a module, which implies "importing with level > 1"
436 > from .xsub1.xsub2 import relimporter
436 > from .xsub1.xsub2 import relimporter
437 >
437 >
438 > def getresult():
438 > def getresult():
439 > result = []
439 > result = []
440 > result.append(used.detail)
440 > result.append(used.detail)
441 > result.append(func())
441 > result.append(func())
442 > result.append(relimporter.detail)
442 > result.append(relimporter.detail)
443 > return result
443 > return result
444 > EOF
444 > EOF
445
445
446 Setup main procedure of extension.
446 Setup main procedure of extension.
447
447
448 $ cat > $TESTTMP/absextroot/__init__.py <<EOF
448 $ cat > $TESTTMP/absextroot/__init__.py <<EOF
449 > from __future__ import absolute_import
449 > from __future__ import absolute_import
450 > from mercurial import registrar
450 > from mercurial import registrar
451 > cmdtable = {}
451 > cmdtable = {}
452 > command = registrar.command(cmdtable)
452 > command = registrar.command(cmdtable)
453 >
453 >
454 > # "absolute" and "relative" shouldn't be imported before actual
454 > # "absolute" and "relative" shouldn't be imported before actual
455 > # command execution, because (1) they import same modules, and (2)
455 > # command execution, because (1) they import same modules, and (2)
456 > # preceding import (= instantiate "demandmod" object instead of
456 > # preceding import (= instantiate "demandmod" object instead of
457 > # real "module" object) might hide problem of succeeding import.
457 > # real "module" object) might hide problem of succeeding import.
458 >
458 >
459 > @command(b'showabsolute', [], norepo=True)
459 > @command(b'showabsolute', [], norepo=True)
460 > def showabsolute(ui, *args, **opts):
460 > def showabsolute(ui, *args, **opts):
461 > from absextroot import absolute
461 > from absextroot import absolute
462 > ui.write(b'ABS: %s\n' % '\nABS: '.join(absolute.getresult()))
462 > ui.write(b'ABS: %s\n' % '\nABS: '.join(absolute.getresult()))
463 >
463 >
464 > @command(b'showrelative', [], norepo=True)
464 > @command(b'showrelative', [], norepo=True)
465 > def showrelative(ui, *args, **opts):
465 > def showrelative(ui, *args, **opts):
466 > from . import relative
466 > from . import relative
467 > ui.write(b'REL: %s\n' % '\nREL: '.join(relative.getresult()))
467 > ui.write(b'REL: %s\n' % '\nREL: '.join(relative.getresult()))
468 >
468 >
469 > # import modules from external library
469 > # import modules from external library
470 > from extlibroot.lsub1.lsub2 import used as lused, unused as lunused
470 > from extlibroot.lsub1.lsub2 import used as lused, unused as lunused
471 > from extlibroot.lsub1.lsub2.called import func as lfunc
471 > from extlibroot.lsub1.lsub2.called import func as lfunc
472 > from extlibroot.recursedown import absdetail, legacydetail
472 > from extlibroot.recursedown import absdetail, legacydetail
473 > from extlibroot.shadowing import proxied
473 > from extlibroot.shadowing import proxied
474 >
474 >
475 > def uisetup(ui):
475 > def uisetup(ui):
476 > result = []
476 > result = []
477 > result.append(lused.detail)
477 > result.append(lused.detail)
478 > result.append(lfunc())
478 > result.append(lfunc())
479 > result.append(absdetail)
479 > result.append(absdetail)
480 > result.append(legacydetail)
480 > result.append(legacydetail)
481 > result.append(proxied.detail)
481 > result.append(proxied.detail)
482 > ui.write(b'LIB: %s\n' % '\nLIB: '.join(result))
482 > ui.write(b'LIB: %s\n' % '\nLIB: '.join(result))
483 > EOF
483 > EOF
484
484
485 Examine module importing.
485 Examine module importing.
486
486
487 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showabsolute)
487 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showabsolute)
488 LIB: this is extlibroot.lsub1.lsub2.used
488 LIB: this is extlibroot.lsub1.lsub2.used
489 LIB: this is extlibroot.lsub1.lsub2.called.func()
489 LIB: this is extlibroot.lsub1.lsub2.called.func()
490 LIB: this is extlibroot.recursedown.abs.used
490 LIB: this is extlibroot.recursedown.abs.used
491 LIB: this is extlibroot.recursedown.legacy.used
491 LIB: this is extlibroot.recursedown.legacy.used
492 LIB: this is extlibroot.shadowing.used
492 LIB: this is extlibroot.shadowing.used
493 ABS: this is absextroot.xsub1.xsub2.used
493 ABS: this is absextroot.xsub1.xsub2.used
494 ABS: this is absextroot.xsub1.xsub2.called.func()
494 ABS: this is absextroot.xsub1.xsub2.called.func()
495
495
496 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showrelative)
496 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showrelative)
497 LIB: this is extlibroot.lsub1.lsub2.used
497 LIB: this is extlibroot.lsub1.lsub2.used
498 LIB: this is extlibroot.lsub1.lsub2.called.func()
498 LIB: this is extlibroot.lsub1.lsub2.called.func()
499 LIB: this is extlibroot.recursedown.abs.used
499 LIB: this is extlibroot.recursedown.abs.used
500 LIB: this is extlibroot.recursedown.legacy.used
500 LIB: this is extlibroot.recursedown.legacy.used
501 LIB: this is extlibroot.shadowing.used
501 LIB: this is extlibroot.shadowing.used
502 REL: this is absextroot.xsub1.xsub2.used
502 REL: this is absextroot.xsub1.xsub2.used
503 REL: this is absextroot.xsub1.xsub2.called.func()
503 REL: this is absextroot.xsub1.xsub2.called.func()
504 REL: this relimporter imports 'this is absextroot.relimportee'
504 REL: this relimporter imports 'this is absextroot.relimportee'
505
505
506 Examine whether sub-module is imported relatively as expected.
506 Examine whether sub-module is imported relatively as expected.
507
507
508 See also issue5208 for detail about example case on Python 3.x.
508 See also issue5208 for detail about example case on Python 3.x.
509
509
510 $ f -q $TESTTMP/extlibroot/lsub1/lsub2/notexist.py
510 $ f -q $TESTTMP/extlibroot/lsub1/lsub2/notexist.py
511 $TESTTMP/extlibroot/lsub1/lsub2/notexist.py: file not found
511 $TESTTMP/extlibroot/lsub1/lsub2/notexist.py: file not found
512
512
513 $ cat > $TESTTMP/notexist.py <<EOF
513 $ cat > $TESTTMP/notexist.py <<EOF
514 > text = 'notexist.py at root is loaded unintentionally\n'
514 > text = 'notexist.py at root is loaded unintentionally\n'
515 > EOF
515 > EOF
516
516
517 $ cat > $TESTTMP/checkrelativity.py <<EOF
517 $ cat > $TESTTMP/checkrelativity.py <<EOF
518 > from mercurial import registrar
518 > from mercurial import registrar
519 > cmdtable = {}
519 > cmdtable = {}
520 > command = registrar.command(cmdtable)
520 > command = registrar.command(cmdtable)
521 >
521 >
522 > # demand import avoids failure of importing notexist here
522 > # demand import avoids failure of importing notexist here
523 > import extlibroot.lsub1.lsub2.notexist
523 > import extlibroot.lsub1.lsub2.notexist
524 >
524 >
525 > @command(b'checkrelativity', [], norepo=True)
525 > @command(b'checkrelativity', [], norepo=True)
526 > def checkrelativity(ui, *args, **opts):
526 > def checkrelativity(ui, *args, **opts):
527 > try:
527 > try:
528 > ui.write(extlibroot.lsub1.lsub2.notexist.text)
528 > ui.write(extlibroot.lsub1.lsub2.notexist.text)
529 > return 1 # unintentional success
529 > return 1 # unintentional success
530 > except ImportError:
530 > except ImportError:
531 > pass # intentional failure
531 > pass # intentional failure
532 > EOF
532 > EOF
533
533
534 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.checkrelativity=$TESTTMP/checkrelativity.py checkrelativity)
534 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.checkrelativity=$TESTTMP/checkrelativity.py checkrelativity)
535
535
536 #endif
536 #endif
537
537
538 Make sure a broken uisetup doesn't globally break hg:
538 Make sure a broken uisetup doesn't globally break hg:
539 $ cat > $TESTTMP/baduisetup.py <<EOF
539 $ cat > $TESTTMP/baduisetup.py <<EOF
540 > def uisetup(ui):
540 > def uisetup(ui):
541 > 1/0
541 > 1/0
542 > EOF
542 > EOF
543
543
544 Even though the extension fails during uisetup, hg is still basically usable:
544 Even though the extension fails during uisetup, hg is still basically usable:
545 $ hg --config extensions.baduisetup=$TESTTMP/baduisetup.py version
545 $ hg --config extensions.baduisetup=$TESTTMP/baduisetup.py version
546 Traceback (most recent call last):
546 Traceback (most recent call last):
547 File "*/mercurial/extensions.py", line *, in _runuisetup (glob)
547 File "*/mercurial/extensions.py", line *, in _runuisetup (glob)
548 uisetup(ui)
548 uisetup(ui)
549 File "$TESTTMP/baduisetup.py", line 2, in uisetup
549 File "$TESTTMP/baduisetup.py", line 2, in uisetup
550 1/0
550 1/0
551 ZeroDivisionError: integer division or modulo by zero
551 ZeroDivisionError: integer division or modulo by zero
552 *** failed to set up extension baduisetup: integer division or modulo by zero
552 *** failed to set up extension baduisetup: integer division or modulo by zero
553 Mercurial Distributed SCM (version *) (glob)
553 Mercurial Distributed SCM (version *) (glob)
554 (see https://mercurial-scm.org for more information)
554 (see https://mercurial-scm.org for more information)
555
555
556 Copyright (C) 2005-* Matt Mackall and others (glob)
556 Copyright (C) 2005-* Matt Mackall and others (glob)
557 This is free software; see the source for copying conditions. There is NO
557 This is free software; see the source for copying conditions. There is NO
558 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
558 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
559
559
560 $ cd ..
560 $ cd ..
561
561
562 hide outer repo
562 hide outer repo
563 $ hg init
563 $ hg init
564
564
565 $ cat > empty.py <<EOF
565 $ cat > empty.py <<EOF
566 > '''empty cmdtable
566 > '''empty cmdtable
567 > '''
567 > '''
568 > cmdtable = {}
568 > cmdtable = {}
569 > EOF
569 > EOF
570 $ emptypath=`pwd`/empty.py
570 $ emptypath=`pwd`/empty.py
571 $ echo "empty = $emptypath" >> $HGRCPATH
571 $ echo "empty = $emptypath" >> $HGRCPATH
572 $ hg help empty
572 $ hg help empty
573 empty extension - empty cmdtable
573 empty extension - empty cmdtable
574
574
575 no commands defined
575 no commands defined
576
576
577
577
578 $ echo 'empty = !' >> $HGRCPATH
578 $ echo 'empty = !' >> $HGRCPATH
579
579
580 $ cat > debugextension.py <<EOF
580 $ cat > debugextension.py <<EOF
581 > '''only debugcommands
581 > '''only debugcommands
582 > '''
582 > '''
583 > from mercurial import registrar
583 > from mercurial import registrar
584 > cmdtable = {}
584 > cmdtable = {}
585 > command = registrar.command(cmdtable)
585 > command = registrar.command(cmdtable)
586 > @command(b'debugfoobar', [], b'hg debugfoobar')
586 > @command(b'debugfoobar', [], b'hg debugfoobar')
587 > def debugfoobar(ui, repo, *args, **opts):
587 > def debugfoobar(ui, repo, *args, **opts):
588 > "yet another debug command"
588 > "yet another debug command"
589 > pass
589 > pass
590 > @command(b'foo', [], b'hg foo')
590 > @command(b'foo', [], b'hg foo')
591 > def foo(ui, repo, *args, **opts):
591 > def foo(ui, repo, *args, **opts):
592 > """yet another foo command
592 > """yet another foo command
593 > This command has been DEPRECATED since forever.
593 > This command has been DEPRECATED since forever.
594 > """
594 > """
595 > pass
595 > pass
596 > EOF
596 > EOF
597 $ debugpath=`pwd`/debugextension.py
597 $ debugpath=`pwd`/debugextension.py
598 $ echo "debugextension = $debugpath" >> $HGRCPATH
598 $ echo "debugextension = $debugpath" >> $HGRCPATH
599
599
600 $ hg help debugextension
600 $ hg help debugextension
601 hg debugextensions
601 hg debugextensions
602
602
603 show information about active extensions
603 show information about active extensions
604
604
605 options:
605 options:
606
606
607 -T --template TEMPLATE display with template
608
607 (some details hidden, use --verbose to show complete help)
609 (some details hidden, use --verbose to show complete help)
608
610
609
611
610 $ hg --verbose help debugextension
612 $ hg --verbose help debugextension
611 hg debugextensions
613 hg debugextensions
612
614
613 show information about active extensions
615 show information about active extensions
614
616
615 options:
617 options:
616
618
617 -T --template TEMPLATE display with template (EXPERIMENTAL)
619 -T --template TEMPLATE display with template
618
620
619 global options ([+] can be repeated):
621 global options ([+] can be repeated):
620
622
621 -R --repository REPO repository root directory or name of overlay bundle
623 -R --repository REPO repository root directory or name of overlay bundle
622 file
624 file
623 --cwd DIR change working directory
625 --cwd DIR change working directory
624 -y --noninteractive do not prompt, automatically pick the first choice for
626 -y --noninteractive do not prompt, automatically pick the first choice for
625 all prompts
627 all prompts
626 -q --quiet suppress output
628 -q --quiet suppress output
627 -v --verbose enable additional output
629 -v --verbose enable additional output
628 --color TYPE when to colorize (boolean, always, auto, never, or
630 --color TYPE when to colorize (boolean, always, auto, never, or
629 debug)
631 debug)
630 --config CONFIG [+] set/override config option (use 'section.name=value')
632 --config CONFIG [+] set/override config option (use 'section.name=value')
631 --debug enable debugging output
633 --debug enable debugging output
632 --debugger start debugger
634 --debugger start debugger
633 --encoding ENCODE set the charset encoding (default: ascii)
635 --encoding ENCODE set the charset encoding (default: ascii)
634 --encodingmode MODE set the charset encoding mode (default: strict)
636 --encodingmode MODE set the charset encoding mode (default: strict)
635 --traceback always print a traceback on exception
637 --traceback always print a traceback on exception
636 --time time how long the command takes
638 --time time how long the command takes
637 --profile print command execution profile
639 --profile print command execution profile
638 --version output version information and exit
640 --version output version information and exit
639 -h --help display help and exit
641 -h --help display help and exit
640 --hidden consider hidden changesets
642 --hidden consider hidden changesets
641 --pager TYPE when to paginate (boolean, always, auto, or never)
643 --pager TYPE when to paginate (boolean, always, auto, or never)
642 (default: auto)
644 (default: auto)
643
645
644
646
645
647
646
648
647
649
648
650
649 $ hg --debug help debugextension
651 $ hg --debug help debugextension
650 hg debugextensions
652 hg debugextensions
651
653
652 show information about active extensions
654 show information about active extensions
653
655
654 options:
656 options:
655
657
656 -T --template TEMPLATE display with template (EXPERIMENTAL)
658 -T --template TEMPLATE display with template
657
659
658 global options ([+] can be repeated):
660 global options ([+] can be repeated):
659
661
660 -R --repository REPO repository root directory or name of overlay bundle
662 -R --repository REPO repository root directory or name of overlay bundle
661 file
663 file
662 --cwd DIR change working directory
664 --cwd DIR change working directory
663 -y --noninteractive do not prompt, automatically pick the first choice for
665 -y --noninteractive do not prompt, automatically pick the first choice for
664 all prompts
666 all prompts
665 -q --quiet suppress output
667 -q --quiet suppress output
666 -v --verbose enable additional output
668 -v --verbose enable additional output
667 --color TYPE when to colorize (boolean, always, auto, never, or
669 --color TYPE when to colorize (boolean, always, auto, never, or
668 debug)
670 debug)
669 --config CONFIG [+] set/override config option (use 'section.name=value')
671 --config CONFIG [+] set/override config option (use 'section.name=value')
670 --debug enable debugging output
672 --debug enable debugging output
671 --debugger start debugger
673 --debugger start debugger
672 --encoding ENCODE set the charset encoding (default: ascii)
674 --encoding ENCODE set the charset encoding (default: ascii)
673 --encodingmode MODE set the charset encoding mode (default: strict)
675 --encodingmode MODE set the charset encoding mode (default: strict)
674 --traceback always print a traceback on exception
676 --traceback always print a traceback on exception
675 --time time how long the command takes
677 --time time how long the command takes
676 --profile print command execution profile
678 --profile print command execution profile
677 --version output version information and exit
679 --version output version information and exit
678 -h --help display help and exit
680 -h --help display help and exit
679 --hidden consider hidden changesets
681 --hidden consider hidden changesets
680 --pager TYPE when to paginate (boolean, always, auto, or never)
682 --pager TYPE when to paginate (boolean, always, auto, or never)
681 (default: auto)
683 (default: auto)
682
684
683
685
684
686
685
687
686
688
687 $ echo 'debugextension = !' >> $HGRCPATH
689 $ echo 'debugextension = !' >> $HGRCPATH
688
690
689 Asking for help about a deprecated extension should do something useful:
691 Asking for help about a deprecated extension should do something useful:
690
692
691 $ hg help glog
693 $ hg help glog
692 'glog' is provided by the following extension:
694 'glog' is provided by the following extension:
693
695
694 graphlog command to view revision graphs from a shell (DEPRECATED)
696 graphlog command to view revision graphs from a shell (DEPRECATED)
695
697
696 (use 'hg help extensions' for information on enabling extensions)
698 (use 'hg help extensions' for information on enabling extensions)
697
699
698 Extension module help vs command help:
700 Extension module help vs command help:
699
701
700 $ echo 'extdiff =' >> $HGRCPATH
702 $ echo 'extdiff =' >> $HGRCPATH
701 $ hg help extdiff
703 $ hg help extdiff
702 hg extdiff [OPT]... [FILE]...
704 hg extdiff [OPT]... [FILE]...
703
705
704 use external program to diff repository (or selected files)
706 use external program to diff repository (or selected files)
705
707
706 Show differences between revisions for the specified files, using an
708 Show differences between revisions for the specified files, using an
707 external program. The default program used is diff, with default options
709 external program. The default program used is diff, with default options
708 "-Npru".
710 "-Npru".
709
711
710 To select a different program, use the -p/--program option. The program
712 To select a different program, use the -p/--program option. The program
711 will be passed the names of two directories to compare. To pass additional
713 will be passed the names of two directories to compare. To pass additional
712 options to the program, use -o/--option. These will be passed before the
714 options to the program, use -o/--option. These will be passed before the
713 names of the directories to compare.
715 names of the directories to compare.
714
716
715 When two revision arguments are given, then changes are shown between
717 When two revision arguments are given, then changes are shown between
716 those revisions. If only one revision is specified then that revision is
718 those revisions. If only one revision is specified then that revision is
717 compared to the working directory, and, when no revisions are specified,
719 compared to the working directory, and, when no revisions are specified,
718 the working directory files are compared to its parent.
720 the working directory files are compared to its parent.
719
721
720 (use 'hg help -e extdiff' to show help for the extdiff extension)
722 (use 'hg help -e extdiff' to show help for the extdiff extension)
721
723
722 options ([+] can be repeated):
724 options ([+] can be repeated):
723
725
724 -p --program CMD comparison program to run
726 -p --program CMD comparison program to run
725 -o --option OPT [+] pass option to comparison program
727 -o --option OPT [+] pass option to comparison program
726 -r --rev REV [+] revision
728 -r --rev REV [+] revision
727 -c --change REV change made by revision
729 -c --change REV change made by revision
728 --patch compare patches for two revisions
730 --patch compare patches for two revisions
729 -I --include PATTERN [+] include names matching the given patterns
731 -I --include PATTERN [+] include names matching the given patterns
730 -X --exclude PATTERN [+] exclude names matching the given patterns
732 -X --exclude PATTERN [+] exclude names matching the given patterns
731 -S --subrepos recurse into subrepositories
733 -S --subrepos recurse into subrepositories
732
734
733 (some details hidden, use --verbose to show complete help)
735 (some details hidden, use --verbose to show complete help)
734
736
735
737
736
738
737
739
738
740
739
741
740
742
741
743
742
744
743
745
744 $ hg help --extension extdiff
746 $ hg help --extension extdiff
745 extdiff extension - command to allow external programs to compare revisions
747 extdiff extension - command to allow external programs to compare revisions
746
748
747 The extdiff Mercurial extension allows you to use external programs to compare
749 The extdiff Mercurial extension allows you to use external programs to compare
748 revisions, or revision with working directory. The external diff programs are
750 revisions, or revision with working directory. The external diff programs are
749 called with a configurable set of options and two non-option arguments: paths
751 called with a configurable set of options and two non-option arguments: paths
750 to directories containing snapshots of files to compare.
752 to directories containing snapshots of files to compare.
751
753
752 If there is more than one file being compared and the "child" revision is the
754 If there is more than one file being compared and the "child" revision is the
753 working directory, any modifications made in the external diff program will be
755 working directory, any modifications made in the external diff program will be
754 copied back to the working directory from the temporary directory.
756 copied back to the working directory from the temporary directory.
755
757
756 The extdiff extension also allows you to configure new diff commands, so you
758 The extdiff extension also allows you to configure new diff commands, so you
757 do not need to type 'hg extdiff -p kdiff3' always.
759 do not need to type 'hg extdiff -p kdiff3' always.
758
760
759 [extdiff]
761 [extdiff]
760 # add new command that runs GNU diff(1) in 'context diff' mode
762 # add new command that runs GNU diff(1) in 'context diff' mode
761 cdiff = gdiff -Nprc5
763 cdiff = gdiff -Nprc5
762 ## or the old way:
764 ## or the old way:
763 #cmd.cdiff = gdiff
765 #cmd.cdiff = gdiff
764 #opts.cdiff = -Nprc5
766 #opts.cdiff = -Nprc5
765
767
766 # add new command called meld, runs meld (no need to name twice). If
768 # add new command called meld, runs meld (no need to name twice). If
767 # the meld executable is not available, the meld tool in [merge-tools]
769 # the meld executable is not available, the meld tool in [merge-tools]
768 # will be used, if available
770 # will be used, if available
769 meld =
771 meld =
770
772
771 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
773 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
772 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
774 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
773 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
775 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
774 # your .vimrc
776 # your .vimrc
775 vimdiff = gvim -f "+next" \
777 vimdiff = gvim -f "+next" \
776 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
778 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
777
779
778 Tool arguments can include variables that are expanded at runtime:
780 Tool arguments can include variables that are expanded at runtime:
779
781
780 $parent1, $plabel1 - filename, descriptive label of first parent
782 $parent1, $plabel1 - filename, descriptive label of first parent
781 $child, $clabel - filename, descriptive label of child revision
783 $child, $clabel - filename, descriptive label of child revision
782 $parent2, $plabel2 - filename, descriptive label of second parent
784 $parent2, $plabel2 - filename, descriptive label of second parent
783 $root - repository root
785 $root - repository root
784 $parent is an alias for $parent1.
786 $parent is an alias for $parent1.
785
787
786 The extdiff extension will look in your [diff-tools] and [merge-tools]
788 The extdiff extension will look in your [diff-tools] and [merge-tools]
787 sections for diff tool arguments, when none are specified in [extdiff].
789 sections for diff tool arguments, when none are specified in [extdiff].
788
790
789 [extdiff]
791 [extdiff]
790 kdiff3 =
792 kdiff3 =
791
793
792 [diff-tools]
794 [diff-tools]
793 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
795 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
794
796
795 You can use -I/-X and list of file or directory names like normal 'hg diff'
797 You can use -I/-X and list of file or directory names like normal 'hg diff'
796 command. The extdiff extension makes snapshots of only needed files, so
798 command. The extdiff extension makes snapshots of only needed files, so
797 running the external diff program will actually be pretty fast (at least
799 running the external diff program will actually be pretty fast (at least
798 faster than having to compare the entire tree).
800 faster than having to compare the entire tree).
799
801
800 list of commands:
802 list of commands:
801
803
802 extdiff use external program to diff repository (or selected files)
804 extdiff use external program to diff repository (or selected files)
803
805
804 (use 'hg help -v -e extdiff' to show built-in aliases and global options)
806 (use 'hg help -v -e extdiff' to show built-in aliases and global options)
805
807
806
808
807
809
808
810
809
811
810
812
811
813
812
814
813
815
814
816
815
817
816
818
817
819
818
820
819
821
820
822
821 $ echo 'extdiff = !' >> $HGRCPATH
823 $ echo 'extdiff = !' >> $HGRCPATH
822
824
823 Test help topic with same name as extension
825 Test help topic with same name as extension
824
826
825 $ cat > multirevs.py <<EOF
827 $ cat > multirevs.py <<EOF
826 > from mercurial import commands, registrar
828 > from mercurial import commands, registrar
827 > cmdtable = {}
829 > cmdtable = {}
828 > command = registrar.command(cmdtable)
830 > command = registrar.command(cmdtable)
829 > """multirevs extension
831 > """multirevs extension
830 > Big multi-line module docstring."""
832 > Big multi-line module docstring."""
831 > @command(b'multirevs', [], b'ARG', norepo=True)
833 > @command(b'multirevs', [], b'ARG', norepo=True)
832 > def multirevs(ui, repo, arg, *args, **opts):
834 > def multirevs(ui, repo, arg, *args, **opts):
833 > """multirevs command"""
835 > """multirevs command"""
834 > pass
836 > pass
835 > EOF
837 > EOF
836 $ echo "multirevs = multirevs.py" >> $HGRCPATH
838 $ echo "multirevs = multirevs.py" >> $HGRCPATH
837
839
838 $ hg help multirevs | tail
840 $ hg help multirevs | tail
839 used):
841 used):
840
842
841 hg update :@
843 hg update :@
842
844
843 - Show diff between tags 1.3 and 1.5 (this works because the first and the
845 - Show diff between tags 1.3 and 1.5 (this works because the first and the
844 last revisions of the revset are used):
846 last revisions of the revset are used):
845
847
846 hg diff -r 1.3::1.5
848 hg diff -r 1.3::1.5
847
849
848 use 'hg help -c multirevs' to see help for the multirevs command
850 use 'hg help -c multirevs' to see help for the multirevs command
849
851
850
852
851
853
852
854
853
855
854
856
855 $ hg help -c multirevs
857 $ hg help -c multirevs
856 hg multirevs ARG
858 hg multirevs ARG
857
859
858 multirevs command
860 multirevs command
859
861
860 (some details hidden, use --verbose to show complete help)
862 (some details hidden, use --verbose to show complete help)
861
863
862
864
863
865
864 $ hg multirevs
866 $ hg multirevs
865 hg multirevs: invalid arguments
867 hg multirevs: invalid arguments
866 hg multirevs ARG
868 hg multirevs ARG
867
869
868 multirevs command
870 multirevs command
869
871
870 (use 'hg multirevs -h' to show more help)
872 (use 'hg multirevs -h' to show more help)
871 [255]
873 [255]
872
874
873
875
874
876
875 $ echo "multirevs = !" >> $HGRCPATH
877 $ echo "multirevs = !" >> $HGRCPATH
876
878
877 Issue811: Problem loading extensions twice (by site and by user)
879 Issue811: Problem loading extensions twice (by site and by user)
878
880
879 $ cat <<EOF >> $HGRCPATH
881 $ cat <<EOF >> $HGRCPATH
880 > mq =
882 > mq =
881 > strip =
883 > strip =
882 > hgext.mq =
884 > hgext.mq =
883 > hgext/mq =
885 > hgext/mq =
884 > EOF
886 > EOF
885
887
886 Show extensions:
888 Show extensions:
887 (note that mq force load strip, also checking it's not loaded twice)
889 (note that mq force load strip, also checking it's not loaded twice)
888
890
889 #if no-extraextensions
891 #if no-extraextensions
890 $ hg debugextensions
892 $ hg debugextensions
891 mq
893 mq
892 strip
894 strip
893 #endif
895 #endif
894
896
895 For extensions, which name matches one of its commands, help
897 For extensions, which name matches one of its commands, help
896 message should ask '-v -e' to get list of built-in aliases
898 message should ask '-v -e' to get list of built-in aliases
897 along with extension help itself
899 along with extension help itself
898
900
899 $ mkdir $TESTTMP/d
901 $ mkdir $TESTTMP/d
900 $ cat > $TESTTMP/d/dodo.py <<EOF
902 $ cat > $TESTTMP/d/dodo.py <<EOF
901 > """
903 > """
902 > This is an awesome 'dodo' extension. It does nothing and
904 > This is an awesome 'dodo' extension. It does nothing and
903 > writes 'Foo foo'
905 > writes 'Foo foo'
904 > """
906 > """
905 > from mercurial import commands, registrar
907 > from mercurial import commands, registrar
906 > cmdtable = {}
908 > cmdtable = {}
907 > command = registrar.command(cmdtable)
909 > command = registrar.command(cmdtable)
908 > @command(b'dodo', [], b'hg dodo')
910 > @command(b'dodo', [], b'hg dodo')
909 > def dodo(ui, *args, **kwargs):
911 > def dodo(ui, *args, **kwargs):
910 > """Does nothing"""
912 > """Does nothing"""
911 > ui.write(b"I do nothing. Yay\\n")
913 > ui.write(b"I do nothing. Yay\\n")
912 > @command(b'foofoo', [], b'hg foofoo')
914 > @command(b'foofoo', [], b'hg foofoo')
913 > def foofoo(ui, *args, **kwargs):
915 > def foofoo(ui, *args, **kwargs):
914 > """Writes 'Foo foo'"""
916 > """Writes 'Foo foo'"""
915 > ui.write(b"Foo foo\\n")
917 > ui.write(b"Foo foo\\n")
916 > EOF
918 > EOF
917 $ dodopath=$TESTTMP/d/dodo.py
919 $ dodopath=$TESTTMP/d/dodo.py
918
920
919 $ echo "dodo = $dodopath" >> $HGRCPATH
921 $ echo "dodo = $dodopath" >> $HGRCPATH
920
922
921 Make sure that user is asked to enter '-v -e' to get list of built-in aliases
923 Make sure that user is asked to enter '-v -e' to get list of built-in aliases
922 $ hg help -e dodo
924 $ hg help -e dodo
923 dodo extension -
925 dodo extension -
924
926
925 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
927 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
926
928
927 list of commands:
929 list of commands:
928
930
929 dodo Does nothing
931 dodo Does nothing
930 foofoo Writes 'Foo foo'
932 foofoo Writes 'Foo foo'
931
933
932 (use 'hg help -v -e dodo' to show built-in aliases and global options)
934 (use 'hg help -v -e dodo' to show built-in aliases and global options)
933
935
934 Make sure that '-v -e' prints list of built-in aliases along with
936 Make sure that '-v -e' prints list of built-in aliases along with
935 extension help itself
937 extension help itself
936 $ hg help -v -e dodo
938 $ hg help -v -e dodo
937 dodo extension -
939 dodo extension -
938
940
939 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
941 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
940
942
941 list of commands:
943 list of commands:
942
944
943 dodo Does nothing
945 dodo Does nothing
944 foofoo Writes 'Foo foo'
946 foofoo Writes 'Foo foo'
945
947
946 global options ([+] can be repeated):
948 global options ([+] can be repeated):
947
949
948 -R --repository REPO repository root directory or name of overlay bundle
950 -R --repository REPO repository root directory or name of overlay bundle
949 file
951 file
950 --cwd DIR change working directory
952 --cwd DIR change working directory
951 -y --noninteractive do not prompt, automatically pick the first choice for
953 -y --noninteractive do not prompt, automatically pick the first choice for
952 all prompts
954 all prompts
953 -q --quiet suppress output
955 -q --quiet suppress output
954 -v --verbose enable additional output
956 -v --verbose enable additional output
955 --color TYPE when to colorize (boolean, always, auto, never, or
957 --color TYPE when to colorize (boolean, always, auto, never, or
956 debug)
958 debug)
957 --config CONFIG [+] set/override config option (use 'section.name=value')
959 --config CONFIG [+] set/override config option (use 'section.name=value')
958 --debug enable debugging output
960 --debug enable debugging output
959 --debugger start debugger
961 --debugger start debugger
960 --encoding ENCODE set the charset encoding (default: ascii)
962 --encoding ENCODE set the charset encoding (default: ascii)
961 --encodingmode MODE set the charset encoding mode (default: strict)
963 --encodingmode MODE set the charset encoding mode (default: strict)
962 --traceback always print a traceback on exception
964 --traceback always print a traceback on exception
963 --time time how long the command takes
965 --time time how long the command takes
964 --profile print command execution profile
966 --profile print command execution profile
965 --version output version information and exit
967 --version output version information and exit
966 -h --help display help and exit
968 -h --help display help and exit
967 --hidden consider hidden changesets
969 --hidden consider hidden changesets
968 --pager TYPE when to paginate (boolean, always, auto, or never)
970 --pager TYPE when to paginate (boolean, always, auto, or never)
969 (default: auto)
971 (default: auto)
970
972
971 Make sure that single '-v' option shows help and built-ins only for 'dodo' command
973 Make sure that single '-v' option shows help and built-ins only for 'dodo' command
972 $ hg help -v dodo
974 $ hg help -v dodo
973 hg dodo
975 hg dodo
974
976
975 Does nothing
977 Does nothing
976
978
977 (use 'hg help -e dodo' to show help for the dodo extension)
979 (use 'hg help -e dodo' to show help for the dodo extension)
978
980
979 options:
981 options:
980
982
981 --mq operate on patch repository
983 --mq operate on patch repository
982
984
983 global options ([+] can be repeated):
985 global options ([+] can be repeated):
984
986
985 -R --repository REPO repository root directory or name of overlay bundle
987 -R --repository REPO repository root directory or name of overlay bundle
986 file
988 file
987 --cwd DIR change working directory
989 --cwd DIR change working directory
988 -y --noninteractive do not prompt, automatically pick the first choice for
990 -y --noninteractive do not prompt, automatically pick the first choice for
989 all prompts
991 all prompts
990 -q --quiet suppress output
992 -q --quiet suppress output
991 -v --verbose enable additional output
993 -v --verbose enable additional output
992 --color TYPE when to colorize (boolean, always, auto, never, or
994 --color TYPE when to colorize (boolean, always, auto, never, or
993 debug)
995 debug)
994 --config CONFIG [+] set/override config option (use 'section.name=value')
996 --config CONFIG [+] set/override config option (use 'section.name=value')
995 --debug enable debugging output
997 --debug enable debugging output
996 --debugger start debugger
998 --debugger start debugger
997 --encoding ENCODE set the charset encoding (default: ascii)
999 --encoding ENCODE set the charset encoding (default: ascii)
998 --encodingmode MODE set the charset encoding mode (default: strict)
1000 --encodingmode MODE set the charset encoding mode (default: strict)
999 --traceback always print a traceback on exception
1001 --traceback always print a traceback on exception
1000 --time time how long the command takes
1002 --time time how long the command takes
1001 --profile print command execution profile
1003 --profile print command execution profile
1002 --version output version information and exit
1004 --version output version information and exit
1003 -h --help display help and exit
1005 -h --help display help and exit
1004 --hidden consider hidden changesets
1006 --hidden consider hidden changesets
1005 --pager TYPE when to paginate (boolean, always, auto, or never)
1007 --pager TYPE when to paginate (boolean, always, auto, or never)
1006 (default: auto)
1008 (default: auto)
1007
1009
1008 In case when extension name doesn't match any of its commands,
1010 In case when extension name doesn't match any of its commands,
1009 help message should ask for '-v' to get list of built-in aliases
1011 help message should ask for '-v' to get list of built-in aliases
1010 along with extension help
1012 along with extension help
1011 $ cat > $TESTTMP/d/dudu.py <<EOF
1013 $ cat > $TESTTMP/d/dudu.py <<EOF
1012 > """
1014 > """
1013 > This is an awesome 'dudu' extension. It does something and
1015 > This is an awesome 'dudu' extension. It does something and
1014 > also writes 'Beep beep'
1016 > also writes 'Beep beep'
1015 > """
1017 > """
1016 > from mercurial import commands, registrar
1018 > from mercurial import commands, registrar
1017 > cmdtable = {}
1019 > cmdtable = {}
1018 > command = registrar.command(cmdtable)
1020 > command = registrar.command(cmdtable)
1019 > @command(b'something', [], b'hg something')
1021 > @command(b'something', [], b'hg something')
1020 > def something(ui, *args, **kwargs):
1022 > def something(ui, *args, **kwargs):
1021 > """Does something"""
1023 > """Does something"""
1022 > ui.write(b"I do something. Yaaay\\n")
1024 > ui.write(b"I do something. Yaaay\\n")
1023 > @command(b'beep', [], b'hg beep')
1025 > @command(b'beep', [], b'hg beep')
1024 > def beep(ui, *args, **kwargs):
1026 > def beep(ui, *args, **kwargs):
1025 > """Writes 'Beep beep'"""
1027 > """Writes 'Beep beep'"""
1026 > ui.write(b"Beep beep\\n")
1028 > ui.write(b"Beep beep\\n")
1027 > EOF
1029 > EOF
1028 $ dudupath=$TESTTMP/d/dudu.py
1030 $ dudupath=$TESTTMP/d/dudu.py
1029
1031
1030 $ echo "dudu = $dudupath" >> $HGRCPATH
1032 $ echo "dudu = $dudupath" >> $HGRCPATH
1031
1033
1032 $ hg help -e dudu
1034 $ hg help -e dudu
1033 dudu extension -
1035 dudu extension -
1034
1036
1035 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1037 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1036 beep'
1038 beep'
1037
1039
1038 list of commands:
1040 list of commands:
1039
1041
1040 beep Writes 'Beep beep'
1042 beep Writes 'Beep beep'
1041 something Does something
1043 something Does something
1042
1044
1043 (use 'hg help -v dudu' to show built-in aliases and global options)
1045 (use 'hg help -v dudu' to show built-in aliases and global options)
1044
1046
1045 In case when extension name doesn't match any of its commands,
1047 In case when extension name doesn't match any of its commands,
1046 help options '-v' and '-v -e' should be equivalent
1048 help options '-v' and '-v -e' should be equivalent
1047 $ hg help -v dudu
1049 $ hg help -v dudu
1048 dudu extension -
1050 dudu extension -
1049
1051
1050 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1052 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1051 beep'
1053 beep'
1052
1054
1053 list of commands:
1055 list of commands:
1054
1056
1055 beep Writes 'Beep beep'
1057 beep Writes 'Beep beep'
1056 something Does something
1058 something Does something
1057
1059
1058 global options ([+] can be repeated):
1060 global options ([+] can be repeated):
1059
1061
1060 -R --repository REPO repository root directory or name of overlay bundle
1062 -R --repository REPO repository root directory or name of overlay bundle
1061 file
1063 file
1062 --cwd DIR change working directory
1064 --cwd DIR change working directory
1063 -y --noninteractive do not prompt, automatically pick the first choice for
1065 -y --noninteractive do not prompt, automatically pick the first choice for
1064 all prompts
1066 all prompts
1065 -q --quiet suppress output
1067 -q --quiet suppress output
1066 -v --verbose enable additional output
1068 -v --verbose enable additional output
1067 --color TYPE when to colorize (boolean, always, auto, never, or
1069 --color TYPE when to colorize (boolean, always, auto, never, or
1068 debug)
1070 debug)
1069 --config CONFIG [+] set/override config option (use 'section.name=value')
1071 --config CONFIG [+] set/override config option (use 'section.name=value')
1070 --debug enable debugging output
1072 --debug enable debugging output
1071 --debugger start debugger
1073 --debugger start debugger
1072 --encoding ENCODE set the charset encoding (default: ascii)
1074 --encoding ENCODE set the charset encoding (default: ascii)
1073 --encodingmode MODE set the charset encoding mode (default: strict)
1075 --encodingmode MODE set the charset encoding mode (default: strict)
1074 --traceback always print a traceback on exception
1076 --traceback always print a traceback on exception
1075 --time time how long the command takes
1077 --time time how long the command takes
1076 --profile print command execution profile
1078 --profile print command execution profile
1077 --version output version information and exit
1079 --version output version information and exit
1078 -h --help display help and exit
1080 -h --help display help and exit
1079 --hidden consider hidden changesets
1081 --hidden consider hidden changesets
1080 --pager TYPE when to paginate (boolean, always, auto, or never)
1082 --pager TYPE when to paginate (boolean, always, auto, or never)
1081 (default: auto)
1083 (default: auto)
1082
1084
1083 $ hg help -v -e dudu
1085 $ hg help -v -e dudu
1084 dudu extension -
1086 dudu extension -
1085
1087
1086 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1088 This is an awesome 'dudu' extension. It does something and also writes 'Beep
1087 beep'
1089 beep'
1088
1090
1089 list of commands:
1091 list of commands:
1090
1092
1091 beep Writes 'Beep beep'
1093 beep Writes 'Beep beep'
1092 something Does something
1094 something Does something
1093
1095
1094 global options ([+] can be repeated):
1096 global options ([+] can be repeated):
1095
1097
1096 -R --repository REPO repository root directory or name of overlay bundle
1098 -R --repository REPO repository root directory or name of overlay bundle
1097 file
1099 file
1098 --cwd DIR change working directory
1100 --cwd DIR change working directory
1099 -y --noninteractive do not prompt, automatically pick the first choice for
1101 -y --noninteractive do not prompt, automatically pick the first choice for
1100 all prompts
1102 all prompts
1101 -q --quiet suppress output
1103 -q --quiet suppress output
1102 -v --verbose enable additional output
1104 -v --verbose enable additional output
1103 --color TYPE when to colorize (boolean, always, auto, never, or
1105 --color TYPE when to colorize (boolean, always, auto, never, or
1104 debug)
1106 debug)
1105 --config CONFIG [+] set/override config option (use 'section.name=value')
1107 --config CONFIG [+] set/override config option (use 'section.name=value')
1106 --debug enable debugging output
1108 --debug enable debugging output
1107 --debugger start debugger
1109 --debugger start debugger
1108 --encoding ENCODE set the charset encoding (default: ascii)
1110 --encoding ENCODE set the charset encoding (default: ascii)
1109 --encodingmode MODE set the charset encoding mode (default: strict)
1111 --encodingmode MODE set the charset encoding mode (default: strict)
1110 --traceback always print a traceback on exception
1112 --traceback always print a traceback on exception
1111 --time time how long the command takes
1113 --time time how long the command takes
1112 --profile print command execution profile
1114 --profile print command execution profile
1113 --version output version information and exit
1115 --version output version information and exit
1114 -h --help display help and exit
1116 -h --help display help and exit
1115 --hidden consider hidden changesets
1117 --hidden consider hidden changesets
1116 --pager TYPE when to paginate (boolean, always, auto, or never)
1118 --pager TYPE when to paginate (boolean, always, auto, or never)
1117 (default: auto)
1119 (default: auto)
1118
1120
1119 Disabled extension commands:
1121 Disabled extension commands:
1120
1122
1121 $ ORGHGRCPATH=$HGRCPATH
1123 $ ORGHGRCPATH=$HGRCPATH
1122 $ HGRCPATH=
1124 $ HGRCPATH=
1123 $ export HGRCPATH
1125 $ export HGRCPATH
1124 $ hg help email
1126 $ hg help email
1125 'email' is provided by the following extension:
1127 'email' is provided by the following extension:
1126
1128
1127 patchbomb command to send changesets as (a series of) patch emails
1129 patchbomb command to send changesets as (a series of) patch emails
1128
1130
1129 (use 'hg help extensions' for information on enabling extensions)
1131 (use 'hg help extensions' for information on enabling extensions)
1130
1132
1131
1133
1132 $ hg qdel
1134 $ hg qdel
1133 hg: unknown command 'qdel'
1135 hg: unknown command 'qdel'
1134 'qdelete' is provided by the following extension:
1136 'qdelete' is provided by the following extension:
1135
1137
1136 mq manage a stack of patches
1138 mq manage a stack of patches
1137
1139
1138 (use 'hg help extensions' for information on enabling extensions)
1140 (use 'hg help extensions' for information on enabling extensions)
1139 [255]
1141 [255]
1140
1142
1141
1143
1142 $ hg churn
1144 $ hg churn
1143 hg: unknown command 'churn'
1145 hg: unknown command 'churn'
1144 'churn' is provided by the following extension:
1146 'churn' is provided by the following extension:
1145
1147
1146 churn command to display statistics about repository history
1148 churn command to display statistics about repository history
1147
1149
1148 (use 'hg help extensions' for information on enabling extensions)
1150 (use 'hg help extensions' for information on enabling extensions)
1149 [255]
1151 [255]
1150
1152
1151
1153
1152
1154
1153 Disabled extensions:
1155 Disabled extensions:
1154
1156
1155 $ hg help churn
1157 $ hg help churn
1156 churn extension - command to display statistics about repository history
1158 churn extension - command to display statistics about repository history
1157
1159
1158 (use 'hg help extensions' for information on enabling extensions)
1160 (use 'hg help extensions' for information on enabling extensions)
1159
1161
1160 $ hg help patchbomb
1162 $ hg help patchbomb
1161 patchbomb extension - command to send changesets as (a series of) patch emails
1163 patchbomb extension - command to send changesets as (a series of) patch emails
1162
1164
1163 The series is started off with a "[PATCH 0 of N]" introduction, which
1165 The series is started off with a "[PATCH 0 of N]" introduction, which
1164 describes the series as a whole.
1166 describes the series as a whole.
1165
1167
1166 Each patch email has a Subject line of "[PATCH M of N] ...", using the first
1168 Each patch email has a Subject line of "[PATCH M of N] ...", using the first
1167 line of the changeset description as the subject text. The message contains
1169 line of the changeset description as the subject text. The message contains
1168 two or three body parts:
1170 two or three body parts:
1169
1171
1170 - The changeset description.
1172 - The changeset description.
1171 - [Optional] The result of running diffstat on the patch.
1173 - [Optional] The result of running diffstat on the patch.
1172 - The patch itself, as generated by 'hg export'.
1174 - The patch itself, as generated by 'hg export'.
1173
1175
1174 Each message refers to the first in the series using the In-Reply-To and
1176 Each message refers to the first in the series using the In-Reply-To and
1175 References headers, so they will show up as a sequence in threaded mail and
1177 References headers, so they will show up as a sequence in threaded mail and
1176 news readers, and in mail archives.
1178 news readers, and in mail archives.
1177
1179
1178 To configure other defaults, add a section like this to your configuration
1180 To configure other defaults, add a section like this to your configuration
1179 file:
1181 file:
1180
1182
1181 [email]
1183 [email]
1182 from = My Name <my@email>
1184 from = My Name <my@email>
1183 to = recipient1, recipient2, ...
1185 to = recipient1, recipient2, ...
1184 cc = cc1, cc2, ...
1186 cc = cc1, cc2, ...
1185 bcc = bcc1, bcc2, ...
1187 bcc = bcc1, bcc2, ...
1186 reply-to = address1, address2, ...
1188 reply-to = address1, address2, ...
1187
1189
1188 Use "[patchbomb]" as configuration section name if you need to override global
1190 Use "[patchbomb]" as configuration section name if you need to override global
1189 "[email]" address settings.
1191 "[email]" address settings.
1190
1192
1191 Then you can use the 'hg email' command to mail a series of changesets as a
1193 Then you can use the 'hg email' command to mail a series of changesets as a
1192 patchbomb.
1194 patchbomb.
1193
1195
1194 You can also either configure the method option in the email section to be a
1196 You can also either configure the method option in the email section to be a
1195 sendmail compatible mailer or fill out the [smtp] section so that the
1197 sendmail compatible mailer or fill out the [smtp] section so that the
1196 patchbomb extension can automatically send patchbombs directly from the
1198 patchbomb extension can automatically send patchbombs directly from the
1197 commandline. See the [email] and [smtp] sections in hgrc(5) for details.
1199 commandline. See the [email] and [smtp] sections in hgrc(5) for details.
1198
1200
1199 By default, 'hg email' will prompt for a "To" or "CC" header if you do not
1201 By default, 'hg email' will prompt for a "To" or "CC" header if you do not
1200 supply one via configuration or the command line. You can override this to
1202 supply one via configuration or the command line. You can override this to
1201 never prompt by configuring an empty value:
1203 never prompt by configuring an empty value:
1202
1204
1203 [email]
1205 [email]
1204 cc =
1206 cc =
1205
1207
1206 You can control the default inclusion of an introduction message with the
1208 You can control the default inclusion of an introduction message with the
1207 "patchbomb.intro" configuration option. The configuration is always
1209 "patchbomb.intro" configuration option. The configuration is always
1208 overwritten by command line flags like --intro and --desc:
1210 overwritten by command line flags like --intro and --desc:
1209
1211
1210 [patchbomb]
1212 [patchbomb]
1211 intro=auto # include introduction message if more than 1 patch (default)
1213 intro=auto # include introduction message if more than 1 patch (default)
1212 intro=never # never include an introduction message
1214 intro=never # never include an introduction message
1213 intro=always # always include an introduction message
1215 intro=always # always include an introduction message
1214
1216
1215 You can specify a template for flags to be added in subject prefixes. Flags
1217 You can specify a template for flags to be added in subject prefixes. Flags
1216 specified by --flag option are exported as "{flags}" keyword:
1218 specified by --flag option are exported as "{flags}" keyword:
1217
1219
1218 [patchbomb]
1220 [patchbomb]
1219 flagtemplate = "{separate(' ',
1221 flagtemplate = "{separate(' ',
1220 ifeq(branch, 'default', '', branch|upper),
1222 ifeq(branch, 'default', '', branch|upper),
1221 flags)}"
1223 flags)}"
1222
1224
1223 You can set patchbomb to always ask for confirmation by setting
1225 You can set patchbomb to always ask for confirmation by setting
1224 "patchbomb.confirm" to true.
1226 "patchbomb.confirm" to true.
1225
1227
1226 (use 'hg help extensions' for information on enabling extensions)
1228 (use 'hg help extensions' for information on enabling extensions)
1227
1229
1228
1230
1229 Broken disabled extension and command:
1231 Broken disabled extension and command:
1230
1232
1231 $ mkdir hgext
1233 $ mkdir hgext
1232 $ echo > hgext/__init__.py
1234 $ echo > hgext/__init__.py
1233 $ cat > hgext/broken.py <<EOF
1235 $ cat > hgext/broken.py <<EOF
1234 > "broken extension'
1236 > "broken extension'
1235 > EOF
1237 > EOF
1236 $ cat > path.py <<EOF
1238 $ cat > path.py <<EOF
1237 > import os, sys
1239 > import os, sys
1238 > sys.path.insert(0, os.environ['HGEXTPATH'])
1240 > sys.path.insert(0, os.environ['HGEXTPATH'])
1239 > EOF
1241 > EOF
1240 $ HGEXTPATH=`pwd`
1242 $ HGEXTPATH=`pwd`
1241 $ export HGEXTPATH
1243 $ export HGEXTPATH
1242
1244
1243 $ hg --config extensions.path=./path.py help broken
1245 $ hg --config extensions.path=./path.py help broken
1244 broken extension - (no help text available)
1246 broken extension - (no help text available)
1245
1247
1246 (use 'hg help extensions' for information on enabling extensions)
1248 (use 'hg help extensions' for information on enabling extensions)
1247
1249
1248
1250
1249 $ cat > hgext/forest.py <<EOF
1251 $ cat > hgext/forest.py <<EOF
1250 > cmdtable = None
1252 > cmdtable = None
1251 > @command()
1253 > @command()
1252 > def f():
1254 > def f():
1253 > pass
1255 > pass
1254 > @command(123)
1256 > @command(123)
1255 > def g():
1257 > def g():
1256 > pass
1258 > pass
1257 > EOF
1259 > EOF
1258 $ hg --config extensions.path=./path.py help foo
1260 $ hg --config extensions.path=./path.py help foo
1259 abort: no such help topic: foo
1261 abort: no such help topic: foo
1260 (try 'hg help --keyword foo')
1262 (try 'hg help --keyword foo')
1261 [255]
1263 [255]
1262
1264
1263 $ cat > throw.py <<EOF
1265 $ cat > throw.py <<EOF
1264 > from mercurial import commands, registrar, util
1266 > from mercurial import commands, registrar, util
1265 > cmdtable = {}
1267 > cmdtable = {}
1266 > command = registrar.command(cmdtable)
1268 > command = registrar.command(cmdtable)
1267 > class Bogon(Exception): pass
1269 > class Bogon(Exception): pass
1268 > @command(b'throw', [], b'hg throw', norepo=True)
1270 > @command(b'throw', [], b'hg throw', norepo=True)
1269 > def throw(ui, **opts):
1271 > def throw(ui, **opts):
1270 > """throws an exception"""
1272 > """throws an exception"""
1271 > raise Bogon()
1273 > raise Bogon()
1272 > EOF
1274 > EOF
1273
1275
1274 No declared supported version, extension complains:
1276 No declared supported version, extension complains:
1275 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1277 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1276 ** Unknown exception encountered with possibly-broken third-party extension throw
1278 ** Unknown exception encountered with possibly-broken third-party extension throw
1277 ** which supports versions unknown of Mercurial.
1279 ** which supports versions unknown of Mercurial.
1278 ** Please disable throw and try your action again.
1280 ** Please disable throw and try your action again.
1279 ** If that fixes the bug please report it to the extension author.
1281 ** If that fixes the bug please report it to the extension author.
1280 ** Python * (glob)
1282 ** Python * (glob)
1281 ** Mercurial Distributed SCM * (glob)
1283 ** Mercurial Distributed SCM * (glob)
1282 ** Extensions loaded: throw
1284 ** Extensions loaded: throw
1283
1285
1284 empty declaration of supported version, extension complains:
1286 empty declaration of supported version, extension complains:
1285 $ echo "testedwith = ''" >> throw.py
1287 $ echo "testedwith = ''" >> throw.py
1286 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1288 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1287 ** Unknown exception encountered with possibly-broken third-party extension throw
1289 ** Unknown exception encountered with possibly-broken third-party extension throw
1288 ** which supports versions unknown of Mercurial.
1290 ** which supports versions unknown of Mercurial.
1289 ** Please disable throw and try your action again.
1291 ** Please disable throw and try your action again.
1290 ** If that fixes the bug please report it to the extension author.
1292 ** If that fixes the bug please report it to the extension author.
1291 ** Python * (glob)
1293 ** Python * (glob)
1292 ** Mercurial Distributed SCM (*) (glob)
1294 ** Mercurial Distributed SCM (*) (glob)
1293 ** Extensions loaded: throw
1295 ** Extensions loaded: throw
1294
1296
1295 If the extension specifies a buglink, show that:
1297 If the extension specifies a buglink, show that:
1296 $ echo 'buglink = "http://example.com/bts"' >> throw.py
1298 $ echo 'buglink = "http://example.com/bts"' >> throw.py
1297 $ rm -f throw.pyc throw.pyo
1299 $ rm -f throw.pyc throw.pyo
1298 $ rm -Rf __pycache__
1300 $ rm -Rf __pycache__
1299 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1301 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1300 ** Unknown exception encountered with possibly-broken third-party extension throw
1302 ** Unknown exception encountered with possibly-broken third-party extension throw
1301 ** which supports versions unknown of Mercurial.
1303 ** which supports versions unknown of Mercurial.
1302 ** Please disable throw and try your action again.
1304 ** Please disable throw and try your action again.
1303 ** If that fixes the bug please report it to http://example.com/bts
1305 ** If that fixes the bug please report it to http://example.com/bts
1304 ** Python * (glob)
1306 ** Python * (glob)
1305 ** Mercurial Distributed SCM (*) (glob)
1307 ** Mercurial Distributed SCM (*) (glob)
1306 ** Extensions loaded: throw
1308 ** Extensions loaded: throw
1307
1309
1308 If the extensions declare outdated versions, accuse the older extension first:
1310 If the extensions declare outdated versions, accuse the older extension first:
1309 $ echo "from mercurial import util" >> older.py
1311 $ echo "from mercurial import util" >> older.py
1310 $ echo "util.version = lambda:b'2.2'" >> older.py
1312 $ echo "util.version = lambda:b'2.2'" >> older.py
1311 $ echo "testedwith = b'1.9.3'" >> older.py
1313 $ echo "testedwith = b'1.9.3'" >> older.py
1312 $ echo "testedwith = b'2.1.1'" >> throw.py
1314 $ echo "testedwith = b'2.1.1'" >> throw.py
1313 $ rm -f throw.pyc throw.pyo
1315 $ rm -f throw.pyc throw.pyo
1314 $ rm -Rf __pycache__
1316 $ rm -Rf __pycache__
1315 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1317 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1316 > throw 2>&1 | egrep '^\*\*'
1318 > throw 2>&1 | egrep '^\*\*'
1317 ** Unknown exception encountered with possibly-broken third-party extension older
1319 ** Unknown exception encountered with possibly-broken third-party extension older
1318 ** which supports versions 1.9 of Mercurial.
1320 ** which supports versions 1.9 of Mercurial.
1319 ** Please disable older and try your action again.
1321 ** Please disable older and try your action again.
1320 ** If that fixes the bug please report it to the extension author.
1322 ** If that fixes the bug please report it to the extension author.
1321 ** Python * (glob)
1323 ** Python * (glob)
1322 ** Mercurial Distributed SCM (version 2.2)
1324 ** Mercurial Distributed SCM (version 2.2)
1323 ** Extensions loaded: throw, older
1325 ** Extensions loaded: throw, older
1324
1326
1325 One extension only tested with older, one only with newer versions:
1327 One extension only tested with older, one only with newer versions:
1326 $ echo "util.version = lambda:b'2.1'" >> older.py
1328 $ echo "util.version = lambda:b'2.1'" >> older.py
1327 $ rm -f older.pyc older.pyo
1329 $ rm -f older.pyc older.pyo
1328 $ rm -Rf __pycache__
1330 $ rm -Rf __pycache__
1329 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1331 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1330 > throw 2>&1 | egrep '^\*\*'
1332 > throw 2>&1 | egrep '^\*\*'
1331 ** Unknown exception encountered with possibly-broken third-party extension older
1333 ** Unknown exception encountered with possibly-broken third-party extension older
1332 ** which supports versions 1.9 of Mercurial.
1334 ** which supports versions 1.9 of Mercurial.
1333 ** Please disable older and try your action again.
1335 ** Please disable older and try your action again.
1334 ** If that fixes the bug please report it to the extension author.
1336 ** If that fixes the bug please report it to the extension author.
1335 ** Python * (glob)
1337 ** Python * (glob)
1336 ** Mercurial Distributed SCM (version 2.1)
1338 ** Mercurial Distributed SCM (version 2.1)
1337 ** Extensions loaded: throw, older
1339 ** Extensions loaded: throw, older
1338
1340
1339 Older extension is tested with current version, the other only with newer:
1341 Older extension is tested with current version, the other only with newer:
1340 $ echo "util.version = lambda:b'1.9.3'" >> older.py
1342 $ echo "util.version = lambda:b'1.9.3'" >> older.py
1341 $ rm -f older.pyc older.pyo
1343 $ rm -f older.pyc older.pyo
1342 $ rm -Rf __pycache__
1344 $ rm -Rf __pycache__
1343 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1345 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1344 > throw 2>&1 | egrep '^\*\*'
1346 > throw 2>&1 | egrep '^\*\*'
1345 ** Unknown exception encountered with possibly-broken third-party extension throw
1347 ** Unknown exception encountered with possibly-broken third-party extension throw
1346 ** which supports versions 2.1 of Mercurial.
1348 ** which supports versions 2.1 of Mercurial.
1347 ** Please disable throw and try your action again.
1349 ** Please disable throw and try your action again.
1348 ** If that fixes the bug please report it to http://example.com/bts
1350 ** If that fixes the bug please report it to http://example.com/bts
1349 ** Python * (glob)
1351 ** Python * (glob)
1350 ** Mercurial Distributed SCM (version 1.9.3)
1352 ** Mercurial Distributed SCM (version 1.9.3)
1351 ** Extensions loaded: throw, older
1353 ** Extensions loaded: throw, older
1352
1354
1353 Ability to point to a different point
1355 Ability to point to a different point
1354 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1356 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1355 > --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | egrep '^\*\*'
1357 > --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | egrep '^\*\*'
1356 ** unknown exception encountered, please report by visiting
1358 ** unknown exception encountered, please report by visiting
1357 ** Your Local Goat Lenders
1359 ** Your Local Goat Lenders
1358 ** Python * (glob)
1360 ** Python * (glob)
1359 ** Mercurial Distributed SCM (*) (glob)
1361 ** Mercurial Distributed SCM (*) (glob)
1360 ** Extensions loaded: throw, older
1362 ** Extensions loaded: throw, older
1361
1363
1362 Declare the version as supporting this hg version, show regular bts link:
1364 Declare the version as supporting this hg version, show regular bts link:
1363 $ hgver=`hg debuginstall -T '{hgver}'`
1365 $ hgver=`hg debuginstall -T '{hgver}'`
1364 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
1366 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
1365 $ if [ -z "$hgver" ]; then
1367 $ if [ -z "$hgver" ]; then
1366 > echo "unable to fetch a mercurial version. Make sure __version__ is correct";
1368 > echo "unable to fetch a mercurial version. Make sure __version__ is correct";
1367 > fi
1369 > fi
1368 $ rm -f throw.pyc throw.pyo
1370 $ rm -f throw.pyc throw.pyo
1369 $ rm -Rf __pycache__
1371 $ rm -Rf __pycache__
1370 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1372 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1371 ** unknown exception encountered, please report by visiting
1373 ** unknown exception encountered, please report by visiting
1372 ** https://mercurial-scm.org/wiki/BugTracker
1374 ** https://mercurial-scm.org/wiki/BugTracker
1373 ** Python * (glob)
1375 ** Python * (glob)
1374 ** Mercurial Distributed SCM (*) (glob)
1376 ** Mercurial Distributed SCM (*) (glob)
1375 ** Extensions loaded: throw
1377 ** Extensions loaded: throw
1376
1378
1377 Patch version is ignored during compatibility check
1379 Patch version is ignored during compatibility check
1378 $ echo "testedwith = b'3.2'" >> throw.py
1380 $ echo "testedwith = b'3.2'" >> throw.py
1379 $ echo "util.version = lambda:b'3.2.2'" >> throw.py
1381 $ echo "util.version = lambda:b'3.2.2'" >> throw.py
1380 $ rm -f throw.pyc throw.pyo
1382 $ rm -f throw.pyc throw.pyo
1381 $ rm -Rf __pycache__
1383 $ rm -Rf __pycache__
1382 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1384 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1383 ** unknown exception encountered, please report by visiting
1385 ** unknown exception encountered, please report by visiting
1384 ** https://mercurial-scm.org/wiki/BugTracker
1386 ** https://mercurial-scm.org/wiki/BugTracker
1385 ** Python * (glob)
1387 ** Python * (glob)
1386 ** Mercurial Distributed SCM (*) (glob)
1388 ** Mercurial Distributed SCM (*) (glob)
1387 ** Extensions loaded: throw
1389 ** Extensions loaded: throw
1388
1390
1389 Test version number support in 'hg version':
1391 Test version number support in 'hg version':
1390 $ echo '__version__ = (1, 2, 3)' >> throw.py
1392 $ echo '__version__ = (1, 2, 3)' >> throw.py
1391 $ rm -f throw.pyc throw.pyo
1393 $ rm -f throw.pyc throw.pyo
1392 $ rm -Rf __pycache__
1394 $ rm -Rf __pycache__
1393 $ hg version -v
1395 $ hg version -v
1394 Mercurial Distributed SCM (version *) (glob)
1396 Mercurial Distributed SCM (version *) (glob)
1395 (see https://mercurial-scm.org for more information)
1397 (see https://mercurial-scm.org for more information)
1396
1398
1397 Copyright (C) 2005-* Matt Mackall and others (glob)
1399 Copyright (C) 2005-* Matt Mackall and others (glob)
1398 This is free software; see the source for copying conditions. There is NO
1400 This is free software; see the source for copying conditions. There is NO
1399 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1401 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1400
1402
1401 Enabled extensions:
1403 Enabled extensions:
1402
1404
1403
1405
1404 $ hg version -v --config extensions.throw=throw.py
1406 $ hg version -v --config extensions.throw=throw.py
1405 Mercurial Distributed SCM (version *) (glob)
1407 Mercurial Distributed SCM (version *) (glob)
1406 (see https://mercurial-scm.org for more information)
1408 (see https://mercurial-scm.org for more information)
1407
1409
1408 Copyright (C) 2005-* Matt Mackall and others (glob)
1410 Copyright (C) 2005-* Matt Mackall and others (glob)
1409 This is free software; see the source for copying conditions. There is NO
1411 This is free software; see the source for copying conditions. There is NO
1410 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1412 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1411
1413
1412 Enabled extensions:
1414 Enabled extensions:
1413
1415
1414 throw external 1.2.3
1416 throw external 1.2.3
1415 $ echo 'getversion = lambda: b"1.twentythree"' >> throw.py
1417 $ echo 'getversion = lambda: b"1.twentythree"' >> throw.py
1416 $ rm -f throw.pyc throw.pyo
1418 $ rm -f throw.pyc throw.pyo
1417 $ rm -Rf __pycache__
1419 $ rm -Rf __pycache__
1418 $ hg version -v --config extensions.throw=throw.py --config extensions.strip=
1420 $ hg version -v --config extensions.throw=throw.py --config extensions.strip=
1419 Mercurial Distributed SCM (version *) (glob)
1421 Mercurial Distributed SCM (version *) (glob)
1420 (see https://mercurial-scm.org for more information)
1422 (see https://mercurial-scm.org for more information)
1421
1423
1422 Copyright (C) 2005-* Matt Mackall and others (glob)
1424 Copyright (C) 2005-* Matt Mackall and others (glob)
1423 This is free software; see the source for copying conditions. There is NO
1425 This is free software; see the source for copying conditions. There is NO
1424 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1426 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1425
1427
1426 Enabled extensions:
1428 Enabled extensions:
1427
1429
1428 throw external 1.twentythree
1430 throw external 1.twentythree
1429 strip internal
1431 strip internal
1430
1432
1431 $ hg version -q --config extensions.throw=throw.py
1433 $ hg version -q --config extensions.throw=throw.py
1432 Mercurial Distributed SCM (version *) (glob)
1434 Mercurial Distributed SCM (version *) (glob)
1433
1435
1434 Test template output:
1436 Test template output:
1435
1437
1436 $ hg version --config extensions.strip= -T'{extensions}'
1438 $ hg version --config extensions.strip= -T'{extensions}'
1437 strip
1439 strip
1438
1440
1439 Test JSON output of version:
1441 Test JSON output of version:
1440
1442
1441 $ hg version -Tjson
1443 $ hg version -Tjson
1442 [
1444 [
1443 {
1445 {
1444 "extensions": [],
1446 "extensions": [],
1445 "ver": "*" (glob)
1447 "ver": "*" (glob)
1446 }
1448 }
1447 ]
1449 ]
1448
1450
1449 $ hg version --config extensions.throw=throw.py -Tjson
1451 $ hg version --config extensions.throw=throw.py -Tjson
1450 [
1452 [
1451 {
1453 {
1452 "extensions": [{"bundled": false, "name": "throw", "ver": "1.twentythree"}],
1454 "extensions": [{"bundled": false, "name": "throw", "ver": "1.twentythree"}],
1453 "ver": "3.2.2"
1455 "ver": "3.2.2"
1454 }
1456 }
1455 ]
1457 ]
1456
1458
1457 $ hg version --config extensions.strip= -Tjson
1459 $ hg version --config extensions.strip= -Tjson
1458 [
1460 [
1459 {
1461 {
1460 "extensions": [{"bundled": true, "name": "strip", "ver": null}],
1462 "extensions": [{"bundled": true, "name": "strip", "ver": null}],
1461 "ver": "*" (glob)
1463 "ver": "*" (glob)
1462 }
1464 }
1463 ]
1465 ]
1464
1466
1465 Test template output of version:
1467 Test template output of version:
1466
1468
1467 $ hg version --config extensions.throw=throw.py --config extensions.strip= \
1469 $ hg version --config extensions.throw=throw.py --config extensions.strip= \
1468 > -T'{extensions % "{name} {pad(ver, 16)} ({if(bundled, "internal", "external")})\n"}'
1470 > -T'{extensions % "{name} {pad(ver, 16)} ({if(bundled, "internal", "external")})\n"}'
1469 throw 1.twentythree (external)
1471 throw 1.twentythree (external)
1470 strip (internal)
1472 strip (internal)
1471
1473
1472 Refuse to load extensions with minimum version requirements
1474 Refuse to load extensions with minimum version requirements
1473
1475
1474 $ cat > minversion1.py << EOF
1476 $ cat > minversion1.py << EOF
1475 > from mercurial import util
1477 > from mercurial import util
1476 > util.version = lambda: b'3.5.2'
1478 > util.version = lambda: b'3.5.2'
1477 > minimumhgversion = b'3.6'
1479 > minimumhgversion = b'3.6'
1478 > EOF
1480 > EOF
1479 $ hg --config extensions.minversion=minversion1.py version
1481 $ hg --config extensions.minversion=minversion1.py version
1480 (third party extension minversion requires version 3.6 or newer of Mercurial; disabling)
1482 (third party extension minversion requires version 3.6 or newer of Mercurial; disabling)
1481 Mercurial Distributed SCM (version 3.5.2)
1483 Mercurial Distributed SCM (version 3.5.2)
1482 (see https://mercurial-scm.org for more information)
1484 (see https://mercurial-scm.org for more information)
1483
1485
1484 Copyright (C) 2005-* Matt Mackall and others (glob)
1486 Copyright (C) 2005-* Matt Mackall and others (glob)
1485 This is free software; see the source for copying conditions. There is NO
1487 This is free software; see the source for copying conditions. There is NO
1486 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1488 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1487
1489
1488 $ cat > minversion2.py << EOF
1490 $ cat > minversion2.py << EOF
1489 > from mercurial import util
1491 > from mercurial import util
1490 > util.version = lambda: b'3.6'
1492 > util.version = lambda: b'3.6'
1491 > minimumhgversion = b'3.7'
1493 > minimumhgversion = b'3.7'
1492 > EOF
1494 > EOF
1493 $ hg --config extensions.minversion=minversion2.py version 2>&1 | egrep '\(third'
1495 $ hg --config extensions.minversion=minversion2.py version 2>&1 | egrep '\(third'
1494 (third party extension minversion requires version 3.7 or newer of Mercurial; disabling)
1496 (third party extension minversion requires version 3.7 or newer of Mercurial; disabling)
1495
1497
1496 Can load version that is only off by point release
1498 Can load version that is only off by point release
1497
1499
1498 $ cat > minversion2.py << EOF
1500 $ cat > minversion2.py << EOF
1499 > from mercurial import util
1501 > from mercurial import util
1500 > util.version = lambda: b'3.6.1'
1502 > util.version = lambda: b'3.6.1'
1501 > minimumhgversion = b'3.6'
1503 > minimumhgversion = b'3.6'
1502 > EOF
1504 > EOF
1503 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1505 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1504 [1]
1506 [1]
1505
1507
1506 Can load minimum version identical to current
1508 Can load minimum version identical to current
1507
1509
1508 $ cat > minversion3.py << EOF
1510 $ cat > minversion3.py << EOF
1509 > from mercurial import util
1511 > from mercurial import util
1510 > util.version = lambda: b'3.5'
1512 > util.version = lambda: b'3.5'
1511 > minimumhgversion = b'3.5'
1513 > minimumhgversion = b'3.5'
1512 > EOF
1514 > EOF
1513 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1515 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1514 [1]
1516 [1]
1515
1517
1516 Restore HGRCPATH
1518 Restore HGRCPATH
1517
1519
1518 $ HGRCPATH=$ORGHGRCPATH
1520 $ HGRCPATH=$ORGHGRCPATH
1519 $ export HGRCPATH
1521 $ export HGRCPATH
1520
1522
1521 Commands handling multiple repositories at a time should invoke only
1523 Commands handling multiple repositories at a time should invoke only
1522 "reposetup()" of extensions enabling in the target repository.
1524 "reposetup()" of extensions enabling in the target repository.
1523
1525
1524 $ mkdir reposetup-test
1526 $ mkdir reposetup-test
1525 $ cd reposetup-test
1527 $ cd reposetup-test
1526
1528
1527 $ cat > $TESTTMP/reposetuptest.py <<EOF
1529 $ cat > $TESTTMP/reposetuptest.py <<EOF
1528 > from mercurial import extensions
1530 > from mercurial import extensions
1529 > def reposetup(ui, repo):
1531 > def reposetup(ui, repo):
1530 > ui.write(b'reposetup() for %s\n' % (repo.root))
1532 > ui.write(b'reposetup() for %s\n' % (repo.root))
1531 > ui.flush()
1533 > ui.flush()
1532 > EOF
1534 > EOF
1533 $ hg init src
1535 $ hg init src
1534 $ echo a > src/a
1536 $ echo a > src/a
1535 $ hg -R src commit -Am '#0 at src/a'
1537 $ hg -R src commit -Am '#0 at src/a'
1536 adding a
1538 adding a
1537 $ echo '[extensions]' >> src/.hg/hgrc
1539 $ echo '[extensions]' >> src/.hg/hgrc
1538 $ echo '# enable extension locally' >> src/.hg/hgrc
1540 $ echo '# enable extension locally' >> src/.hg/hgrc
1539 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
1541 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
1540 $ hg -R src status
1542 $ hg -R src status
1541 reposetup() for $TESTTMP/reposetup-test/src
1543 reposetup() for $TESTTMP/reposetup-test/src
1542 reposetup() for $TESTTMP/reposetup-test/src (chg !)
1544 reposetup() for $TESTTMP/reposetup-test/src (chg !)
1543
1545
1544 #if no-extraextensions
1546 #if no-extraextensions
1545 $ hg --cwd src debugextensions
1547 $ hg --cwd src debugextensions
1546 reposetup() for $TESTTMP/reposetup-test/src
1548 reposetup() for $TESTTMP/reposetup-test/src
1547 dodo (untested!)
1549 dodo (untested!)
1548 dudu (untested!)
1550 dudu (untested!)
1549 mq
1551 mq
1550 reposetuptest (untested!)
1552 reposetuptest (untested!)
1551 strip
1553 strip
1552 #endif
1554 #endif
1553
1555
1554 $ hg clone -U src clone-dst1
1556 $ hg clone -U src clone-dst1
1555 reposetup() for $TESTTMP/reposetup-test/src
1557 reposetup() for $TESTTMP/reposetup-test/src
1556 $ hg init push-dst1
1558 $ hg init push-dst1
1557 $ hg -q -R src push push-dst1
1559 $ hg -q -R src push push-dst1
1558 reposetup() for $TESTTMP/reposetup-test/src
1560 reposetup() for $TESTTMP/reposetup-test/src
1559 $ hg init pull-src1
1561 $ hg init pull-src1
1560 $ hg -q -R pull-src1 pull src
1562 $ hg -q -R pull-src1 pull src
1561 reposetup() for $TESTTMP/reposetup-test/src
1563 reposetup() for $TESTTMP/reposetup-test/src
1562
1564
1563 $ cat <<EOF >> $HGRCPATH
1565 $ cat <<EOF >> $HGRCPATH
1564 > [extensions]
1566 > [extensions]
1565 > # disable extension globally and explicitly
1567 > # disable extension globally and explicitly
1566 > reposetuptest = !
1568 > reposetuptest = !
1567 > EOF
1569 > EOF
1568 $ hg clone -U src clone-dst2
1570 $ hg clone -U src clone-dst2
1569 reposetup() for $TESTTMP/reposetup-test/src
1571 reposetup() for $TESTTMP/reposetup-test/src
1570 $ hg init push-dst2
1572 $ hg init push-dst2
1571 $ hg -q -R src push push-dst2
1573 $ hg -q -R src push push-dst2
1572 reposetup() for $TESTTMP/reposetup-test/src
1574 reposetup() for $TESTTMP/reposetup-test/src
1573 $ hg init pull-src2
1575 $ hg init pull-src2
1574 $ hg -q -R pull-src2 pull src
1576 $ hg -q -R pull-src2 pull src
1575 reposetup() for $TESTTMP/reposetup-test/src
1577 reposetup() for $TESTTMP/reposetup-test/src
1576
1578
1577 $ cat <<EOF >> $HGRCPATH
1579 $ cat <<EOF >> $HGRCPATH
1578 > [extensions]
1580 > [extensions]
1579 > # enable extension globally
1581 > # enable extension globally
1580 > reposetuptest = $TESTTMP/reposetuptest.py
1582 > reposetuptest = $TESTTMP/reposetuptest.py
1581 > EOF
1583 > EOF
1582 $ hg clone -U src clone-dst3
1584 $ hg clone -U src clone-dst3
1583 reposetup() for $TESTTMP/reposetup-test/src
1585 reposetup() for $TESTTMP/reposetup-test/src
1584 reposetup() for $TESTTMP/reposetup-test/clone-dst3
1586 reposetup() for $TESTTMP/reposetup-test/clone-dst3
1585 $ hg init push-dst3
1587 $ hg init push-dst3
1586 reposetup() for $TESTTMP/reposetup-test/push-dst3
1588 reposetup() for $TESTTMP/reposetup-test/push-dst3
1587 $ hg -q -R src push push-dst3
1589 $ hg -q -R src push push-dst3
1588 reposetup() for $TESTTMP/reposetup-test/src
1590 reposetup() for $TESTTMP/reposetup-test/src
1589 reposetup() for $TESTTMP/reposetup-test/push-dst3
1591 reposetup() for $TESTTMP/reposetup-test/push-dst3
1590 $ hg init pull-src3
1592 $ hg init pull-src3
1591 reposetup() for $TESTTMP/reposetup-test/pull-src3
1593 reposetup() for $TESTTMP/reposetup-test/pull-src3
1592 $ hg -q -R pull-src3 pull src
1594 $ hg -q -R pull-src3 pull src
1593 reposetup() for $TESTTMP/reposetup-test/pull-src3
1595 reposetup() for $TESTTMP/reposetup-test/pull-src3
1594 reposetup() for $TESTTMP/reposetup-test/src
1596 reposetup() for $TESTTMP/reposetup-test/src
1595
1597
1596 $ echo '[extensions]' >> src/.hg/hgrc
1598 $ echo '[extensions]' >> src/.hg/hgrc
1597 $ echo '# disable extension locally' >> src/.hg/hgrc
1599 $ echo '# disable extension locally' >> src/.hg/hgrc
1598 $ echo 'reposetuptest = !' >> src/.hg/hgrc
1600 $ echo 'reposetuptest = !' >> src/.hg/hgrc
1599 $ hg clone -U src clone-dst4
1601 $ hg clone -U src clone-dst4
1600 reposetup() for $TESTTMP/reposetup-test/clone-dst4
1602 reposetup() for $TESTTMP/reposetup-test/clone-dst4
1601 $ hg init push-dst4
1603 $ hg init push-dst4
1602 reposetup() for $TESTTMP/reposetup-test/push-dst4
1604 reposetup() for $TESTTMP/reposetup-test/push-dst4
1603 $ hg -q -R src push push-dst4
1605 $ hg -q -R src push push-dst4
1604 reposetup() for $TESTTMP/reposetup-test/push-dst4
1606 reposetup() for $TESTTMP/reposetup-test/push-dst4
1605 $ hg init pull-src4
1607 $ hg init pull-src4
1606 reposetup() for $TESTTMP/reposetup-test/pull-src4
1608 reposetup() for $TESTTMP/reposetup-test/pull-src4
1607 $ hg -q -R pull-src4 pull src
1609 $ hg -q -R pull-src4 pull src
1608 reposetup() for $TESTTMP/reposetup-test/pull-src4
1610 reposetup() for $TESTTMP/reposetup-test/pull-src4
1609
1611
1610 disabling in command line overlays with all configuration
1612 disabling in command line overlays with all configuration
1611 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
1613 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
1612 $ hg --config extensions.reposetuptest=! init push-dst5
1614 $ hg --config extensions.reposetuptest=! init push-dst5
1613 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
1615 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
1614 $ hg --config extensions.reposetuptest=! init pull-src5
1616 $ hg --config extensions.reposetuptest=! init pull-src5
1615 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
1617 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
1616
1618
1617 $ cat <<EOF >> $HGRCPATH
1619 $ cat <<EOF >> $HGRCPATH
1618 > [extensions]
1620 > [extensions]
1619 > # disable extension globally and explicitly
1621 > # disable extension globally and explicitly
1620 > reposetuptest = !
1622 > reposetuptest = !
1621 > EOF
1623 > EOF
1622 $ hg init parent
1624 $ hg init parent
1623 $ hg init parent/sub1
1625 $ hg init parent/sub1
1624 $ echo 1 > parent/sub1/1
1626 $ echo 1 > parent/sub1/1
1625 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
1627 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
1626 adding 1
1628 adding 1
1627 $ hg init parent/sub2
1629 $ hg init parent/sub2
1628 $ hg init parent/sub2/sub21
1630 $ hg init parent/sub2/sub21
1629 $ echo 21 > parent/sub2/sub21/21
1631 $ echo 21 > parent/sub2/sub21/21
1630 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
1632 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
1631 adding 21
1633 adding 21
1632 $ cat > parent/sub2/.hgsub <<EOF
1634 $ cat > parent/sub2/.hgsub <<EOF
1633 > sub21 = sub21
1635 > sub21 = sub21
1634 > EOF
1636 > EOF
1635 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
1637 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
1636 adding .hgsub
1638 adding .hgsub
1637 $ hg init parent/sub3
1639 $ hg init parent/sub3
1638 $ echo 3 > parent/sub3/3
1640 $ echo 3 > parent/sub3/3
1639 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
1641 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
1640 adding 3
1642 adding 3
1641 $ cat > parent/.hgsub <<EOF
1643 $ cat > parent/.hgsub <<EOF
1642 > sub1 = sub1
1644 > sub1 = sub1
1643 > sub2 = sub2
1645 > sub2 = sub2
1644 > sub3 = sub3
1646 > sub3 = sub3
1645 > EOF
1647 > EOF
1646 $ hg -R parent commit -Am '#0 at parent'
1648 $ hg -R parent commit -Am '#0 at parent'
1647 adding .hgsub
1649 adding .hgsub
1648 $ echo '[extensions]' >> parent/.hg/hgrc
1650 $ echo '[extensions]' >> parent/.hg/hgrc
1649 $ echo '# enable extension locally' >> parent/.hg/hgrc
1651 $ echo '# enable extension locally' >> parent/.hg/hgrc
1650 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
1652 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
1651 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
1653 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
1652 $ hg -R parent status -S -A
1654 $ hg -R parent status -S -A
1653 reposetup() for $TESTTMP/reposetup-test/parent
1655 reposetup() for $TESTTMP/reposetup-test/parent
1654 reposetup() for $TESTTMP/reposetup-test/parent/sub2
1656 reposetup() for $TESTTMP/reposetup-test/parent/sub2
1655 C .hgsub
1657 C .hgsub
1656 C .hgsubstate
1658 C .hgsubstate
1657 C sub1/1
1659 C sub1/1
1658 C sub2/.hgsub
1660 C sub2/.hgsub
1659 C sub2/.hgsubstate
1661 C sub2/.hgsubstate
1660 C sub2/sub21/21
1662 C sub2/sub21/21
1661 C sub3/3
1663 C sub3/3
1662
1664
1663 $ cd ..
1665 $ cd ..
1664
1666
1665 Prohibit registration of commands that don't use @command (issue5137)
1667 Prohibit registration of commands that don't use @command (issue5137)
1666
1668
1667 $ hg init deprecated
1669 $ hg init deprecated
1668 $ cd deprecated
1670 $ cd deprecated
1669
1671
1670 $ cat <<EOF > deprecatedcmd.py
1672 $ cat <<EOF > deprecatedcmd.py
1671 > def deprecatedcmd(repo, ui):
1673 > def deprecatedcmd(repo, ui):
1672 > pass
1674 > pass
1673 > cmdtable = {
1675 > cmdtable = {
1674 > b'deprecatedcmd': (deprecatedcmd, [], b''),
1676 > b'deprecatedcmd': (deprecatedcmd, [], b''),
1675 > }
1677 > }
1676 > EOF
1678 > EOF
1677 $ cat <<EOF > .hg/hgrc
1679 $ cat <<EOF > .hg/hgrc
1678 > [extensions]
1680 > [extensions]
1679 > deprecatedcmd = `pwd`/deprecatedcmd.py
1681 > deprecatedcmd = `pwd`/deprecatedcmd.py
1680 > mq = !
1682 > mq = !
1681 > hgext.mq = !
1683 > hgext.mq = !
1682 > hgext/mq = !
1684 > hgext/mq = !
1683 > EOF
1685 > EOF
1684
1686
1685 $ hg deprecatedcmd > /dev/null
1687 $ hg deprecatedcmd > /dev/null
1686 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1688 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1687 *** (use @command decorator to register 'deprecatedcmd')
1689 *** (use @command decorator to register 'deprecatedcmd')
1688 hg: unknown command 'deprecatedcmd'
1690 hg: unknown command 'deprecatedcmd'
1689 (use 'hg help' for a list of commands)
1691 (use 'hg help' for a list of commands)
1690 [255]
1692 [255]
1691
1693
1692 the extension shouldn't be loaded at all so the mq works:
1694 the extension shouldn't be loaded at all so the mq works:
1693
1695
1694 $ hg qseries --config extensions.mq= > /dev/null
1696 $ hg qseries --config extensions.mq= > /dev/null
1695 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1697 *** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo
1696 *** (use @command decorator to register 'deprecatedcmd')
1698 *** (use @command decorator to register 'deprecatedcmd')
1697
1699
1698 $ cd ..
1700 $ cd ..
1699
1701
1700 Test synopsis and docstring extending
1702 Test synopsis and docstring extending
1701
1703
1702 $ hg init exthelp
1704 $ hg init exthelp
1703 $ cat > exthelp.py <<EOF
1705 $ cat > exthelp.py <<EOF
1704 > from mercurial import commands, extensions
1706 > from mercurial import commands, extensions
1705 > def exbookmarks(orig, *args, **opts):
1707 > def exbookmarks(orig, *args, **opts):
1706 > return orig(*args, **opts)
1708 > return orig(*args, **opts)
1707 > def uisetup(ui):
1709 > def uisetup(ui):
1708 > synopsis = b' GREPME [--foo] [-x]'
1710 > synopsis = b' GREPME [--foo] [-x]'
1709 > docstring = '''
1711 > docstring = '''
1710 > GREPME make sure that this is in the help!
1712 > GREPME make sure that this is in the help!
1711 > '''
1713 > '''
1712 > extensions.wrapcommand(commands.table, b'bookmarks', exbookmarks,
1714 > extensions.wrapcommand(commands.table, b'bookmarks', exbookmarks,
1713 > synopsis, docstring)
1715 > synopsis, docstring)
1714 > EOF
1716 > EOF
1715 $ abspath=`pwd`/exthelp.py
1717 $ abspath=`pwd`/exthelp.py
1716 $ echo '[extensions]' >> $HGRCPATH
1718 $ echo '[extensions]' >> $HGRCPATH
1717 $ echo "exthelp = $abspath" >> $HGRCPATH
1719 $ echo "exthelp = $abspath" >> $HGRCPATH
1718 $ cd exthelp
1720 $ cd exthelp
1719 $ hg help bookmarks | grep GREPME
1721 $ hg help bookmarks | grep GREPME
1720 hg bookmarks [OPTIONS]... [NAME]... GREPME [--foo] [-x]
1722 hg bookmarks [OPTIONS]... [NAME]... GREPME [--foo] [-x]
1721 GREPME make sure that this is in the help!
1723 GREPME make sure that this is in the help!
1722 $ cd ..
1724 $ cd ..
1723
1725
1724 Show deprecation warning for the use of cmdutil.command
1726 Show deprecation warning for the use of cmdutil.command
1725
1727
1726 $ cat > nonregistrar.py <<EOF
1728 $ cat > nonregistrar.py <<EOF
1727 > from mercurial import cmdutil
1729 > from mercurial import cmdutil
1728 > cmdtable = {}
1730 > cmdtable = {}
1729 > command = cmdutil.command(cmdtable)
1731 > command = cmdutil.command(cmdtable)
1730 > @command(b'foo', [], norepo=True)
1732 > @command(b'foo', [], norepo=True)
1731 > def foo(ui):
1733 > def foo(ui):
1732 > pass
1734 > pass
1733 > EOF
1735 > EOF
1734
1736
1735 Prohibit the use of unicode strings as the default value of options
1737 Prohibit the use of unicode strings as the default value of options
1736
1738
1737 $ hg init $TESTTMP/opt-unicode-default
1739 $ hg init $TESTTMP/opt-unicode-default
1738
1740
1739 $ cat > $TESTTMP/test_unicode_default_value.py << EOF
1741 $ cat > $TESTTMP/test_unicode_default_value.py << EOF
1740 > from mercurial import registrar
1742 > from mercurial import registrar
1741 > cmdtable = {}
1743 > cmdtable = {}
1742 > command = registrar.command(cmdtable)
1744 > command = registrar.command(cmdtable)
1743 > @command(b'dummy', [(b'', b'opt', u'value', u'help')], 'ext [OPTIONS]')
1745 > @command(b'dummy', [(b'', b'opt', u'value', u'help')], 'ext [OPTIONS]')
1744 > def ext(*args, **opts):
1746 > def ext(*args, **opts):
1745 > print(opts[b'opt'])
1747 > print(opts[b'opt'])
1746 > EOF
1748 > EOF
1747 $ cat > $TESTTMP/opt-unicode-default/.hg/hgrc << EOF
1749 $ cat > $TESTTMP/opt-unicode-default/.hg/hgrc << EOF
1748 > [extensions]
1750 > [extensions]
1749 > test_unicode_default_value = $TESTTMP/test_unicode_default_value.py
1751 > test_unicode_default_value = $TESTTMP/test_unicode_default_value.py
1750 > EOF
1752 > EOF
1751 $ hg -R $TESTTMP/opt-unicode-default dummy
1753 $ hg -R $TESTTMP/opt-unicode-default dummy
1752 *** failed to import extension test_unicode_default_value from $TESTTMP/test_unicode_default_value.py: unicode u'value' found in cmdtable.dummy
1754 *** failed to import extension test_unicode_default_value from $TESTTMP/test_unicode_default_value.py: unicode u'value' found in cmdtable.dummy
1753 *** (use b'' to make it byte string)
1755 *** (use b'' to make it byte string)
1754 hg: unknown command 'dummy'
1756 hg: unknown command 'dummy'
1755 (did you mean summary?)
1757 (did you mean summary?)
1756 [255]
1758 [255]
@@ -1,3719 +1,3720 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 Extra extensions will be printed in help output in a non-reliable order since
47 Extra extensions will be printed in help output in a non-reliable order since
48 the extension is unknown.
48 the extension is unknown.
49 #if no-extraextensions
49 #if no-extraextensions
50
50
51 $ hg help
51 $ hg help
52 Mercurial Distributed SCM
52 Mercurial Distributed SCM
53
53
54 list of commands:
54 list of commands:
55
55
56 add add the specified files on the next commit
56 add add the specified files on the next commit
57 addremove add all new files, delete all missing files
57 addremove add all new files, delete all missing files
58 annotate show changeset information by line for each file
58 annotate show changeset information by line for each file
59 archive create an unversioned archive of a repository revision
59 archive create an unversioned archive of a repository revision
60 backout reverse effect of earlier changeset
60 backout reverse effect of earlier changeset
61 bisect subdivision search of changesets
61 bisect subdivision search of changesets
62 bookmarks create a new bookmark or list existing bookmarks
62 bookmarks create a new bookmark or list existing bookmarks
63 branch set or show the current branch name
63 branch set or show the current branch name
64 branches list repository named branches
64 branches list repository named branches
65 bundle create a bundle file
65 bundle create a bundle file
66 cat output the current or given revision of files
66 cat output the current or given revision of files
67 clone make a copy of an existing repository
67 clone make a copy of an existing repository
68 commit commit the specified files or all outstanding changes
68 commit commit the specified files or all outstanding changes
69 config show combined config settings from all hgrc files
69 config show combined config settings from all hgrc files
70 copy mark files as copied for the next commit
70 copy mark files as copied for the next commit
71 diff diff repository (or selected files)
71 diff diff repository (or selected files)
72 export dump the header and diffs for one or more changesets
72 export dump the header and diffs for one or more changesets
73 files list tracked files
73 files list tracked files
74 forget forget the specified files on the next commit
74 forget forget the specified files on the next commit
75 graft copy changes from other branches onto the current branch
75 graft copy changes from other branches onto the current branch
76 grep search revision history for a pattern in specified files
76 grep search revision history for a pattern in specified files
77 heads show branch heads
77 heads show branch heads
78 help show help for a given topic or a help overview
78 help show help for a given topic or a help overview
79 identify identify the working directory or specified revision
79 identify identify the working directory or specified revision
80 import import an ordered set of patches
80 import import an ordered set of patches
81 incoming show new changesets found in source
81 incoming show new changesets found in source
82 init create a new repository in the given directory
82 init create a new repository in the given directory
83 log show revision history of entire repository or files
83 log show revision history of entire repository or files
84 manifest output the current or given revision of the project manifest
84 manifest output the current or given revision of the project manifest
85 merge merge another revision into working directory
85 merge merge another revision into working directory
86 outgoing show changesets not found in the destination
86 outgoing show changesets not found in the destination
87 paths show aliases for remote repositories
87 paths show aliases for remote repositories
88 phase set or show the current phase name
88 phase set or show the current phase name
89 pull pull changes from the specified source
89 pull pull changes from the specified source
90 push push changes to the specified destination
90 push push changes to the specified destination
91 recover roll back an interrupted transaction
91 recover roll back an interrupted transaction
92 remove remove the specified files on the next commit
92 remove remove the specified files on the next commit
93 rename rename files; equivalent of copy + remove
93 rename rename files; equivalent of copy + remove
94 resolve redo merges or set/view the merge status of files
94 resolve redo merges or set/view the merge status of files
95 revert restore files to their checkout state
95 revert restore files to their checkout state
96 root print the root (top) of the current working directory
96 root print the root (top) of the current working directory
97 serve start stand-alone webserver
97 serve start stand-alone webserver
98 status show changed files in the working directory
98 status show changed files in the working directory
99 summary summarize working directory state
99 summary summarize working directory state
100 tag add one or more tags for the current or given revision
100 tag add one or more tags for the current or given revision
101 tags list repository tags
101 tags list repository tags
102 unbundle apply one or more bundle files
102 unbundle apply one or more bundle files
103 update update working directory (or switch revisions)
103 update update working directory (or switch revisions)
104 verify verify the integrity of the repository
104 verify verify the integrity of the repository
105 version output version and copyright information
105 version output version and copyright information
106
106
107 additional help topics:
107 additional help topics:
108
108
109 bundlespec Bundle File Formats
109 bundlespec Bundle File Formats
110 color Colorizing Outputs
110 color Colorizing Outputs
111 config Configuration Files
111 config Configuration Files
112 dates Date Formats
112 dates Date Formats
113 deprecated Deprecated Features
113 deprecated Deprecated Features
114 diffs Diff Formats
114 diffs Diff Formats
115 environment Environment Variables
115 environment Environment Variables
116 extensions Using Additional Features
116 extensions Using Additional Features
117 filesets Specifying File Sets
117 filesets Specifying File Sets
118 flags Command-line flags
118 flags Command-line flags
119 glossary Glossary
119 glossary Glossary
120 hgignore Syntax for Mercurial Ignore Files
120 hgignore Syntax for Mercurial Ignore Files
121 hgweb Configuring hgweb
121 hgweb Configuring hgweb
122 internals Technical implementation topics
122 internals Technical implementation topics
123 merge-tools Merge Tools
123 merge-tools Merge Tools
124 pager Pager Support
124 pager Pager Support
125 patterns File Name Patterns
125 patterns File Name Patterns
126 phases Working with Phases
126 phases Working with Phases
127 revisions Specifying Revisions
127 revisions Specifying Revisions
128 scripting Using Mercurial from scripts and automation
128 scripting Using Mercurial from scripts and automation
129 subrepos Subrepositories
129 subrepos Subrepositories
130 templating Template Usage
130 templating Template Usage
131 urls URL Paths
131 urls URL Paths
132
132
133 (use 'hg help -v' to show built-in aliases and global options)
133 (use 'hg help -v' to show built-in aliases and global options)
134
134
135 $ hg -q help
135 $ hg -q help
136 add add the specified files on the next commit
136 add add the specified files on the next commit
137 addremove add all new files, delete all missing files
137 addremove add all new files, delete all missing files
138 annotate show changeset information by line for each file
138 annotate show changeset information by line for each file
139 archive create an unversioned archive of a repository revision
139 archive create an unversioned archive of a repository revision
140 backout reverse effect of earlier changeset
140 backout reverse effect of earlier changeset
141 bisect subdivision search of changesets
141 bisect subdivision search of changesets
142 bookmarks create a new bookmark or list existing bookmarks
142 bookmarks create a new bookmark or list existing bookmarks
143 branch set or show the current branch name
143 branch set or show the current branch name
144 branches list repository named branches
144 branches list repository named branches
145 bundle create a bundle file
145 bundle create a bundle file
146 cat output the current or given revision of files
146 cat output the current or given revision of files
147 clone make a copy of an existing repository
147 clone make a copy of an existing repository
148 commit commit the specified files or all outstanding changes
148 commit commit the specified files or all outstanding changes
149 config show combined config settings from all hgrc files
149 config show combined config settings from all hgrc files
150 copy mark files as copied for the next commit
150 copy mark files as copied for the next commit
151 diff diff repository (or selected files)
151 diff diff repository (or selected files)
152 export dump the header and diffs for one or more changesets
152 export dump the header and diffs for one or more changesets
153 files list tracked files
153 files list tracked files
154 forget forget the specified files on the next commit
154 forget forget the specified files on the next commit
155 graft copy changes from other branches onto the current branch
155 graft copy changes from other branches onto the current branch
156 grep search revision history for a pattern in specified files
156 grep search revision history for a pattern in specified files
157 heads show branch heads
157 heads show branch heads
158 help show help for a given topic or a help overview
158 help show help for a given topic or a help overview
159 identify identify the working directory or specified revision
159 identify identify the working directory or specified revision
160 import import an ordered set of patches
160 import import an ordered set of patches
161 incoming show new changesets found in source
161 incoming show new changesets found in source
162 init create a new repository in the given directory
162 init create a new repository in the given directory
163 log show revision history of entire repository or files
163 log show revision history of entire repository or files
164 manifest output the current or given revision of the project manifest
164 manifest output the current or given revision of the project manifest
165 merge merge another revision into working directory
165 merge merge another revision into working directory
166 outgoing show changesets not found in the destination
166 outgoing show changesets not found in the destination
167 paths show aliases for remote repositories
167 paths show aliases for remote repositories
168 phase set or show the current phase name
168 phase set or show the current phase name
169 pull pull changes from the specified source
169 pull pull changes from the specified source
170 push push changes to the specified destination
170 push push changes to the specified destination
171 recover roll back an interrupted transaction
171 recover roll back an interrupted transaction
172 remove remove the specified files on the next commit
172 remove remove the specified files on the next commit
173 rename rename files; equivalent of copy + remove
173 rename rename files; equivalent of copy + remove
174 resolve redo merges or set/view the merge status of files
174 resolve redo merges or set/view the merge status of files
175 revert restore files to their checkout state
175 revert restore files to their checkout state
176 root print the root (top) of the current working directory
176 root print the root (top) of the current working directory
177 serve start stand-alone webserver
177 serve start stand-alone webserver
178 status show changed files in the working directory
178 status show changed files in the working directory
179 summary summarize working directory state
179 summary summarize working directory state
180 tag add one or more tags for the current or given revision
180 tag add one or more tags for the current or given revision
181 tags list repository tags
181 tags list repository tags
182 unbundle apply one or more bundle files
182 unbundle apply one or more bundle files
183 update update working directory (or switch revisions)
183 update update working directory (or switch revisions)
184 verify verify the integrity of the repository
184 verify verify the integrity of the repository
185 version output version and copyright information
185 version output version and copyright information
186
186
187 additional help topics:
187 additional help topics:
188
188
189 bundlespec Bundle File Formats
189 bundlespec Bundle File Formats
190 color Colorizing Outputs
190 color Colorizing Outputs
191 config Configuration Files
191 config Configuration Files
192 dates Date Formats
192 dates Date Formats
193 deprecated Deprecated Features
193 deprecated Deprecated Features
194 diffs Diff Formats
194 diffs Diff Formats
195 environment Environment Variables
195 environment Environment Variables
196 extensions Using Additional Features
196 extensions Using Additional Features
197 filesets Specifying File Sets
197 filesets Specifying File Sets
198 flags Command-line flags
198 flags Command-line flags
199 glossary Glossary
199 glossary Glossary
200 hgignore Syntax for Mercurial Ignore Files
200 hgignore Syntax for Mercurial Ignore Files
201 hgweb Configuring hgweb
201 hgweb Configuring hgweb
202 internals Technical implementation topics
202 internals Technical implementation topics
203 merge-tools Merge Tools
203 merge-tools Merge Tools
204 pager Pager Support
204 pager Pager Support
205 patterns File Name Patterns
205 patterns File Name Patterns
206 phases Working with Phases
206 phases Working with Phases
207 revisions Specifying Revisions
207 revisions Specifying Revisions
208 scripting Using Mercurial from scripts and automation
208 scripting Using Mercurial from scripts and automation
209 subrepos Subrepositories
209 subrepos Subrepositories
210 templating Template Usage
210 templating Template Usage
211 urls URL Paths
211 urls URL Paths
212
212
213 Test extension help:
213 Test extension help:
214 $ hg help extensions --config extensions.rebase= --config extensions.children=
214 $ hg help extensions --config extensions.rebase= --config extensions.children=
215 Using Additional Features
215 Using Additional Features
216 """""""""""""""""""""""""
216 """""""""""""""""""""""""
217
217
218 Mercurial has the ability to add new features through the use of
218 Mercurial has the ability to add new features through the use of
219 extensions. Extensions may add new commands, add options to existing
219 extensions. Extensions may add new commands, add options to existing
220 commands, change the default behavior of commands, or implement hooks.
220 commands, change the default behavior of commands, or implement hooks.
221
221
222 To enable the "foo" extension, either shipped with Mercurial or in the
222 To enable the "foo" extension, either shipped with Mercurial or in the
223 Python search path, create an entry for it in your configuration file,
223 Python search path, create an entry for it in your configuration file,
224 like this:
224 like this:
225
225
226 [extensions]
226 [extensions]
227 foo =
227 foo =
228
228
229 You may also specify the full path to an extension:
229 You may also specify the full path to an extension:
230
230
231 [extensions]
231 [extensions]
232 myfeature = ~/.hgext/myfeature.py
232 myfeature = ~/.hgext/myfeature.py
233
233
234 See 'hg help config' for more information on configuration files.
234 See 'hg help config' for more information on configuration files.
235
235
236 Extensions are not loaded by default for a variety of reasons: they can
236 Extensions are not loaded by default for a variety of reasons: they can
237 increase startup overhead; they may be meant for advanced usage only; they
237 increase startup overhead; they may be meant for advanced usage only; they
238 may provide potentially dangerous abilities (such as letting you destroy
238 may provide potentially dangerous abilities (such as letting you destroy
239 or modify history); they might not be ready for prime time; or they may
239 or modify history); they might not be ready for prime time; or they may
240 alter some usual behaviors of stock Mercurial. It is thus up to the user
240 alter some usual behaviors of stock Mercurial. It is thus up to the user
241 to activate extensions as needed.
241 to activate extensions as needed.
242
242
243 To explicitly disable an extension enabled in a configuration file of
243 To explicitly disable an extension enabled in a configuration file of
244 broader scope, prepend its path with !:
244 broader scope, prepend its path with !:
245
245
246 [extensions]
246 [extensions]
247 # disabling extension bar residing in /path/to/extension/bar.py
247 # disabling extension bar residing in /path/to/extension/bar.py
248 bar = !/path/to/extension/bar.py
248 bar = !/path/to/extension/bar.py
249 # ditto, but no path was supplied for extension baz
249 # ditto, but no path was supplied for extension baz
250 baz = !
250 baz = !
251
251
252 enabled extensions:
252 enabled extensions:
253
253
254 children command to display child changesets (DEPRECATED)
254 children command to display child changesets (DEPRECATED)
255 rebase command to move sets of revisions to a different ancestor
255 rebase command to move sets of revisions to a different ancestor
256
256
257 disabled extensions:
257 disabled extensions:
258
258
259 acl hooks for controlling repository access
259 acl hooks for controlling repository access
260 blackbox log repository events to a blackbox for debugging
260 blackbox log repository events to a blackbox for debugging
261 bugzilla hooks for integrating with the Bugzilla bug tracker
261 bugzilla hooks for integrating with the Bugzilla bug tracker
262 censor erase file content at a given revision
262 censor erase file content at a given revision
263 churn command to display statistics about repository history
263 churn command to display statistics about repository history
264 clonebundles advertise pre-generated bundles to seed clones
264 clonebundles advertise pre-generated bundles to seed clones
265 convert import revisions from foreign VCS repositories into
265 convert import revisions from foreign VCS repositories into
266 Mercurial
266 Mercurial
267 eol automatically manage newlines in repository files
267 eol automatically manage newlines in repository files
268 extdiff command to allow external programs to compare revisions
268 extdiff command to allow external programs to compare revisions
269 factotum http authentication with factotum
269 factotum http authentication with factotum
270 githelp try mapping git commands to Mercurial commands
270 githelp try mapping git commands to Mercurial commands
271 gpg commands to sign and verify changesets
271 gpg commands to sign and verify changesets
272 hgk browse the repository in a graphical way
272 hgk browse the repository in a graphical way
273 highlight syntax highlighting for hgweb (requires Pygments)
273 highlight syntax highlighting for hgweb (requires Pygments)
274 histedit interactive history editing
274 histedit interactive history editing
275 keyword expand keywords in tracked files
275 keyword expand keywords in tracked files
276 largefiles track large binary files
276 largefiles track large binary files
277 mq manage a stack of patches
277 mq manage a stack of patches
278 notify hooks for sending email push notifications
278 notify hooks for sending email push notifications
279 patchbomb command to send changesets as (a series of) patch emails
279 patchbomb command to send changesets as (a series of) patch emails
280 purge command to delete untracked files from the working
280 purge command to delete untracked files from the working
281 directory
281 directory
282 relink recreates hardlinks between repository clones
282 relink recreates hardlinks between repository clones
283 schemes extend schemes with shortcuts to repository swarms
283 schemes extend schemes with shortcuts to repository swarms
284 share share a common history between several working directories
284 share share a common history between several working directories
285 shelve save and restore changes to the working directory
285 shelve save and restore changes to the working directory
286 strip strip changesets and their descendants from history
286 strip strip changesets and their descendants from history
287 transplant command to transplant changesets from another branch
287 transplant command to transplant changesets from another branch
288 win32mbcs allow the use of MBCS paths with problematic encodings
288 win32mbcs allow the use of MBCS paths with problematic encodings
289 zeroconf discover and advertise repositories on the local network
289 zeroconf discover and advertise repositories on the local network
290
290
291 #endif
291 #endif
292
292
293 Verify that deprecated extensions are included if --verbose:
293 Verify that deprecated extensions are included if --verbose:
294
294
295 $ hg -v help extensions | grep children
295 $ hg -v help extensions | grep children
296 children command to display child changesets (DEPRECATED)
296 children command to display child changesets (DEPRECATED)
297
297
298 Verify that extension keywords appear in help templates
298 Verify that extension keywords appear in help templates
299
299
300 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
300 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
301
301
302 Test short command list with verbose option
302 Test short command list with verbose option
303
303
304 $ hg -v help shortlist
304 $ hg -v help shortlist
305 Mercurial Distributed SCM
305 Mercurial Distributed SCM
306
306
307 basic commands:
307 basic commands:
308
308
309 add add the specified files on the next commit
309 add add the specified files on the next commit
310 annotate, blame
310 annotate, blame
311 show changeset information by line for each file
311 show changeset information by line for each file
312 clone make a copy of an existing repository
312 clone make a copy of an existing repository
313 commit, ci commit the specified files or all outstanding changes
313 commit, ci commit the specified files or all outstanding changes
314 diff diff repository (or selected files)
314 diff diff repository (or selected files)
315 export dump the header and diffs for one or more changesets
315 export dump the header and diffs for one or more changesets
316 forget forget the specified files on the next commit
316 forget forget the specified files on the next commit
317 init create a new repository in the given directory
317 init create a new repository in the given directory
318 log, history show revision history of entire repository or files
318 log, history show revision history of entire repository or files
319 merge merge another revision into working directory
319 merge merge another revision into working directory
320 pull pull changes from the specified source
320 pull pull changes from the specified source
321 push push changes to the specified destination
321 push push changes to the specified destination
322 remove, rm remove the specified files on the next commit
322 remove, rm remove the specified files on the next commit
323 serve start stand-alone webserver
323 serve start stand-alone webserver
324 status, st show changed files in the working directory
324 status, st show changed files in the working directory
325 summary, sum summarize working directory state
325 summary, sum summarize working directory state
326 update, up, checkout, co
326 update, up, checkout, co
327 update working directory (or switch revisions)
327 update working directory (or switch revisions)
328
328
329 global options ([+] can be repeated):
329 global options ([+] can be repeated):
330
330
331 -R --repository REPO repository root directory or name of overlay bundle
331 -R --repository REPO repository root directory or name of overlay bundle
332 file
332 file
333 --cwd DIR change working directory
333 --cwd DIR change working directory
334 -y --noninteractive do not prompt, automatically pick the first choice for
334 -y --noninteractive do not prompt, automatically pick the first choice for
335 all prompts
335 all prompts
336 -q --quiet suppress output
336 -q --quiet suppress output
337 -v --verbose enable additional output
337 -v --verbose enable additional output
338 --color TYPE when to colorize (boolean, always, auto, never, or
338 --color TYPE when to colorize (boolean, always, auto, never, or
339 debug)
339 debug)
340 --config CONFIG [+] set/override config option (use 'section.name=value')
340 --config CONFIG [+] set/override config option (use 'section.name=value')
341 --debug enable debugging output
341 --debug enable debugging output
342 --debugger start debugger
342 --debugger start debugger
343 --encoding ENCODE set the charset encoding (default: ascii)
343 --encoding ENCODE set the charset encoding (default: ascii)
344 --encodingmode MODE set the charset encoding mode (default: strict)
344 --encodingmode MODE set the charset encoding mode (default: strict)
345 --traceback always print a traceback on exception
345 --traceback always print a traceback on exception
346 --time time how long the command takes
346 --time time how long the command takes
347 --profile print command execution profile
347 --profile print command execution profile
348 --version output version information and exit
348 --version output version information and exit
349 -h --help display help and exit
349 -h --help display help and exit
350 --hidden consider hidden changesets
350 --hidden consider hidden changesets
351 --pager TYPE when to paginate (boolean, always, auto, or never)
351 --pager TYPE when to paginate (boolean, always, auto, or never)
352 (default: auto)
352 (default: auto)
353
353
354 (use 'hg help' for the full list of commands)
354 (use 'hg help' for the full list of commands)
355
355
356 $ hg add -h
356 $ hg add -h
357 hg add [OPTION]... [FILE]...
357 hg add [OPTION]... [FILE]...
358
358
359 add the specified files on the next commit
359 add the specified files on the next commit
360
360
361 Schedule files to be version controlled and added to the repository.
361 Schedule files to be version controlled and added to the repository.
362
362
363 The files will be added to the repository at the next commit. To undo an
363 The files will be added to the repository at the next commit. To undo an
364 add before that, see 'hg forget'.
364 add before that, see 'hg forget'.
365
365
366 If no names are given, add all files to the repository (except files
366 If no names are given, add all files to the repository (except files
367 matching ".hgignore").
367 matching ".hgignore").
368
368
369 Returns 0 if all files are successfully added.
369 Returns 0 if all files are successfully added.
370
370
371 options ([+] can be repeated):
371 options ([+] can be repeated):
372
372
373 -I --include PATTERN [+] include names matching the given patterns
373 -I --include PATTERN [+] include names matching the given patterns
374 -X --exclude PATTERN [+] exclude names matching the given patterns
374 -X --exclude PATTERN [+] exclude names matching the given patterns
375 -S --subrepos recurse into subrepositories
375 -S --subrepos recurse into subrepositories
376 -n --dry-run do not perform actions, just print output
376 -n --dry-run do not perform actions, just print output
377
377
378 (some details hidden, use --verbose to show complete help)
378 (some details hidden, use --verbose to show complete help)
379
379
380 Verbose help for add
380 Verbose help for add
381
381
382 $ hg add -hv
382 $ hg add -hv
383 hg add [OPTION]... [FILE]...
383 hg add [OPTION]... [FILE]...
384
384
385 add the specified files on the next commit
385 add the specified files on the next commit
386
386
387 Schedule files to be version controlled and added to the repository.
387 Schedule files to be version controlled and added to the repository.
388
388
389 The files will be added to the repository at the next commit. To undo an
389 The files will be added to the repository at the next commit. To undo an
390 add before that, see 'hg forget'.
390 add before that, see 'hg forget'.
391
391
392 If no names are given, add all files to the repository (except files
392 If no names are given, add all files to the repository (except files
393 matching ".hgignore").
393 matching ".hgignore").
394
394
395 Examples:
395 Examples:
396
396
397 - New (unknown) files are added automatically by 'hg add':
397 - New (unknown) files are added automatically by 'hg add':
398
398
399 $ ls
399 $ ls
400 foo.c
400 foo.c
401 $ hg status
401 $ hg status
402 ? foo.c
402 ? foo.c
403 $ hg add
403 $ hg add
404 adding foo.c
404 adding foo.c
405 $ hg status
405 $ hg status
406 A foo.c
406 A foo.c
407
407
408 - Specific files to be added can be specified:
408 - Specific files to be added can be specified:
409
409
410 $ ls
410 $ ls
411 bar.c foo.c
411 bar.c foo.c
412 $ hg status
412 $ hg status
413 ? bar.c
413 ? bar.c
414 ? foo.c
414 ? foo.c
415 $ hg add bar.c
415 $ hg add bar.c
416 $ hg status
416 $ hg status
417 A bar.c
417 A bar.c
418 ? foo.c
418 ? foo.c
419
419
420 Returns 0 if all files are successfully added.
420 Returns 0 if all files are successfully added.
421
421
422 options ([+] can be repeated):
422 options ([+] can be repeated):
423
423
424 -I --include PATTERN [+] include names matching the given patterns
424 -I --include PATTERN [+] include names matching the given patterns
425 -X --exclude PATTERN [+] exclude names matching the given patterns
425 -X --exclude PATTERN [+] exclude names matching the given patterns
426 -S --subrepos recurse into subrepositories
426 -S --subrepos recurse into subrepositories
427 -n --dry-run do not perform actions, just print output
427 -n --dry-run do not perform actions, just print output
428
428
429 global options ([+] can be repeated):
429 global options ([+] can be repeated):
430
430
431 -R --repository REPO repository root directory or name of overlay bundle
431 -R --repository REPO repository root directory or name of overlay bundle
432 file
432 file
433 --cwd DIR change working directory
433 --cwd DIR change working directory
434 -y --noninteractive do not prompt, automatically pick the first choice for
434 -y --noninteractive do not prompt, automatically pick the first choice for
435 all prompts
435 all prompts
436 -q --quiet suppress output
436 -q --quiet suppress output
437 -v --verbose enable additional output
437 -v --verbose enable additional output
438 --color TYPE when to colorize (boolean, always, auto, never, or
438 --color TYPE when to colorize (boolean, always, auto, never, or
439 debug)
439 debug)
440 --config CONFIG [+] set/override config option (use 'section.name=value')
440 --config CONFIG [+] set/override config option (use 'section.name=value')
441 --debug enable debugging output
441 --debug enable debugging output
442 --debugger start debugger
442 --debugger start debugger
443 --encoding ENCODE set the charset encoding (default: ascii)
443 --encoding ENCODE set the charset encoding (default: ascii)
444 --encodingmode MODE set the charset encoding mode (default: strict)
444 --encodingmode MODE set the charset encoding mode (default: strict)
445 --traceback always print a traceback on exception
445 --traceback always print a traceback on exception
446 --time time how long the command takes
446 --time time how long the command takes
447 --profile print command execution profile
447 --profile print command execution profile
448 --version output version information and exit
448 --version output version information and exit
449 -h --help display help and exit
449 -h --help display help and exit
450 --hidden consider hidden changesets
450 --hidden consider hidden changesets
451 --pager TYPE when to paginate (boolean, always, auto, or never)
451 --pager TYPE when to paginate (boolean, always, auto, or never)
452 (default: auto)
452 (default: auto)
453
453
454 Test the textwidth config option
454 Test the textwidth config option
455
455
456 $ hg root -h --config ui.textwidth=50
456 $ hg root -h --config ui.textwidth=50
457 hg root
457 hg root
458
458
459 print the root (top) of the current working
459 print the root (top) of the current working
460 directory
460 directory
461
461
462 Print the root directory of the current
462 Print the root directory of the current
463 repository.
463 repository.
464
464
465 Returns 0 on success.
465 Returns 0 on success.
466
466
467 (some details hidden, use --verbose to show
467 (some details hidden, use --verbose to show
468 complete help)
468 complete help)
469
469
470 Test help option with version option
470 Test help option with version option
471
471
472 $ hg add -h --version
472 $ hg add -h --version
473 Mercurial Distributed SCM (version *) (glob)
473 Mercurial Distributed SCM (version *) (glob)
474 (see https://mercurial-scm.org for more information)
474 (see https://mercurial-scm.org for more information)
475
475
476 Copyright (C) 2005-* Matt Mackall and others (glob)
476 Copyright (C) 2005-* Matt Mackall and others (glob)
477 This is free software; see the source for copying conditions. There is NO
477 This is free software; see the source for copying conditions. There is NO
478 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
478 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
479
479
480 $ hg add --skjdfks
480 $ hg add --skjdfks
481 hg add: option --skjdfks not recognized
481 hg add: option --skjdfks not recognized
482 hg add [OPTION]... [FILE]...
482 hg add [OPTION]... [FILE]...
483
483
484 add the specified files on the next commit
484 add the specified files on the next commit
485
485
486 options ([+] can be repeated):
486 options ([+] can be repeated):
487
487
488 -I --include PATTERN [+] include names matching the given patterns
488 -I --include PATTERN [+] include names matching the given patterns
489 -X --exclude PATTERN [+] exclude names matching the given patterns
489 -X --exclude PATTERN [+] exclude names matching the given patterns
490 -S --subrepos recurse into subrepositories
490 -S --subrepos recurse into subrepositories
491 -n --dry-run do not perform actions, just print output
491 -n --dry-run do not perform actions, just print output
492
492
493 (use 'hg add -h' to show more help)
493 (use 'hg add -h' to show more help)
494 [255]
494 [255]
495
495
496 Test ambiguous command help
496 Test ambiguous command help
497
497
498 $ hg help ad
498 $ hg help ad
499 list of commands:
499 list of commands:
500
500
501 add add the specified files on the next commit
501 add add the specified files on the next commit
502 addremove add all new files, delete all missing files
502 addremove add all new files, delete all missing files
503
503
504 (use 'hg help -v ad' to show built-in aliases and global options)
504 (use 'hg help -v ad' to show built-in aliases and global options)
505
505
506 Test command without options
506 Test command without options
507
507
508 $ hg help verify
508 $ hg help verify
509 hg verify
509 hg verify
510
510
511 verify the integrity of the repository
511 verify the integrity of the repository
512
512
513 Verify the integrity of the current repository.
513 Verify the integrity of the current repository.
514
514
515 This will perform an extensive check of the repository's integrity,
515 This will perform an extensive check of the repository's integrity,
516 validating the hashes and checksums of each entry in the changelog,
516 validating the hashes and checksums of each entry in the changelog,
517 manifest, and tracked files, as well as the integrity of their crosslinks
517 manifest, and tracked files, as well as the integrity of their crosslinks
518 and indices.
518 and indices.
519
519
520 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
520 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
521 information about recovery from corruption of the repository.
521 information about recovery from corruption of the repository.
522
522
523 Returns 0 on success, 1 if errors are encountered.
523 Returns 0 on success, 1 if errors are encountered.
524
524
525 (some details hidden, use --verbose to show complete help)
525 (some details hidden, use --verbose to show complete help)
526
526
527 $ hg help diff
527 $ hg help diff
528 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
528 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
529
529
530 diff repository (or selected files)
530 diff repository (or selected files)
531
531
532 Show differences between revisions for the specified files.
532 Show differences between revisions for the specified files.
533
533
534 Differences between files are shown using the unified diff format.
534 Differences between files are shown using the unified diff format.
535
535
536 Note:
536 Note:
537 'hg diff' may generate unexpected results for merges, as it will
537 'hg diff' may generate unexpected results for merges, as it will
538 default to comparing against the working directory's first parent
538 default to comparing against the working directory's first parent
539 changeset if no revisions are specified.
539 changeset if no revisions are specified.
540
540
541 When two revision arguments are given, then changes are shown between
541 When two revision arguments are given, then changes are shown between
542 those revisions. If only one revision is specified then that revision is
542 those revisions. If only one revision is specified then that revision is
543 compared to the working directory, and, when no revisions are specified,
543 compared to the working directory, and, when no revisions are specified,
544 the working directory files are compared to its first parent.
544 the working directory files are compared to its first parent.
545
545
546 Alternatively you can specify -c/--change with a revision to see the
546 Alternatively you can specify -c/--change with a revision to see the
547 changes in that changeset relative to its first parent.
547 changes in that changeset relative to its first parent.
548
548
549 Without the -a/--text option, diff will avoid generating diffs of files it
549 Without the -a/--text option, diff will avoid generating diffs of files it
550 detects as binary. With -a, diff will generate a diff anyway, probably
550 detects as binary. With -a, diff will generate a diff anyway, probably
551 with undesirable results.
551 with undesirable results.
552
552
553 Use the -g/--git option to generate diffs in the git extended diff format.
553 Use the -g/--git option to generate diffs in the git extended diff format.
554 For more information, read 'hg help diffs'.
554 For more information, read 'hg help diffs'.
555
555
556 Returns 0 on success.
556 Returns 0 on success.
557
557
558 options ([+] can be repeated):
558 options ([+] can be repeated):
559
559
560 -r --rev REV [+] revision
560 -r --rev REV [+] revision
561 -c --change REV change made by revision
561 -c --change REV change made by revision
562 -a --text treat all files as text
562 -a --text treat all files as text
563 -g --git use git extended diff format
563 -g --git use git extended diff format
564 --binary generate binary diffs in git mode (default)
564 --binary generate binary diffs in git mode (default)
565 --nodates omit dates from diff headers
565 --nodates omit dates from diff headers
566 --noprefix omit a/ and b/ prefixes from filenames
566 --noprefix omit a/ and b/ prefixes from filenames
567 -p --show-function show which function each change is in
567 -p --show-function show which function each change is in
568 --reverse produce a diff that undoes the changes
568 --reverse produce a diff that undoes the changes
569 -w --ignore-all-space ignore white space when comparing lines
569 -w --ignore-all-space ignore white space when comparing lines
570 -b --ignore-space-change ignore changes in the amount of white space
570 -b --ignore-space-change ignore changes in the amount of white space
571 -B --ignore-blank-lines ignore changes whose lines are all blank
571 -B --ignore-blank-lines ignore changes whose lines are all blank
572 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
572 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
573 -U --unified NUM number of lines of context to show
573 -U --unified NUM number of lines of context to show
574 --stat output diffstat-style summary of changes
574 --stat output diffstat-style summary of changes
575 --root DIR produce diffs relative to subdirectory
575 --root DIR produce diffs relative to subdirectory
576 -I --include PATTERN [+] include names matching the given patterns
576 -I --include PATTERN [+] include names matching the given patterns
577 -X --exclude PATTERN [+] exclude names matching the given patterns
577 -X --exclude PATTERN [+] exclude names matching the given patterns
578 -S --subrepos recurse into subrepositories
578 -S --subrepos recurse into subrepositories
579
579
580 (some details hidden, use --verbose to show complete help)
580 (some details hidden, use --verbose to show complete help)
581
581
582 $ hg help status
582 $ hg help status
583 hg status [OPTION]... [FILE]...
583 hg status [OPTION]... [FILE]...
584
584
585 aliases: st
585 aliases: st
586
586
587 show changed files in the working directory
587 show changed files in the working directory
588
588
589 Show status of files in the repository. If names are given, only files
589 Show status of files in the repository. If names are given, only files
590 that match are shown. Files that are clean or ignored or the source of a
590 that match are shown. Files that are clean or ignored or the source of a
591 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
591 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
592 -C/--copies or -A/--all are given. Unless options described with "show
592 -C/--copies or -A/--all are given. Unless options described with "show
593 only ..." are given, the options -mardu are used.
593 only ..." are given, the options -mardu are used.
594
594
595 Option -q/--quiet hides untracked (unknown and ignored) files unless
595 Option -q/--quiet hides untracked (unknown and ignored) files unless
596 explicitly requested with -u/--unknown or -i/--ignored.
596 explicitly requested with -u/--unknown or -i/--ignored.
597
597
598 Note:
598 Note:
599 'hg status' may appear to disagree with diff if permissions have
599 'hg status' may appear to disagree with diff if permissions have
600 changed or a merge has occurred. The standard diff format does not
600 changed or a merge has occurred. The standard diff format does not
601 report permission changes and diff only reports changes relative to one
601 report permission changes and diff only reports changes relative to one
602 merge parent.
602 merge parent.
603
603
604 If one revision is given, it is used as the base revision. If two
604 If one revision is given, it is used as the base revision. If two
605 revisions are given, the differences between them are shown. The --change
605 revisions are given, the differences between them are shown. The --change
606 option can also be used as a shortcut to list the changed files of a
606 option can also be used as a shortcut to list the changed files of a
607 revision from its first parent.
607 revision from its first parent.
608
608
609 The codes used to show the status of files are:
609 The codes used to show the status of files are:
610
610
611 M = modified
611 M = modified
612 A = added
612 A = added
613 R = removed
613 R = removed
614 C = clean
614 C = clean
615 ! = missing (deleted by non-hg command, but still tracked)
615 ! = missing (deleted by non-hg command, but still tracked)
616 ? = not tracked
616 ? = not tracked
617 I = ignored
617 I = ignored
618 = origin of the previous file (with --copies)
618 = origin of the previous file (with --copies)
619
619
620 Returns 0 on success.
620 Returns 0 on success.
621
621
622 options ([+] can be repeated):
622 options ([+] can be repeated):
623
623
624 -A --all show status of all files
624 -A --all show status of all files
625 -m --modified show only modified files
625 -m --modified show only modified files
626 -a --added show only added files
626 -a --added show only added files
627 -r --removed show only removed files
627 -r --removed show only removed files
628 -d --deleted show only deleted (but tracked) files
628 -d --deleted show only deleted (but tracked) files
629 -c --clean show only files without changes
629 -c --clean show only files without changes
630 -u --unknown show only unknown (not tracked) files
630 -u --unknown show only unknown (not tracked) files
631 -i --ignored show only ignored files
631 -i --ignored show only ignored files
632 -n --no-status hide status prefix
632 -n --no-status hide status prefix
633 -C --copies show source of copied files
633 -C --copies show source of copied files
634 -0 --print0 end filenames with NUL, for use with xargs
634 -0 --print0 end filenames with NUL, for use with xargs
635 --rev REV [+] show difference from revision
635 --rev REV [+] show difference from revision
636 --change REV list the changed files of a revision
636 --change REV list the changed files of a revision
637 -I --include PATTERN [+] include names matching the given patterns
637 -I --include PATTERN [+] include names matching the given patterns
638 -X --exclude PATTERN [+] exclude names matching the given patterns
638 -X --exclude PATTERN [+] exclude names matching the given patterns
639 -S --subrepos recurse into subrepositories
639 -S --subrepos recurse into subrepositories
640 -T --template TEMPLATE display with template
640
641
641 (some details hidden, use --verbose to show complete help)
642 (some details hidden, use --verbose to show complete help)
642
643
643 $ hg -q help status
644 $ hg -q help status
644 hg status [OPTION]... [FILE]...
645 hg status [OPTION]... [FILE]...
645
646
646 show changed files in the working directory
647 show changed files in the working directory
647
648
648 $ hg help foo
649 $ hg help foo
649 abort: no such help topic: foo
650 abort: no such help topic: foo
650 (try 'hg help --keyword foo')
651 (try 'hg help --keyword foo')
651 [255]
652 [255]
652
653
653 $ hg skjdfks
654 $ hg skjdfks
654 hg: unknown command 'skjdfks'
655 hg: unknown command 'skjdfks'
655 (use 'hg help' for a list of commands)
656 (use 'hg help' for a list of commands)
656 [255]
657 [255]
657
658
658 Typoed command gives suggestion
659 Typoed command gives suggestion
659 $ hg puls
660 $ hg puls
660 hg: unknown command 'puls'
661 hg: unknown command 'puls'
661 (did you mean one of pull, push?)
662 (did you mean one of pull, push?)
662 [255]
663 [255]
663
664
664 Not enabled extension gets suggested
665 Not enabled extension gets suggested
665
666
666 $ hg rebase
667 $ hg rebase
667 hg: unknown command 'rebase'
668 hg: unknown command 'rebase'
668 'rebase' is provided by the following extension:
669 'rebase' is provided by the following extension:
669
670
670 rebase command to move sets of revisions to a different ancestor
671 rebase command to move sets of revisions to a different ancestor
671
672
672 (use 'hg help extensions' for information on enabling extensions)
673 (use 'hg help extensions' for information on enabling extensions)
673 [255]
674 [255]
674
675
675 Disabled extension gets suggested
676 Disabled extension gets suggested
676 $ hg --config extensions.rebase=! rebase
677 $ hg --config extensions.rebase=! rebase
677 hg: unknown command 'rebase'
678 hg: unknown command 'rebase'
678 'rebase' is provided by the following extension:
679 'rebase' is provided by the following extension:
679
680
680 rebase command to move sets of revisions to a different ancestor
681 rebase command to move sets of revisions to a different ancestor
681
682
682 (use 'hg help extensions' for information on enabling extensions)
683 (use 'hg help extensions' for information on enabling extensions)
683 [255]
684 [255]
684
685
685 Make sure that we don't run afoul of the help system thinking that
686 Make sure that we don't run afoul of the help system thinking that
686 this is a section and erroring out weirdly.
687 this is a section and erroring out weirdly.
687
688
688 $ hg .log
689 $ hg .log
689 hg: unknown command '.log'
690 hg: unknown command '.log'
690 (did you mean log?)
691 (did you mean log?)
691 [255]
692 [255]
692
693
693 $ hg log.
694 $ hg log.
694 hg: unknown command 'log.'
695 hg: unknown command 'log.'
695 (did you mean log?)
696 (did you mean log?)
696 [255]
697 [255]
697 $ hg pu.lh
698 $ hg pu.lh
698 hg: unknown command 'pu.lh'
699 hg: unknown command 'pu.lh'
699 (did you mean one of pull, push?)
700 (did you mean one of pull, push?)
700 [255]
701 [255]
701
702
702 $ cat > helpext.py <<EOF
703 $ cat > helpext.py <<EOF
703 > import os
704 > import os
704 > from mercurial import commands, fancyopts, registrar
705 > from mercurial import commands, fancyopts, registrar
705 >
706 >
706 > def func(arg):
707 > def func(arg):
707 > return '%sfoo' % arg
708 > return '%sfoo' % arg
708 > class customopt(fancyopts.customopt):
709 > class customopt(fancyopts.customopt):
709 > def newstate(self, oldstate, newparam, abort):
710 > def newstate(self, oldstate, newparam, abort):
710 > return '%sbar' % oldstate
711 > return '%sbar' % oldstate
711 > cmdtable = {}
712 > cmdtable = {}
712 > command = registrar.command(cmdtable)
713 > command = registrar.command(cmdtable)
713 >
714 >
714 > @command(b'nohelp',
715 > @command(b'nohelp',
715 > [(b'', b'longdesc', 3, b'x'*67),
716 > [(b'', b'longdesc', 3, b'x'*67),
716 > (b'n', b'', None, b'normal desc'),
717 > (b'n', b'', None, b'normal desc'),
717 > (b'', b'newline', b'', b'line1\nline2'),
718 > (b'', b'newline', b'', b'line1\nline2'),
718 > (b'', b'callableopt', func, b'adds foo'),
719 > (b'', b'callableopt', func, b'adds foo'),
719 > (b'', b'customopt', customopt(''), b'adds bar'),
720 > (b'', b'customopt', customopt(''), b'adds bar'),
720 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
721 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
721 > b'hg nohelp',
722 > b'hg nohelp',
722 > norepo=True)
723 > norepo=True)
723 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
724 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
724 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
725 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
725 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
726 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
726 > def nohelp(ui, *args, **kwargs):
727 > def nohelp(ui, *args, **kwargs):
727 > pass
728 > pass
728 >
729 >
729 > def uisetup(ui):
730 > def uisetup(ui):
730 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
731 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
731 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
732 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
732 >
733 >
733 > EOF
734 > EOF
734 $ echo '[extensions]' >> $HGRCPATH
735 $ echo '[extensions]' >> $HGRCPATH
735 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
736 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
736
737
737 Test for aliases
738 Test for aliases
738
739
739 $ hg help hgalias
740 $ hg help hgalias
740 hg hgalias [--remote]
741 hg hgalias [--remote]
741
742
742 alias for: hg summary
743 alias for: hg summary
743
744
744 summarize working directory state
745 summarize working directory state
745
746
746 This generates a brief summary of the working directory state, including
747 This generates a brief summary of the working directory state, including
747 parents, branch, commit status, phase and available updates.
748 parents, branch, commit status, phase and available updates.
748
749
749 With the --remote option, this will check the default paths for incoming
750 With the --remote option, this will check the default paths for incoming
750 and outgoing changes. This can be time-consuming.
751 and outgoing changes. This can be time-consuming.
751
752
752 Returns 0 on success.
753 Returns 0 on success.
753
754
754 defined by: helpext
755 defined by: helpext
755
756
756 options:
757 options:
757
758
758 --remote check for push and pull
759 --remote check for push and pull
759
760
760 (some details hidden, use --verbose to show complete help)
761 (some details hidden, use --verbose to show complete help)
761
762
762 $ hg help shellalias
763 $ hg help shellalias
763 hg shellalias
764 hg shellalias
764
765
765 shell alias for: echo hi
766 shell alias for: echo hi
766
767
767 (no help text available)
768 (no help text available)
768
769
769 defined by: helpext
770 defined by: helpext
770
771
771 (some details hidden, use --verbose to show complete help)
772 (some details hidden, use --verbose to show complete help)
772
773
773 Test command with no help text
774 Test command with no help text
774
775
775 $ hg help nohelp
776 $ hg help nohelp
776 hg nohelp
777 hg nohelp
777
778
778 (no help text available)
779 (no help text available)
779
780
780 options:
781 options:
781
782
782 --longdesc VALUE
783 --longdesc VALUE
783 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
784 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
784 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
785 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
785 -n -- normal desc
786 -n -- normal desc
786 --newline VALUE line1 line2
787 --newline VALUE line1 line2
787 --callableopt VALUE adds foo
788 --callableopt VALUE adds foo
788 --customopt VALUE adds bar
789 --customopt VALUE adds bar
789 --customopt-withdefault VALUE adds bar (default: foo)
790 --customopt-withdefault VALUE adds bar (default: foo)
790
791
791 (some details hidden, use --verbose to show complete help)
792 (some details hidden, use --verbose to show complete help)
792
793
793 $ hg help -k nohelp
794 $ hg help -k nohelp
794 Commands:
795 Commands:
795
796
796 nohelp hg nohelp
797 nohelp hg nohelp
797
798
798 Extension Commands:
799 Extension Commands:
799
800
800 nohelp (no help text available)
801 nohelp (no help text available)
801
802
802 Test that default list of commands omits extension commands
803 Test that default list of commands omits extension commands
803
804
804 #if no-extraextensions
805 #if no-extraextensions
805
806
806 $ hg help
807 $ hg help
807 Mercurial Distributed SCM
808 Mercurial Distributed SCM
808
809
809 list of commands:
810 list of commands:
810
811
811 add add the specified files on the next commit
812 add add the specified files on the next commit
812 addremove add all new files, delete all missing files
813 addremove add all new files, delete all missing files
813 annotate show changeset information by line for each file
814 annotate show changeset information by line for each file
814 archive create an unversioned archive of a repository revision
815 archive create an unversioned archive of a repository revision
815 backout reverse effect of earlier changeset
816 backout reverse effect of earlier changeset
816 bisect subdivision search of changesets
817 bisect subdivision search of changesets
817 bookmarks create a new bookmark or list existing bookmarks
818 bookmarks create a new bookmark or list existing bookmarks
818 branch set or show the current branch name
819 branch set or show the current branch name
819 branches list repository named branches
820 branches list repository named branches
820 bundle create a bundle file
821 bundle create a bundle file
821 cat output the current or given revision of files
822 cat output the current or given revision of files
822 clone make a copy of an existing repository
823 clone make a copy of an existing repository
823 commit commit the specified files or all outstanding changes
824 commit commit the specified files or all outstanding changes
824 config show combined config settings from all hgrc files
825 config show combined config settings from all hgrc files
825 copy mark files as copied for the next commit
826 copy mark files as copied for the next commit
826 diff diff repository (or selected files)
827 diff diff repository (or selected files)
827 export dump the header and diffs for one or more changesets
828 export dump the header and diffs for one or more changesets
828 files list tracked files
829 files list tracked files
829 forget forget the specified files on the next commit
830 forget forget the specified files on the next commit
830 graft copy changes from other branches onto the current branch
831 graft copy changes from other branches onto the current branch
831 grep search revision history for a pattern in specified files
832 grep search revision history for a pattern in specified files
832 heads show branch heads
833 heads show branch heads
833 help show help for a given topic or a help overview
834 help show help for a given topic or a help overview
834 identify identify the working directory or specified revision
835 identify identify the working directory or specified revision
835 import import an ordered set of patches
836 import import an ordered set of patches
836 incoming show new changesets found in source
837 incoming show new changesets found in source
837 init create a new repository in the given directory
838 init create a new repository in the given directory
838 log show revision history of entire repository or files
839 log show revision history of entire repository or files
839 manifest output the current or given revision of the project manifest
840 manifest output the current or given revision of the project manifest
840 merge merge another revision into working directory
841 merge merge another revision into working directory
841 outgoing show changesets not found in the destination
842 outgoing show changesets not found in the destination
842 paths show aliases for remote repositories
843 paths show aliases for remote repositories
843 phase set or show the current phase name
844 phase set or show the current phase name
844 pull pull changes from the specified source
845 pull pull changes from the specified source
845 push push changes to the specified destination
846 push push changes to the specified destination
846 recover roll back an interrupted transaction
847 recover roll back an interrupted transaction
847 remove remove the specified files on the next commit
848 remove remove the specified files on the next commit
848 rename rename files; equivalent of copy + remove
849 rename rename files; equivalent of copy + remove
849 resolve redo merges or set/view the merge status of files
850 resolve redo merges or set/view the merge status of files
850 revert restore files to their checkout state
851 revert restore files to their checkout state
851 root print the root (top) of the current working directory
852 root print the root (top) of the current working directory
852 serve start stand-alone webserver
853 serve start stand-alone webserver
853 status show changed files in the working directory
854 status show changed files in the working directory
854 summary summarize working directory state
855 summary summarize working directory state
855 tag add one or more tags for the current or given revision
856 tag add one or more tags for the current or given revision
856 tags list repository tags
857 tags list repository tags
857 unbundle apply one or more bundle files
858 unbundle apply one or more bundle files
858 update update working directory (or switch revisions)
859 update update working directory (or switch revisions)
859 verify verify the integrity of the repository
860 verify verify the integrity of the repository
860 version output version and copyright information
861 version output version and copyright information
861
862
862 enabled extensions:
863 enabled extensions:
863
864
864 helpext (no help text available)
865 helpext (no help text available)
865
866
866 additional help topics:
867 additional help topics:
867
868
868 bundlespec Bundle File Formats
869 bundlespec Bundle File Formats
869 color Colorizing Outputs
870 color Colorizing Outputs
870 config Configuration Files
871 config Configuration Files
871 dates Date Formats
872 dates Date Formats
872 deprecated Deprecated Features
873 deprecated Deprecated Features
873 diffs Diff Formats
874 diffs Diff Formats
874 environment Environment Variables
875 environment Environment Variables
875 extensions Using Additional Features
876 extensions Using Additional Features
876 filesets Specifying File Sets
877 filesets Specifying File Sets
877 flags Command-line flags
878 flags Command-line flags
878 glossary Glossary
879 glossary Glossary
879 hgignore Syntax for Mercurial Ignore Files
880 hgignore Syntax for Mercurial Ignore Files
880 hgweb Configuring hgweb
881 hgweb Configuring hgweb
881 internals Technical implementation topics
882 internals Technical implementation topics
882 merge-tools Merge Tools
883 merge-tools Merge Tools
883 pager Pager Support
884 pager Pager Support
884 patterns File Name Patterns
885 patterns File Name Patterns
885 phases Working with Phases
886 phases Working with Phases
886 revisions Specifying Revisions
887 revisions Specifying Revisions
887 scripting Using Mercurial from scripts and automation
888 scripting Using Mercurial from scripts and automation
888 subrepos Subrepositories
889 subrepos Subrepositories
889 templating Template Usage
890 templating Template Usage
890 urls URL Paths
891 urls URL Paths
891
892
892 (use 'hg help -v' to show built-in aliases and global options)
893 (use 'hg help -v' to show built-in aliases and global options)
893
894
894 #endif
895 #endif
895
896
896 Test list of internal help commands
897 Test list of internal help commands
897
898
898 $ hg help debug
899 $ hg help debug
899 debug commands (internal and unsupported):
900 debug commands (internal and unsupported):
900
901
901 debugancestor
902 debugancestor
902 find the ancestor revision of two revisions in a given index
903 find the ancestor revision of two revisions in a given index
903 debugapplystreamclonebundle
904 debugapplystreamclonebundle
904 apply a stream clone bundle file
905 apply a stream clone bundle file
905 debugbuilddag
906 debugbuilddag
906 builds a repo with a given DAG from scratch in the current
907 builds a repo with a given DAG from scratch in the current
907 empty repo
908 empty repo
908 debugbundle lists the contents of a bundle
909 debugbundle lists the contents of a bundle
909 debugcapabilities
910 debugcapabilities
910 lists the capabilities of a remote peer
911 lists the capabilities of a remote peer
911 debugcheckstate
912 debugcheckstate
912 validate the correctness of the current dirstate
913 validate the correctness of the current dirstate
913 debugcolor show available color, effects or style
914 debugcolor show available color, effects or style
914 debugcommands
915 debugcommands
915 list all available commands and options
916 list all available commands and options
916 debugcomplete
917 debugcomplete
917 returns the completion list associated with the given command
918 returns the completion list associated with the given command
918 debugcreatestreamclonebundle
919 debugcreatestreamclonebundle
919 create a stream clone bundle file
920 create a stream clone bundle file
920 debugdag format the changelog or an index DAG as a concise textual
921 debugdag format the changelog or an index DAG as a concise textual
921 description
922 description
922 debugdata dump the contents of a data file revision
923 debugdata dump the contents of a data file revision
923 debugdate parse and display a date
924 debugdate parse and display a date
924 debugdeltachain
925 debugdeltachain
925 dump information about delta chains in a revlog
926 dump information about delta chains in a revlog
926 debugdirstate
927 debugdirstate
927 show the contents of the current dirstate
928 show the contents of the current dirstate
928 debugdiscovery
929 debugdiscovery
929 runs the changeset discovery protocol in isolation
930 runs the changeset discovery protocol in isolation
930 debugdownload
931 debugdownload
931 download a resource using Mercurial logic and config
932 download a resource using Mercurial logic and config
932 debugextensions
933 debugextensions
933 show information about active extensions
934 show information about active extensions
934 debugfileset parse and apply a fileset specification
935 debugfileset parse and apply a fileset specification
935 debugformat display format information about the current repository
936 debugformat display format information about the current repository
936 debugfsinfo show information detected about current filesystem
937 debugfsinfo show information detected about current filesystem
937 debuggetbundle
938 debuggetbundle
938 retrieves a bundle from a repo
939 retrieves a bundle from a repo
939 debugignore display the combined ignore pattern and information about
940 debugignore display the combined ignore pattern and information about
940 ignored files
941 ignored files
941 debugindex dump index data for a storage primitive
942 debugindex dump index data for a storage primitive
942 debugindexdot
943 debugindexdot
943 dump an index DAG as a graphviz dot file
944 dump an index DAG as a graphviz dot file
944 debuginstall test Mercurial installation
945 debuginstall test Mercurial installation
945 debugknown test whether node ids are known to a repo
946 debugknown test whether node ids are known to a repo
946 debuglocks show or modify state of locks
947 debuglocks show or modify state of locks
947 debugmanifestfulltextcache
948 debugmanifestfulltextcache
948 show, clear or amend the contents of the manifest fulltext
949 show, clear or amend the contents of the manifest fulltext
949 cache
950 cache
950 debugmergestate
951 debugmergestate
951 print merge state
952 print merge state
952 debugnamecomplete
953 debugnamecomplete
953 complete "names" - tags, open branch names, bookmark names
954 complete "names" - tags, open branch names, bookmark names
954 debugobsolete
955 debugobsolete
955 create arbitrary obsolete marker
956 create arbitrary obsolete marker
956 debugoptADV (no help text available)
957 debugoptADV (no help text available)
957 debugoptDEP (no help text available)
958 debugoptDEP (no help text available)
958 debugoptEXP (no help text available)
959 debugoptEXP (no help text available)
959 debugpathcomplete
960 debugpathcomplete
960 complete part or all of a tracked path
961 complete part or all of a tracked path
961 debugpeer establish a connection to a peer repository
962 debugpeer establish a connection to a peer repository
962 debugpickmergetool
963 debugpickmergetool
963 examine which merge tool is chosen for specified file
964 examine which merge tool is chosen for specified file
964 debugpushkey access the pushkey key/value protocol
965 debugpushkey access the pushkey key/value protocol
965 debugpvec (no help text available)
966 debugpvec (no help text available)
966 debugrebuilddirstate
967 debugrebuilddirstate
967 rebuild the dirstate as it would look like for the given
968 rebuild the dirstate as it would look like for the given
968 revision
969 revision
969 debugrebuildfncache
970 debugrebuildfncache
970 rebuild the fncache file
971 rebuild the fncache file
971 debugrename dump rename information
972 debugrename dump rename information
972 debugrevlog show data and statistics about a revlog
973 debugrevlog show data and statistics about a revlog
973 debugrevlogindex
974 debugrevlogindex
974 dump the contents of a revlog index
975 dump the contents of a revlog index
975 debugrevspec parse and apply a revision specification
976 debugrevspec parse and apply a revision specification
976 debugserve run a server with advanced settings
977 debugserve run a server with advanced settings
977 debugsetparents
978 debugsetparents
978 manually set the parents of the current working directory
979 manually set the parents of the current working directory
979 debugssl test a secure connection to a server
980 debugssl test a secure connection to a server
980 debugsub (no help text available)
981 debugsub (no help text available)
981 debugsuccessorssets
982 debugsuccessorssets
982 show set of successors for revision
983 show set of successors for revision
983 debugtemplate
984 debugtemplate
984 parse and apply a template
985 parse and apply a template
985 debuguigetpass
986 debuguigetpass
986 show prompt to type password
987 show prompt to type password
987 debuguiprompt
988 debuguiprompt
988 show plain prompt
989 show plain prompt
989 debugupdatecaches
990 debugupdatecaches
990 warm all known caches in the repository
991 warm all known caches in the repository
991 debugupgraderepo
992 debugupgraderepo
992 upgrade a repository to use different features
993 upgrade a repository to use different features
993 debugwalk show how files match on given patterns
994 debugwalk show how files match on given patterns
994 debugwhyunstable
995 debugwhyunstable
995 explain instabilities of a changeset
996 explain instabilities of a changeset
996 debugwireargs
997 debugwireargs
997 (no help text available)
998 (no help text available)
998 debugwireproto
999 debugwireproto
999 send wire protocol commands to a server
1000 send wire protocol commands to a server
1000
1001
1001 (use 'hg help -v debug' to show built-in aliases and global options)
1002 (use 'hg help -v debug' to show built-in aliases and global options)
1002
1003
1003 internals topic renders index of available sub-topics
1004 internals topic renders index of available sub-topics
1004
1005
1005 $ hg help internals
1006 $ hg help internals
1006 Technical implementation topics
1007 Technical implementation topics
1007 """""""""""""""""""""""""""""""
1008 """""""""""""""""""""""""""""""
1008
1009
1009 To access a subtopic, use "hg help internals.{subtopic-name}"
1010 To access a subtopic, use "hg help internals.{subtopic-name}"
1010
1011
1011 bundle2 Bundle2
1012 bundle2 Bundle2
1012 bundles Bundles
1013 bundles Bundles
1013 cbor CBOR
1014 cbor CBOR
1014 censor Censor
1015 censor Censor
1015 changegroups Changegroups
1016 changegroups Changegroups
1016 config Config Registrar
1017 config Config Registrar
1017 requirements Repository Requirements
1018 requirements Repository Requirements
1018 revlogs Revision Logs
1019 revlogs Revision Logs
1019 wireprotocol Wire Protocol
1020 wireprotocol Wire Protocol
1020 wireprotocolrpc
1021 wireprotocolrpc
1021 Wire Protocol RPC
1022 Wire Protocol RPC
1022 wireprotocolv2
1023 wireprotocolv2
1023 Wire Protocol Version 2
1024 Wire Protocol Version 2
1024
1025
1025 sub-topics can be accessed
1026 sub-topics can be accessed
1026
1027
1027 $ hg help internals.changegroups
1028 $ hg help internals.changegroups
1028 Changegroups
1029 Changegroups
1029 """"""""""""
1030 """"""""""""
1030
1031
1031 Changegroups are representations of repository revlog data, specifically
1032 Changegroups are representations of repository revlog data, specifically
1032 the changelog data, root/flat manifest data, treemanifest data, and
1033 the changelog data, root/flat manifest data, treemanifest data, and
1033 filelogs.
1034 filelogs.
1034
1035
1035 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-
1036 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
1037 difference being an additional item in the *delta header*. Version "3"
1038 difference being an additional item in the *delta header*. Version "3"
1038 adds support for revlog flags in the *delta header* and optionally
1039 adds support for revlog flags in the *delta header* and optionally
1039 exchanging treemanifests (enabled by setting an option on the
1040 exchanging treemanifests (enabled by setting an option on the
1040 "changegroup" part in the bundle2).
1041 "changegroup" part in the bundle2).
1041
1042
1042 Changegroups when not exchanging treemanifests consist of 3 logical
1043 Changegroups when not exchanging treemanifests consist of 3 logical
1043 segments:
1044 segments:
1044
1045
1045 +---------------------------------+
1046 +---------------------------------+
1046 | | | |
1047 | | | |
1047 | changeset | manifest | filelogs |
1048 | changeset | manifest | filelogs |
1048 | | | |
1049 | | | |
1049 | | | |
1050 | | | |
1050 +---------------------------------+
1051 +---------------------------------+
1051
1052
1052 When exchanging treemanifests, there are 4 logical segments:
1053 When exchanging treemanifests, there are 4 logical segments:
1053
1054
1054 +-------------------------------------------------+
1055 +-------------------------------------------------+
1055 | | | | |
1056 | | | | |
1056 | changeset | root | treemanifests | filelogs |
1057 | changeset | root | treemanifests | filelogs |
1057 | | manifest | | |
1058 | | manifest | | |
1058 | | | | |
1059 | | | | |
1059 +-------------------------------------------------+
1060 +-------------------------------------------------+
1060
1061
1061 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
1062 framed piece of data:
1063 framed piece of data:
1063
1064
1064 +---------------------------------------+
1065 +---------------------------------------+
1065 | | |
1066 | | |
1066 | length | data |
1067 | length | data |
1067 | (4 bytes) | (<length - 4> bytes) |
1068 | (4 bytes) | (<length - 4> bytes) |
1068 | | |
1069 | | |
1069 +---------------------------------------+
1070 +---------------------------------------+
1070
1071
1071 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
1072 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
1073 length field itself).
1074 length field itself).
1074
1075
1075 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
1076 ("0x00000000"). We call this an *empty chunk*.
1077 ("0x00000000"). We call this an *empty chunk*.
1077
1078
1078 Delta Groups
1079 Delta Groups
1079 ============
1080 ============
1080
1081
1081 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,
1082 or patches against previous revisions.
1083 or patches against previous revisions.
1083
1084
1084 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*
1085 to signal the end of the delta group:
1086 to signal the end of the delta group:
1086
1087
1087 +------------------------------------------------------------------------+
1088 +------------------------------------------------------------------------+
1088 | | | | | |
1089 | | | | | |
1089 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1090 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1090 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1091 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1091 | | | | | |
1092 | | | | | |
1092 +------------------------------------------------------------------------+
1093 +------------------------------------------------------------------------+
1093
1094
1094 Each *chunk*'s data consists of the following:
1095 Each *chunk*'s data consists of the following:
1095
1096
1096 +---------------------------------------+
1097 +---------------------------------------+
1097 | | |
1098 | | |
1098 | delta header | delta data |
1099 | delta header | delta data |
1099 | (various by version) | (various) |
1100 | (various by version) | (various) |
1100 | | |
1101 | | |
1101 +---------------------------------------+
1102 +---------------------------------------+
1102
1103
1103 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
1104 existing entry (either that the recipient already has, or previously
1105 existing entry (either that the recipient already has, or previously
1105 specified in the bundle/changegroup).
1106 specified in the bundle/changegroup).
1106
1107
1107 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
1108 changegroup format.
1109 changegroup format.
1109
1110
1110 Version 1 (headerlen=80):
1111 Version 1 (headerlen=80):
1111
1112
1112 +------------------------------------------------------+
1113 +------------------------------------------------------+
1113 | | | | |
1114 | | | | |
1114 | node | p1 node | p2 node | link node |
1115 | node | p1 node | p2 node | link node |
1115 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1116 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1116 | | | | |
1117 | | | | |
1117 +------------------------------------------------------+
1118 +------------------------------------------------------+
1118
1119
1119 Version 2 (headerlen=100):
1120 Version 2 (headerlen=100):
1120
1121
1121 +------------------------------------------------------------------+
1122 +------------------------------------------------------------------+
1122 | | | | | |
1123 | | | | | |
1123 | node | p1 node | p2 node | base node | link node |
1124 | node | p1 node | p2 node | base node | link node |
1124 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1125 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1125 | | | | | |
1126 | | | | | |
1126 +------------------------------------------------------------------+
1127 +------------------------------------------------------------------+
1127
1128
1128 Version 3 (headerlen=102):
1129 Version 3 (headerlen=102):
1129
1130
1130 +------------------------------------------------------------------------------+
1131 +------------------------------------------------------------------------------+
1131 | | | | | | |
1132 | | | | | | |
1132 | node | p1 node | p2 node | base node | link node | flags |
1133 | node | p1 node | p2 node | base node | link node | flags |
1133 | (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) |
1134 | | | | | | |
1135 | | | | | | |
1135 +------------------------------------------------------------------------------+
1136 +------------------------------------------------------------------------------+
1136
1137
1137 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1138 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1138 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
1139 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
1140 has, or previously specified in the bundle/changegroup). The format is
1141 has, or previously specified in the bundle/changegroup). The format is
1141 described more fully in "hg help internals.bdiff", but briefly:
1142 described more fully in "hg help internals.bdiff", but briefly:
1142
1143
1143 +---------------------------------------------------------------+
1144 +---------------------------------------------------------------+
1144 | | | | |
1145 | | | | |
1145 | start offset | end offset | new length | content |
1146 | start offset | end offset | new length | content |
1146 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1147 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1147 | | | | |
1148 | | | | |
1148 +---------------------------------------------------------------+
1149 +---------------------------------------------------------------+
1149
1150
1150 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
1151 itself.
1152 itself.
1152
1153
1153 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
1154 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
1155 changegroup.
1156 changegroup.
1156
1157
1157 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
1158 changegroup. This allows the delta to be expressed against any parent,
1159 changegroup. This allows the delta to be expressed against any parent,
1159 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.
1160
1161
1161 Changeset Segment
1162 Changeset Segment
1162 =================
1163 =================
1163
1164
1164 The *changeset segment* consists of a single *delta group* holding
1165 The *changeset segment* consists of a single *delta group* holding
1165 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
1166 the boundary to the *manifest segment*.
1167 the boundary to the *manifest segment*.
1167
1168
1168 Manifest Segment
1169 Manifest Segment
1169 ================
1170 ================
1170
1171
1171 The *manifest segment* consists of a single *delta group* holding manifest
1172 The *manifest segment* consists of a single *delta group* holding manifest
1172 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
1173 root directory of the repository. Otherwise, it contains the entire
1174 root directory of the repository. Otherwise, it contains the entire
1174 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
1175 the boundary to the next segment (either the *treemanifests segment* or
1176 the boundary to the next segment (either the *treemanifests segment* or
1176 the *filelogs segment*, depending on version and the request options).
1177 the *filelogs segment*, depending on version and the request options).
1177
1178
1178 Treemanifests Segment
1179 Treemanifests Segment
1179 ---------------------
1180 ---------------------
1180
1181
1181 The *treemanifests segment* only exists in changegroup version "3", and
1182 The *treemanifests segment* only exists in changegroup version "3", and
1182 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
1183 (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).
1184 Aside from the filenames in the *treemanifests segment* containing a
1185 Aside from the filenames in the *treemanifests segment* containing a
1185 trailing "/" character, it behaves identically to the *filelogs segment*
1186 trailing "/" character, it behaves identically to the *filelogs segment*
1186 (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*
1187 (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
1188 to the *filelogs segment*.
1189 to the *filelogs segment*.
1189
1190
1190 Filelogs Segment
1191 Filelogs Segment
1191 ================
1192 ================
1192
1193
1193 The *filelogs segment* consists of multiple sub-segments, each
1194 The *filelogs segment* consists of multiple sub-segments, each
1194 corresponding to an individual file whose data is being described:
1195 corresponding to an individual file whose data is being described:
1195
1196
1196 +--------------------------------------------------+
1197 +--------------------------------------------------+
1197 | | | | | |
1198 | | | | | |
1198 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1199 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1199 | | | | | (4 bytes) |
1200 | | | | | (4 bytes) |
1200 | | | | | |
1201 | | | | | |
1201 +--------------------------------------------------+
1202 +--------------------------------------------------+
1202
1203
1203 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,
1204 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
1205 and of the overall changegroup.
1206 and of the overall changegroup.
1206
1207
1207 Each filelog sub-segment consists of the following:
1208 Each filelog sub-segment consists of the following:
1208
1209
1209 +------------------------------------------------------+
1210 +------------------------------------------------------+
1210 | | | |
1211 | | | |
1211 | filename length | filename | delta group |
1212 | filename length | filename | delta group |
1212 | (4 bytes) | (<length - 4> bytes) | (various) |
1213 | (4 bytes) | (<length - 4> bytes) | (various) |
1213 | | | |
1214 | | | |
1214 +------------------------------------------------------+
1215 +------------------------------------------------------+
1215
1216
1216 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)
1217 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
1218 *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
1219 next filelog sub-segment.
1220 next filelog sub-segment.
1220
1221
1221 Test list of commands with command with no help text
1222 Test list of commands with command with no help text
1222
1223
1223 $ hg help helpext
1224 $ hg help helpext
1224 helpext extension - no help text available
1225 helpext extension - no help text available
1225
1226
1226 list of commands:
1227 list of commands:
1227
1228
1228 nohelp (no help text available)
1229 nohelp (no help text available)
1229
1230
1230 (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)
1231
1232
1232
1233
1233 test advanced, deprecated and experimental options are hidden in command help
1234 test advanced, deprecated and experimental options are hidden in command help
1234 $ hg help debugoptADV
1235 $ hg help debugoptADV
1235 hg debugoptADV
1236 hg debugoptADV
1236
1237
1237 (no help text available)
1238 (no help text available)
1238
1239
1239 options:
1240 options:
1240
1241
1241 (some details hidden, use --verbose to show complete help)
1242 (some details hidden, use --verbose to show complete help)
1242 $ hg help debugoptDEP
1243 $ hg help debugoptDEP
1243 hg debugoptDEP
1244 hg debugoptDEP
1244
1245
1245 (no help text available)
1246 (no help text available)
1246
1247
1247 options:
1248 options:
1248
1249
1249 (some details hidden, use --verbose to show complete help)
1250 (some details hidden, use --verbose to show complete help)
1250
1251
1251 $ hg help debugoptEXP
1252 $ hg help debugoptEXP
1252 hg debugoptEXP
1253 hg debugoptEXP
1253
1254
1254 (no help text available)
1255 (no help text available)
1255
1256
1256 options:
1257 options:
1257
1258
1258 (some details hidden, use --verbose to show complete help)
1259 (some details hidden, use --verbose to show complete help)
1259
1260
1260 test advanced, deprecated and experimental options are shown with -v
1261 test advanced, deprecated and experimental options are shown with -v
1261 $ hg help -v debugoptADV | grep aopt
1262 $ hg help -v debugoptADV | grep aopt
1262 --aopt option is (ADVANCED)
1263 --aopt option is (ADVANCED)
1263 $ hg help -v debugoptDEP | grep dopt
1264 $ hg help -v debugoptDEP | grep dopt
1264 --dopt option is (DEPRECATED)
1265 --dopt option is (DEPRECATED)
1265 $ hg help -v debugoptEXP | grep eopt
1266 $ hg help -v debugoptEXP | grep eopt
1266 --eopt option is (EXPERIMENTAL)
1267 --eopt option is (EXPERIMENTAL)
1267
1268
1268 #if gettext
1269 #if gettext
1269 test deprecated option is hidden with translation with untranslated description
1270 test deprecated option is hidden with translation with untranslated description
1270 (use many globy for not failing on changed transaction)
1271 (use many globy for not failing on changed transaction)
1271 $ LANGUAGE=sv hg help debugoptDEP
1272 $ LANGUAGE=sv hg help debugoptDEP
1272 hg debugoptDEP
1273 hg debugoptDEP
1273
1274
1274 (*) (glob)
1275 (*) (glob)
1275
1276
1276 options:
1277 options:
1277
1278
1278 (some details hidden, use --verbose to show complete help)
1279 (some details hidden, use --verbose to show complete help)
1279 #endif
1280 #endif
1280
1281
1281 Test commands that collide with topics (issue4240)
1282 Test commands that collide with topics (issue4240)
1282
1283
1283 $ hg config -hq
1284 $ hg config -hq
1284 hg config [-u] [NAME]...
1285 hg config [-u] [NAME]...
1285
1286
1286 show combined config settings from all hgrc files
1287 show combined config settings from all hgrc files
1287 $ hg showconfig -hq
1288 $ hg showconfig -hq
1288 hg config [-u] [NAME]...
1289 hg config [-u] [NAME]...
1289
1290
1290 show combined config settings from all hgrc files
1291 show combined config settings from all hgrc files
1291
1292
1292 Test a help topic
1293 Test a help topic
1293
1294
1294 $ hg help dates
1295 $ hg help dates
1295 Date Formats
1296 Date Formats
1296 """"""""""""
1297 """"""""""""
1297
1298
1298 Some commands allow the user to specify a date, e.g.:
1299 Some commands allow the user to specify a date, e.g.:
1299
1300
1300 - backout, commit, import, tag: Specify the commit date.
1301 - backout, commit, import, tag: Specify the commit date.
1301 - log, revert, update: Select revision(s) by date.
1302 - log, revert, update: Select revision(s) by date.
1302
1303
1303 Many date formats are valid. Here are some examples:
1304 Many date formats are valid. Here are some examples:
1304
1305
1305 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1306 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1306 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1307 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1307 - "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)
1308 - "Dec 6" (midnight)
1309 - "Dec 6" (midnight)
1309 - "13:18" (today assumed)
1310 - "13:18" (today assumed)
1310 - "3:39" (3:39AM assumed)
1311 - "3:39" (3:39AM assumed)
1311 - "3:39pm" (15:39)
1312 - "3:39pm" (15:39)
1312 - "2006-12-06 13:18:29" (ISO 8601 format)
1313 - "2006-12-06 13:18:29" (ISO 8601 format)
1313 - "2006-12-6 13:18"
1314 - "2006-12-6 13:18"
1314 - "2006-12-6"
1315 - "2006-12-6"
1315 - "12-6"
1316 - "12-6"
1316 - "12/6"
1317 - "12/6"
1317 - "12/6/6" (Dec 6 2006)
1318 - "12/6/6" (Dec 6 2006)
1318 - "today" (midnight)
1319 - "today" (midnight)
1319 - "yesterday" (midnight)
1320 - "yesterday" (midnight)
1320 - "now" - right now
1321 - "now" - right now
1321
1322
1322 Lastly, there is Mercurial's internal format:
1323 Lastly, there is Mercurial's internal format:
1323
1324
1324 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1325 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1325
1326
1326 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
1327 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
1328 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
1329 the timezone is east of UTC).
1330 the timezone is east of UTC).
1330
1331
1331 The log command also accepts date ranges:
1332 The log command also accepts date ranges:
1332
1333
1333 - "<DATE" - at or before a given date/time
1334 - "<DATE" - at or before a given date/time
1334 - ">DATE" - on or after a given date/time
1335 - ">DATE" - on or after a given date/time
1335 - "DATE to DATE" - a date range, inclusive
1336 - "DATE to DATE" - a date range, inclusive
1336 - "-DAYS" - within a given number of days of today
1337 - "-DAYS" - within a given number of days of today
1337
1338
1338 Test repeated config section name
1339 Test repeated config section name
1339
1340
1340 $ hg help config.host
1341 $ hg help config.host
1341 "http_proxy.host"
1342 "http_proxy.host"
1342 Host name and (optional) port of the proxy server, for example
1343 Host name and (optional) port of the proxy server, for example
1343 "myproxy:8000".
1344 "myproxy:8000".
1344
1345
1345 "smtp.host"
1346 "smtp.host"
1346 Host name of mail server, e.g. "mail.example.com".
1347 Host name of mail server, e.g. "mail.example.com".
1347
1348
1348
1349
1349 Test section name with dot
1350 Test section name with dot
1350
1351
1351 $ hg help config.ui.username
1352 $ hg help config.ui.username
1352 "ui.username"
1353 "ui.username"
1353 The committer of a changeset created when running "commit". Typically
1354 The committer of a changeset created when running "commit". Typically
1354 a person's name and email address, e.g. "Fred Widget
1355 a person's name and email address, e.g. "Fred Widget
1355 <fred@example.com>". Environment variables in the username are
1356 <fred@example.com>". Environment variables in the username are
1356 expanded.
1357 expanded.
1357
1358
1358 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1359 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1359 empty, e.g. if the system admin set "username =" in the system hgrc,
1360 empty, e.g. if the system admin set "username =" in the system hgrc,
1360 it has to be specified manually or in a different hgrc file)
1361 it has to be specified manually or in a different hgrc file)
1361
1362
1362
1363
1363 $ hg help config.annotate.git
1364 $ hg help config.annotate.git
1364 abort: help section not found: config.annotate.git
1365 abort: help section not found: config.annotate.git
1365 [255]
1366 [255]
1366
1367
1367 $ hg help config.update.check
1368 $ hg help config.update.check
1368 "commands.update.check"
1369 "commands.update.check"
1369 Determines what level of checking 'hg update' will perform before
1370 Determines what level of checking 'hg update' will perform before
1370 moving to a destination revision. Valid values are "abort", "none",
1371 moving to a destination revision. Valid values are "abort", "none",
1371 "linear", and "noconflict". "abort" always fails if the working
1372 "linear", and "noconflict". "abort" always fails if the working
1372 directory has uncommitted changes. "none" performs no checking, and
1373 directory has uncommitted changes. "none" performs no checking, and
1373 may result in a merge with uncommitted changes. "linear" allows any
1374 may result in a merge with uncommitted changes. "linear" allows any
1374 update as long as it follows a straight line in the revision history,
1375 update as long as it follows a straight line in the revision history,
1375 and may trigger a merge with uncommitted changes. "noconflict" will
1376 and may trigger a merge with uncommitted changes. "noconflict" will
1376 allow any update which would not trigger a merge with uncommitted
1377 allow any update which would not trigger a merge with uncommitted
1377 changes, if any are present. (default: "linear")
1378 changes, if any are present. (default: "linear")
1378
1379
1379
1380
1380 $ hg help config.commands.update.check
1381 $ hg help config.commands.update.check
1381 "commands.update.check"
1382 "commands.update.check"
1382 Determines what level of checking 'hg update' will perform before
1383 Determines what level of checking 'hg update' will perform before
1383 moving to a destination revision. Valid values are "abort", "none",
1384 moving to a destination revision. Valid values are "abort", "none",
1384 "linear", and "noconflict". "abort" always fails if the working
1385 "linear", and "noconflict". "abort" always fails if the working
1385 directory has uncommitted changes. "none" performs no checking, and
1386 directory has uncommitted changes. "none" performs no checking, and
1386 may result in a merge with uncommitted changes. "linear" allows any
1387 may result in a merge with uncommitted changes. "linear" allows any
1387 update as long as it follows a straight line in the revision history,
1388 update as long as it follows a straight line in the revision history,
1388 and may trigger a merge with uncommitted changes. "noconflict" will
1389 and may trigger a merge with uncommitted changes. "noconflict" will
1389 allow any update which would not trigger a merge with uncommitted
1390 allow any update which would not trigger a merge with uncommitted
1390 changes, if any are present. (default: "linear")
1391 changes, if any are present. (default: "linear")
1391
1392
1392
1393
1393 $ hg help config.ommands.update.check
1394 $ hg help config.ommands.update.check
1394 abort: help section not found: config.ommands.update.check
1395 abort: help section not found: config.ommands.update.check
1395 [255]
1396 [255]
1396
1397
1397 Unrelated trailing paragraphs shouldn't be included
1398 Unrelated trailing paragraphs shouldn't be included
1398
1399
1399 $ hg help config.extramsg | grep '^$'
1400 $ hg help config.extramsg | grep '^$'
1400
1401
1401
1402
1402 Test capitalized section name
1403 Test capitalized section name
1403
1404
1404 $ hg help scripting.HGPLAIN > /dev/null
1405 $ hg help scripting.HGPLAIN > /dev/null
1405
1406
1406 Help subsection:
1407 Help subsection:
1407
1408
1408 $ hg help config.charsets |grep "Email example:" > /dev/null
1409 $ hg help config.charsets |grep "Email example:" > /dev/null
1409 [1]
1410 [1]
1410
1411
1411 Show nested definitions
1412 Show nested definitions
1412 ("profiling.type"[break]"ls"[break]"stat"[break])
1413 ("profiling.type"[break]"ls"[break]"stat"[break])
1413
1414
1414 $ hg help config.type | egrep '^$'|wc -l
1415 $ hg help config.type | egrep '^$'|wc -l
1415 \s*3 (re)
1416 \s*3 (re)
1416
1417
1417 $ hg help config.profiling.type.ls
1418 $ hg help config.profiling.type.ls
1418 "profiling.type.ls"
1419 "profiling.type.ls"
1419 Use Python's built-in instrumenting profiler. This profiler works on
1420 Use Python's built-in instrumenting profiler. This profiler works on
1420 all platforms, but each line number it reports is the first line of
1421 all platforms, but each line number it reports is the first line of
1421 a function. This restriction makes it difficult to identify the
1422 a function. This restriction makes it difficult to identify the
1422 expensive parts of a non-trivial function.
1423 expensive parts of a non-trivial function.
1423
1424
1424
1425
1425 Separate sections from subsections
1426 Separate sections from subsections
1426
1427
1427 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1428 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1428 "format"
1429 "format"
1429 --------
1430 --------
1430
1431
1431 "usegeneraldelta"
1432 "usegeneraldelta"
1432
1433
1433 "dotencode"
1434 "dotencode"
1434
1435
1435 "usefncache"
1436 "usefncache"
1436
1437
1437 "usestore"
1438 "usestore"
1438
1439
1439 "profiling"
1440 "profiling"
1440 -----------
1441 -----------
1441
1442
1442 "format"
1443 "format"
1443
1444
1444 "progress"
1445 "progress"
1445 ----------
1446 ----------
1446
1447
1447 "format"
1448 "format"
1448
1449
1449
1450
1450 Last item in help config.*:
1451 Last item in help config.*:
1451
1452
1452 $ hg help config.`hg help config|grep '^ "'| \
1453 $ hg help config.`hg help config|grep '^ "'| \
1453 > tail -1|sed 's![ "]*!!g'`| \
1454 > tail -1|sed 's![ "]*!!g'`| \
1454 > grep 'hg help -c config' > /dev/null
1455 > grep 'hg help -c config' > /dev/null
1455 [1]
1456 [1]
1456
1457
1457 note to use help -c for general hg help config:
1458 note to use help -c for general hg help config:
1458
1459
1459 $ hg help config |grep 'hg help -c config' > /dev/null
1460 $ hg help config |grep 'hg help -c config' > /dev/null
1460
1461
1461 Test templating help
1462 Test templating help
1462
1463
1463 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1464 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1464 desc String. The text of the changeset description.
1465 desc String. The text of the changeset description.
1465 diffstat String. Statistics of changes with the following format:
1466 diffstat String. Statistics of changes with the following format:
1466 firstline Any text. Returns the first line of text.
1467 firstline Any text. Returns the first line of text.
1467 nonempty Any text. Returns '(none)' if the string is empty.
1468 nonempty Any text. Returns '(none)' if the string is empty.
1468
1469
1469 Test deprecated items
1470 Test deprecated items
1470
1471
1471 $ hg help -v templating | grep currentbookmark
1472 $ hg help -v templating | grep currentbookmark
1472 currentbookmark
1473 currentbookmark
1473 $ hg help templating | (grep currentbookmark || true)
1474 $ hg help templating | (grep currentbookmark || true)
1474
1475
1475 Test help hooks
1476 Test help hooks
1476
1477
1477 $ cat > helphook1.py <<EOF
1478 $ cat > helphook1.py <<EOF
1478 > from mercurial import help
1479 > from mercurial import help
1479 >
1480 >
1480 > def rewrite(ui, topic, doc):
1481 > def rewrite(ui, topic, doc):
1481 > return doc + '\nhelphook1\n'
1482 > return doc + '\nhelphook1\n'
1482 >
1483 >
1483 > def extsetup(ui):
1484 > def extsetup(ui):
1484 > help.addtopichook('revisions', rewrite)
1485 > help.addtopichook('revisions', rewrite)
1485 > EOF
1486 > EOF
1486 $ cat > helphook2.py <<EOF
1487 $ cat > helphook2.py <<EOF
1487 > from mercurial import help
1488 > from mercurial import help
1488 >
1489 >
1489 > def rewrite(ui, topic, doc):
1490 > def rewrite(ui, topic, doc):
1490 > return doc + '\nhelphook2\n'
1491 > return doc + '\nhelphook2\n'
1491 >
1492 >
1492 > def extsetup(ui):
1493 > def extsetup(ui):
1493 > help.addtopichook('revisions', rewrite)
1494 > help.addtopichook('revisions', rewrite)
1494 > EOF
1495 > EOF
1495 $ echo '[extensions]' >> $HGRCPATH
1496 $ echo '[extensions]' >> $HGRCPATH
1496 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1497 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1497 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1498 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1498 $ hg help revsets | grep helphook
1499 $ hg help revsets | grep helphook
1499 helphook1
1500 helphook1
1500 helphook2
1501 helphook2
1501
1502
1502 help -c should only show debug --debug
1503 help -c should only show debug --debug
1503
1504
1504 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1505 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1505 [1]
1506 [1]
1506
1507
1507 help -c should only show deprecated for -v
1508 help -c should only show deprecated for -v
1508
1509
1509 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1510 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1510 [1]
1511 [1]
1511
1512
1512 Test -s / --system
1513 Test -s / --system
1513
1514
1514 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1515 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1515 > wc -l | sed -e 's/ //g'
1516 > wc -l | sed -e 's/ //g'
1516 0
1517 0
1517 $ hg help config.files --system unix | grep 'USER' | \
1518 $ hg help config.files --system unix | grep 'USER' | \
1518 > wc -l | sed -e 's/ //g'
1519 > wc -l | sed -e 's/ //g'
1519 0
1520 0
1520
1521
1521 Test -e / -c / -k combinations
1522 Test -e / -c / -k combinations
1522
1523
1523 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1524 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1524 Commands:
1525 Commands:
1525 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1526 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1526 Extensions:
1527 Extensions:
1527 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1528 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1528 Topics:
1529 Topics:
1529 Commands:
1530 Commands:
1530 Extensions:
1531 Extensions:
1531 Extension Commands:
1532 Extension Commands:
1532 $ hg help -c schemes
1533 $ hg help -c schemes
1533 abort: no such help topic: schemes
1534 abort: no such help topic: schemes
1534 (try 'hg help --keyword schemes')
1535 (try 'hg help --keyword schemes')
1535 [255]
1536 [255]
1536 $ hg help -e schemes |head -1
1537 $ hg help -e schemes |head -1
1537 schemes extension - extend schemes with shortcuts to repository swarms
1538 schemes extension - extend schemes with shortcuts to repository swarms
1538 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1539 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1539 Commands:
1540 Commands:
1540 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1541 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1541 Extensions:
1542 Extensions:
1542 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1543 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1543 Extensions:
1544 Extensions:
1544 Commands:
1545 Commands:
1545 $ hg help -c commit > /dev/null
1546 $ hg help -c commit > /dev/null
1546 $ hg help -e -c commit > /dev/null
1547 $ hg help -e -c commit > /dev/null
1547 $ hg help -e commit
1548 $ hg help -e commit
1548 abort: no such help topic: commit
1549 abort: no such help topic: commit
1549 (try 'hg help --keyword commit')
1550 (try 'hg help --keyword commit')
1550 [255]
1551 [255]
1551
1552
1552 Test keyword search help
1553 Test keyword search help
1553
1554
1554 $ cat > prefixedname.py <<EOF
1555 $ cat > prefixedname.py <<EOF
1555 > '''matched against word "clone"
1556 > '''matched against word "clone"
1556 > '''
1557 > '''
1557 > EOF
1558 > EOF
1558 $ echo '[extensions]' >> $HGRCPATH
1559 $ echo '[extensions]' >> $HGRCPATH
1559 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1560 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1560 $ hg help -k clone
1561 $ hg help -k clone
1561 Topics:
1562 Topics:
1562
1563
1563 config Configuration Files
1564 config Configuration Files
1564 extensions Using Additional Features
1565 extensions Using Additional Features
1565 glossary Glossary
1566 glossary Glossary
1566 phases Working with Phases
1567 phases Working with Phases
1567 subrepos Subrepositories
1568 subrepos Subrepositories
1568 urls URL Paths
1569 urls URL Paths
1569
1570
1570 Commands:
1571 Commands:
1571
1572
1572 bookmarks create a new bookmark or list existing bookmarks
1573 bookmarks create a new bookmark or list existing bookmarks
1573 clone make a copy of an existing repository
1574 clone make a copy of an existing repository
1574 paths show aliases for remote repositories
1575 paths show aliases for remote repositories
1575 pull pull changes from the specified source
1576 pull pull changes from the specified source
1576 update update working directory (or switch revisions)
1577 update update working directory (or switch revisions)
1577
1578
1578 Extensions:
1579 Extensions:
1579
1580
1580 clonebundles advertise pre-generated bundles to seed clones
1581 clonebundles advertise pre-generated bundles to seed clones
1581 narrow create clones which fetch history data for subset of files
1582 narrow create clones which fetch history data for subset of files
1582 (EXPERIMENTAL)
1583 (EXPERIMENTAL)
1583 prefixedname matched against word "clone"
1584 prefixedname matched against word "clone"
1584 relink recreates hardlinks between repository clones
1585 relink recreates hardlinks between repository clones
1585
1586
1586 Extension Commands:
1587 Extension Commands:
1587
1588
1588 qclone clone main and patch repository at same time
1589 qclone clone main and patch repository at same time
1589
1590
1590 Test unfound topic
1591 Test unfound topic
1591
1592
1592 $ hg help nonexistingtopicthatwillneverexisteverever
1593 $ hg help nonexistingtopicthatwillneverexisteverever
1593 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1594 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1594 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1595 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1595 [255]
1596 [255]
1596
1597
1597 Test unfound keyword
1598 Test unfound keyword
1598
1599
1599 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1600 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1600 abort: no matches
1601 abort: no matches
1601 (try 'hg help' for a list of topics)
1602 (try 'hg help' for a list of topics)
1602 [255]
1603 [255]
1603
1604
1604 Test omit indicating for help
1605 Test omit indicating for help
1605
1606
1606 $ cat > addverboseitems.py <<EOF
1607 $ cat > addverboseitems.py <<EOF
1607 > '''extension to test omit indicating.
1608 > '''extension to test omit indicating.
1608 >
1609 >
1609 > This paragraph is never omitted (for extension)
1610 > This paragraph is never omitted (for extension)
1610 >
1611 >
1611 > .. container:: verbose
1612 > .. container:: verbose
1612 >
1613 >
1613 > This paragraph is omitted,
1614 > This paragraph is omitted,
1614 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1615 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1615 >
1616 >
1616 > This paragraph is never omitted, too (for extension)
1617 > This paragraph is never omitted, too (for extension)
1617 > '''
1618 > '''
1618 > from __future__ import absolute_import
1619 > from __future__ import absolute_import
1619 > from mercurial import commands, help
1620 > from mercurial import commands, help
1620 > testtopic = """This paragraph is never omitted (for topic).
1621 > testtopic = """This paragraph is never omitted (for topic).
1621 >
1622 >
1622 > .. container:: verbose
1623 > .. container:: verbose
1623 >
1624 >
1624 > This paragraph is omitted,
1625 > This paragraph is omitted,
1625 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1626 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1626 >
1627 >
1627 > This paragraph is never omitted, too (for topic)
1628 > This paragraph is never omitted, too (for topic)
1628 > """
1629 > """
1629 > def extsetup(ui):
1630 > def extsetup(ui):
1630 > help.helptable.append((["topic-containing-verbose"],
1631 > help.helptable.append((["topic-containing-verbose"],
1631 > "This is the topic to test omit indicating.",
1632 > "This is the topic to test omit indicating.",
1632 > lambda ui: testtopic))
1633 > lambda ui: testtopic))
1633 > EOF
1634 > EOF
1634 $ echo '[extensions]' >> $HGRCPATH
1635 $ echo '[extensions]' >> $HGRCPATH
1635 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1636 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1636 $ hg help addverboseitems
1637 $ hg help addverboseitems
1637 addverboseitems extension - extension to test omit indicating.
1638 addverboseitems extension - extension to test omit indicating.
1638
1639
1639 This paragraph is never omitted (for extension)
1640 This paragraph is never omitted (for extension)
1640
1641
1641 This paragraph is never omitted, too (for extension)
1642 This paragraph is never omitted, too (for extension)
1642
1643
1643 (some details hidden, use --verbose to show complete help)
1644 (some details hidden, use --verbose to show complete help)
1644
1645
1645 no commands defined
1646 no commands defined
1646 $ hg help -v addverboseitems
1647 $ hg help -v addverboseitems
1647 addverboseitems extension - extension to test omit indicating.
1648 addverboseitems extension - extension to test omit indicating.
1648
1649
1649 This paragraph is never omitted (for extension)
1650 This paragraph is never omitted (for extension)
1650
1651
1651 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1652 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1652 extension)
1653 extension)
1653
1654
1654 This paragraph is never omitted, too (for extension)
1655 This paragraph is never omitted, too (for extension)
1655
1656
1656 no commands defined
1657 no commands defined
1657 $ hg help topic-containing-verbose
1658 $ hg help topic-containing-verbose
1658 This is the topic to test omit indicating.
1659 This is the topic to test omit indicating.
1659 """"""""""""""""""""""""""""""""""""""""""
1660 """"""""""""""""""""""""""""""""""""""""""
1660
1661
1661 This paragraph is never omitted (for topic).
1662 This paragraph is never omitted (for topic).
1662
1663
1663 This paragraph is never omitted, too (for topic)
1664 This paragraph is never omitted, too (for topic)
1664
1665
1665 (some details hidden, use --verbose to show complete help)
1666 (some details hidden, use --verbose to show complete help)
1666 $ hg help -v topic-containing-verbose
1667 $ hg help -v topic-containing-verbose
1667 This is the topic to test omit indicating.
1668 This is the topic to test omit indicating.
1668 """"""""""""""""""""""""""""""""""""""""""
1669 """"""""""""""""""""""""""""""""""""""""""
1669
1670
1670 This paragraph is never omitted (for topic).
1671 This paragraph is never omitted (for topic).
1671
1672
1672 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1673 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1673 topic)
1674 topic)
1674
1675
1675 This paragraph is never omitted, too (for topic)
1676 This paragraph is never omitted, too (for topic)
1676
1677
1677 Test section lookup
1678 Test section lookup
1678
1679
1679 $ hg help revset.merge
1680 $ hg help revset.merge
1680 "merge()"
1681 "merge()"
1681 Changeset is a merge changeset.
1682 Changeset is a merge changeset.
1682
1683
1683 $ hg help glossary.dag
1684 $ hg help glossary.dag
1684 DAG
1685 DAG
1685 The repository of changesets of a distributed version control system
1686 The repository of changesets of a distributed version control system
1686 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1687 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1687 of nodes and edges, where nodes correspond to changesets and edges
1688 of nodes and edges, where nodes correspond to changesets and edges
1688 imply a parent -> child relation. This graph can be visualized by
1689 imply a parent -> child relation. This graph can be visualized by
1689 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1690 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1690 limited by the requirement for children to have at most two parents.
1691 limited by the requirement for children to have at most two parents.
1691
1692
1692
1693
1693 $ hg help hgrc.paths
1694 $ hg help hgrc.paths
1694 "paths"
1695 "paths"
1695 -------
1696 -------
1696
1697
1697 Assigns symbolic names and behavior to repositories.
1698 Assigns symbolic names and behavior to repositories.
1698
1699
1699 Options are symbolic names defining the URL or directory that is the
1700 Options are symbolic names defining the URL or directory that is the
1700 location of the repository. Example:
1701 location of the repository. Example:
1701
1702
1702 [paths]
1703 [paths]
1703 my_server = https://example.com/my_repo
1704 my_server = https://example.com/my_repo
1704 local_path = /home/me/repo
1705 local_path = /home/me/repo
1705
1706
1706 These symbolic names can be used from the command line. To pull from
1707 These symbolic names can be used from the command line. To pull from
1707 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1708 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1708 local_path'.
1709 local_path'.
1709
1710
1710 Options containing colons (":") denote sub-options that can influence
1711 Options containing colons (":") denote sub-options that can influence
1711 behavior for that specific path. Example:
1712 behavior for that specific path. Example:
1712
1713
1713 [paths]
1714 [paths]
1714 my_server = https://example.com/my_path
1715 my_server = https://example.com/my_path
1715 my_server:pushurl = ssh://example.com/my_path
1716 my_server:pushurl = ssh://example.com/my_path
1716
1717
1717 The following sub-options can be defined:
1718 The following sub-options can be defined:
1718
1719
1719 "pushurl"
1720 "pushurl"
1720 The URL to use for push operations. If not defined, the location
1721 The URL to use for push operations. If not defined, the location
1721 defined by the path's main entry is used.
1722 defined by the path's main entry is used.
1722
1723
1723 "pushrev"
1724 "pushrev"
1724 A revset defining which revisions to push by default.
1725 A revset defining which revisions to push by default.
1725
1726
1726 When 'hg push' is executed without a "-r" argument, the revset defined
1727 When 'hg push' is executed without a "-r" argument, the revset defined
1727 by this sub-option is evaluated to determine what to push.
1728 by this sub-option is evaluated to determine what to push.
1728
1729
1729 For example, a value of "." will push the working directory's revision
1730 For example, a value of "." will push the working directory's revision
1730 by default.
1731 by default.
1731
1732
1732 Revsets specifying bookmarks will not result in the bookmark being
1733 Revsets specifying bookmarks will not result in the bookmark being
1733 pushed.
1734 pushed.
1734
1735
1735 The following special named paths exist:
1736 The following special named paths exist:
1736
1737
1737 "default"
1738 "default"
1738 The URL or directory to use when no source or remote is specified.
1739 The URL or directory to use when no source or remote is specified.
1739
1740
1740 'hg clone' will automatically define this path to the location the
1741 'hg clone' will automatically define this path to the location the
1741 repository was cloned from.
1742 repository was cloned from.
1742
1743
1743 "default-push"
1744 "default-push"
1744 (deprecated) The URL or directory for the default 'hg push' location.
1745 (deprecated) The URL or directory for the default 'hg push' location.
1745 "default:pushurl" should be used instead.
1746 "default:pushurl" should be used instead.
1746
1747
1747 $ hg help glossary.mcguffin
1748 $ hg help glossary.mcguffin
1748 abort: help section not found: glossary.mcguffin
1749 abort: help section not found: glossary.mcguffin
1749 [255]
1750 [255]
1750
1751
1751 $ hg help glossary.mc.guffin
1752 $ hg help glossary.mc.guffin
1752 abort: help section not found: glossary.mc.guffin
1753 abort: help section not found: glossary.mc.guffin
1753 [255]
1754 [255]
1754
1755
1755 $ hg help template.files
1756 $ hg help template.files
1756 files List of strings. All files modified, added, or removed by
1757 files List of strings. All files modified, added, or removed by
1757 this changeset.
1758 this changeset.
1758 files(pattern)
1759 files(pattern)
1759 All files of the current changeset matching the pattern. See
1760 All files of the current changeset matching the pattern. See
1760 'hg help patterns'.
1761 'hg help patterns'.
1761
1762
1762 Test section lookup by translated message
1763 Test section lookup by translated message
1763
1764
1764 str.lower() instead of encoding.lower(str) on translated message might
1765 str.lower() instead of encoding.lower(str) on translated message might
1765 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1766 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1766 as the second or later byte of multi-byte character.
1767 as the second or later byte of multi-byte character.
1767
1768
1768 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1769 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1769 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1770 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1770 replacement makes message meaningless.
1771 replacement makes message meaningless.
1771
1772
1772 This tests that section lookup by translated string isn't broken by
1773 This tests that section lookup by translated string isn't broken by
1773 such str.lower().
1774 such str.lower().
1774
1775
1775 $ "$PYTHON" <<EOF
1776 $ "$PYTHON" <<EOF
1776 > def escape(s):
1777 > def escape(s):
1777 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1778 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1778 > # translation of "record" in ja_JP.cp932
1779 > # translation of "record" in ja_JP.cp932
1779 > upper = "\x8bL\x98^"
1780 > upper = "\x8bL\x98^"
1780 > # str.lower()-ed section name should be treated as different one
1781 > # str.lower()-ed section name should be treated as different one
1781 > lower = "\x8bl\x98^"
1782 > lower = "\x8bl\x98^"
1782 > with open('ambiguous.py', 'w') as fp:
1783 > with open('ambiguous.py', 'w') as fp:
1783 > fp.write("""# ambiguous section names in ja_JP.cp932
1784 > fp.write("""# ambiguous section names in ja_JP.cp932
1784 > u'''summary of extension
1785 > u'''summary of extension
1785 >
1786 >
1786 > %s
1787 > %s
1787 > ----
1788 > ----
1788 >
1789 >
1789 > Upper name should show only this message
1790 > Upper name should show only this message
1790 >
1791 >
1791 > %s
1792 > %s
1792 > ----
1793 > ----
1793 >
1794 >
1794 > Lower name should show only this message
1795 > Lower name should show only this message
1795 >
1796 >
1796 > subsequent section
1797 > subsequent section
1797 > ------------------
1798 > ------------------
1798 >
1799 >
1799 > This should be hidden at 'hg help ambiguous' with section name.
1800 > This should be hidden at 'hg help ambiguous' with section name.
1800 > '''
1801 > '''
1801 > """ % (escape(upper), escape(lower)))
1802 > """ % (escape(upper), escape(lower)))
1802 > EOF
1803 > EOF
1803
1804
1804 $ cat >> $HGRCPATH <<EOF
1805 $ cat >> $HGRCPATH <<EOF
1805 > [extensions]
1806 > [extensions]
1806 > ambiguous = ./ambiguous.py
1807 > ambiguous = ./ambiguous.py
1807 > EOF
1808 > EOF
1808
1809
1809 $ "$PYTHON" <<EOF | sh
1810 $ "$PYTHON" <<EOF | sh
1810 > upper = "\x8bL\x98^"
1811 > upper = "\x8bL\x98^"
1811 > print("hg --encoding cp932 help -e ambiguous.%s" % upper)
1812 > print("hg --encoding cp932 help -e ambiguous.%s" % upper)
1812 > EOF
1813 > EOF
1813 \x8bL\x98^ (esc)
1814 \x8bL\x98^ (esc)
1814 ----
1815 ----
1815
1816
1816 Upper name should show only this message
1817 Upper name should show only this message
1817
1818
1818
1819
1819 $ "$PYTHON" <<EOF | sh
1820 $ "$PYTHON" <<EOF | sh
1820 > lower = "\x8bl\x98^"
1821 > lower = "\x8bl\x98^"
1821 > print("hg --encoding cp932 help -e ambiguous.%s" % lower)
1822 > print("hg --encoding cp932 help -e ambiguous.%s" % lower)
1822 > EOF
1823 > EOF
1823 \x8bl\x98^ (esc)
1824 \x8bl\x98^ (esc)
1824 ----
1825 ----
1825
1826
1826 Lower name should show only this message
1827 Lower name should show only this message
1827
1828
1828
1829
1829 $ cat >> $HGRCPATH <<EOF
1830 $ cat >> $HGRCPATH <<EOF
1830 > [extensions]
1831 > [extensions]
1831 > ambiguous = !
1832 > ambiguous = !
1832 > EOF
1833 > EOF
1833
1834
1834 Show help content of disabled extensions
1835 Show help content of disabled extensions
1835
1836
1836 $ cat >> $HGRCPATH <<EOF
1837 $ cat >> $HGRCPATH <<EOF
1837 > [extensions]
1838 > [extensions]
1838 > ambiguous = !./ambiguous.py
1839 > ambiguous = !./ambiguous.py
1839 > EOF
1840 > EOF
1840 $ hg help -e ambiguous
1841 $ hg help -e ambiguous
1841 ambiguous extension - (no help text available)
1842 ambiguous extension - (no help text available)
1842
1843
1843 (use 'hg help extensions' for information on enabling extensions)
1844 (use 'hg help extensions' for information on enabling extensions)
1844
1845
1845 Test dynamic list of merge tools only shows up once
1846 Test dynamic list of merge tools only shows up once
1846 $ hg help merge-tools
1847 $ hg help merge-tools
1847 Merge Tools
1848 Merge Tools
1848 """""""""""
1849 """""""""""
1849
1850
1850 To merge files Mercurial uses merge tools.
1851 To merge files Mercurial uses merge tools.
1851
1852
1852 A merge tool combines two different versions of a file into a merged file.
1853 A merge tool combines two different versions of a file into a merged file.
1853 Merge tools are given the two files and the greatest common ancestor of
1854 Merge tools are given the two files and the greatest common ancestor of
1854 the two file versions, so they can determine the changes made on both
1855 the two file versions, so they can determine the changes made on both
1855 branches.
1856 branches.
1856
1857
1857 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1858 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1858 backout' and in several extensions.
1859 backout' and in several extensions.
1859
1860
1860 Usually, the merge tool tries to automatically reconcile the files by
1861 Usually, the merge tool tries to automatically reconcile the files by
1861 combining all non-overlapping changes that occurred separately in the two
1862 combining all non-overlapping changes that occurred separately in the two
1862 different evolutions of the same initial base file. Furthermore, some
1863 different evolutions of the same initial base file. Furthermore, some
1863 interactive merge programs make it easier to manually resolve conflicting
1864 interactive merge programs make it easier to manually resolve conflicting
1864 merges, either in a graphical way, or by inserting some conflict markers.
1865 merges, either in a graphical way, or by inserting some conflict markers.
1865 Mercurial does not include any interactive merge programs but relies on
1866 Mercurial does not include any interactive merge programs but relies on
1866 external tools for that.
1867 external tools for that.
1867
1868
1868 Available merge tools
1869 Available merge tools
1869 =====================
1870 =====================
1870
1871
1871 External merge tools and their properties are configured in the merge-
1872 External merge tools and their properties are configured in the merge-
1872 tools configuration section - see hgrc(5) - but they can often just be
1873 tools configuration section - see hgrc(5) - but they can often just be
1873 named by their executable.
1874 named by their executable.
1874
1875
1875 A merge tool is generally usable if its executable can be found on the
1876 A merge tool is generally usable if its executable can be found on the
1876 system and if it can handle the merge. The executable is found if it is an
1877 system and if it can handle the merge. The executable is found if it is an
1877 absolute or relative executable path or the name of an application in the
1878 absolute or relative executable path or the name of an application in the
1878 executable search path. The tool is assumed to be able to handle the merge
1879 executable search path. The tool is assumed to be able to handle the merge
1879 if it can handle symlinks if the file is a symlink, if it can handle
1880 if it can handle symlinks if the file is a symlink, if it can handle
1880 binary files if the file is binary, and if a GUI is available if the tool
1881 binary files if the file is binary, and if a GUI is available if the tool
1881 requires a GUI.
1882 requires a GUI.
1882
1883
1883 There are some internal merge tools which can be used. The internal merge
1884 There are some internal merge tools which can be used. The internal merge
1884 tools are:
1885 tools are:
1885
1886
1886 ":dump"
1887 ":dump"
1887 Creates three versions of the files to merge, containing the contents of
1888 Creates three versions of the files to merge, containing the contents of
1888 local, other and base. These files can then be used to perform a merge
1889 local, other and base. These files can then be used to perform a merge
1889 manually. If the file to be merged is named "a.txt", these files will
1890 manually. If the file to be merged is named "a.txt", these files will
1890 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1891 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1891 they will be placed in the same directory as "a.txt".
1892 they will be placed in the same directory as "a.txt".
1892
1893
1893 This implies premerge. Therefore, files aren't dumped, if premerge runs
1894 This implies premerge. Therefore, files aren't dumped, if premerge runs
1894 successfully. Use :forcedump to forcibly write files out.
1895 successfully. Use :forcedump to forcibly write files out.
1895
1896
1896 (actual capabilities: binary, symlink)
1897 (actual capabilities: binary, symlink)
1897
1898
1898 ":fail"
1899 ":fail"
1899 Rather than attempting to merge files that were modified on both
1900 Rather than attempting to merge files that were modified on both
1900 branches, it marks them as unresolved. The resolve command must be used
1901 branches, it marks them as unresolved. The resolve command must be used
1901 to resolve these conflicts.
1902 to resolve these conflicts.
1902
1903
1903 (actual capabilities: binary, symlink)
1904 (actual capabilities: binary, symlink)
1904
1905
1905 ":forcedump"
1906 ":forcedump"
1906 Creates three versions of the files as same as :dump, but omits
1907 Creates three versions of the files as same as :dump, but omits
1907 premerge.
1908 premerge.
1908
1909
1909 (actual capabilities: binary, symlink)
1910 (actual capabilities: binary, symlink)
1910
1911
1911 ":local"
1912 ":local"
1912 Uses the local 'p1()' version of files as the merged version.
1913 Uses the local 'p1()' version of files as the merged version.
1913
1914
1914 (actual capabilities: binary, symlink)
1915 (actual capabilities: binary, symlink)
1915
1916
1916 ":merge"
1917 ":merge"
1917 Uses the internal non-interactive simple merge algorithm for merging
1918 Uses the internal non-interactive simple merge algorithm for merging
1918 files. It will fail if there are any conflicts and leave markers in the
1919 files. It will fail if there are any conflicts and leave markers in the
1919 partially merged file. Markers will have two sections, one for each side
1920 partially merged file. Markers will have two sections, one for each side
1920 of merge.
1921 of merge.
1921
1922
1922 ":merge-local"
1923 ":merge-local"
1923 Like :merge, but resolve all conflicts non-interactively in favor of the
1924 Like :merge, but resolve all conflicts non-interactively in favor of the
1924 local 'p1()' changes.
1925 local 'p1()' changes.
1925
1926
1926 ":merge-other"
1927 ":merge-other"
1927 Like :merge, but resolve all conflicts non-interactively in favor of the
1928 Like :merge, but resolve all conflicts non-interactively in favor of the
1928 other 'p2()' changes.
1929 other 'p2()' changes.
1929
1930
1930 ":merge3"
1931 ":merge3"
1931 Uses the internal non-interactive simple merge algorithm for merging
1932 Uses the internal non-interactive simple merge algorithm for merging
1932 files. It will fail if there are any conflicts and leave markers in the
1933 files. It will fail if there are any conflicts and leave markers in the
1933 partially merged file. Marker will have three sections, one from each
1934 partially merged file. Marker will have three sections, one from each
1934 side of the merge and one for the base content.
1935 side of the merge and one for the base content.
1935
1936
1936 ":other"
1937 ":other"
1937 Uses the other 'p2()' version of files as the merged version.
1938 Uses the other 'p2()' version of files as the merged version.
1938
1939
1939 (actual capabilities: binary, symlink)
1940 (actual capabilities: binary, symlink)
1940
1941
1941 ":prompt"
1942 ":prompt"
1942 Asks the user which of the local 'p1()' or the other 'p2()' version to
1943 Asks the user which of the local 'p1()' or the other 'p2()' version to
1943 keep as the merged version.
1944 keep as the merged version.
1944
1945
1945 (actual capabilities: binary, symlink)
1946 (actual capabilities: binary, symlink)
1946
1947
1947 ":tagmerge"
1948 ":tagmerge"
1948 Uses the internal tag merge algorithm (experimental).
1949 Uses the internal tag merge algorithm (experimental).
1949
1950
1950 ":union"
1951 ":union"
1951 Uses the internal non-interactive simple merge algorithm for merging
1952 Uses the internal non-interactive simple merge algorithm for merging
1952 files. It will use both left and right sides for conflict regions. No
1953 files. It will use both left and right sides for conflict regions. No
1953 markers are inserted.
1954 markers are inserted.
1954
1955
1955 Internal tools are always available and do not require a GUI but will by
1956 Internal tools are always available and do not require a GUI but will by
1956 default not handle symlinks or binary files. See next section for detail
1957 default not handle symlinks or binary files. See next section for detail
1957 about "actual capabilities" described above.
1958 about "actual capabilities" described above.
1958
1959
1959 Choosing a merge tool
1960 Choosing a merge tool
1960 =====================
1961 =====================
1961
1962
1962 Mercurial uses these rules when deciding which merge tool to use:
1963 Mercurial uses these rules when deciding which merge tool to use:
1963
1964
1964 1. If a tool has been specified with the --tool option to merge or
1965 1. If a tool has been specified with the --tool option to merge or
1965 resolve, it is used. If it is the name of a tool in the merge-tools
1966 resolve, it is used. If it is the name of a tool in the merge-tools
1966 configuration, its configuration is used. Otherwise the specified tool
1967 configuration, its configuration is used. Otherwise the specified tool
1967 must be executable by the shell.
1968 must be executable by the shell.
1968 2. If the "HGMERGE" environment variable is present, its value is used and
1969 2. If the "HGMERGE" environment variable is present, its value is used and
1969 must be executable by the shell.
1970 must be executable by the shell.
1970 3. If the filename of the file to be merged matches any of the patterns in
1971 3. If the filename of the file to be merged matches any of the patterns in
1971 the merge-patterns configuration section, the first usable merge tool
1972 the merge-patterns configuration section, the first usable merge tool
1972 corresponding to a matching pattern is used.
1973 corresponding to a matching pattern is used.
1973 4. If ui.merge is set it will be considered next. If the value is not the
1974 4. If ui.merge is set it will be considered next. If the value is not the
1974 name of a configured tool, the specified value is used and must be
1975 name of a configured tool, the specified value is used and must be
1975 executable by the shell. Otherwise the named tool is used if it is
1976 executable by the shell. Otherwise the named tool is used if it is
1976 usable.
1977 usable.
1977 5. If any usable merge tools are present in the merge-tools configuration
1978 5. If any usable merge tools are present in the merge-tools configuration
1978 section, the one with the highest priority is used.
1979 section, the one with the highest priority is used.
1979 6. If a program named "hgmerge" can be found on the system, it is used -
1980 6. If a program named "hgmerge" can be found on the system, it is used -
1980 but it will by default not be used for symlinks and binary files.
1981 but it will by default not be used for symlinks and binary files.
1981 7. If the file to be merged is not binary and is not a symlink, then
1982 7. If the file to be merged is not binary and is not a symlink, then
1982 internal ":merge" is used.
1983 internal ":merge" is used.
1983 8. Otherwise, ":prompt" is used.
1984 8. Otherwise, ":prompt" is used.
1984
1985
1985 For historical reason, Mercurial treats merge tools as below while
1986 For historical reason, Mercurial treats merge tools as below while
1986 examining rules above.
1987 examining rules above.
1987
1988
1988 step specified via binary symlink
1989 step specified via binary symlink
1989 ----------------------------------
1990 ----------------------------------
1990 1. --tool o/o o/o
1991 1. --tool o/o o/o
1991 2. HGMERGE o/o o/o
1992 2. HGMERGE o/o o/o
1992 3. merge-patterns o/o(*) x/?(*)
1993 3. merge-patterns o/o(*) x/?(*)
1993 4. ui.merge x/?(*) x/?(*)
1994 4. ui.merge x/?(*) x/?(*)
1994
1995
1995 Each capability column indicates Mercurial behavior for internal/external
1996 Each capability column indicates Mercurial behavior for internal/external
1996 merge tools at examining each rule.
1997 merge tools at examining each rule.
1997
1998
1998 - "o": "assume that a tool has capability"
1999 - "o": "assume that a tool has capability"
1999 - "x": "assume that a tool does not have capability"
2000 - "x": "assume that a tool does not have capability"
2000 - "?": "check actual capability of a tool"
2001 - "?": "check actual capability of a tool"
2001
2002
2002 If "merge.strict-capability-check" configuration is true, Mercurial checks
2003 If "merge.strict-capability-check" configuration is true, Mercurial checks
2003 capabilities of merge tools strictly in (*) cases above (= each capability
2004 capabilities of merge tools strictly in (*) cases above (= each capability
2004 column becomes "?/?"). It is false by default for backward compatibility.
2005 column becomes "?/?"). It is false by default for backward compatibility.
2005
2006
2006 Note:
2007 Note:
2007 After selecting a merge program, Mercurial will by default attempt to
2008 After selecting a merge program, Mercurial will by default attempt to
2008 merge the files using a simple merge algorithm first. Only if it
2009 merge the files using a simple merge algorithm first. Only if it
2009 doesn't succeed because of conflicting changes will Mercurial actually
2010 doesn't succeed because of conflicting changes will Mercurial actually
2010 execute the merge program. Whether to use the simple merge algorithm
2011 execute the merge program. Whether to use the simple merge algorithm
2011 first can be controlled by the premerge setting of the merge tool.
2012 first can be controlled by the premerge setting of the merge tool.
2012 Premerge is enabled by default unless the file is binary or a symlink.
2013 Premerge is enabled by default unless the file is binary or a symlink.
2013
2014
2014 See the merge-tools and ui sections of hgrc(5) for details on the
2015 See the merge-tools and ui sections of hgrc(5) for details on the
2015 configuration of merge tools.
2016 configuration of merge tools.
2016
2017
2017 Compression engines listed in `hg help bundlespec`
2018 Compression engines listed in `hg help bundlespec`
2018
2019
2019 $ hg help bundlespec | grep gzip
2020 $ hg help bundlespec | grep gzip
2020 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2021 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2021 An algorithm that produces smaller bundles than "gzip".
2022 An algorithm that produces smaller bundles than "gzip".
2022 This engine will likely produce smaller bundles than "gzip" but will be
2023 This engine will likely produce smaller bundles than "gzip" but will be
2023 "gzip"
2024 "gzip"
2024 better compression than "gzip". It also frequently yields better (?)
2025 better compression than "gzip". It also frequently yields better (?)
2025
2026
2026 Test usage of section marks in help documents
2027 Test usage of section marks in help documents
2027
2028
2028 $ cd "$TESTDIR"/../doc
2029 $ cd "$TESTDIR"/../doc
2029 $ "$PYTHON" check-seclevel.py
2030 $ "$PYTHON" check-seclevel.py
2030 $ cd $TESTTMP
2031 $ cd $TESTTMP
2031
2032
2032 #if serve
2033 #if serve
2033
2034
2034 Test the help pages in hgweb.
2035 Test the help pages in hgweb.
2035
2036
2036 Dish up an empty repo; serve it cold.
2037 Dish up an empty repo; serve it cold.
2037
2038
2038 $ hg init "$TESTTMP/test"
2039 $ hg init "$TESTTMP/test"
2039 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2040 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2040 $ cat hg.pid >> $DAEMON_PIDS
2041 $ cat hg.pid >> $DAEMON_PIDS
2041
2042
2042 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2043 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2043 200 Script output follows
2044 200 Script output follows
2044
2045
2045 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2046 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2046 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2047 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2047 <head>
2048 <head>
2048 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2049 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2049 <meta name="robots" content="index, nofollow" />
2050 <meta name="robots" content="index, nofollow" />
2050 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2051 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2051 <script type="text/javascript" src="/static/mercurial.js"></script>
2052 <script type="text/javascript" src="/static/mercurial.js"></script>
2052
2053
2053 <title>Help: Index</title>
2054 <title>Help: Index</title>
2054 </head>
2055 </head>
2055 <body>
2056 <body>
2056
2057
2057 <div class="container">
2058 <div class="container">
2058 <div class="menu">
2059 <div class="menu">
2059 <div class="logo">
2060 <div class="logo">
2060 <a href="https://mercurial-scm.org/">
2061 <a href="https://mercurial-scm.org/">
2061 <img src="/static/hglogo.png" alt="mercurial" /></a>
2062 <img src="/static/hglogo.png" alt="mercurial" /></a>
2062 </div>
2063 </div>
2063 <ul>
2064 <ul>
2064 <li><a href="/shortlog">log</a></li>
2065 <li><a href="/shortlog">log</a></li>
2065 <li><a href="/graph">graph</a></li>
2066 <li><a href="/graph">graph</a></li>
2066 <li><a href="/tags">tags</a></li>
2067 <li><a href="/tags">tags</a></li>
2067 <li><a href="/bookmarks">bookmarks</a></li>
2068 <li><a href="/bookmarks">bookmarks</a></li>
2068 <li><a href="/branches">branches</a></li>
2069 <li><a href="/branches">branches</a></li>
2069 </ul>
2070 </ul>
2070 <ul>
2071 <ul>
2071 <li class="active">help</li>
2072 <li class="active">help</li>
2072 </ul>
2073 </ul>
2073 </div>
2074 </div>
2074
2075
2075 <div class="main">
2076 <div class="main">
2076 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2077 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2077
2078
2078 <form class="search" action="/log">
2079 <form class="search" action="/log">
2079
2080
2080 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2081 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2081 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2082 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2082 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2083 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2083 </form>
2084 </form>
2084 <table class="bigtable">
2085 <table class="bigtable">
2085 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2086 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2086
2087
2087 <tr><td>
2088 <tr><td>
2088 <a href="/help/bundlespec">
2089 <a href="/help/bundlespec">
2089 bundlespec
2090 bundlespec
2090 </a>
2091 </a>
2091 </td><td>
2092 </td><td>
2092 Bundle File Formats
2093 Bundle File Formats
2093 </td></tr>
2094 </td></tr>
2094 <tr><td>
2095 <tr><td>
2095 <a href="/help/color">
2096 <a href="/help/color">
2096 color
2097 color
2097 </a>
2098 </a>
2098 </td><td>
2099 </td><td>
2099 Colorizing Outputs
2100 Colorizing Outputs
2100 </td></tr>
2101 </td></tr>
2101 <tr><td>
2102 <tr><td>
2102 <a href="/help/config">
2103 <a href="/help/config">
2103 config
2104 config
2104 </a>
2105 </a>
2105 </td><td>
2106 </td><td>
2106 Configuration Files
2107 Configuration Files
2107 </td></tr>
2108 </td></tr>
2108 <tr><td>
2109 <tr><td>
2109 <a href="/help/dates">
2110 <a href="/help/dates">
2110 dates
2111 dates
2111 </a>
2112 </a>
2112 </td><td>
2113 </td><td>
2113 Date Formats
2114 Date Formats
2114 </td></tr>
2115 </td></tr>
2115 <tr><td>
2116 <tr><td>
2116 <a href="/help/deprecated">
2117 <a href="/help/deprecated">
2117 deprecated
2118 deprecated
2118 </a>
2119 </a>
2119 </td><td>
2120 </td><td>
2120 Deprecated Features
2121 Deprecated Features
2121 </td></tr>
2122 </td></tr>
2122 <tr><td>
2123 <tr><td>
2123 <a href="/help/diffs">
2124 <a href="/help/diffs">
2124 diffs
2125 diffs
2125 </a>
2126 </a>
2126 </td><td>
2127 </td><td>
2127 Diff Formats
2128 Diff Formats
2128 </td></tr>
2129 </td></tr>
2129 <tr><td>
2130 <tr><td>
2130 <a href="/help/environment">
2131 <a href="/help/environment">
2131 environment
2132 environment
2132 </a>
2133 </a>
2133 </td><td>
2134 </td><td>
2134 Environment Variables
2135 Environment Variables
2135 </td></tr>
2136 </td></tr>
2136 <tr><td>
2137 <tr><td>
2137 <a href="/help/extensions">
2138 <a href="/help/extensions">
2138 extensions
2139 extensions
2139 </a>
2140 </a>
2140 </td><td>
2141 </td><td>
2141 Using Additional Features
2142 Using Additional Features
2142 </td></tr>
2143 </td></tr>
2143 <tr><td>
2144 <tr><td>
2144 <a href="/help/filesets">
2145 <a href="/help/filesets">
2145 filesets
2146 filesets
2146 </a>
2147 </a>
2147 </td><td>
2148 </td><td>
2148 Specifying File Sets
2149 Specifying File Sets
2149 </td></tr>
2150 </td></tr>
2150 <tr><td>
2151 <tr><td>
2151 <a href="/help/flags">
2152 <a href="/help/flags">
2152 flags
2153 flags
2153 </a>
2154 </a>
2154 </td><td>
2155 </td><td>
2155 Command-line flags
2156 Command-line flags
2156 </td></tr>
2157 </td></tr>
2157 <tr><td>
2158 <tr><td>
2158 <a href="/help/glossary">
2159 <a href="/help/glossary">
2159 glossary
2160 glossary
2160 </a>
2161 </a>
2161 </td><td>
2162 </td><td>
2162 Glossary
2163 Glossary
2163 </td></tr>
2164 </td></tr>
2164 <tr><td>
2165 <tr><td>
2165 <a href="/help/hgignore">
2166 <a href="/help/hgignore">
2166 hgignore
2167 hgignore
2167 </a>
2168 </a>
2168 </td><td>
2169 </td><td>
2169 Syntax for Mercurial Ignore Files
2170 Syntax for Mercurial Ignore Files
2170 </td></tr>
2171 </td></tr>
2171 <tr><td>
2172 <tr><td>
2172 <a href="/help/hgweb">
2173 <a href="/help/hgweb">
2173 hgweb
2174 hgweb
2174 </a>
2175 </a>
2175 </td><td>
2176 </td><td>
2176 Configuring hgweb
2177 Configuring hgweb
2177 </td></tr>
2178 </td></tr>
2178 <tr><td>
2179 <tr><td>
2179 <a href="/help/internals">
2180 <a href="/help/internals">
2180 internals
2181 internals
2181 </a>
2182 </a>
2182 </td><td>
2183 </td><td>
2183 Technical implementation topics
2184 Technical implementation topics
2184 </td></tr>
2185 </td></tr>
2185 <tr><td>
2186 <tr><td>
2186 <a href="/help/merge-tools">
2187 <a href="/help/merge-tools">
2187 merge-tools
2188 merge-tools
2188 </a>
2189 </a>
2189 </td><td>
2190 </td><td>
2190 Merge Tools
2191 Merge Tools
2191 </td></tr>
2192 </td></tr>
2192 <tr><td>
2193 <tr><td>
2193 <a href="/help/pager">
2194 <a href="/help/pager">
2194 pager
2195 pager
2195 </a>
2196 </a>
2196 </td><td>
2197 </td><td>
2197 Pager Support
2198 Pager Support
2198 </td></tr>
2199 </td></tr>
2199 <tr><td>
2200 <tr><td>
2200 <a href="/help/patterns">
2201 <a href="/help/patterns">
2201 patterns
2202 patterns
2202 </a>
2203 </a>
2203 </td><td>
2204 </td><td>
2204 File Name Patterns
2205 File Name Patterns
2205 </td></tr>
2206 </td></tr>
2206 <tr><td>
2207 <tr><td>
2207 <a href="/help/phases">
2208 <a href="/help/phases">
2208 phases
2209 phases
2209 </a>
2210 </a>
2210 </td><td>
2211 </td><td>
2211 Working with Phases
2212 Working with Phases
2212 </td></tr>
2213 </td></tr>
2213 <tr><td>
2214 <tr><td>
2214 <a href="/help/revisions">
2215 <a href="/help/revisions">
2215 revisions
2216 revisions
2216 </a>
2217 </a>
2217 </td><td>
2218 </td><td>
2218 Specifying Revisions
2219 Specifying Revisions
2219 </td></tr>
2220 </td></tr>
2220 <tr><td>
2221 <tr><td>
2221 <a href="/help/scripting">
2222 <a href="/help/scripting">
2222 scripting
2223 scripting
2223 </a>
2224 </a>
2224 </td><td>
2225 </td><td>
2225 Using Mercurial from scripts and automation
2226 Using Mercurial from scripts and automation
2226 </td></tr>
2227 </td></tr>
2227 <tr><td>
2228 <tr><td>
2228 <a href="/help/subrepos">
2229 <a href="/help/subrepos">
2229 subrepos
2230 subrepos
2230 </a>
2231 </a>
2231 </td><td>
2232 </td><td>
2232 Subrepositories
2233 Subrepositories
2233 </td></tr>
2234 </td></tr>
2234 <tr><td>
2235 <tr><td>
2235 <a href="/help/templating">
2236 <a href="/help/templating">
2236 templating
2237 templating
2237 </a>
2238 </a>
2238 </td><td>
2239 </td><td>
2239 Template Usage
2240 Template Usage
2240 </td></tr>
2241 </td></tr>
2241 <tr><td>
2242 <tr><td>
2242 <a href="/help/urls">
2243 <a href="/help/urls">
2243 urls
2244 urls
2244 </a>
2245 </a>
2245 </td><td>
2246 </td><td>
2246 URL Paths
2247 URL Paths
2247 </td></tr>
2248 </td></tr>
2248 <tr><td>
2249 <tr><td>
2249 <a href="/help/topic-containing-verbose">
2250 <a href="/help/topic-containing-verbose">
2250 topic-containing-verbose
2251 topic-containing-verbose
2251 </a>
2252 </a>
2252 </td><td>
2253 </td><td>
2253 This is the topic to test omit indicating.
2254 This is the topic to test omit indicating.
2254 </td></tr>
2255 </td></tr>
2255
2256
2256
2257
2257 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2258 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2258
2259
2259 <tr><td>
2260 <tr><td>
2260 <a href="/help/add">
2261 <a href="/help/add">
2261 add
2262 add
2262 </a>
2263 </a>
2263 </td><td>
2264 </td><td>
2264 add the specified files on the next commit
2265 add the specified files on the next commit
2265 </td></tr>
2266 </td></tr>
2266 <tr><td>
2267 <tr><td>
2267 <a href="/help/annotate">
2268 <a href="/help/annotate">
2268 annotate
2269 annotate
2269 </a>
2270 </a>
2270 </td><td>
2271 </td><td>
2271 show changeset information by line for each file
2272 show changeset information by line for each file
2272 </td></tr>
2273 </td></tr>
2273 <tr><td>
2274 <tr><td>
2274 <a href="/help/clone">
2275 <a href="/help/clone">
2275 clone
2276 clone
2276 </a>
2277 </a>
2277 </td><td>
2278 </td><td>
2278 make a copy of an existing repository
2279 make a copy of an existing repository
2279 </td></tr>
2280 </td></tr>
2280 <tr><td>
2281 <tr><td>
2281 <a href="/help/commit">
2282 <a href="/help/commit">
2282 commit
2283 commit
2283 </a>
2284 </a>
2284 </td><td>
2285 </td><td>
2285 commit the specified files or all outstanding changes
2286 commit the specified files or all outstanding changes
2286 </td></tr>
2287 </td></tr>
2287 <tr><td>
2288 <tr><td>
2288 <a href="/help/diff">
2289 <a href="/help/diff">
2289 diff
2290 diff
2290 </a>
2291 </a>
2291 </td><td>
2292 </td><td>
2292 diff repository (or selected files)
2293 diff repository (or selected files)
2293 </td></tr>
2294 </td></tr>
2294 <tr><td>
2295 <tr><td>
2295 <a href="/help/export">
2296 <a href="/help/export">
2296 export
2297 export
2297 </a>
2298 </a>
2298 </td><td>
2299 </td><td>
2299 dump the header and diffs for one or more changesets
2300 dump the header and diffs for one or more changesets
2300 </td></tr>
2301 </td></tr>
2301 <tr><td>
2302 <tr><td>
2302 <a href="/help/forget">
2303 <a href="/help/forget">
2303 forget
2304 forget
2304 </a>
2305 </a>
2305 </td><td>
2306 </td><td>
2306 forget the specified files on the next commit
2307 forget the specified files on the next commit
2307 </td></tr>
2308 </td></tr>
2308 <tr><td>
2309 <tr><td>
2309 <a href="/help/init">
2310 <a href="/help/init">
2310 init
2311 init
2311 </a>
2312 </a>
2312 </td><td>
2313 </td><td>
2313 create a new repository in the given directory
2314 create a new repository in the given directory
2314 </td></tr>
2315 </td></tr>
2315 <tr><td>
2316 <tr><td>
2316 <a href="/help/log">
2317 <a href="/help/log">
2317 log
2318 log
2318 </a>
2319 </a>
2319 </td><td>
2320 </td><td>
2320 show revision history of entire repository or files
2321 show revision history of entire repository or files
2321 </td></tr>
2322 </td></tr>
2322 <tr><td>
2323 <tr><td>
2323 <a href="/help/merge">
2324 <a href="/help/merge">
2324 merge
2325 merge
2325 </a>
2326 </a>
2326 </td><td>
2327 </td><td>
2327 merge another revision into working directory
2328 merge another revision into working directory
2328 </td></tr>
2329 </td></tr>
2329 <tr><td>
2330 <tr><td>
2330 <a href="/help/pull">
2331 <a href="/help/pull">
2331 pull
2332 pull
2332 </a>
2333 </a>
2333 </td><td>
2334 </td><td>
2334 pull changes from the specified source
2335 pull changes from the specified source
2335 </td></tr>
2336 </td></tr>
2336 <tr><td>
2337 <tr><td>
2337 <a href="/help/push">
2338 <a href="/help/push">
2338 push
2339 push
2339 </a>
2340 </a>
2340 </td><td>
2341 </td><td>
2341 push changes to the specified destination
2342 push changes to the specified destination
2342 </td></tr>
2343 </td></tr>
2343 <tr><td>
2344 <tr><td>
2344 <a href="/help/remove">
2345 <a href="/help/remove">
2345 remove
2346 remove
2346 </a>
2347 </a>
2347 </td><td>
2348 </td><td>
2348 remove the specified files on the next commit
2349 remove the specified files on the next commit
2349 </td></tr>
2350 </td></tr>
2350 <tr><td>
2351 <tr><td>
2351 <a href="/help/serve">
2352 <a href="/help/serve">
2352 serve
2353 serve
2353 </a>
2354 </a>
2354 </td><td>
2355 </td><td>
2355 start stand-alone webserver
2356 start stand-alone webserver
2356 </td></tr>
2357 </td></tr>
2357 <tr><td>
2358 <tr><td>
2358 <a href="/help/status">
2359 <a href="/help/status">
2359 status
2360 status
2360 </a>
2361 </a>
2361 </td><td>
2362 </td><td>
2362 show changed files in the working directory
2363 show changed files in the working directory
2363 </td></tr>
2364 </td></tr>
2364 <tr><td>
2365 <tr><td>
2365 <a href="/help/summary">
2366 <a href="/help/summary">
2366 summary
2367 summary
2367 </a>
2368 </a>
2368 </td><td>
2369 </td><td>
2369 summarize working directory state
2370 summarize working directory state
2370 </td></tr>
2371 </td></tr>
2371 <tr><td>
2372 <tr><td>
2372 <a href="/help/update">
2373 <a href="/help/update">
2373 update
2374 update
2374 </a>
2375 </a>
2375 </td><td>
2376 </td><td>
2376 update working directory (or switch revisions)
2377 update working directory (or switch revisions)
2377 </td></tr>
2378 </td></tr>
2378
2379
2379
2380
2380
2381
2381 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2382 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2382
2383
2383 <tr><td>
2384 <tr><td>
2384 <a href="/help/addremove">
2385 <a href="/help/addremove">
2385 addremove
2386 addremove
2386 </a>
2387 </a>
2387 </td><td>
2388 </td><td>
2388 add all new files, delete all missing files
2389 add all new files, delete all missing files
2389 </td></tr>
2390 </td></tr>
2390 <tr><td>
2391 <tr><td>
2391 <a href="/help/archive">
2392 <a href="/help/archive">
2392 archive
2393 archive
2393 </a>
2394 </a>
2394 </td><td>
2395 </td><td>
2395 create an unversioned archive of a repository revision
2396 create an unversioned archive of a repository revision
2396 </td></tr>
2397 </td></tr>
2397 <tr><td>
2398 <tr><td>
2398 <a href="/help/backout">
2399 <a href="/help/backout">
2399 backout
2400 backout
2400 </a>
2401 </a>
2401 </td><td>
2402 </td><td>
2402 reverse effect of earlier changeset
2403 reverse effect of earlier changeset
2403 </td></tr>
2404 </td></tr>
2404 <tr><td>
2405 <tr><td>
2405 <a href="/help/bisect">
2406 <a href="/help/bisect">
2406 bisect
2407 bisect
2407 </a>
2408 </a>
2408 </td><td>
2409 </td><td>
2409 subdivision search of changesets
2410 subdivision search of changesets
2410 </td></tr>
2411 </td></tr>
2411 <tr><td>
2412 <tr><td>
2412 <a href="/help/bookmarks">
2413 <a href="/help/bookmarks">
2413 bookmarks
2414 bookmarks
2414 </a>
2415 </a>
2415 </td><td>
2416 </td><td>
2416 create a new bookmark or list existing bookmarks
2417 create a new bookmark or list existing bookmarks
2417 </td></tr>
2418 </td></tr>
2418 <tr><td>
2419 <tr><td>
2419 <a href="/help/branch">
2420 <a href="/help/branch">
2420 branch
2421 branch
2421 </a>
2422 </a>
2422 </td><td>
2423 </td><td>
2423 set or show the current branch name
2424 set or show the current branch name
2424 </td></tr>
2425 </td></tr>
2425 <tr><td>
2426 <tr><td>
2426 <a href="/help/branches">
2427 <a href="/help/branches">
2427 branches
2428 branches
2428 </a>
2429 </a>
2429 </td><td>
2430 </td><td>
2430 list repository named branches
2431 list repository named branches
2431 </td></tr>
2432 </td></tr>
2432 <tr><td>
2433 <tr><td>
2433 <a href="/help/bundle">
2434 <a href="/help/bundle">
2434 bundle
2435 bundle
2435 </a>
2436 </a>
2436 </td><td>
2437 </td><td>
2437 create a bundle file
2438 create a bundle file
2438 </td></tr>
2439 </td></tr>
2439 <tr><td>
2440 <tr><td>
2440 <a href="/help/cat">
2441 <a href="/help/cat">
2441 cat
2442 cat
2442 </a>
2443 </a>
2443 </td><td>
2444 </td><td>
2444 output the current or given revision of files
2445 output the current or given revision of files
2445 </td></tr>
2446 </td></tr>
2446 <tr><td>
2447 <tr><td>
2447 <a href="/help/config">
2448 <a href="/help/config">
2448 config
2449 config
2449 </a>
2450 </a>
2450 </td><td>
2451 </td><td>
2451 show combined config settings from all hgrc files
2452 show combined config settings from all hgrc files
2452 </td></tr>
2453 </td></tr>
2453 <tr><td>
2454 <tr><td>
2454 <a href="/help/copy">
2455 <a href="/help/copy">
2455 copy
2456 copy
2456 </a>
2457 </a>
2457 </td><td>
2458 </td><td>
2458 mark files as copied for the next commit
2459 mark files as copied for the next commit
2459 </td></tr>
2460 </td></tr>
2460 <tr><td>
2461 <tr><td>
2461 <a href="/help/files">
2462 <a href="/help/files">
2462 files
2463 files
2463 </a>
2464 </a>
2464 </td><td>
2465 </td><td>
2465 list tracked files
2466 list tracked files
2466 </td></tr>
2467 </td></tr>
2467 <tr><td>
2468 <tr><td>
2468 <a href="/help/graft">
2469 <a href="/help/graft">
2469 graft
2470 graft
2470 </a>
2471 </a>
2471 </td><td>
2472 </td><td>
2472 copy changes from other branches onto the current branch
2473 copy changes from other branches onto the current branch
2473 </td></tr>
2474 </td></tr>
2474 <tr><td>
2475 <tr><td>
2475 <a href="/help/grep">
2476 <a href="/help/grep">
2476 grep
2477 grep
2477 </a>
2478 </a>
2478 </td><td>
2479 </td><td>
2479 search revision history for a pattern in specified files
2480 search revision history for a pattern in specified files
2480 </td></tr>
2481 </td></tr>
2481 <tr><td>
2482 <tr><td>
2482 <a href="/help/heads">
2483 <a href="/help/heads">
2483 heads
2484 heads
2484 </a>
2485 </a>
2485 </td><td>
2486 </td><td>
2486 show branch heads
2487 show branch heads
2487 </td></tr>
2488 </td></tr>
2488 <tr><td>
2489 <tr><td>
2489 <a href="/help/help">
2490 <a href="/help/help">
2490 help
2491 help
2491 </a>
2492 </a>
2492 </td><td>
2493 </td><td>
2493 show help for a given topic or a help overview
2494 show help for a given topic or a help overview
2494 </td></tr>
2495 </td></tr>
2495 <tr><td>
2496 <tr><td>
2496 <a href="/help/hgalias">
2497 <a href="/help/hgalias">
2497 hgalias
2498 hgalias
2498 </a>
2499 </a>
2499 </td><td>
2500 </td><td>
2500 summarize working directory state
2501 summarize working directory state
2501 </td></tr>
2502 </td></tr>
2502 <tr><td>
2503 <tr><td>
2503 <a href="/help/identify">
2504 <a href="/help/identify">
2504 identify
2505 identify
2505 </a>
2506 </a>
2506 </td><td>
2507 </td><td>
2507 identify the working directory or specified revision
2508 identify the working directory or specified revision
2508 </td></tr>
2509 </td></tr>
2509 <tr><td>
2510 <tr><td>
2510 <a href="/help/import">
2511 <a href="/help/import">
2511 import
2512 import
2512 </a>
2513 </a>
2513 </td><td>
2514 </td><td>
2514 import an ordered set of patches
2515 import an ordered set of patches
2515 </td></tr>
2516 </td></tr>
2516 <tr><td>
2517 <tr><td>
2517 <a href="/help/incoming">
2518 <a href="/help/incoming">
2518 incoming
2519 incoming
2519 </a>
2520 </a>
2520 </td><td>
2521 </td><td>
2521 show new changesets found in source
2522 show new changesets found in source
2522 </td></tr>
2523 </td></tr>
2523 <tr><td>
2524 <tr><td>
2524 <a href="/help/manifest">
2525 <a href="/help/manifest">
2525 manifest
2526 manifest
2526 </a>
2527 </a>
2527 </td><td>
2528 </td><td>
2528 output the current or given revision of the project manifest
2529 output the current or given revision of the project manifest
2529 </td></tr>
2530 </td></tr>
2530 <tr><td>
2531 <tr><td>
2531 <a href="/help/nohelp">
2532 <a href="/help/nohelp">
2532 nohelp
2533 nohelp
2533 </a>
2534 </a>
2534 </td><td>
2535 </td><td>
2535 (no help text available)
2536 (no help text available)
2536 </td></tr>
2537 </td></tr>
2537 <tr><td>
2538 <tr><td>
2538 <a href="/help/outgoing">
2539 <a href="/help/outgoing">
2539 outgoing
2540 outgoing
2540 </a>
2541 </a>
2541 </td><td>
2542 </td><td>
2542 show changesets not found in the destination
2543 show changesets not found in the destination
2543 </td></tr>
2544 </td></tr>
2544 <tr><td>
2545 <tr><td>
2545 <a href="/help/paths">
2546 <a href="/help/paths">
2546 paths
2547 paths
2547 </a>
2548 </a>
2548 </td><td>
2549 </td><td>
2549 show aliases for remote repositories
2550 show aliases for remote repositories
2550 </td></tr>
2551 </td></tr>
2551 <tr><td>
2552 <tr><td>
2552 <a href="/help/phase">
2553 <a href="/help/phase">
2553 phase
2554 phase
2554 </a>
2555 </a>
2555 </td><td>
2556 </td><td>
2556 set or show the current phase name
2557 set or show the current phase name
2557 </td></tr>
2558 </td></tr>
2558 <tr><td>
2559 <tr><td>
2559 <a href="/help/recover">
2560 <a href="/help/recover">
2560 recover
2561 recover
2561 </a>
2562 </a>
2562 </td><td>
2563 </td><td>
2563 roll back an interrupted transaction
2564 roll back an interrupted transaction
2564 </td></tr>
2565 </td></tr>
2565 <tr><td>
2566 <tr><td>
2566 <a href="/help/rename">
2567 <a href="/help/rename">
2567 rename
2568 rename
2568 </a>
2569 </a>
2569 </td><td>
2570 </td><td>
2570 rename files; equivalent of copy + remove
2571 rename files; equivalent of copy + remove
2571 </td></tr>
2572 </td></tr>
2572 <tr><td>
2573 <tr><td>
2573 <a href="/help/resolve">
2574 <a href="/help/resolve">
2574 resolve
2575 resolve
2575 </a>
2576 </a>
2576 </td><td>
2577 </td><td>
2577 redo merges or set/view the merge status of files
2578 redo merges or set/view the merge status of files
2578 </td></tr>
2579 </td></tr>
2579 <tr><td>
2580 <tr><td>
2580 <a href="/help/revert">
2581 <a href="/help/revert">
2581 revert
2582 revert
2582 </a>
2583 </a>
2583 </td><td>
2584 </td><td>
2584 restore files to their checkout state
2585 restore files to their checkout state
2585 </td></tr>
2586 </td></tr>
2586 <tr><td>
2587 <tr><td>
2587 <a href="/help/root">
2588 <a href="/help/root">
2588 root
2589 root
2589 </a>
2590 </a>
2590 </td><td>
2591 </td><td>
2591 print the root (top) of the current working directory
2592 print the root (top) of the current working directory
2592 </td></tr>
2593 </td></tr>
2593 <tr><td>
2594 <tr><td>
2594 <a href="/help/shellalias">
2595 <a href="/help/shellalias">
2595 shellalias
2596 shellalias
2596 </a>
2597 </a>
2597 </td><td>
2598 </td><td>
2598 (no help text available)
2599 (no help text available)
2599 </td></tr>
2600 </td></tr>
2600 <tr><td>
2601 <tr><td>
2601 <a href="/help/tag">
2602 <a href="/help/tag">
2602 tag
2603 tag
2603 </a>
2604 </a>
2604 </td><td>
2605 </td><td>
2605 add one or more tags for the current or given revision
2606 add one or more tags for the current or given revision
2606 </td></tr>
2607 </td></tr>
2607 <tr><td>
2608 <tr><td>
2608 <a href="/help/tags">
2609 <a href="/help/tags">
2609 tags
2610 tags
2610 </a>
2611 </a>
2611 </td><td>
2612 </td><td>
2612 list repository tags
2613 list repository tags
2613 </td></tr>
2614 </td></tr>
2614 <tr><td>
2615 <tr><td>
2615 <a href="/help/unbundle">
2616 <a href="/help/unbundle">
2616 unbundle
2617 unbundle
2617 </a>
2618 </a>
2618 </td><td>
2619 </td><td>
2619 apply one or more bundle files
2620 apply one or more bundle files
2620 </td></tr>
2621 </td></tr>
2621 <tr><td>
2622 <tr><td>
2622 <a href="/help/verify">
2623 <a href="/help/verify">
2623 verify
2624 verify
2624 </a>
2625 </a>
2625 </td><td>
2626 </td><td>
2626 verify the integrity of the repository
2627 verify the integrity of the repository
2627 </td></tr>
2628 </td></tr>
2628 <tr><td>
2629 <tr><td>
2629 <a href="/help/version">
2630 <a href="/help/version">
2630 version
2631 version
2631 </a>
2632 </a>
2632 </td><td>
2633 </td><td>
2633 output version and copyright information
2634 output version and copyright information
2634 </td></tr>
2635 </td></tr>
2635
2636
2636
2637
2637 </table>
2638 </table>
2638 </div>
2639 </div>
2639 </div>
2640 </div>
2640
2641
2641
2642
2642
2643
2643 </body>
2644 </body>
2644 </html>
2645 </html>
2645
2646
2646
2647
2647 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2648 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2648 200 Script output follows
2649 200 Script output follows
2649
2650
2650 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2651 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2651 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2652 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2652 <head>
2653 <head>
2653 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2654 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2654 <meta name="robots" content="index, nofollow" />
2655 <meta name="robots" content="index, nofollow" />
2655 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2656 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2656 <script type="text/javascript" src="/static/mercurial.js"></script>
2657 <script type="text/javascript" src="/static/mercurial.js"></script>
2657
2658
2658 <title>Help: add</title>
2659 <title>Help: add</title>
2659 </head>
2660 </head>
2660 <body>
2661 <body>
2661
2662
2662 <div class="container">
2663 <div class="container">
2663 <div class="menu">
2664 <div class="menu">
2664 <div class="logo">
2665 <div class="logo">
2665 <a href="https://mercurial-scm.org/">
2666 <a href="https://mercurial-scm.org/">
2666 <img src="/static/hglogo.png" alt="mercurial" /></a>
2667 <img src="/static/hglogo.png" alt="mercurial" /></a>
2667 </div>
2668 </div>
2668 <ul>
2669 <ul>
2669 <li><a href="/shortlog">log</a></li>
2670 <li><a href="/shortlog">log</a></li>
2670 <li><a href="/graph">graph</a></li>
2671 <li><a href="/graph">graph</a></li>
2671 <li><a href="/tags">tags</a></li>
2672 <li><a href="/tags">tags</a></li>
2672 <li><a href="/bookmarks">bookmarks</a></li>
2673 <li><a href="/bookmarks">bookmarks</a></li>
2673 <li><a href="/branches">branches</a></li>
2674 <li><a href="/branches">branches</a></li>
2674 </ul>
2675 </ul>
2675 <ul>
2676 <ul>
2676 <li class="active"><a href="/help">help</a></li>
2677 <li class="active"><a href="/help">help</a></li>
2677 </ul>
2678 </ul>
2678 </div>
2679 </div>
2679
2680
2680 <div class="main">
2681 <div class="main">
2681 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2682 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2682 <h3>Help: add</h3>
2683 <h3>Help: add</h3>
2683
2684
2684 <form class="search" action="/log">
2685 <form class="search" action="/log">
2685
2686
2686 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2687 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2687 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2688 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2688 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2689 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2689 </form>
2690 </form>
2690 <div id="doc">
2691 <div id="doc">
2691 <p>
2692 <p>
2692 hg add [OPTION]... [FILE]...
2693 hg add [OPTION]... [FILE]...
2693 </p>
2694 </p>
2694 <p>
2695 <p>
2695 add the specified files on the next commit
2696 add the specified files on the next commit
2696 </p>
2697 </p>
2697 <p>
2698 <p>
2698 Schedule files to be version controlled and added to the
2699 Schedule files to be version controlled and added to the
2699 repository.
2700 repository.
2700 </p>
2701 </p>
2701 <p>
2702 <p>
2702 The files will be added to the repository at the next commit. To
2703 The files will be added to the repository at the next commit. To
2703 undo an add before that, see 'hg forget'.
2704 undo an add before that, see 'hg forget'.
2704 </p>
2705 </p>
2705 <p>
2706 <p>
2706 If no names are given, add all files to the repository (except
2707 If no names are given, add all files to the repository (except
2707 files matching &quot;.hgignore&quot;).
2708 files matching &quot;.hgignore&quot;).
2708 </p>
2709 </p>
2709 <p>
2710 <p>
2710 Examples:
2711 Examples:
2711 </p>
2712 </p>
2712 <ul>
2713 <ul>
2713 <li> New (unknown) files are added automatically by 'hg add':
2714 <li> New (unknown) files are added automatically by 'hg add':
2714 <pre>
2715 <pre>
2715 \$ ls (re)
2716 \$ ls (re)
2716 foo.c
2717 foo.c
2717 \$ hg status (re)
2718 \$ hg status (re)
2718 ? foo.c
2719 ? foo.c
2719 \$ hg add (re)
2720 \$ hg add (re)
2720 adding foo.c
2721 adding foo.c
2721 \$ hg status (re)
2722 \$ hg status (re)
2722 A foo.c
2723 A foo.c
2723 </pre>
2724 </pre>
2724 <li> Specific files to be added can be specified:
2725 <li> Specific files to be added can be specified:
2725 <pre>
2726 <pre>
2726 \$ ls (re)
2727 \$ ls (re)
2727 bar.c foo.c
2728 bar.c foo.c
2728 \$ hg status (re)
2729 \$ hg status (re)
2729 ? bar.c
2730 ? bar.c
2730 ? foo.c
2731 ? foo.c
2731 \$ hg add bar.c (re)
2732 \$ hg add bar.c (re)
2732 \$ hg status (re)
2733 \$ hg status (re)
2733 A bar.c
2734 A bar.c
2734 ? foo.c
2735 ? foo.c
2735 </pre>
2736 </pre>
2736 </ul>
2737 </ul>
2737 <p>
2738 <p>
2738 Returns 0 if all files are successfully added.
2739 Returns 0 if all files are successfully added.
2739 </p>
2740 </p>
2740 <p>
2741 <p>
2741 options ([+] can be repeated):
2742 options ([+] can be repeated):
2742 </p>
2743 </p>
2743 <table>
2744 <table>
2744 <tr><td>-I</td>
2745 <tr><td>-I</td>
2745 <td>--include PATTERN [+]</td>
2746 <td>--include PATTERN [+]</td>
2746 <td>include names matching the given patterns</td></tr>
2747 <td>include names matching the given patterns</td></tr>
2747 <tr><td>-X</td>
2748 <tr><td>-X</td>
2748 <td>--exclude PATTERN [+]</td>
2749 <td>--exclude PATTERN [+]</td>
2749 <td>exclude names matching the given patterns</td></tr>
2750 <td>exclude names matching the given patterns</td></tr>
2750 <tr><td>-S</td>
2751 <tr><td>-S</td>
2751 <td>--subrepos</td>
2752 <td>--subrepos</td>
2752 <td>recurse into subrepositories</td></tr>
2753 <td>recurse into subrepositories</td></tr>
2753 <tr><td>-n</td>
2754 <tr><td>-n</td>
2754 <td>--dry-run</td>
2755 <td>--dry-run</td>
2755 <td>do not perform actions, just print output</td></tr>
2756 <td>do not perform actions, just print output</td></tr>
2756 </table>
2757 </table>
2757 <p>
2758 <p>
2758 global options ([+] can be repeated):
2759 global options ([+] can be repeated):
2759 </p>
2760 </p>
2760 <table>
2761 <table>
2761 <tr><td>-R</td>
2762 <tr><td>-R</td>
2762 <td>--repository REPO</td>
2763 <td>--repository REPO</td>
2763 <td>repository root directory or name of overlay bundle file</td></tr>
2764 <td>repository root directory or name of overlay bundle file</td></tr>
2764 <tr><td></td>
2765 <tr><td></td>
2765 <td>--cwd DIR</td>
2766 <td>--cwd DIR</td>
2766 <td>change working directory</td></tr>
2767 <td>change working directory</td></tr>
2767 <tr><td>-y</td>
2768 <tr><td>-y</td>
2768 <td>--noninteractive</td>
2769 <td>--noninteractive</td>
2769 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2770 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2770 <tr><td>-q</td>
2771 <tr><td>-q</td>
2771 <td>--quiet</td>
2772 <td>--quiet</td>
2772 <td>suppress output</td></tr>
2773 <td>suppress output</td></tr>
2773 <tr><td>-v</td>
2774 <tr><td>-v</td>
2774 <td>--verbose</td>
2775 <td>--verbose</td>
2775 <td>enable additional output</td></tr>
2776 <td>enable additional output</td></tr>
2776 <tr><td></td>
2777 <tr><td></td>
2777 <td>--color TYPE</td>
2778 <td>--color TYPE</td>
2778 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2779 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2779 <tr><td></td>
2780 <tr><td></td>
2780 <td>--config CONFIG [+]</td>
2781 <td>--config CONFIG [+]</td>
2781 <td>set/override config option (use 'section.name=value')</td></tr>
2782 <td>set/override config option (use 'section.name=value')</td></tr>
2782 <tr><td></td>
2783 <tr><td></td>
2783 <td>--debug</td>
2784 <td>--debug</td>
2784 <td>enable debugging output</td></tr>
2785 <td>enable debugging output</td></tr>
2785 <tr><td></td>
2786 <tr><td></td>
2786 <td>--debugger</td>
2787 <td>--debugger</td>
2787 <td>start debugger</td></tr>
2788 <td>start debugger</td></tr>
2788 <tr><td></td>
2789 <tr><td></td>
2789 <td>--encoding ENCODE</td>
2790 <td>--encoding ENCODE</td>
2790 <td>set the charset encoding (default: ascii)</td></tr>
2791 <td>set the charset encoding (default: ascii)</td></tr>
2791 <tr><td></td>
2792 <tr><td></td>
2792 <td>--encodingmode MODE</td>
2793 <td>--encodingmode MODE</td>
2793 <td>set the charset encoding mode (default: strict)</td></tr>
2794 <td>set the charset encoding mode (default: strict)</td></tr>
2794 <tr><td></td>
2795 <tr><td></td>
2795 <td>--traceback</td>
2796 <td>--traceback</td>
2796 <td>always print a traceback on exception</td></tr>
2797 <td>always print a traceback on exception</td></tr>
2797 <tr><td></td>
2798 <tr><td></td>
2798 <td>--time</td>
2799 <td>--time</td>
2799 <td>time how long the command takes</td></tr>
2800 <td>time how long the command takes</td></tr>
2800 <tr><td></td>
2801 <tr><td></td>
2801 <td>--profile</td>
2802 <td>--profile</td>
2802 <td>print command execution profile</td></tr>
2803 <td>print command execution profile</td></tr>
2803 <tr><td></td>
2804 <tr><td></td>
2804 <td>--version</td>
2805 <td>--version</td>
2805 <td>output version information and exit</td></tr>
2806 <td>output version information and exit</td></tr>
2806 <tr><td>-h</td>
2807 <tr><td>-h</td>
2807 <td>--help</td>
2808 <td>--help</td>
2808 <td>display help and exit</td></tr>
2809 <td>display help and exit</td></tr>
2809 <tr><td></td>
2810 <tr><td></td>
2810 <td>--hidden</td>
2811 <td>--hidden</td>
2811 <td>consider hidden changesets</td></tr>
2812 <td>consider hidden changesets</td></tr>
2812 <tr><td></td>
2813 <tr><td></td>
2813 <td>--pager TYPE</td>
2814 <td>--pager TYPE</td>
2814 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2815 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2815 </table>
2816 </table>
2816
2817
2817 </div>
2818 </div>
2818 </div>
2819 </div>
2819 </div>
2820 </div>
2820
2821
2821
2822
2822
2823
2823 </body>
2824 </body>
2824 </html>
2825 </html>
2825
2826
2826
2827
2827 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2828 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2828 200 Script output follows
2829 200 Script output follows
2829
2830
2830 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2831 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2831 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2832 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2832 <head>
2833 <head>
2833 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2834 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2834 <meta name="robots" content="index, nofollow" />
2835 <meta name="robots" content="index, nofollow" />
2835 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2836 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2836 <script type="text/javascript" src="/static/mercurial.js"></script>
2837 <script type="text/javascript" src="/static/mercurial.js"></script>
2837
2838
2838 <title>Help: remove</title>
2839 <title>Help: remove</title>
2839 </head>
2840 </head>
2840 <body>
2841 <body>
2841
2842
2842 <div class="container">
2843 <div class="container">
2843 <div class="menu">
2844 <div class="menu">
2844 <div class="logo">
2845 <div class="logo">
2845 <a href="https://mercurial-scm.org/">
2846 <a href="https://mercurial-scm.org/">
2846 <img src="/static/hglogo.png" alt="mercurial" /></a>
2847 <img src="/static/hglogo.png" alt="mercurial" /></a>
2847 </div>
2848 </div>
2848 <ul>
2849 <ul>
2849 <li><a href="/shortlog">log</a></li>
2850 <li><a href="/shortlog">log</a></li>
2850 <li><a href="/graph">graph</a></li>
2851 <li><a href="/graph">graph</a></li>
2851 <li><a href="/tags">tags</a></li>
2852 <li><a href="/tags">tags</a></li>
2852 <li><a href="/bookmarks">bookmarks</a></li>
2853 <li><a href="/bookmarks">bookmarks</a></li>
2853 <li><a href="/branches">branches</a></li>
2854 <li><a href="/branches">branches</a></li>
2854 </ul>
2855 </ul>
2855 <ul>
2856 <ul>
2856 <li class="active"><a href="/help">help</a></li>
2857 <li class="active"><a href="/help">help</a></li>
2857 </ul>
2858 </ul>
2858 </div>
2859 </div>
2859
2860
2860 <div class="main">
2861 <div class="main">
2861 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2862 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2862 <h3>Help: remove</h3>
2863 <h3>Help: remove</h3>
2863
2864
2864 <form class="search" action="/log">
2865 <form class="search" action="/log">
2865
2866
2866 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2867 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2867 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2868 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2868 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2869 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2869 </form>
2870 </form>
2870 <div id="doc">
2871 <div id="doc">
2871 <p>
2872 <p>
2872 hg remove [OPTION]... FILE...
2873 hg remove [OPTION]... FILE...
2873 </p>
2874 </p>
2874 <p>
2875 <p>
2875 aliases: rm
2876 aliases: rm
2876 </p>
2877 </p>
2877 <p>
2878 <p>
2878 remove the specified files on the next commit
2879 remove the specified files on the next commit
2879 </p>
2880 </p>
2880 <p>
2881 <p>
2881 Schedule the indicated files for removal from the current branch.
2882 Schedule the indicated files for removal from the current branch.
2882 </p>
2883 </p>
2883 <p>
2884 <p>
2884 This command schedules the files to be removed at the next commit.
2885 This command schedules the files to be removed at the next commit.
2885 To undo a remove before that, see 'hg revert'. To undo added
2886 To undo a remove before that, see 'hg revert'. To undo added
2886 files, see 'hg forget'.
2887 files, see 'hg forget'.
2887 </p>
2888 </p>
2888 <p>
2889 <p>
2889 -A/--after can be used to remove only files that have already
2890 -A/--after can be used to remove only files that have already
2890 been deleted, -f/--force can be used to force deletion, and -Af
2891 been deleted, -f/--force can be used to force deletion, and -Af
2891 can be used to remove files from the next revision without
2892 can be used to remove files from the next revision without
2892 deleting them from the working directory.
2893 deleting them from the working directory.
2893 </p>
2894 </p>
2894 <p>
2895 <p>
2895 The following table details the behavior of remove for different
2896 The following table details the behavior of remove for different
2896 file states (columns) and option combinations (rows). The file
2897 file states (columns) and option combinations (rows). The file
2897 states are Added [A], Clean [C], Modified [M] and Missing [!]
2898 states are Added [A], Clean [C], Modified [M] and Missing [!]
2898 (as reported by 'hg status'). The actions are Warn, Remove
2899 (as reported by 'hg status'). The actions are Warn, Remove
2899 (from branch) and Delete (from disk):
2900 (from branch) and Delete (from disk):
2900 </p>
2901 </p>
2901 <table>
2902 <table>
2902 <tr><td>opt/state</td>
2903 <tr><td>opt/state</td>
2903 <td>A</td>
2904 <td>A</td>
2904 <td>C</td>
2905 <td>C</td>
2905 <td>M</td>
2906 <td>M</td>
2906 <td>!</td></tr>
2907 <td>!</td></tr>
2907 <tr><td>none</td>
2908 <tr><td>none</td>
2908 <td>W</td>
2909 <td>W</td>
2909 <td>RD</td>
2910 <td>RD</td>
2910 <td>W</td>
2911 <td>W</td>
2911 <td>R</td></tr>
2912 <td>R</td></tr>
2912 <tr><td>-f</td>
2913 <tr><td>-f</td>
2913 <td>R</td>
2914 <td>R</td>
2914 <td>RD</td>
2915 <td>RD</td>
2915 <td>RD</td>
2916 <td>RD</td>
2916 <td>R</td></tr>
2917 <td>R</td></tr>
2917 <tr><td>-A</td>
2918 <tr><td>-A</td>
2918 <td>W</td>
2919 <td>W</td>
2919 <td>W</td>
2920 <td>W</td>
2920 <td>W</td>
2921 <td>W</td>
2921 <td>R</td></tr>
2922 <td>R</td></tr>
2922 <tr><td>-Af</td>
2923 <tr><td>-Af</td>
2923 <td>R</td>
2924 <td>R</td>
2924 <td>R</td>
2925 <td>R</td>
2925 <td>R</td>
2926 <td>R</td>
2926 <td>R</td></tr>
2927 <td>R</td></tr>
2927 </table>
2928 </table>
2928 <p>
2929 <p>
2929 <b>Note:</b>
2930 <b>Note:</b>
2930 </p>
2931 </p>
2931 <p>
2932 <p>
2932 'hg remove' never deletes files in Added [A] state from the
2933 'hg remove' never deletes files in Added [A] state from the
2933 working directory, not even if &quot;--force&quot; is specified.
2934 working directory, not even if &quot;--force&quot; is specified.
2934 </p>
2935 </p>
2935 <p>
2936 <p>
2936 Returns 0 on success, 1 if any warnings encountered.
2937 Returns 0 on success, 1 if any warnings encountered.
2937 </p>
2938 </p>
2938 <p>
2939 <p>
2939 options ([+] can be repeated):
2940 options ([+] can be repeated):
2940 </p>
2941 </p>
2941 <table>
2942 <table>
2942 <tr><td>-A</td>
2943 <tr><td>-A</td>
2943 <td>--after</td>
2944 <td>--after</td>
2944 <td>record delete for missing files</td></tr>
2945 <td>record delete for missing files</td></tr>
2945 <tr><td>-f</td>
2946 <tr><td>-f</td>
2946 <td>--force</td>
2947 <td>--force</td>
2947 <td>forget added files, delete modified files</td></tr>
2948 <td>forget added files, delete modified files</td></tr>
2948 <tr><td>-S</td>
2949 <tr><td>-S</td>
2949 <td>--subrepos</td>
2950 <td>--subrepos</td>
2950 <td>recurse into subrepositories</td></tr>
2951 <td>recurse into subrepositories</td></tr>
2951 <tr><td>-I</td>
2952 <tr><td>-I</td>
2952 <td>--include PATTERN [+]</td>
2953 <td>--include PATTERN [+]</td>
2953 <td>include names matching the given patterns</td></tr>
2954 <td>include names matching the given patterns</td></tr>
2954 <tr><td>-X</td>
2955 <tr><td>-X</td>
2955 <td>--exclude PATTERN [+]</td>
2956 <td>--exclude PATTERN [+]</td>
2956 <td>exclude names matching the given patterns</td></tr>
2957 <td>exclude names matching the given patterns</td></tr>
2957 <tr><td>-n</td>
2958 <tr><td>-n</td>
2958 <td>--dry-run</td>
2959 <td>--dry-run</td>
2959 <td>do not perform actions, just print output</td></tr>
2960 <td>do not perform actions, just print output</td></tr>
2960 </table>
2961 </table>
2961 <p>
2962 <p>
2962 global options ([+] can be repeated):
2963 global options ([+] can be repeated):
2963 </p>
2964 </p>
2964 <table>
2965 <table>
2965 <tr><td>-R</td>
2966 <tr><td>-R</td>
2966 <td>--repository REPO</td>
2967 <td>--repository REPO</td>
2967 <td>repository root directory or name of overlay bundle file</td></tr>
2968 <td>repository root directory or name of overlay bundle file</td></tr>
2968 <tr><td></td>
2969 <tr><td></td>
2969 <td>--cwd DIR</td>
2970 <td>--cwd DIR</td>
2970 <td>change working directory</td></tr>
2971 <td>change working directory</td></tr>
2971 <tr><td>-y</td>
2972 <tr><td>-y</td>
2972 <td>--noninteractive</td>
2973 <td>--noninteractive</td>
2973 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2974 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2974 <tr><td>-q</td>
2975 <tr><td>-q</td>
2975 <td>--quiet</td>
2976 <td>--quiet</td>
2976 <td>suppress output</td></tr>
2977 <td>suppress output</td></tr>
2977 <tr><td>-v</td>
2978 <tr><td>-v</td>
2978 <td>--verbose</td>
2979 <td>--verbose</td>
2979 <td>enable additional output</td></tr>
2980 <td>enable additional output</td></tr>
2980 <tr><td></td>
2981 <tr><td></td>
2981 <td>--color TYPE</td>
2982 <td>--color TYPE</td>
2982 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2983 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2983 <tr><td></td>
2984 <tr><td></td>
2984 <td>--config CONFIG [+]</td>
2985 <td>--config CONFIG [+]</td>
2985 <td>set/override config option (use 'section.name=value')</td></tr>
2986 <td>set/override config option (use 'section.name=value')</td></tr>
2986 <tr><td></td>
2987 <tr><td></td>
2987 <td>--debug</td>
2988 <td>--debug</td>
2988 <td>enable debugging output</td></tr>
2989 <td>enable debugging output</td></tr>
2989 <tr><td></td>
2990 <tr><td></td>
2990 <td>--debugger</td>
2991 <td>--debugger</td>
2991 <td>start debugger</td></tr>
2992 <td>start debugger</td></tr>
2992 <tr><td></td>
2993 <tr><td></td>
2993 <td>--encoding ENCODE</td>
2994 <td>--encoding ENCODE</td>
2994 <td>set the charset encoding (default: ascii)</td></tr>
2995 <td>set the charset encoding (default: ascii)</td></tr>
2995 <tr><td></td>
2996 <tr><td></td>
2996 <td>--encodingmode MODE</td>
2997 <td>--encodingmode MODE</td>
2997 <td>set the charset encoding mode (default: strict)</td></tr>
2998 <td>set the charset encoding mode (default: strict)</td></tr>
2998 <tr><td></td>
2999 <tr><td></td>
2999 <td>--traceback</td>
3000 <td>--traceback</td>
3000 <td>always print a traceback on exception</td></tr>
3001 <td>always print a traceback on exception</td></tr>
3001 <tr><td></td>
3002 <tr><td></td>
3002 <td>--time</td>
3003 <td>--time</td>
3003 <td>time how long the command takes</td></tr>
3004 <td>time how long the command takes</td></tr>
3004 <tr><td></td>
3005 <tr><td></td>
3005 <td>--profile</td>
3006 <td>--profile</td>
3006 <td>print command execution profile</td></tr>
3007 <td>print command execution profile</td></tr>
3007 <tr><td></td>
3008 <tr><td></td>
3008 <td>--version</td>
3009 <td>--version</td>
3009 <td>output version information and exit</td></tr>
3010 <td>output version information and exit</td></tr>
3010 <tr><td>-h</td>
3011 <tr><td>-h</td>
3011 <td>--help</td>
3012 <td>--help</td>
3012 <td>display help and exit</td></tr>
3013 <td>display help and exit</td></tr>
3013 <tr><td></td>
3014 <tr><td></td>
3014 <td>--hidden</td>
3015 <td>--hidden</td>
3015 <td>consider hidden changesets</td></tr>
3016 <td>consider hidden changesets</td></tr>
3016 <tr><td></td>
3017 <tr><td></td>
3017 <td>--pager TYPE</td>
3018 <td>--pager TYPE</td>
3018 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3019 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3019 </table>
3020 </table>
3020
3021
3021 </div>
3022 </div>
3022 </div>
3023 </div>
3023 </div>
3024 </div>
3024
3025
3025
3026
3026
3027
3027 </body>
3028 </body>
3028 </html>
3029 </html>
3029
3030
3030
3031
3031 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3032 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3032 200 Script output follows
3033 200 Script output follows
3033
3034
3034 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3035 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3035 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3036 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3036 <head>
3037 <head>
3037 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3038 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3038 <meta name="robots" content="index, nofollow" />
3039 <meta name="robots" content="index, nofollow" />
3039 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3040 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3040 <script type="text/javascript" src="/static/mercurial.js"></script>
3041 <script type="text/javascript" src="/static/mercurial.js"></script>
3041
3042
3042 <title>Help: dates</title>
3043 <title>Help: dates</title>
3043 </head>
3044 </head>
3044 <body>
3045 <body>
3045
3046
3046 <div class="container">
3047 <div class="container">
3047 <div class="menu">
3048 <div class="menu">
3048 <div class="logo">
3049 <div class="logo">
3049 <a href="https://mercurial-scm.org/">
3050 <a href="https://mercurial-scm.org/">
3050 <img src="/static/hglogo.png" alt="mercurial" /></a>
3051 <img src="/static/hglogo.png" alt="mercurial" /></a>
3051 </div>
3052 </div>
3052 <ul>
3053 <ul>
3053 <li><a href="/shortlog">log</a></li>
3054 <li><a href="/shortlog">log</a></li>
3054 <li><a href="/graph">graph</a></li>
3055 <li><a href="/graph">graph</a></li>
3055 <li><a href="/tags">tags</a></li>
3056 <li><a href="/tags">tags</a></li>
3056 <li><a href="/bookmarks">bookmarks</a></li>
3057 <li><a href="/bookmarks">bookmarks</a></li>
3057 <li><a href="/branches">branches</a></li>
3058 <li><a href="/branches">branches</a></li>
3058 </ul>
3059 </ul>
3059 <ul>
3060 <ul>
3060 <li class="active"><a href="/help">help</a></li>
3061 <li class="active"><a href="/help">help</a></li>
3061 </ul>
3062 </ul>
3062 </div>
3063 </div>
3063
3064
3064 <div class="main">
3065 <div class="main">
3065 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3066 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3066 <h3>Help: dates</h3>
3067 <h3>Help: dates</h3>
3067
3068
3068 <form class="search" action="/log">
3069 <form class="search" action="/log">
3069
3070
3070 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3071 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3071 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3072 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3072 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3073 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3073 </form>
3074 </form>
3074 <div id="doc">
3075 <div id="doc">
3075 <h1>Date Formats</h1>
3076 <h1>Date Formats</h1>
3076 <p>
3077 <p>
3077 Some commands allow the user to specify a date, e.g.:
3078 Some commands allow the user to specify a date, e.g.:
3078 </p>
3079 </p>
3079 <ul>
3080 <ul>
3080 <li> backout, commit, import, tag: Specify the commit date.
3081 <li> backout, commit, import, tag: Specify the commit date.
3081 <li> log, revert, update: Select revision(s) by date.
3082 <li> log, revert, update: Select revision(s) by date.
3082 </ul>
3083 </ul>
3083 <p>
3084 <p>
3084 Many date formats are valid. Here are some examples:
3085 Many date formats are valid. Here are some examples:
3085 </p>
3086 </p>
3086 <ul>
3087 <ul>
3087 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3088 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3088 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3089 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3089 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3090 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3090 <li> &quot;Dec 6&quot; (midnight)
3091 <li> &quot;Dec 6&quot; (midnight)
3091 <li> &quot;13:18&quot; (today assumed)
3092 <li> &quot;13:18&quot; (today assumed)
3092 <li> &quot;3:39&quot; (3:39AM assumed)
3093 <li> &quot;3:39&quot; (3:39AM assumed)
3093 <li> &quot;3:39pm&quot; (15:39)
3094 <li> &quot;3:39pm&quot; (15:39)
3094 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3095 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3095 <li> &quot;2006-12-6 13:18&quot;
3096 <li> &quot;2006-12-6 13:18&quot;
3096 <li> &quot;2006-12-6&quot;
3097 <li> &quot;2006-12-6&quot;
3097 <li> &quot;12-6&quot;
3098 <li> &quot;12-6&quot;
3098 <li> &quot;12/6&quot;
3099 <li> &quot;12/6&quot;
3099 <li> &quot;12/6/6&quot; (Dec 6 2006)
3100 <li> &quot;12/6/6&quot; (Dec 6 2006)
3100 <li> &quot;today&quot; (midnight)
3101 <li> &quot;today&quot; (midnight)
3101 <li> &quot;yesterday&quot; (midnight)
3102 <li> &quot;yesterday&quot; (midnight)
3102 <li> &quot;now&quot; - right now
3103 <li> &quot;now&quot; - right now
3103 </ul>
3104 </ul>
3104 <p>
3105 <p>
3105 Lastly, there is Mercurial's internal format:
3106 Lastly, there is Mercurial's internal format:
3106 </p>
3107 </p>
3107 <ul>
3108 <ul>
3108 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3109 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3109 </ul>
3110 </ul>
3110 <p>
3111 <p>
3111 This is the internal representation format for dates. The first number
3112 This is the internal representation format for dates. The first number
3112 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3113 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3113 second is the offset of the local timezone, in seconds west of UTC
3114 second is the offset of the local timezone, in seconds west of UTC
3114 (negative if the timezone is east of UTC).
3115 (negative if the timezone is east of UTC).
3115 </p>
3116 </p>
3116 <p>
3117 <p>
3117 The log command also accepts date ranges:
3118 The log command also accepts date ranges:
3118 </p>
3119 </p>
3119 <ul>
3120 <ul>
3120 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3121 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3121 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3122 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3122 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3123 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3123 <li> &quot;-DAYS&quot; - within a given number of days of today
3124 <li> &quot;-DAYS&quot; - within a given number of days of today
3124 </ul>
3125 </ul>
3125
3126
3126 </div>
3127 </div>
3127 </div>
3128 </div>
3128 </div>
3129 </div>
3129
3130
3130
3131
3131
3132
3132 </body>
3133 </body>
3133 </html>
3134 </html>
3134
3135
3135
3136
3136 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3137 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3137 200 Script output follows
3138 200 Script output follows
3138
3139
3139 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3140 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3140 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3141 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3141 <head>
3142 <head>
3142 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3143 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3143 <meta name="robots" content="index, nofollow" />
3144 <meta name="robots" content="index, nofollow" />
3144 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3145 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3145 <script type="text/javascript" src="/static/mercurial.js"></script>
3146 <script type="text/javascript" src="/static/mercurial.js"></script>
3146
3147
3147 <title>Help: pager</title>
3148 <title>Help: pager</title>
3148 </head>
3149 </head>
3149 <body>
3150 <body>
3150
3151
3151 <div class="container">
3152 <div class="container">
3152 <div class="menu">
3153 <div class="menu">
3153 <div class="logo">
3154 <div class="logo">
3154 <a href="https://mercurial-scm.org/">
3155 <a href="https://mercurial-scm.org/">
3155 <img src="/static/hglogo.png" alt="mercurial" /></a>
3156 <img src="/static/hglogo.png" alt="mercurial" /></a>
3156 </div>
3157 </div>
3157 <ul>
3158 <ul>
3158 <li><a href="/shortlog">log</a></li>
3159 <li><a href="/shortlog">log</a></li>
3159 <li><a href="/graph">graph</a></li>
3160 <li><a href="/graph">graph</a></li>
3160 <li><a href="/tags">tags</a></li>
3161 <li><a href="/tags">tags</a></li>
3161 <li><a href="/bookmarks">bookmarks</a></li>
3162 <li><a href="/bookmarks">bookmarks</a></li>
3162 <li><a href="/branches">branches</a></li>
3163 <li><a href="/branches">branches</a></li>
3163 </ul>
3164 </ul>
3164 <ul>
3165 <ul>
3165 <li class="active"><a href="/help">help</a></li>
3166 <li class="active"><a href="/help">help</a></li>
3166 </ul>
3167 </ul>
3167 </div>
3168 </div>
3168
3169
3169 <div class="main">
3170 <div class="main">
3170 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3171 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3171 <h3>Help: pager</h3>
3172 <h3>Help: pager</h3>
3172
3173
3173 <form class="search" action="/log">
3174 <form class="search" action="/log">
3174
3175
3175 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3176 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3176 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3177 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3177 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3178 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3178 </form>
3179 </form>
3179 <div id="doc">
3180 <div id="doc">
3180 <h1>Pager Support</h1>
3181 <h1>Pager Support</h1>
3181 <p>
3182 <p>
3182 Some Mercurial commands can produce a lot of output, and Mercurial will
3183 Some Mercurial commands can produce a lot of output, and Mercurial will
3183 attempt to use a pager to make those commands more pleasant.
3184 attempt to use a pager to make those commands more pleasant.
3184 </p>
3185 </p>
3185 <p>
3186 <p>
3186 To set the pager that should be used, set the application variable:
3187 To set the pager that should be used, set the application variable:
3187 </p>
3188 </p>
3188 <pre>
3189 <pre>
3189 [pager]
3190 [pager]
3190 pager = less -FRX
3191 pager = less -FRX
3191 </pre>
3192 </pre>
3192 <p>
3193 <p>
3193 If no pager is set in the user or repository configuration, Mercurial uses the
3194 If no pager is set in the user or repository configuration, Mercurial uses the
3194 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3195 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3195 or system configuration is used. If none of these are set, a default pager will
3196 or system configuration is used. If none of these are set, a default pager will
3196 be used, typically 'less' on Unix and 'more' on Windows.
3197 be used, typically 'less' on Unix and 'more' on Windows.
3197 </p>
3198 </p>
3198 <p>
3199 <p>
3199 You can disable the pager for certain commands by adding them to the
3200 You can disable the pager for certain commands by adding them to the
3200 pager.ignore list:
3201 pager.ignore list:
3201 </p>
3202 </p>
3202 <pre>
3203 <pre>
3203 [pager]
3204 [pager]
3204 ignore = version, help, update
3205 ignore = version, help, update
3205 </pre>
3206 </pre>
3206 <p>
3207 <p>
3207 To ignore global commands like 'hg version' or 'hg help', you have
3208 To ignore global commands like 'hg version' or 'hg help', you have
3208 to specify them in your user configuration file.
3209 to specify them in your user configuration file.
3209 </p>
3210 </p>
3210 <p>
3211 <p>
3211 To control whether the pager is used at all for an individual command,
3212 To control whether the pager is used at all for an individual command,
3212 you can use --pager=&lt;value&gt;:
3213 you can use --pager=&lt;value&gt;:
3213 </p>
3214 </p>
3214 <ul>
3215 <ul>
3215 <li> use as needed: 'auto'.
3216 <li> use as needed: 'auto'.
3216 <li> require the pager: 'yes' or 'on'.
3217 <li> require the pager: 'yes' or 'on'.
3217 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3218 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3218 </ul>
3219 </ul>
3219 <p>
3220 <p>
3220 To globally turn off all attempts to use a pager, set:
3221 To globally turn off all attempts to use a pager, set:
3221 </p>
3222 </p>
3222 <pre>
3223 <pre>
3223 [ui]
3224 [ui]
3224 paginate = never
3225 paginate = never
3225 </pre>
3226 </pre>
3226 <p>
3227 <p>
3227 which will prevent the pager from running.
3228 which will prevent the pager from running.
3228 </p>
3229 </p>
3229
3230
3230 </div>
3231 </div>
3231 </div>
3232 </div>
3232 </div>
3233 </div>
3233
3234
3234
3235
3235
3236
3236 </body>
3237 </body>
3237 </html>
3238 </html>
3238
3239
3239
3240
3240 Sub-topic indexes rendered properly
3241 Sub-topic indexes rendered properly
3241
3242
3242 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3243 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3243 200 Script output follows
3244 200 Script output follows
3244
3245
3245 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3246 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3246 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3247 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3247 <head>
3248 <head>
3248 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3249 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3249 <meta name="robots" content="index, nofollow" />
3250 <meta name="robots" content="index, nofollow" />
3250 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3251 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3251 <script type="text/javascript" src="/static/mercurial.js"></script>
3252 <script type="text/javascript" src="/static/mercurial.js"></script>
3252
3253
3253 <title>Help: internals</title>
3254 <title>Help: internals</title>
3254 </head>
3255 </head>
3255 <body>
3256 <body>
3256
3257
3257 <div class="container">
3258 <div class="container">
3258 <div class="menu">
3259 <div class="menu">
3259 <div class="logo">
3260 <div class="logo">
3260 <a href="https://mercurial-scm.org/">
3261 <a href="https://mercurial-scm.org/">
3261 <img src="/static/hglogo.png" alt="mercurial" /></a>
3262 <img src="/static/hglogo.png" alt="mercurial" /></a>
3262 </div>
3263 </div>
3263 <ul>
3264 <ul>
3264 <li><a href="/shortlog">log</a></li>
3265 <li><a href="/shortlog">log</a></li>
3265 <li><a href="/graph">graph</a></li>
3266 <li><a href="/graph">graph</a></li>
3266 <li><a href="/tags">tags</a></li>
3267 <li><a href="/tags">tags</a></li>
3267 <li><a href="/bookmarks">bookmarks</a></li>
3268 <li><a href="/bookmarks">bookmarks</a></li>
3268 <li><a href="/branches">branches</a></li>
3269 <li><a href="/branches">branches</a></li>
3269 </ul>
3270 </ul>
3270 <ul>
3271 <ul>
3271 <li><a href="/help">help</a></li>
3272 <li><a href="/help">help</a></li>
3272 </ul>
3273 </ul>
3273 </div>
3274 </div>
3274
3275
3275 <div class="main">
3276 <div class="main">
3276 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3277 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3277
3278
3278 <form class="search" action="/log">
3279 <form class="search" action="/log">
3279
3280
3280 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3281 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3281 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3282 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3282 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3283 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3283 </form>
3284 </form>
3284 <table class="bigtable">
3285 <table class="bigtable">
3285 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3286 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3286
3287
3287 <tr><td>
3288 <tr><td>
3288 <a href="/help/internals.bundle2">
3289 <a href="/help/internals.bundle2">
3289 bundle2
3290 bundle2
3290 </a>
3291 </a>
3291 </td><td>
3292 </td><td>
3292 Bundle2
3293 Bundle2
3293 </td></tr>
3294 </td></tr>
3294 <tr><td>
3295 <tr><td>
3295 <a href="/help/internals.bundles">
3296 <a href="/help/internals.bundles">
3296 bundles
3297 bundles
3297 </a>
3298 </a>
3298 </td><td>
3299 </td><td>
3299 Bundles
3300 Bundles
3300 </td></tr>
3301 </td></tr>
3301 <tr><td>
3302 <tr><td>
3302 <a href="/help/internals.cbor">
3303 <a href="/help/internals.cbor">
3303 cbor
3304 cbor
3304 </a>
3305 </a>
3305 </td><td>
3306 </td><td>
3306 CBOR
3307 CBOR
3307 </td></tr>
3308 </td></tr>
3308 <tr><td>
3309 <tr><td>
3309 <a href="/help/internals.censor">
3310 <a href="/help/internals.censor">
3310 censor
3311 censor
3311 </a>
3312 </a>
3312 </td><td>
3313 </td><td>
3313 Censor
3314 Censor
3314 </td></tr>
3315 </td></tr>
3315 <tr><td>
3316 <tr><td>
3316 <a href="/help/internals.changegroups">
3317 <a href="/help/internals.changegroups">
3317 changegroups
3318 changegroups
3318 </a>
3319 </a>
3319 </td><td>
3320 </td><td>
3320 Changegroups
3321 Changegroups
3321 </td></tr>
3322 </td></tr>
3322 <tr><td>
3323 <tr><td>
3323 <a href="/help/internals.config">
3324 <a href="/help/internals.config">
3324 config
3325 config
3325 </a>
3326 </a>
3326 </td><td>
3327 </td><td>
3327 Config Registrar
3328 Config Registrar
3328 </td></tr>
3329 </td></tr>
3329 <tr><td>
3330 <tr><td>
3330 <a href="/help/internals.requirements">
3331 <a href="/help/internals.requirements">
3331 requirements
3332 requirements
3332 </a>
3333 </a>
3333 </td><td>
3334 </td><td>
3334 Repository Requirements
3335 Repository Requirements
3335 </td></tr>
3336 </td></tr>
3336 <tr><td>
3337 <tr><td>
3337 <a href="/help/internals.revlogs">
3338 <a href="/help/internals.revlogs">
3338 revlogs
3339 revlogs
3339 </a>
3340 </a>
3340 </td><td>
3341 </td><td>
3341 Revision Logs
3342 Revision Logs
3342 </td></tr>
3343 </td></tr>
3343 <tr><td>
3344 <tr><td>
3344 <a href="/help/internals.wireprotocol">
3345 <a href="/help/internals.wireprotocol">
3345 wireprotocol
3346 wireprotocol
3346 </a>
3347 </a>
3347 </td><td>
3348 </td><td>
3348 Wire Protocol
3349 Wire Protocol
3349 </td></tr>
3350 </td></tr>
3350 <tr><td>
3351 <tr><td>
3351 <a href="/help/internals.wireprotocolrpc">
3352 <a href="/help/internals.wireprotocolrpc">
3352 wireprotocolrpc
3353 wireprotocolrpc
3353 </a>
3354 </a>
3354 </td><td>
3355 </td><td>
3355 Wire Protocol RPC
3356 Wire Protocol RPC
3356 </td></tr>
3357 </td></tr>
3357 <tr><td>
3358 <tr><td>
3358 <a href="/help/internals.wireprotocolv2">
3359 <a href="/help/internals.wireprotocolv2">
3359 wireprotocolv2
3360 wireprotocolv2
3360 </a>
3361 </a>
3361 </td><td>
3362 </td><td>
3362 Wire Protocol Version 2
3363 Wire Protocol Version 2
3363 </td></tr>
3364 </td></tr>
3364
3365
3365
3366
3366
3367
3367
3368
3368
3369
3369 </table>
3370 </table>
3370 </div>
3371 </div>
3371 </div>
3372 </div>
3372
3373
3373
3374
3374
3375
3375 </body>
3376 </body>
3376 </html>
3377 </html>
3377
3378
3378
3379
3379 Sub-topic topics rendered properly
3380 Sub-topic topics rendered properly
3380
3381
3381 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3382 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3382 200 Script output follows
3383 200 Script output follows
3383
3384
3384 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3385 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3385 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3386 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3386 <head>
3387 <head>
3387 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3388 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3388 <meta name="robots" content="index, nofollow" />
3389 <meta name="robots" content="index, nofollow" />
3389 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3390 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3390 <script type="text/javascript" src="/static/mercurial.js"></script>
3391 <script type="text/javascript" src="/static/mercurial.js"></script>
3391
3392
3392 <title>Help: internals.changegroups</title>
3393 <title>Help: internals.changegroups</title>
3393 </head>
3394 </head>
3394 <body>
3395 <body>
3395
3396
3396 <div class="container">
3397 <div class="container">
3397 <div class="menu">
3398 <div class="menu">
3398 <div class="logo">
3399 <div class="logo">
3399 <a href="https://mercurial-scm.org/">
3400 <a href="https://mercurial-scm.org/">
3400 <img src="/static/hglogo.png" alt="mercurial" /></a>
3401 <img src="/static/hglogo.png" alt="mercurial" /></a>
3401 </div>
3402 </div>
3402 <ul>
3403 <ul>
3403 <li><a href="/shortlog">log</a></li>
3404 <li><a href="/shortlog">log</a></li>
3404 <li><a href="/graph">graph</a></li>
3405 <li><a href="/graph">graph</a></li>
3405 <li><a href="/tags">tags</a></li>
3406 <li><a href="/tags">tags</a></li>
3406 <li><a href="/bookmarks">bookmarks</a></li>
3407 <li><a href="/bookmarks">bookmarks</a></li>
3407 <li><a href="/branches">branches</a></li>
3408 <li><a href="/branches">branches</a></li>
3408 </ul>
3409 </ul>
3409 <ul>
3410 <ul>
3410 <li class="active"><a href="/help">help</a></li>
3411 <li class="active"><a href="/help">help</a></li>
3411 </ul>
3412 </ul>
3412 </div>
3413 </div>
3413
3414
3414 <div class="main">
3415 <div class="main">
3415 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3416 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3416 <h3>Help: internals.changegroups</h3>
3417 <h3>Help: internals.changegroups</h3>
3417
3418
3418 <form class="search" action="/log">
3419 <form class="search" action="/log">
3419
3420
3420 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3421 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3421 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3422 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3422 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3423 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3423 </form>
3424 </form>
3424 <div id="doc">
3425 <div id="doc">
3425 <h1>Changegroups</h1>
3426 <h1>Changegroups</h1>
3426 <p>
3427 <p>
3427 Changegroups are representations of repository revlog data, specifically
3428 Changegroups are representations of repository revlog data, specifically
3428 the changelog data, root/flat manifest data, treemanifest data, and
3429 the changelog data, root/flat manifest data, treemanifest data, and
3429 filelogs.
3430 filelogs.
3430 </p>
3431 </p>
3431 <p>
3432 <p>
3432 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3433 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3433 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3434 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3434 only difference being an additional item in the *delta header*. Version
3435 only difference being an additional item in the *delta header*. Version
3435 &quot;3&quot; adds support for revlog flags in the *delta header* and optionally
3436 &quot;3&quot; adds support for revlog flags in the *delta header* and optionally
3436 exchanging treemanifests (enabled by setting an option on the
3437 exchanging treemanifests (enabled by setting an option on the
3437 &quot;changegroup&quot; part in the bundle2).
3438 &quot;changegroup&quot; part in the bundle2).
3438 </p>
3439 </p>
3439 <p>
3440 <p>
3440 Changegroups when not exchanging treemanifests consist of 3 logical
3441 Changegroups when not exchanging treemanifests consist of 3 logical
3441 segments:
3442 segments:
3442 </p>
3443 </p>
3443 <pre>
3444 <pre>
3444 +---------------------------------+
3445 +---------------------------------+
3445 | | | |
3446 | | | |
3446 | changeset | manifest | filelogs |
3447 | changeset | manifest | filelogs |
3447 | | | |
3448 | | | |
3448 | | | |
3449 | | | |
3449 +---------------------------------+
3450 +---------------------------------+
3450 </pre>
3451 </pre>
3451 <p>
3452 <p>
3452 When exchanging treemanifests, there are 4 logical segments:
3453 When exchanging treemanifests, there are 4 logical segments:
3453 </p>
3454 </p>
3454 <pre>
3455 <pre>
3455 +-------------------------------------------------+
3456 +-------------------------------------------------+
3456 | | | | |
3457 | | | | |
3457 | changeset | root | treemanifests | filelogs |
3458 | changeset | root | treemanifests | filelogs |
3458 | | manifest | | |
3459 | | manifest | | |
3459 | | | | |
3460 | | | | |
3460 +-------------------------------------------------+
3461 +-------------------------------------------------+
3461 </pre>
3462 </pre>
3462 <p>
3463 <p>
3463 The principle building block of each segment is a *chunk*. A *chunk*
3464 The principle building block of each segment is a *chunk*. A *chunk*
3464 is a framed piece of data:
3465 is a framed piece of data:
3465 </p>
3466 </p>
3466 <pre>
3467 <pre>
3467 +---------------------------------------+
3468 +---------------------------------------+
3468 | | |
3469 | | |
3469 | length | data |
3470 | length | data |
3470 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3471 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3471 | | |
3472 | | |
3472 +---------------------------------------+
3473 +---------------------------------------+
3473 </pre>
3474 </pre>
3474 <p>
3475 <p>
3475 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3476 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3476 integer indicating the length of the entire chunk (including the length field
3477 integer indicating the length of the entire chunk (including the length field
3477 itself).
3478 itself).
3478 </p>
3479 </p>
3479 <p>
3480 <p>
3480 There is a special case chunk that has a value of 0 for the length
3481 There is a special case chunk that has a value of 0 for the length
3481 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3482 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3482 </p>
3483 </p>
3483 <h2>Delta Groups</h2>
3484 <h2>Delta Groups</h2>
3484 <p>
3485 <p>
3485 A *delta group* expresses the content of a revlog as a series of deltas,
3486 A *delta group* expresses the content of a revlog as a series of deltas,
3486 or patches against previous revisions.
3487 or patches against previous revisions.
3487 </p>
3488 </p>
3488 <p>
3489 <p>
3489 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3490 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3490 to signal the end of the delta group:
3491 to signal the end of the delta group:
3491 </p>
3492 </p>
3492 <pre>
3493 <pre>
3493 +------------------------------------------------------------------------+
3494 +------------------------------------------------------------------------+
3494 | | | | | |
3495 | | | | | |
3495 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3496 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3496 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3497 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3497 | | | | | |
3498 | | | | | |
3498 +------------------------------------------------------------------------+
3499 +------------------------------------------------------------------------+
3499 </pre>
3500 </pre>
3500 <p>
3501 <p>
3501 Each *chunk*'s data consists of the following:
3502 Each *chunk*'s data consists of the following:
3502 </p>
3503 </p>
3503 <pre>
3504 <pre>
3504 +---------------------------------------+
3505 +---------------------------------------+
3505 | | |
3506 | | |
3506 | delta header | delta data |
3507 | delta header | delta data |
3507 | (various by version) | (various) |
3508 | (various by version) | (various) |
3508 | | |
3509 | | |
3509 +---------------------------------------+
3510 +---------------------------------------+
3510 </pre>
3511 </pre>
3511 <p>
3512 <p>
3512 The *delta data* is a series of *delta*s that describe a diff from an existing
3513 The *delta data* is a series of *delta*s that describe a diff from an existing
3513 entry (either that the recipient already has, or previously specified in the
3514 entry (either that the recipient already has, or previously specified in the
3514 bundle/changegroup).
3515 bundle/changegroup).
3515 </p>
3516 </p>
3516 <p>
3517 <p>
3517 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3518 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3518 &quot;3&quot; of the changegroup format.
3519 &quot;3&quot; of the changegroup format.
3519 </p>
3520 </p>
3520 <p>
3521 <p>
3521 Version 1 (headerlen=80):
3522 Version 1 (headerlen=80):
3522 </p>
3523 </p>
3523 <pre>
3524 <pre>
3524 +------------------------------------------------------+
3525 +------------------------------------------------------+
3525 | | | | |
3526 | | | | |
3526 | node | p1 node | p2 node | link node |
3527 | node | p1 node | p2 node | link node |
3527 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3528 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3528 | | | | |
3529 | | | | |
3529 +------------------------------------------------------+
3530 +------------------------------------------------------+
3530 </pre>
3531 </pre>
3531 <p>
3532 <p>
3532 Version 2 (headerlen=100):
3533 Version 2 (headerlen=100):
3533 </p>
3534 </p>
3534 <pre>
3535 <pre>
3535 +------------------------------------------------------------------+
3536 +------------------------------------------------------------------+
3536 | | | | | |
3537 | | | | | |
3537 | node | p1 node | p2 node | base node | link node |
3538 | node | p1 node | p2 node | base node | link node |
3538 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3539 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3539 | | | | | |
3540 | | | | | |
3540 +------------------------------------------------------------------+
3541 +------------------------------------------------------------------+
3541 </pre>
3542 </pre>
3542 <p>
3543 <p>
3543 Version 3 (headerlen=102):
3544 Version 3 (headerlen=102):
3544 </p>
3545 </p>
3545 <pre>
3546 <pre>
3546 +------------------------------------------------------------------------------+
3547 +------------------------------------------------------------------------------+
3547 | | | | | | |
3548 | | | | | | |
3548 | node | p1 node | p2 node | base node | link node | flags |
3549 | node | p1 node | p2 node | base node | link node | flags |
3549 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3550 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3550 | | | | | | |
3551 | | | | | | |
3551 +------------------------------------------------------------------------------+
3552 +------------------------------------------------------------------------------+
3552 </pre>
3553 </pre>
3553 <p>
3554 <p>
3554 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3555 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3555 series of *delta*s, densely packed (no separators). These deltas describe a diff
3556 series of *delta*s, densely packed (no separators). These deltas describe a diff
3556 from an existing entry (either that the recipient already has, or previously
3557 from an existing entry (either that the recipient already has, or previously
3557 specified in the bundle/changegroup). The format is described more fully in
3558 specified in the bundle/changegroup). The format is described more fully in
3558 &quot;hg help internals.bdiff&quot;, but briefly:
3559 &quot;hg help internals.bdiff&quot;, but briefly:
3559 </p>
3560 </p>
3560 <pre>
3561 <pre>
3561 +---------------------------------------------------------------+
3562 +---------------------------------------------------------------+
3562 | | | | |
3563 | | | | |
3563 | start offset | end offset | new length | content |
3564 | start offset | end offset | new length | content |
3564 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3565 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3565 | | | | |
3566 | | | | |
3566 +---------------------------------------------------------------+
3567 +---------------------------------------------------------------+
3567 </pre>
3568 </pre>
3568 <p>
3569 <p>
3569 Please note that the length field in the delta data does *not* include itself.
3570 Please note that the length field in the delta data does *not* include itself.
3570 </p>
3571 </p>
3571 <p>
3572 <p>
3572 In version 1, the delta is always applied against the previous node from
3573 In version 1, the delta is always applied against the previous node from
3573 the changegroup or the first parent if this is the first entry in the
3574 the changegroup or the first parent if this is the first entry in the
3574 changegroup.
3575 changegroup.
3575 </p>
3576 </p>
3576 <p>
3577 <p>
3577 In version 2 and up, the delta base node is encoded in the entry in the
3578 In version 2 and up, the delta base node is encoded in the entry in the
3578 changegroup. This allows the delta to be expressed against any parent,
3579 changegroup. This allows the delta to be expressed against any parent,
3579 which can result in smaller deltas and more efficient encoding of data.
3580 which can result in smaller deltas and more efficient encoding of data.
3580 </p>
3581 </p>
3581 <h2>Changeset Segment</h2>
3582 <h2>Changeset Segment</h2>
3582 <p>
3583 <p>
3583 The *changeset segment* consists of a single *delta group* holding
3584 The *changeset segment* consists of a single *delta group* holding
3584 changelog data. The *empty chunk* at the end of the *delta group* denotes
3585 changelog data. The *empty chunk* at the end of the *delta group* denotes
3585 the boundary to the *manifest segment*.
3586 the boundary to the *manifest segment*.
3586 </p>
3587 </p>
3587 <h2>Manifest Segment</h2>
3588 <h2>Manifest Segment</h2>
3588 <p>
3589 <p>
3589 The *manifest segment* consists of a single *delta group* holding manifest
3590 The *manifest segment* consists of a single *delta group* holding manifest
3590 data. If treemanifests are in use, it contains only the manifest for the
3591 data. If treemanifests are in use, it contains only the manifest for the
3591 root directory of the repository. Otherwise, it contains the entire
3592 root directory of the repository. Otherwise, it contains the entire
3592 manifest data. The *empty chunk* at the end of the *delta group* denotes
3593 manifest data. The *empty chunk* at the end of the *delta group* denotes
3593 the boundary to the next segment (either the *treemanifests segment* or the
3594 the boundary to the next segment (either the *treemanifests segment* or the
3594 *filelogs segment*, depending on version and the request options).
3595 *filelogs segment*, depending on version and the request options).
3595 </p>
3596 </p>
3596 <h3>Treemanifests Segment</h3>
3597 <h3>Treemanifests Segment</h3>
3597 <p>
3598 <p>
3598 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3599 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3599 only if the 'treemanifest' param is part of the bundle2 changegroup part
3600 only if the 'treemanifest' param is part of the bundle2 changegroup part
3600 (it is not possible to use changegroup version 3 outside of bundle2).
3601 (it is not possible to use changegroup version 3 outside of bundle2).
3601 Aside from the filenames in the *treemanifests segment* containing a
3602 Aside from the filenames in the *treemanifests segment* containing a
3602 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3603 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3603 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3604 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3604 a sub-segment with filename size 0). This denotes the boundary to the
3605 a sub-segment with filename size 0). This denotes the boundary to the
3605 *filelogs segment*.
3606 *filelogs segment*.
3606 </p>
3607 </p>
3607 <h2>Filelogs Segment</h2>
3608 <h2>Filelogs Segment</h2>
3608 <p>
3609 <p>
3609 The *filelogs segment* consists of multiple sub-segments, each
3610 The *filelogs segment* consists of multiple sub-segments, each
3610 corresponding to an individual file whose data is being described:
3611 corresponding to an individual file whose data is being described:
3611 </p>
3612 </p>
3612 <pre>
3613 <pre>
3613 +--------------------------------------------------+
3614 +--------------------------------------------------+
3614 | | | | | |
3615 | | | | | |
3615 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3616 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3616 | | | | | (4 bytes) |
3617 | | | | | (4 bytes) |
3617 | | | | | |
3618 | | | | | |
3618 +--------------------------------------------------+
3619 +--------------------------------------------------+
3619 </pre>
3620 </pre>
3620 <p>
3621 <p>
3621 The final filelog sub-segment is followed by an *empty chunk* (logically,
3622 The final filelog sub-segment is followed by an *empty chunk* (logically,
3622 a sub-segment with filename size 0). This denotes the end of the segment
3623 a sub-segment with filename size 0). This denotes the end of the segment
3623 and of the overall changegroup.
3624 and of the overall changegroup.
3624 </p>
3625 </p>
3625 <p>
3626 <p>
3626 Each filelog sub-segment consists of the following:
3627 Each filelog sub-segment consists of the following:
3627 </p>
3628 </p>
3628 <pre>
3629 <pre>
3629 +------------------------------------------------------+
3630 +------------------------------------------------------+
3630 | | | |
3631 | | | |
3631 | filename length | filename | delta group |
3632 | filename length | filename | delta group |
3632 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3633 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3633 | | | |
3634 | | | |
3634 +------------------------------------------------------+
3635 +------------------------------------------------------+
3635 </pre>
3636 </pre>
3636 <p>
3637 <p>
3637 That is, a *chunk* consisting of the filename (not terminated or padded)
3638 That is, a *chunk* consisting of the filename (not terminated or padded)
3638 followed by N chunks constituting the *delta group* for this file. The
3639 followed by N chunks constituting the *delta group* for this file. The
3639 *empty chunk* at the end of each *delta group* denotes the boundary to the
3640 *empty chunk* at the end of each *delta group* denotes the boundary to the
3640 next filelog sub-segment.
3641 next filelog sub-segment.
3641 </p>
3642 </p>
3642
3643
3643 </div>
3644 </div>
3644 </div>
3645 </div>
3645 </div>
3646 </div>
3646
3647
3647
3648
3648
3649
3649 </body>
3650 </body>
3650 </html>
3651 </html>
3651
3652
3652
3653
3653 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3654 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3654 404 Not Found
3655 404 Not Found
3655
3656
3656 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3657 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3657 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3658 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3658 <head>
3659 <head>
3659 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3660 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3660 <meta name="robots" content="index, nofollow" />
3661 <meta name="robots" content="index, nofollow" />
3661 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3662 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3662 <script type="text/javascript" src="/static/mercurial.js"></script>
3663 <script type="text/javascript" src="/static/mercurial.js"></script>
3663
3664
3664 <title>test: error</title>
3665 <title>test: error</title>
3665 </head>
3666 </head>
3666 <body>
3667 <body>
3667
3668
3668 <div class="container">
3669 <div class="container">
3669 <div class="menu">
3670 <div class="menu">
3670 <div class="logo">
3671 <div class="logo">
3671 <a href="https://mercurial-scm.org/">
3672 <a href="https://mercurial-scm.org/">
3672 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3673 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3673 </div>
3674 </div>
3674 <ul>
3675 <ul>
3675 <li><a href="/shortlog">log</a></li>
3676 <li><a href="/shortlog">log</a></li>
3676 <li><a href="/graph">graph</a></li>
3677 <li><a href="/graph">graph</a></li>
3677 <li><a href="/tags">tags</a></li>
3678 <li><a href="/tags">tags</a></li>
3678 <li><a href="/bookmarks">bookmarks</a></li>
3679 <li><a href="/bookmarks">bookmarks</a></li>
3679 <li><a href="/branches">branches</a></li>
3680 <li><a href="/branches">branches</a></li>
3680 </ul>
3681 </ul>
3681 <ul>
3682 <ul>
3682 <li><a href="/help">help</a></li>
3683 <li><a href="/help">help</a></li>
3683 </ul>
3684 </ul>
3684 </div>
3685 </div>
3685
3686
3686 <div class="main">
3687 <div class="main">
3687
3688
3688 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3689 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3689 <h3>error</h3>
3690 <h3>error</h3>
3690
3691
3691
3692
3692 <form class="search" action="/log">
3693 <form class="search" action="/log">
3693
3694
3694 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3695 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3695 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3696 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3696 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3697 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3697 </form>
3698 </form>
3698
3699
3699 <div class="description">
3700 <div class="description">
3700 <p>
3701 <p>
3701 An error occurred while processing your request:
3702 An error occurred while processing your request:
3702 </p>
3703 </p>
3703 <p>
3704 <p>
3704 Not Found
3705 Not Found
3705 </p>
3706 </p>
3706 </div>
3707 </div>
3707 </div>
3708 </div>
3708 </div>
3709 </div>
3709
3710
3710
3711
3711
3712
3712 </body>
3713 </body>
3713 </html>
3714 </html>
3714
3715
3715 [1]
3716 [1]
3716
3717
3717 $ killdaemons.py
3718 $ killdaemons.py
3718
3719
3719 #endif
3720 #endif
General Comments 0
You need to be logged in to leave comments. Login now