##// END OF EJS Templates
help: don't try to render a section on sub-topics...
Gregory Szorc -
r29747:aba2bb2a default
parent child Browse files
Show More
@@ -1,7275 +1,7278 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import operator
12 import operator
13 import os
13 import os
14 import random
14 import random
15 import re
15 import re
16 import shlex
16 import shlex
17 import socket
17 import socket
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 import time
20 import time
21
21
22 from .i18n import _
22 from .i18n import _
23 from .node import (
23 from .node import (
24 bin,
24 bin,
25 hex,
25 hex,
26 nullhex,
26 nullhex,
27 nullid,
27 nullid,
28 nullrev,
28 nullrev,
29 short,
29 short,
30 )
30 )
31 from . import (
31 from . import (
32 archival,
32 archival,
33 bookmarks,
33 bookmarks,
34 bundle2,
34 bundle2,
35 changegroup,
35 changegroup,
36 cmdutil,
36 cmdutil,
37 commandserver,
37 commandserver,
38 context,
38 context,
39 copies,
39 copies,
40 dagparser,
40 dagparser,
41 dagutil,
41 dagutil,
42 destutil,
42 destutil,
43 discovery,
43 discovery,
44 encoding,
44 encoding,
45 error,
45 error,
46 exchange,
46 exchange,
47 extensions,
47 extensions,
48 fileset,
48 fileset,
49 formatter,
49 formatter,
50 graphmod,
50 graphmod,
51 hbisect,
51 hbisect,
52 help,
52 help,
53 hg,
53 hg,
54 hgweb,
54 hgweb,
55 localrepo,
55 localrepo,
56 lock as lockmod,
56 lock as lockmod,
57 merge as mergemod,
57 merge as mergemod,
58 minirst,
58 minirst,
59 obsolete,
59 obsolete,
60 patch,
60 patch,
61 phases,
61 phases,
62 policy,
62 policy,
63 pvec,
63 pvec,
64 repair,
64 repair,
65 revlog,
65 revlog,
66 revset,
66 revset,
67 scmutil,
67 scmutil,
68 setdiscovery,
68 setdiscovery,
69 simplemerge,
69 simplemerge,
70 sshserver,
70 sshserver,
71 streamclone,
71 streamclone,
72 templatekw,
72 templatekw,
73 templater,
73 templater,
74 treediscovery,
74 treediscovery,
75 ui as uimod,
75 ui as uimod,
76 util,
76 util,
77 )
77 )
78
78
79 release = lockmod.release
79 release = lockmod.release
80
80
81 table = {}
81 table = {}
82
82
83 command = cmdutil.command(table)
83 command = cmdutil.command(table)
84
84
85 # label constants
85 # label constants
86 # until 3.5, bookmarks.current was the advertised name, not
86 # until 3.5, bookmarks.current was the advertised name, not
87 # bookmarks.active, so we must use both to avoid breaking old
87 # bookmarks.active, so we must use both to avoid breaking old
88 # custom styles
88 # custom styles
89 activebookmarklabel = 'bookmarks.active bookmarks.current'
89 activebookmarklabel = 'bookmarks.active bookmarks.current'
90
90
91 # common command options
91 # common command options
92
92
93 globalopts = [
93 globalopts = [
94 ('R', 'repository', '',
94 ('R', 'repository', '',
95 _('repository root directory or name of overlay bundle file'),
95 _('repository root directory or name of overlay bundle file'),
96 _('REPO')),
96 _('REPO')),
97 ('', 'cwd', '',
97 ('', 'cwd', '',
98 _('change working directory'), _('DIR')),
98 _('change working directory'), _('DIR')),
99 ('y', 'noninteractive', None,
99 ('y', 'noninteractive', None,
100 _('do not prompt, automatically pick the first choice for all prompts')),
100 _('do not prompt, automatically pick the first choice for all prompts')),
101 ('q', 'quiet', None, _('suppress output')),
101 ('q', 'quiet', None, _('suppress output')),
102 ('v', 'verbose', None, _('enable additional output')),
102 ('v', 'verbose', None, _('enable additional output')),
103 ('', 'config', [],
103 ('', 'config', [],
104 _('set/override config option (use \'section.name=value\')'),
104 _('set/override config option (use \'section.name=value\')'),
105 _('CONFIG')),
105 _('CONFIG')),
106 ('', 'debug', None, _('enable debugging output')),
106 ('', 'debug', None, _('enable debugging output')),
107 ('', 'debugger', None, _('start debugger')),
107 ('', 'debugger', None, _('start debugger')),
108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
109 _('ENCODE')),
109 _('ENCODE')),
110 ('', 'encodingmode', encoding.encodingmode,
110 ('', 'encodingmode', encoding.encodingmode,
111 _('set the charset encoding mode'), _('MODE')),
111 _('set the charset encoding mode'), _('MODE')),
112 ('', 'traceback', None, _('always print a traceback on exception')),
112 ('', 'traceback', None, _('always print a traceback on exception')),
113 ('', 'time', None, _('time how long the command takes')),
113 ('', 'time', None, _('time how long the command takes')),
114 ('', 'profile', None, _('print command execution profile')),
114 ('', 'profile', None, _('print command execution profile')),
115 ('', 'version', None, _('output version information and exit')),
115 ('', 'version', None, _('output version information and exit')),
116 ('h', 'help', None, _('display help and exit')),
116 ('h', 'help', None, _('display help and exit')),
117 ('', 'hidden', False, _('consider hidden changesets')),
117 ('', 'hidden', False, _('consider hidden changesets')),
118 ]
118 ]
119
119
120 dryrunopts = [('n', 'dry-run', None,
120 dryrunopts = [('n', 'dry-run', None,
121 _('do not perform actions, just print output'))]
121 _('do not perform actions, just print output'))]
122
122
123 remoteopts = [
123 remoteopts = [
124 ('e', 'ssh', '',
124 ('e', 'ssh', '',
125 _('specify ssh command to use'), _('CMD')),
125 _('specify ssh command to use'), _('CMD')),
126 ('', 'remotecmd', '',
126 ('', 'remotecmd', '',
127 _('specify hg command to run on the remote side'), _('CMD')),
127 _('specify hg command to run on the remote side'), _('CMD')),
128 ('', 'insecure', None,
128 ('', 'insecure', None,
129 _('do not verify server certificate (ignoring web.cacerts config)')),
129 _('do not verify server certificate (ignoring web.cacerts config)')),
130 ]
130 ]
131
131
132 walkopts = [
132 walkopts = [
133 ('I', 'include', [],
133 ('I', 'include', [],
134 _('include names matching the given patterns'), _('PATTERN')),
134 _('include names matching the given patterns'), _('PATTERN')),
135 ('X', 'exclude', [],
135 ('X', 'exclude', [],
136 _('exclude names matching the given patterns'), _('PATTERN')),
136 _('exclude names matching the given patterns'), _('PATTERN')),
137 ]
137 ]
138
138
139 commitopts = [
139 commitopts = [
140 ('m', 'message', '',
140 ('m', 'message', '',
141 _('use text as commit message'), _('TEXT')),
141 _('use text as commit message'), _('TEXT')),
142 ('l', 'logfile', '',
142 ('l', 'logfile', '',
143 _('read commit message from file'), _('FILE')),
143 _('read commit message from file'), _('FILE')),
144 ]
144 ]
145
145
146 commitopts2 = [
146 commitopts2 = [
147 ('d', 'date', '',
147 ('d', 'date', '',
148 _('record the specified date as commit date'), _('DATE')),
148 _('record the specified date as commit date'), _('DATE')),
149 ('u', 'user', '',
149 ('u', 'user', '',
150 _('record the specified user as committer'), _('USER')),
150 _('record the specified user as committer'), _('USER')),
151 ]
151 ]
152
152
153 # hidden for now
153 # hidden for now
154 formatteropts = [
154 formatteropts = [
155 ('T', 'template', '',
155 ('T', 'template', '',
156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
157 ]
157 ]
158
158
159 templateopts = [
159 templateopts = [
160 ('', 'style', '',
160 ('', 'style', '',
161 _('display using template map file (DEPRECATED)'), _('STYLE')),
161 _('display using template map file (DEPRECATED)'), _('STYLE')),
162 ('T', 'template', '',
162 ('T', 'template', '',
163 _('display with template'), _('TEMPLATE')),
163 _('display with template'), _('TEMPLATE')),
164 ]
164 ]
165
165
166 logopts = [
166 logopts = [
167 ('p', 'patch', None, _('show patch')),
167 ('p', 'patch', None, _('show patch')),
168 ('g', 'git', None, _('use git extended diff format')),
168 ('g', 'git', None, _('use git extended diff format')),
169 ('l', 'limit', '',
169 ('l', 'limit', '',
170 _('limit number of changes displayed'), _('NUM')),
170 _('limit number of changes displayed'), _('NUM')),
171 ('M', 'no-merges', None, _('do not show merges')),
171 ('M', 'no-merges', None, _('do not show merges')),
172 ('', 'stat', None, _('output diffstat-style summary of changes')),
172 ('', 'stat', None, _('output diffstat-style summary of changes')),
173 ('G', 'graph', None, _("show the revision DAG")),
173 ('G', 'graph', None, _("show the revision DAG")),
174 ] + templateopts
174 ] + templateopts
175
175
176 diffopts = [
176 diffopts = [
177 ('a', 'text', None, _('treat all files as text')),
177 ('a', 'text', None, _('treat all files as text')),
178 ('g', 'git', None, _('use git extended diff format')),
178 ('g', 'git', None, _('use git extended diff format')),
179 ('', 'nodates', None, _('omit dates from diff headers'))
179 ('', 'nodates', None, _('omit dates from diff headers'))
180 ]
180 ]
181
181
182 diffwsopts = [
182 diffwsopts = [
183 ('w', 'ignore-all-space', None,
183 ('w', 'ignore-all-space', None,
184 _('ignore white space when comparing lines')),
184 _('ignore white space when comparing lines')),
185 ('b', 'ignore-space-change', None,
185 ('b', 'ignore-space-change', None,
186 _('ignore changes in the amount of white space')),
186 _('ignore changes in the amount of white space')),
187 ('B', 'ignore-blank-lines', None,
187 ('B', 'ignore-blank-lines', None,
188 _('ignore changes whose lines are all blank')),
188 _('ignore changes whose lines are all blank')),
189 ]
189 ]
190
190
191 diffopts2 = [
191 diffopts2 = [
192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
193 ('p', 'show-function', None, _('show which function each change is in')),
193 ('p', 'show-function', None, _('show which function each change is in')),
194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
195 ] + diffwsopts + [
195 ] + diffwsopts + [
196 ('U', 'unified', '',
196 ('U', 'unified', '',
197 _('number of lines of context to show'), _('NUM')),
197 _('number of lines of context to show'), _('NUM')),
198 ('', 'stat', None, _('output diffstat-style summary of changes')),
198 ('', 'stat', None, _('output diffstat-style summary of changes')),
199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
200 ]
200 ]
201
201
202 mergetoolopts = [
202 mergetoolopts = [
203 ('t', 'tool', '', _('specify merge tool')),
203 ('t', 'tool', '', _('specify merge tool')),
204 ]
204 ]
205
205
206 similarityopts = [
206 similarityopts = [
207 ('s', 'similarity', '',
207 ('s', 'similarity', '',
208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
209 ]
209 ]
210
210
211 subrepoopts = [
211 subrepoopts = [
212 ('S', 'subrepos', None,
212 ('S', 'subrepos', None,
213 _('recurse into subrepositories'))
213 _('recurse into subrepositories'))
214 ]
214 ]
215
215
216 debugrevlogopts = [
216 debugrevlogopts = [
217 ('c', 'changelog', False, _('open changelog')),
217 ('c', 'changelog', False, _('open changelog')),
218 ('m', 'manifest', False, _('open manifest')),
218 ('m', 'manifest', False, _('open manifest')),
219 ('', 'dir', '', _('open directory manifest')),
219 ('', 'dir', '', _('open directory manifest')),
220 ]
220 ]
221
221
222 # Commands start here, listed alphabetically
222 # Commands start here, listed alphabetically
223
223
224 @command('^add',
224 @command('^add',
225 walkopts + subrepoopts + dryrunopts,
225 walkopts + subrepoopts + dryrunopts,
226 _('[OPTION]... [FILE]...'),
226 _('[OPTION]... [FILE]...'),
227 inferrepo=True)
227 inferrepo=True)
228 def add(ui, repo, *pats, **opts):
228 def add(ui, repo, *pats, **opts):
229 """add the specified files on the next commit
229 """add the specified files on the next commit
230
230
231 Schedule files to be version controlled and added to the
231 Schedule files to be version controlled and added to the
232 repository.
232 repository.
233
233
234 The files will be added to the repository at the next commit. To
234 The files will be added to the repository at the next commit. To
235 undo an add before that, see :hg:`forget`.
235 undo an add before that, see :hg:`forget`.
236
236
237 If no names are given, add all files to the repository (except
237 If no names are given, add all files to the repository (except
238 files matching ``.hgignore``).
238 files matching ``.hgignore``).
239
239
240 .. container:: verbose
240 .. container:: verbose
241
241
242 Examples:
242 Examples:
243
243
244 - New (unknown) files are added
244 - New (unknown) files are added
245 automatically by :hg:`add`::
245 automatically by :hg:`add`::
246
246
247 $ ls
247 $ ls
248 foo.c
248 foo.c
249 $ hg status
249 $ hg status
250 ? foo.c
250 ? foo.c
251 $ hg add
251 $ hg add
252 adding foo.c
252 adding foo.c
253 $ hg status
253 $ hg status
254 A foo.c
254 A foo.c
255
255
256 - Specific files to be added can be specified::
256 - Specific files to be added can be specified::
257
257
258 $ ls
258 $ ls
259 bar.c foo.c
259 bar.c foo.c
260 $ hg status
260 $ hg status
261 ? bar.c
261 ? bar.c
262 ? foo.c
262 ? foo.c
263 $ hg add bar.c
263 $ hg add bar.c
264 $ hg status
264 $ hg status
265 A bar.c
265 A bar.c
266 ? foo.c
266 ? foo.c
267
267
268 Returns 0 if all files are successfully added.
268 Returns 0 if all files are successfully added.
269 """
269 """
270
270
271 m = scmutil.match(repo[None], pats, opts)
271 m = scmutil.match(repo[None], pats, opts)
272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
273 return rejected and 1 or 0
273 return rejected and 1 or 0
274
274
275 @command('addremove',
275 @command('addremove',
276 similarityopts + subrepoopts + walkopts + dryrunopts,
276 similarityopts + subrepoopts + walkopts + dryrunopts,
277 _('[OPTION]... [FILE]...'),
277 _('[OPTION]... [FILE]...'),
278 inferrepo=True)
278 inferrepo=True)
279 def addremove(ui, repo, *pats, **opts):
279 def addremove(ui, repo, *pats, **opts):
280 """add all new files, delete all missing files
280 """add all new files, delete all missing files
281
281
282 Add all new files and remove all missing files from the
282 Add all new files and remove all missing files from the
283 repository.
283 repository.
284
284
285 Unless names are given, new files are ignored if they match any of
285 Unless names are given, new files are ignored if they match any of
286 the patterns in ``.hgignore``. As with add, these changes take
286 the patterns in ``.hgignore``. As with add, these changes take
287 effect at the next commit.
287 effect at the next commit.
288
288
289 Use the -s/--similarity option to detect renamed files. This
289 Use the -s/--similarity option to detect renamed files. This
290 option takes a percentage between 0 (disabled) and 100 (files must
290 option takes a percentage between 0 (disabled) and 100 (files must
291 be identical) as its parameter. With a parameter greater than 0,
291 be identical) as its parameter. With a parameter greater than 0,
292 this compares every removed file with every added file and records
292 this compares every removed file with every added file and records
293 those similar enough as renames. Detecting renamed files this way
293 those similar enough as renames. Detecting renamed files this way
294 can be expensive. After using this option, :hg:`status -C` can be
294 can be expensive. After using this option, :hg:`status -C` can be
295 used to check which files were identified as moved or renamed. If
295 used to check which files were identified as moved or renamed. If
296 not specified, -s/--similarity defaults to 100 and only renames of
296 not specified, -s/--similarity defaults to 100 and only renames of
297 identical files are detected.
297 identical files are detected.
298
298
299 .. container:: verbose
299 .. container:: verbose
300
300
301 Examples:
301 Examples:
302
302
303 - A number of files (bar.c and foo.c) are new,
303 - A number of files (bar.c and foo.c) are new,
304 while foobar.c has been removed (without using :hg:`remove`)
304 while foobar.c has been removed (without using :hg:`remove`)
305 from the repository::
305 from the repository::
306
306
307 $ ls
307 $ ls
308 bar.c foo.c
308 bar.c foo.c
309 $ hg status
309 $ hg status
310 ! foobar.c
310 ! foobar.c
311 ? bar.c
311 ? bar.c
312 ? foo.c
312 ? foo.c
313 $ hg addremove
313 $ hg addremove
314 adding bar.c
314 adding bar.c
315 adding foo.c
315 adding foo.c
316 removing foobar.c
316 removing foobar.c
317 $ hg status
317 $ hg status
318 A bar.c
318 A bar.c
319 A foo.c
319 A foo.c
320 R foobar.c
320 R foobar.c
321
321
322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
323 Afterwards, it was edited slightly::
323 Afterwards, it was edited slightly::
324
324
325 $ ls
325 $ ls
326 foo.c
326 foo.c
327 $ hg status
327 $ hg status
328 ! foobar.c
328 ! foobar.c
329 ? foo.c
329 ? foo.c
330 $ hg addremove --similarity 90
330 $ hg addremove --similarity 90
331 removing foobar.c
331 removing foobar.c
332 adding foo.c
332 adding foo.c
333 recording removal of foobar.c as rename to foo.c (94% similar)
333 recording removal of foobar.c as rename to foo.c (94% similar)
334 $ hg status -C
334 $ hg status -C
335 A foo.c
335 A foo.c
336 foobar.c
336 foobar.c
337 R foobar.c
337 R foobar.c
338
338
339 Returns 0 if all files are successfully added.
339 Returns 0 if all files are successfully added.
340 """
340 """
341 try:
341 try:
342 sim = float(opts.get('similarity') or 100)
342 sim = float(opts.get('similarity') or 100)
343 except ValueError:
343 except ValueError:
344 raise error.Abort(_('similarity must be a number'))
344 raise error.Abort(_('similarity must be a number'))
345 if sim < 0 or sim > 100:
345 if sim < 0 or sim > 100:
346 raise error.Abort(_('similarity must be between 0 and 100'))
346 raise error.Abort(_('similarity must be between 0 and 100'))
347 matcher = scmutil.match(repo[None], pats, opts)
347 matcher = scmutil.match(repo[None], pats, opts)
348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
349
349
350 @command('^annotate|blame',
350 @command('^annotate|blame',
351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
352 ('', 'follow', None,
352 ('', 'follow', None,
353 _('follow copies/renames and list the filename (DEPRECATED)')),
353 _('follow copies/renames and list the filename (DEPRECATED)')),
354 ('', 'no-follow', None, _("don't follow copies and renames")),
354 ('', 'no-follow', None, _("don't follow copies and renames")),
355 ('a', 'text', None, _('treat all files as text')),
355 ('a', 'text', None, _('treat all files as text')),
356 ('u', 'user', None, _('list the author (long with -v)')),
356 ('u', 'user', None, _('list the author (long with -v)')),
357 ('f', 'file', None, _('list the filename')),
357 ('f', 'file', None, _('list the filename')),
358 ('d', 'date', None, _('list the date (short with -q)')),
358 ('d', 'date', None, _('list the date (short with -q)')),
359 ('n', 'number', None, _('list the revision number (default)')),
359 ('n', 'number', None, _('list the revision number (default)')),
360 ('c', 'changeset', None, _('list the changeset')),
360 ('c', 'changeset', None, _('list the changeset')),
361 ('l', 'line-number', None, _('show line number at the first appearance'))
361 ('l', 'line-number', None, _('show line number at the first appearance'))
362 ] + diffwsopts + walkopts + formatteropts,
362 ] + diffwsopts + walkopts + formatteropts,
363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
364 inferrepo=True)
364 inferrepo=True)
365 def annotate(ui, repo, *pats, **opts):
365 def annotate(ui, repo, *pats, **opts):
366 """show changeset information by line for each file
366 """show changeset information by line for each file
367
367
368 List changes in files, showing the revision id responsible for
368 List changes in files, showing the revision id responsible for
369 each line.
369 each line.
370
370
371 This command is useful for discovering when a change was made and
371 This command is useful for discovering when a change was made and
372 by whom.
372 by whom.
373
373
374 If you include --file, --user, or --date, the revision number is
374 If you include --file, --user, or --date, the revision number is
375 suppressed unless you also include --number.
375 suppressed unless you also include --number.
376
376
377 Without the -a/--text option, annotate will avoid processing files
377 Without the -a/--text option, annotate will avoid processing files
378 it detects as binary. With -a, annotate will annotate the file
378 it detects as binary. With -a, annotate will annotate the file
379 anyway, although the results will probably be neither useful
379 anyway, although the results will probably be neither useful
380 nor desirable.
380 nor desirable.
381
381
382 Returns 0 on success.
382 Returns 0 on success.
383 """
383 """
384 if not pats:
384 if not pats:
385 raise error.Abort(_('at least one filename or pattern is required'))
385 raise error.Abort(_('at least one filename or pattern is required'))
386
386
387 if opts.get('follow'):
387 if opts.get('follow'):
388 # --follow is deprecated and now just an alias for -f/--file
388 # --follow is deprecated and now just an alias for -f/--file
389 # to mimic the behavior of Mercurial before version 1.5
389 # to mimic the behavior of Mercurial before version 1.5
390 opts['file'] = True
390 opts['file'] = True
391
391
392 ctx = scmutil.revsingle(repo, opts.get('rev'))
392 ctx = scmutil.revsingle(repo, opts.get('rev'))
393
393
394 fm = ui.formatter('annotate', opts)
394 fm = ui.formatter('annotate', opts)
395 if ui.quiet:
395 if ui.quiet:
396 datefunc = util.shortdate
396 datefunc = util.shortdate
397 else:
397 else:
398 datefunc = util.datestr
398 datefunc = util.datestr
399 if ctx.rev() is None:
399 if ctx.rev() is None:
400 def hexfn(node):
400 def hexfn(node):
401 if node is None:
401 if node is None:
402 return None
402 return None
403 else:
403 else:
404 return fm.hexfunc(node)
404 return fm.hexfunc(node)
405 if opts.get('changeset'):
405 if opts.get('changeset'):
406 # omit "+" suffix which is appended to node hex
406 # omit "+" suffix which is appended to node hex
407 def formatrev(rev):
407 def formatrev(rev):
408 if rev is None:
408 if rev is None:
409 return '%d' % ctx.p1().rev()
409 return '%d' % ctx.p1().rev()
410 else:
410 else:
411 return '%d' % rev
411 return '%d' % rev
412 else:
412 else:
413 def formatrev(rev):
413 def formatrev(rev):
414 if rev is None:
414 if rev is None:
415 return '%d+' % ctx.p1().rev()
415 return '%d+' % ctx.p1().rev()
416 else:
416 else:
417 return '%d ' % rev
417 return '%d ' % rev
418 def formathex(hex):
418 def formathex(hex):
419 if hex is None:
419 if hex is None:
420 return '%s+' % fm.hexfunc(ctx.p1().node())
420 return '%s+' % fm.hexfunc(ctx.p1().node())
421 else:
421 else:
422 return '%s ' % hex
422 return '%s ' % hex
423 else:
423 else:
424 hexfn = fm.hexfunc
424 hexfn = fm.hexfunc
425 formatrev = formathex = str
425 formatrev = formathex = str
426
426
427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
428 ('number', ' ', lambda x: x[0].rev(), formatrev),
428 ('number', ' ', lambda x: x[0].rev(), formatrev),
429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
431 ('file', ' ', lambda x: x[0].path(), str),
431 ('file', ' ', lambda x: x[0].path(), str),
432 ('line_number', ':', lambda x: x[1], str),
432 ('line_number', ':', lambda x: x[1], str),
433 ]
433 ]
434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
435
435
436 if (not opts.get('user') and not opts.get('changeset')
436 if (not opts.get('user') and not opts.get('changeset')
437 and not opts.get('date') and not opts.get('file')):
437 and not opts.get('date') and not opts.get('file')):
438 opts['number'] = True
438 opts['number'] = True
439
439
440 linenumber = opts.get('line_number') is not None
440 linenumber = opts.get('line_number') is not None
441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
442 raise error.Abort(_('at least one of -n/-c is required for -l'))
442 raise error.Abort(_('at least one of -n/-c is required for -l'))
443
443
444 if fm:
444 if fm:
445 def makefunc(get, fmt):
445 def makefunc(get, fmt):
446 return get
446 return get
447 else:
447 else:
448 def makefunc(get, fmt):
448 def makefunc(get, fmt):
449 return lambda x: fmt(get(x))
449 return lambda x: fmt(get(x))
450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
451 if opts.get(op)]
451 if opts.get(op)]
452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
454 if opts.get(op))
454 if opts.get(op))
455
455
456 def bad(x, y):
456 def bad(x, y):
457 raise error.Abort("%s: %s" % (x, y))
457 raise error.Abort("%s: %s" % (x, y))
458
458
459 m = scmutil.match(ctx, pats, opts, badfn=bad)
459 m = scmutil.match(ctx, pats, opts, badfn=bad)
460
460
461 follow = not opts.get('no_follow')
461 follow = not opts.get('no_follow')
462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
463 whitespace=True)
463 whitespace=True)
464 for abs in ctx.walk(m):
464 for abs in ctx.walk(m):
465 fctx = ctx[abs]
465 fctx = ctx[abs]
466 if not opts.get('text') and util.binary(fctx.data()):
466 if not opts.get('text') and util.binary(fctx.data()):
467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
468 continue
468 continue
469
469
470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
471 diffopts=diffopts)
471 diffopts=diffopts)
472 if not lines:
472 if not lines:
473 continue
473 continue
474 formats = []
474 formats = []
475 pieces = []
475 pieces = []
476
476
477 for f, sep in funcmap:
477 for f, sep in funcmap:
478 l = [f(n) for n, dummy in lines]
478 l = [f(n) for n, dummy in lines]
479 if fm:
479 if fm:
480 formats.append(['%s' for x in l])
480 formats.append(['%s' for x in l])
481 else:
481 else:
482 sizes = [encoding.colwidth(x) for x in l]
482 sizes = [encoding.colwidth(x) for x in l]
483 ml = max(sizes)
483 ml = max(sizes)
484 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
484 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
485 pieces.append(l)
485 pieces.append(l)
486
486
487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
488 fm.startitem()
488 fm.startitem()
489 fm.write(fields, "".join(f), *p)
489 fm.write(fields, "".join(f), *p)
490 fm.write('line', ": %s", l[1])
490 fm.write('line', ": %s", l[1])
491
491
492 if not lines[-1][1].endswith('\n'):
492 if not lines[-1][1].endswith('\n'):
493 fm.plain('\n')
493 fm.plain('\n')
494
494
495 fm.end()
495 fm.end()
496
496
497 @command('archive',
497 @command('archive',
498 [('', 'no-decode', None, _('do not pass files through decoders')),
498 [('', 'no-decode', None, _('do not pass files through decoders')),
499 ('p', 'prefix', '', _('directory prefix for files in archive'),
499 ('p', 'prefix', '', _('directory prefix for files in archive'),
500 _('PREFIX')),
500 _('PREFIX')),
501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
503 ] + subrepoopts + walkopts,
503 ] + subrepoopts + walkopts,
504 _('[OPTION]... DEST'))
504 _('[OPTION]... DEST'))
505 def archive(ui, repo, dest, **opts):
505 def archive(ui, repo, dest, **opts):
506 '''create an unversioned archive of a repository revision
506 '''create an unversioned archive of a repository revision
507
507
508 By default, the revision used is the parent of the working
508 By default, the revision used is the parent of the working
509 directory; use -r/--rev to specify a different revision.
509 directory; use -r/--rev to specify a different revision.
510
510
511 The archive type is automatically detected based on file
511 The archive type is automatically detected based on file
512 extension (to override, use -t/--type).
512 extension (to override, use -t/--type).
513
513
514 .. container:: verbose
514 .. container:: verbose
515
515
516 Examples:
516 Examples:
517
517
518 - create a zip file containing the 1.0 release::
518 - create a zip file containing the 1.0 release::
519
519
520 hg archive -r 1.0 project-1.0.zip
520 hg archive -r 1.0 project-1.0.zip
521
521
522 - create a tarball excluding .hg files::
522 - create a tarball excluding .hg files::
523
523
524 hg archive project.tar.gz -X ".hg*"
524 hg archive project.tar.gz -X ".hg*"
525
525
526 Valid types are:
526 Valid types are:
527
527
528 :``files``: a directory full of files (default)
528 :``files``: a directory full of files (default)
529 :``tar``: tar archive, uncompressed
529 :``tar``: tar archive, uncompressed
530 :``tbz2``: tar archive, compressed using bzip2
530 :``tbz2``: tar archive, compressed using bzip2
531 :``tgz``: tar archive, compressed using gzip
531 :``tgz``: tar archive, compressed using gzip
532 :``uzip``: zip archive, uncompressed
532 :``uzip``: zip archive, uncompressed
533 :``zip``: zip archive, compressed using deflate
533 :``zip``: zip archive, compressed using deflate
534
534
535 The exact name of the destination archive or directory is given
535 The exact name of the destination archive or directory is given
536 using a format string; see :hg:`help export` for details.
536 using a format string; see :hg:`help export` for details.
537
537
538 Each member added to an archive file has a directory prefix
538 Each member added to an archive file has a directory prefix
539 prepended. Use -p/--prefix to specify a format string for the
539 prepended. Use -p/--prefix to specify a format string for the
540 prefix. The default is the basename of the archive, with suffixes
540 prefix. The default is the basename of the archive, with suffixes
541 removed.
541 removed.
542
542
543 Returns 0 on success.
543 Returns 0 on success.
544 '''
544 '''
545
545
546 ctx = scmutil.revsingle(repo, opts.get('rev'))
546 ctx = scmutil.revsingle(repo, opts.get('rev'))
547 if not ctx:
547 if not ctx:
548 raise error.Abort(_('no working directory: please specify a revision'))
548 raise error.Abort(_('no working directory: please specify a revision'))
549 node = ctx.node()
549 node = ctx.node()
550 dest = cmdutil.makefilename(repo, dest, node)
550 dest = cmdutil.makefilename(repo, dest, node)
551 if os.path.realpath(dest) == repo.root:
551 if os.path.realpath(dest) == repo.root:
552 raise error.Abort(_('repository root cannot be destination'))
552 raise error.Abort(_('repository root cannot be destination'))
553
553
554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
555 prefix = opts.get('prefix')
555 prefix = opts.get('prefix')
556
556
557 if dest == '-':
557 if dest == '-':
558 if kind == 'files':
558 if kind == 'files':
559 raise error.Abort(_('cannot archive plain files to stdout'))
559 raise error.Abort(_('cannot archive plain files to stdout'))
560 dest = cmdutil.makefileobj(repo, dest)
560 dest = cmdutil.makefileobj(repo, dest)
561 if not prefix:
561 if not prefix:
562 prefix = os.path.basename(repo.root) + '-%h'
562 prefix = os.path.basename(repo.root) + '-%h'
563
563
564 prefix = cmdutil.makefilename(repo, prefix, node)
564 prefix = cmdutil.makefilename(repo, prefix, node)
565 matchfn = scmutil.match(ctx, [], opts)
565 matchfn = scmutil.match(ctx, [], opts)
566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
567 matchfn, prefix, subrepos=opts.get('subrepos'))
567 matchfn, prefix, subrepos=opts.get('subrepos'))
568
568
569 @command('backout',
569 @command('backout',
570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
571 ('', 'commit', None,
571 ('', 'commit', None,
572 _('commit if no conflicts were encountered (DEPRECATED)')),
572 _('commit if no conflicts were encountered (DEPRECATED)')),
573 ('', 'no-commit', None, _('do not commit')),
573 ('', 'no-commit', None, _('do not commit')),
574 ('', 'parent', '',
574 ('', 'parent', '',
575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
576 ('r', 'rev', '', _('revision to backout'), _('REV')),
576 ('r', 'rev', '', _('revision to backout'), _('REV')),
577 ('e', 'edit', False, _('invoke editor on commit messages')),
577 ('e', 'edit', False, _('invoke editor on commit messages')),
578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
579 _('[OPTION]... [-r] REV'))
579 _('[OPTION]... [-r] REV'))
580 def backout(ui, repo, node=None, rev=None, **opts):
580 def backout(ui, repo, node=None, rev=None, **opts):
581 '''reverse effect of earlier changeset
581 '''reverse effect of earlier changeset
582
582
583 Prepare a new changeset with the effect of REV undone in the
583 Prepare a new changeset with the effect of REV undone in the
584 current working directory. If no conflicts were encountered,
584 current working directory. If no conflicts were encountered,
585 it will be committed immediately.
585 it will be committed immediately.
586
586
587 If REV is the parent of the working directory, then this new changeset
587 If REV is the parent of the working directory, then this new changeset
588 is committed automatically (unless --no-commit is specified).
588 is committed automatically (unless --no-commit is specified).
589
589
590 .. note::
590 .. note::
591
591
592 :hg:`backout` cannot be used to fix either an unwanted or
592 :hg:`backout` cannot be used to fix either an unwanted or
593 incorrect merge.
593 incorrect merge.
594
594
595 .. container:: verbose
595 .. container:: verbose
596
596
597 Examples:
597 Examples:
598
598
599 - Reverse the effect of the parent of the working directory.
599 - Reverse the effect of the parent of the working directory.
600 This backout will be committed immediately::
600 This backout will be committed immediately::
601
601
602 hg backout -r .
602 hg backout -r .
603
603
604 - Reverse the effect of previous bad revision 23::
604 - Reverse the effect of previous bad revision 23::
605
605
606 hg backout -r 23
606 hg backout -r 23
607
607
608 - Reverse the effect of previous bad revision 23 and
608 - Reverse the effect of previous bad revision 23 and
609 leave changes uncommitted::
609 leave changes uncommitted::
610
610
611 hg backout -r 23 --no-commit
611 hg backout -r 23 --no-commit
612 hg commit -m "Backout revision 23"
612 hg commit -m "Backout revision 23"
613
613
614 By default, the pending changeset will have one parent,
614 By default, the pending changeset will have one parent,
615 maintaining a linear history. With --merge, the pending
615 maintaining a linear history. With --merge, the pending
616 changeset will instead have two parents: the old parent of the
616 changeset will instead have two parents: the old parent of the
617 working directory and a new child of REV that simply undoes REV.
617 working directory and a new child of REV that simply undoes REV.
618
618
619 Before version 1.7, the behavior without --merge was equivalent
619 Before version 1.7, the behavior without --merge was equivalent
620 to specifying --merge followed by :hg:`update --clean .` to
620 to specifying --merge followed by :hg:`update --clean .` to
621 cancel the merge and leave the child of REV as a head to be
621 cancel the merge and leave the child of REV as a head to be
622 merged separately.
622 merged separately.
623
623
624 See :hg:`help dates` for a list of formats valid for -d/--date.
624 See :hg:`help dates` for a list of formats valid for -d/--date.
625
625
626 See :hg:`help revert` for a way to restore files to the state
626 See :hg:`help revert` for a way to restore files to the state
627 of another revision.
627 of another revision.
628
628
629 Returns 0 on success, 1 if nothing to backout or there are unresolved
629 Returns 0 on success, 1 if nothing to backout or there are unresolved
630 files.
630 files.
631 '''
631 '''
632 wlock = lock = None
632 wlock = lock = None
633 try:
633 try:
634 wlock = repo.wlock()
634 wlock = repo.wlock()
635 lock = repo.lock()
635 lock = repo.lock()
636 return _dobackout(ui, repo, node, rev, **opts)
636 return _dobackout(ui, repo, node, rev, **opts)
637 finally:
637 finally:
638 release(lock, wlock)
638 release(lock, wlock)
639
639
640 def _dobackout(ui, repo, node=None, rev=None, **opts):
640 def _dobackout(ui, repo, node=None, rev=None, **opts):
641 if opts.get('commit') and opts.get('no_commit'):
641 if opts.get('commit') and opts.get('no_commit'):
642 raise error.Abort(_("cannot use --commit with --no-commit"))
642 raise error.Abort(_("cannot use --commit with --no-commit"))
643 if opts.get('merge') and opts.get('no_commit'):
643 if opts.get('merge') and opts.get('no_commit'):
644 raise error.Abort(_("cannot use --merge with --no-commit"))
644 raise error.Abort(_("cannot use --merge with --no-commit"))
645
645
646 if rev and node:
646 if rev and node:
647 raise error.Abort(_("please specify just one revision"))
647 raise error.Abort(_("please specify just one revision"))
648
648
649 if not rev:
649 if not rev:
650 rev = node
650 rev = node
651
651
652 if not rev:
652 if not rev:
653 raise error.Abort(_("please specify a revision to backout"))
653 raise error.Abort(_("please specify a revision to backout"))
654
654
655 date = opts.get('date')
655 date = opts.get('date')
656 if date:
656 if date:
657 opts['date'] = util.parsedate(date)
657 opts['date'] = util.parsedate(date)
658
658
659 cmdutil.checkunfinished(repo)
659 cmdutil.checkunfinished(repo)
660 cmdutil.bailifchanged(repo)
660 cmdutil.bailifchanged(repo)
661 node = scmutil.revsingle(repo, rev).node()
661 node = scmutil.revsingle(repo, rev).node()
662
662
663 op1, op2 = repo.dirstate.parents()
663 op1, op2 = repo.dirstate.parents()
664 if not repo.changelog.isancestor(node, op1):
664 if not repo.changelog.isancestor(node, op1):
665 raise error.Abort(_('cannot backout change that is not an ancestor'))
665 raise error.Abort(_('cannot backout change that is not an ancestor'))
666
666
667 p1, p2 = repo.changelog.parents(node)
667 p1, p2 = repo.changelog.parents(node)
668 if p1 == nullid:
668 if p1 == nullid:
669 raise error.Abort(_('cannot backout a change with no parents'))
669 raise error.Abort(_('cannot backout a change with no parents'))
670 if p2 != nullid:
670 if p2 != nullid:
671 if not opts.get('parent'):
671 if not opts.get('parent'):
672 raise error.Abort(_('cannot backout a merge changeset'))
672 raise error.Abort(_('cannot backout a merge changeset'))
673 p = repo.lookup(opts['parent'])
673 p = repo.lookup(opts['parent'])
674 if p not in (p1, p2):
674 if p not in (p1, p2):
675 raise error.Abort(_('%s is not a parent of %s') %
675 raise error.Abort(_('%s is not a parent of %s') %
676 (short(p), short(node)))
676 (short(p), short(node)))
677 parent = p
677 parent = p
678 else:
678 else:
679 if opts.get('parent'):
679 if opts.get('parent'):
680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
681 parent = p1
681 parent = p1
682
682
683 # the backout should appear on the same branch
683 # the backout should appear on the same branch
684 branch = repo.dirstate.branch()
684 branch = repo.dirstate.branch()
685 bheads = repo.branchheads(branch)
685 bheads = repo.branchheads(branch)
686 rctx = scmutil.revsingle(repo, hex(parent))
686 rctx = scmutil.revsingle(repo, hex(parent))
687 if not opts.get('merge') and op1 != node:
687 if not opts.get('merge') and op1 != node:
688 dsguard = cmdutil.dirstateguard(repo, 'backout')
688 dsguard = cmdutil.dirstateguard(repo, 'backout')
689 try:
689 try:
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
691 'backout')
691 'backout')
692 stats = mergemod.update(repo, parent, True, True, node, False)
692 stats = mergemod.update(repo, parent, True, True, node, False)
693 repo.setparents(op1, op2)
693 repo.setparents(op1, op2)
694 dsguard.close()
694 dsguard.close()
695 hg._showstats(repo, stats)
695 hg._showstats(repo, stats)
696 if stats[3]:
696 if stats[3]:
697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
698 "file merges\n"))
698 "file merges\n"))
699 return 1
699 return 1
700 finally:
700 finally:
701 ui.setconfig('ui', 'forcemerge', '', '')
701 ui.setconfig('ui', 'forcemerge', '', '')
702 lockmod.release(dsguard)
702 lockmod.release(dsguard)
703 else:
703 else:
704 hg.clean(repo, node, show_stats=False)
704 hg.clean(repo, node, show_stats=False)
705 repo.dirstate.setbranch(branch)
705 repo.dirstate.setbranch(branch)
706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
707
707
708 if opts.get('no_commit'):
708 if opts.get('no_commit'):
709 msg = _("changeset %s backed out, "
709 msg = _("changeset %s backed out, "
710 "don't forget to commit.\n")
710 "don't forget to commit.\n")
711 ui.status(msg % short(node))
711 ui.status(msg % short(node))
712 return 0
712 return 0
713
713
714 def commitfunc(ui, repo, message, match, opts):
714 def commitfunc(ui, repo, message, match, opts):
715 editform = 'backout'
715 editform = 'backout'
716 e = cmdutil.getcommiteditor(editform=editform, **opts)
716 e = cmdutil.getcommiteditor(editform=editform, **opts)
717 if not message:
717 if not message:
718 # we don't translate commit messages
718 # we don't translate commit messages
719 message = "Backed out changeset %s" % short(node)
719 message = "Backed out changeset %s" % short(node)
720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
721 return repo.commit(message, opts.get('user'), opts.get('date'),
721 return repo.commit(message, opts.get('user'), opts.get('date'),
722 match, editor=e)
722 match, editor=e)
723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
724 if not newnode:
724 if not newnode:
725 ui.status(_("nothing changed\n"))
725 ui.status(_("nothing changed\n"))
726 return 1
726 return 1
727 cmdutil.commitstatus(repo, newnode, branch, bheads)
727 cmdutil.commitstatus(repo, newnode, branch, bheads)
728
728
729 def nice(node):
729 def nice(node):
730 return '%d:%s' % (repo.changelog.rev(node), short(node))
730 return '%d:%s' % (repo.changelog.rev(node), short(node))
731 ui.status(_('changeset %s backs out changeset %s\n') %
731 ui.status(_('changeset %s backs out changeset %s\n') %
732 (nice(repo.changelog.tip()), nice(node)))
732 (nice(repo.changelog.tip()), nice(node)))
733 if opts.get('merge') and op1 != node:
733 if opts.get('merge') and op1 != node:
734 hg.clean(repo, op1, show_stats=False)
734 hg.clean(repo, op1, show_stats=False)
735 ui.status(_('merging with changeset %s\n')
735 ui.status(_('merging with changeset %s\n')
736 % nice(repo.changelog.tip()))
736 % nice(repo.changelog.tip()))
737 try:
737 try:
738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
739 'backout')
739 'backout')
740 return hg.merge(repo, hex(repo.changelog.tip()))
740 return hg.merge(repo, hex(repo.changelog.tip()))
741 finally:
741 finally:
742 ui.setconfig('ui', 'forcemerge', '', '')
742 ui.setconfig('ui', 'forcemerge', '', '')
743 return 0
743 return 0
744
744
745 @command('bisect',
745 @command('bisect',
746 [('r', 'reset', False, _('reset bisect state')),
746 [('r', 'reset', False, _('reset bisect state')),
747 ('g', 'good', False, _('mark changeset good')),
747 ('g', 'good', False, _('mark changeset good')),
748 ('b', 'bad', False, _('mark changeset bad')),
748 ('b', 'bad', False, _('mark changeset bad')),
749 ('s', 'skip', False, _('skip testing changeset')),
749 ('s', 'skip', False, _('skip testing changeset')),
750 ('e', 'extend', False, _('extend the bisect range')),
750 ('e', 'extend', False, _('extend the bisect range')),
751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
752 ('U', 'noupdate', False, _('do not update to target'))],
752 ('U', 'noupdate', False, _('do not update to target'))],
753 _("[-gbsr] [-U] [-c CMD] [REV]"))
753 _("[-gbsr] [-U] [-c CMD] [REV]"))
754 def bisect(ui, repo, rev=None, extra=None, command=None,
754 def bisect(ui, repo, rev=None, extra=None, command=None,
755 reset=None, good=None, bad=None, skip=None, extend=None,
755 reset=None, good=None, bad=None, skip=None, extend=None,
756 noupdate=None):
756 noupdate=None):
757 """subdivision search of changesets
757 """subdivision search of changesets
758
758
759 This command helps to find changesets which introduce problems. To
759 This command helps to find changesets which introduce problems. To
760 use, mark the earliest changeset you know exhibits the problem as
760 use, mark the earliest changeset you know exhibits the problem as
761 bad, then mark the latest changeset which is free from the problem
761 bad, then mark the latest changeset which is free from the problem
762 as good. Bisect will update your working directory to a revision
762 as good. Bisect will update your working directory to a revision
763 for testing (unless the -U/--noupdate option is specified). Once
763 for testing (unless the -U/--noupdate option is specified). Once
764 you have performed tests, mark the working directory as good or
764 you have performed tests, mark the working directory as good or
765 bad, and bisect will either update to another candidate changeset
765 bad, and bisect will either update to another candidate changeset
766 or announce that it has found the bad revision.
766 or announce that it has found the bad revision.
767
767
768 As a shortcut, you can also use the revision argument to mark a
768 As a shortcut, you can also use the revision argument to mark a
769 revision as good or bad without checking it out first.
769 revision as good or bad without checking it out first.
770
770
771 If you supply a command, it will be used for automatic bisection.
771 If you supply a command, it will be used for automatic bisection.
772 The environment variable HG_NODE will contain the ID of the
772 The environment variable HG_NODE will contain the ID of the
773 changeset being tested. The exit status of the command will be
773 changeset being tested. The exit status of the command will be
774 used to mark revisions as good or bad: status 0 means good, 125
774 used to mark revisions as good or bad: status 0 means good, 125
775 means to skip the revision, 127 (command not found) will abort the
775 means to skip the revision, 127 (command not found) will abort the
776 bisection, and any other non-zero exit status means the revision
776 bisection, and any other non-zero exit status means the revision
777 is bad.
777 is bad.
778
778
779 .. container:: verbose
779 .. container:: verbose
780
780
781 Some examples:
781 Some examples:
782
782
783 - start a bisection with known bad revision 34, and good revision 12::
783 - start a bisection with known bad revision 34, and good revision 12::
784
784
785 hg bisect --bad 34
785 hg bisect --bad 34
786 hg bisect --good 12
786 hg bisect --good 12
787
787
788 - advance the current bisection by marking current revision as good or
788 - advance the current bisection by marking current revision as good or
789 bad::
789 bad::
790
790
791 hg bisect --good
791 hg bisect --good
792 hg bisect --bad
792 hg bisect --bad
793
793
794 - mark the current revision, or a known revision, to be skipped (e.g. if
794 - mark the current revision, or a known revision, to be skipped (e.g. if
795 that revision is not usable because of another issue)::
795 that revision is not usable because of another issue)::
796
796
797 hg bisect --skip
797 hg bisect --skip
798 hg bisect --skip 23
798 hg bisect --skip 23
799
799
800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
801
801
802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
803
803
804 - forget the current bisection::
804 - forget the current bisection::
805
805
806 hg bisect --reset
806 hg bisect --reset
807
807
808 - use 'make && make tests' to automatically find the first broken
808 - use 'make && make tests' to automatically find the first broken
809 revision::
809 revision::
810
810
811 hg bisect --reset
811 hg bisect --reset
812 hg bisect --bad 34
812 hg bisect --bad 34
813 hg bisect --good 12
813 hg bisect --good 12
814 hg bisect --command "make && make tests"
814 hg bisect --command "make && make tests"
815
815
816 - see all changesets whose states are already known in the current
816 - see all changesets whose states are already known in the current
817 bisection::
817 bisection::
818
818
819 hg log -r "bisect(pruned)"
819 hg log -r "bisect(pruned)"
820
820
821 - see the changeset currently being bisected (especially useful
821 - see the changeset currently being bisected (especially useful
822 if running with -U/--noupdate)::
822 if running with -U/--noupdate)::
823
823
824 hg log -r "bisect(current)"
824 hg log -r "bisect(current)"
825
825
826 - see all changesets that took part in the current bisection::
826 - see all changesets that took part in the current bisection::
827
827
828 hg log -r "bisect(range)"
828 hg log -r "bisect(range)"
829
829
830 - you can even get a nice graph::
830 - you can even get a nice graph::
831
831
832 hg log --graph -r "bisect(range)"
832 hg log --graph -r "bisect(range)"
833
833
834 See :hg:`help revsets` for more about the `bisect()` keyword.
834 See :hg:`help revsets` for more about the `bisect()` keyword.
835
835
836 Returns 0 on success.
836 Returns 0 on success.
837 """
837 """
838 def extendbisectrange(nodes, good):
838 def extendbisectrange(nodes, good):
839 # bisect is incomplete when it ends on a merge node and
839 # bisect is incomplete when it ends on a merge node and
840 # one of the parent was not checked.
840 # one of the parent was not checked.
841 parents = repo[nodes[0]].parents()
841 parents = repo[nodes[0]].parents()
842 if len(parents) > 1:
842 if len(parents) > 1:
843 if good:
843 if good:
844 side = state['bad']
844 side = state['bad']
845 else:
845 else:
846 side = state['good']
846 side = state['good']
847 num = len(set(i.node() for i in parents) & set(side))
847 num = len(set(i.node() for i in parents) & set(side))
848 if num == 1:
848 if num == 1:
849 return parents[0].ancestor(parents[1])
849 return parents[0].ancestor(parents[1])
850 return None
850 return None
851
851
852 def print_result(nodes, good):
852 def print_result(nodes, good):
853 displayer = cmdutil.show_changeset(ui, repo, {})
853 displayer = cmdutil.show_changeset(ui, repo, {})
854 if len(nodes) == 1:
854 if len(nodes) == 1:
855 # narrowed it down to a single revision
855 # narrowed it down to a single revision
856 if good:
856 if good:
857 ui.write(_("The first good revision is:\n"))
857 ui.write(_("The first good revision is:\n"))
858 else:
858 else:
859 ui.write(_("The first bad revision is:\n"))
859 ui.write(_("The first bad revision is:\n"))
860 displayer.show(repo[nodes[0]])
860 displayer.show(repo[nodes[0]])
861 extendnode = extendbisectrange(nodes, good)
861 extendnode = extendbisectrange(nodes, good)
862 if extendnode is not None:
862 if extendnode is not None:
863 ui.write(_('Not all ancestors of this changeset have been'
863 ui.write(_('Not all ancestors of this changeset have been'
864 ' checked.\nUse bisect --extend to continue the '
864 ' checked.\nUse bisect --extend to continue the '
865 'bisection from\nthe common ancestor, %s.\n')
865 'bisection from\nthe common ancestor, %s.\n')
866 % extendnode)
866 % extendnode)
867 else:
867 else:
868 # multiple possible revisions
868 # multiple possible revisions
869 if good:
869 if good:
870 ui.write(_("Due to skipped revisions, the first "
870 ui.write(_("Due to skipped revisions, the first "
871 "good revision could be any of:\n"))
871 "good revision could be any of:\n"))
872 else:
872 else:
873 ui.write(_("Due to skipped revisions, the first "
873 ui.write(_("Due to skipped revisions, the first "
874 "bad revision could be any of:\n"))
874 "bad revision could be any of:\n"))
875 for n in nodes:
875 for n in nodes:
876 displayer.show(repo[n])
876 displayer.show(repo[n])
877 displayer.close()
877 displayer.close()
878
878
879 def check_state(state, interactive=True):
879 def check_state(state, interactive=True):
880 if not state['good'] or not state['bad']:
880 if not state['good'] or not state['bad']:
881 if (good or bad or skip or reset) and interactive:
881 if (good or bad or skip or reset) and interactive:
882 return
882 return
883 if not state['good']:
883 if not state['good']:
884 raise error.Abort(_('cannot bisect (no known good revisions)'))
884 raise error.Abort(_('cannot bisect (no known good revisions)'))
885 else:
885 else:
886 raise error.Abort(_('cannot bisect (no known bad revisions)'))
886 raise error.Abort(_('cannot bisect (no known bad revisions)'))
887 return True
887 return True
888
888
889 # backward compatibility
889 # backward compatibility
890 if rev in "good bad reset init".split():
890 if rev in "good bad reset init".split():
891 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
891 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
892 cmd, rev, extra = rev, extra, None
892 cmd, rev, extra = rev, extra, None
893 if cmd == "good":
893 if cmd == "good":
894 good = True
894 good = True
895 elif cmd == "bad":
895 elif cmd == "bad":
896 bad = True
896 bad = True
897 else:
897 else:
898 reset = True
898 reset = True
899 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
899 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
900 raise error.Abort(_('incompatible arguments'))
900 raise error.Abort(_('incompatible arguments'))
901
901
902 cmdutil.checkunfinished(repo)
902 cmdutil.checkunfinished(repo)
903
903
904 if reset:
904 if reset:
905 p = repo.join("bisect.state")
905 p = repo.join("bisect.state")
906 if os.path.exists(p):
906 if os.path.exists(p):
907 os.unlink(p)
907 os.unlink(p)
908 return
908 return
909
909
910 state = hbisect.load_state(repo)
910 state = hbisect.load_state(repo)
911
911
912 if command:
912 if command:
913 changesets = 1
913 changesets = 1
914 if noupdate:
914 if noupdate:
915 try:
915 try:
916 node = state['current'][0]
916 node = state['current'][0]
917 except LookupError:
917 except LookupError:
918 raise error.Abort(_('current bisect revision is unknown - '
918 raise error.Abort(_('current bisect revision is unknown - '
919 'start a new bisect to fix'))
919 'start a new bisect to fix'))
920 else:
920 else:
921 node, p2 = repo.dirstate.parents()
921 node, p2 = repo.dirstate.parents()
922 if p2 != nullid:
922 if p2 != nullid:
923 raise error.Abort(_('current bisect revision is a merge'))
923 raise error.Abort(_('current bisect revision is a merge'))
924 try:
924 try:
925 while changesets:
925 while changesets:
926 # update state
926 # update state
927 state['current'] = [node]
927 state['current'] = [node]
928 hbisect.save_state(repo, state)
928 hbisect.save_state(repo, state)
929 status = ui.system(command, environ={'HG_NODE': hex(node)})
929 status = ui.system(command, environ={'HG_NODE': hex(node)})
930 if status == 125:
930 if status == 125:
931 transition = "skip"
931 transition = "skip"
932 elif status == 0:
932 elif status == 0:
933 transition = "good"
933 transition = "good"
934 # status < 0 means process was killed
934 # status < 0 means process was killed
935 elif status == 127:
935 elif status == 127:
936 raise error.Abort(_("failed to execute %s") % command)
936 raise error.Abort(_("failed to execute %s") % command)
937 elif status < 0:
937 elif status < 0:
938 raise error.Abort(_("%s killed") % command)
938 raise error.Abort(_("%s killed") % command)
939 else:
939 else:
940 transition = "bad"
940 transition = "bad"
941 ctx = scmutil.revsingle(repo, rev, node)
941 ctx = scmutil.revsingle(repo, rev, node)
942 rev = None # clear for future iterations
942 rev = None # clear for future iterations
943 state[transition].append(ctx.node())
943 state[transition].append(ctx.node())
944 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
944 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
945 check_state(state, interactive=False)
945 check_state(state, interactive=False)
946 # bisect
946 # bisect
947 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
947 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
948 # update to next check
948 # update to next check
949 node = nodes[0]
949 node = nodes[0]
950 if not noupdate:
950 if not noupdate:
951 cmdutil.bailifchanged(repo)
951 cmdutil.bailifchanged(repo)
952 hg.clean(repo, node, show_stats=False)
952 hg.clean(repo, node, show_stats=False)
953 finally:
953 finally:
954 state['current'] = [node]
954 state['current'] = [node]
955 hbisect.save_state(repo, state)
955 hbisect.save_state(repo, state)
956 print_result(nodes, bgood)
956 print_result(nodes, bgood)
957 return
957 return
958
958
959 # update state
959 # update state
960
960
961 if rev:
961 if rev:
962 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
962 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
963 else:
963 else:
964 nodes = [repo.lookup('.')]
964 nodes = [repo.lookup('.')]
965
965
966 if good or bad or skip:
966 if good or bad or skip:
967 if good:
967 if good:
968 state['good'] += nodes
968 state['good'] += nodes
969 elif bad:
969 elif bad:
970 state['bad'] += nodes
970 state['bad'] += nodes
971 elif skip:
971 elif skip:
972 state['skip'] += nodes
972 state['skip'] += nodes
973 hbisect.save_state(repo, state)
973 hbisect.save_state(repo, state)
974
974
975 if not check_state(state):
975 if not check_state(state):
976 return
976 return
977
977
978 # actually bisect
978 # actually bisect
979 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
979 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
980 if extend:
980 if extend:
981 if not changesets:
981 if not changesets:
982 extendnode = extendbisectrange(nodes, good)
982 extendnode = extendbisectrange(nodes, good)
983 if extendnode is not None:
983 if extendnode is not None:
984 ui.write(_("Extending search to changeset %d:%s\n")
984 ui.write(_("Extending search to changeset %d:%s\n")
985 % (extendnode.rev(), extendnode))
985 % (extendnode.rev(), extendnode))
986 state['current'] = [extendnode.node()]
986 state['current'] = [extendnode.node()]
987 hbisect.save_state(repo, state)
987 hbisect.save_state(repo, state)
988 if noupdate:
988 if noupdate:
989 return
989 return
990 cmdutil.bailifchanged(repo)
990 cmdutil.bailifchanged(repo)
991 return hg.clean(repo, extendnode.node())
991 return hg.clean(repo, extendnode.node())
992 raise error.Abort(_("nothing to extend"))
992 raise error.Abort(_("nothing to extend"))
993
993
994 if changesets == 0:
994 if changesets == 0:
995 print_result(nodes, good)
995 print_result(nodes, good)
996 else:
996 else:
997 assert len(nodes) == 1 # only a single node can be tested next
997 assert len(nodes) == 1 # only a single node can be tested next
998 node = nodes[0]
998 node = nodes[0]
999 # compute the approximate number of remaining tests
999 # compute the approximate number of remaining tests
1000 tests, size = 0, 2
1000 tests, size = 0, 2
1001 while size <= changesets:
1001 while size <= changesets:
1002 tests, size = tests + 1, size * 2
1002 tests, size = tests + 1, size * 2
1003 rev = repo.changelog.rev(node)
1003 rev = repo.changelog.rev(node)
1004 ui.write(_("Testing changeset %d:%s "
1004 ui.write(_("Testing changeset %d:%s "
1005 "(%d changesets remaining, ~%d tests)\n")
1005 "(%d changesets remaining, ~%d tests)\n")
1006 % (rev, short(node), changesets, tests))
1006 % (rev, short(node), changesets, tests))
1007 state['current'] = [node]
1007 state['current'] = [node]
1008 hbisect.save_state(repo, state)
1008 hbisect.save_state(repo, state)
1009 if not noupdate:
1009 if not noupdate:
1010 cmdutil.bailifchanged(repo)
1010 cmdutil.bailifchanged(repo)
1011 return hg.clean(repo, node)
1011 return hg.clean(repo, node)
1012
1012
1013 @command('bookmarks|bookmark',
1013 @command('bookmarks|bookmark',
1014 [('f', 'force', False, _('force')),
1014 [('f', 'force', False, _('force')),
1015 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
1015 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
1016 ('d', 'delete', False, _('delete a given bookmark')),
1016 ('d', 'delete', False, _('delete a given bookmark')),
1017 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
1017 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
1018 ('i', 'inactive', False, _('mark a bookmark inactive')),
1018 ('i', 'inactive', False, _('mark a bookmark inactive')),
1019 ] + formatteropts,
1019 ] + formatteropts,
1020 _('hg bookmarks [OPTIONS]... [NAME]...'))
1020 _('hg bookmarks [OPTIONS]... [NAME]...'))
1021 def bookmark(ui, repo, *names, **opts):
1021 def bookmark(ui, repo, *names, **opts):
1022 '''create a new bookmark or list existing bookmarks
1022 '''create a new bookmark or list existing bookmarks
1023
1023
1024 Bookmarks are labels on changesets to help track lines of development.
1024 Bookmarks are labels on changesets to help track lines of development.
1025 Bookmarks are unversioned and can be moved, renamed and deleted.
1025 Bookmarks are unversioned and can be moved, renamed and deleted.
1026 Deleting or moving a bookmark has no effect on the associated changesets.
1026 Deleting or moving a bookmark has no effect on the associated changesets.
1027
1027
1028 Creating or updating to a bookmark causes it to be marked as 'active'.
1028 Creating or updating to a bookmark causes it to be marked as 'active'.
1029 The active bookmark is indicated with a '*'.
1029 The active bookmark is indicated with a '*'.
1030 When a commit is made, the active bookmark will advance to the new commit.
1030 When a commit is made, the active bookmark will advance to the new commit.
1031 A plain :hg:`update` will also advance an active bookmark, if possible.
1031 A plain :hg:`update` will also advance an active bookmark, if possible.
1032 Updating away from a bookmark will cause it to be deactivated.
1032 Updating away from a bookmark will cause it to be deactivated.
1033
1033
1034 Bookmarks can be pushed and pulled between repositories (see
1034 Bookmarks can be pushed and pulled between repositories (see
1035 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1035 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1036 diverged, a new 'divergent bookmark' of the form 'name@path' will
1036 diverged, a new 'divergent bookmark' of the form 'name@path' will
1037 be created. Using :hg:`merge` will resolve the divergence.
1037 be created. Using :hg:`merge` will resolve the divergence.
1038
1038
1039 A bookmark named '@' has the special property that :hg:`clone` will
1039 A bookmark named '@' has the special property that :hg:`clone` will
1040 check it out by default if it exists.
1040 check it out by default if it exists.
1041
1041
1042 .. container:: verbose
1042 .. container:: verbose
1043
1043
1044 Examples:
1044 Examples:
1045
1045
1046 - create an active bookmark for a new line of development::
1046 - create an active bookmark for a new line of development::
1047
1047
1048 hg book new-feature
1048 hg book new-feature
1049
1049
1050 - create an inactive bookmark as a place marker::
1050 - create an inactive bookmark as a place marker::
1051
1051
1052 hg book -i reviewed
1052 hg book -i reviewed
1053
1053
1054 - create an inactive bookmark on another changeset::
1054 - create an inactive bookmark on another changeset::
1055
1055
1056 hg book -r .^ tested
1056 hg book -r .^ tested
1057
1057
1058 - rename bookmark turkey to dinner::
1058 - rename bookmark turkey to dinner::
1059
1059
1060 hg book -m turkey dinner
1060 hg book -m turkey dinner
1061
1061
1062 - move the '@' bookmark from another branch::
1062 - move the '@' bookmark from another branch::
1063
1063
1064 hg book -f @
1064 hg book -f @
1065 '''
1065 '''
1066 force = opts.get('force')
1066 force = opts.get('force')
1067 rev = opts.get('rev')
1067 rev = opts.get('rev')
1068 delete = opts.get('delete')
1068 delete = opts.get('delete')
1069 rename = opts.get('rename')
1069 rename = opts.get('rename')
1070 inactive = opts.get('inactive')
1070 inactive = opts.get('inactive')
1071
1071
1072 def checkformat(mark):
1072 def checkformat(mark):
1073 mark = mark.strip()
1073 mark = mark.strip()
1074 if not mark:
1074 if not mark:
1075 raise error.Abort(_("bookmark names cannot consist entirely of "
1075 raise error.Abort(_("bookmark names cannot consist entirely of "
1076 "whitespace"))
1076 "whitespace"))
1077 scmutil.checknewlabel(repo, mark, 'bookmark')
1077 scmutil.checknewlabel(repo, mark, 'bookmark')
1078 return mark
1078 return mark
1079
1079
1080 def checkconflict(repo, mark, cur, force=False, target=None):
1080 def checkconflict(repo, mark, cur, force=False, target=None):
1081 if mark in marks and not force:
1081 if mark in marks and not force:
1082 if target:
1082 if target:
1083 if marks[mark] == target and target == cur:
1083 if marks[mark] == target and target == cur:
1084 # re-activating a bookmark
1084 # re-activating a bookmark
1085 return
1085 return
1086 anc = repo.changelog.ancestors([repo[target].rev()])
1086 anc = repo.changelog.ancestors([repo[target].rev()])
1087 bmctx = repo[marks[mark]]
1087 bmctx = repo[marks[mark]]
1088 divs = [repo[b].node() for b in marks
1088 divs = [repo[b].node() for b in marks
1089 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1089 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1090
1090
1091 # allow resolving a single divergent bookmark even if moving
1091 # allow resolving a single divergent bookmark even if moving
1092 # the bookmark across branches when a revision is specified
1092 # the bookmark across branches when a revision is specified
1093 # that contains a divergent bookmark
1093 # that contains a divergent bookmark
1094 if bmctx.rev() not in anc and target in divs:
1094 if bmctx.rev() not in anc and target in divs:
1095 bookmarks.deletedivergent(repo, [target], mark)
1095 bookmarks.deletedivergent(repo, [target], mark)
1096 return
1096 return
1097
1097
1098 deletefrom = [b for b in divs
1098 deletefrom = [b for b in divs
1099 if repo[b].rev() in anc or b == target]
1099 if repo[b].rev() in anc or b == target]
1100 bookmarks.deletedivergent(repo, deletefrom, mark)
1100 bookmarks.deletedivergent(repo, deletefrom, mark)
1101 if bookmarks.validdest(repo, bmctx, repo[target]):
1101 if bookmarks.validdest(repo, bmctx, repo[target]):
1102 ui.status(_("moving bookmark '%s' forward from %s\n") %
1102 ui.status(_("moving bookmark '%s' forward from %s\n") %
1103 (mark, short(bmctx.node())))
1103 (mark, short(bmctx.node())))
1104 return
1104 return
1105 raise error.Abort(_("bookmark '%s' already exists "
1105 raise error.Abort(_("bookmark '%s' already exists "
1106 "(use -f to force)") % mark)
1106 "(use -f to force)") % mark)
1107 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1107 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1108 and not force):
1108 and not force):
1109 raise error.Abort(
1109 raise error.Abort(
1110 _("a bookmark cannot have the name of an existing branch"))
1110 _("a bookmark cannot have the name of an existing branch"))
1111
1111
1112 if delete and rename:
1112 if delete and rename:
1113 raise error.Abort(_("--delete and --rename are incompatible"))
1113 raise error.Abort(_("--delete and --rename are incompatible"))
1114 if delete and rev:
1114 if delete and rev:
1115 raise error.Abort(_("--rev is incompatible with --delete"))
1115 raise error.Abort(_("--rev is incompatible with --delete"))
1116 if rename and rev:
1116 if rename and rev:
1117 raise error.Abort(_("--rev is incompatible with --rename"))
1117 raise error.Abort(_("--rev is incompatible with --rename"))
1118 if not names and (delete or rev):
1118 if not names and (delete or rev):
1119 raise error.Abort(_("bookmark name required"))
1119 raise error.Abort(_("bookmark name required"))
1120
1120
1121 if delete or rename or names or inactive:
1121 if delete or rename or names or inactive:
1122 wlock = lock = tr = None
1122 wlock = lock = tr = None
1123 try:
1123 try:
1124 wlock = repo.wlock()
1124 wlock = repo.wlock()
1125 lock = repo.lock()
1125 lock = repo.lock()
1126 cur = repo.changectx('.').node()
1126 cur = repo.changectx('.').node()
1127 marks = repo._bookmarks
1127 marks = repo._bookmarks
1128 if delete:
1128 if delete:
1129 tr = repo.transaction('bookmark')
1129 tr = repo.transaction('bookmark')
1130 for mark in names:
1130 for mark in names:
1131 if mark not in marks:
1131 if mark not in marks:
1132 raise error.Abort(_("bookmark '%s' does not exist") %
1132 raise error.Abort(_("bookmark '%s' does not exist") %
1133 mark)
1133 mark)
1134 if mark == repo._activebookmark:
1134 if mark == repo._activebookmark:
1135 bookmarks.deactivate(repo)
1135 bookmarks.deactivate(repo)
1136 del marks[mark]
1136 del marks[mark]
1137
1137
1138 elif rename:
1138 elif rename:
1139 tr = repo.transaction('bookmark')
1139 tr = repo.transaction('bookmark')
1140 if not names:
1140 if not names:
1141 raise error.Abort(_("new bookmark name required"))
1141 raise error.Abort(_("new bookmark name required"))
1142 elif len(names) > 1:
1142 elif len(names) > 1:
1143 raise error.Abort(_("only one new bookmark name allowed"))
1143 raise error.Abort(_("only one new bookmark name allowed"))
1144 mark = checkformat(names[0])
1144 mark = checkformat(names[0])
1145 if rename not in marks:
1145 if rename not in marks:
1146 raise error.Abort(_("bookmark '%s' does not exist")
1146 raise error.Abort(_("bookmark '%s' does not exist")
1147 % rename)
1147 % rename)
1148 checkconflict(repo, mark, cur, force)
1148 checkconflict(repo, mark, cur, force)
1149 marks[mark] = marks[rename]
1149 marks[mark] = marks[rename]
1150 if repo._activebookmark == rename and not inactive:
1150 if repo._activebookmark == rename and not inactive:
1151 bookmarks.activate(repo, mark)
1151 bookmarks.activate(repo, mark)
1152 del marks[rename]
1152 del marks[rename]
1153 elif names:
1153 elif names:
1154 tr = repo.transaction('bookmark')
1154 tr = repo.transaction('bookmark')
1155 newact = None
1155 newact = None
1156 for mark in names:
1156 for mark in names:
1157 mark = checkformat(mark)
1157 mark = checkformat(mark)
1158 if newact is None:
1158 if newact is None:
1159 newact = mark
1159 newact = mark
1160 if inactive and mark == repo._activebookmark:
1160 if inactive and mark == repo._activebookmark:
1161 bookmarks.deactivate(repo)
1161 bookmarks.deactivate(repo)
1162 return
1162 return
1163 tgt = cur
1163 tgt = cur
1164 if rev:
1164 if rev:
1165 tgt = scmutil.revsingle(repo, rev).node()
1165 tgt = scmutil.revsingle(repo, rev).node()
1166 checkconflict(repo, mark, cur, force, tgt)
1166 checkconflict(repo, mark, cur, force, tgt)
1167 marks[mark] = tgt
1167 marks[mark] = tgt
1168 if not inactive and cur == marks[newact] and not rev:
1168 if not inactive and cur == marks[newact] and not rev:
1169 bookmarks.activate(repo, newact)
1169 bookmarks.activate(repo, newact)
1170 elif cur != tgt and newact == repo._activebookmark:
1170 elif cur != tgt and newact == repo._activebookmark:
1171 bookmarks.deactivate(repo)
1171 bookmarks.deactivate(repo)
1172 elif inactive:
1172 elif inactive:
1173 if len(marks) == 0:
1173 if len(marks) == 0:
1174 ui.status(_("no bookmarks set\n"))
1174 ui.status(_("no bookmarks set\n"))
1175 elif not repo._activebookmark:
1175 elif not repo._activebookmark:
1176 ui.status(_("no active bookmark\n"))
1176 ui.status(_("no active bookmark\n"))
1177 else:
1177 else:
1178 bookmarks.deactivate(repo)
1178 bookmarks.deactivate(repo)
1179 if tr is not None:
1179 if tr is not None:
1180 marks.recordchange(tr)
1180 marks.recordchange(tr)
1181 tr.close()
1181 tr.close()
1182 finally:
1182 finally:
1183 lockmod.release(tr, lock, wlock)
1183 lockmod.release(tr, lock, wlock)
1184 else: # show bookmarks
1184 else: # show bookmarks
1185 fm = ui.formatter('bookmarks', opts)
1185 fm = ui.formatter('bookmarks', opts)
1186 hexfn = fm.hexfunc
1186 hexfn = fm.hexfunc
1187 marks = repo._bookmarks
1187 marks = repo._bookmarks
1188 if len(marks) == 0 and not fm:
1188 if len(marks) == 0 and not fm:
1189 ui.status(_("no bookmarks set\n"))
1189 ui.status(_("no bookmarks set\n"))
1190 for bmark, n in sorted(marks.iteritems()):
1190 for bmark, n in sorted(marks.iteritems()):
1191 active = repo._activebookmark
1191 active = repo._activebookmark
1192 if bmark == active:
1192 if bmark == active:
1193 prefix, label = '*', activebookmarklabel
1193 prefix, label = '*', activebookmarklabel
1194 else:
1194 else:
1195 prefix, label = ' ', ''
1195 prefix, label = ' ', ''
1196
1196
1197 fm.startitem()
1197 fm.startitem()
1198 if not ui.quiet:
1198 if not ui.quiet:
1199 fm.plain(' %s ' % prefix, label=label)
1199 fm.plain(' %s ' % prefix, label=label)
1200 fm.write('bookmark', '%s', bmark, label=label)
1200 fm.write('bookmark', '%s', bmark, label=label)
1201 pad = " " * (25 - encoding.colwidth(bmark))
1201 pad = " " * (25 - encoding.colwidth(bmark))
1202 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1202 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1203 repo.changelog.rev(n), hexfn(n), label=label)
1203 repo.changelog.rev(n), hexfn(n), label=label)
1204 fm.data(active=(bmark == active))
1204 fm.data(active=(bmark == active))
1205 fm.plain('\n')
1205 fm.plain('\n')
1206 fm.end()
1206 fm.end()
1207
1207
1208 @command('branch',
1208 @command('branch',
1209 [('f', 'force', None,
1209 [('f', 'force', None,
1210 _('set branch name even if it shadows an existing branch')),
1210 _('set branch name even if it shadows an existing branch')),
1211 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1211 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1212 _('[-fC] [NAME]'))
1212 _('[-fC] [NAME]'))
1213 def branch(ui, repo, label=None, **opts):
1213 def branch(ui, repo, label=None, **opts):
1214 """set or show the current branch name
1214 """set or show the current branch name
1215
1215
1216 .. note::
1216 .. note::
1217
1217
1218 Branch names are permanent and global. Use :hg:`bookmark` to create a
1218 Branch names are permanent and global. Use :hg:`bookmark` to create a
1219 light-weight bookmark instead. See :hg:`help glossary` for more
1219 light-weight bookmark instead. See :hg:`help glossary` for more
1220 information about named branches and bookmarks.
1220 information about named branches and bookmarks.
1221
1221
1222 With no argument, show the current branch name. With one argument,
1222 With no argument, show the current branch name. With one argument,
1223 set the working directory branch name (the branch will not exist
1223 set the working directory branch name (the branch will not exist
1224 in the repository until the next commit). Standard practice
1224 in the repository until the next commit). Standard practice
1225 recommends that primary development take place on the 'default'
1225 recommends that primary development take place on the 'default'
1226 branch.
1226 branch.
1227
1227
1228 Unless -f/--force is specified, branch will not let you set a
1228 Unless -f/--force is specified, branch will not let you set a
1229 branch name that already exists.
1229 branch name that already exists.
1230
1230
1231 Use -C/--clean to reset the working directory branch to that of
1231 Use -C/--clean to reset the working directory branch to that of
1232 the parent of the working directory, negating a previous branch
1232 the parent of the working directory, negating a previous branch
1233 change.
1233 change.
1234
1234
1235 Use the command :hg:`update` to switch to an existing branch. Use
1235 Use the command :hg:`update` to switch to an existing branch. Use
1236 :hg:`commit --close-branch` to mark this branch head as closed.
1236 :hg:`commit --close-branch` to mark this branch head as closed.
1237 When all heads of a branch are closed, the branch will be
1237 When all heads of a branch are closed, the branch will be
1238 considered closed.
1238 considered closed.
1239
1239
1240 Returns 0 on success.
1240 Returns 0 on success.
1241 """
1241 """
1242 if label:
1242 if label:
1243 label = label.strip()
1243 label = label.strip()
1244
1244
1245 if not opts.get('clean') and not label:
1245 if not opts.get('clean') and not label:
1246 ui.write("%s\n" % repo.dirstate.branch())
1246 ui.write("%s\n" % repo.dirstate.branch())
1247 return
1247 return
1248
1248
1249 with repo.wlock():
1249 with repo.wlock():
1250 if opts.get('clean'):
1250 if opts.get('clean'):
1251 label = repo[None].p1().branch()
1251 label = repo[None].p1().branch()
1252 repo.dirstate.setbranch(label)
1252 repo.dirstate.setbranch(label)
1253 ui.status(_('reset working directory to branch %s\n') % label)
1253 ui.status(_('reset working directory to branch %s\n') % label)
1254 elif label:
1254 elif label:
1255 if not opts.get('force') and label in repo.branchmap():
1255 if not opts.get('force') and label in repo.branchmap():
1256 if label not in [p.branch() for p in repo[None].parents()]:
1256 if label not in [p.branch() for p in repo[None].parents()]:
1257 raise error.Abort(_('a branch of the same name already'
1257 raise error.Abort(_('a branch of the same name already'
1258 ' exists'),
1258 ' exists'),
1259 # i18n: "it" refers to an existing branch
1259 # i18n: "it" refers to an existing branch
1260 hint=_("use 'hg update' to switch to it"))
1260 hint=_("use 'hg update' to switch to it"))
1261 scmutil.checknewlabel(repo, label, 'branch')
1261 scmutil.checknewlabel(repo, label, 'branch')
1262 repo.dirstate.setbranch(label)
1262 repo.dirstate.setbranch(label)
1263 ui.status(_('marked working directory as branch %s\n') % label)
1263 ui.status(_('marked working directory as branch %s\n') % label)
1264
1264
1265 # find any open named branches aside from default
1265 # find any open named branches aside from default
1266 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1266 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1267 if n != "default" and not c]
1267 if n != "default" and not c]
1268 if not others:
1268 if not others:
1269 ui.status(_('(branches are permanent and global, '
1269 ui.status(_('(branches are permanent and global, '
1270 'did you want a bookmark?)\n'))
1270 'did you want a bookmark?)\n'))
1271
1271
1272 @command('branches',
1272 @command('branches',
1273 [('a', 'active', False,
1273 [('a', 'active', False,
1274 _('show only branches that have unmerged heads (DEPRECATED)')),
1274 _('show only branches that have unmerged heads (DEPRECATED)')),
1275 ('c', 'closed', False, _('show normal and closed branches')),
1275 ('c', 'closed', False, _('show normal and closed branches')),
1276 ] + formatteropts,
1276 ] + formatteropts,
1277 _('[-c]'))
1277 _('[-c]'))
1278 def branches(ui, repo, active=False, closed=False, **opts):
1278 def branches(ui, repo, active=False, closed=False, **opts):
1279 """list repository named branches
1279 """list repository named branches
1280
1280
1281 List the repository's named branches, indicating which ones are
1281 List the repository's named branches, indicating which ones are
1282 inactive. If -c/--closed is specified, also list branches which have
1282 inactive. If -c/--closed is specified, also list branches which have
1283 been marked closed (see :hg:`commit --close-branch`).
1283 been marked closed (see :hg:`commit --close-branch`).
1284
1284
1285 Use the command :hg:`update` to switch to an existing branch.
1285 Use the command :hg:`update` to switch to an existing branch.
1286
1286
1287 Returns 0.
1287 Returns 0.
1288 """
1288 """
1289
1289
1290 fm = ui.formatter('branches', opts)
1290 fm = ui.formatter('branches', opts)
1291 hexfunc = fm.hexfunc
1291 hexfunc = fm.hexfunc
1292
1292
1293 allheads = set(repo.heads())
1293 allheads = set(repo.heads())
1294 branches = []
1294 branches = []
1295 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1295 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1296 isactive = not isclosed and bool(set(heads) & allheads)
1296 isactive = not isclosed and bool(set(heads) & allheads)
1297 branches.append((tag, repo[tip], isactive, not isclosed))
1297 branches.append((tag, repo[tip], isactive, not isclosed))
1298 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1298 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1299 reverse=True)
1299 reverse=True)
1300
1300
1301 for tag, ctx, isactive, isopen in branches:
1301 for tag, ctx, isactive, isopen in branches:
1302 if active and not isactive:
1302 if active and not isactive:
1303 continue
1303 continue
1304 if isactive:
1304 if isactive:
1305 label = 'branches.active'
1305 label = 'branches.active'
1306 notice = ''
1306 notice = ''
1307 elif not isopen:
1307 elif not isopen:
1308 if not closed:
1308 if not closed:
1309 continue
1309 continue
1310 label = 'branches.closed'
1310 label = 'branches.closed'
1311 notice = _(' (closed)')
1311 notice = _(' (closed)')
1312 else:
1312 else:
1313 label = 'branches.inactive'
1313 label = 'branches.inactive'
1314 notice = _(' (inactive)')
1314 notice = _(' (inactive)')
1315 current = (tag == repo.dirstate.branch())
1315 current = (tag == repo.dirstate.branch())
1316 if current:
1316 if current:
1317 label = 'branches.current'
1317 label = 'branches.current'
1318
1318
1319 fm.startitem()
1319 fm.startitem()
1320 fm.write('branch', '%s', tag, label=label)
1320 fm.write('branch', '%s', tag, label=label)
1321 rev = ctx.rev()
1321 rev = ctx.rev()
1322 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1322 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1323 fmt = ' ' * padsize + ' %d:%s'
1323 fmt = ' ' * padsize + ' %d:%s'
1324 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1324 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1325 label='log.changeset changeset.%s' % ctx.phasestr())
1325 label='log.changeset changeset.%s' % ctx.phasestr())
1326 fm.data(active=isactive, closed=not isopen, current=current)
1326 fm.data(active=isactive, closed=not isopen, current=current)
1327 if not ui.quiet:
1327 if not ui.quiet:
1328 fm.plain(notice)
1328 fm.plain(notice)
1329 fm.plain('\n')
1329 fm.plain('\n')
1330 fm.end()
1330 fm.end()
1331
1331
1332 @command('bundle',
1332 @command('bundle',
1333 [('f', 'force', None, _('run even when the destination is unrelated')),
1333 [('f', 'force', None, _('run even when the destination is unrelated')),
1334 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1334 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1335 _('REV')),
1335 _('REV')),
1336 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1336 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1337 _('BRANCH')),
1337 _('BRANCH')),
1338 ('', 'base', [],
1338 ('', 'base', [],
1339 _('a base changeset assumed to be available at the destination'),
1339 _('a base changeset assumed to be available at the destination'),
1340 _('REV')),
1340 _('REV')),
1341 ('a', 'all', None, _('bundle all changesets in the repository')),
1341 ('a', 'all', None, _('bundle all changesets in the repository')),
1342 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1342 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1343 ] + remoteopts,
1343 ] + remoteopts,
1344 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1344 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1345 def bundle(ui, repo, fname, dest=None, **opts):
1345 def bundle(ui, repo, fname, dest=None, **opts):
1346 """create a changegroup file
1346 """create a changegroup file
1347
1347
1348 Generate a changegroup file collecting changesets to be added
1348 Generate a changegroup file collecting changesets to be added
1349 to a repository.
1349 to a repository.
1350
1350
1351 To create a bundle containing all changesets, use -a/--all
1351 To create a bundle containing all changesets, use -a/--all
1352 (or --base null). Otherwise, hg assumes the destination will have
1352 (or --base null). Otherwise, hg assumes the destination will have
1353 all the nodes you specify with --base parameters. Otherwise, hg
1353 all the nodes you specify with --base parameters. Otherwise, hg
1354 will assume the repository has all the nodes in destination, or
1354 will assume the repository has all the nodes in destination, or
1355 default-push/default if no destination is specified.
1355 default-push/default if no destination is specified.
1356
1356
1357 You can change bundle format with the -t/--type option. You can
1357 You can change bundle format with the -t/--type option. You can
1358 specify a compression, a bundle version or both using a dash
1358 specify a compression, a bundle version or both using a dash
1359 (comp-version). The available compression methods are: none, bzip2,
1359 (comp-version). The available compression methods are: none, bzip2,
1360 and gzip (by default, bundles are compressed using bzip2). The
1360 and gzip (by default, bundles are compressed using bzip2). The
1361 available formats are: v1, v2 (default to most suitable).
1361 available formats are: v1, v2 (default to most suitable).
1362
1362
1363 The bundle file can then be transferred using conventional means
1363 The bundle file can then be transferred using conventional means
1364 and applied to another repository with the unbundle or pull
1364 and applied to another repository with the unbundle or pull
1365 command. This is useful when direct push and pull are not
1365 command. This is useful when direct push and pull are not
1366 available or when exporting an entire repository is undesirable.
1366 available or when exporting an entire repository is undesirable.
1367
1367
1368 Applying bundles preserves all changeset contents including
1368 Applying bundles preserves all changeset contents including
1369 permissions, copy/rename information, and revision history.
1369 permissions, copy/rename information, and revision history.
1370
1370
1371 Returns 0 on success, 1 if no changes found.
1371 Returns 0 on success, 1 if no changes found.
1372 """
1372 """
1373 revs = None
1373 revs = None
1374 if 'rev' in opts:
1374 if 'rev' in opts:
1375 revstrings = opts['rev']
1375 revstrings = opts['rev']
1376 revs = scmutil.revrange(repo, revstrings)
1376 revs = scmutil.revrange(repo, revstrings)
1377 if revstrings and not revs:
1377 if revstrings and not revs:
1378 raise error.Abort(_('no commits to bundle'))
1378 raise error.Abort(_('no commits to bundle'))
1379
1379
1380 bundletype = opts.get('type', 'bzip2').lower()
1380 bundletype = opts.get('type', 'bzip2').lower()
1381 try:
1381 try:
1382 bcompression, cgversion, params = exchange.parsebundlespec(
1382 bcompression, cgversion, params = exchange.parsebundlespec(
1383 repo, bundletype, strict=False)
1383 repo, bundletype, strict=False)
1384 except error.UnsupportedBundleSpecification as e:
1384 except error.UnsupportedBundleSpecification as e:
1385 raise error.Abort(str(e),
1385 raise error.Abort(str(e),
1386 hint=_('see "hg help bundle" for supported '
1386 hint=_('see "hg help bundle" for supported '
1387 'values for --type'))
1387 'values for --type'))
1388
1388
1389 # Packed bundles are a pseudo bundle format for now.
1389 # Packed bundles are a pseudo bundle format for now.
1390 if cgversion == 's1':
1390 if cgversion == 's1':
1391 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1391 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1392 hint=_("use 'hg debugcreatestreamclonebundle'"))
1392 hint=_("use 'hg debugcreatestreamclonebundle'"))
1393
1393
1394 if opts.get('all'):
1394 if opts.get('all'):
1395 if dest:
1395 if dest:
1396 raise error.Abort(_("--all is incompatible with specifying "
1396 raise error.Abort(_("--all is incompatible with specifying "
1397 "a destination"))
1397 "a destination"))
1398 if opts.get('base'):
1398 if opts.get('base'):
1399 ui.warn(_("ignoring --base because --all was specified\n"))
1399 ui.warn(_("ignoring --base because --all was specified\n"))
1400 base = ['null']
1400 base = ['null']
1401 else:
1401 else:
1402 base = scmutil.revrange(repo, opts.get('base'))
1402 base = scmutil.revrange(repo, opts.get('base'))
1403 # TODO: get desired bundlecaps from command line.
1403 # TODO: get desired bundlecaps from command line.
1404 bundlecaps = None
1404 bundlecaps = None
1405 if cgversion not in changegroup.supportedoutgoingversions(repo):
1405 if cgversion not in changegroup.supportedoutgoingversions(repo):
1406 raise error.Abort(_("repository does not support bundle version %s") %
1406 raise error.Abort(_("repository does not support bundle version %s") %
1407 cgversion)
1407 cgversion)
1408
1408
1409 if base:
1409 if base:
1410 if dest:
1410 if dest:
1411 raise error.Abort(_("--base is incompatible with specifying "
1411 raise error.Abort(_("--base is incompatible with specifying "
1412 "a destination"))
1412 "a destination"))
1413 common = [repo.lookup(rev) for rev in base]
1413 common = [repo.lookup(rev) for rev in base]
1414 heads = revs and map(repo.lookup, revs) or revs
1414 heads = revs and map(repo.lookup, revs) or revs
1415 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1415 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1416 common=common, bundlecaps=bundlecaps,
1416 common=common, bundlecaps=bundlecaps,
1417 version=cgversion)
1417 version=cgversion)
1418 outgoing = None
1418 outgoing = None
1419 else:
1419 else:
1420 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1420 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1421 dest, branches = hg.parseurl(dest, opts.get('branch'))
1421 dest, branches = hg.parseurl(dest, opts.get('branch'))
1422 other = hg.peer(repo, opts, dest)
1422 other = hg.peer(repo, opts, dest)
1423 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1423 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1424 heads = revs and map(repo.lookup, revs) or revs
1424 heads = revs and map(repo.lookup, revs) or revs
1425 outgoing = discovery.findcommonoutgoing(repo, other,
1425 outgoing = discovery.findcommonoutgoing(repo, other,
1426 onlyheads=heads,
1426 onlyheads=heads,
1427 force=opts.get('force'),
1427 force=opts.get('force'),
1428 portable=True)
1428 portable=True)
1429 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1429 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1430 bundlecaps, version=cgversion)
1430 bundlecaps, version=cgversion)
1431 if not cg:
1431 if not cg:
1432 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1432 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1433 return 1
1433 return 1
1434
1434
1435 if cgversion == '01': #bundle1
1435 if cgversion == '01': #bundle1
1436 if bcompression is None:
1436 if bcompression is None:
1437 bcompression = 'UN'
1437 bcompression = 'UN'
1438 bversion = 'HG10' + bcompression
1438 bversion = 'HG10' + bcompression
1439 bcompression = None
1439 bcompression = None
1440 else:
1440 else:
1441 assert cgversion == '02'
1441 assert cgversion == '02'
1442 bversion = 'HG20'
1442 bversion = 'HG20'
1443
1443
1444 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1444 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1445
1445
1446 @command('cat',
1446 @command('cat',
1447 [('o', 'output', '',
1447 [('o', 'output', '',
1448 _('print output to file with formatted name'), _('FORMAT')),
1448 _('print output to file with formatted name'), _('FORMAT')),
1449 ('r', 'rev', '', _('print the given revision'), _('REV')),
1449 ('r', 'rev', '', _('print the given revision'), _('REV')),
1450 ('', 'decode', None, _('apply any matching decode filter')),
1450 ('', 'decode', None, _('apply any matching decode filter')),
1451 ] + walkopts,
1451 ] + walkopts,
1452 _('[OPTION]... FILE...'),
1452 _('[OPTION]... FILE...'),
1453 inferrepo=True)
1453 inferrepo=True)
1454 def cat(ui, repo, file1, *pats, **opts):
1454 def cat(ui, repo, file1, *pats, **opts):
1455 """output the current or given revision of files
1455 """output the current or given revision of files
1456
1456
1457 Print the specified files as they were at the given revision. If
1457 Print the specified files as they were at the given revision. If
1458 no revision is given, the parent of the working directory is used.
1458 no revision is given, the parent of the working directory is used.
1459
1459
1460 Output may be to a file, in which case the name of the file is
1460 Output may be to a file, in which case the name of the file is
1461 given using a format string. The formatting rules as follows:
1461 given using a format string. The formatting rules as follows:
1462
1462
1463 :``%%``: literal "%" character
1463 :``%%``: literal "%" character
1464 :``%s``: basename of file being printed
1464 :``%s``: basename of file being printed
1465 :``%d``: dirname of file being printed, or '.' if in repository root
1465 :``%d``: dirname of file being printed, or '.' if in repository root
1466 :``%p``: root-relative path name of file being printed
1466 :``%p``: root-relative path name of file being printed
1467 :``%H``: changeset hash (40 hexadecimal digits)
1467 :``%H``: changeset hash (40 hexadecimal digits)
1468 :``%R``: changeset revision number
1468 :``%R``: changeset revision number
1469 :``%h``: short-form changeset hash (12 hexadecimal digits)
1469 :``%h``: short-form changeset hash (12 hexadecimal digits)
1470 :``%r``: zero-padded changeset revision number
1470 :``%r``: zero-padded changeset revision number
1471 :``%b``: basename of the exporting repository
1471 :``%b``: basename of the exporting repository
1472
1472
1473 Returns 0 on success.
1473 Returns 0 on success.
1474 """
1474 """
1475 ctx = scmutil.revsingle(repo, opts.get('rev'))
1475 ctx = scmutil.revsingle(repo, opts.get('rev'))
1476 m = scmutil.match(ctx, (file1,) + pats, opts)
1476 m = scmutil.match(ctx, (file1,) + pats, opts)
1477
1477
1478 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1478 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1479
1479
1480 @command('^clone',
1480 @command('^clone',
1481 [('U', 'noupdate', None, _('the clone will include an empty working '
1481 [('U', 'noupdate', None, _('the clone will include an empty working '
1482 'directory (only a repository)')),
1482 'directory (only a repository)')),
1483 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1483 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1484 _('REV')),
1484 _('REV')),
1485 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1485 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1486 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1486 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1487 ('', 'pull', None, _('use pull protocol to copy metadata')),
1487 ('', 'pull', None, _('use pull protocol to copy metadata')),
1488 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1488 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1489 ] + remoteopts,
1489 ] + remoteopts,
1490 _('[OPTION]... SOURCE [DEST]'),
1490 _('[OPTION]... SOURCE [DEST]'),
1491 norepo=True)
1491 norepo=True)
1492 def clone(ui, source, dest=None, **opts):
1492 def clone(ui, source, dest=None, **opts):
1493 """make a copy of an existing repository
1493 """make a copy of an existing repository
1494
1494
1495 Create a copy of an existing repository in a new directory.
1495 Create a copy of an existing repository in a new directory.
1496
1496
1497 If no destination directory name is specified, it defaults to the
1497 If no destination directory name is specified, it defaults to the
1498 basename of the source.
1498 basename of the source.
1499
1499
1500 The location of the source is added to the new repository's
1500 The location of the source is added to the new repository's
1501 ``.hg/hgrc`` file, as the default to be used for future pulls.
1501 ``.hg/hgrc`` file, as the default to be used for future pulls.
1502
1502
1503 Only local paths and ``ssh://`` URLs are supported as
1503 Only local paths and ``ssh://`` URLs are supported as
1504 destinations. For ``ssh://`` destinations, no working directory or
1504 destinations. For ``ssh://`` destinations, no working directory or
1505 ``.hg/hgrc`` will be created on the remote side.
1505 ``.hg/hgrc`` will be created on the remote side.
1506
1506
1507 If the source repository has a bookmark called '@' set, that
1507 If the source repository has a bookmark called '@' set, that
1508 revision will be checked out in the new repository by default.
1508 revision will be checked out in the new repository by default.
1509
1509
1510 To check out a particular version, use -u/--update, or
1510 To check out a particular version, use -u/--update, or
1511 -U/--noupdate to create a clone with no working directory.
1511 -U/--noupdate to create a clone with no working directory.
1512
1512
1513 To pull only a subset of changesets, specify one or more revisions
1513 To pull only a subset of changesets, specify one or more revisions
1514 identifiers with -r/--rev or branches with -b/--branch. The
1514 identifiers with -r/--rev or branches with -b/--branch. The
1515 resulting clone will contain only the specified changesets and
1515 resulting clone will contain only the specified changesets and
1516 their ancestors. These options (or 'clone src#rev dest') imply
1516 their ancestors. These options (or 'clone src#rev dest') imply
1517 --pull, even for local source repositories.
1517 --pull, even for local source repositories.
1518
1518
1519 .. note::
1519 .. note::
1520
1520
1521 Specifying a tag will include the tagged changeset but not the
1521 Specifying a tag will include the tagged changeset but not the
1522 changeset containing the tag.
1522 changeset containing the tag.
1523
1523
1524 .. container:: verbose
1524 .. container:: verbose
1525
1525
1526 For efficiency, hardlinks are used for cloning whenever the
1526 For efficiency, hardlinks are used for cloning whenever the
1527 source and destination are on the same filesystem (note this
1527 source and destination are on the same filesystem (note this
1528 applies only to the repository data, not to the working
1528 applies only to the repository data, not to the working
1529 directory). Some filesystems, such as AFS, implement hardlinking
1529 directory). Some filesystems, such as AFS, implement hardlinking
1530 incorrectly, but do not report errors. In these cases, use the
1530 incorrectly, but do not report errors. In these cases, use the
1531 --pull option to avoid hardlinking.
1531 --pull option to avoid hardlinking.
1532
1532
1533 In some cases, you can clone repositories and the working
1533 In some cases, you can clone repositories and the working
1534 directory using full hardlinks with ::
1534 directory using full hardlinks with ::
1535
1535
1536 $ cp -al REPO REPOCLONE
1536 $ cp -al REPO REPOCLONE
1537
1537
1538 This is the fastest way to clone, but it is not always safe. The
1538 This is the fastest way to clone, but it is not always safe. The
1539 operation is not atomic (making sure REPO is not modified during
1539 operation is not atomic (making sure REPO is not modified during
1540 the operation is up to you) and you have to make sure your
1540 the operation is up to you) and you have to make sure your
1541 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1541 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1542 so). Also, this is not compatible with certain extensions that
1542 so). Also, this is not compatible with certain extensions that
1543 place their metadata under the .hg directory, such as mq.
1543 place their metadata under the .hg directory, such as mq.
1544
1544
1545 Mercurial will update the working directory to the first applicable
1545 Mercurial will update the working directory to the first applicable
1546 revision from this list:
1546 revision from this list:
1547
1547
1548 a) null if -U or the source repository has no changesets
1548 a) null if -U or the source repository has no changesets
1549 b) if -u . and the source repository is local, the first parent of
1549 b) if -u . and the source repository is local, the first parent of
1550 the source repository's working directory
1550 the source repository's working directory
1551 c) the changeset specified with -u (if a branch name, this means the
1551 c) the changeset specified with -u (if a branch name, this means the
1552 latest head of that branch)
1552 latest head of that branch)
1553 d) the changeset specified with -r
1553 d) the changeset specified with -r
1554 e) the tipmost head specified with -b
1554 e) the tipmost head specified with -b
1555 f) the tipmost head specified with the url#branch source syntax
1555 f) the tipmost head specified with the url#branch source syntax
1556 g) the revision marked with the '@' bookmark, if present
1556 g) the revision marked with the '@' bookmark, if present
1557 h) the tipmost head of the default branch
1557 h) the tipmost head of the default branch
1558 i) tip
1558 i) tip
1559
1559
1560 When cloning from servers that support it, Mercurial may fetch
1560 When cloning from servers that support it, Mercurial may fetch
1561 pre-generated data from a server-advertised URL. When this is done,
1561 pre-generated data from a server-advertised URL. When this is done,
1562 hooks operating on incoming changesets and changegroups may fire twice,
1562 hooks operating on incoming changesets and changegroups may fire twice,
1563 once for the bundle fetched from the URL and another for any additional
1563 once for the bundle fetched from the URL and another for any additional
1564 data not fetched from this URL. In addition, if an error occurs, the
1564 data not fetched from this URL. In addition, if an error occurs, the
1565 repository may be rolled back to a partial clone. This behavior may
1565 repository may be rolled back to a partial clone. This behavior may
1566 change in future releases. See :hg:`help -e clonebundles` for more.
1566 change in future releases. See :hg:`help -e clonebundles` for more.
1567
1567
1568 Examples:
1568 Examples:
1569
1569
1570 - clone a remote repository to a new directory named hg/::
1570 - clone a remote repository to a new directory named hg/::
1571
1571
1572 hg clone http://selenic.com/hg
1572 hg clone http://selenic.com/hg
1573
1573
1574 - create a lightweight local clone::
1574 - create a lightweight local clone::
1575
1575
1576 hg clone project/ project-feature/
1576 hg clone project/ project-feature/
1577
1577
1578 - clone from an absolute path on an ssh server (note double-slash)::
1578 - clone from an absolute path on an ssh server (note double-slash)::
1579
1579
1580 hg clone ssh://user@server//home/projects/alpha/
1580 hg clone ssh://user@server//home/projects/alpha/
1581
1581
1582 - do a high-speed clone over a LAN while checking out a
1582 - do a high-speed clone over a LAN while checking out a
1583 specified version::
1583 specified version::
1584
1584
1585 hg clone --uncompressed http://server/repo -u 1.5
1585 hg clone --uncompressed http://server/repo -u 1.5
1586
1586
1587 - create a repository without changesets after a particular revision::
1587 - create a repository without changesets after a particular revision::
1588
1588
1589 hg clone -r 04e544 experimental/ good/
1589 hg clone -r 04e544 experimental/ good/
1590
1590
1591 - clone (and track) a particular named branch::
1591 - clone (and track) a particular named branch::
1592
1592
1593 hg clone http://selenic.com/hg#stable
1593 hg clone http://selenic.com/hg#stable
1594
1594
1595 See :hg:`help urls` for details on specifying URLs.
1595 See :hg:`help urls` for details on specifying URLs.
1596
1596
1597 Returns 0 on success.
1597 Returns 0 on success.
1598 """
1598 """
1599 if opts.get('noupdate') and opts.get('updaterev'):
1599 if opts.get('noupdate') and opts.get('updaterev'):
1600 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1600 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1601
1601
1602 r = hg.clone(ui, opts, source, dest,
1602 r = hg.clone(ui, opts, source, dest,
1603 pull=opts.get('pull'),
1603 pull=opts.get('pull'),
1604 stream=opts.get('uncompressed'),
1604 stream=opts.get('uncompressed'),
1605 rev=opts.get('rev'),
1605 rev=opts.get('rev'),
1606 update=opts.get('updaterev') or not opts.get('noupdate'),
1606 update=opts.get('updaterev') or not opts.get('noupdate'),
1607 branch=opts.get('branch'),
1607 branch=opts.get('branch'),
1608 shareopts=opts.get('shareopts'))
1608 shareopts=opts.get('shareopts'))
1609
1609
1610 return r is None
1610 return r is None
1611
1611
1612 @command('^commit|ci',
1612 @command('^commit|ci',
1613 [('A', 'addremove', None,
1613 [('A', 'addremove', None,
1614 _('mark new/missing files as added/removed before committing')),
1614 _('mark new/missing files as added/removed before committing')),
1615 ('', 'close-branch', None,
1615 ('', 'close-branch', None,
1616 _('mark a branch head as closed')),
1616 _('mark a branch head as closed')),
1617 ('', 'amend', None, _('amend the parent of the working directory')),
1617 ('', 'amend', None, _('amend the parent of the working directory')),
1618 ('s', 'secret', None, _('use the secret phase for committing')),
1618 ('s', 'secret', None, _('use the secret phase for committing')),
1619 ('e', 'edit', None, _('invoke editor on commit messages')),
1619 ('e', 'edit', None, _('invoke editor on commit messages')),
1620 ('i', 'interactive', None, _('use interactive mode')),
1620 ('i', 'interactive', None, _('use interactive mode')),
1621 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1621 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1622 _('[OPTION]... [FILE]...'),
1622 _('[OPTION]... [FILE]...'),
1623 inferrepo=True)
1623 inferrepo=True)
1624 def commit(ui, repo, *pats, **opts):
1624 def commit(ui, repo, *pats, **opts):
1625 """commit the specified files or all outstanding changes
1625 """commit the specified files or all outstanding changes
1626
1626
1627 Commit changes to the given files into the repository. Unlike a
1627 Commit changes to the given files into the repository. Unlike a
1628 centralized SCM, this operation is a local operation. See
1628 centralized SCM, this operation is a local operation. See
1629 :hg:`push` for a way to actively distribute your changes.
1629 :hg:`push` for a way to actively distribute your changes.
1630
1630
1631 If a list of files is omitted, all changes reported by :hg:`status`
1631 If a list of files is omitted, all changes reported by :hg:`status`
1632 will be committed.
1632 will be committed.
1633
1633
1634 If you are committing the result of a merge, do not provide any
1634 If you are committing the result of a merge, do not provide any
1635 filenames or -I/-X filters.
1635 filenames or -I/-X filters.
1636
1636
1637 If no commit message is specified, Mercurial starts your
1637 If no commit message is specified, Mercurial starts your
1638 configured editor where you can enter a message. In case your
1638 configured editor where you can enter a message. In case your
1639 commit fails, you will find a backup of your message in
1639 commit fails, you will find a backup of your message in
1640 ``.hg/last-message.txt``.
1640 ``.hg/last-message.txt``.
1641
1641
1642 The --close-branch flag can be used to mark the current branch
1642 The --close-branch flag can be used to mark the current branch
1643 head closed. When all heads of a branch are closed, the branch
1643 head closed. When all heads of a branch are closed, the branch
1644 will be considered closed and no longer listed.
1644 will be considered closed and no longer listed.
1645
1645
1646 The --amend flag can be used to amend the parent of the
1646 The --amend flag can be used to amend the parent of the
1647 working directory with a new commit that contains the changes
1647 working directory with a new commit that contains the changes
1648 in the parent in addition to those currently reported by :hg:`status`,
1648 in the parent in addition to those currently reported by :hg:`status`,
1649 if there are any. The old commit is stored in a backup bundle in
1649 if there are any. The old commit is stored in a backup bundle in
1650 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1650 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1651 on how to restore it).
1651 on how to restore it).
1652
1652
1653 Message, user and date are taken from the amended commit unless
1653 Message, user and date are taken from the amended commit unless
1654 specified. When a message isn't specified on the command line,
1654 specified. When a message isn't specified on the command line,
1655 the editor will open with the message of the amended commit.
1655 the editor will open with the message of the amended commit.
1656
1656
1657 It is not possible to amend public changesets (see :hg:`help phases`)
1657 It is not possible to amend public changesets (see :hg:`help phases`)
1658 or changesets that have children.
1658 or changesets that have children.
1659
1659
1660 See :hg:`help dates` for a list of formats valid for -d/--date.
1660 See :hg:`help dates` for a list of formats valid for -d/--date.
1661
1661
1662 Returns 0 on success, 1 if nothing changed.
1662 Returns 0 on success, 1 if nothing changed.
1663
1663
1664 .. container:: verbose
1664 .. container:: verbose
1665
1665
1666 Examples:
1666 Examples:
1667
1667
1668 - commit all files ending in .py::
1668 - commit all files ending in .py::
1669
1669
1670 hg commit --include "set:**.py"
1670 hg commit --include "set:**.py"
1671
1671
1672 - commit all non-binary files::
1672 - commit all non-binary files::
1673
1673
1674 hg commit --exclude "set:binary()"
1674 hg commit --exclude "set:binary()"
1675
1675
1676 - amend the current commit and set the date to now::
1676 - amend the current commit and set the date to now::
1677
1677
1678 hg commit --amend --date now
1678 hg commit --amend --date now
1679 """
1679 """
1680 wlock = lock = None
1680 wlock = lock = None
1681 try:
1681 try:
1682 wlock = repo.wlock()
1682 wlock = repo.wlock()
1683 lock = repo.lock()
1683 lock = repo.lock()
1684 return _docommit(ui, repo, *pats, **opts)
1684 return _docommit(ui, repo, *pats, **opts)
1685 finally:
1685 finally:
1686 release(lock, wlock)
1686 release(lock, wlock)
1687
1687
1688 def _docommit(ui, repo, *pats, **opts):
1688 def _docommit(ui, repo, *pats, **opts):
1689 if opts.get('interactive'):
1689 if opts.get('interactive'):
1690 opts.pop('interactive')
1690 opts.pop('interactive')
1691 cmdutil.dorecord(ui, repo, commit, None, False,
1691 cmdutil.dorecord(ui, repo, commit, None, False,
1692 cmdutil.recordfilter, *pats, **opts)
1692 cmdutil.recordfilter, *pats, **opts)
1693 return
1693 return
1694
1694
1695 if opts.get('subrepos'):
1695 if opts.get('subrepos'):
1696 if opts.get('amend'):
1696 if opts.get('amend'):
1697 raise error.Abort(_('cannot amend with --subrepos'))
1697 raise error.Abort(_('cannot amend with --subrepos'))
1698 # Let --subrepos on the command line override config setting.
1698 # Let --subrepos on the command line override config setting.
1699 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1699 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1700
1700
1701 cmdutil.checkunfinished(repo, commit=True)
1701 cmdutil.checkunfinished(repo, commit=True)
1702
1702
1703 branch = repo[None].branch()
1703 branch = repo[None].branch()
1704 bheads = repo.branchheads(branch)
1704 bheads = repo.branchheads(branch)
1705
1705
1706 extra = {}
1706 extra = {}
1707 if opts.get('close_branch'):
1707 if opts.get('close_branch'):
1708 extra['close'] = 1
1708 extra['close'] = 1
1709
1709
1710 if not bheads:
1710 if not bheads:
1711 raise error.Abort(_('can only close branch heads'))
1711 raise error.Abort(_('can only close branch heads'))
1712 elif opts.get('amend'):
1712 elif opts.get('amend'):
1713 if repo[None].parents()[0].p1().branch() != branch and \
1713 if repo[None].parents()[0].p1().branch() != branch and \
1714 repo[None].parents()[0].p2().branch() != branch:
1714 repo[None].parents()[0].p2().branch() != branch:
1715 raise error.Abort(_('can only close branch heads'))
1715 raise error.Abort(_('can only close branch heads'))
1716
1716
1717 if opts.get('amend'):
1717 if opts.get('amend'):
1718 if ui.configbool('ui', 'commitsubrepos'):
1718 if ui.configbool('ui', 'commitsubrepos'):
1719 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1719 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1720
1720
1721 old = repo['.']
1721 old = repo['.']
1722 if not old.mutable():
1722 if not old.mutable():
1723 raise error.Abort(_('cannot amend public changesets'))
1723 raise error.Abort(_('cannot amend public changesets'))
1724 if len(repo[None].parents()) > 1:
1724 if len(repo[None].parents()) > 1:
1725 raise error.Abort(_('cannot amend while merging'))
1725 raise error.Abort(_('cannot amend while merging'))
1726 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1726 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1727 if not allowunstable and old.children():
1727 if not allowunstable and old.children():
1728 raise error.Abort(_('cannot amend changeset with children'))
1728 raise error.Abort(_('cannot amend changeset with children'))
1729
1729
1730 # Currently histedit gets confused if an amend happens while histedit
1730 # Currently histedit gets confused if an amend happens while histedit
1731 # is in progress. Since we have a checkunfinished command, we are
1731 # is in progress. Since we have a checkunfinished command, we are
1732 # temporarily honoring it.
1732 # temporarily honoring it.
1733 #
1733 #
1734 # Note: eventually this guard will be removed. Please do not expect
1734 # Note: eventually this guard will be removed. Please do not expect
1735 # this behavior to remain.
1735 # this behavior to remain.
1736 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1736 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1737 cmdutil.checkunfinished(repo)
1737 cmdutil.checkunfinished(repo)
1738
1738
1739 # commitfunc is used only for temporary amend commit by cmdutil.amend
1739 # commitfunc is used only for temporary amend commit by cmdutil.amend
1740 def commitfunc(ui, repo, message, match, opts):
1740 def commitfunc(ui, repo, message, match, opts):
1741 return repo.commit(message,
1741 return repo.commit(message,
1742 opts.get('user') or old.user(),
1742 opts.get('user') or old.user(),
1743 opts.get('date') or old.date(),
1743 opts.get('date') or old.date(),
1744 match,
1744 match,
1745 extra=extra)
1745 extra=extra)
1746
1746
1747 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1747 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1748 if node == old.node():
1748 if node == old.node():
1749 ui.status(_("nothing changed\n"))
1749 ui.status(_("nothing changed\n"))
1750 return 1
1750 return 1
1751 else:
1751 else:
1752 def commitfunc(ui, repo, message, match, opts):
1752 def commitfunc(ui, repo, message, match, opts):
1753 backup = ui.backupconfig('phases', 'new-commit')
1753 backup = ui.backupconfig('phases', 'new-commit')
1754 baseui = repo.baseui
1754 baseui = repo.baseui
1755 basebackup = baseui.backupconfig('phases', 'new-commit')
1755 basebackup = baseui.backupconfig('phases', 'new-commit')
1756 try:
1756 try:
1757 if opts.get('secret'):
1757 if opts.get('secret'):
1758 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1758 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1759 # Propagate to subrepos
1759 # Propagate to subrepos
1760 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1760 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1761
1761
1762 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1762 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1763 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1763 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1764 return repo.commit(message, opts.get('user'), opts.get('date'),
1764 return repo.commit(message, opts.get('user'), opts.get('date'),
1765 match,
1765 match,
1766 editor=editor,
1766 editor=editor,
1767 extra=extra)
1767 extra=extra)
1768 finally:
1768 finally:
1769 ui.restoreconfig(backup)
1769 ui.restoreconfig(backup)
1770 repo.baseui.restoreconfig(basebackup)
1770 repo.baseui.restoreconfig(basebackup)
1771
1771
1772
1772
1773 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1773 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1774
1774
1775 if not node:
1775 if not node:
1776 stat = cmdutil.postcommitstatus(repo, pats, opts)
1776 stat = cmdutil.postcommitstatus(repo, pats, opts)
1777 if stat[3]:
1777 if stat[3]:
1778 ui.status(_("nothing changed (%d missing files, see "
1778 ui.status(_("nothing changed (%d missing files, see "
1779 "'hg status')\n") % len(stat[3]))
1779 "'hg status')\n") % len(stat[3]))
1780 else:
1780 else:
1781 ui.status(_("nothing changed\n"))
1781 ui.status(_("nothing changed\n"))
1782 return 1
1782 return 1
1783
1783
1784 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1784 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1785
1785
1786 @command('config|showconfig|debugconfig',
1786 @command('config|showconfig|debugconfig',
1787 [('u', 'untrusted', None, _('show untrusted configuration options')),
1787 [('u', 'untrusted', None, _('show untrusted configuration options')),
1788 ('e', 'edit', None, _('edit user config')),
1788 ('e', 'edit', None, _('edit user config')),
1789 ('l', 'local', None, _('edit repository config')),
1789 ('l', 'local', None, _('edit repository config')),
1790 ('g', 'global', None, _('edit global config'))],
1790 ('g', 'global', None, _('edit global config'))],
1791 _('[-u] [NAME]...'),
1791 _('[-u] [NAME]...'),
1792 optionalrepo=True)
1792 optionalrepo=True)
1793 def config(ui, repo, *values, **opts):
1793 def config(ui, repo, *values, **opts):
1794 """show combined config settings from all hgrc files
1794 """show combined config settings from all hgrc files
1795
1795
1796 With no arguments, print names and values of all config items.
1796 With no arguments, print names and values of all config items.
1797
1797
1798 With one argument of the form section.name, print just the value
1798 With one argument of the form section.name, print just the value
1799 of that config item.
1799 of that config item.
1800
1800
1801 With multiple arguments, print names and values of all config
1801 With multiple arguments, print names and values of all config
1802 items with matching section names.
1802 items with matching section names.
1803
1803
1804 With --edit, start an editor on the user-level config file. With
1804 With --edit, start an editor on the user-level config file. With
1805 --global, edit the system-wide config file. With --local, edit the
1805 --global, edit the system-wide config file. With --local, edit the
1806 repository-level config file.
1806 repository-level config file.
1807
1807
1808 With --debug, the source (filename and line number) is printed
1808 With --debug, the source (filename and line number) is printed
1809 for each config item.
1809 for each config item.
1810
1810
1811 See :hg:`help config` for more information about config files.
1811 See :hg:`help config` for more information about config files.
1812
1812
1813 Returns 0 on success, 1 if NAME does not exist.
1813 Returns 0 on success, 1 if NAME does not exist.
1814
1814
1815 """
1815 """
1816
1816
1817 if opts.get('edit') or opts.get('local') or opts.get('global'):
1817 if opts.get('edit') or opts.get('local') or opts.get('global'):
1818 if opts.get('local') and opts.get('global'):
1818 if opts.get('local') and opts.get('global'):
1819 raise error.Abort(_("can't use --local and --global together"))
1819 raise error.Abort(_("can't use --local and --global together"))
1820
1820
1821 if opts.get('local'):
1821 if opts.get('local'):
1822 if not repo:
1822 if not repo:
1823 raise error.Abort(_("can't use --local outside a repository"))
1823 raise error.Abort(_("can't use --local outside a repository"))
1824 paths = [repo.join('hgrc')]
1824 paths = [repo.join('hgrc')]
1825 elif opts.get('global'):
1825 elif opts.get('global'):
1826 paths = scmutil.systemrcpath()
1826 paths = scmutil.systemrcpath()
1827 else:
1827 else:
1828 paths = scmutil.userrcpath()
1828 paths = scmutil.userrcpath()
1829
1829
1830 for f in paths:
1830 for f in paths:
1831 if os.path.exists(f):
1831 if os.path.exists(f):
1832 break
1832 break
1833 else:
1833 else:
1834 if opts.get('global'):
1834 if opts.get('global'):
1835 samplehgrc = uimod.samplehgrcs['global']
1835 samplehgrc = uimod.samplehgrcs['global']
1836 elif opts.get('local'):
1836 elif opts.get('local'):
1837 samplehgrc = uimod.samplehgrcs['local']
1837 samplehgrc = uimod.samplehgrcs['local']
1838 else:
1838 else:
1839 samplehgrc = uimod.samplehgrcs['user']
1839 samplehgrc = uimod.samplehgrcs['user']
1840
1840
1841 f = paths[0]
1841 f = paths[0]
1842 fp = open(f, "w")
1842 fp = open(f, "w")
1843 fp.write(samplehgrc)
1843 fp.write(samplehgrc)
1844 fp.close()
1844 fp.close()
1845
1845
1846 editor = ui.geteditor()
1846 editor = ui.geteditor()
1847 ui.system("%s \"%s\"" % (editor, f),
1847 ui.system("%s \"%s\"" % (editor, f),
1848 onerr=error.Abort, errprefix=_("edit failed"))
1848 onerr=error.Abort, errprefix=_("edit failed"))
1849 return
1849 return
1850
1850
1851 for f in scmutil.rcpath():
1851 for f in scmutil.rcpath():
1852 ui.debug('read config from: %s\n' % f)
1852 ui.debug('read config from: %s\n' % f)
1853 untrusted = bool(opts.get('untrusted'))
1853 untrusted = bool(opts.get('untrusted'))
1854 if values:
1854 if values:
1855 sections = [v for v in values if '.' not in v]
1855 sections = [v for v in values if '.' not in v]
1856 items = [v for v in values if '.' in v]
1856 items = [v for v in values if '.' in v]
1857 if len(items) > 1 or items and sections:
1857 if len(items) > 1 or items and sections:
1858 raise error.Abort(_('only one config item permitted'))
1858 raise error.Abort(_('only one config item permitted'))
1859 matched = False
1859 matched = False
1860 for section, name, value in ui.walkconfig(untrusted=untrusted):
1860 for section, name, value in ui.walkconfig(untrusted=untrusted):
1861 value = str(value).replace('\n', '\\n')
1861 value = str(value).replace('\n', '\\n')
1862 sectname = section + '.' + name
1862 sectname = section + '.' + name
1863 if values:
1863 if values:
1864 for v in values:
1864 for v in values:
1865 if v == section:
1865 if v == section:
1866 ui.debug('%s: ' %
1866 ui.debug('%s: ' %
1867 ui.configsource(section, name, untrusted))
1867 ui.configsource(section, name, untrusted))
1868 ui.write('%s=%s\n' % (sectname, value))
1868 ui.write('%s=%s\n' % (sectname, value))
1869 matched = True
1869 matched = True
1870 elif v == sectname:
1870 elif v == sectname:
1871 ui.debug('%s: ' %
1871 ui.debug('%s: ' %
1872 ui.configsource(section, name, untrusted))
1872 ui.configsource(section, name, untrusted))
1873 ui.write(value, '\n')
1873 ui.write(value, '\n')
1874 matched = True
1874 matched = True
1875 else:
1875 else:
1876 ui.debug('%s: ' %
1876 ui.debug('%s: ' %
1877 ui.configsource(section, name, untrusted))
1877 ui.configsource(section, name, untrusted))
1878 ui.write('%s=%s\n' % (sectname, value))
1878 ui.write('%s=%s\n' % (sectname, value))
1879 matched = True
1879 matched = True
1880 if matched:
1880 if matched:
1881 return 0
1881 return 0
1882 return 1
1882 return 1
1883
1883
1884 @command('copy|cp',
1884 @command('copy|cp',
1885 [('A', 'after', None, _('record a copy that has already occurred')),
1885 [('A', 'after', None, _('record a copy that has already occurred')),
1886 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1886 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1887 ] + walkopts + dryrunopts,
1887 ] + walkopts + dryrunopts,
1888 _('[OPTION]... [SOURCE]... DEST'))
1888 _('[OPTION]... [SOURCE]... DEST'))
1889 def copy(ui, repo, *pats, **opts):
1889 def copy(ui, repo, *pats, **opts):
1890 """mark files as copied for the next commit
1890 """mark files as copied for the next commit
1891
1891
1892 Mark dest as having copies of source files. If dest is a
1892 Mark dest as having copies of source files. If dest is a
1893 directory, copies are put in that directory. If dest is a file,
1893 directory, copies are put in that directory. If dest is a file,
1894 the source must be a single file.
1894 the source must be a single file.
1895
1895
1896 By default, this command copies the contents of files as they
1896 By default, this command copies the contents of files as they
1897 exist in the working directory. If invoked with -A/--after, the
1897 exist in the working directory. If invoked with -A/--after, the
1898 operation is recorded, but no copying is performed.
1898 operation is recorded, but no copying is performed.
1899
1899
1900 This command takes effect with the next commit. To undo a copy
1900 This command takes effect with the next commit. To undo a copy
1901 before that, see :hg:`revert`.
1901 before that, see :hg:`revert`.
1902
1902
1903 Returns 0 on success, 1 if errors are encountered.
1903 Returns 0 on success, 1 if errors are encountered.
1904 """
1904 """
1905 with repo.wlock(False):
1905 with repo.wlock(False):
1906 return cmdutil.copy(ui, repo, pats, opts)
1906 return cmdutil.copy(ui, repo, pats, opts)
1907
1907
1908 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1908 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1909 def debugancestor(ui, repo, *args):
1909 def debugancestor(ui, repo, *args):
1910 """find the ancestor revision of two revisions in a given index"""
1910 """find the ancestor revision of two revisions in a given index"""
1911 if len(args) == 3:
1911 if len(args) == 3:
1912 index, rev1, rev2 = args
1912 index, rev1, rev2 = args
1913 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1913 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1914 lookup = r.lookup
1914 lookup = r.lookup
1915 elif len(args) == 2:
1915 elif len(args) == 2:
1916 if not repo:
1916 if not repo:
1917 raise error.Abort(_("there is no Mercurial repository here "
1917 raise error.Abort(_("there is no Mercurial repository here "
1918 "(.hg not found)"))
1918 "(.hg not found)"))
1919 rev1, rev2 = args
1919 rev1, rev2 = args
1920 r = repo.changelog
1920 r = repo.changelog
1921 lookup = repo.lookup
1921 lookup = repo.lookup
1922 else:
1922 else:
1923 raise error.Abort(_('either two or three arguments required'))
1923 raise error.Abort(_('either two or three arguments required'))
1924 a = r.ancestor(lookup(rev1), lookup(rev2))
1924 a = r.ancestor(lookup(rev1), lookup(rev2))
1925 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1925 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1926
1926
1927 @command('debugbuilddag',
1927 @command('debugbuilddag',
1928 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1928 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1929 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1929 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1930 ('n', 'new-file', None, _('add new file at each rev'))],
1930 ('n', 'new-file', None, _('add new file at each rev'))],
1931 _('[OPTION]... [TEXT]'))
1931 _('[OPTION]... [TEXT]'))
1932 def debugbuilddag(ui, repo, text=None,
1932 def debugbuilddag(ui, repo, text=None,
1933 mergeable_file=False,
1933 mergeable_file=False,
1934 overwritten_file=False,
1934 overwritten_file=False,
1935 new_file=False):
1935 new_file=False):
1936 """builds a repo with a given DAG from scratch in the current empty repo
1936 """builds a repo with a given DAG from scratch in the current empty repo
1937
1937
1938 The description of the DAG is read from stdin if not given on the
1938 The description of the DAG is read from stdin if not given on the
1939 command line.
1939 command line.
1940
1940
1941 Elements:
1941 Elements:
1942
1942
1943 - "+n" is a linear run of n nodes based on the current default parent
1943 - "+n" is a linear run of n nodes based on the current default parent
1944 - "." is a single node based on the current default parent
1944 - "." is a single node based on the current default parent
1945 - "$" resets the default parent to null (implied at the start);
1945 - "$" resets the default parent to null (implied at the start);
1946 otherwise the default parent is always the last node created
1946 otherwise the default parent is always the last node created
1947 - "<p" sets the default parent to the backref p
1947 - "<p" sets the default parent to the backref p
1948 - "*p" is a fork at parent p, which is a backref
1948 - "*p" is a fork at parent p, which is a backref
1949 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1949 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1950 - "/p2" is a merge of the preceding node and p2
1950 - "/p2" is a merge of the preceding node and p2
1951 - ":tag" defines a local tag for the preceding node
1951 - ":tag" defines a local tag for the preceding node
1952 - "@branch" sets the named branch for subsequent nodes
1952 - "@branch" sets the named branch for subsequent nodes
1953 - "#...\\n" is a comment up to the end of the line
1953 - "#...\\n" is a comment up to the end of the line
1954
1954
1955 Whitespace between the above elements is ignored.
1955 Whitespace between the above elements is ignored.
1956
1956
1957 A backref is either
1957 A backref is either
1958
1958
1959 - a number n, which references the node curr-n, where curr is the current
1959 - a number n, which references the node curr-n, where curr is the current
1960 node, or
1960 node, or
1961 - the name of a local tag you placed earlier using ":tag", or
1961 - the name of a local tag you placed earlier using ":tag", or
1962 - empty to denote the default parent.
1962 - empty to denote the default parent.
1963
1963
1964 All string valued-elements are either strictly alphanumeric, or must
1964 All string valued-elements are either strictly alphanumeric, or must
1965 be enclosed in double quotes ("..."), with "\\" as escape character.
1965 be enclosed in double quotes ("..."), with "\\" as escape character.
1966 """
1966 """
1967
1967
1968 if text is None:
1968 if text is None:
1969 ui.status(_("reading DAG from stdin\n"))
1969 ui.status(_("reading DAG from stdin\n"))
1970 text = ui.fin.read()
1970 text = ui.fin.read()
1971
1971
1972 cl = repo.changelog
1972 cl = repo.changelog
1973 if len(cl) > 0:
1973 if len(cl) > 0:
1974 raise error.Abort(_('repository is not empty'))
1974 raise error.Abort(_('repository is not empty'))
1975
1975
1976 # determine number of revs in DAG
1976 # determine number of revs in DAG
1977 total = 0
1977 total = 0
1978 for type, data in dagparser.parsedag(text):
1978 for type, data in dagparser.parsedag(text):
1979 if type == 'n':
1979 if type == 'n':
1980 total += 1
1980 total += 1
1981
1981
1982 if mergeable_file:
1982 if mergeable_file:
1983 linesperrev = 2
1983 linesperrev = 2
1984 # make a file with k lines per rev
1984 # make a file with k lines per rev
1985 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1985 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1986 initialmergedlines.append("")
1986 initialmergedlines.append("")
1987
1987
1988 tags = []
1988 tags = []
1989
1989
1990 lock = tr = None
1990 lock = tr = None
1991 try:
1991 try:
1992 lock = repo.lock()
1992 lock = repo.lock()
1993 tr = repo.transaction("builddag")
1993 tr = repo.transaction("builddag")
1994
1994
1995 at = -1
1995 at = -1
1996 atbranch = 'default'
1996 atbranch = 'default'
1997 nodeids = []
1997 nodeids = []
1998 id = 0
1998 id = 0
1999 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1999 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2000 for type, data in dagparser.parsedag(text):
2000 for type, data in dagparser.parsedag(text):
2001 if type == 'n':
2001 if type == 'n':
2002 ui.note(('node %s\n' % str(data)))
2002 ui.note(('node %s\n' % str(data)))
2003 id, ps = data
2003 id, ps = data
2004
2004
2005 files = []
2005 files = []
2006 fctxs = {}
2006 fctxs = {}
2007
2007
2008 p2 = None
2008 p2 = None
2009 if mergeable_file:
2009 if mergeable_file:
2010 fn = "mf"
2010 fn = "mf"
2011 p1 = repo[ps[0]]
2011 p1 = repo[ps[0]]
2012 if len(ps) > 1:
2012 if len(ps) > 1:
2013 p2 = repo[ps[1]]
2013 p2 = repo[ps[1]]
2014 pa = p1.ancestor(p2)
2014 pa = p1.ancestor(p2)
2015 base, local, other = [x[fn].data() for x in (pa, p1,
2015 base, local, other = [x[fn].data() for x in (pa, p1,
2016 p2)]
2016 p2)]
2017 m3 = simplemerge.Merge3Text(base, local, other)
2017 m3 = simplemerge.Merge3Text(base, local, other)
2018 ml = [l.strip() for l in m3.merge_lines()]
2018 ml = [l.strip() for l in m3.merge_lines()]
2019 ml.append("")
2019 ml.append("")
2020 elif at > 0:
2020 elif at > 0:
2021 ml = p1[fn].data().split("\n")
2021 ml = p1[fn].data().split("\n")
2022 else:
2022 else:
2023 ml = initialmergedlines
2023 ml = initialmergedlines
2024 ml[id * linesperrev] += " r%i" % id
2024 ml[id * linesperrev] += " r%i" % id
2025 mergedtext = "\n".join(ml)
2025 mergedtext = "\n".join(ml)
2026 files.append(fn)
2026 files.append(fn)
2027 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
2027 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
2028
2028
2029 if overwritten_file:
2029 if overwritten_file:
2030 fn = "of"
2030 fn = "of"
2031 files.append(fn)
2031 files.append(fn)
2032 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2032 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2033
2033
2034 if new_file:
2034 if new_file:
2035 fn = "nf%i" % id
2035 fn = "nf%i" % id
2036 files.append(fn)
2036 files.append(fn)
2037 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2037 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2038 if len(ps) > 1:
2038 if len(ps) > 1:
2039 if not p2:
2039 if not p2:
2040 p2 = repo[ps[1]]
2040 p2 = repo[ps[1]]
2041 for fn in p2:
2041 for fn in p2:
2042 if fn.startswith("nf"):
2042 if fn.startswith("nf"):
2043 files.append(fn)
2043 files.append(fn)
2044 fctxs[fn] = p2[fn]
2044 fctxs[fn] = p2[fn]
2045
2045
2046 def fctxfn(repo, cx, path):
2046 def fctxfn(repo, cx, path):
2047 return fctxs.get(path)
2047 return fctxs.get(path)
2048
2048
2049 if len(ps) == 0 or ps[0] < 0:
2049 if len(ps) == 0 or ps[0] < 0:
2050 pars = [None, None]
2050 pars = [None, None]
2051 elif len(ps) == 1:
2051 elif len(ps) == 1:
2052 pars = [nodeids[ps[0]], None]
2052 pars = [nodeids[ps[0]], None]
2053 else:
2053 else:
2054 pars = [nodeids[p] for p in ps]
2054 pars = [nodeids[p] for p in ps]
2055 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2055 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2056 date=(id, 0),
2056 date=(id, 0),
2057 user="debugbuilddag",
2057 user="debugbuilddag",
2058 extra={'branch': atbranch})
2058 extra={'branch': atbranch})
2059 nodeid = repo.commitctx(cx)
2059 nodeid = repo.commitctx(cx)
2060 nodeids.append(nodeid)
2060 nodeids.append(nodeid)
2061 at = id
2061 at = id
2062 elif type == 'l':
2062 elif type == 'l':
2063 id, name = data
2063 id, name = data
2064 ui.note(('tag %s\n' % name))
2064 ui.note(('tag %s\n' % name))
2065 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2065 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2066 elif type == 'a':
2066 elif type == 'a':
2067 ui.note(('branch %s\n' % data))
2067 ui.note(('branch %s\n' % data))
2068 atbranch = data
2068 atbranch = data
2069 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2069 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2070 tr.close()
2070 tr.close()
2071
2071
2072 if tags:
2072 if tags:
2073 repo.vfs.write("localtags", "".join(tags))
2073 repo.vfs.write("localtags", "".join(tags))
2074 finally:
2074 finally:
2075 ui.progress(_('building'), None)
2075 ui.progress(_('building'), None)
2076 release(tr, lock)
2076 release(tr, lock)
2077
2077
2078 @command('debugbundle',
2078 @command('debugbundle',
2079 [('a', 'all', None, _('show all details')),
2079 [('a', 'all', None, _('show all details')),
2080 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2080 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2081 _('FILE'),
2081 _('FILE'),
2082 norepo=True)
2082 norepo=True)
2083 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2083 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2084 """lists the contents of a bundle"""
2084 """lists the contents of a bundle"""
2085 with hg.openpath(ui, bundlepath) as f:
2085 with hg.openpath(ui, bundlepath) as f:
2086 if spec:
2086 if spec:
2087 spec = exchange.getbundlespec(ui, f)
2087 spec = exchange.getbundlespec(ui, f)
2088 ui.write('%s\n' % spec)
2088 ui.write('%s\n' % spec)
2089 return
2089 return
2090
2090
2091 gen = exchange.readbundle(ui, f, bundlepath)
2091 gen = exchange.readbundle(ui, f, bundlepath)
2092 if isinstance(gen, bundle2.unbundle20):
2092 if isinstance(gen, bundle2.unbundle20):
2093 return _debugbundle2(ui, gen, all=all, **opts)
2093 return _debugbundle2(ui, gen, all=all, **opts)
2094 _debugchangegroup(ui, gen, all=all, **opts)
2094 _debugchangegroup(ui, gen, all=all, **opts)
2095
2095
2096 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2096 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2097 indent_string = ' ' * indent
2097 indent_string = ' ' * indent
2098 if all:
2098 if all:
2099 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2099 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2100 % indent_string)
2100 % indent_string)
2101
2101
2102 def showchunks(named):
2102 def showchunks(named):
2103 ui.write("\n%s%s\n" % (indent_string, named))
2103 ui.write("\n%s%s\n" % (indent_string, named))
2104 chain = None
2104 chain = None
2105 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2105 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2106 node = chunkdata['node']
2106 node = chunkdata['node']
2107 p1 = chunkdata['p1']
2107 p1 = chunkdata['p1']
2108 p2 = chunkdata['p2']
2108 p2 = chunkdata['p2']
2109 cs = chunkdata['cs']
2109 cs = chunkdata['cs']
2110 deltabase = chunkdata['deltabase']
2110 deltabase = chunkdata['deltabase']
2111 delta = chunkdata['delta']
2111 delta = chunkdata['delta']
2112 ui.write("%s%s %s %s %s %s %s\n" %
2112 ui.write("%s%s %s %s %s %s %s\n" %
2113 (indent_string, hex(node), hex(p1), hex(p2),
2113 (indent_string, hex(node), hex(p1), hex(p2),
2114 hex(cs), hex(deltabase), len(delta)))
2114 hex(cs), hex(deltabase), len(delta)))
2115 chain = node
2115 chain = node
2116
2116
2117 chunkdata = gen.changelogheader()
2117 chunkdata = gen.changelogheader()
2118 showchunks("changelog")
2118 showchunks("changelog")
2119 chunkdata = gen.manifestheader()
2119 chunkdata = gen.manifestheader()
2120 showchunks("manifest")
2120 showchunks("manifest")
2121 for chunkdata in iter(gen.filelogheader, {}):
2121 for chunkdata in iter(gen.filelogheader, {}):
2122 fname = chunkdata['filename']
2122 fname = chunkdata['filename']
2123 showchunks(fname)
2123 showchunks(fname)
2124 else:
2124 else:
2125 if isinstance(gen, bundle2.unbundle20):
2125 if isinstance(gen, bundle2.unbundle20):
2126 raise error.Abort(_('use debugbundle2 for this file'))
2126 raise error.Abort(_('use debugbundle2 for this file'))
2127 chunkdata = gen.changelogheader()
2127 chunkdata = gen.changelogheader()
2128 chain = None
2128 chain = None
2129 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2129 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2130 node = chunkdata['node']
2130 node = chunkdata['node']
2131 ui.write("%s%s\n" % (indent_string, hex(node)))
2131 ui.write("%s%s\n" % (indent_string, hex(node)))
2132 chain = node
2132 chain = node
2133
2133
2134 def _debugbundle2(ui, gen, all=None, **opts):
2134 def _debugbundle2(ui, gen, all=None, **opts):
2135 """lists the contents of a bundle2"""
2135 """lists the contents of a bundle2"""
2136 if not isinstance(gen, bundle2.unbundle20):
2136 if not isinstance(gen, bundle2.unbundle20):
2137 raise error.Abort(_('not a bundle2 file'))
2137 raise error.Abort(_('not a bundle2 file'))
2138 ui.write(('Stream params: %s\n' % repr(gen.params)))
2138 ui.write(('Stream params: %s\n' % repr(gen.params)))
2139 for part in gen.iterparts():
2139 for part in gen.iterparts():
2140 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2140 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2141 if part.type == 'changegroup':
2141 if part.type == 'changegroup':
2142 version = part.params.get('version', '01')
2142 version = part.params.get('version', '01')
2143 cg = changegroup.getunbundler(version, part, 'UN')
2143 cg = changegroup.getunbundler(version, part, 'UN')
2144 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2144 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2145
2145
2146 @command('debugcreatestreamclonebundle', [], 'FILE')
2146 @command('debugcreatestreamclonebundle', [], 'FILE')
2147 def debugcreatestreamclonebundle(ui, repo, fname):
2147 def debugcreatestreamclonebundle(ui, repo, fname):
2148 """create a stream clone bundle file
2148 """create a stream clone bundle file
2149
2149
2150 Stream bundles are special bundles that are essentially archives of
2150 Stream bundles are special bundles that are essentially archives of
2151 revlog files. They are commonly used for cloning very quickly.
2151 revlog files. They are commonly used for cloning very quickly.
2152 """
2152 """
2153 requirements, gen = streamclone.generatebundlev1(repo)
2153 requirements, gen = streamclone.generatebundlev1(repo)
2154 changegroup.writechunks(ui, gen, fname)
2154 changegroup.writechunks(ui, gen, fname)
2155
2155
2156 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2156 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2157
2157
2158 @command('debugapplystreamclonebundle', [], 'FILE')
2158 @command('debugapplystreamclonebundle', [], 'FILE')
2159 def debugapplystreamclonebundle(ui, repo, fname):
2159 def debugapplystreamclonebundle(ui, repo, fname):
2160 """apply a stream clone bundle file"""
2160 """apply a stream clone bundle file"""
2161 f = hg.openpath(ui, fname)
2161 f = hg.openpath(ui, fname)
2162 gen = exchange.readbundle(ui, f, fname)
2162 gen = exchange.readbundle(ui, f, fname)
2163 gen.apply(repo)
2163 gen.apply(repo)
2164
2164
2165 @command('debugcheckstate', [], '')
2165 @command('debugcheckstate', [], '')
2166 def debugcheckstate(ui, repo):
2166 def debugcheckstate(ui, repo):
2167 """validate the correctness of the current dirstate"""
2167 """validate the correctness of the current dirstate"""
2168 parent1, parent2 = repo.dirstate.parents()
2168 parent1, parent2 = repo.dirstate.parents()
2169 m1 = repo[parent1].manifest()
2169 m1 = repo[parent1].manifest()
2170 m2 = repo[parent2].manifest()
2170 m2 = repo[parent2].manifest()
2171 errors = 0
2171 errors = 0
2172 for f in repo.dirstate:
2172 for f in repo.dirstate:
2173 state = repo.dirstate[f]
2173 state = repo.dirstate[f]
2174 if state in "nr" and f not in m1:
2174 if state in "nr" and f not in m1:
2175 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2175 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2176 errors += 1
2176 errors += 1
2177 if state in "a" and f in m1:
2177 if state in "a" and f in m1:
2178 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2178 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2179 errors += 1
2179 errors += 1
2180 if state in "m" and f not in m1 and f not in m2:
2180 if state in "m" and f not in m1 and f not in m2:
2181 ui.warn(_("%s in state %s, but not in either manifest\n") %
2181 ui.warn(_("%s in state %s, but not in either manifest\n") %
2182 (f, state))
2182 (f, state))
2183 errors += 1
2183 errors += 1
2184 for f in m1:
2184 for f in m1:
2185 state = repo.dirstate[f]
2185 state = repo.dirstate[f]
2186 if state not in "nrm":
2186 if state not in "nrm":
2187 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2187 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2188 errors += 1
2188 errors += 1
2189 if errors:
2189 if errors:
2190 error = _(".hg/dirstate inconsistent with current parent's manifest")
2190 error = _(".hg/dirstate inconsistent with current parent's manifest")
2191 raise error.Abort(error)
2191 raise error.Abort(error)
2192
2192
2193 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2193 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2194 def debugcommands(ui, cmd='', *args):
2194 def debugcommands(ui, cmd='', *args):
2195 """list all available commands and options"""
2195 """list all available commands and options"""
2196 for cmd, vals in sorted(table.iteritems()):
2196 for cmd, vals in sorted(table.iteritems()):
2197 cmd = cmd.split('|')[0].strip('^')
2197 cmd = cmd.split('|')[0].strip('^')
2198 opts = ', '.join([i[1] for i in vals[1]])
2198 opts = ', '.join([i[1] for i in vals[1]])
2199 ui.write('%s: %s\n' % (cmd, opts))
2199 ui.write('%s: %s\n' % (cmd, opts))
2200
2200
2201 @command('debugcomplete',
2201 @command('debugcomplete',
2202 [('o', 'options', None, _('show the command options'))],
2202 [('o', 'options', None, _('show the command options'))],
2203 _('[-o] CMD'),
2203 _('[-o] CMD'),
2204 norepo=True)
2204 norepo=True)
2205 def debugcomplete(ui, cmd='', **opts):
2205 def debugcomplete(ui, cmd='', **opts):
2206 """returns the completion list associated with the given command"""
2206 """returns the completion list associated with the given command"""
2207
2207
2208 if opts.get('options'):
2208 if opts.get('options'):
2209 options = []
2209 options = []
2210 otables = [globalopts]
2210 otables = [globalopts]
2211 if cmd:
2211 if cmd:
2212 aliases, entry = cmdutil.findcmd(cmd, table, False)
2212 aliases, entry = cmdutil.findcmd(cmd, table, False)
2213 otables.append(entry[1])
2213 otables.append(entry[1])
2214 for t in otables:
2214 for t in otables:
2215 for o in t:
2215 for o in t:
2216 if "(DEPRECATED)" in o[3]:
2216 if "(DEPRECATED)" in o[3]:
2217 continue
2217 continue
2218 if o[0]:
2218 if o[0]:
2219 options.append('-%s' % o[0])
2219 options.append('-%s' % o[0])
2220 options.append('--%s' % o[1])
2220 options.append('--%s' % o[1])
2221 ui.write("%s\n" % "\n".join(options))
2221 ui.write("%s\n" % "\n".join(options))
2222 return
2222 return
2223
2223
2224 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2224 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2225 if ui.verbose:
2225 if ui.verbose:
2226 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2226 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2227 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2227 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2228
2228
2229 @command('debugdag',
2229 @command('debugdag',
2230 [('t', 'tags', None, _('use tags as labels')),
2230 [('t', 'tags', None, _('use tags as labels')),
2231 ('b', 'branches', None, _('annotate with branch names')),
2231 ('b', 'branches', None, _('annotate with branch names')),
2232 ('', 'dots', None, _('use dots for runs')),
2232 ('', 'dots', None, _('use dots for runs')),
2233 ('s', 'spaces', None, _('separate elements by spaces'))],
2233 ('s', 'spaces', None, _('separate elements by spaces'))],
2234 _('[OPTION]... [FILE [REV]...]'),
2234 _('[OPTION]... [FILE [REV]...]'),
2235 optionalrepo=True)
2235 optionalrepo=True)
2236 def debugdag(ui, repo, file_=None, *revs, **opts):
2236 def debugdag(ui, repo, file_=None, *revs, **opts):
2237 """format the changelog or an index DAG as a concise textual description
2237 """format the changelog or an index DAG as a concise textual description
2238
2238
2239 If you pass a revlog index, the revlog's DAG is emitted. If you list
2239 If you pass a revlog index, the revlog's DAG is emitted. If you list
2240 revision numbers, they get labeled in the output as rN.
2240 revision numbers, they get labeled in the output as rN.
2241
2241
2242 Otherwise, the changelog DAG of the current repo is emitted.
2242 Otherwise, the changelog DAG of the current repo is emitted.
2243 """
2243 """
2244 spaces = opts.get('spaces')
2244 spaces = opts.get('spaces')
2245 dots = opts.get('dots')
2245 dots = opts.get('dots')
2246 if file_:
2246 if file_:
2247 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2247 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2248 revs = set((int(r) for r in revs))
2248 revs = set((int(r) for r in revs))
2249 def events():
2249 def events():
2250 for r in rlog:
2250 for r in rlog:
2251 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2251 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2252 if p != -1))
2252 if p != -1))
2253 if r in revs:
2253 if r in revs:
2254 yield 'l', (r, "r%i" % r)
2254 yield 'l', (r, "r%i" % r)
2255 elif repo:
2255 elif repo:
2256 cl = repo.changelog
2256 cl = repo.changelog
2257 tags = opts.get('tags')
2257 tags = opts.get('tags')
2258 branches = opts.get('branches')
2258 branches = opts.get('branches')
2259 if tags:
2259 if tags:
2260 labels = {}
2260 labels = {}
2261 for l, n in repo.tags().items():
2261 for l, n in repo.tags().items():
2262 labels.setdefault(cl.rev(n), []).append(l)
2262 labels.setdefault(cl.rev(n), []).append(l)
2263 def events():
2263 def events():
2264 b = "default"
2264 b = "default"
2265 for r in cl:
2265 for r in cl:
2266 if branches:
2266 if branches:
2267 newb = cl.read(cl.node(r))[5]['branch']
2267 newb = cl.read(cl.node(r))[5]['branch']
2268 if newb != b:
2268 if newb != b:
2269 yield 'a', newb
2269 yield 'a', newb
2270 b = newb
2270 b = newb
2271 yield 'n', (r, list(p for p in cl.parentrevs(r)
2271 yield 'n', (r, list(p for p in cl.parentrevs(r)
2272 if p != -1))
2272 if p != -1))
2273 if tags:
2273 if tags:
2274 ls = labels.get(r)
2274 ls = labels.get(r)
2275 if ls:
2275 if ls:
2276 for l in ls:
2276 for l in ls:
2277 yield 'l', (r, l)
2277 yield 'l', (r, l)
2278 else:
2278 else:
2279 raise error.Abort(_('need repo for changelog dag'))
2279 raise error.Abort(_('need repo for changelog dag'))
2280
2280
2281 for line in dagparser.dagtextlines(events(),
2281 for line in dagparser.dagtextlines(events(),
2282 addspaces=spaces,
2282 addspaces=spaces,
2283 wraplabels=True,
2283 wraplabels=True,
2284 wrapannotations=True,
2284 wrapannotations=True,
2285 wrapnonlinear=dots,
2285 wrapnonlinear=dots,
2286 usedots=dots,
2286 usedots=dots,
2287 maxlinewidth=70):
2287 maxlinewidth=70):
2288 ui.write(line)
2288 ui.write(line)
2289 ui.write("\n")
2289 ui.write("\n")
2290
2290
2291 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2291 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2292 def debugdata(ui, repo, file_, rev=None, **opts):
2292 def debugdata(ui, repo, file_, rev=None, **opts):
2293 """dump the contents of a data file revision"""
2293 """dump the contents of a data file revision"""
2294 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2294 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2295 if rev is not None:
2295 if rev is not None:
2296 raise error.CommandError('debugdata', _('invalid arguments'))
2296 raise error.CommandError('debugdata', _('invalid arguments'))
2297 file_, rev = None, file_
2297 file_, rev = None, file_
2298 elif rev is None:
2298 elif rev is None:
2299 raise error.CommandError('debugdata', _('invalid arguments'))
2299 raise error.CommandError('debugdata', _('invalid arguments'))
2300 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2300 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2301 try:
2301 try:
2302 ui.write(r.revision(r.lookup(rev)))
2302 ui.write(r.revision(r.lookup(rev)))
2303 except KeyError:
2303 except KeyError:
2304 raise error.Abort(_('invalid revision identifier %s') % rev)
2304 raise error.Abort(_('invalid revision identifier %s') % rev)
2305
2305
2306 @command('debugdate',
2306 @command('debugdate',
2307 [('e', 'extended', None, _('try extended date formats'))],
2307 [('e', 'extended', None, _('try extended date formats'))],
2308 _('[-e] DATE [RANGE]'),
2308 _('[-e] DATE [RANGE]'),
2309 norepo=True, optionalrepo=True)
2309 norepo=True, optionalrepo=True)
2310 def debugdate(ui, date, range=None, **opts):
2310 def debugdate(ui, date, range=None, **opts):
2311 """parse and display a date"""
2311 """parse and display a date"""
2312 if opts["extended"]:
2312 if opts["extended"]:
2313 d = util.parsedate(date, util.extendeddateformats)
2313 d = util.parsedate(date, util.extendeddateformats)
2314 else:
2314 else:
2315 d = util.parsedate(date)
2315 d = util.parsedate(date)
2316 ui.write(("internal: %s %s\n") % d)
2316 ui.write(("internal: %s %s\n") % d)
2317 ui.write(("standard: %s\n") % util.datestr(d))
2317 ui.write(("standard: %s\n") % util.datestr(d))
2318 if range:
2318 if range:
2319 m = util.matchdate(range)
2319 m = util.matchdate(range)
2320 ui.write(("match: %s\n") % m(d[0]))
2320 ui.write(("match: %s\n") % m(d[0]))
2321
2321
2322 @command('debugdiscovery',
2322 @command('debugdiscovery',
2323 [('', 'old', None, _('use old-style discovery')),
2323 [('', 'old', None, _('use old-style discovery')),
2324 ('', 'nonheads', None,
2324 ('', 'nonheads', None,
2325 _('use old-style discovery with non-heads included')),
2325 _('use old-style discovery with non-heads included')),
2326 ] + remoteopts,
2326 ] + remoteopts,
2327 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2327 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2328 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2328 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2329 """runs the changeset discovery protocol in isolation"""
2329 """runs the changeset discovery protocol in isolation"""
2330 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2330 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2331 opts.get('branch'))
2331 opts.get('branch'))
2332 remote = hg.peer(repo, opts, remoteurl)
2332 remote = hg.peer(repo, opts, remoteurl)
2333 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2333 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2334
2334
2335 # make sure tests are repeatable
2335 # make sure tests are repeatable
2336 random.seed(12323)
2336 random.seed(12323)
2337
2337
2338 def doit(localheads, remoteheads, remote=remote):
2338 def doit(localheads, remoteheads, remote=remote):
2339 if opts.get('old'):
2339 if opts.get('old'):
2340 if localheads:
2340 if localheads:
2341 raise error.Abort('cannot use localheads with old style '
2341 raise error.Abort('cannot use localheads with old style '
2342 'discovery')
2342 'discovery')
2343 if not util.safehasattr(remote, 'branches'):
2343 if not util.safehasattr(remote, 'branches'):
2344 # enable in-client legacy support
2344 # enable in-client legacy support
2345 remote = localrepo.locallegacypeer(remote.local())
2345 remote = localrepo.locallegacypeer(remote.local())
2346 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2346 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2347 force=True)
2347 force=True)
2348 common = set(common)
2348 common = set(common)
2349 if not opts.get('nonheads'):
2349 if not opts.get('nonheads'):
2350 ui.write(("unpruned common: %s\n") %
2350 ui.write(("unpruned common: %s\n") %
2351 " ".join(sorted(short(n) for n in common)))
2351 " ".join(sorted(short(n) for n in common)))
2352 dag = dagutil.revlogdag(repo.changelog)
2352 dag = dagutil.revlogdag(repo.changelog)
2353 all = dag.ancestorset(dag.internalizeall(common))
2353 all = dag.ancestorset(dag.internalizeall(common))
2354 common = dag.externalizeall(dag.headsetofconnecteds(all))
2354 common = dag.externalizeall(dag.headsetofconnecteds(all))
2355 else:
2355 else:
2356 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2356 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2357 common = set(common)
2357 common = set(common)
2358 rheads = set(hds)
2358 rheads = set(hds)
2359 lheads = set(repo.heads())
2359 lheads = set(repo.heads())
2360 ui.write(("common heads: %s\n") %
2360 ui.write(("common heads: %s\n") %
2361 " ".join(sorted(short(n) for n in common)))
2361 " ".join(sorted(short(n) for n in common)))
2362 if lheads <= common:
2362 if lheads <= common:
2363 ui.write(("local is subset\n"))
2363 ui.write(("local is subset\n"))
2364 elif rheads <= common:
2364 elif rheads <= common:
2365 ui.write(("remote is subset\n"))
2365 ui.write(("remote is subset\n"))
2366
2366
2367 serverlogs = opts.get('serverlog')
2367 serverlogs = opts.get('serverlog')
2368 if serverlogs:
2368 if serverlogs:
2369 for filename in serverlogs:
2369 for filename in serverlogs:
2370 with open(filename, 'r') as logfile:
2370 with open(filename, 'r') as logfile:
2371 line = logfile.readline()
2371 line = logfile.readline()
2372 while line:
2372 while line:
2373 parts = line.strip().split(';')
2373 parts = line.strip().split(';')
2374 op = parts[1]
2374 op = parts[1]
2375 if op == 'cg':
2375 if op == 'cg':
2376 pass
2376 pass
2377 elif op == 'cgss':
2377 elif op == 'cgss':
2378 doit(parts[2].split(' '), parts[3].split(' '))
2378 doit(parts[2].split(' '), parts[3].split(' '))
2379 elif op == 'unb':
2379 elif op == 'unb':
2380 doit(parts[3].split(' '), parts[2].split(' '))
2380 doit(parts[3].split(' '), parts[2].split(' '))
2381 line = logfile.readline()
2381 line = logfile.readline()
2382 else:
2382 else:
2383 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2383 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2384 opts.get('remote_head'))
2384 opts.get('remote_head'))
2385 localrevs = opts.get('local_head')
2385 localrevs = opts.get('local_head')
2386 doit(localrevs, remoterevs)
2386 doit(localrevs, remoterevs)
2387
2387
2388 @command('debugextensions', formatteropts, [], norepo=True)
2388 @command('debugextensions', formatteropts, [], norepo=True)
2389 def debugextensions(ui, **opts):
2389 def debugextensions(ui, **opts):
2390 '''show information about active extensions'''
2390 '''show information about active extensions'''
2391 exts = extensions.extensions(ui)
2391 exts = extensions.extensions(ui)
2392 hgver = util.version()
2392 hgver = util.version()
2393 fm = ui.formatter('debugextensions', opts)
2393 fm = ui.formatter('debugextensions', opts)
2394 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2394 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2395 extsource = extmod.__file__
2395 extsource = extmod.__file__
2396 exttestedwith = getattr(extmod, 'testedwith', '').split()
2396 exttestedwith = getattr(extmod, 'testedwith', '').split()
2397 extbuglink = getattr(extmod, 'buglink', None)
2397 extbuglink = getattr(extmod, 'buglink', None)
2398
2398
2399 fm.startitem()
2399 fm.startitem()
2400
2400
2401 if ui.quiet or ui.verbose:
2401 if ui.quiet or ui.verbose:
2402 fm.write('name', '%s\n', extname)
2402 fm.write('name', '%s\n', extname)
2403 else:
2403 else:
2404 fm.write('name', '%s', extname)
2404 fm.write('name', '%s', extname)
2405 if not exttestedwith:
2405 if not exttestedwith:
2406 fm.plain(_(' (untested!)\n'))
2406 fm.plain(_(' (untested!)\n'))
2407 elif exttestedwith == ['internal'] or hgver in exttestedwith:
2407 elif exttestedwith == ['internal'] or hgver in exttestedwith:
2408 fm.plain('\n')
2408 fm.plain('\n')
2409 else:
2409 else:
2410 lasttestedversion = exttestedwith[-1]
2410 lasttestedversion = exttestedwith[-1]
2411 fm.plain(' (%s!)\n' % lasttestedversion)
2411 fm.plain(' (%s!)\n' % lasttestedversion)
2412
2412
2413 fm.condwrite(ui.verbose and extsource, 'source',
2413 fm.condwrite(ui.verbose and extsource, 'source',
2414 _(' location: %s\n'), extsource or "")
2414 _(' location: %s\n'), extsource or "")
2415
2415
2416 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2416 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2417 _(' tested with: %s\n'),
2417 _(' tested with: %s\n'),
2418 fm.formatlist(exttestedwith, name='ver'))
2418 fm.formatlist(exttestedwith, name='ver'))
2419
2419
2420 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2420 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2421 _(' bug reporting: %s\n'), extbuglink or "")
2421 _(' bug reporting: %s\n'), extbuglink or "")
2422
2422
2423 fm.end()
2423 fm.end()
2424
2424
2425 @command('debugfileset',
2425 @command('debugfileset',
2426 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2426 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2427 _('[-r REV] FILESPEC'))
2427 _('[-r REV] FILESPEC'))
2428 def debugfileset(ui, repo, expr, **opts):
2428 def debugfileset(ui, repo, expr, **opts):
2429 '''parse and apply a fileset specification'''
2429 '''parse and apply a fileset specification'''
2430 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2430 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2431 if ui.verbose:
2431 if ui.verbose:
2432 tree = fileset.parse(expr)
2432 tree = fileset.parse(expr)
2433 ui.note(fileset.prettyformat(tree), "\n")
2433 ui.note(fileset.prettyformat(tree), "\n")
2434
2434
2435 for f in ctx.getfileset(expr):
2435 for f in ctx.getfileset(expr):
2436 ui.write("%s\n" % f)
2436 ui.write("%s\n" % f)
2437
2437
2438 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2438 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2439 def debugfsinfo(ui, path="."):
2439 def debugfsinfo(ui, path="."):
2440 """show information detected about current filesystem"""
2440 """show information detected about current filesystem"""
2441 util.writefile('.debugfsinfo', '')
2441 util.writefile('.debugfsinfo', '')
2442 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2442 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2443 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2443 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2444 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2444 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2445 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2445 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2446 and 'yes' or 'no'))
2446 and 'yes' or 'no'))
2447 os.unlink('.debugfsinfo')
2447 os.unlink('.debugfsinfo')
2448
2448
2449 @command('debuggetbundle',
2449 @command('debuggetbundle',
2450 [('H', 'head', [], _('id of head node'), _('ID')),
2450 [('H', 'head', [], _('id of head node'), _('ID')),
2451 ('C', 'common', [], _('id of common node'), _('ID')),
2451 ('C', 'common', [], _('id of common node'), _('ID')),
2452 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2452 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2453 _('REPO FILE [-H|-C ID]...'),
2453 _('REPO FILE [-H|-C ID]...'),
2454 norepo=True)
2454 norepo=True)
2455 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2455 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2456 """retrieves a bundle from a repo
2456 """retrieves a bundle from a repo
2457
2457
2458 Every ID must be a full-length hex node id string. Saves the bundle to the
2458 Every ID must be a full-length hex node id string. Saves the bundle to the
2459 given file.
2459 given file.
2460 """
2460 """
2461 repo = hg.peer(ui, opts, repopath)
2461 repo = hg.peer(ui, opts, repopath)
2462 if not repo.capable('getbundle'):
2462 if not repo.capable('getbundle'):
2463 raise error.Abort("getbundle() not supported by target repository")
2463 raise error.Abort("getbundle() not supported by target repository")
2464 args = {}
2464 args = {}
2465 if common:
2465 if common:
2466 args['common'] = [bin(s) for s in common]
2466 args['common'] = [bin(s) for s in common]
2467 if head:
2467 if head:
2468 args['heads'] = [bin(s) for s in head]
2468 args['heads'] = [bin(s) for s in head]
2469 # TODO: get desired bundlecaps from command line.
2469 # TODO: get desired bundlecaps from command line.
2470 args['bundlecaps'] = None
2470 args['bundlecaps'] = None
2471 bundle = repo.getbundle('debug', **args)
2471 bundle = repo.getbundle('debug', **args)
2472
2472
2473 bundletype = opts.get('type', 'bzip2').lower()
2473 bundletype = opts.get('type', 'bzip2').lower()
2474 btypes = {'none': 'HG10UN',
2474 btypes = {'none': 'HG10UN',
2475 'bzip2': 'HG10BZ',
2475 'bzip2': 'HG10BZ',
2476 'gzip': 'HG10GZ',
2476 'gzip': 'HG10GZ',
2477 'bundle2': 'HG20'}
2477 'bundle2': 'HG20'}
2478 bundletype = btypes.get(bundletype)
2478 bundletype = btypes.get(bundletype)
2479 if bundletype not in bundle2.bundletypes:
2479 if bundletype not in bundle2.bundletypes:
2480 raise error.Abort(_('unknown bundle type specified with --type'))
2480 raise error.Abort(_('unknown bundle type specified with --type'))
2481 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2481 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2482
2482
2483 @command('debugignore', [], '[FILE]')
2483 @command('debugignore', [], '[FILE]')
2484 def debugignore(ui, repo, *files, **opts):
2484 def debugignore(ui, repo, *files, **opts):
2485 """display the combined ignore pattern and information about ignored files
2485 """display the combined ignore pattern and information about ignored files
2486
2486
2487 With no argument display the combined ignore pattern.
2487 With no argument display the combined ignore pattern.
2488
2488
2489 Given space separated file names, shows if the given file is ignored and
2489 Given space separated file names, shows if the given file is ignored and
2490 if so, show the ignore rule (file and line number) that matched it.
2490 if so, show the ignore rule (file and line number) that matched it.
2491 """
2491 """
2492 ignore = repo.dirstate._ignore
2492 ignore = repo.dirstate._ignore
2493 if not files:
2493 if not files:
2494 # Show all the patterns
2494 # Show all the patterns
2495 includepat = getattr(ignore, 'includepat', None)
2495 includepat = getattr(ignore, 'includepat', None)
2496 if includepat is not None:
2496 if includepat is not None:
2497 ui.write("%s\n" % includepat)
2497 ui.write("%s\n" % includepat)
2498 else:
2498 else:
2499 raise error.Abort(_("no ignore patterns found"))
2499 raise error.Abort(_("no ignore patterns found"))
2500 else:
2500 else:
2501 for f in files:
2501 for f in files:
2502 nf = util.normpath(f)
2502 nf = util.normpath(f)
2503 ignored = None
2503 ignored = None
2504 ignoredata = None
2504 ignoredata = None
2505 if nf != '.':
2505 if nf != '.':
2506 if ignore(nf):
2506 if ignore(nf):
2507 ignored = nf
2507 ignored = nf
2508 ignoredata = repo.dirstate._ignorefileandline(nf)
2508 ignoredata = repo.dirstate._ignorefileandline(nf)
2509 else:
2509 else:
2510 for p in util.finddirs(nf):
2510 for p in util.finddirs(nf):
2511 if ignore(p):
2511 if ignore(p):
2512 ignored = p
2512 ignored = p
2513 ignoredata = repo.dirstate._ignorefileandline(p)
2513 ignoredata = repo.dirstate._ignorefileandline(p)
2514 break
2514 break
2515 if ignored:
2515 if ignored:
2516 if ignored == nf:
2516 if ignored == nf:
2517 ui.write(_("%s is ignored\n") % f)
2517 ui.write(_("%s is ignored\n") % f)
2518 else:
2518 else:
2519 ui.write(_("%s is ignored because of "
2519 ui.write(_("%s is ignored because of "
2520 "containing folder %s\n")
2520 "containing folder %s\n")
2521 % (f, ignored))
2521 % (f, ignored))
2522 ignorefile, lineno, line = ignoredata
2522 ignorefile, lineno, line = ignoredata
2523 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2523 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2524 % (ignorefile, lineno, line))
2524 % (ignorefile, lineno, line))
2525 else:
2525 else:
2526 ui.write(_("%s is not ignored\n") % f)
2526 ui.write(_("%s is not ignored\n") % f)
2527
2527
2528 @command('debugindex', debugrevlogopts +
2528 @command('debugindex', debugrevlogopts +
2529 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2529 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2530 _('[-f FORMAT] -c|-m|FILE'),
2530 _('[-f FORMAT] -c|-m|FILE'),
2531 optionalrepo=True)
2531 optionalrepo=True)
2532 def debugindex(ui, repo, file_=None, **opts):
2532 def debugindex(ui, repo, file_=None, **opts):
2533 """dump the contents of an index file"""
2533 """dump the contents of an index file"""
2534 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2534 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2535 format = opts.get('format', 0)
2535 format = opts.get('format', 0)
2536 if format not in (0, 1):
2536 if format not in (0, 1):
2537 raise error.Abort(_("unknown format %d") % format)
2537 raise error.Abort(_("unknown format %d") % format)
2538
2538
2539 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2539 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2540 if generaldelta:
2540 if generaldelta:
2541 basehdr = ' delta'
2541 basehdr = ' delta'
2542 else:
2542 else:
2543 basehdr = ' base'
2543 basehdr = ' base'
2544
2544
2545 if ui.debugflag:
2545 if ui.debugflag:
2546 shortfn = hex
2546 shortfn = hex
2547 else:
2547 else:
2548 shortfn = short
2548 shortfn = short
2549
2549
2550 # There might not be anything in r, so have a sane default
2550 # There might not be anything in r, so have a sane default
2551 idlen = 12
2551 idlen = 12
2552 for i in r:
2552 for i in r:
2553 idlen = len(shortfn(r.node(i)))
2553 idlen = len(shortfn(r.node(i)))
2554 break
2554 break
2555
2555
2556 if format == 0:
2556 if format == 0:
2557 ui.write((" rev offset length " + basehdr + " linkrev"
2557 ui.write((" rev offset length " + basehdr + " linkrev"
2558 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2558 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2559 elif format == 1:
2559 elif format == 1:
2560 ui.write((" rev flag offset length"
2560 ui.write((" rev flag offset length"
2561 " size " + basehdr + " link p1 p2"
2561 " size " + basehdr + " link p1 p2"
2562 " %s\n") % "nodeid".rjust(idlen))
2562 " %s\n") % "nodeid".rjust(idlen))
2563
2563
2564 for i in r:
2564 for i in r:
2565 node = r.node(i)
2565 node = r.node(i)
2566 if generaldelta:
2566 if generaldelta:
2567 base = r.deltaparent(i)
2567 base = r.deltaparent(i)
2568 else:
2568 else:
2569 base = r.chainbase(i)
2569 base = r.chainbase(i)
2570 if format == 0:
2570 if format == 0:
2571 try:
2571 try:
2572 pp = r.parents(node)
2572 pp = r.parents(node)
2573 except Exception:
2573 except Exception:
2574 pp = [nullid, nullid]
2574 pp = [nullid, nullid]
2575 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2575 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2576 i, r.start(i), r.length(i), base, r.linkrev(i),
2576 i, r.start(i), r.length(i), base, r.linkrev(i),
2577 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2577 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2578 elif format == 1:
2578 elif format == 1:
2579 pr = r.parentrevs(i)
2579 pr = r.parentrevs(i)
2580 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2580 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2581 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2581 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2582 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2582 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2583
2583
2584 @command('debugindexdot', debugrevlogopts,
2584 @command('debugindexdot', debugrevlogopts,
2585 _('-c|-m|FILE'), optionalrepo=True)
2585 _('-c|-m|FILE'), optionalrepo=True)
2586 def debugindexdot(ui, repo, file_=None, **opts):
2586 def debugindexdot(ui, repo, file_=None, **opts):
2587 """dump an index DAG as a graphviz dot file"""
2587 """dump an index DAG as a graphviz dot file"""
2588 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2588 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2589 ui.write(("digraph G {\n"))
2589 ui.write(("digraph G {\n"))
2590 for i in r:
2590 for i in r:
2591 node = r.node(i)
2591 node = r.node(i)
2592 pp = r.parents(node)
2592 pp = r.parents(node)
2593 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2593 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2594 if pp[1] != nullid:
2594 if pp[1] != nullid:
2595 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2595 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2596 ui.write("}\n")
2596 ui.write("}\n")
2597
2597
2598 @command('debugdeltachain',
2598 @command('debugdeltachain',
2599 debugrevlogopts + formatteropts,
2599 debugrevlogopts + formatteropts,
2600 _('-c|-m|FILE'),
2600 _('-c|-m|FILE'),
2601 optionalrepo=True)
2601 optionalrepo=True)
2602 def debugdeltachain(ui, repo, file_=None, **opts):
2602 def debugdeltachain(ui, repo, file_=None, **opts):
2603 """dump information about delta chains in a revlog
2603 """dump information about delta chains in a revlog
2604
2604
2605 Output can be templatized. Available template keywords are:
2605 Output can be templatized. Available template keywords are:
2606
2606
2607 :``rev``: revision number
2607 :``rev``: revision number
2608 :``chainid``: delta chain identifier (numbered by unique base)
2608 :``chainid``: delta chain identifier (numbered by unique base)
2609 :``chainlen``: delta chain length to this revision
2609 :``chainlen``: delta chain length to this revision
2610 :``prevrev``: previous revision in delta chain
2610 :``prevrev``: previous revision in delta chain
2611 :``deltatype``: role of delta / how it was computed
2611 :``deltatype``: role of delta / how it was computed
2612 :``compsize``: compressed size of revision
2612 :``compsize``: compressed size of revision
2613 :``uncompsize``: uncompressed size of revision
2613 :``uncompsize``: uncompressed size of revision
2614 :``chainsize``: total size of compressed revisions in chain
2614 :``chainsize``: total size of compressed revisions in chain
2615 :``chainratio``: total chain size divided by uncompressed revision size
2615 :``chainratio``: total chain size divided by uncompressed revision size
2616 (new delta chains typically start at ratio 2.00)
2616 (new delta chains typically start at ratio 2.00)
2617 :``lindist``: linear distance from base revision in delta chain to end
2617 :``lindist``: linear distance from base revision in delta chain to end
2618 of this revision
2618 of this revision
2619 :``extradist``: total size of revisions not part of this delta chain from
2619 :``extradist``: total size of revisions not part of this delta chain from
2620 base of delta chain to end of this revision; a measurement
2620 base of delta chain to end of this revision; a measurement
2621 of how much extra data we need to read/seek across to read
2621 of how much extra data we need to read/seek across to read
2622 the delta chain for this revision
2622 the delta chain for this revision
2623 :``extraratio``: extradist divided by chainsize; another representation of
2623 :``extraratio``: extradist divided by chainsize; another representation of
2624 how much unrelated data is needed to load this delta chain
2624 how much unrelated data is needed to load this delta chain
2625 """
2625 """
2626 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2626 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2627 index = r.index
2627 index = r.index
2628 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2628 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2629
2629
2630 def revinfo(rev):
2630 def revinfo(rev):
2631 e = index[rev]
2631 e = index[rev]
2632 compsize = e[1]
2632 compsize = e[1]
2633 uncompsize = e[2]
2633 uncompsize = e[2]
2634 chainsize = 0
2634 chainsize = 0
2635
2635
2636 if generaldelta:
2636 if generaldelta:
2637 if e[3] == e[5]:
2637 if e[3] == e[5]:
2638 deltatype = 'p1'
2638 deltatype = 'p1'
2639 elif e[3] == e[6]:
2639 elif e[3] == e[6]:
2640 deltatype = 'p2'
2640 deltatype = 'p2'
2641 elif e[3] == rev - 1:
2641 elif e[3] == rev - 1:
2642 deltatype = 'prev'
2642 deltatype = 'prev'
2643 elif e[3] == rev:
2643 elif e[3] == rev:
2644 deltatype = 'base'
2644 deltatype = 'base'
2645 else:
2645 else:
2646 deltatype = 'other'
2646 deltatype = 'other'
2647 else:
2647 else:
2648 if e[3] == rev:
2648 if e[3] == rev:
2649 deltatype = 'base'
2649 deltatype = 'base'
2650 else:
2650 else:
2651 deltatype = 'prev'
2651 deltatype = 'prev'
2652
2652
2653 chain = r._deltachain(rev)[0]
2653 chain = r._deltachain(rev)[0]
2654 for iterrev in chain:
2654 for iterrev in chain:
2655 e = index[iterrev]
2655 e = index[iterrev]
2656 chainsize += e[1]
2656 chainsize += e[1]
2657
2657
2658 return compsize, uncompsize, deltatype, chain, chainsize
2658 return compsize, uncompsize, deltatype, chain, chainsize
2659
2659
2660 fm = ui.formatter('debugdeltachain', opts)
2660 fm = ui.formatter('debugdeltachain', opts)
2661
2661
2662 fm.plain(' rev chain# chainlen prev delta '
2662 fm.plain(' rev chain# chainlen prev delta '
2663 'size rawsize chainsize ratio lindist extradist '
2663 'size rawsize chainsize ratio lindist extradist '
2664 'extraratio\n')
2664 'extraratio\n')
2665
2665
2666 chainbases = {}
2666 chainbases = {}
2667 for rev in r:
2667 for rev in r:
2668 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2668 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2669 chainbase = chain[0]
2669 chainbase = chain[0]
2670 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2670 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2671 basestart = r.start(chainbase)
2671 basestart = r.start(chainbase)
2672 revstart = r.start(rev)
2672 revstart = r.start(rev)
2673 lineardist = revstart + comp - basestart
2673 lineardist = revstart + comp - basestart
2674 extradist = lineardist - chainsize
2674 extradist = lineardist - chainsize
2675 try:
2675 try:
2676 prevrev = chain[-2]
2676 prevrev = chain[-2]
2677 except IndexError:
2677 except IndexError:
2678 prevrev = -1
2678 prevrev = -1
2679
2679
2680 chainratio = float(chainsize) / float(uncomp)
2680 chainratio = float(chainsize) / float(uncomp)
2681 extraratio = float(extradist) / float(chainsize)
2681 extraratio = float(extradist) / float(chainsize)
2682
2682
2683 fm.startitem()
2683 fm.startitem()
2684 fm.write('rev chainid chainlen prevrev deltatype compsize '
2684 fm.write('rev chainid chainlen prevrev deltatype compsize '
2685 'uncompsize chainsize chainratio lindist extradist '
2685 'uncompsize chainsize chainratio lindist extradist '
2686 'extraratio',
2686 'extraratio',
2687 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2687 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2688 rev, chainid, len(chain), prevrev, deltatype, comp,
2688 rev, chainid, len(chain), prevrev, deltatype, comp,
2689 uncomp, chainsize, chainratio, lineardist, extradist,
2689 uncomp, chainsize, chainratio, lineardist, extradist,
2690 extraratio,
2690 extraratio,
2691 rev=rev, chainid=chainid, chainlen=len(chain),
2691 rev=rev, chainid=chainid, chainlen=len(chain),
2692 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2692 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2693 uncompsize=uncomp, chainsize=chainsize,
2693 uncompsize=uncomp, chainsize=chainsize,
2694 chainratio=chainratio, lindist=lineardist,
2694 chainratio=chainratio, lindist=lineardist,
2695 extradist=extradist, extraratio=extraratio)
2695 extradist=extradist, extraratio=extraratio)
2696
2696
2697 fm.end()
2697 fm.end()
2698
2698
2699 @command('debuginstall', [] + formatteropts, '', norepo=True)
2699 @command('debuginstall', [] + formatteropts, '', norepo=True)
2700 def debuginstall(ui, **opts):
2700 def debuginstall(ui, **opts):
2701 '''test Mercurial installation
2701 '''test Mercurial installation
2702
2702
2703 Returns 0 on success.
2703 Returns 0 on success.
2704 '''
2704 '''
2705
2705
2706 def writetemp(contents):
2706 def writetemp(contents):
2707 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2707 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2708 f = os.fdopen(fd, "wb")
2708 f = os.fdopen(fd, "wb")
2709 f.write(contents)
2709 f.write(contents)
2710 f.close()
2710 f.close()
2711 return name
2711 return name
2712
2712
2713 problems = 0
2713 problems = 0
2714
2714
2715 fm = ui.formatter('debuginstall', opts)
2715 fm = ui.formatter('debuginstall', opts)
2716 fm.startitem()
2716 fm.startitem()
2717
2717
2718 # encoding
2718 # encoding
2719 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2719 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2720 err = None
2720 err = None
2721 try:
2721 try:
2722 encoding.fromlocal("test")
2722 encoding.fromlocal("test")
2723 except error.Abort as inst:
2723 except error.Abort as inst:
2724 err = inst
2724 err = inst
2725 problems += 1
2725 problems += 1
2726 fm.condwrite(err, 'encodingerror', _(" %s\n"
2726 fm.condwrite(err, 'encodingerror', _(" %s\n"
2727 " (check that your locale is properly set)\n"), err)
2727 " (check that your locale is properly set)\n"), err)
2728
2728
2729 # Python
2729 # Python
2730 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2730 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2731 sys.executable)
2731 sys.executable)
2732 fm.write('pythonver', _("checking Python version (%s)\n"),
2732 fm.write('pythonver', _("checking Python version (%s)\n"),
2733 ("%s.%s.%s" % sys.version_info[:3]))
2733 ("%s.%s.%s" % sys.version_info[:3]))
2734 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2734 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2735 os.path.dirname(os.__file__))
2735 os.path.dirname(os.__file__))
2736
2736
2737 # hg version
2737 # hg version
2738 hgver = util.version()
2738 hgver = util.version()
2739 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2739 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2740 hgver.split('+')[0])
2740 hgver.split('+')[0])
2741 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2741 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2742 '+'.join(hgver.split('+')[1:]))
2742 '+'.join(hgver.split('+')[1:]))
2743
2743
2744 # compiled modules
2744 # compiled modules
2745 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2745 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2746 policy.policy)
2746 policy.policy)
2747 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2747 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2748 os.path.dirname(__file__))
2748 os.path.dirname(__file__))
2749
2749
2750 err = None
2750 err = None
2751 try:
2751 try:
2752 from . import (
2752 from . import (
2753 base85,
2753 base85,
2754 bdiff,
2754 bdiff,
2755 mpatch,
2755 mpatch,
2756 osutil,
2756 osutil,
2757 )
2757 )
2758 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2758 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2759 except Exception as inst:
2759 except Exception as inst:
2760 err = inst
2760 err = inst
2761 problems += 1
2761 problems += 1
2762 fm.condwrite(err, 'extensionserror', " %s\n", err)
2762 fm.condwrite(err, 'extensionserror', " %s\n", err)
2763
2763
2764 # templates
2764 # templates
2765 p = templater.templatepaths()
2765 p = templater.templatepaths()
2766 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2766 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2767 fm.condwrite(not p, '', _(" no template directories found\n"))
2767 fm.condwrite(not p, '', _(" no template directories found\n"))
2768 if p:
2768 if p:
2769 m = templater.templatepath("map-cmdline.default")
2769 m = templater.templatepath("map-cmdline.default")
2770 if m:
2770 if m:
2771 # template found, check if it is working
2771 # template found, check if it is working
2772 err = None
2772 err = None
2773 try:
2773 try:
2774 templater.templater.frommapfile(m)
2774 templater.templater.frommapfile(m)
2775 except Exception as inst:
2775 except Exception as inst:
2776 err = inst
2776 err = inst
2777 p = None
2777 p = None
2778 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2778 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2779 else:
2779 else:
2780 p = None
2780 p = None
2781 fm.condwrite(p, 'defaulttemplate',
2781 fm.condwrite(p, 'defaulttemplate',
2782 _("checking default template (%s)\n"), m)
2782 _("checking default template (%s)\n"), m)
2783 fm.condwrite(not m, 'defaulttemplatenotfound',
2783 fm.condwrite(not m, 'defaulttemplatenotfound',
2784 _(" template '%s' not found\n"), "default")
2784 _(" template '%s' not found\n"), "default")
2785 if not p:
2785 if not p:
2786 problems += 1
2786 problems += 1
2787 fm.condwrite(not p, '',
2787 fm.condwrite(not p, '',
2788 _(" (templates seem to have been installed incorrectly)\n"))
2788 _(" (templates seem to have been installed incorrectly)\n"))
2789
2789
2790 # editor
2790 # editor
2791 editor = ui.geteditor()
2791 editor = ui.geteditor()
2792 editor = util.expandpath(editor)
2792 editor = util.expandpath(editor)
2793 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2793 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2794 cmdpath = util.findexe(shlex.split(editor)[0])
2794 cmdpath = util.findexe(shlex.split(editor)[0])
2795 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2795 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2796 _(" No commit editor set and can't find %s in PATH\n"
2796 _(" No commit editor set and can't find %s in PATH\n"
2797 " (specify a commit editor in your configuration"
2797 " (specify a commit editor in your configuration"
2798 " file)\n"), not cmdpath and editor == 'vi' and editor)
2798 " file)\n"), not cmdpath and editor == 'vi' and editor)
2799 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2799 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2800 _(" Can't find editor '%s' in PATH\n"
2800 _(" Can't find editor '%s' in PATH\n"
2801 " (specify a commit editor in your configuration"
2801 " (specify a commit editor in your configuration"
2802 " file)\n"), not cmdpath and editor)
2802 " file)\n"), not cmdpath and editor)
2803 if not cmdpath and editor != 'vi':
2803 if not cmdpath and editor != 'vi':
2804 problems += 1
2804 problems += 1
2805
2805
2806 # check username
2806 # check username
2807 username = None
2807 username = None
2808 err = None
2808 err = None
2809 try:
2809 try:
2810 username = ui.username()
2810 username = ui.username()
2811 except error.Abort as e:
2811 except error.Abort as e:
2812 err = e
2812 err = e
2813 problems += 1
2813 problems += 1
2814
2814
2815 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2815 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2816 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2816 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2817 " (specify a username in your configuration file)\n"), err)
2817 " (specify a username in your configuration file)\n"), err)
2818
2818
2819 fm.condwrite(not problems, '',
2819 fm.condwrite(not problems, '',
2820 _("no problems detected\n"))
2820 _("no problems detected\n"))
2821 if not problems:
2821 if not problems:
2822 fm.data(problems=problems)
2822 fm.data(problems=problems)
2823 fm.condwrite(problems, 'problems',
2823 fm.condwrite(problems, 'problems',
2824 _("%s problems detected,"
2824 _("%s problems detected,"
2825 " please check your install!\n"), problems)
2825 " please check your install!\n"), problems)
2826 fm.end()
2826 fm.end()
2827
2827
2828 return problems
2828 return problems
2829
2829
2830 @command('debugknown', [], _('REPO ID...'), norepo=True)
2830 @command('debugknown', [], _('REPO ID...'), norepo=True)
2831 def debugknown(ui, repopath, *ids, **opts):
2831 def debugknown(ui, repopath, *ids, **opts):
2832 """test whether node ids are known to a repo
2832 """test whether node ids are known to a repo
2833
2833
2834 Every ID must be a full-length hex node id string. Returns a list of 0s
2834 Every ID must be a full-length hex node id string. Returns a list of 0s
2835 and 1s indicating unknown/known.
2835 and 1s indicating unknown/known.
2836 """
2836 """
2837 repo = hg.peer(ui, opts, repopath)
2837 repo = hg.peer(ui, opts, repopath)
2838 if not repo.capable('known'):
2838 if not repo.capable('known'):
2839 raise error.Abort("known() not supported by target repository")
2839 raise error.Abort("known() not supported by target repository")
2840 flags = repo.known([bin(s) for s in ids])
2840 flags = repo.known([bin(s) for s in ids])
2841 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2841 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2842
2842
2843 @command('debuglabelcomplete', [], _('LABEL...'))
2843 @command('debuglabelcomplete', [], _('LABEL...'))
2844 def debuglabelcomplete(ui, repo, *args):
2844 def debuglabelcomplete(ui, repo, *args):
2845 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2845 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2846 debugnamecomplete(ui, repo, *args)
2846 debugnamecomplete(ui, repo, *args)
2847
2847
2848 @command('debugmergestate', [], '')
2848 @command('debugmergestate', [], '')
2849 def debugmergestate(ui, repo, *args):
2849 def debugmergestate(ui, repo, *args):
2850 """print merge state
2850 """print merge state
2851
2851
2852 Use --verbose to print out information about whether v1 or v2 merge state
2852 Use --verbose to print out information about whether v1 or v2 merge state
2853 was chosen."""
2853 was chosen."""
2854 def _hashornull(h):
2854 def _hashornull(h):
2855 if h == nullhex:
2855 if h == nullhex:
2856 return 'null'
2856 return 'null'
2857 else:
2857 else:
2858 return h
2858 return h
2859
2859
2860 def printrecords(version):
2860 def printrecords(version):
2861 ui.write(('* version %s records\n') % version)
2861 ui.write(('* version %s records\n') % version)
2862 if version == 1:
2862 if version == 1:
2863 records = v1records
2863 records = v1records
2864 else:
2864 else:
2865 records = v2records
2865 records = v2records
2866
2866
2867 for rtype, record in records:
2867 for rtype, record in records:
2868 # pretty print some record types
2868 # pretty print some record types
2869 if rtype == 'L':
2869 if rtype == 'L':
2870 ui.write(('local: %s\n') % record)
2870 ui.write(('local: %s\n') % record)
2871 elif rtype == 'O':
2871 elif rtype == 'O':
2872 ui.write(('other: %s\n') % record)
2872 ui.write(('other: %s\n') % record)
2873 elif rtype == 'm':
2873 elif rtype == 'm':
2874 driver, mdstate = record.split('\0', 1)
2874 driver, mdstate = record.split('\0', 1)
2875 ui.write(('merge driver: %s (state "%s")\n')
2875 ui.write(('merge driver: %s (state "%s")\n')
2876 % (driver, mdstate))
2876 % (driver, mdstate))
2877 elif rtype in 'FDC':
2877 elif rtype in 'FDC':
2878 r = record.split('\0')
2878 r = record.split('\0')
2879 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2879 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2880 if version == 1:
2880 if version == 1:
2881 onode = 'not stored in v1 format'
2881 onode = 'not stored in v1 format'
2882 flags = r[7]
2882 flags = r[7]
2883 else:
2883 else:
2884 onode, flags = r[7:9]
2884 onode, flags = r[7:9]
2885 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2885 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2886 % (f, rtype, state, _hashornull(hash)))
2886 % (f, rtype, state, _hashornull(hash)))
2887 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2887 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2888 ui.write((' ancestor path: %s (node %s)\n')
2888 ui.write((' ancestor path: %s (node %s)\n')
2889 % (afile, _hashornull(anode)))
2889 % (afile, _hashornull(anode)))
2890 ui.write((' other path: %s (node %s)\n')
2890 ui.write((' other path: %s (node %s)\n')
2891 % (ofile, _hashornull(onode)))
2891 % (ofile, _hashornull(onode)))
2892 elif rtype == 'f':
2892 elif rtype == 'f':
2893 filename, rawextras = record.split('\0', 1)
2893 filename, rawextras = record.split('\0', 1)
2894 extras = rawextras.split('\0')
2894 extras = rawextras.split('\0')
2895 i = 0
2895 i = 0
2896 extrastrings = []
2896 extrastrings = []
2897 while i < len(extras):
2897 while i < len(extras):
2898 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2898 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2899 i += 2
2899 i += 2
2900
2900
2901 ui.write(('file extras: %s (%s)\n')
2901 ui.write(('file extras: %s (%s)\n')
2902 % (filename, ', '.join(extrastrings)))
2902 % (filename, ', '.join(extrastrings)))
2903 elif rtype == 'l':
2903 elif rtype == 'l':
2904 labels = record.split('\0', 2)
2904 labels = record.split('\0', 2)
2905 labels = [l for l in labels if len(l) > 0]
2905 labels = [l for l in labels if len(l) > 0]
2906 ui.write(('labels:\n'))
2906 ui.write(('labels:\n'))
2907 ui.write((' local: %s\n' % labels[0]))
2907 ui.write((' local: %s\n' % labels[0]))
2908 ui.write((' other: %s\n' % labels[1]))
2908 ui.write((' other: %s\n' % labels[1]))
2909 if len(labels) > 2:
2909 if len(labels) > 2:
2910 ui.write((' base: %s\n' % labels[2]))
2910 ui.write((' base: %s\n' % labels[2]))
2911 else:
2911 else:
2912 ui.write(('unrecognized entry: %s\t%s\n')
2912 ui.write(('unrecognized entry: %s\t%s\n')
2913 % (rtype, record.replace('\0', '\t')))
2913 % (rtype, record.replace('\0', '\t')))
2914
2914
2915 # Avoid mergestate.read() since it may raise an exception for unsupported
2915 # Avoid mergestate.read() since it may raise an exception for unsupported
2916 # merge state records. We shouldn't be doing this, but this is OK since this
2916 # merge state records. We shouldn't be doing this, but this is OK since this
2917 # command is pretty low-level.
2917 # command is pretty low-level.
2918 ms = mergemod.mergestate(repo)
2918 ms = mergemod.mergestate(repo)
2919
2919
2920 # sort so that reasonable information is on top
2920 # sort so that reasonable information is on top
2921 v1records = ms._readrecordsv1()
2921 v1records = ms._readrecordsv1()
2922 v2records = ms._readrecordsv2()
2922 v2records = ms._readrecordsv2()
2923 order = 'LOml'
2923 order = 'LOml'
2924 def key(r):
2924 def key(r):
2925 idx = order.find(r[0])
2925 idx = order.find(r[0])
2926 if idx == -1:
2926 if idx == -1:
2927 return (1, r[1])
2927 return (1, r[1])
2928 else:
2928 else:
2929 return (0, idx)
2929 return (0, idx)
2930 v1records.sort(key=key)
2930 v1records.sort(key=key)
2931 v2records.sort(key=key)
2931 v2records.sort(key=key)
2932
2932
2933 if not v1records and not v2records:
2933 if not v1records and not v2records:
2934 ui.write(('no merge state found\n'))
2934 ui.write(('no merge state found\n'))
2935 elif not v2records:
2935 elif not v2records:
2936 ui.note(('no version 2 merge state\n'))
2936 ui.note(('no version 2 merge state\n'))
2937 printrecords(1)
2937 printrecords(1)
2938 elif ms._v1v2match(v1records, v2records):
2938 elif ms._v1v2match(v1records, v2records):
2939 ui.note(('v1 and v2 states match: using v2\n'))
2939 ui.note(('v1 and v2 states match: using v2\n'))
2940 printrecords(2)
2940 printrecords(2)
2941 else:
2941 else:
2942 ui.note(('v1 and v2 states mismatch: using v1\n'))
2942 ui.note(('v1 and v2 states mismatch: using v1\n'))
2943 printrecords(1)
2943 printrecords(1)
2944 if ui.verbose:
2944 if ui.verbose:
2945 printrecords(2)
2945 printrecords(2)
2946
2946
2947 @command('debugnamecomplete', [], _('NAME...'))
2947 @command('debugnamecomplete', [], _('NAME...'))
2948 def debugnamecomplete(ui, repo, *args):
2948 def debugnamecomplete(ui, repo, *args):
2949 '''complete "names" - tags, open branch names, bookmark names'''
2949 '''complete "names" - tags, open branch names, bookmark names'''
2950
2950
2951 names = set()
2951 names = set()
2952 # since we previously only listed open branches, we will handle that
2952 # since we previously only listed open branches, we will handle that
2953 # specially (after this for loop)
2953 # specially (after this for loop)
2954 for name, ns in repo.names.iteritems():
2954 for name, ns in repo.names.iteritems():
2955 if name != 'branches':
2955 if name != 'branches':
2956 names.update(ns.listnames(repo))
2956 names.update(ns.listnames(repo))
2957 names.update(tag for (tag, heads, tip, closed)
2957 names.update(tag for (tag, heads, tip, closed)
2958 in repo.branchmap().iterbranches() if not closed)
2958 in repo.branchmap().iterbranches() if not closed)
2959 completions = set()
2959 completions = set()
2960 if not args:
2960 if not args:
2961 args = ['']
2961 args = ['']
2962 for a in args:
2962 for a in args:
2963 completions.update(n for n in names if n.startswith(a))
2963 completions.update(n for n in names if n.startswith(a))
2964 ui.write('\n'.join(sorted(completions)))
2964 ui.write('\n'.join(sorted(completions)))
2965 ui.write('\n')
2965 ui.write('\n')
2966
2966
2967 @command('debuglocks',
2967 @command('debuglocks',
2968 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2968 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2969 ('W', 'force-wlock', None,
2969 ('W', 'force-wlock', None,
2970 _('free the working state lock (DANGEROUS)'))],
2970 _('free the working state lock (DANGEROUS)'))],
2971 _('[OPTION]...'))
2971 _('[OPTION]...'))
2972 def debuglocks(ui, repo, **opts):
2972 def debuglocks(ui, repo, **opts):
2973 """show or modify state of locks
2973 """show or modify state of locks
2974
2974
2975 By default, this command will show which locks are held. This
2975 By default, this command will show which locks are held. This
2976 includes the user and process holding the lock, the amount of time
2976 includes the user and process holding the lock, the amount of time
2977 the lock has been held, and the machine name where the process is
2977 the lock has been held, and the machine name where the process is
2978 running if it's not local.
2978 running if it's not local.
2979
2979
2980 Locks protect the integrity of Mercurial's data, so should be
2980 Locks protect the integrity of Mercurial's data, so should be
2981 treated with care. System crashes or other interruptions may cause
2981 treated with care. System crashes or other interruptions may cause
2982 locks to not be properly released, though Mercurial will usually
2982 locks to not be properly released, though Mercurial will usually
2983 detect and remove such stale locks automatically.
2983 detect and remove such stale locks automatically.
2984
2984
2985 However, detecting stale locks may not always be possible (for
2985 However, detecting stale locks may not always be possible (for
2986 instance, on a shared filesystem). Removing locks may also be
2986 instance, on a shared filesystem). Removing locks may also be
2987 blocked by filesystem permissions.
2987 blocked by filesystem permissions.
2988
2988
2989 Returns 0 if no locks are held.
2989 Returns 0 if no locks are held.
2990
2990
2991 """
2991 """
2992
2992
2993 if opts.get('force_lock'):
2993 if opts.get('force_lock'):
2994 repo.svfs.unlink('lock')
2994 repo.svfs.unlink('lock')
2995 if opts.get('force_wlock'):
2995 if opts.get('force_wlock'):
2996 repo.vfs.unlink('wlock')
2996 repo.vfs.unlink('wlock')
2997 if opts.get('force_lock') or opts.get('force_lock'):
2997 if opts.get('force_lock') or opts.get('force_lock'):
2998 return 0
2998 return 0
2999
2999
3000 now = time.time()
3000 now = time.time()
3001 held = 0
3001 held = 0
3002
3002
3003 def report(vfs, name, method):
3003 def report(vfs, name, method):
3004 # this causes stale locks to get reaped for more accurate reporting
3004 # this causes stale locks to get reaped for more accurate reporting
3005 try:
3005 try:
3006 l = method(False)
3006 l = method(False)
3007 except error.LockHeld:
3007 except error.LockHeld:
3008 l = None
3008 l = None
3009
3009
3010 if l:
3010 if l:
3011 l.release()
3011 l.release()
3012 else:
3012 else:
3013 try:
3013 try:
3014 stat = vfs.lstat(name)
3014 stat = vfs.lstat(name)
3015 age = now - stat.st_mtime
3015 age = now - stat.st_mtime
3016 user = util.username(stat.st_uid)
3016 user = util.username(stat.st_uid)
3017 locker = vfs.readlock(name)
3017 locker = vfs.readlock(name)
3018 if ":" in locker:
3018 if ":" in locker:
3019 host, pid = locker.split(':')
3019 host, pid = locker.split(':')
3020 if host == socket.gethostname():
3020 if host == socket.gethostname():
3021 locker = 'user %s, process %s' % (user, pid)
3021 locker = 'user %s, process %s' % (user, pid)
3022 else:
3022 else:
3023 locker = 'user %s, process %s, host %s' \
3023 locker = 'user %s, process %s, host %s' \
3024 % (user, pid, host)
3024 % (user, pid, host)
3025 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
3025 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
3026 return 1
3026 return 1
3027 except OSError as e:
3027 except OSError as e:
3028 if e.errno != errno.ENOENT:
3028 if e.errno != errno.ENOENT:
3029 raise
3029 raise
3030
3030
3031 ui.write(("%-6s free\n") % (name + ":"))
3031 ui.write(("%-6s free\n") % (name + ":"))
3032 return 0
3032 return 0
3033
3033
3034 held += report(repo.svfs, "lock", repo.lock)
3034 held += report(repo.svfs, "lock", repo.lock)
3035 held += report(repo.vfs, "wlock", repo.wlock)
3035 held += report(repo.vfs, "wlock", repo.wlock)
3036
3036
3037 return held
3037 return held
3038
3038
3039 @command('debugobsolete',
3039 @command('debugobsolete',
3040 [('', 'flags', 0, _('markers flag')),
3040 [('', 'flags', 0, _('markers flag')),
3041 ('', 'record-parents', False,
3041 ('', 'record-parents', False,
3042 _('record parent information for the precursor')),
3042 _('record parent information for the precursor')),
3043 ('r', 'rev', [], _('display markers relevant to REV')),
3043 ('r', 'rev', [], _('display markers relevant to REV')),
3044 ('', 'index', False, _('display index of the marker')),
3044 ('', 'index', False, _('display index of the marker')),
3045 ('', 'delete', [], _('delete markers specified by indices')),
3045 ('', 'delete', [], _('delete markers specified by indices')),
3046 ] + commitopts2,
3046 ] + commitopts2,
3047 _('[OBSOLETED [REPLACEMENT ...]]'))
3047 _('[OBSOLETED [REPLACEMENT ...]]'))
3048 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3048 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3049 """create arbitrary obsolete marker
3049 """create arbitrary obsolete marker
3050
3050
3051 With no arguments, displays the list of obsolescence markers."""
3051 With no arguments, displays the list of obsolescence markers."""
3052
3052
3053 def parsenodeid(s):
3053 def parsenodeid(s):
3054 try:
3054 try:
3055 # We do not use revsingle/revrange functions here to accept
3055 # We do not use revsingle/revrange functions here to accept
3056 # arbitrary node identifiers, possibly not present in the
3056 # arbitrary node identifiers, possibly not present in the
3057 # local repository.
3057 # local repository.
3058 n = bin(s)
3058 n = bin(s)
3059 if len(n) != len(nullid):
3059 if len(n) != len(nullid):
3060 raise TypeError()
3060 raise TypeError()
3061 return n
3061 return n
3062 except TypeError:
3062 except TypeError:
3063 raise error.Abort('changeset references must be full hexadecimal '
3063 raise error.Abort('changeset references must be full hexadecimal '
3064 'node identifiers')
3064 'node identifiers')
3065
3065
3066 if opts.get('delete'):
3066 if opts.get('delete'):
3067 indices = []
3067 indices = []
3068 for v in opts.get('delete'):
3068 for v in opts.get('delete'):
3069 try:
3069 try:
3070 indices.append(int(v))
3070 indices.append(int(v))
3071 except ValueError:
3071 except ValueError:
3072 raise error.Abort(_('invalid index value: %r') % v,
3072 raise error.Abort(_('invalid index value: %r') % v,
3073 hint=_('use integers for indices'))
3073 hint=_('use integers for indices'))
3074
3074
3075 if repo.currenttransaction():
3075 if repo.currenttransaction():
3076 raise error.Abort(_('cannot delete obsmarkers in the middle '
3076 raise error.Abort(_('cannot delete obsmarkers in the middle '
3077 'of transaction.'))
3077 'of transaction.'))
3078
3078
3079 with repo.lock():
3079 with repo.lock():
3080 n = repair.deleteobsmarkers(repo.obsstore, indices)
3080 n = repair.deleteobsmarkers(repo.obsstore, indices)
3081 ui.write(_('deleted %i obsolescense markers\n') % n)
3081 ui.write(_('deleted %i obsolescense markers\n') % n)
3082
3082
3083 return
3083 return
3084
3084
3085 if precursor is not None:
3085 if precursor is not None:
3086 if opts['rev']:
3086 if opts['rev']:
3087 raise error.Abort('cannot select revision when creating marker')
3087 raise error.Abort('cannot select revision when creating marker')
3088 metadata = {}
3088 metadata = {}
3089 metadata['user'] = opts['user'] or ui.username()
3089 metadata['user'] = opts['user'] or ui.username()
3090 succs = tuple(parsenodeid(succ) for succ in successors)
3090 succs = tuple(parsenodeid(succ) for succ in successors)
3091 l = repo.lock()
3091 l = repo.lock()
3092 try:
3092 try:
3093 tr = repo.transaction('debugobsolete')
3093 tr = repo.transaction('debugobsolete')
3094 try:
3094 try:
3095 date = opts.get('date')
3095 date = opts.get('date')
3096 if date:
3096 if date:
3097 date = util.parsedate(date)
3097 date = util.parsedate(date)
3098 else:
3098 else:
3099 date = None
3099 date = None
3100 prec = parsenodeid(precursor)
3100 prec = parsenodeid(precursor)
3101 parents = None
3101 parents = None
3102 if opts['record_parents']:
3102 if opts['record_parents']:
3103 if prec not in repo.unfiltered():
3103 if prec not in repo.unfiltered():
3104 raise error.Abort('cannot used --record-parents on '
3104 raise error.Abort('cannot used --record-parents on '
3105 'unknown changesets')
3105 'unknown changesets')
3106 parents = repo.unfiltered()[prec].parents()
3106 parents = repo.unfiltered()[prec].parents()
3107 parents = tuple(p.node() for p in parents)
3107 parents = tuple(p.node() for p in parents)
3108 repo.obsstore.create(tr, prec, succs, opts['flags'],
3108 repo.obsstore.create(tr, prec, succs, opts['flags'],
3109 parents=parents, date=date,
3109 parents=parents, date=date,
3110 metadata=metadata)
3110 metadata=metadata)
3111 tr.close()
3111 tr.close()
3112 except ValueError as exc:
3112 except ValueError as exc:
3113 raise error.Abort(_('bad obsmarker input: %s') % exc)
3113 raise error.Abort(_('bad obsmarker input: %s') % exc)
3114 finally:
3114 finally:
3115 tr.release()
3115 tr.release()
3116 finally:
3116 finally:
3117 l.release()
3117 l.release()
3118 else:
3118 else:
3119 if opts['rev']:
3119 if opts['rev']:
3120 revs = scmutil.revrange(repo, opts['rev'])
3120 revs = scmutil.revrange(repo, opts['rev'])
3121 nodes = [repo[r].node() for r in revs]
3121 nodes = [repo[r].node() for r in revs]
3122 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3122 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3123 markers.sort(key=lambda x: x._data)
3123 markers.sort(key=lambda x: x._data)
3124 else:
3124 else:
3125 markers = obsolete.getmarkers(repo)
3125 markers = obsolete.getmarkers(repo)
3126
3126
3127 markerstoiter = markers
3127 markerstoiter = markers
3128 isrelevant = lambda m: True
3128 isrelevant = lambda m: True
3129 if opts.get('rev') and opts.get('index'):
3129 if opts.get('rev') and opts.get('index'):
3130 markerstoiter = obsolete.getmarkers(repo)
3130 markerstoiter = obsolete.getmarkers(repo)
3131 markerset = set(markers)
3131 markerset = set(markers)
3132 isrelevant = lambda m: m in markerset
3132 isrelevant = lambda m: m in markerset
3133
3133
3134 for i, m in enumerate(markerstoiter):
3134 for i, m in enumerate(markerstoiter):
3135 if not isrelevant(m):
3135 if not isrelevant(m):
3136 # marker can be irrelevant when we're iterating over a set
3136 # marker can be irrelevant when we're iterating over a set
3137 # of markers (markerstoiter) which is bigger than the set
3137 # of markers (markerstoiter) which is bigger than the set
3138 # of markers we want to display (markers)
3138 # of markers we want to display (markers)
3139 # this can happen if both --index and --rev options are
3139 # this can happen if both --index and --rev options are
3140 # provided and thus we need to iterate over all of the markers
3140 # provided and thus we need to iterate over all of the markers
3141 # to get the correct indices, but only display the ones that
3141 # to get the correct indices, but only display the ones that
3142 # are relevant to --rev value
3142 # are relevant to --rev value
3143 continue
3143 continue
3144 ind = i if opts.get('index') else None
3144 ind = i if opts.get('index') else None
3145 cmdutil.showmarker(ui, m, index=ind)
3145 cmdutil.showmarker(ui, m, index=ind)
3146
3146
3147 @command('debugpathcomplete',
3147 @command('debugpathcomplete',
3148 [('f', 'full', None, _('complete an entire path')),
3148 [('f', 'full', None, _('complete an entire path')),
3149 ('n', 'normal', None, _('show only normal files')),
3149 ('n', 'normal', None, _('show only normal files')),
3150 ('a', 'added', None, _('show only added files')),
3150 ('a', 'added', None, _('show only added files')),
3151 ('r', 'removed', None, _('show only removed files'))],
3151 ('r', 'removed', None, _('show only removed files'))],
3152 _('FILESPEC...'))
3152 _('FILESPEC...'))
3153 def debugpathcomplete(ui, repo, *specs, **opts):
3153 def debugpathcomplete(ui, repo, *specs, **opts):
3154 '''complete part or all of a tracked path
3154 '''complete part or all of a tracked path
3155
3155
3156 This command supports shells that offer path name completion. It
3156 This command supports shells that offer path name completion. It
3157 currently completes only files already known to the dirstate.
3157 currently completes only files already known to the dirstate.
3158
3158
3159 Completion extends only to the next path segment unless
3159 Completion extends only to the next path segment unless
3160 --full is specified, in which case entire paths are used.'''
3160 --full is specified, in which case entire paths are used.'''
3161
3161
3162 def complete(path, acceptable):
3162 def complete(path, acceptable):
3163 dirstate = repo.dirstate
3163 dirstate = repo.dirstate
3164 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3164 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3165 rootdir = repo.root + os.sep
3165 rootdir = repo.root + os.sep
3166 if spec != repo.root and not spec.startswith(rootdir):
3166 if spec != repo.root and not spec.startswith(rootdir):
3167 return [], []
3167 return [], []
3168 if os.path.isdir(spec):
3168 if os.path.isdir(spec):
3169 spec += '/'
3169 spec += '/'
3170 spec = spec[len(rootdir):]
3170 spec = spec[len(rootdir):]
3171 fixpaths = os.sep != '/'
3171 fixpaths = os.sep != '/'
3172 if fixpaths:
3172 if fixpaths:
3173 spec = spec.replace(os.sep, '/')
3173 spec = spec.replace(os.sep, '/')
3174 speclen = len(spec)
3174 speclen = len(spec)
3175 fullpaths = opts['full']
3175 fullpaths = opts['full']
3176 files, dirs = set(), set()
3176 files, dirs = set(), set()
3177 adddir, addfile = dirs.add, files.add
3177 adddir, addfile = dirs.add, files.add
3178 for f, st in dirstate.iteritems():
3178 for f, st in dirstate.iteritems():
3179 if f.startswith(spec) and st[0] in acceptable:
3179 if f.startswith(spec) and st[0] in acceptable:
3180 if fixpaths:
3180 if fixpaths:
3181 f = f.replace('/', os.sep)
3181 f = f.replace('/', os.sep)
3182 if fullpaths:
3182 if fullpaths:
3183 addfile(f)
3183 addfile(f)
3184 continue
3184 continue
3185 s = f.find(os.sep, speclen)
3185 s = f.find(os.sep, speclen)
3186 if s >= 0:
3186 if s >= 0:
3187 adddir(f[:s])
3187 adddir(f[:s])
3188 else:
3188 else:
3189 addfile(f)
3189 addfile(f)
3190 return files, dirs
3190 return files, dirs
3191
3191
3192 acceptable = ''
3192 acceptable = ''
3193 if opts['normal']:
3193 if opts['normal']:
3194 acceptable += 'nm'
3194 acceptable += 'nm'
3195 if opts['added']:
3195 if opts['added']:
3196 acceptable += 'a'
3196 acceptable += 'a'
3197 if opts['removed']:
3197 if opts['removed']:
3198 acceptable += 'r'
3198 acceptable += 'r'
3199 cwd = repo.getcwd()
3199 cwd = repo.getcwd()
3200 if not specs:
3200 if not specs:
3201 specs = ['.']
3201 specs = ['.']
3202
3202
3203 files, dirs = set(), set()
3203 files, dirs = set(), set()
3204 for spec in specs:
3204 for spec in specs:
3205 f, d = complete(spec, acceptable or 'nmar')
3205 f, d = complete(spec, acceptable or 'nmar')
3206 files.update(f)
3206 files.update(f)
3207 dirs.update(d)
3207 dirs.update(d)
3208 files.update(dirs)
3208 files.update(dirs)
3209 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3209 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3210 ui.write('\n')
3210 ui.write('\n')
3211
3211
3212 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3212 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3213 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3213 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3214 '''access the pushkey key/value protocol
3214 '''access the pushkey key/value protocol
3215
3215
3216 With two args, list the keys in the given namespace.
3216 With two args, list the keys in the given namespace.
3217
3217
3218 With five args, set a key to new if it currently is set to old.
3218 With five args, set a key to new if it currently is set to old.
3219 Reports success or failure.
3219 Reports success or failure.
3220 '''
3220 '''
3221
3221
3222 target = hg.peer(ui, {}, repopath)
3222 target = hg.peer(ui, {}, repopath)
3223 if keyinfo:
3223 if keyinfo:
3224 key, old, new = keyinfo
3224 key, old, new = keyinfo
3225 r = target.pushkey(namespace, key, old, new)
3225 r = target.pushkey(namespace, key, old, new)
3226 ui.status(str(r) + '\n')
3226 ui.status(str(r) + '\n')
3227 return not r
3227 return not r
3228 else:
3228 else:
3229 for k, v in sorted(target.listkeys(namespace).iteritems()):
3229 for k, v in sorted(target.listkeys(namespace).iteritems()):
3230 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3230 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3231 v.encode('string-escape')))
3231 v.encode('string-escape')))
3232
3232
3233 @command('debugpvec', [], _('A B'))
3233 @command('debugpvec', [], _('A B'))
3234 def debugpvec(ui, repo, a, b=None):
3234 def debugpvec(ui, repo, a, b=None):
3235 ca = scmutil.revsingle(repo, a)
3235 ca = scmutil.revsingle(repo, a)
3236 cb = scmutil.revsingle(repo, b)
3236 cb = scmutil.revsingle(repo, b)
3237 pa = pvec.ctxpvec(ca)
3237 pa = pvec.ctxpvec(ca)
3238 pb = pvec.ctxpvec(cb)
3238 pb = pvec.ctxpvec(cb)
3239 if pa == pb:
3239 if pa == pb:
3240 rel = "="
3240 rel = "="
3241 elif pa > pb:
3241 elif pa > pb:
3242 rel = ">"
3242 rel = ">"
3243 elif pa < pb:
3243 elif pa < pb:
3244 rel = "<"
3244 rel = "<"
3245 elif pa | pb:
3245 elif pa | pb:
3246 rel = "|"
3246 rel = "|"
3247 ui.write(_("a: %s\n") % pa)
3247 ui.write(_("a: %s\n") % pa)
3248 ui.write(_("b: %s\n") % pb)
3248 ui.write(_("b: %s\n") % pb)
3249 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3249 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3250 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3250 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3251 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3251 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3252 pa.distance(pb), rel))
3252 pa.distance(pb), rel))
3253
3253
3254 @command('debugrebuilddirstate|debugrebuildstate',
3254 @command('debugrebuilddirstate|debugrebuildstate',
3255 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3255 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3256 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3256 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3257 'the working copy parent')),
3257 'the working copy parent')),
3258 ],
3258 ],
3259 _('[-r REV]'))
3259 _('[-r REV]'))
3260 def debugrebuilddirstate(ui, repo, rev, **opts):
3260 def debugrebuilddirstate(ui, repo, rev, **opts):
3261 """rebuild the dirstate as it would look like for the given revision
3261 """rebuild the dirstate as it would look like for the given revision
3262
3262
3263 If no revision is specified the first current parent will be used.
3263 If no revision is specified the first current parent will be used.
3264
3264
3265 The dirstate will be set to the files of the given revision.
3265 The dirstate will be set to the files of the given revision.
3266 The actual working directory content or existing dirstate
3266 The actual working directory content or existing dirstate
3267 information such as adds or removes is not considered.
3267 information such as adds or removes is not considered.
3268
3268
3269 ``minimal`` will only rebuild the dirstate status for files that claim to be
3269 ``minimal`` will only rebuild the dirstate status for files that claim to be
3270 tracked but are not in the parent manifest, or that exist in the parent
3270 tracked but are not in the parent manifest, or that exist in the parent
3271 manifest but are not in the dirstate. It will not change adds, removes, or
3271 manifest but are not in the dirstate. It will not change adds, removes, or
3272 modified files that are in the working copy parent.
3272 modified files that are in the working copy parent.
3273
3273
3274 One use of this command is to make the next :hg:`status` invocation
3274 One use of this command is to make the next :hg:`status` invocation
3275 check the actual file content.
3275 check the actual file content.
3276 """
3276 """
3277 ctx = scmutil.revsingle(repo, rev)
3277 ctx = scmutil.revsingle(repo, rev)
3278 with repo.wlock():
3278 with repo.wlock():
3279 dirstate = repo.dirstate
3279 dirstate = repo.dirstate
3280 changedfiles = None
3280 changedfiles = None
3281 # See command doc for what minimal does.
3281 # See command doc for what minimal does.
3282 if opts.get('minimal'):
3282 if opts.get('minimal'):
3283 manifestfiles = set(ctx.manifest().keys())
3283 manifestfiles = set(ctx.manifest().keys())
3284 dirstatefiles = set(dirstate)
3284 dirstatefiles = set(dirstate)
3285 manifestonly = manifestfiles - dirstatefiles
3285 manifestonly = manifestfiles - dirstatefiles
3286 dsonly = dirstatefiles - manifestfiles
3286 dsonly = dirstatefiles - manifestfiles
3287 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3287 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3288 changedfiles = manifestonly | dsnotadded
3288 changedfiles = manifestonly | dsnotadded
3289
3289
3290 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3290 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3291
3291
3292 @command('debugrebuildfncache', [], '')
3292 @command('debugrebuildfncache', [], '')
3293 def debugrebuildfncache(ui, repo):
3293 def debugrebuildfncache(ui, repo):
3294 """rebuild the fncache file"""
3294 """rebuild the fncache file"""
3295 repair.rebuildfncache(ui, repo)
3295 repair.rebuildfncache(ui, repo)
3296
3296
3297 @command('debugrename',
3297 @command('debugrename',
3298 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3298 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3299 _('[-r REV] FILE'))
3299 _('[-r REV] FILE'))
3300 def debugrename(ui, repo, file1, *pats, **opts):
3300 def debugrename(ui, repo, file1, *pats, **opts):
3301 """dump rename information"""
3301 """dump rename information"""
3302
3302
3303 ctx = scmutil.revsingle(repo, opts.get('rev'))
3303 ctx = scmutil.revsingle(repo, opts.get('rev'))
3304 m = scmutil.match(ctx, (file1,) + pats, opts)
3304 m = scmutil.match(ctx, (file1,) + pats, opts)
3305 for abs in ctx.walk(m):
3305 for abs in ctx.walk(m):
3306 fctx = ctx[abs]
3306 fctx = ctx[abs]
3307 o = fctx.filelog().renamed(fctx.filenode())
3307 o = fctx.filelog().renamed(fctx.filenode())
3308 rel = m.rel(abs)
3308 rel = m.rel(abs)
3309 if o:
3309 if o:
3310 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3310 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3311 else:
3311 else:
3312 ui.write(_("%s not renamed\n") % rel)
3312 ui.write(_("%s not renamed\n") % rel)
3313
3313
3314 @command('debugrevlog', debugrevlogopts +
3314 @command('debugrevlog', debugrevlogopts +
3315 [('d', 'dump', False, _('dump index data'))],
3315 [('d', 'dump', False, _('dump index data'))],
3316 _('-c|-m|FILE'),
3316 _('-c|-m|FILE'),
3317 optionalrepo=True)
3317 optionalrepo=True)
3318 def debugrevlog(ui, repo, file_=None, **opts):
3318 def debugrevlog(ui, repo, file_=None, **opts):
3319 """show data and statistics about a revlog"""
3319 """show data and statistics about a revlog"""
3320 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3320 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3321
3321
3322 if opts.get("dump"):
3322 if opts.get("dump"):
3323 numrevs = len(r)
3323 numrevs = len(r)
3324 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3324 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3325 " rawsize totalsize compression heads chainlen\n"))
3325 " rawsize totalsize compression heads chainlen\n"))
3326 ts = 0
3326 ts = 0
3327 heads = set()
3327 heads = set()
3328
3328
3329 for rev in xrange(numrevs):
3329 for rev in xrange(numrevs):
3330 dbase = r.deltaparent(rev)
3330 dbase = r.deltaparent(rev)
3331 if dbase == -1:
3331 if dbase == -1:
3332 dbase = rev
3332 dbase = rev
3333 cbase = r.chainbase(rev)
3333 cbase = r.chainbase(rev)
3334 clen = r.chainlen(rev)
3334 clen = r.chainlen(rev)
3335 p1, p2 = r.parentrevs(rev)
3335 p1, p2 = r.parentrevs(rev)
3336 rs = r.rawsize(rev)
3336 rs = r.rawsize(rev)
3337 ts = ts + rs
3337 ts = ts + rs
3338 heads -= set(r.parentrevs(rev))
3338 heads -= set(r.parentrevs(rev))
3339 heads.add(rev)
3339 heads.add(rev)
3340 try:
3340 try:
3341 compression = ts / r.end(rev)
3341 compression = ts / r.end(rev)
3342 except ZeroDivisionError:
3342 except ZeroDivisionError:
3343 compression = 0
3343 compression = 0
3344 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3344 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3345 "%11d %5d %8d\n" %
3345 "%11d %5d %8d\n" %
3346 (rev, p1, p2, r.start(rev), r.end(rev),
3346 (rev, p1, p2, r.start(rev), r.end(rev),
3347 r.start(dbase), r.start(cbase),
3347 r.start(dbase), r.start(cbase),
3348 r.start(p1), r.start(p2),
3348 r.start(p1), r.start(p2),
3349 rs, ts, compression, len(heads), clen))
3349 rs, ts, compression, len(heads), clen))
3350 return 0
3350 return 0
3351
3351
3352 v = r.version
3352 v = r.version
3353 format = v & 0xFFFF
3353 format = v & 0xFFFF
3354 flags = []
3354 flags = []
3355 gdelta = False
3355 gdelta = False
3356 if v & revlog.REVLOGNGINLINEDATA:
3356 if v & revlog.REVLOGNGINLINEDATA:
3357 flags.append('inline')
3357 flags.append('inline')
3358 if v & revlog.REVLOGGENERALDELTA:
3358 if v & revlog.REVLOGGENERALDELTA:
3359 gdelta = True
3359 gdelta = True
3360 flags.append('generaldelta')
3360 flags.append('generaldelta')
3361 if not flags:
3361 if not flags:
3362 flags = ['(none)']
3362 flags = ['(none)']
3363
3363
3364 nummerges = 0
3364 nummerges = 0
3365 numfull = 0
3365 numfull = 0
3366 numprev = 0
3366 numprev = 0
3367 nump1 = 0
3367 nump1 = 0
3368 nump2 = 0
3368 nump2 = 0
3369 numother = 0
3369 numother = 0
3370 nump1prev = 0
3370 nump1prev = 0
3371 nump2prev = 0
3371 nump2prev = 0
3372 chainlengths = []
3372 chainlengths = []
3373
3373
3374 datasize = [None, 0, 0L]
3374 datasize = [None, 0, 0L]
3375 fullsize = [None, 0, 0L]
3375 fullsize = [None, 0, 0L]
3376 deltasize = [None, 0, 0L]
3376 deltasize = [None, 0, 0L]
3377
3377
3378 def addsize(size, l):
3378 def addsize(size, l):
3379 if l[0] is None or size < l[0]:
3379 if l[0] is None or size < l[0]:
3380 l[0] = size
3380 l[0] = size
3381 if size > l[1]:
3381 if size > l[1]:
3382 l[1] = size
3382 l[1] = size
3383 l[2] += size
3383 l[2] += size
3384
3384
3385 numrevs = len(r)
3385 numrevs = len(r)
3386 for rev in xrange(numrevs):
3386 for rev in xrange(numrevs):
3387 p1, p2 = r.parentrevs(rev)
3387 p1, p2 = r.parentrevs(rev)
3388 delta = r.deltaparent(rev)
3388 delta = r.deltaparent(rev)
3389 if format > 0:
3389 if format > 0:
3390 addsize(r.rawsize(rev), datasize)
3390 addsize(r.rawsize(rev), datasize)
3391 if p2 != nullrev:
3391 if p2 != nullrev:
3392 nummerges += 1
3392 nummerges += 1
3393 size = r.length(rev)
3393 size = r.length(rev)
3394 if delta == nullrev:
3394 if delta == nullrev:
3395 chainlengths.append(0)
3395 chainlengths.append(0)
3396 numfull += 1
3396 numfull += 1
3397 addsize(size, fullsize)
3397 addsize(size, fullsize)
3398 else:
3398 else:
3399 chainlengths.append(chainlengths[delta] + 1)
3399 chainlengths.append(chainlengths[delta] + 1)
3400 addsize(size, deltasize)
3400 addsize(size, deltasize)
3401 if delta == rev - 1:
3401 if delta == rev - 1:
3402 numprev += 1
3402 numprev += 1
3403 if delta == p1:
3403 if delta == p1:
3404 nump1prev += 1
3404 nump1prev += 1
3405 elif delta == p2:
3405 elif delta == p2:
3406 nump2prev += 1
3406 nump2prev += 1
3407 elif delta == p1:
3407 elif delta == p1:
3408 nump1 += 1
3408 nump1 += 1
3409 elif delta == p2:
3409 elif delta == p2:
3410 nump2 += 1
3410 nump2 += 1
3411 elif delta != nullrev:
3411 elif delta != nullrev:
3412 numother += 1
3412 numother += 1
3413
3413
3414 # Adjust size min value for empty cases
3414 # Adjust size min value for empty cases
3415 for size in (datasize, fullsize, deltasize):
3415 for size in (datasize, fullsize, deltasize):
3416 if size[0] is None:
3416 if size[0] is None:
3417 size[0] = 0
3417 size[0] = 0
3418
3418
3419 numdeltas = numrevs - numfull
3419 numdeltas = numrevs - numfull
3420 numoprev = numprev - nump1prev - nump2prev
3420 numoprev = numprev - nump1prev - nump2prev
3421 totalrawsize = datasize[2]
3421 totalrawsize = datasize[2]
3422 datasize[2] /= numrevs
3422 datasize[2] /= numrevs
3423 fulltotal = fullsize[2]
3423 fulltotal = fullsize[2]
3424 fullsize[2] /= numfull
3424 fullsize[2] /= numfull
3425 deltatotal = deltasize[2]
3425 deltatotal = deltasize[2]
3426 if numrevs - numfull > 0:
3426 if numrevs - numfull > 0:
3427 deltasize[2] /= numrevs - numfull
3427 deltasize[2] /= numrevs - numfull
3428 totalsize = fulltotal + deltatotal
3428 totalsize = fulltotal + deltatotal
3429 avgchainlen = sum(chainlengths) / numrevs
3429 avgchainlen = sum(chainlengths) / numrevs
3430 maxchainlen = max(chainlengths)
3430 maxchainlen = max(chainlengths)
3431 compratio = 1
3431 compratio = 1
3432 if totalsize:
3432 if totalsize:
3433 compratio = totalrawsize / totalsize
3433 compratio = totalrawsize / totalsize
3434
3434
3435 basedfmtstr = '%%%dd\n'
3435 basedfmtstr = '%%%dd\n'
3436 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3436 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3437
3437
3438 def dfmtstr(max):
3438 def dfmtstr(max):
3439 return basedfmtstr % len(str(max))
3439 return basedfmtstr % len(str(max))
3440 def pcfmtstr(max, padding=0):
3440 def pcfmtstr(max, padding=0):
3441 return basepcfmtstr % (len(str(max)), ' ' * padding)
3441 return basepcfmtstr % (len(str(max)), ' ' * padding)
3442
3442
3443 def pcfmt(value, total):
3443 def pcfmt(value, total):
3444 if total:
3444 if total:
3445 return (value, 100 * float(value) / total)
3445 return (value, 100 * float(value) / total)
3446 else:
3446 else:
3447 return value, 100.0
3447 return value, 100.0
3448
3448
3449 ui.write(('format : %d\n') % format)
3449 ui.write(('format : %d\n') % format)
3450 ui.write(('flags : %s\n') % ', '.join(flags))
3450 ui.write(('flags : %s\n') % ', '.join(flags))
3451
3451
3452 ui.write('\n')
3452 ui.write('\n')
3453 fmt = pcfmtstr(totalsize)
3453 fmt = pcfmtstr(totalsize)
3454 fmt2 = dfmtstr(totalsize)
3454 fmt2 = dfmtstr(totalsize)
3455 ui.write(('revisions : ') + fmt2 % numrevs)
3455 ui.write(('revisions : ') + fmt2 % numrevs)
3456 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3456 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3457 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3457 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3458 ui.write(('revisions : ') + fmt2 % numrevs)
3458 ui.write(('revisions : ') + fmt2 % numrevs)
3459 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3459 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3460 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3460 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3461 ui.write(('revision size : ') + fmt2 % totalsize)
3461 ui.write(('revision size : ') + fmt2 % totalsize)
3462 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3462 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3463 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3463 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3464
3464
3465 ui.write('\n')
3465 ui.write('\n')
3466 fmt = dfmtstr(max(avgchainlen, compratio))
3466 fmt = dfmtstr(max(avgchainlen, compratio))
3467 ui.write(('avg chain length : ') + fmt % avgchainlen)
3467 ui.write(('avg chain length : ') + fmt % avgchainlen)
3468 ui.write(('max chain length : ') + fmt % maxchainlen)
3468 ui.write(('max chain length : ') + fmt % maxchainlen)
3469 ui.write(('compression ratio : ') + fmt % compratio)
3469 ui.write(('compression ratio : ') + fmt % compratio)
3470
3470
3471 if format > 0:
3471 if format > 0:
3472 ui.write('\n')
3472 ui.write('\n')
3473 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3473 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3474 % tuple(datasize))
3474 % tuple(datasize))
3475 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3475 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3476 % tuple(fullsize))
3476 % tuple(fullsize))
3477 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3477 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3478 % tuple(deltasize))
3478 % tuple(deltasize))
3479
3479
3480 if numdeltas > 0:
3480 if numdeltas > 0:
3481 ui.write('\n')
3481 ui.write('\n')
3482 fmt = pcfmtstr(numdeltas)
3482 fmt = pcfmtstr(numdeltas)
3483 fmt2 = pcfmtstr(numdeltas, 4)
3483 fmt2 = pcfmtstr(numdeltas, 4)
3484 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3484 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3485 if numprev > 0:
3485 if numprev > 0:
3486 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3486 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3487 numprev))
3487 numprev))
3488 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3488 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3489 numprev))
3489 numprev))
3490 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3490 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3491 numprev))
3491 numprev))
3492 if gdelta:
3492 if gdelta:
3493 ui.write(('deltas against p1 : ')
3493 ui.write(('deltas against p1 : ')
3494 + fmt % pcfmt(nump1, numdeltas))
3494 + fmt % pcfmt(nump1, numdeltas))
3495 ui.write(('deltas against p2 : ')
3495 ui.write(('deltas against p2 : ')
3496 + fmt % pcfmt(nump2, numdeltas))
3496 + fmt % pcfmt(nump2, numdeltas))
3497 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3497 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3498 numdeltas))
3498 numdeltas))
3499
3499
3500 @command('debugrevspec',
3500 @command('debugrevspec',
3501 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3501 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3502 ('REVSPEC'))
3502 ('REVSPEC'))
3503 def debugrevspec(ui, repo, expr, **opts):
3503 def debugrevspec(ui, repo, expr, **opts):
3504 """parse and apply a revision specification
3504 """parse and apply a revision specification
3505
3505
3506 Use --verbose to print the parsed tree before and after aliases
3506 Use --verbose to print the parsed tree before and after aliases
3507 expansion.
3507 expansion.
3508 """
3508 """
3509 if ui.verbose:
3509 if ui.verbose:
3510 tree = revset.parse(expr, lookup=repo.__contains__)
3510 tree = revset.parse(expr, lookup=repo.__contains__)
3511 ui.note(revset.prettyformat(tree), "\n")
3511 ui.note(revset.prettyformat(tree), "\n")
3512 newtree = revset.expandaliases(ui, tree)
3512 newtree = revset.expandaliases(ui, tree)
3513 if newtree != tree:
3513 if newtree != tree:
3514 ui.note(("* expanded:\n"), revset.prettyformat(newtree), "\n")
3514 ui.note(("* expanded:\n"), revset.prettyformat(newtree), "\n")
3515 tree = newtree
3515 tree = newtree
3516 newtree = revset.foldconcat(tree)
3516 newtree = revset.foldconcat(tree)
3517 if newtree != tree:
3517 if newtree != tree:
3518 ui.note(("* concatenated:\n"), revset.prettyformat(newtree), "\n")
3518 ui.note(("* concatenated:\n"), revset.prettyformat(newtree), "\n")
3519 if opts["optimize"]:
3519 if opts["optimize"]:
3520 optimizedtree = revset.optimize(newtree)
3520 optimizedtree = revset.optimize(newtree)
3521 ui.note(("* optimized:\n"),
3521 ui.note(("* optimized:\n"),
3522 revset.prettyformat(optimizedtree), "\n")
3522 revset.prettyformat(optimizedtree), "\n")
3523 func = revset.match(ui, expr, repo)
3523 func = revset.match(ui, expr, repo)
3524 revs = func(repo)
3524 revs = func(repo)
3525 if ui.verbose:
3525 if ui.verbose:
3526 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3526 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3527 for c in revs:
3527 for c in revs:
3528 ui.write("%s\n" % c)
3528 ui.write("%s\n" % c)
3529
3529
3530 @command('debugsetparents', [], _('REV1 [REV2]'))
3530 @command('debugsetparents', [], _('REV1 [REV2]'))
3531 def debugsetparents(ui, repo, rev1, rev2=None):
3531 def debugsetparents(ui, repo, rev1, rev2=None):
3532 """manually set the parents of the current working directory
3532 """manually set the parents of the current working directory
3533
3533
3534 This is useful for writing repository conversion tools, but should
3534 This is useful for writing repository conversion tools, but should
3535 be used with care. For example, neither the working directory nor the
3535 be used with care. For example, neither the working directory nor the
3536 dirstate is updated, so file status may be incorrect after running this
3536 dirstate is updated, so file status may be incorrect after running this
3537 command.
3537 command.
3538
3538
3539 Returns 0 on success.
3539 Returns 0 on success.
3540 """
3540 """
3541
3541
3542 r1 = scmutil.revsingle(repo, rev1).node()
3542 r1 = scmutil.revsingle(repo, rev1).node()
3543 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3543 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3544
3544
3545 with repo.wlock():
3545 with repo.wlock():
3546 repo.setparents(r1, r2)
3546 repo.setparents(r1, r2)
3547
3547
3548 @command('debugdirstate|debugstate',
3548 @command('debugdirstate|debugstate',
3549 [('', 'nodates', None, _('do not display the saved mtime')),
3549 [('', 'nodates', None, _('do not display the saved mtime')),
3550 ('', 'datesort', None, _('sort by saved mtime'))],
3550 ('', 'datesort', None, _('sort by saved mtime'))],
3551 _('[OPTION]...'))
3551 _('[OPTION]...'))
3552 def debugstate(ui, repo, **opts):
3552 def debugstate(ui, repo, **opts):
3553 """show the contents of the current dirstate"""
3553 """show the contents of the current dirstate"""
3554
3554
3555 nodates = opts.get('nodates')
3555 nodates = opts.get('nodates')
3556 datesort = opts.get('datesort')
3556 datesort = opts.get('datesort')
3557
3557
3558 timestr = ""
3558 timestr = ""
3559 if datesort:
3559 if datesort:
3560 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3560 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3561 else:
3561 else:
3562 keyfunc = None # sort by filename
3562 keyfunc = None # sort by filename
3563 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3563 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3564 if ent[3] == -1:
3564 if ent[3] == -1:
3565 timestr = 'unset '
3565 timestr = 'unset '
3566 elif nodates:
3566 elif nodates:
3567 timestr = 'set '
3567 timestr = 'set '
3568 else:
3568 else:
3569 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3569 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3570 time.localtime(ent[3]))
3570 time.localtime(ent[3]))
3571 if ent[1] & 0o20000:
3571 if ent[1] & 0o20000:
3572 mode = 'lnk'
3572 mode = 'lnk'
3573 else:
3573 else:
3574 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3574 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3575 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3575 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3576 for f in repo.dirstate.copies():
3576 for f in repo.dirstate.copies():
3577 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3577 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3578
3578
3579 @command('debugsub',
3579 @command('debugsub',
3580 [('r', 'rev', '',
3580 [('r', 'rev', '',
3581 _('revision to check'), _('REV'))],
3581 _('revision to check'), _('REV'))],
3582 _('[-r REV] [REV]'))
3582 _('[-r REV] [REV]'))
3583 def debugsub(ui, repo, rev=None):
3583 def debugsub(ui, repo, rev=None):
3584 ctx = scmutil.revsingle(repo, rev, None)
3584 ctx = scmutil.revsingle(repo, rev, None)
3585 for k, v in sorted(ctx.substate.items()):
3585 for k, v in sorted(ctx.substate.items()):
3586 ui.write(('path %s\n') % k)
3586 ui.write(('path %s\n') % k)
3587 ui.write((' source %s\n') % v[0])
3587 ui.write((' source %s\n') % v[0])
3588 ui.write((' revision %s\n') % v[1])
3588 ui.write((' revision %s\n') % v[1])
3589
3589
3590 @command('debugsuccessorssets',
3590 @command('debugsuccessorssets',
3591 [],
3591 [],
3592 _('[REV]'))
3592 _('[REV]'))
3593 def debugsuccessorssets(ui, repo, *revs):
3593 def debugsuccessorssets(ui, repo, *revs):
3594 """show set of successors for revision
3594 """show set of successors for revision
3595
3595
3596 A successors set of changeset A is a consistent group of revisions that
3596 A successors set of changeset A is a consistent group of revisions that
3597 succeed A. It contains non-obsolete changesets only.
3597 succeed A. It contains non-obsolete changesets only.
3598
3598
3599 In most cases a changeset A has a single successors set containing a single
3599 In most cases a changeset A has a single successors set containing a single
3600 successor (changeset A replaced by A').
3600 successor (changeset A replaced by A').
3601
3601
3602 A changeset that is made obsolete with no successors are called "pruned".
3602 A changeset that is made obsolete with no successors are called "pruned".
3603 Such changesets have no successors sets at all.
3603 Such changesets have no successors sets at all.
3604
3604
3605 A changeset that has been "split" will have a successors set containing
3605 A changeset that has been "split" will have a successors set containing
3606 more than one successor.
3606 more than one successor.
3607
3607
3608 A changeset that has been rewritten in multiple different ways is called
3608 A changeset that has been rewritten in multiple different ways is called
3609 "divergent". Such changesets have multiple successor sets (each of which
3609 "divergent". Such changesets have multiple successor sets (each of which
3610 may also be split, i.e. have multiple successors).
3610 may also be split, i.e. have multiple successors).
3611
3611
3612 Results are displayed as follows::
3612 Results are displayed as follows::
3613
3613
3614 <rev1>
3614 <rev1>
3615 <successors-1A>
3615 <successors-1A>
3616 <rev2>
3616 <rev2>
3617 <successors-2A>
3617 <successors-2A>
3618 <successors-2B1> <successors-2B2> <successors-2B3>
3618 <successors-2B1> <successors-2B2> <successors-2B3>
3619
3619
3620 Here rev2 has two possible (i.e. divergent) successors sets. The first
3620 Here rev2 has two possible (i.e. divergent) successors sets. The first
3621 holds one element, whereas the second holds three (i.e. the changeset has
3621 holds one element, whereas the second holds three (i.e. the changeset has
3622 been split).
3622 been split).
3623 """
3623 """
3624 # passed to successorssets caching computation from one call to another
3624 # passed to successorssets caching computation from one call to another
3625 cache = {}
3625 cache = {}
3626 ctx2str = str
3626 ctx2str = str
3627 node2str = short
3627 node2str = short
3628 if ui.debug():
3628 if ui.debug():
3629 def ctx2str(ctx):
3629 def ctx2str(ctx):
3630 return ctx.hex()
3630 return ctx.hex()
3631 node2str = hex
3631 node2str = hex
3632 for rev in scmutil.revrange(repo, revs):
3632 for rev in scmutil.revrange(repo, revs):
3633 ctx = repo[rev]
3633 ctx = repo[rev]
3634 ui.write('%s\n'% ctx2str(ctx))
3634 ui.write('%s\n'% ctx2str(ctx))
3635 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3635 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3636 if succsset:
3636 if succsset:
3637 ui.write(' ')
3637 ui.write(' ')
3638 ui.write(node2str(succsset[0]))
3638 ui.write(node2str(succsset[0]))
3639 for node in succsset[1:]:
3639 for node in succsset[1:]:
3640 ui.write(' ')
3640 ui.write(' ')
3641 ui.write(node2str(node))
3641 ui.write(node2str(node))
3642 ui.write('\n')
3642 ui.write('\n')
3643
3643
3644 @command('debugtemplate',
3644 @command('debugtemplate',
3645 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3645 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3646 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3646 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3647 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3647 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3648 optionalrepo=True)
3648 optionalrepo=True)
3649 def debugtemplate(ui, repo, tmpl, **opts):
3649 def debugtemplate(ui, repo, tmpl, **opts):
3650 """parse and apply a template
3650 """parse and apply a template
3651
3651
3652 If -r/--rev is given, the template is processed as a log template and
3652 If -r/--rev is given, the template is processed as a log template and
3653 applied to the given changesets. Otherwise, it is processed as a generic
3653 applied to the given changesets. Otherwise, it is processed as a generic
3654 template.
3654 template.
3655
3655
3656 Use --verbose to print the parsed tree.
3656 Use --verbose to print the parsed tree.
3657 """
3657 """
3658 revs = None
3658 revs = None
3659 if opts['rev']:
3659 if opts['rev']:
3660 if repo is None:
3660 if repo is None:
3661 raise error.RepoError(_('there is no Mercurial repository here '
3661 raise error.RepoError(_('there is no Mercurial repository here '
3662 '(.hg not found)'))
3662 '(.hg not found)'))
3663 revs = scmutil.revrange(repo, opts['rev'])
3663 revs = scmutil.revrange(repo, opts['rev'])
3664
3664
3665 props = {}
3665 props = {}
3666 for d in opts['define']:
3666 for d in opts['define']:
3667 try:
3667 try:
3668 k, v = (e.strip() for e in d.split('=', 1))
3668 k, v = (e.strip() for e in d.split('=', 1))
3669 if not k:
3669 if not k:
3670 raise ValueError
3670 raise ValueError
3671 props[k] = v
3671 props[k] = v
3672 except ValueError:
3672 except ValueError:
3673 raise error.Abort(_('malformed keyword definition: %s') % d)
3673 raise error.Abort(_('malformed keyword definition: %s') % d)
3674
3674
3675 if ui.verbose:
3675 if ui.verbose:
3676 aliases = ui.configitems('templatealias')
3676 aliases = ui.configitems('templatealias')
3677 tree = templater.parse(tmpl)
3677 tree = templater.parse(tmpl)
3678 ui.note(templater.prettyformat(tree), '\n')
3678 ui.note(templater.prettyformat(tree), '\n')
3679 newtree = templater.expandaliases(tree, aliases)
3679 newtree = templater.expandaliases(tree, aliases)
3680 if newtree != tree:
3680 if newtree != tree:
3681 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3681 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3682
3682
3683 mapfile = None
3683 mapfile = None
3684 if revs is None:
3684 if revs is None:
3685 k = 'debugtemplate'
3685 k = 'debugtemplate'
3686 t = formatter.maketemplater(ui, k, tmpl)
3686 t = formatter.maketemplater(ui, k, tmpl)
3687 ui.write(templater.stringify(t(k, **props)))
3687 ui.write(templater.stringify(t(k, **props)))
3688 else:
3688 else:
3689 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3689 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3690 mapfile, buffered=False)
3690 mapfile, buffered=False)
3691 for r in revs:
3691 for r in revs:
3692 displayer.show(repo[r], **props)
3692 displayer.show(repo[r], **props)
3693 displayer.close()
3693 displayer.close()
3694
3694
3695 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3695 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3696 def debugwalk(ui, repo, *pats, **opts):
3696 def debugwalk(ui, repo, *pats, **opts):
3697 """show how files match on given patterns"""
3697 """show how files match on given patterns"""
3698 m = scmutil.match(repo[None], pats, opts)
3698 m = scmutil.match(repo[None], pats, opts)
3699 items = list(repo.walk(m))
3699 items = list(repo.walk(m))
3700 if not items:
3700 if not items:
3701 return
3701 return
3702 f = lambda fn: fn
3702 f = lambda fn: fn
3703 if ui.configbool('ui', 'slash') and os.sep != '/':
3703 if ui.configbool('ui', 'slash') and os.sep != '/':
3704 f = lambda fn: util.normpath(fn)
3704 f = lambda fn: util.normpath(fn)
3705 fmt = 'f %%-%ds %%-%ds %%s' % (
3705 fmt = 'f %%-%ds %%-%ds %%s' % (
3706 max([len(abs) for abs in items]),
3706 max([len(abs) for abs in items]),
3707 max([len(m.rel(abs)) for abs in items]))
3707 max([len(m.rel(abs)) for abs in items]))
3708 for abs in items:
3708 for abs in items:
3709 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3709 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3710 ui.write("%s\n" % line.rstrip())
3710 ui.write("%s\n" % line.rstrip())
3711
3711
3712 @command('debugwireargs',
3712 @command('debugwireargs',
3713 [('', 'three', '', 'three'),
3713 [('', 'three', '', 'three'),
3714 ('', 'four', '', 'four'),
3714 ('', 'four', '', 'four'),
3715 ('', 'five', '', 'five'),
3715 ('', 'five', '', 'five'),
3716 ] + remoteopts,
3716 ] + remoteopts,
3717 _('REPO [OPTIONS]... [ONE [TWO]]'),
3717 _('REPO [OPTIONS]... [ONE [TWO]]'),
3718 norepo=True)
3718 norepo=True)
3719 def debugwireargs(ui, repopath, *vals, **opts):
3719 def debugwireargs(ui, repopath, *vals, **opts):
3720 repo = hg.peer(ui, opts, repopath)
3720 repo = hg.peer(ui, opts, repopath)
3721 for opt in remoteopts:
3721 for opt in remoteopts:
3722 del opts[opt[1]]
3722 del opts[opt[1]]
3723 args = {}
3723 args = {}
3724 for k, v in opts.iteritems():
3724 for k, v in opts.iteritems():
3725 if v:
3725 if v:
3726 args[k] = v
3726 args[k] = v
3727 # run twice to check that we don't mess up the stream for the next command
3727 # run twice to check that we don't mess up the stream for the next command
3728 res1 = repo.debugwireargs(*vals, **args)
3728 res1 = repo.debugwireargs(*vals, **args)
3729 res2 = repo.debugwireargs(*vals, **args)
3729 res2 = repo.debugwireargs(*vals, **args)
3730 ui.write("%s\n" % res1)
3730 ui.write("%s\n" % res1)
3731 if res1 != res2:
3731 if res1 != res2:
3732 ui.warn("%s\n" % res2)
3732 ui.warn("%s\n" % res2)
3733
3733
3734 @command('^diff',
3734 @command('^diff',
3735 [('r', 'rev', [], _('revision'), _('REV')),
3735 [('r', 'rev', [], _('revision'), _('REV')),
3736 ('c', 'change', '', _('change made by revision'), _('REV'))
3736 ('c', 'change', '', _('change made by revision'), _('REV'))
3737 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3737 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3738 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3738 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3739 inferrepo=True)
3739 inferrepo=True)
3740 def diff(ui, repo, *pats, **opts):
3740 def diff(ui, repo, *pats, **opts):
3741 """diff repository (or selected files)
3741 """diff repository (or selected files)
3742
3742
3743 Show differences between revisions for the specified files.
3743 Show differences between revisions for the specified files.
3744
3744
3745 Differences between files are shown using the unified diff format.
3745 Differences between files are shown using the unified diff format.
3746
3746
3747 .. note::
3747 .. note::
3748
3748
3749 :hg:`diff` may generate unexpected results for merges, as it will
3749 :hg:`diff` may generate unexpected results for merges, as it will
3750 default to comparing against the working directory's first
3750 default to comparing against the working directory's first
3751 parent changeset if no revisions are specified.
3751 parent changeset if no revisions are specified.
3752
3752
3753 When two revision arguments are given, then changes are shown
3753 When two revision arguments are given, then changes are shown
3754 between those revisions. If only one revision is specified then
3754 between those revisions. If only one revision is specified then
3755 that revision is compared to the working directory, and, when no
3755 that revision is compared to the working directory, and, when no
3756 revisions are specified, the working directory files are compared
3756 revisions are specified, the working directory files are compared
3757 to its first parent.
3757 to its first parent.
3758
3758
3759 Alternatively you can specify -c/--change with a revision to see
3759 Alternatively you can specify -c/--change with a revision to see
3760 the changes in that changeset relative to its first parent.
3760 the changes in that changeset relative to its first parent.
3761
3761
3762 Without the -a/--text option, diff will avoid generating diffs of
3762 Without the -a/--text option, diff will avoid generating diffs of
3763 files it detects as binary. With -a, diff will generate a diff
3763 files it detects as binary. With -a, diff will generate a diff
3764 anyway, probably with undesirable results.
3764 anyway, probably with undesirable results.
3765
3765
3766 Use the -g/--git option to generate diffs in the git extended diff
3766 Use the -g/--git option to generate diffs in the git extended diff
3767 format. For more information, read :hg:`help diffs`.
3767 format. For more information, read :hg:`help diffs`.
3768
3768
3769 .. container:: verbose
3769 .. container:: verbose
3770
3770
3771 Examples:
3771 Examples:
3772
3772
3773 - compare a file in the current working directory to its parent::
3773 - compare a file in the current working directory to its parent::
3774
3774
3775 hg diff foo.c
3775 hg diff foo.c
3776
3776
3777 - compare two historical versions of a directory, with rename info::
3777 - compare two historical versions of a directory, with rename info::
3778
3778
3779 hg diff --git -r 1.0:1.2 lib/
3779 hg diff --git -r 1.0:1.2 lib/
3780
3780
3781 - get change stats relative to the last change on some date::
3781 - get change stats relative to the last change on some date::
3782
3782
3783 hg diff --stat -r "date('may 2')"
3783 hg diff --stat -r "date('may 2')"
3784
3784
3785 - diff all newly-added files that contain a keyword::
3785 - diff all newly-added files that contain a keyword::
3786
3786
3787 hg diff "set:added() and grep(GNU)"
3787 hg diff "set:added() and grep(GNU)"
3788
3788
3789 - compare a revision and its parents::
3789 - compare a revision and its parents::
3790
3790
3791 hg diff -c 9353 # compare against first parent
3791 hg diff -c 9353 # compare against first parent
3792 hg diff -r 9353^:9353 # same using revset syntax
3792 hg diff -r 9353^:9353 # same using revset syntax
3793 hg diff -r 9353^2:9353 # compare against the second parent
3793 hg diff -r 9353^2:9353 # compare against the second parent
3794
3794
3795 Returns 0 on success.
3795 Returns 0 on success.
3796 """
3796 """
3797
3797
3798 revs = opts.get('rev')
3798 revs = opts.get('rev')
3799 change = opts.get('change')
3799 change = opts.get('change')
3800 stat = opts.get('stat')
3800 stat = opts.get('stat')
3801 reverse = opts.get('reverse')
3801 reverse = opts.get('reverse')
3802
3802
3803 if revs and change:
3803 if revs and change:
3804 msg = _('cannot specify --rev and --change at the same time')
3804 msg = _('cannot specify --rev and --change at the same time')
3805 raise error.Abort(msg)
3805 raise error.Abort(msg)
3806 elif change:
3806 elif change:
3807 node2 = scmutil.revsingle(repo, change, None).node()
3807 node2 = scmutil.revsingle(repo, change, None).node()
3808 node1 = repo[node2].p1().node()
3808 node1 = repo[node2].p1().node()
3809 else:
3809 else:
3810 node1, node2 = scmutil.revpair(repo, revs)
3810 node1, node2 = scmutil.revpair(repo, revs)
3811
3811
3812 if reverse:
3812 if reverse:
3813 node1, node2 = node2, node1
3813 node1, node2 = node2, node1
3814
3814
3815 diffopts = patch.diffallopts(ui, opts)
3815 diffopts = patch.diffallopts(ui, opts)
3816 m = scmutil.match(repo[node2], pats, opts)
3816 m = scmutil.match(repo[node2], pats, opts)
3817 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3817 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3818 listsubrepos=opts.get('subrepos'),
3818 listsubrepos=opts.get('subrepos'),
3819 root=opts.get('root'))
3819 root=opts.get('root'))
3820
3820
3821 @command('^export',
3821 @command('^export',
3822 [('o', 'output', '',
3822 [('o', 'output', '',
3823 _('print output to file with formatted name'), _('FORMAT')),
3823 _('print output to file with formatted name'), _('FORMAT')),
3824 ('', 'switch-parent', None, _('diff against the second parent')),
3824 ('', 'switch-parent', None, _('diff against the second parent')),
3825 ('r', 'rev', [], _('revisions to export'), _('REV')),
3825 ('r', 'rev', [], _('revisions to export'), _('REV')),
3826 ] + diffopts,
3826 ] + diffopts,
3827 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3827 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3828 def export(ui, repo, *changesets, **opts):
3828 def export(ui, repo, *changesets, **opts):
3829 """dump the header and diffs for one or more changesets
3829 """dump the header and diffs for one or more changesets
3830
3830
3831 Print the changeset header and diffs for one or more revisions.
3831 Print the changeset header and diffs for one or more revisions.
3832 If no revision is given, the parent of the working directory is used.
3832 If no revision is given, the parent of the working directory is used.
3833
3833
3834 The information shown in the changeset header is: author, date,
3834 The information shown in the changeset header is: author, date,
3835 branch name (if non-default), changeset hash, parent(s) and commit
3835 branch name (if non-default), changeset hash, parent(s) and commit
3836 comment.
3836 comment.
3837
3837
3838 .. note::
3838 .. note::
3839
3839
3840 :hg:`export` may generate unexpected diff output for merge
3840 :hg:`export` may generate unexpected diff output for merge
3841 changesets, as it will compare the merge changeset against its
3841 changesets, as it will compare the merge changeset against its
3842 first parent only.
3842 first parent only.
3843
3843
3844 Output may be to a file, in which case the name of the file is
3844 Output may be to a file, in which case the name of the file is
3845 given using a format string. The formatting rules are as follows:
3845 given using a format string. The formatting rules are as follows:
3846
3846
3847 :``%%``: literal "%" character
3847 :``%%``: literal "%" character
3848 :``%H``: changeset hash (40 hexadecimal digits)
3848 :``%H``: changeset hash (40 hexadecimal digits)
3849 :``%N``: number of patches being generated
3849 :``%N``: number of patches being generated
3850 :``%R``: changeset revision number
3850 :``%R``: changeset revision number
3851 :``%b``: basename of the exporting repository
3851 :``%b``: basename of the exporting repository
3852 :``%h``: short-form changeset hash (12 hexadecimal digits)
3852 :``%h``: short-form changeset hash (12 hexadecimal digits)
3853 :``%m``: first line of the commit message (only alphanumeric characters)
3853 :``%m``: first line of the commit message (only alphanumeric characters)
3854 :``%n``: zero-padded sequence number, starting at 1
3854 :``%n``: zero-padded sequence number, starting at 1
3855 :``%r``: zero-padded changeset revision number
3855 :``%r``: zero-padded changeset revision number
3856
3856
3857 Without the -a/--text option, export will avoid generating diffs
3857 Without the -a/--text option, export will avoid generating diffs
3858 of files it detects as binary. With -a, export will generate a
3858 of files it detects as binary. With -a, export will generate a
3859 diff anyway, probably with undesirable results.
3859 diff anyway, probably with undesirable results.
3860
3860
3861 Use the -g/--git option to generate diffs in the git extended diff
3861 Use the -g/--git option to generate diffs in the git extended diff
3862 format. See :hg:`help diffs` for more information.
3862 format. See :hg:`help diffs` for more information.
3863
3863
3864 With the --switch-parent option, the diff will be against the
3864 With the --switch-parent option, the diff will be against the
3865 second parent. It can be useful to review a merge.
3865 second parent. It can be useful to review a merge.
3866
3866
3867 .. container:: verbose
3867 .. container:: verbose
3868
3868
3869 Examples:
3869 Examples:
3870
3870
3871 - use export and import to transplant a bugfix to the current
3871 - use export and import to transplant a bugfix to the current
3872 branch::
3872 branch::
3873
3873
3874 hg export -r 9353 | hg import -
3874 hg export -r 9353 | hg import -
3875
3875
3876 - export all the changesets between two revisions to a file with
3876 - export all the changesets between two revisions to a file with
3877 rename information::
3877 rename information::
3878
3878
3879 hg export --git -r 123:150 > changes.txt
3879 hg export --git -r 123:150 > changes.txt
3880
3880
3881 - split outgoing changes into a series of patches with
3881 - split outgoing changes into a series of patches with
3882 descriptive names::
3882 descriptive names::
3883
3883
3884 hg export -r "outgoing()" -o "%n-%m.patch"
3884 hg export -r "outgoing()" -o "%n-%m.patch"
3885
3885
3886 Returns 0 on success.
3886 Returns 0 on success.
3887 """
3887 """
3888 changesets += tuple(opts.get('rev', []))
3888 changesets += tuple(opts.get('rev', []))
3889 if not changesets:
3889 if not changesets:
3890 changesets = ['.']
3890 changesets = ['.']
3891 revs = scmutil.revrange(repo, changesets)
3891 revs = scmutil.revrange(repo, changesets)
3892 if not revs:
3892 if not revs:
3893 raise error.Abort(_("export requires at least one changeset"))
3893 raise error.Abort(_("export requires at least one changeset"))
3894 if len(revs) > 1:
3894 if len(revs) > 1:
3895 ui.note(_('exporting patches:\n'))
3895 ui.note(_('exporting patches:\n'))
3896 else:
3896 else:
3897 ui.note(_('exporting patch:\n'))
3897 ui.note(_('exporting patch:\n'))
3898 cmdutil.export(repo, revs, template=opts.get('output'),
3898 cmdutil.export(repo, revs, template=opts.get('output'),
3899 switch_parent=opts.get('switch_parent'),
3899 switch_parent=opts.get('switch_parent'),
3900 opts=patch.diffallopts(ui, opts))
3900 opts=patch.diffallopts(ui, opts))
3901
3901
3902 @command('files',
3902 @command('files',
3903 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3903 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3904 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3904 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3905 ] + walkopts + formatteropts + subrepoopts,
3905 ] + walkopts + formatteropts + subrepoopts,
3906 _('[OPTION]... [PATTERN]...'))
3906 _('[OPTION]... [PATTERN]...'))
3907 def files(ui, repo, *pats, **opts):
3907 def files(ui, repo, *pats, **opts):
3908 """list tracked files
3908 """list tracked files
3909
3909
3910 Print files under Mercurial control in the working directory or
3910 Print files under Mercurial control in the working directory or
3911 specified revision whose names match the given patterns (excluding
3911 specified revision whose names match the given patterns (excluding
3912 removed files).
3912 removed files).
3913
3913
3914 If no patterns are given to match, this command prints the names
3914 If no patterns are given to match, this command prints the names
3915 of all files under Mercurial control in the working directory.
3915 of all files under Mercurial control in the working directory.
3916
3916
3917 .. container:: verbose
3917 .. container:: verbose
3918
3918
3919 Examples:
3919 Examples:
3920
3920
3921 - list all files under the current directory::
3921 - list all files under the current directory::
3922
3922
3923 hg files .
3923 hg files .
3924
3924
3925 - shows sizes and flags for current revision::
3925 - shows sizes and flags for current revision::
3926
3926
3927 hg files -vr .
3927 hg files -vr .
3928
3928
3929 - list all files named README::
3929 - list all files named README::
3930
3930
3931 hg files -I "**/README"
3931 hg files -I "**/README"
3932
3932
3933 - list all binary files::
3933 - list all binary files::
3934
3934
3935 hg files "set:binary()"
3935 hg files "set:binary()"
3936
3936
3937 - find files containing a regular expression::
3937 - find files containing a regular expression::
3938
3938
3939 hg files "set:grep('bob')"
3939 hg files "set:grep('bob')"
3940
3940
3941 - search tracked file contents with xargs and grep::
3941 - search tracked file contents with xargs and grep::
3942
3942
3943 hg files -0 | xargs -0 grep foo
3943 hg files -0 | xargs -0 grep foo
3944
3944
3945 See :hg:`help patterns` and :hg:`help filesets` for more information
3945 See :hg:`help patterns` and :hg:`help filesets` for more information
3946 on specifying file patterns.
3946 on specifying file patterns.
3947
3947
3948 Returns 0 if a match is found, 1 otherwise.
3948 Returns 0 if a match is found, 1 otherwise.
3949
3949
3950 """
3950 """
3951 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3951 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3952
3952
3953 end = '\n'
3953 end = '\n'
3954 if opts.get('print0'):
3954 if opts.get('print0'):
3955 end = '\0'
3955 end = '\0'
3956 fm = ui.formatter('files', opts)
3956 fm = ui.formatter('files', opts)
3957 fmt = '%s' + end
3957 fmt = '%s' + end
3958
3958
3959 m = scmutil.match(ctx, pats, opts)
3959 m = scmutil.match(ctx, pats, opts)
3960 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3960 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3961
3961
3962 fm.end()
3962 fm.end()
3963
3963
3964 return ret
3964 return ret
3965
3965
3966 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3966 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3967 def forget(ui, repo, *pats, **opts):
3967 def forget(ui, repo, *pats, **opts):
3968 """forget the specified files on the next commit
3968 """forget the specified files on the next commit
3969
3969
3970 Mark the specified files so they will no longer be tracked
3970 Mark the specified files so they will no longer be tracked
3971 after the next commit.
3971 after the next commit.
3972
3972
3973 This only removes files from the current branch, not from the
3973 This only removes files from the current branch, not from the
3974 entire project history, and it does not delete them from the
3974 entire project history, and it does not delete them from the
3975 working directory.
3975 working directory.
3976
3976
3977 To delete the file from the working directory, see :hg:`remove`.
3977 To delete the file from the working directory, see :hg:`remove`.
3978
3978
3979 To undo a forget before the next commit, see :hg:`add`.
3979 To undo a forget before the next commit, see :hg:`add`.
3980
3980
3981 .. container:: verbose
3981 .. container:: verbose
3982
3982
3983 Examples:
3983 Examples:
3984
3984
3985 - forget newly-added binary files::
3985 - forget newly-added binary files::
3986
3986
3987 hg forget "set:added() and binary()"
3987 hg forget "set:added() and binary()"
3988
3988
3989 - forget files that would be excluded by .hgignore::
3989 - forget files that would be excluded by .hgignore::
3990
3990
3991 hg forget "set:hgignore()"
3991 hg forget "set:hgignore()"
3992
3992
3993 Returns 0 on success.
3993 Returns 0 on success.
3994 """
3994 """
3995
3995
3996 if not pats:
3996 if not pats:
3997 raise error.Abort(_('no files specified'))
3997 raise error.Abort(_('no files specified'))
3998
3998
3999 m = scmutil.match(repo[None], pats, opts)
3999 m = scmutil.match(repo[None], pats, opts)
4000 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4000 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4001 return rejected and 1 or 0
4001 return rejected and 1 or 0
4002
4002
4003 @command(
4003 @command(
4004 'graft',
4004 'graft',
4005 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4005 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4006 ('c', 'continue', False, _('resume interrupted graft')),
4006 ('c', 'continue', False, _('resume interrupted graft')),
4007 ('e', 'edit', False, _('invoke editor on commit messages')),
4007 ('e', 'edit', False, _('invoke editor on commit messages')),
4008 ('', 'log', None, _('append graft info to log message')),
4008 ('', 'log', None, _('append graft info to log message')),
4009 ('f', 'force', False, _('force graft')),
4009 ('f', 'force', False, _('force graft')),
4010 ('D', 'currentdate', False,
4010 ('D', 'currentdate', False,
4011 _('record the current date as commit date')),
4011 _('record the current date as commit date')),
4012 ('U', 'currentuser', False,
4012 ('U', 'currentuser', False,
4013 _('record the current user as committer'), _('DATE'))]
4013 _('record the current user as committer'), _('DATE'))]
4014 + commitopts2 + mergetoolopts + dryrunopts,
4014 + commitopts2 + mergetoolopts + dryrunopts,
4015 _('[OPTION]... [-r REV]... REV...'))
4015 _('[OPTION]... [-r REV]... REV...'))
4016 def graft(ui, repo, *revs, **opts):
4016 def graft(ui, repo, *revs, **opts):
4017 '''copy changes from other branches onto the current branch
4017 '''copy changes from other branches onto the current branch
4018
4018
4019 This command uses Mercurial's merge logic to copy individual
4019 This command uses Mercurial's merge logic to copy individual
4020 changes from other branches without merging branches in the
4020 changes from other branches without merging branches in the
4021 history graph. This is sometimes known as 'backporting' or
4021 history graph. This is sometimes known as 'backporting' or
4022 'cherry-picking'. By default, graft will copy user, date, and
4022 'cherry-picking'. By default, graft will copy user, date, and
4023 description from the source changesets.
4023 description from the source changesets.
4024
4024
4025 Changesets that are ancestors of the current revision, that have
4025 Changesets that are ancestors of the current revision, that have
4026 already been grafted, or that are merges will be skipped.
4026 already been grafted, or that are merges will be skipped.
4027
4027
4028 If --log is specified, log messages will have a comment appended
4028 If --log is specified, log messages will have a comment appended
4029 of the form::
4029 of the form::
4030
4030
4031 (grafted from CHANGESETHASH)
4031 (grafted from CHANGESETHASH)
4032
4032
4033 If --force is specified, revisions will be grafted even if they
4033 If --force is specified, revisions will be grafted even if they
4034 are already ancestors of or have been grafted to the destination.
4034 are already ancestors of or have been grafted to the destination.
4035 This is useful when the revisions have since been backed out.
4035 This is useful when the revisions have since been backed out.
4036
4036
4037 If a graft merge results in conflicts, the graft process is
4037 If a graft merge results in conflicts, the graft process is
4038 interrupted so that the current merge can be manually resolved.
4038 interrupted so that the current merge can be manually resolved.
4039 Once all conflicts are addressed, the graft process can be
4039 Once all conflicts are addressed, the graft process can be
4040 continued with the -c/--continue option.
4040 continued with the -c/--continue option.
4041
4041
4042 .. note::
4042 .. note::
4043
4043
4044 The -c/--continue option does not reapply earlier options, except
4044 The -c/--continue option does not reapply earlier options, except
4045 for --force.
4045 for --force.
4046
4046
4047 .. container:: verbose
4047 .. container:: verbose
4048
4048
4049 Examples:
4049 Examples:
4050
4050
4051 - copy a single change to the stable branch and edit its description::
4051 - copy a single change to the stable branch and edit its description::
4052
4052
4053 hg update stable
4053 hg update stable
4054 hg graft --edit 9393
4054 hg graft --edit 9393
4055
4055
4056 - graft a range of changesets with one exception, updating dates::
4056 - graft a range of changesets with one exception, updating dates::
4057
4057
4058 hg graft -D "2085::2093 and not 2091"
4058 hg graft -D "2085::2093 and not 2091"
4059
4059
4060 - continue a graft after resolving conflicts::
4060 - continue a graft after resolving conflicts::
4061
4061
4062 hg graft -c
4062 hg graft -c
4063
4063
4064 - show the source of a grafted changeset::
4064 - show the source of a grafted changeset::
4065
4065
4066 hg log --debug -r .
4066 hg log --debug -r .
4067
4067
4068 - show revisions sorted by date::
4068 - show revisions sorted by date::
4069
4069
4070 hg log -r "sort(all(), date)"
4070 hg log -r "sort(all(), date)"
4071
4071
4072 See :hg:`help revisions` and :hg:`help revsets` for more about
4072 See :hg:`help revisions` and :hg:`help revsets` for more about
4073 specifying revisions.
4073 specifying revisions.
4074
4074
4075 Returns 0 on successful completion.
4075 Returns 0 on successful completion.
4076 '''
4076 '''
4077 with repo.wlock():
4077 with repo.wlock():
4078 return _dograft(ui, repo, *revs, **opts)
4078 return _dograft(ui, repo, *revs, **opts)
4079
4079
4080 def _dograft(ui, repo, *revs, **opts):
4080 def _dograft(ui, repo, *revs, **opts):
4081 if revs and opts.get('rev'):
4081 if revs and opts.get('rev'):
4082 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4082 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4083 'revision ordering!\n'))
4083 'revision ordering!\n'))
4084
4084
4085 revs = list(revs)
4085 revs = list(revs)
4086 revs.extend(opts.get('rev'))
4086 revs.extend(opts.get('rev'))
4087
4087
4088 if not opts.get('user') and opts.get('currentuser'):
4088 if not opts.get('user') and opts.get('currentuser'):
4089 opts['user'] = ui.username()
4089 opts['user'] = ui.username()
4090 if not opts.get('date') and opts.get('currentdate'):
4090 if not opts.get('date') and opts.get('currentdate'):
4091 opts['date'] = "%d %d" % util.makedate()
4091 opts['date'] = "%d %d" % util.makedate()
4092
4092
4093 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4093 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4094
4094
4095 cont = False
4095 cont = False
4096 if opts.get('continue'):
4096 if opts.get('continue'):
4097 cont = True
4097 cont = True
4098 if revs:
4098 if revs:
4099 raise error.Abort(_("can't specify --continue and revisions"))
4099 raise error.Abort(_("can't specify --continue and revisions"))
4100 # read in unfinished revisions
4100 # read in unfinished revisions
4101 try:
4101 try:
4102 nodes = repo.vfs.read('graftstate').splitlines()
4102 nodes = repo.vfs.read('graftstate').splitlines()
4103 revs = [repo[node].rev() for node in nodes]
4103 revs = [repo[node].rev() for node in nodes]
4104 except IOError as inst:
4104 except IOError as inst:
4105 if inst.errno != errno.ENOENT:
4105 if inst.errno != errno.ENOENT:
4106 raise
4106 raise
4107 cmdutil.wrongtooltocontinue(repo, _('graft'))
4107 cmdutil.wrongtooltocontinue(repo, _('graft'))
4108 else:
4108 else:
4109 cmdutil.checkunfinished(repo)
4109 cmdutil.checkunfinished(repo)
4110 cmdutil.bailifchanged(repo)
4110 cmdutil.bailifchanged(repo)
4111 if not revs:
4111 if not revs:
4112 raise error.Abort(_('no revisions specified'))
4112 raise error.Abort(_('no revisions specified'))
4113 revs = scmutil.revrange(repo, revs)
4113 revs = scmutil.revrange(repo, revs)
4114
4114
4115 skipped = set()
4115 skipped = set()
4116 # check for merges
4116 # check for merges
4117 for rev in repo.revs('%ld and merge()', revs):
4117 for rev in repo.revs('%ld and merge()', revs):
4118 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4118 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4119 skipped.add(rev)
4119 skipped.add(rev)
4120 revs = [r for r in revs if r not in skipped]
4120 revs = [r for r in revs if r not in skipped]
4121 if not revs:
4121 if not revs:
4122 return -1
4122 return -1
4123
4123
4124 # Don't check in the --continue case, in effect retaining --force across
4124 # Don't check in the --continue case, in effect retaining --force across
4125 # --continues. That's because without --force, any revisions we decided to
4125 # --continues. That's because without --force, any revisions we decided to
4126 # skip would have been filtered out here, so they wouldn't have made their
4126 # skip would have been filtered out here, so they wouldn't have made their
4127 # way to the graftstate. With --force, any revisions we would have otherwise
4127 # way to the graftstate. With --force, any revisions we would have otherwise
4128 # skipped would not have been filtered out, and if they hadn't been applied
4128 # skipped would not have been filtered out, and if they hadn't been applied
4129 # already, they'd have been in the graftstate.
4129 # already, they'd have been in the graftstate.
4130 if not (cont or opts.get('force')):
4130 if not (cont or opts.get('force')):
4131 # check for ancestors of dest branch
4131 # check for ancestors of dest branch
4132 crev = repo['.'].rev()
4132 crev = repo['.'].rev()
4133 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4133 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4134 # Cannot use x.remove(y) on smart set, this has to be a list.
4134 # Cannot use x.remove(y) on smart set, this has to be a list.
4135 # XXX make this lazy in the future
4135 # XXX make this lazy in the future
4136 revs = list(revs)
4136 revs = list(revs)
4137 # don't mutate while iterating, create a copy
4137 # don't mutate while iterating, create a copy
4138 for rev in list(revs):
4138 for rev in list(revs):
4139 if rev in ancestors:
4139 if rev in ancestors:
4140 ui.warn(_('skipping ancestor revision %d:%s\n') %
4140 ui.warn(_('skipping ancestor revision %d:%s\n') %
4141 (rev, repo[rev]))
4141 (rev, repo[rev]))
4142 # XXX remove on list is slow
4142 # XXX remove on list is slow
4143 revs.remove(rev)
4143 revs.remove(rev)
4144 if not revs:
4144 if not revs:
4145 return -1
4145 return -1
4146
4146
4147 # analyze revs for earlier grafts
4147 # analyze revs for earlier grafts
4148 ids = {}
4148 ids = {}
4149 for ctx in repo.set("%ld", revs):
4149 for ctx in repo.set("%ld", revs):
4150 ids[ctx.hex()] = ctx.rev()
4150 ids[ctx.hex()] = ctx.rev()
4151 n = ctx.extra().get('source')
4151 n = ctx.extra().get('source')
4152 if n:
4152 if n:
4153 ids[n] = ctx.rev()
4153 ids[n] = ctx.rev()
4154
4154
4155 # check ancestors for earlier grafts
4155 # check ancestors for earlier grafts
4156 ui.debug('scanning for duplicate grafts\n')
4156 ui.debug('scanning for duplicate grafts\n')
4157
4157
4158 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4158 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4159 ctx = repo[rev]
4159 ctx = repo[rev]
4160 n = ctx.extra().get('source')
4160 n = ctx.extra().get('source')
4161 if n in ids:
4161 if n in ids:
4162 try:
4162 try:
4163 r = repo[n].rev()
4163 r = repo[n].rev()
4164 except error.RepoLookupError:
4164 except error.RepoLookupError:
4165 r = None
4165 r = None
4166 if r in revs:
4166 if r in revs:
4167 ui.warn(_('skipping revision %d:%s '
4167 ui.warn(_('skipping revision %d:%s '
4168 '(already grafted to %d:%s)\n')
4168 '(already grafted to %d:%s)\n')
4169 % (r, repo[r], rev, ctx))
4169 % (r, repo[r], rev, ctx))
4170 revs.remove(r)
4170 revs.remove(r)
4171 elif ids[n] in revs:
4171 elif ids[n] in revs:
4172 if r is None:
4172 if r is None:
4173 ui.warn(_('skipping already grafted revision %d:%s '
4173 ui.warn(_('skipping already grafted revision %d:%s '
4174 '(%d:%s also has unknown origin %s)\n')
4174 '(%d:%s also has unknown origin %s)\n')
4175 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4175 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4176 else:
4176 else:
4177 ui.warn(_('skipping already grafted revision %d:%s '
4177 ui.warn(_('skipping already grafted revision %d:%s '
4178 '(%d:%s also has origin %d:%s)\n')
4178 '(%d:%s also has origin %d:%s)\n')
4179 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4179 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4180 revs.remove(ids[n])
4180 revs.remove(ids[n])
4181 elif ctx.hex() in ids:
4181 elif ctx.hex() in ids:
4182 r = ids[ctx.hex()]
4182 r = ids[ctx.hex()]
4183 ui.warn(_('skipping already grafted revision %d:%s '
4183 ui.warn(_('skipping already grafted revision %d:%s '
4184 '(was grafted from %d:%s)\n') %
4184 '(was grafted from %d:%s)\n') %
4185 (r, repo[r], rev, ctx))
4185 (r, repo[r], rev, ctx))
4186 revs.remove(r)
4186 revs.remove(r)
4187 if not revs:
4187 if not revs:
4188 return -1
4188 return -1
4189
4189
4190 for pos, ctx in enumerate(repo.set("%ld", revs)):
4190 for pos, ctx in enumerate(repo.set("%ld", revs)):
4191 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4191 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4192 ctx.description().split('\n', 1)[0])
4192 ctx.description().split('\n', 1)[0])
4193 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4193 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4194 if names:
4194 if names:
4195 desc += ' (%s)' % ' '.join(names)
4195 desc += ' (%s)' % ' '.join(names)
4196 ui.status(_('grafting %s\n') % desc)
4196 ui.status(_('grafting %s\n') % desc)
4197 if opts.get('dry_run'):
4197 if opts.get('dry_run'):
4198 continue
4198 continue
4199
4199
4200 source = ctx.extra().get('source')
4200 source = ctx.extra().get('source')
4201 extra = {}
4201 extra = {}
4202 if source:
4202 if source:
4203 extra['source'] = source
4203 extra['source'] = source
4204 extra['intermediate-source'] = ctx.hex()
4204 extra['intermediate-source'] = ctx.hex()
4205 else:
4205 else:
4206 extra['source'] = ctx.hex()
4206 extra['source'] = ctx.hex()
4207 user = ctx.user()
4207 user = ctx.user()
4208 if opts.get('user'):
4208 if opts.get('user'):
4209 user = opts['user']
4209 user = opts['user']
4210 date = ctx.date()
4210 date = ctx.date()
4211 if opts.get('date'):
4211 if opts.get('date'):
4212 date = opts['date']
4212 date = opts['date']
4213 message = ctx.description()
4213 message = ctx.description()
4214 if opts.get('log'):
4214 if opts.get('log'):
4215 message += '\n(grafted from %s)' % ctx.hex()
4215 message += '\n(grafted from %s)' % ctx.hex()
4216
4216
4217 # we don't merge the first commit when continuing
4217 # we don't merge the first commit when continuing
4218 if not cont:
4218 if not cont:
4219 # perform the graft merge with p1(rev) as 'ancestor'
4219 # perform the graft merge with p1(rev) as 'ancestor'
4220 try:
4220 try:
4221 # ui.forcemerge is an internal variable, do not document
4221 # ui.forcemerge is an internal variable, do not document
4222 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4222 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4223 'graft')
4223 'graft')
4224 stats = mergemod.graft(repo, ctx, ctx.p1(),
4224 stats = mergemod.graft(repo, ctx, ctx.p1(),
4225 ['local', 'graft'])
4225 ['local', 'graft'])
4226 finally:
4226 finally:
4227 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4227 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4228 # report any conflicts
4228 # report any conflicts
4229 if stats and stats[3] > 0:
4229 if stats and stats[3] > 0:
4230 # write out state for --continue
4230 # write out state for --continue
4231 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4231 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4232 repo.vfs.write('graftstate', ''.join(nodelines))
4232 repo.vfs.write('graftstate', ''.join(nodelines))
4233 extra = ''
4233 extra = ''
4234 if opts.get('user'):
4234 if opts.get('user'):
4235 extra += ' --user %s' % util.shellquote(opts['user'])
4235 extra += ' --user %s' % util.shellquote(opts['user'])
4236 if opts.get('date'):
4236 if opts.get('date'):
4237 extra += ' --date %s' % util.shellquote(opts['date'])
4237 extra += ' --date %s' % util.shellquote(opts['date'])
4238 if opts.get('log'):
4238 if opts.get('log'):
4239 extra += ' --log'
4239 extra += ' --log'
4240 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4240 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4241 raise error.Abort(
4241 raise error.Abort(
4242 _("unresolved conflicts, can't continue"),
4242 _("unresolved conflicts, can't continue"),
4243 hint=hint)
4243 hint=hint)
4244 else:
4244 else:
4245 cont = False
4245 cont = False
4246
4246
4247 # commit
4247 # commit
4248 node = repo.commit(text=message, user=user,
4248 node = repo.commit(text=message, user=user,
4249 date=date, extra=extra, editor=editor)
4249 date=date, extra=extra, editor=editor)
4250 if node is None:
4250 if node is None:
4251 ui.warn(
4251 ui.warn(
4252 _('note: graft of %d:%s created no changes to commit\n') %
4252 _('note: graft of %d:%s created no changes to commit\n') %
4253 (ctx.rev(), ctx))
4253 (ctx.rev(), ctx))
4254
4254
4255 # remove state when we complete successfully
4255 # remove state when we complete successfully
4256 if not opts.get('dry_run'):
4256 if not opts.get('dry_run'):
4257 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4257 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4258
4258
4259 return 0
4259 return 0
4260
4260
4261 @command('grep',
4261 @command('grep',
4262 [('0', 'print0', None, _('end fields with NUL')),
4262 [('0', 'print0', None, _('end fields with NUL')),
4263 ('', 'all', None, _('print all revisions that match')),
4263 ('', 'all', None, _('print all revisions that match')),
4264 ('a', 'text', None, _('treat all files as text')),
4264 ('a', 'text', None, _('treat all files as text')),
4265 ('f', 'follow', None,
4265 ('f', 'follow', None,
4266 _('follow changeset history,'
4266 _('follow changeset history,'
4267 ' or file history across copies and renames')),
4267 ' or file history across copies and renames')),
4268 ('i', 'ignore-case', None, _('ignore case when matching')),
4268 ('i', 'ignore-case', None, _('ignore case when matching')),
4269 ('l', 'files-with-matches', None,
4269 ('l', 'files-with-matches', None,
4270 _('print only filenames and revisions that match')),
4270 _('print only filenames and revisions that match')),
4271 ('n', 'line-number', None, _('print matching line numbers')),
4271 ('n', 'line-number', None, _('print matching line numbers')),
4272 ('r', 'rev', [],
4272 ('r', 'rev', [],
4273 _('only search files changed within revision range'), _('REV')),
4273 _('only search files changed within revision range'), _('REV')),
4274 ('u', 'user', None, _('list the author (long with -v)')),
4274 ('u', 'user', None, _('list the author (long with -v)')),
4275 ('d', 'date', None, _('list the date (short with -q)')),
4275 ('d', 'date', None, _('list the date (short with -q)')),
4276 ] + walkopts,
4276 ] + walkopts,
4277 _('[OPTION]... PATTERN [FILE]...'),
4277 _('[OPTION]... PATTERN [FILE]...'),
4278 inferrepo=True)
4278 inferrepo=True)
4279 def grep(ui, repo, pattern, *pats, **opts):
4279 def grep(ui, repo, pattern, *pats, **opts):
4280 """search for a pattern in specified files and revisions
4280 """search for a pattern in specified files and revisions
4281
4281
4282 Search revisions of files for a regular expression.
4282 Search revisions of files for a regular expression.
4283
4283
4284 This command behaves differently than Unix grep. It only accepts
4284 This command behaves differently than Unix grep. It only accepts
4285 Python/Perl regexps. It searches repository history, not the
4285 Python/Perl regexps. It searches repository history, not the
4286 working directory. It always prints the revision number in which a
4286 working directory. It always prints the revision number in which a
4287 match appears.
4287 match appears.
4288
4288
4289 By default, grep only prints output for the first revision of a
4289 By default, grep only prints output for the first revision of a
4290 file in which it finds a match. To get it to print every revision
4290 file in which it finds a match. To get it to print every revision
4291 that contains a change in match status ("-" for a match that
4291 that contains a change in match status ("-" for a match that
4292 becomes a non-match, or "+" for a non-match that becomes a match),
4292 becomes a non-match, or "+" for a non-match that becomes a match),
4293 use the --all flag.
4293 use the --all flag.
4294
4294
4295 Returns 0 if a match is found, 1 otherwise.
4295 Returns 0 if a match is found, 1 otherwise.
4296 """
4296 """
4297 reflags = re.M
4297 reflags = re.M
4298 if opts.get('ignore_case'):
4298 if opts.get('ignore_case'):
4299 reflags |= re.I
4299 reflags |= re.I
4300 try:
4300 try:
4301 regexp = util.re.compile(pattern, reflags)
4301 regexp = util.re.compile(pattern, reflags)
4302 except re.error as inst:
4302 except re.error as inst:
4303 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4303 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4304 return 1
4304 return 1
4305 sep, eol = ':', '\n'
4305 sep, eol = ':', '\n'
4306 if opts.get('print0'):
4306 if opts.get('print0'):
4307 sep = eol = '\0'
4307 sep = eol = '\0'
4308
4308
4309 getfile = util.lrucachefunc(repo.file)
4309 getfile = util.lrucachefunc(repo.file)
4310
4310
4311 def matchlines(body):
4311 def matchlines(body):
4312 begin = 0
4312 begin = 0
4313 linenum = 0
4313 linenum = 0
4314 while begin < len(body):
4314 while begin < len(body):
4315 match = regexp.search(body, begin)
4315 match = regexp.search(body, begin)
4316 if not match:
4316 if not match:
4317 break
4317 break
4318 mstart, mend = match.span()
4318 mstart, mend = match.span()
4319 linenum += body.count('\n', begin, mstart) + 1
4319 linenum += body.count('\n', begin, mstart) + 1
4320 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4320 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4321 begin = body.find('\n', mend) + 1 or len(body) + 1
4321 begin = body.find('\n', mend) + 1 or len(body) + 1
4322 lend = begin - 1
4322 lend = begin - 1
4323 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4323 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4324
4324
4325 class linestate(object):
4325 class linestate(object):
4326 def __init__(self, line, linenum, colstart, colend):
4326 def __init__(self, line, linenum, colstart, colend):
4327 self.line = line
4327 self.line = line
4328 self.linenum = linenum
4328 self.linenum = linenum
4329 self.colstart = colstart
4329 self.colstart = colstart
4330 self.colend = colend
4330 self.colend = colend
4331
4331
4332 def __hash__(self):
4332 def __hash__(self):
4333 return hash((self.linenum, self.line))
4333 return hash((self.linenum, self.line))
4334
4334
4335 def __eq__(self, other):
4335 def __eq__(self, other):
4336 return self.line == other.line
4336 return self.line == other.line
4337
4337
4338 def __iter__(self):
4338 def __iter__(self):
4339 yield (self.line[:self.colstart], '')
4339 yield (self.line[:self.colstart], '')
4340 yield (self.line[self.colstart:self.colend], 'grep.match')
4340 yield (self.line[self.colstart:self.colend], 'grep.match')
4341 rest = self.line[self.colend:]
4341 rest = self.line[self.colend:]
4342 while rest != '':
4342 while rest != '':
4343 match = regexp.search(rest)
4343 match = regexp.search(rest)
4344 if not match:
4344 if not match:
4345 yield (rest, '')
4345 yield (rest, '')
4346 break
4346 break
4347 mstart, mend = match.span()
4347 mstart, mend = match.span()
4348 yield (rest[:mstart], '')
4348 yield (rest[:mstart], '')
4349 yield (rest[mstart:mend], 'grep.match')
4349 yield (rest[mstart:mend], 'grep.match')
4350 rest = rest[mend:]
4350 rest = rest[mend:]
4351
4351
4352 matches = {}
4352 matches = {}
4353 copies = {}
4353 copies = {}
4354 def grepbody(fn, rev, body):
4354 def grepbody(fn, rev, body):
4355 matches[rev].setdefault(fn, [])
4355 matches[rev].setdefault(fn, [])
4356 m = matches[rev][fn]
4356 m = matches[rev][fn]
4357 for lnum, cstart, cend, line in matchlines(body):
4357 for lnum, cstart, cend, line in matchlines(body):
4358 s = linestate(line, lnum, cstart, cend)
4358 s = linestate(line, lnum, cstart, cend)
4359 m.append(s)
4359 m.append(s)
4360
4360
4361 def difflinestates(a, b):
4361 def difflinestates(a, b):
4362 sm = difflib.SequenceMatcher(None, a, b)
4362 sm = difflib.SequenceMatcher(None, a, b)
4363 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4363 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4364 if tag == 'insert':
4364 if tag == 'insert':
4365 for i in xrange(blo, bhi):
4365 for i in xrange(blo, bhi):
4366 yield ('+', b[i])
4366 yield ('+', b[i])
4367 elif tag == 'delete':
4367 elif tag == 'delete':
4368 for i in xrange(alo, ahi):
4368 for i in xrange(alo, ahi):
4369 yield ('-', a[i])
4369 yield ('-', a[i])
4370 elif tag == 'replace':
4370 elif tag == 'replace':
4371 for i in xrange(alo, ahi):
4371 for i in xrange(alo, ahi):
4372 yield ('-', a[i])
4372 yield ('-', a[i])
4373 for i in xrange(blo, bhi):
4373 for i in xrange(blo, bhi):
4374 yield ('+', b[i])
4374 yield ('+', b[i])
4375
4375
4376 def display(fn, ctx, pstates, states):
4376 def display(fn, ctx, pstates, states):
4377 rev = ctx.rev()
4377 rev = ctx.rev()
4378 if ui.quiet:
4378 if ui.quiet:
4379 datefunc = util.shortdate
4379 datefunc = util.shortdate
4380 else:
4380 else:
4381 datefunc = util.datestr
4381 datefunc = util.datestr
4382 found = False
4382 found = False
4383 @util.cachefunc
4383 @util.cachefunc
4384 def binary():
4384 def binary():
4385 flog = getfile(fn)
4385 flog = getfile(fn)
4386 return util.binary(flog.read(ctx.filenode(fn)))
4386 return util.binary(flog.read(ctx.filenode(fn)))
4387
4387
4388 if opts.get('all'):
4388 if opts.get('all'):
4389 iter = difflinestates(pstates, states)
4389 iter = difflinestates(pstates, states)
4390 else:
4390 else:
4391 iter = [('', l) for l in states]
4391 iter = [('', l) for l in states]
4392 for change, l in iter:
4392 for change, l in iter:
4393 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4393 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4394
4394
4395 if opts.get('line_number'):
4395 if opts.get('line_number'):
4396 cols.append((str(l.linenum), 'grep.linenumber'))
4396 cols.append((str(l.linenum), 'grep.linenumber'))
4397 if opts.get('all'):
4397 if opts.get('all'):
4398 cols.append((change, 'grep.change'))
4398 cols.append((change, 'grep.change'))
4399 if opts.get('user'):
4399 if opts.get('user'):
4400 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4400 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4401 if opts.get('date'):
4401 if opts.get('date'):
4402 cols.append((datefunc(ctx.date()), 'grep.date'))
4402 cols.append((datefunc(ctx.date()), 'grep.date'))
4403 for col, label in cols[:-1]:
4403 for col, label in cols[:-1]:
4404 ui.write(col, label=label)
4404 ui.write(col, label=label)
4405 ui.write(sep, label='grep.sep')
4405 ui.write(sep, label='grep.sep')
4406 ui.write(cols[-1][0], label=cols[-1][1])
4406 ui.write(cols[-1][0], label=cols[-1][1])
4407 if not opts.get('files_with_matches'):
4407 if not opts.get('files_with_matches'):
4408 ui.write(sep, label='grep.sep')
4408 ui.write(sep, label='grep.sep')
4409 if not opts.get('text') and binary():
4409 if not opts.get('text') and binary():
4410 ui.write(_(" Binary file matches"))
4410 ui.write(_(" Binary file matches"))
4411 else:
4411 else:
4412 for s, label in l:
4412 for s, label in l:
4413 ui.write(s, label=label)
4413 ui.write(s, label=label)
4414 ui.write(eol)
4414 ui.write(eol)
4415 found = True
4415 found = True
4416 if opts.get('files_with_matches'):
4416 if opts.get('files_with_matches'):
4417 break
4417 break
4418 return found
4418 return found
4419
4419
4420 skip = {}
4420 skip = {}
4421 revfiles = {}
4421 revfiles = {}
4422 matchfn = scmutil.match(repo[None], pats, opts)
4422 matchfn = scmutil.match(repo[None], pats, opts)
4423 found = False
4423 found = False
4424 follow = opts.get('follow')
4424 follow = opts.get('follow')
4425
4425
4426 def prep(ctx, fns):
4426 def prep(ctx, fns):
4427 rev = ctx.rev()
4427 rev = ctx.rev()
4428 pctx = ctx.p1()
4428 pctx = ctx.p1()
4429 parent = pctx.rev()
4429 parent = pctx.rev()
4430 matches.setdefault(rev, {})
4430 matches.setdefault(rev, {})
4431 matches.setdefault(parent, {})
4431 matches.setdefault(parent, {})
4432 files = revfiles.setdefault(rev, [])
4432 files = revfiles.setdefault(rev, [])
4433 for fn in fns:
4433 for fn in fns:
4434 flog = getfile(fn)
4434 flog = getfile(fn)
4435 try:
4435 try:
4436 fnode = ctx.filenode(fn)
4436 fnode = ctx.filenode(fn)
4437 except error.LookupError:
4437 except error.LookupError:
4438 continue
4438 continue
4439
4439
4440 copied = flog.renamed(fnode)
4440 copied = flog.renamed(fnode)
4441 copy = follow and copied and copied[0]
4441 copy = follow and copied and copied[0]
4442 if copy:
4442 if copy:
4443 copies.setdefault(rev, {})[fn] = copy
4443 copies.setdefault(rev, {})[fn] = copy
4444 if fn in skip:
4444 if fn in skip:
4445 if copy:
4445 if copy:
4446 skip[copy] = True
4446 skip[copy] = True
4447 continue
4447 continue
4448 files.append(fn)
4448 files.append(fn)
4449
4449
4450 if fn not in matches[rev]:
4450 if fn not in matches[rev]:
4451 grepbody(fn, rev, flog.read(fnode))
4451 grepbody(fn, rev, flog.read(fnode))
4452
4452
4453 pfn = copy or fn
4453 pfn = copy or fn
4454 if pfn not in matches[parent]:
4454 if pfn not in matches[parent]:
4455 try:
4455 try:
4456 fnode = pctx.filenode(pfn)
4456 fnode = pctx.filenode(pfn)
4457 grepbody(pfn, parent, flog.read(fnode))
4457 grepbody(pfn, parent, flog.read(fnode))
4458 except error.LookupError:
4458 except error.LookupError:
4459 pass
4459 pass
4460
4460
4461 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4461 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4462 rev = ctx.rev()
4462 rev = ctx.rev()
4463 parent = ctx.p1().rev()
4463 parent = ctx.p1().rev()
4464 for fn in sorted(revfiles.get(rev, [])):
4464 for fn in sorted(revfiles.get(rev, [])):
4465 states = matches[rev][fn]
4465 states = matches[rev][fn]
4466 copy = copies.get(rev, {}).get(fn)
4466 copy = copies.get(rev, {}).get(fn)
4467 if fn in skip:
4467 if fn in skip:
4468 if copy:
4468 if copy:
4469 skip[copy] = True
4469 skip[copy] = True
4470 continue
4470 continue
4471 pstates = matches.get(parent, {}).get(copy or fn, [])
4471 pstates = matches.get(parent, {}).get(copy or fn, [])
4472 if pstates or states:
4472 if pstates or states:
4473 r = display(fn, ctx, pstates, states)
4473 r = display(fn, ctx, pstates, states)
4474 found = found or r
4474 found = found or r
4475 if r and not opts.get('all'):
4475 if r and not opts.get('all'):
4476 skip[fn] = True
4476 skip[fn] = True
4477 if copy:
4477 if copy:
4478 skip[copy] = True
4478 skip[copy] = True
4479 del matches[rev]
4479 del matches[rev]
4480 del revfiles[rev]
4480 del revfiles[rev]
4481
4481
4482 return not found
4482 return not found
4483
4483
4484 @command('heads',
4484 @command('heads',
4485 [('r', 'rev', '',
4485 [('r', 'rev', '',
4486 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4486 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4487 ('t', 'topo', False, _('show topological heads only')),
4487 ('t', 'topo', False, _('show topological heads only')),
4488 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4488 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4489 ('c', 'closed', False, _('show normal and closed branch heads')),
4489 ('c', 'closed', False, _('show normal and closed branch heads')),
4490 ] + templateopts,
4490 ] + templateopts,
4491 _('[-ct] [-r STARTREV] [REV]...'))
4491 _('[-ct] [-r STARTREV] [REV]...'))
4492 def heads(ui, repo, *branchrevs, **opts):
4492 def heads(ui, repo, *branchrevs, **opts):
4493 """show branch heads
4493 """show branch heads
4494
4494
4495 With no arguments, show all open branch heads in the repository.
4495 With no arguments, show all open branch heads in the repository.
4496 Branch heads are changesets that have no descendants on the
4496 Branch heads are changesets that have no descendants on the
4497 same branch. They are where development generally takes place and
4497 same branch. They are where development generally takes place and
4498 are the usual targets for update and merge operations.
4498 are the usual targets for update and merge operations.
4499
4499
4500 If one or more REVs are given, only open branch heads on the
4500 If one or more REVs are given, only open branch heads on the
4501 branches associated with the specified changesets are shown. This
4501 branches associated with the specified changesets are shown. This
4502 means that you can use :hg:`heads .` to see the heads on the
4502 means that you can use :hg:`heads .` to see the heads on the
4503 currently checked-out branch.
4503 currently checked-out branch.
4504
4504
4505 If -c/--closed is specified, also show branch heads marked closed
4505 If -c/--closed is specified, also show branch heads marked closed
4506 (see :hg:`commit --close-branch`).
4506 (see :hg:`commit --close-branch`).
4507
4507
4508 If STARTREV is specified, only those heads that are descendants of
4508 If STARTREV is specified, only those heads that are descendants of
4509 STARTREV will be displayed.
4509 STARTREV will be displayed.
4510
4510
4511 If -t/--topo is specified, named branch mechanics will be ignored and only
4511 If -t/--topo is specified, named branch mechanics will be ignored and only
4512 topological heads (changesets with no children) will be shown.
4512 topological heads (changesets with no children) will be shown.
4513
4513
4514 Returns 0 if matching heads are found, 1 if not.
4514 Returns 0 if matching heads are found, 1 if not.
4515 """
4515 """
4516
4516
4517 start = None
4517 start = None
4518 if 'rev' in opts:
4518 if 'rev' in opts:
4519 start = scmutil.revsingle(repo, opts['rev'], None).node()
4519 start = scmutil.revsingle(repo, opts['rev'], None).node()
4520
4520
4521 if opts.get('topo'):
4521 if opts.get('topo'):
4522 heads = [repo[h] for h in repo.heads(start)]
4522 heads = [repo[h] for h in repo.heads(start)]
4523 else:
4523 else:
4524 heads = []
4524 heads = []
4525 for branch in repo.branchmap():
4525 for branch in repo.branchmap():
4526 heads += repo.branchheads(branch, start, opts.get('closed'))
4526 heads += repo.branchheads(branch, start, opts.get('closed'))
4527 heads = [repo[h] for h in heads]
4527 heads = [repo[h] for h in heads]
4528
4528
4529 if branchrevs:
4529 if branchrevs:
4530 branches = set(repo[br].branch() for br in branchrevs)
4530 branches = set(repo[br].branch() for br in branchrevs)
4531 heads = [h for h in heads if h.branch() in branches]
4531 heads = [h for h in heads if h.branch() in branches]
4532
4532
4533 if opts.get('active') and branchrevs:
4533 if opts.get('active') and branchrevs:
4534 dagheads = repo.heads(start)
4534 dagheads = repo.heads(start)
4535 heads = [h for h in heads if h.node() in dagheads]
4535 heads = [h for h in heads if h.node() in dagheads]
4536
4536
4537 if branchrevs:
4537 if branchrevs:
4538 haveheads = set(h.branch() for h in heads)
4538 haveheads = set(h.branch() for h in heads)
4539 if branches - haveheads:
4539 if branches - haveheads:
4540 headless = ', '.join(b for b in branches - haveheads)
4540 headless = ', '.join(b for b in branches - haveheads)
4541 msg = _('no open branch heads found on branches %s')
4541 msg = _('no open branch heads found on branches %s')
4542 if opts.get('rev'):
4542 if opts.get('rev'):
4543 msg += _(' (started at %s)') % opts['rev']
4543 msg += _(' (started at %s)') % opts['rev']
4544 ui.warn((msg + '\n') % headless)
4544 ui.warn((msg + '\n') % headless)
4545
4545
4546 if not heads:
4546 if not heads:
4547 return 1
4547 return 1
4548
4548
4549 heads = sorted(heads, key=lambda x: -x.rev())
4549 heads = sorted(heads, key=lambda x: -x.rev())
4550 displayer = cmdutil.show_changeset(ui, repo, opts)
4550 displayer = cmdutil.show_changeset(ui, repo, opts)
4551 for ctx in heads:
4551 for ctx in heads:
4552 displayer.show(ctx)
4552 displayer.show(ctx)
4553 displayer.close()
4553 displayer.close()
4554
4554
4555 @command('help',
4555 @command('help',
4556 [('e', 'extension', None, _('show only help for extensions')),
4556 [('e', 'extension', None, _('show only help for extensions')),
4557 ('c', 'command', None, _('show only help for commands')),
4557 ('c', 'command', None, _('show only help for commands')),
4558 ('k', 'keyword', None, _('show topics matching keyword')),
4558 ('k', 'keyword', None, _('show topics matching keyword')),
4559 ('s', 'system', [], _('show help for specific platform(s)')),
4559 ('s', 'system', [], _('show help for specific platform(s)')),
4560 ],
4560 ],
4561 _('[-ecks] [TOPIC]'),
4561 _('[-ecks] [TOPIC]'),
4562 norepo=True)
4562 norepo=True)
4563 def help_(ui, name=None, **opts):
4563 def help_(ui, name=None, **opts):
4564 """show help for a given topic or a help overview
4564 """show help for a given topic or a help overview
4565
4565
4566 With no arguments, print a list of commands with short help messages.
4566 With no arguments, print a list of commands with short help messages.
4567
4567
4568 Given a topic, extension, or command name, print help for that
4568 Given a topic, extension, or command name, print help for that
4569 topic.
4569 topic.
4570
4570
4571 Returns 0 if successful.
4571 Returns 0 if successful.
4572 """
4572 """
4573
4573
4574 textwidth = ui.configint('ui', 'textwidth', 78)
4574 textwidth = ui.configint('ui', 'textwidth', 78)
4575 termwidth = ui.termwidth() - 2
4575 termwidth = ui.termwidth() - 2
4576 if textwidth <= 0 or termwidth < textwidth:
4576 if textwidth <= 0 or termwidth < textwidth:
4577 textwidth = termwidth
4577 textwidth = termwidth
4578
4578
4579 keep = opts.get('system') or []
4579 keep = opts.get('system') or []
4580 if len(keep) == 0:
4580 if len(keep) == 0:
4581 if sys.platform.startswith('win'):
4581 if sys.platform.startswith('win'):
4582 keep.append('windows')
4582 keep.append('windows')
4583 elif sys.platform == 'OpenVMS':
4583 elif sys.platform == 'OpenVMS':
4584 keep.append('vms')
4584 keep.append('vms')
4585 elif sys.platform == 'plan9':
4585 elif sys.platform == 'plan9':
4586 keep.append('plan9')
4586 keep.append('plan9')
4587 else:
4587 else:
4588 keep.append('unix')
4588 keep.append('unix')
4589 keep.append(sys.platform.lower())
4589 keep.append(sys.platform.lower())
4590 if ui.verbose:
4590 if ui.verbose:
4591 keep.append('verbose')
4591 keep.append('verbose')
4592
4592
4593 section = None
4593 section = None
4594 subtopic = None
4594 subtopic = None
4595 if name and '.' in name:
4595 if name and '.' in name:
4596 name, section = name.split('.', 1)
4596 name, remaining = name.split('.', 1)
4597 section = encoding.lower(section)
4597 remaining = encoding.lower(remaining)
4598 if '.' in section:
4598 if '.' in remaining:
4599 subtopic, section = section.split('.', 1)
4599 subtopic, section = remaining.split('.', 1)
4600 else:
4600 else:
4601 subtopic = section
4601 if name in help.subtopics:
4602 subtopic = remaining
4603 else:
4604 section = remaining
4602
4605
4603 text = help.help_(ui, name, subtopic=subtopic, **opts)
4606 text = help.help_(ui, name, subtopic=subtopic, **opts)
4604
4607
4605 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4608 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4606 section=section)
4609 section=section)
4607
4610
4608 # We could have been given a weird ".foo" section without a name
4611 # We could have been given a weird ".foo" section without a name
4609 # to look for, or we could have simply failed to found "foo.bar"
4612 # to look for, or we could have simply failed to found "foo.bar"
4610 # because bar isn't a section of foo
4613 # because bar isn't a section of foo
4611 if section and not (formatted and name):
4614 if section and not (formatted and name):
4612 raise error.Abort(_("help section not found"))
4615 raise error.Abort(_("help section not found"))
4613
4616
4614 if 'verbose' in pruned:
4617 if 'verbose' in pruned:
4615 keep.append('omitted')
4618 keep.append('omitted')
4616 else:
4619 else:
4617 keep.append('notomitted')
4620 keep.append('notomitted')
4618 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4621 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4619 section=section)
4622 section=section)
4620 ui.write(formatted)
4623 ui.write(formatted)
4621
4624
4622
4625
4623 @command('identify|id',
4626 @command('identify|id',
4624 [('r', 'rev', '',
4627 [('r', 'rev', '',
4625 _('identify the specified revision'), _('REV')),
4628 _('identify the specified revision'), _('REV')),
4626 ('n', 'num', None, _('show local revision number')),
4629 ('n', 'num', None, _('show local revision number')),
4627 ('i', 'id', None, _('show global revision id')),
4630 ('i', 'id', None, _('show global revision id')),
4628 ('b', 'branch', None, _('show branch')),
4631 ('b', 'branch', None, _('show branch')),
4629 ('t', 'tags', None, _('show tags')),
4632 ('t', 'tags', None, _('show tags')),
4630 ('B', 'bookmarks', None, _('show bookmarks')),
4633 ('B', 'bookmarks', None, _('show bookmarks')),
4631 ] + remoteopts,
4634 ] + remoteopts,
4632 _('[-nibtB] [-r REV] [SOURCE]'),
4635 _('[-nibtB] [-r REV] [SOURCE]'),
4633 optionalrepo=True)
4636 optionalrepo=True)
4634 def identify(ui, repo, source=None, rev=None,
4637 def identify(ui, repo, source=None, rev=None,
4635 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4638 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4636 """identify the working directory or specified revision
4639 """identify the working directory or specified revision
4637
4640
4638 Print a summary identifying the repository state at REV using one or
4641 Print a summary identifying the repository state at REV using one or
4639 two parent hash identifiers, followed by a "+" if the working
4642 two parent hash identifiers, followed by a "+" if the working
4640 directory has uncommitted changes, the branch name (if not default),
4643 directory has uncommitted changes, the branch name (if not default),
4641 a list of tags, and a list of bookmarks.
4644 a list of tags, and a list of bookmarks.
4642
4645
4643 When REV is not given, print a summary of the current state of the
4646 When REV is not given, print a summary of the current state of the
4644 repository.
4647 repository.
4645
4648
4646 Specifying a path to a repository root or Mercurial bundle will
4649 Specifying a path to a repository root or Mercurial bundle will
4647 cause lookup to operate on that repository/bundle.
4650 cause lookup to operate on that repository/bundle.
4648
4651
4649 .. container:: verbose
4652 .. container:: verbose
4650
4653
4651 Examples:
4654 Examples:
4652
4655
4653 - generate a build identifier for the working directory::
4656 - generate a build identifier for the working directory::
4654
4657
4655 hg id --id > build-id.dat
4658 hg id --id > build-id.dat
4656
4659
4657 - find the revision corresponding to a tag::
4660 - find the revision corresponding to a tag::
4658
4661
4659 hg id -n -r 1.3
4662 hg id -n -r 1.3
4660
4663
4661 - check the most recent revision of a remote repository::
4664 - check the most recent revision of a remote repository::
4662
4665
4663 hg id -r tip http://selenic.com/hg/
4666 hg id -r tip http://selenic.com/hg/
4664
4667
4665 See :hg:`log` for generating more information about specific revisions,
4668 See :hg:`log` for generating more information about specific revisions,
4666 including full hash identifiers.
4669 including full hash identifiers.
4667
4670
4668 Returns 0 if successful.
4671 Returns 0 if successful.
4669 """
4672 """
4670
4673
4671 if not repo and not source:
4674 if not repo and not source:
4672 raise error.Abort(_("there is no Mercurial repository here "
4675 raise error.Abort(_("there is no Mercurial repository here "
4673 "(.hg not found)"))
4676 "(.hg not found)"))
4674
4677
4675 if ui.debugflag:
4678 if ui.debugflag:
4676 hexfunc = hex
4679 hexfunc = hex
4677 else:
4680 else:
4678 hexfunc = short
4681 hexfunc = short
4679 default = not (num or id or branch or tags or bookmarks)
4682 default = not (num or id or branch or tags or bookmarks)
4680 output = []
4683 output = []
4681 revs = []
4684 revs = []
4682
4685
4683 if source:
4686 if source:
4684 source, branches = hg.parseurl(ui.expandpath(source))
4687 source, branches = hg.parseurl(ui.expandpath(source))
4685 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4688 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4686 repo = peer.local()
4689 repo = peer.local()
4687 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4690 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4688
4691
4689 if not repo:
4692 if not repo:
4690 if num or branch or tags:
4693 if num or branch or tags:
4691 raise error.Abort(
4694 raise error.Abort(
4692 _("can't query remote revision number, branch, or tags"))
4695 _("can't query remote revision number, branch, or tags"))
4693 if not rev and revs:
4696 if not rev and revs:
4694 rev = revs[0]
4697 rev = revs[0]
4695 if not rev:
4698 if not rev:
4696 rev = "tip"
4699 rev = "tip"
4697
4700
4698 remoterev = peer.lookup(rev)
4701 remoterev = peer.lookup(rev)
4699 if default or id:
4702 if default or id:
4700 output = [hexfunc(remoterev)]
4703 output = [hexfunc(remoterev)]
4701
4704
4702 def getbms():
4705 def getbms():
4703 bms = []
4706 bms = []
4704
4707
4705 if 'bookmarks' in peer.listkeys('namespaces'):
4708 if 'bookmarks' in peer.listkeys('namespaces'):
4706 hexremoterev = hex(remoterev)
4709 hexremoterev = hex(remoterev)
4707 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4710 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4708 if bmr == hexremoterev]
4711 if bmr == hexremoterev]
4709
4712
4710 return sorted(bms)
4713 return sorted(bms)
4711
4714
4712 if bookmarks:
4715 if bookmarks:
4713 output.extend(getbms())
4716 output.extend(getbms())
4714 elif default and not ui.quiet:
4717 elif default and not ui.quiet:
4715 # multiple bookmarks for a single parent separated by '/'
4718 # multiple bookmarks for a single parent separated by '/'
4716 bm = '/'.join(getbms())
4719 bm = '/'.join(getbms())
4717 if bm:
4720 if bm:
4718 output.append(bm)
4721 output.append(bm)
4719 else:
4722 else:
4720 ctx = scmutil.revsingle(repo, rev, None)
4723 ctx = scmutil.revsingle(repo, rev, None)
4721
4724
4722 if ctx.rev() is None:
4725 if ctx.rev() is None:
4723 ctx = repo[None]
4726 ctx = repo[None]
4724 parents = ctx.parents()
4727 parents = ctx.parents()
4725 taglist = []
4728 taglist = []
4726 for p in parents:
4729 for p in parents:
4727 taglist.extend(p.tags())
4730 taglist.extend(p.tags())
4728
4731
4729 changed = ""
4732 changed = ""
4730 if default or id or num:
4733 if default or id or num:
4731 if (any(repo.status())
4734 if (any(repo.status())
4732 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4735 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4733 changed = '+'
4736 changed = '+'
4734 if default or id:
4737 if default or id:
4735 output = ["%s%s" %
4738 output = ["%s%s" %
4736 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4739 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4737 if num:
4740 if num:
4738 output.append("%s%s" %
4741 output.append("%s%s" %
4739 ('+'.join([str(p.rev()) for p in parents]), changed))
4742 ('+'.join([str(p.rev()) for p in parents]), changed))
4740 else:
4743 else:
4741 if default or id:
4744 if default or id:
4742 output = [hexfunc(ctx.node())]
4745 output = [hexfunc(ctx.node())]
4743 if num:
4746 if num:
4744 output.append(str(ctx.rev()))
4747 output.append(str(ctx.rev()))
4745 taglist = ctx.tags()
4748 taglist = ctx.tags()
4746
4749
4747 if default and not ui.quiet:
4750 if default and not ui.quiet:
4748 b = ctx.branch()
4751 b = ctx.branch()
4749 if b != 'default':
4752 if b != 'default':
4750 output.append("(%s)" % b)
4753 output.append("(%s)" % b)
4751
4754
4752 # multiple tags for a single parent separated by '/'
4755 # multiple tags for a single parent separated by '/'
4753 t = '/'.join(taglist)
4756 t = '/'.join(taglist)
4754 if t:
4757 if t:
4755 output.append(t)
4758 output.append(t)
4756
4759
4757 # multiple bookmarks for a single parent separated by '/'
4760 # multiple bookmarks for a single parent separated by '/'
4758 bm = '/'.join(ctx.bookmarks())
4761 bm = '/'.join(ctx.bookmarks())
4759 if bm:
4762 if bm:
4760 output.append(bm)
4763 output.append(bm)
4761 else:
4764 else:
4762 if branch:
4765 if branch:
4763 output.append(ctx.branch())
4766 output.append(ctx.branch())
4764
4767
4765 if tags:
4768 if tags:
4766 output.extend(taglist)
4769 output.extend(taglist)
4767
4770
4768 if bookmarks:
4771 if bookmarks:
4769 output.extend(ctx.bookmarks())
4772 output.extend(ctx.bookmarks())
4770
4773
4771 ui.write("%s\n" % ' '.join(output))
4774 ui.write("%s\n" % ' '.join(output))
4772
4775
4773 @command('import|patch',
4776 @command('import|patch',
4774 [('p', 'strip', 1,
4777 [('p', 'strip', 1,
4775 _('directory strip option for patch. This has the same '
4778 _('directory strip option for patch. This has the same '
4776 'meaning as the corresponding patch option'), _('NUM')),
4779 'meaning as the corresponding patch option'), _('NUM')),
4777 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4780 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4778 ('e', 'edit', False, _('invoke editor on commit messages')),
4781 ('e', 'edit', False, _('invoke editor on commit messages')),
4779 ('f', 'force', None,
4782 ('f', 'force', None,
4780 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4783 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4781 ('', 'no-commit', None,
4784 ('', 'no-commit', None,
4782 _("don't commit, just update the working directory")),
4785 _("don't commit, just update the working directory")),
4783 ('', 'bypass', None,
4786 ('', 'bypass', None,
4784 _("apply patch without touching the working directory")),
4787 _("apply patch without touching the working directory")),
4785 ('', 'partial', None,
4788 ('', 'partial', None,
4786 _('commit even if some hunks fail')),
4789 _('commit even if some hunks fail')),
4787 ('', 'exact', None,
4790 ('', 'exact', None,
4788 _('abort if patch would apply lossily')),
4791 _('abort if patch would apply lossily')),
4789 ('', 'prefix', '',
4792 ('', 'prefix', '',
4790 _('apply patch to subdirectory'), _('DIR')),
4793 _('apply patch to subdirectory'), _('DIR')),
4791 ('', 'import-branch', None,
4794 ('', 'import-branch', None,
4792 _('use any branch information in patch (implied by --exact)'))] +
4795 _('use any branch information in patch (implied by --exact)'))] +
4793 commitopts + commitopts2 + similarityopts,
4796 commitopts + commitopts2 + similarityopts,
4794 _('[OPTION]... PATCH...'))
4797 _('[OPTION]... PATCH...'))
4795 def import_(ui, repo, patch1=None, *patches, **opts):
4798 def import_(ui, repo, patch1=None, *patches, **opts):
4796 """import an ordered set of patches
4799 """import an ordered set of patches
4797
4800
4798 Import a list of patches and commit them individually (unless
4801 Import a list of patches and commit them individually (unless
4799 --no-commit is specified).
4802 --no-commit is specified).
4800
4803
4801 To read a patch from standard input, use "-" as the patch name. If
4804 To read a patch from standard input, use "-" as the patch name. If
4802 a URL is specified, the patch will be downloaded from there.
4805 a URL is specified, the patch will be downloaded from there.
4803
4806
4804 Import first applies changes to the working directory (unless
4807 Import first applies changes to the working directory (unless
4805 --bypass is specified), import will abort if there are outstanding
4808 --bypass is specified), import will abort if there are outstanding
4806 changes.
4809 changes.
4807
4810
4808 Use --bypass to apply and commit patches directly to the
4811 Use --bypass to apply and commit patches directly to the
4809 repository, without affecting the working directory. Without
4812 repository, without affecting the working directory. Without
4810 --exact, patches will be applied on top of the working directory
4813 --exact, patches will be applied on top of the working directory
4811 parent revision.
4814 parent revision.
4812
4815
4813 You can import a patch straight from a mail message. Even patches
4816 You can import a patch straight from a mail message. Even patches
4814 as attachments work (to use the body part, it must have type
4817 as attachments work (to use the body part, it must have type
4815 text/plain or text/x-patch). From and Subject headers of email
4818 text/plain or text/x-patch). From and Subject headers of email
4816 message are used as default committer and commit message. All
4819 message are used as default committer and commit message. All
4817 text/plain body parts before first diff are added to the commit
4820 text/plain body parts before first diff are added to the commit
4818 message.
4821 message.
4819
4822
4820 If the imported patch was generated by :hg:`export`, user and
4823 If the imported patch was generated by :hg:`export`, user and
4821 description from patch override values from message headers and
4824 description from patch override values from message headers and
4822 body. Values given on command line with -m/--message and -u/--user
4825 body. Values given on command line with -m/--message and -u/--user
4823 override these.
4826 override these.
4824
4827
4825 If --exact is specified, import will set the working directory to
4828 If --exact is specified, import will set the working directory to
4826 the parent of each patch before applying it, and will abort if the
4829 the parent of each patch before applying it, and will abort if the
4827 resulting changeset has a different ID than the one recorded in
4830 resulting changeset has a different ID than the one recorded in
4828 the patch. This will guard against various ways that portable
4831 the patch. This will guard against various ways that portable
4829 patch formats and mail systems might fail to transfer Mercurial
4832 patch formats and mail systems might fail to transfer Mercurial
4830 data or metadata. See :hg:`bundle` for lossless transmission.
4833 data or metadata. See :hg:`bundle` for lossless transmission.
4831
4834
4832 Use --partial to ensure a changeset will be created from the patch
4835 Use --partial to ensure a changeset will be created from the patch
4833 even if some hunks fail to apply. Hunks that fail to apply will be
4836 even if some hunks fail to apply. Hunks that fail to apply will be
4834 written to a <target-file>.rej file. Conflicts can then be resolved
4837 written to a <target-file>.rej file. Conflicts can then be resolved
4835 by hand before :hg:`commit --amend` is run to update the created
4838 by hand before :hg:`commit --amend` is run to update the created
4836 changeset. This flag exists to let people import patches that
4839 changeset. This flag exists to let people import patches that
4837 partially apply without losing the associated metadata (author,
4840 partially apply without losing the associated metadata (author,
4838 date, description, ...).
4841 date, description, ...).
4839
4842
4840 .. note::
4843 .. note::
4841
4844
4842 When no hunks apply cleanly, :hg:`import --partial` will create
4845 When no hunks apply cleanly, :hg:`import --partial` will create
4843 an empty changeset, importing only the patch metadata.
4846 an empty changeset, importing only the patch metadata.
4844
4847
4845 With -s/--similarity, hg will attempt to discover renames and
4848 With -s/--similarity, hg will attempt to discover renames and
4846 copies in the patch in the same way as :hg:`addremove`.
4849 copies in the patch in the same way as :hg:`addremove`.
4847
4850
4848 It is possible to use external patch programs to perform the patch
4851 It is possible to use external patch programs to perform the patch
4849 by setting the ``ui.patch`` configuration option. For the default
4852 by setting the ``ui.patch`` configuration option. For the default
4850 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4853 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4851 See :hg:`help config` for more information about configuration
4854 See :hg:`help config` for more information about configuration
4852 files and how to use these options.
4855 files and how to use these options.
4853
4856
4854 See :hg:`help dates` for a list of formats valid for -d/--date.
4857 See :hg:`help dates` for a list of formats valid for -d/--date.
4855
4858
4856 .. container:: verbose
4859 .. container:: verbose
4857
4860
4858 Examples:
4861 Examples:
4859
4862
4860 - import a traditional patch from a website and detect renames::
4863 - import a traditional patch from a website and detect renames::
4861
4864
4862 hg import -s 80 http://example.com/bugfix.patch
4865 hg import -s 80 http://example.com/bugfix.patch
4863
4866
4864 - import a changeset from an hgweb server::
4867 - import a changeset from an hgweb server::
4865
4868
4866 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4869 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4867
4870
4868 - import all the patches in an Unix-style mbox::
4871 - import all the patches in an Unix-style mbox::
4869
4872
4870 hg import incoming-patches.mbox
4873 hg import incoming-patches.mbox
4871
4874
4872 - attempt to exactly restore an exported changeset (not always
4875 - attempt to exactly restore an exported changeset (not always
4873 possible)::
4876 possible)::
4874
4877
4875 hg import --exact proposed-fix.patch
4878 hg import --exact proposed-fix.patch
4876
4879
4877 - use an external tool to apply a patch which is too fuzzy for
4880 - use an external tool to apply a patch which is too fuzzy for
4878 the default internal tool.
4881 the default internal tool.
4879
4882
4880 hg import --config ui.patch="patch --merge" fuzzy.patch
4883 hg import --config ui.patch="patch --merge" fuzzy.patch
4881
4884
4882 - change the default fuzzing from 2 to a less strict 7
4885 - change the default fuzzing from 2 to a less strict 7
4883
4886
4884 hg import --config ui.fuzz=7 fuzz.patch
4887 hg import --config ui.fuzz=7 fuzz.patch
4885
4888
4886 Returns 0 on success, 1 on partial success (see --partial).
4889 Returns 0 on success, 1 on partial success (see --partial).
4887 """
4890 """
4888
4891
4889 if not patch1:
4892 if not patch1:
4890 raise error.Abort(_('need at least one patch to import'))
4893 raise error.Abort(_('need at least one patch to import'))
4891
4894
4892 patches = (patch1,) + patches
4895 patches = (patch1,) + patches
4893
4896
4894 date = opts.get('date')
4897 date = opts.get('date')
4895 if date:
4898 if date:
4896 opts['date'] = util.parsedate(date)
4899 opts['date'] = util.parsedate(date)
4897
4900
4898 exact = opts.get('exact')
4901 exact = opts.get('exact')
4899 update = not opts.get('bypass')
4902 update = not opts.get('bypass')
4900 if not update and opts.get('no_commit'):
4903 if not update and opts.get('no_commit'):
4901 raise error.Abort(_('cannot use --no-commit with --bypass'))
4904 raise error.Abort(_('cannot use --no-commit with --bypass'))
4902 try:
4905 try:
4903 sim = float(opts.get('similarity') or 0)
4906 sim = float(opts.get('similarity') or 0)
4904 except ValueError:
4907 except ValueError:
4905 raise error.Abort(_('similarity must be a number'))
4908 raise error.Abort(_('similarity must be a number'))
4906 if sim < 0 or sim > 100:
4909 if sim < 0 or sim > 100:
4907 raise error.Abort(_('similarity must be between 0 and 100'))
4910 raise error.Abort(_('similarity must be between 0 and 100'))
4908 if sim and not update:
4911 if sim and not update:
4909 raise error.Abort(_('cannot use --similarity with --bypass'))
4912 raise error.Abort(_('cannot use --similarity with --bypass'))
4910 if exact:
4913 if exact:
4911 if opts.get('edit'):
4914 if opts.get('edit'):
4912 raise error.Abort(_('cannot use --exact with --edit'))
4915 raise error.Abort(_('cannot use --exact with --edit'))
4913 if opts.get('prefix'):
4916 if opts.get('prefix'):
4914 raise error.Abort(_('cannot use --exact with --prefix'))
4917 raise error.Abort(_('cannot use --exact with --prefix'))
4915
4918
4916 base = opts["base"]
4919 base = opts["base"]
4917 wlock = dsguard = lock = tr = None
4920 wlock = dsguard = lock = tr = None
4918 msgs = []
4921 msgs = []
4919 ret = 0
4922 ret = 0
4920
4923
4921
4924
4922 try:
4925 try:
4923 wlock = repo.wlock()
4926 wlock = repo.wlock()
4924
4927
4925 if update:
4928 if update:
4926 cmdutil.checkunfinished(repo)
4929 cmdutil.checkunfinished(repo)
4927 if (exact or not opts.get('force')):
4930 if (exact or not opts.get('force')):
4928 cmdutil.bailifchanged(repo)
4931 cmdutil.bailifchanged(repo)
4929
4932
4930 if not opts.get('no_commit'):
4933 if not opts.get('no_commit'):
4931 lock = repo.lock()
4934 lock = repo.lock()
4932 tr = repo.transaction('import')
4935 tr = repo.transaction('import')
4933 else:
4936 else:
4934 dsguard = cmdutil.dirstateguard(repo, 'import')
4937 dsguard = cmdutil.dirstateguard(repo, 'import')
4935 parents = repo[None].parents()
4938 parents = repo[None].parents()
4936 for patchurl in patches:
4939 for patchurl in patches:
4937 if patchurl == '-':
4940 if patchurl == '-':
4938 ui.status(_('applying patch from stdin\n'))
4941 ui.status(_('applying patch from stdin\n'))
4939 patchfile = ui.fin
4942 patchfile = ui.fin
4940 patchurl = 'stdin' # for error message
4943 patchurl = 'stdin' # for error message
4941 else:
4944 else:
4942 patchurl = os.path.join(base, patchurl)
4945 patchurl = os.path.join(base, patchurl)
4943 ui.status(_('applying %s\n') % patchurl)
4946 ui.status(_('applying %s\n') % patchurl)
4944 patchfile = hg.openpath(ui, patchurl)
4947 patchfile = hg.openpath(ui, patchurl)
4945
4948
4946 haspatch = False
4949 haspatch = False
4947 for hunk in patch.split(patchfile):
4950 for hunk in patch.split(patchfile):
4948 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4951 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4949 parents, opts,
4952 parents, opts,
4950 msgs, hg.clean)
4953 msgs, hg.clean)
4951 if msg:
4954 if msg:
4952 haspatch = True
4955 haspatch = True
4953 ui.note(msg + '\n')
4956 ui.note(msg + '\n')
4954 if update or exact:
4957 if update or exact:
4955 parents = repo[None].parents()
4958 parents = repo[None].parents()
4956 else:
4959 else:
4957 parents = [repo[node]]
4960 parents = [repo[node]]
4958 if rej:
4961 if rej:
4959 ui.write_err(_("patch applied partially\n"))
4962 ui.write_err(_("patch applied partially\n"))
4960 ui.write_err(_("(fix the .rej files and run "
4963 ui.write_err(_("(fix the .rej files and run "
4961 "`hg commit --amend`)\n"))
4964 "`hg commit --amend`)\n"))
4962 ret = 1
4965 ret = 1
4963 break
4966 break
4964
4967
4965 if not haspatch:
4968 if not haspatch:
4966 raise error.Abort(_('%s: no diffs found') % patchurl)
4969 raise error.Abort(_('%s: no diffs found') % patchurl)
4967
4970
4968 if tr:
4971 if tr:
4969 tr.close()
4972 tr.close()
4970 if msgs:
4973 if msgs:
4971 repo.savecommitmessage('\n* * *\n'.join(msgs))
4974 repo.savecommitmessage('\n* * *\n'.join(msgs))
4972 if dsguard:
4975 if dsguard:
4973 dsguard.close()
4976 dsguard.close()
4974 return ret
4977 return ret
4975 finally:
4978 finally:
4976 if tr:
4979 if tr:
4977 tr.release()
4980 tr.release()
4978 release(lock, dsguard, wlock)
4981 release(lock, dsguard, wlock)
4979
4982
4980 @command('incoming|in',
4983 @command('incoming|in',
4981 [('f', 'force', None,
4984 [('f', 'force', None,
4982 _('run even if remote repository is unrelated')),
4985 _('run even if remote repository is unrelated')),
4983 ('n', 'newest-first', None, _('show newest record first')),
4986 ('n', 'newest-first', None, _('show newest record first')),
4984 ('', 'bundle', '',
4987 ('', 'bundle', '',
4985 _('file to store the bundles into'), _('FILE')),
4988 _('file to store the bundles into'), _('FILE')),
4986 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4989 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4987 ('B', 'bookmarks', False, _("compare bookmarks")),
4990 ('B', 'bookmarks', False, _("compare bookmarks")),
4988 ('b', 'branch', [],
4991 ('b', 'branch', [],
4989 _('a specific branch you would like to pull'), _('BRANCH')),
4992 _('a specific branch you would like to pull'), _('BRANCH')),
4990 ] + logopts + remoteopts + subrepoopts,
4993 ] + logopts + remoteopts + subrepoopts,
4991 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4994 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4992 def incoming(ui, repo, source="default", **opts):
4995 def incoming(ui, repo, source="default", **opts):
4993 """show new changesets found in source
4996 """show new changesets found in source
4994
4997
4995 Show new changesets found in the specified path/URL or the default
4998 Show new changesets found in the specified path/URL or the default
4996 pull location. These are the changesets that would have been pulled
4999 pull location. These are the changesets that would have been pulled
4997 if a pull at the time you issued this command.
5000 if a pull at the time you issued this command.
4998
5001
4999 See pull for valid source format details.
5002 See pull for valid source format details.
5000
5003
5001 .. container:: verbose
5004 .. container:: verbose
5002
5005
5003 With -B/--bookmarks, the result of bookmark comparison between
5006 With -B/--bookmarks, the result of bookmark comparison between
5004 local and remote repositories is displayed. With -v/--verbose,
5007 local and remote repositories is displayed. With -v/--verbose,
5005 status is also displayed for each bookmark like below::
5008 status is also displayed for each bookmark like below::
5006
5009
5007 BM1 01234567890a added
5010 BM1 01234567890a added
5008 BM2 1234567890ab advanced
5011 BM2 1234567890ab advanced
5009 BM3 234567890abc diverged
5012 BM3 234567890abc diverged
5010 BM4 34567890abcd changed
5013 BM4 34567890abcd changed
5011
5014
5012 The action taken locally when pulling depends on the
5015 The action taken locally when pulling depends on the
5013 status of each bookmark:
5016 status of each bookmark:
5014
5017
5015 :``added``: pull will create it
5018 :``added``: pull will create it
5016 :``advanced``: pull will update it
5019 :``advanced``: pull will update it
5017 :``diverged``: pull will create a divergent bookmark
5020 :``diverged``: pull will create a divergent bookmark
5018 :``changed``: result depends on remote changesets
5021 :``changed``: result depends on remote changesets
5019
5022
5020 From the point of view of pulling behavior, bookmark
5023 From the point of view of pulling behavior, bookmark
5021 existing only in the remote repository are treated as ``added``,
5024 existing only in the remote repository are treated as ``added``,
5022 even if it is in fact locally deleted.
5025 even if it is in fact locally deleted.
5023
5026
5024 .. container:: verbose
5027 .. container:: verbose
5025
5028
5026 For remote repository, using --bundle avoids downloading the
5029 For remote repository, using --bundle avoids downloading the
5027 changesets twice if the incoming is followed by a pull.
5030 changesets twice if the incoming is followed by a pull.
5028
5031
5029 Examples:
5032 Examples:
5030
5033
5031 - show incoming changes with patches and full description::
5034 - show incoming changes with patches and full description::
5032
5035
5033 hg incoming -vp
5036 hg incoming -vp
5034
5037
5035 - show incoming changes excluding merges, store a bundle::
5038 - show incoming changes excluding merges, store a bundle::
5036
5039
5037 hg in -vpM --bundle incoming.hg
5040 hg in -vpM --bundle incoming.hg
5038 hg pull incoming.hg
5041 hg pull incoming.hg
5039
5042
5040 - briefly list changes inside a bundle::
5043 - briefly list changes inside a bundle::
5041
5044
5042 hg in changes.hg -T "{desc|firstline}\\n"
5045 hg in changes.hg -T "{desc|firstline}\\n"
5043
5046
5044 Returns 0 if there are incoming changes, 1 otherwise.
5047 Returns 0 if there are incoming changes, 1 otherwise.
5045 """
5048 """
5046 if opts.get('graph'):
5049 if opts.get('graph'):
5047 cmdutil.checkunsupportedgraphflags([], opts)
5050 cmdutil.checkunsupportedgraphflags([], opts)
5048 def display(other, chlist, displayer):
5051 def display(other, chlist, displayer):
5049 revdag = cmdutil.graphrevs(other, chlist, opts)
5052 revdag = cmdutil.graphrevs(other, chlist, opts)
5050 cmdutil.displaygraph(ui, repo, revdag, displayer,
5053 cmdutil.displaygraph(ui, repo, revdag, displayer,
5051 graphmod.asciiedges)
5054 graphmod.asciiedges)
5052
5055
5053 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5056 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5054 return 0
5057 return 0
5055
5058
5056 if opts.get('bundle') and opts.get('subrepos'):
5059 if opts.get('bundle') and opts.get('subrepos'):
5057 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5060 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5058
5061
5059 if opts.get('bookmarks'):
5062 if opts.get('bookmarks'):
5060 source, branches = hg.parseurl(ui.expandpath(source),
5063 source, branches = hg.parseurl(ui.expandpath(source),
5061 opts.get('branch'))
5064 opts.get('branch'))
5062 other = hg.peer(repo, opts, source)
5065 other = hg.peer(repo, opts, source)
5063 if 'bookmarks' not in other.listkeys('namespaces'):
5066 if 'bookmarks' not in other.listkeys('namespaces'):
5064 ui.warn(_("remote doesn't support bookmarks\n"))
5067 ui.warn(_("remote doesn't support bookmarks\n"))
5065 return 0
5068 return 0
5066 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5069 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5067 return bookmarks.incoming(ui, repo, other)
5070 return bookmarks.incoming(ui, repo, other)
5068
5071
5069 repo._subtoppath = ui.expandpath(source)
5072 repo._subtoppath = ui.expandpath(source)
5070 try:
5073 try:
5071 return hg.incoming(ui, repo, source, opts)
5074 return hg.incoming(ui, repo, source, opts)
5072 finally:
5075 finally:
5073 del repo._subtoppath
5076 del repo._subtoppath
5074
5077
5075
5078
5076 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5079 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5077 norepo=True)
5080 norepo=True)
5078 def init(ui, dest=".", **opts):
5081 def init(ui, dest=".", **opts):
5079 """create a new repository in the given directory
5082 """create a new repository in the given directory
5080
5083
5081 Initialize a new repository in the given directory. If the given
5084 Initialize a new repository in the given directory. If the given
5082 directory does not exist, it will be created.
5085 directory does not exist, it will be created.
5083
5086
5084 If no directory is given, the current directory is used.
5087 If no directory is given, the current directory is used.
5085
5088
5086 It is possible to specify an ``ssh://`` URL as the destination.
5089 It is possible to specify an ``ssh://`` URL as the destination.
5087 See :hg:`help urls` for more information.
5090 See :hg:`help urls` for more information.
5088
5091
5089 Returns 0 on success.
5092 Returns 0 on success.
5090 """
5093 """
5091 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5094 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5092
5095
5093 @command('locate',
5096 @command('locate',
5094 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5097 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5095 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5098 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5096 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5099 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5097 ] + walkopts,
5100 ] + walkopts,
5098 _('[OPTION]... [PATTERN]...'))
5101 _('[OPTION]... [PATTERN]...'))
5099 def locate(ui, repo, *pats, **opts):
5102 def locate(ui, repo, *pats, **opts):
5100 """locate files matching specific patterns (DEPRECATED)
5103 """locate files matching specific patterns (DEPRECATED)
5101
5104
5102 Print files under Mercurial control in the working directory whose
5105 Print files under Mercurial control in the working directory whose
5103 names match the given patterns.
5106 names match the given patterns.
5104
5107
5105 By default, this command searches all directories in the working
5108 By default, this command searches all directories in the working
5106 directory. To search just the current directory and its
5109 directory. To search just the current directory and its
5107 subdirectories, use "--include .".
5110 subdirectories, use "--include .".
5108
5111
5109 If no patterns are given to match, this command prints the names
5112 If no patterns are given to match, this command prints the names
5110 of all files under Mercurial control in the working directory.
5113 of all files under Mercurial control in the working directory.
5111
5114
5112 If you want to feed the output of this command into the "xargs"
5115 If you want to feed the output of this command into the "xargs"
5113 command, use the -0 option to both this command and "xargs". This
5116 command, use the -0 option to both this command and "xargs". This
5114 will avoid the problem of "xargs" treating single filenames that
5117 will avoid the problem of "xargs" treating single filenames that
5115 contain whitespace as multiple filenames.
5118 contain whitespace as multiple filenames.
5116
5119
5117 See :hg:`help files` for a more versatile command.
5120 See :hg:`help files` for a more versatile command.
5118
5121
5119 Returns 0 if a match is found, 1 otherwise.
5122 Returns 0 if a match is found, 1 otherwise.
5120 """
5123 """
5121 if opts.get('print0'):
5124 if opts.get('print0'):
5122 end = '\0'
5125 end = '\0'
5123 else:
5126 else:
5124 end = '\n'
5127 end = '\n'
5125 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5128 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5126
5129
5127 ret = 1
5130 ret = 1
5128 ctx = repo[rev]
5131 ctx = repo[rev]
5129 m = scmutil.match(ctx, pats, opts, default='relglob',
5132 m = scmutil.match(ctx, pats, opts, default='relglob',
5130 badfn=lambda x, y: False)
5133 badfn=lambda x, y: False)
5131
5134
5132 for abs in ctx.matches(m):
5135 for abs in ctx.matches(m):
5133 if opts.get('fullpath'):
5136 if opts.get('fullpath'):
5134 ui.write(repo.wjoin(abs), end)
5137 ui.write(repo.wjoin(abs), end)
5135 else:
5138 else:
5136 ui.write(((pats and m.rel(abs)) or abs), end)
5139 ui.write(((pats and m.rel(abs)) or abs), end)
5137 ret = 0
5140 ret = 0
5138
5141
5139 return ret
5142 return ret
5140
5143
5141 @command('^log|history',
5144 @command('^log|history',
5142 [('f', 'follow', None,
5145 [('f', 'follow', None,
5143 _('follow changeset history, or file history across copies and renames')),
5146 _('follow changeset history, or file history across copies and renames')),
5144 ('', 'follow-first', None,
5147 ('', 'follow-first', None,
5145 _('only follow the first parent of merge changesets (DEPRECATED)')),
5148 _('only follow the first parent of merge changesets (DEPRECATED)')),
5146 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5149 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5147 ('C', 'copies', None, _('show copied files')),
5150 ('C', 'copies', None, _('show copied files')),
5148 ('k', 'keyword', [],
5151 ('k', 'keyword', [],
5149 _('do case-insensitive search for a given text'), _('TEXT')),
5152 _('do case-insensitive search for a given text'), _('TEXT')),
5150 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5153 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5151 ('', 'removed', None, _('include revisions where files were removed')),
5154 ('', 'removed', None, _('include revisions where files were removed')),
5152 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5155 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5153 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5156 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5154 ('', 'only-branch', [],
5157 ('', 'only-branch', [],
5155 _('show only changesets within the given named branch (DEPRECATED)'),
5158 _('show only changesets within the given named branch (DEPRECATED)'),
5156 _('BRANCH')),
5159 _('BRANCH')),
5157 ('b', 'branch', [],
5160 ('b', 'branch', [],
5158 _('show changesets within the given named branch'), _('BRANCH')),
5161 _('show changesets within the given named branch'), _('BRANCH')),
5159 ('P', 'prune', [],
5162 ('P', 'prune', [],
5160 _('do not display revision or any of its ancestors'), _('REV')),
5163 _('do not display revision or any of its ancestors'), _('REV')),
5161 ] + logopts + walkopts,
5164 ] + logopts + walkopts,
5162 _('[OPTION]... [FILE]'),
5165 _('[OPTION]... [FILE]'),
5163 inferrepo=True)
5166 inferrepo=True)
5164 def log(ui, repo, *pats, **opts):
5167 def log(ui, repo, *pats, **opts):
5165 """show revision history of entire repository or files
5168 """show revision history of entire repository or files
5166
5169
5167 Print the revision history of the specified files or the entire
5170 Print the revision history of the specified files or the entire
5168 project.
5171 project.
5169
5172
5170 If no revision range is specified, the default is ``tip:0`` unless
5173 If no revision range is specified, the default is ``tip:0`` unless
5171 --follow is set, in which case the working directory parent is
5174 --follow is set, in which case the working directory parent is
5172 used as the starting revision.
5175 used as the starting revision.
5173
5176
5174 File history is shown without following rename or copy history of
5177 File history is shown without following rename or copy history of
5175 files. Use -f/--follow with a filename to follow history across
5178 files. Use -f/--follow with a filename to follow history across
5176 renames and copies. --follow without a filename will only show
5179 renames and copies. --follow without a filename will only show
5177 ancestors or descendants of the starting revision.
5180 ancestors or descendants of the starting revision.
5178
5181
5179 By default this command prints revision number and changeset id,
5182 By default this command prints revision number and changeset id,
5180 tags, non-trivial parents, user, date and time, and a summary for
5183 tags, non-trivial parents, user, date and time, and a summary for
5181 each commit. When the -v/--verbose switch is used, the list of
5184 each commit. When the -v/--verbose switch is used, the list of
5182 changed files and full commit message are shown.
5185 changed files and full commit message are shown.
5183
5186
5184 With --graph the revisions are shown as an ASCII art DAG with the most
5187 With --graph the revisions are shown as an ASCII art DAG with the most
5185 recent changeset at the top.
5188 recent changeset at the top.
5186 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5189 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5187 and '+' represents a fork where the changeset from the lines below is a
5190 and '+' represents a fork where the changeset from the lines below is a
5188 parent of the 'o' merge on the same line.
5191 parent of the 'o' merge on the same line.
5189
5192
5190 .. note::
5193 .. note::
5191
5194
5192 :hg:`log --patch` may generate unexpected diff output for merge
5195 :hg:`log --patch` may generate unexpected diff output for merge
5193 changesets, as it will only compare the merge changeset against
5196 changesets, as it will only compare the merge changeset against
5194 its first parent. Also, only files different from BOTH parents
5197 its first parent. Also, only files different from BOTH parents
5195 will appear in files:.
5198 will appear in files:.
5196
5199
5197 .. note::
5200 .. note::
5198
5201
5199 For performance reasons, :hg:`log FILE` may omit duplicate changes
5202 For performance reasons, :hg:`log FILE` may omit duplicate changes
5200 made on branches and will not show removals or mode changes. To
5203 made on branches and will not show removals or mode changes. To
5201 see all such changes, use the --removed switch.
5204 see all such changes, use the --removed switch.
5202
5205
5203 .. container:: verbose
5206 .. container:: verbose
5204
5207
5205 Some examples:
5208 Some examples:
5206
5209
5207 - changesets with full descriptions and file lists::
5210 - changesets with full descriptions and file lists::
5208
5211
5209 hg log -v
5212 hg log -v
5210
5213
5211 - changesets ancestral to the working directory::
5214 - changesets ancestral to the working directory::
5212
5215
5213 hg log -f
5216 hg log -f
5214
5217
5215 - last 10 commits on the current branch::
5218 - last 10 commits on the current branch::
5216
5219
5217 hg log -l 10 -b .
5220 hg log -l 10 -b .
5218
5221
5219 - changesets showing all modifications of a file, including removals::
5222 - changesets showing all modifications of a file, including removals::
5220
5223
5221 hg log --removed file.c
5224 hg log --removed file.c
5222
5225
5223 - all changesets that touch a directory, with diffs, excluding merges::
5226 - all changesets that touch a directory, with diffs, excluding merges::
5224
5227
5225 hg log -Mp lib/
5228 hg log -Mp lib/
5226
5229
5227 - all revision numbers that match a keyword::
5230 - all revision numbers that match a keyword::
5228
5231
5229 hg log -k bug --template "{rev}\\n"
5232 hg log -k bug --template "{rev}\\n"
5230
5233
5231 - the full hash identifier of the working directory parent::
5234 - the full hash identifier of the working directory parent::
5232
5235
5233 hg log -r . --template "{node}\\n"
5236 hg log -r . --template "{node}\\n"
5234
5237
5235 - list available log templates::
5238 - list available log templates::
5236
5239
5237 hg log -T list
5240 hg log -T list
5238
5241
5239 - check if a given changeset is included in a tagged release::
5242 - check if a given changeset is included in a tagged release::
5240
5243
5241 hg log -r "a21ccf and ancestor(1.9)"
5244 hg log -r "a21ccf and ancestor(1.9)"
5242
5245
5243 - find all changesets by some user in a date range::
5246 - find all changesets by some user in a date range::
5244
5247
5245 hg log -k alice -d "may 2008 to jul 2008"
5248 hg log -k alice -d "may 2008 to jul 2008"
5246
5249
5247 - summary of all changesets after the last tag::
5250 - summary of all changesets after the last tag::
5248
5251
5249 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5252 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5250
5253
5251 See :hg:`help dates` for a list of formats valid for -d/--date.
5254 See :hg:`help dates` for a list of formats valid for -d/--date.
5252
5255
5253 See :hg:`help revisions` and :hg:`help revsets` for more about
5256 See :hg:`help revisions` and :hg:`help revsets` for more about
5254 specifying and ordering revisions.
5257 specifying and ordering revisions.
5255
5258
5256 See :hg:`help templates` for more about pre-packaged styles and
5259 See :hg:`help templates` for more about pre-packaged styles and
5257 specifying custom templates.
5260 specifying custom templates.
5258
5261
5259 Returns 0 on success.
5262 Returns 0 on success.
5260
5263
5261 """
5264 """
5262 if opts.get('follow') and opts.get('rev'):
5265 if opts.get('follow') and opts.get('rev'):
5263 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5266 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5264 del opts['follow']
5267 del opts['follow']
5265
5268
5266 if opts.get('graph'):
5269 if opts.get('graph'):
5267 return cmdutil.graphlog(ui, repo, *pats, **opts)
5270 return cmdutil.graphlog(ui, repo, *pats, **opts)
5268
5271
5269 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5272 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5270 limit = cmdutil.loglimit(opts)
5273 limit = cmdutil.loglimit(opts)
5271 count = 0
5274 count = 0
5272
5275
5273 getrenamed = None
5276 getrenamed = None
5274 if opts.get('copies'):
5277 if opts.get('copies'):
5275 endrev = None
5278 endrev = None
5276 if opts.get('rev'):
5279 if opts.get('rev'):
5277 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5280 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5278 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5281 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5279
5282
5280 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5283 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5281 for rev in revs:
5284 for rev in revs:
5282 if count == limit:
5285 if count == limit:
5283 break
5286 break
5284 ctx = repo[rev]
5287 ctx = repo[rev]
5285 copies = None
5288 copies = None
5286 if getrenamed is not None and rev:
5289 if getrenamed is not None and rev:
5287 copies = []
5290 copies = []
5288 for fn in ctx.files():
5291 for fn in ctx.files():
5289 rename = getrenamed(fn, rev)
5292 rename = getrenamed(fn, rev)
5290 if rename:
5293 if rename:
5291 copies.append((fn, rename[0]))
5294 copies.append((fn, rename[0]))
5292 if filematcher:
5295 if filematcher:
5293 revmatchfn = filematcher(ctx.rev())
5296 revmatchfn = filematcher(ctx.rev())
5294 else:
5297 else:
5295 revmatchfn = None
5298 revmatchfn = None
5296 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5299 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5297 if displayer.flush(ctx):
5300 if displayer.flush(ctx):
5298 count += 1
5301 count += 1
5299
5302
5300 displayer.close()
5303 displayer.close()
5301
5304
5302 @command('manifest',
5305 @command('manifest',
5303 [('r', 'rev', '', _('revision to display'), _('REV')),
5306 [('r', 'rev', '', _('revision to display'), _('REV')),
5304 ('', 'all', False, _("list files from all revisions"))]
5307 ('', 'all', False, _("list files from all revisions"))]
5305 + formatteropts,
5308 + formatteropts,
5306 _('[-r REV]'))
5309 _('[-r REV]'))
5307 def manifest(ui, repo, node=None, rev=None, **opts):
5310 def manifest(ui, repo, node=None, rev=None, **opts):
5308 """output the current or given revision of the project manifest
5311 """output the current or given revision of the project manifest
5309
5312
5310 Print a list of version controlled files for the given revision.
5313 Print a list of version controlled files for the given revision.
5311 If no revision is given, the first parent of the working directory
5314 If no revision is given, the first parent of the working directory
5312 is used, or the null revision if no revision is checked out.
5315 is used, or the null revision if no revision is checked out.
5313
5316
5314 With -v, print file permissions, symlink and executable bits.
5317 With -v, print file permissions, symlink and executable bits.
5315 With --debug, print file revision hashes.
5318 With --debug, print file revision hashes.
5316
5319
5317 If option --all is specified, the list of all files from all revisions
5320 If option --all is specified, the list of all files from all revisions
5318 is printed. This includes deleted and renamed files.
5321 is printed. This includes deleted and renamed files.
5319
5322
5320 Returns 0 on success.
5323 Returns 0 on success.
5321 """
5324 """
5322
5325
5323 fm = ui.formatter('manifest', opts)
5326 fm = ui.formatter('manifest', opts)
5324
5327
5325 if opts.get('all'):
5328 if opts.get('all'):
5326 if rev or node:
5329 if rev or node:
5327 raise error.Abort(_("can't specify a revision with --all"))
5330 raise error.Abort(_("can't specify a revision with --all"))
5328
5331
5329 res = []
5332 res = []
5330 prefix = "data/"
5333 prefix = "data/"
5331 suffix = ".i"
5334 suffix = ".i"
5332 plen = len(prefix)
5335 plen = len(prefix)
5333 slen = len(suffix)
5336 slen = len(suffix)
5334 with repo.lock():
5337 with repo.lock():
5335 for fn, b, size in repo.store.datafiles():
5338 for fn, b, size in repo.store.datafiles():
5336 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5339 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5337 res.append(fn[plen:-slen])
5340 res.append(fn[plen:-slen])
5338 for f in res:
5341 for f in res:
5339 fm.startitem()
5342 fm.startitem()
5340 fm.write("path", '%s\n', f)
5343 fm.write("path", '%s\n', f)
5341 fm.end()
5344 fm.end()
5342 return
5345 return
5343
5346
5344 if rev and node:
5347 if rev and node:
5345 raise error.Abort(_("please specify just one revision"))
5348 raise error.Abort(_("please specify just one revision"))
5346
5349
5347 if not node:
5350 if not node:
5348 node = rev
5351 node = rev
5349
5352
5350 char = {'l': '@', 'x': '*', '': ''}
5353 char = {'l': '@', 'x': '*', '': ''}
5351 mode = {'l': '644', 'x': '755', '': '644'}
5354 mode = {'l': '644', 'x': '755', '': '644'}
5352 ctx = scmutil.revsingle(repo, node)
5355 ctx = scmutil.revsingle(repo, node)
5353 mf = ctx.manifest()
5356 mf = ctx.manifest()
5354 for f in ctx:
5357 for f in ctx:
5355 fm.startitem()
5358 fm.startitem()
5356 fl = ctx[f].flags()
5359 fl = ctx[f].flags()
5357 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5360 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5358 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5361 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5359 fm.write('path', '%s\n', f)
5362 fm.write('path', '%s\n', f)
5360 fm.end()
5363 fm.end()
5361
5364
5362 @command('^merge',
5365 @command('^merge',
5363 [('f', 'force', None,
5366 [('f', 'force', None,
5364 _('force a merge including outstanding changes (DEPRECATED)')),
5367 _('force a merge including outstanding changes (DEPRECATED)')),
5365 ('r', 'rev', '', _('revision to merge'), _('REV')),
5368 ('r', 'rev', '', _('revision to merge'), _('REV')),
5366 ('P', 'preview', None,
5369 ('P', 'preview', None,
5367 _('review revisions to merge (no merge is performed)'))
5370 _('review revisions to merge (no merge is performed)'))
5368 ] + mergetoolopts,
5371 ] + mergetoolopts,
5369 _('[-P] [[-r] REV]'))
5372 _('[-P] [[-r] REV]'))
5370 def merge(ui, repo, node=None, **opts):
5373 def merge(ui, repo, node=None, **opts):
5371 """merge another revision into working directory
5374 """merge another revision into working directory
5372
5375
5373 The current working directory is updated with all changes made in
5376 The current working directory is updated with all changes made in
5374 the requested revision since the last common predecessor revision.
5377 the requested revision since the last common predecessor revision.
5375
5378
5376 Files that changed between either parent are marked as changed for
5379 Files that changed between either parent are marked as changed for
5377 the next commit and a commit must be performed before any further
5380 the next commit and a commit must be performed before any further
5378 updates to the repository are allowed. The next commit will have
5381 updates to the repository are allowed. The next commit will have
5379 two parents.
5382 two parents.
5380
5383
5381 ``--tool`` can be used to specify the merge tool used for file
5384 ``--tool`` can be used to specify the merge tool used for file
5382 merges. It overrides the HGMERGE environment variable and your
5385 merges. It overrides the HGMERGE environment variable and your
5383 configuration files. See :hg:`help merge-tools` for options.
5386 configuration files. See :hg:`help merge-tools` for options.
5384
5387
5385 If no revision is specified, the working directory's parent is a
5388 If no revision is specified, the working directory's parent is a
5386 head revision, and the current branch contains exactly one other
5389 head revision, and the current branch contains exactly one other
5387 head, the other head is merged with by default. Otherwise, an
5390 head, the other head is merged with by default. Otherwise, an
5388 explicit revision with which to merge with must be provided.
5391 explicit revision with which to merge with must be provided.
5389
5392
5390 See :hg:`help resolve` for information on handling file conflicts.
5393 See :hg:`help resolve` for information on handling file conflicts.
5391
5394
5392 To undo an uncommitted merge, use :hg:`update --clean .` which
5395 To undo an uncommitted merge, use :hg:`update --clean .` which
5393 will check out a clean copy of the original merge parent, losing
5396 will check out a clean copy of the original merge parent, losing
5394 all changes.
5397 all changes.
5395
5398
5396 Returns 0 on success, 1 if there are unresolved files.
5399 Returns 0 on success, 1 if there are unresolved files.
5397 """
5400 """
5398
5401
5399 if opts.get('rev') and node:
5402 if opts.get('rev') and node:
5400 raise error.Abort(_("please specify just one revision"))
5403 raise error.Abort(_("please specify just one revision"))
5401 if not node:
5404 if not node:
5402 node = opts.get('rev')
5405 node = opts.get('rev')
5403
5406
5404 if node:
5407 if node:
5405 node = scmutil.revsingle(repo, node).node()
5408 node = scmutil.revsingle(repo, node).node()
5406
5409
5407 if not node:
5410 if not node:
5408 node = repo[destutil.destmerge(repo)].node()
5411 node = repo[destutil.destmerge(repo)].node()
5409
5412
5410 if opts.get('preview'):
5413 if opts.get('preview'):
5411 # find nodes that are ancestors of p2 but not of p1
5414 # find nodes that are ancestors of p2 but not of p1
5412 p1 = repo.lookup('.')
5415 p1 = repo.lookup('.')
5413 p2 = repo.lookup(node)
5416 p2 = repo.lookup(node)
5414 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5417 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5415
5418
5416 displayer = cmdutil.show_changeset(ui, repo, opts)
5419 displayer = cmdutil.show_changeset(ui, repo, opts)
5417 for node in nodes:
5420 for node in nodes:
5418 displayer.show(repo[node])
5421 displayer.show(repo[node])
5419 displayer.close()
5422 displayer.close()
5420 return 0
5423 return 0
5421
5424
5422 try:
5425 try:
5423 # ui.forcemerge is an internal variable, do not document
5426 # ui.forcemerge is an internal variable, do not document
5424 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5427 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5425 force = opts.get('force')
5428 force = opts.get('force')
5426 return hg.merge(repo, node, force=force, mergeforce=force)
5429 return hg.merge(repo, node, force=force, mergeforce=force)
5427 finally:
5430 finally:
5428 ui.setconfig('ui', 'forcemerge', '', 'merge')
5431 ui.setconfig('ui', 'forcemerge', '', 'merge')
5429
5432
5430 @command('outgoing|out',
5433 @command('outgoing|out',
5431 [('f', 'force', None, _('run even when the destination is unrelated')),
5434 [('f', 'force', None, _('run even when the destination is unrelated')),
5432 ('r', 'rev', [],
5435 ('r', 'rev', [],
5433 _('a changeset intended to be included in the destination'), _('REV')),
5436 _('a changeset intended to be included in the destination'), _('REV')),
5434 ('n', 'newest-first', None, _('show newest record first')),
5437 ('n', 'newest-first', None, _('show newest record first')),
5435 ('B', 'bookmarks', False, _('compare bookmarks')),
5438 ('B', 'bookmarks', False, _('compare bookmarks')),
5436 ('b', 'branch', [], _('a specific branch you would like to push'),
5439 ('b', 'branch', [], _('a specific branch you would like to push'),
5437 _('BRANCH')),
5440 _('BRANCH')),
5438 ] + logopts + remoteopts + subrepoopts,
5441 ] + logopts + remoteopts + subrepoopts,
5439 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5442 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5440 def outgoing(ui, repo, dest=None, **opts):
5443 def outgoing(ui, repo, dest=None, **opts):
5441 """show changesets not found in the destination
5444 """show changesets not found in the destination
5442
5445
5443 Show changesets not found in the specified destination repository
5446 Show changesets not found in the specified destination repository
5444 or the default push location. These are the changesets that would
5447 or the default push location. These are the changesets that would
5445 be pushed if a push was requested.
5448 be pushed if a push was requested.
5446
5449
5447 See pull for details of valid destination formats.
5450 See pull for details of valid destination formats.
5448
5451
5449 .. container:: verbose
5452 .. container:: verbose
5450
5453
5451 With -B/--bookmarks, the result of bookmark comparison between
5454 With -B/--bookmarks, the result of bookmark comparison between
5452 local and remote repositories is displayed. With -v/--verbose,
5455 local and remote repositories is displayed. With -v/--verbose,
5453 status is also displayed for each bookmark like below::
5456 status is also displayed for each bookmark like below::
5454
5457
5455 BM1 01234567890a added
5458 BM1 01234567890a added
5456 BM2 deleted
5459 BM2 deleted
5457 BM3 234567890abc advanced
5460 BM3 234567890abc advanced
5458 BM4 34567890abcd diverged
5461 BM4 34567890abcd diverged
5459 BM5 4567890abcde changed
5462 BM5 4567890abcde changed
5460
5463
5461 The action taken when pushing depends on the
5464 The action taken when pushing depends on the
5462 status of each bookmark:
5465 status of each bookmark:
5463
5466
5464 :``added``: push with ``-B`` will create it
5467 :``added``: push with ``-B`` will create it
5465 :``deleted``: push with ``-B`` will delete it
5468 :``deleted``: push with ``-B`` will delete it
5466 :``advanced``: push will update it
5469 :``advanced``: push will update it
5467 :``diverged``: push with ``-B`` will update it
5470 :``diverged``: push with ``-B`` will update it
5468 :``changed``: push with ``-B`` will update it
5471 :``changed``: push with ``-B`` will update it
5469
5472
5470 From the point of view of pushing behavior, bookmarks
5473 From the point of view of pushing behavior, bookmarks
5471 existing only in the remote repository are treated as
5474 existing only in the remote repository are treated as
5472 ``deleted``, even if it is in fact added remotely.
5475 ``deleted``, even if it is in fact added remotely.
5473
5476
5474 Returns 0 if there are outgoing changes, 1 otherwise.
5477 Returns 0 if there are outgoing changes, 1 otherwise.
5475 """
5478 """
5476 if opts.get('graph'):
5479 if opts.get('graph'):
5477 cmdutil.checkunsupportedgraphflags([], opts)
5480 cmdutil.checkunsupportedgraphflags([], opts)
5478 o, other = hg._outgoing(ui, repo, dest, opts)
5481 o, other = hg._outgoing(ui, repo, dest, opts)
5479 if not o:
5482 if not o:
5480 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5483 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5481 return
5484 return
5482
5485
5483 revdag = cmdutil.graphrevs(repo, o, opts)
5486 revdag = cmdutil.graphrevs(repo, o, opts)
5484 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5487 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5485 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5488 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5486 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5489 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5487 return 0
5490 return 0
5488
5491
5489 if opts.get('bookmarks'):
5492 if opts.get('bookmarks'):
5490 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5493 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5491 dest, branches = hg.parseurl(dest, opts.get('branch'))
5494 dest, branches = hg.parseurl(dest, opts.get('branch'))
5492 other = hg.peer(repo, opts, dest)
5495 other = hg.peer(repo, opts, dest)
5493 if 'bookmarks' not in other.listkeys('namespaces'):
5496 if 'bookmarks' not in other.listkeys('namespaces'):
5494 ui.warn(_("remote doesn't support bookmarks\n"))
5497 ui.warn(_("remote doesn't support bookmarks\n"))
5495 return 0
5498 return 0
5496 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5499 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5497 return bookmarks.outgoing(ui, repo, other)
5500 return bookmarks.outgoing(ui, repo, other)
5498
5501
5499 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5502 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5500 try:
5503 try:
5501 return hg.outgoing(ui, repo, dest, opts)
5504 return hg.outgoing(ui, repo, dest, opts)
5502 finally:
5505 finally:
5503 del repo._subtoppath
5506 del repo._subtoppath
5504
5507
5505 @command('parents',
5508 @command('parents',
5506 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5509 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5507 ] + templateopts,
5510 ] + templateopts,
5508 _('[-r REV] [FILE]'),
5511 _('[-r REV] [FILE]'),
5509 inferrepo=True)
5512 inferrepo=True)
5510 def parents(ui, repo, file_=None, **opts):
5513 def parents(ui, repo, file_=None, **opts):
5511 """show the parents of the working directory or revision (DEPRECATED)
5514 """show the parents of the working directory or revision (DEPRECATED)
5512
5515
5513 Print the working directory's parent revisions. If a revision is
5516 Print the working directory's parent revisions. If a revision is
5514 given via -r/--rev, the parent of that revision will be printed.
5517 given via -r/--rev, the parent of that revision will be printed.
5515 If a file argument is given, the revision in which the file was
5518 If a file argument is given, the revision in which the file was
5516 last changed (before the working directory revision or the
5519 last changed (before the working directory revision or the
5517 argument to --rev if given) is printed.
5520 argument to --rev if given) is printed.
5518
5521
5519 This command is equivalent to::
5522 This command is equivalent to::
5520
5523
5521 hg log -r "p1()+p2()" or
5524 hg log -r "p1()+p2()" or
5522 hg log -r "p1(REV)+p2(REV)" or
5525 hg log -r "p1(REV)+p2(REV)" or
5523 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5526 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5524 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5527 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5525
5528
5526 See :hg:`summary` and :hg:`help revsets` for related information.
5529 See :hg:`summary` and :hg:`help revsets` for related information.
5527
5530
5528 Returns 0 on success.
5531 Returns 0 on success.
5529 """
5532 """
5530
5533
5531 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5534 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5532
5535
5533 if file_:
5536 if file_:
5534 m = scmutil.match(ctx, (file_,), opts)
5537 m = scmutil.match(ctx, (file_,), opts)
5535 if m.anypats() or len(m.files()) != 1:
5538 if m.anypats() or len(m.files()) != 1:
5536 raise error.Abort(_('can only specify an explicit filename'))
5539 raise error.Abort(_('can only specify an explicit filename'))
5537 file_ = m.files()[0]
5540 file_ = m.files()[0]
5538 filenodes = []
5541 filenodes = []
5539 for cp in ctx.parents():
5542 for cp in ctx.parents():
5540 if not cp:
5543 if not cp:
5541 continue
5544 continue
5542 try:
5545 try:
5543 filenodes.append(cp.filenode(file_))
5546 filenodes.append(cp.filenode(file_))
5544 except error.LookupError:
5547 except error.LookupError:
5545 pass
5548 pass
5546 if not filenodes:
5549 if not filenodes:
5547 raise error.Abort(_("'%s' not found in manifest!") % file_)
5550 raise error.Abort(_("'%s' not found in manifest!") % file_)
5548 p = []
5551 p = []
5549 for fn in filenodes:
5552 for fn in filenodes:
5550 fctx = repo.filectx(file_, fileid=fn)
5553 fctx = repo.filectx(file_, fileid=fn)
5551 p.append(fctx.node())
5554 p.append(fctx.node())
5552 else:
5555 else:
5553 p = [cp.node() for cp in ctx.parents()]
5556 p = [cp.node() for cp in ctx.parents()]
5554
5557
5555 displayer = cmdutil.show_changeset(ui, repo, opts)
5558 displayer = cmdutil.show_changeset(ui, repo, opts)
5556 for n in p:
5559 for n in p:
5557 if n != nullid:
5560 if n != nullid:
5558 displayer.show(repo[n])
5561 displayer.show(repo[n])
5559 displayer.close()
5562 displayer.close()
5560
5563
5561 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5564 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5562 def paths(ui, repo, search=None, **opts):
5565 def paths(ui, repo, search=None, **opts):
5563 """show aliases for remote repositories
5566 """show aliases for remote repositories
5564
5567
5565 Show definition of symbolic path name NAME. If no name is given,
5568 Show definition of symbolic path name NAME. If no name is given,
5566 show definition of all available names.
5569 show definition of all available names.
5567
5570
5568 Option -q/--quiet suppresses all output when searching for NAME
5571 Option -q/--quiet suppresses all output when searching for NAME
5569 and shows only the path names when listing all definitions.
5572 and shows only the path names when listing all definitions.
5570
5573
5571 Path names are defined in the [paths] section of your
5574 Path names are defined in the [paths] section of your
5572 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5575 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5573 repository, ``.hg/hgrc`` is used, too.
5576 repository, ``.hg/hgrc`` is used, too.
5574
5577
5575 The path names ``default`` and ``default-push`` have a special
5578 The path names ``default`` and ``default-push`` have a special
5576 meaning. When performing a push or pull operation, they are used
5579 meaning. When performing a push or pull operation, they are used
5577 as fallbacks if no location is specified on the command-line.
5580 as fallbacks if no location is specified on the command-line.
5578 When ``default-push`` is set, it will be used for push and
5581 When ``default-push`` is set, it will be used for push and
5579 ``default`` will be used for pull; otherwise ``default`` is used
5582 ``default`` will be used for pull; otherwise ``default`` is used
5580 as the fallback for both. When cloning a repository, the clone
5583 as the fallback for both. When cloning a repository, the clone
5581 source is written as ``default`` in ``.hg/hgrc``.
5584 source is written as ``default`` in ``.hg/hgrc``.
5582
5585
5583 .. note::
5586 .. note::
5584
5587
5585 ``default`` and ``default-push`` apply to all inbound (e.g.
5588 ``default`` and ``default-push`` apply to all inbound (e.g.
5586 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5589 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5587 and :hg:`bundle`) operations.
5590 and :hg:`bundle`) operations.
5588
5591
5589 See :hg:`help urls` for more information.
5592 See :hg:`help urls` for more information.
5590
5593
5591 Returns 0 on success.
5594 Returns 0 on success.
5592 """
5595 """
5593 if search:
5596 if search:
5594 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5597 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5595 if name == search]
5598 if name == search]
5596 else:
5599 else:
5597 pathitems = sorted(ui.paths.iteritems())
5600 pathitems = sorted(ui.paths.iteritems())
5598
5601
5599 fm = ui.formatter('paths', opts)
5602 fm = ui.formatter('paths', opts)
5600 if fm:
5603 if fm:
5601 hidepassword = str
5604 hidepassword = str
5602 else:
5605 else:
5603 hidepassword = util.hidepassword
5606 hidepassword = util.hidepassword
5604 if ui.quiet:
5607 if ui.quiet:
5605 namefmt = '%s\n'
5608 namefmt = '%s\n'
5606 else:
5609 else:
5607 namefmt = '%s = '
5610 namefmt = '%s = '
5608 showsubopts = not search and not ui.quiet
5611 showsubopts = not search and not ui.quiet
5609
5612
5610 for name, path in pathitems:
5613 for name, path in pathitems:
5611 fm.startitem()
5614 fm.startitem()
5612 fm.condwrite(not search, 'name', namefmt, name)
5615 fm.condwrite(not search, 'name', namefmt, name)
5613 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5616 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5614 for subopt, value in sorted(path.suboptions.items()):
5617 for subopt, value in sorted(path.suboptions.items()):
5615 assert subopt not in ('name', 'url')
5618 assert subopt not in ('name', 'url')
5616 if showsubopts:
5619 if showsubopts:
5617 fm.plain('%s:%s = ' % (name, subopt))
5620 fm.plain('%s:%s = ' % (name, subopt))
5618 fm.condwrite(showsubopts, subopt, '%s\n', value)
5621 fm.condwrite(showsubopts, subopt, '%s\n', value)
5619
5622
5620 fm.end()
5623 fm.end()
5621
5624
5622 if search and not pathitems:
5625 if search and not pathitems:
5623 if not ui.quiet:
5626 if not ui.quiet:
5624 ui.warn(_("not found!\n"))
5627 ui.warn(_("not found!\n"))
5625 return 1
5628 return 1
5626 else:
5629 else:
5627 return 0
5630 return 0
5628
5631
5629 @command('phase',
5632 @command('phase',
5630 [('p', 'public', False, _('set changeset phase to public')),
5633 [('p', 'public', False, _('set changeset phase to public')),
5631 ('d', 'draft', False, _('set changeset phase to draft')),
5634 ('d', 'draft', False, _('set changeset phase to draft')),
5632 ('s', 'secret', False, _('set changeset phase to secret')),
5635 ('s', 'secret', False, _('set changeset phase to secret')),
5633 ('f', 'force', False, _('allow to move boundary backward')),
5636 ('f', 'force', False, _('allow to move boundary backward')),
5634 ('r', 'rev', [], _('target revision'), _('REV')),
5637 ('r', 'rev', [], _('target revision'), _('REV')),
5635 ],
5638 ],
5636 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5639 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5637 def phase(ui, repo, *revs, **opts):
5640 def phase(ui, repo, *revs, **opts):
5638 """set or show the current phase name
5641 """set or show the current phase name
5639
5642
5640 With no argument, show the phase name of the current revision(s).
5643 With no argument, show the phase name of the current revision(s).
5641
5644
5642 With one of -p/--public, -d/--draft or -s/--secret, change the
5645 With one of -p/--public, -d/--draft or -s/--secret, change the
5643 phase value of the specified revisions.
5646 phase value of the specified revisions.
5644
5647
5645 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5648 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5646 lower phase to an higher phase. Phases are ordered as follows::
5649 lower phase to an higher phase. Phases are ordered as follows::
5647
5650
5648 public < draft < secret
5651 public < draft < secret
5649
5652
5650 Returns 0 on success, 1 if some phases could not be changed.
5653 Returns 0 on success, 1 if some phases could not be changed.
5651
5654
5652 (For more information about the phases concept, see :hg:`help phases`.)
5655 (For more information about the phases concept, see :hg:`help phases`.)
5653 """
5656 """
5654 # search for a unique phase argument
5657 # search for a unique phase argument
5655 targetphase = None
5658 targetphase = None
5656 for idx, name in enumerate(phases.phasenames):
5659 for idx, name in enumerate(phases.phasenames):
5657 if opts[name]:
5660 if opts[name]:
5658 if targetphase is not None:
5661 if targetphase is not None:
5659 raise error.Abort(_('only one phase can be specified'))
5662 raise error.Abort(_('only one phase can be specified'))
5660 targetphase = idx
5663 targetphase = idx
5661
5664
5662 # look for specified revision
5665 # look for specified revision
5663 revs = list(revs)
5666 revs = list(revs)
5664 revs.extend(opts['rev'])
5667 revs.extend(opts['rev'])
5665 if not revs:
5668 if not revs:
5666 # display both parents as the second parent phase can influence
5669 # display both parents as the second parent phase can influence
5667 # the phase of a merge commit
5670 # the phase of a merge commit
5668 revs = [c.rev() for c in repo[None].parents()]
5671 revs = [c.rev() for c in repo[None].parents()]
5669
5672
5670 revs = scmutil.revrange(repo, revs)
5673 revs = scmutil.revrange(repo, revs)
5671
5674
5672 lock = None
5675 lock = None
5673 ret = 0
5676 ret = 0
5674 if targetphase is None:
5677 if targetphase is None:
5675 # display
5678 # display
5676 for r in revs:
5679 for r in revs:
5677 ctx = repo[r]
5680 ctx = repo[r]
5678 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5681 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5679 else:
5682 else:
5680 tr = None
5683 tr = None
5681 lock = repo.lock()
5684 lock = repo.lock()
5682 try:
5685 try:
5683 tr = repo.transaction("phase")
5686 tr = repo.transaction("phase")
5684 # set phase
5687 # set phase
5685 if not revs:
5688 if not revs:
5686 raise error.Abort(_('empty revision set'))
5689 raise error.Abort(_('empty revision set'))
5687 nodes = [repo[r].node() for r in revs]
5690 nodes = [repo[r].node() for r in revs]
5688 # moving revision from public to draft may hide them
5691 # moving revision from public to draft may hide them
5689 # We have to check result on an unfiltered repository
5692 # We have to check result on an unfiltered repository
5690 unfi = repo.unfiltered()
5693 unfi = repo.unfiltered()
5691 getphase = unfi._phasecache.phase
5694 getphase = unfi._phasecache.phase
5692 olddata = [getphase(unfi, r) for r in unfi]
5695 olddata = [getphase(unfi, r) for r in unfi]
5693 phases.advanceboundary(repo, tr, targetphase, nodes)
5696 phases.advanceboundary(repo, tr, targetphase, nodes)
5694 if opts['force']:
5697 if opts['force']:
5695 phases.retractboundary(repo, tr, targetphase, nodes)
5698 phases.retractboundary(repo, tr, targetphase, nodes)
5696 tr.close()
5699 tr.close()
5697 finally:
5700 finally:
5698 if tr is not None:
5701 if tr is not None:
5699 tr.release()
5702 tr.release()
5700 lock.release()
5703 lock.release()
5701 getphase = unfi._phasecache.phase
5704 getphase = unfi._phasecache.phase
5702 newdata = [getphase(unfi, r) for r in unfi]
5705 newdata = [getphase(unfi, r) for r in unfi]
5703 changes = sum(newdata[r] != olddata[r] for r in unfi)
5706 changes = sum(newdata[r] != olddata[r] for r in unfi)
5704 cl = unfi.changelog
5707 cl = unfi.changelog
5705 rejected = [n for n in nodes
5708 rejected = [n for n in nodes
5706 if newdata[cl.rev(n)] < targetphase]
5709 if newdata[cl.rev(n)] < targetphase]
5707 if rejected:
5710 if rejected:
5708 ui.warn(_('cannot move %i changesets to a higher '
5711 ui.warn(_('cannot move %i changesets to a higher '
5709 'phase, use --force\n') % len(rejected))
5712 'phase, use --force\n') % len(rejected))
5710 ret = 1
5713 ret = 1
5711 if changes:
5714 if changes:
5712 msg = _('phase changed for %i changesets\n') % changes
5715 msg = _('phase changed for %i changesets\n') % changes
5713 if ret:
5716 if ret:
5714 ui.status(msg)
5717 ui.status(msg)
5715 else:
5718 else:
5716 ui.note(msg)
5719 ui.note(msg)
5717 else:
5720 else:
5718 ui.warn(_('no phases changed\n'))
5721 ui.warn(_('no phases changed\n'))
5719 return ret
5722 return ret
5720
5723
5721 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5724 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5722 """Run after a changegroup has been added via pull/unbundle
5725 """Run after a changegroup has been added via pull/unbundle
5723
5726
5724 This takes arguments below:
5727 This takes arguments below:
5725
5728
5726 :modheads: change of heads by pull/unbundle
5729 :modheads: change of heads by pull/unbundle
5727 :optupdate: updating working directory is needed or not
5730 :optupdate: updating working directory is needed or not
5728 :checkout: update destination revision (or None to default destination)
5731 :checkout: update destination revision (or None to default destination)
5729 :brev: a name, which might be a bookmark to be activated after updating
5732 :brev: a name, which might be a bookmark to be activated after updating
5730 """
5733 """
5731 if modheads == 0:
5734 if modheads == 0:
5732 return
5735 return
5733 if optupdate:
5736 if optupdate:
5734 try:
5737 try:
5735 return hg.updatetotally(ui, repo, checkout, brev)
5738 return hg.updatetotally(ui, repo, checkout, brev)
5736 except error.UpdateAbort as inst:
5739 except error.UpdateAbort as inst:
5737 msg = _("not updating: %s") % str(inst)
5740 msg = _("not updating: %s") % str(inst)
5738 hint = inst.hint
5741 hint = inst.hint
5739 raise error.UpdateAbort(msg, hint=hint)
5742 raise error.UpdateAbort(msg, hint=hint)
5740 if modheads > 1:
5743 if modheads > 1:
5741 currentbranchheads = len(repo.branchheads())
5744 currentbranchheads = len(repo.branchheads())
5742 if currentbranchheads == modheads:
5745 if currentbranchheads == modheads:
5743 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5746 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5744 elif currentbranchheads > 1:
5747 elif currentbranchheads > 1:
5745 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5748 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5746 "merge)\n"))
5749 "merge)\n"))
5747 else:
5750 else:
5748 ui.status(_("(run 'hg heads' to see heads)\n"))
5751 ui.status(_("(run 'hg heads' to see heads)\n"))
5749 else:
5752 else:
5750 ui.status(_("(run 'hg update' to get a working copy)\n"))
5753 ui.status(_("(run 'hg update' to get a working copy)\n"))
5751
5754
5752 @command('^pull',
5755 @command('^pull',
5753 [('u', 'update', None,
5756 [('u', 'update', None,
5754 _('update to new branch head if changesets were pulled')),
5757 _('update to new branch head if changesets were pulled')),
5755 ('f', 'force', None, _('run even when remote repository is unrelated')),
5758 ('f', 'force', None, _('run even when remote repository is unrelated')),
5756 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5759 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5757 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5760 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5758 ('b', 'branch', [], _('a specific branch you would like to pull'),
5761 ('b', 'branch', [], _('a specific branch you would like to pull'),
5759 _('BRANCH')),
5762 _('BRANCH')),
5760 ] + remoteopts,
5763 ] + remoteopts,
5761 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5764 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5762 def pull(ui, repo, source="default", **opts):
5765 def pull(ui, repo, source="default", **opts):
5763 """pull changes from the specified source
5766 """pull changes from the specified source
5764
5767
5765 Pull changes from a remote repository to a local one.
5768 Pull changes from a remote repository to a local one.
5766
5769
5767 This finds all changes from the repository at the specified path
5770 This finds all changes from the repository at the specified path
5768 or URL and adds them to a local repository (the current one unless
5771 or URL and adds them to a local repository (the current one unless
5769 -R is specified). By default, this does not update the copy of the
5772 -R is specified). By default, this does not update the copy of the
5770 project in the working directory.
5773 project in the working directory.
5771
5774
5772 Use :hg:`incoming` if you want to see what would have been added
5775 Use :hg:`incoming` if you want to see what would have been added
5773 by a pull at the time you issued this command. If you then decide
5776 by a pull at the time you issued this command. If you then decide
5774 to add those changes to the repository, you should use :hg:`pull
5777 to add those changes to the repository, you should use :hg:`pull
5775 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5778 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5776
5779
5777 If SOURCE is omitted, the 'default' path will be used.
5780 If SOURCE is omitted, the 'default' path will be used.
5778 See :hg:`help urls` for more information.
5781 See :hg:`help urls` for more information.
5779
5782
5780 Specifying bookmark as ``.`` is equivalent to specifying the active
5783 Specifying bookmark as ``.`` is equivalent to specifying the active
5781 bookmark's name.
5784 bookmark's name.
5782
5785
5783 Returns 0 on success, 1 if an update had unresolved files.
5786 Returns 0 on success, 1 if an update had unresolved files.
5784 """
5787 """
5785 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5788 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5786 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5789 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5787 other = hg.peer(repo, opts, source)
5790 other = hg.peer(repo, opts, source)
5788 try:
5791 try:
5789 revs, checkout = hg.addbranchrevs(repo, other, branches,
5792 revs, checkout = hg.addbranchrevs(repo, other, branches,
5790 opts.get('rev'))
5793 opts.get('rev'))
5791
5794
5792
5795
5793 pullopargs = {}
5796 pullopargs = {}
5794 if opts.get('bookmark'):
5797 if opts.get('bookmark'):
5795 if not revs:
5798 if not revs:
5796 revs = []
5799 revs = []
5797 # The list of bookmark used here is not the one used to actually
5800 # The list of bookmark used here is not the one used to actually
5798 # update the bookmark name. This can result in the revision pulled
5801 # update the bookmark name. This can result in the revision pulled
5799 # not ending up with the name of the bookmark because of a race
5802 # not ending up with the name of the bookmark because of a race
5800 # condition on the server. (See issue 4689 for details)
5803 # condition on the server. (See issue 4689 for details)
5801 remotebookmarks = other.listkeys('bookmarks')
5804 remotebookmarks = other.listkeys('bookmarks')
5802 pullopargs['remotebookmarks'] = remotebookmarks
5805 pullopargs['remotebookmarks'] = remotebookmarks
5803 for b in opts['bookmark']:
5806 for b in opts['bookmark']:
5804 b = repo._bookmarks.expandname(b)
5807 b = repo._bookmarks.expandname(b)
5805 if b not in remotebookmarks:
5808 if b not in remotebookmarks:
5806 raise error.Abort(_('remote bookmark %s not found!') % b)
5809 raise error.Abort(_('remote bookmark %s not found!') % b)
5807 revs.append(remotebookmarks[b])
5810 revs.append(remotebookmarks[b])
5808
5811
5809 if revs:
5812 if revs:
5810 try:
5813 try:
5811 # When 'rev' is a bookmark name, we cannot guarantee that it
5814 # When 'rev' is a bookmark name, we cannot guarantee that it
5812 # will be updated with that name because of a race condition
5815 # will be updated with that name because of a race condition
5813 # server side. (See issue 4689 for details)
5816 # server side. (See issue 4689 for details)
5814 oldrevs = revs
5817 oldrevs = revs
5815 revs = [] # actually, nodes
5818 revs = [] # actually, nodes
5816 for r in oldrevs:
5819 for r in oldrevs:
5817 node = other.lookup(r)
5820 node = other.lookup(r)
5818 revs.append(node)
5821 revs.append(node)
5819 if r == checkout:
5822 if r == checkout:
5820 checkout = node
5823 checkout = node
5821 except error.CapabilityError:
5824 except error.CapabilityError:
5822 err = _("other repository doesn't support revision lookup, "
5825 err = _("other repository doesn't support revision lookup, "
5823 "so a rev cannot be specified.")
5826 "so a rev cannot be specified.")
5824 raise error.Abort(err)
5827 raise error.Abort(err)
5825
5828
5826 pullopargs.update(opts.get('opargs', {}))
5829 pullopargs.update(opts.get('opargs', {}))
5827 modheads = exchange.pull(repo, other, heads=revs,
5830 modheads = exchange.pull(repo, other, heads=revs,
5828 force=opts.get('force'),
5831 force=opts.get('force'),
5829 bookmarks=opts.get('bookmark', ()),
5832 bookmarks=opts.get('bookmark', ()),
5830 opargs=pullopargs).cgresult
5833 opargs=pullopargs).cgresult
5831
5834
5832 # brev is a name, which might be a bookmark to be activated at
5835 # brev is a name, which might be a bookmark to be activated at
5833 # the end of the update. In other words, it is an explicit
5836 # the end of the update. In other words, it is an explicit
5834 # destination of the update
5837 # destination of the update
5835 brev = None
5838 brev = None
5836
5839
5837 if checkout:
5840 if checkout:
5838 checkout = str(repo.changelog.rev(checkout))
5841 checkout = str(repo.changelog.rev(checkout))
5839
5842
5840 # order below depends on implementation of
5843 # order below depends on implementation of
5841 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5844 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5842 # because 'checkout' is determined without it.
5845 # because 'checkout' is determined without it.
5843 if opts.get('rev'):
5846 if opts.get('rev'):
5844 brev = opts['rev'][0]
5847 brev = opts['rev'][0]
5845 elif opts.get('branch'):
5848 elif opts.get('branch'):
5846 brev = opts['branch'][0]
5849 brev = opts['branch'][0]
5847 else:
5850 else:
5848 brev = branches[0]
5851 brev = branches[0]
5849 repo._subtoppath = source
5852 repo._subtoppath = source
5850 try:
5853 try:
5851 ret = postincoming(ui, repo, modheads, opts.get('update'),
5854 ret = postincoming(ui, repo, modheads, opts.get('update'),
5852 checkout, brev)
5855 checkout, brev)
5853
5856
5854 finally:
5857 finally:
5855 del repo._subtoppath
5858 del repo._subtoppath
5856
5859
5857 finally:
5860 finally:
5858 other.close()
5861 other.close()
5859 return ret
5862 return ret
5860
5863
5861 @command('^push',
5864 @command('^push',
5862 [('f', 'force', None, _('force push')),
5865 [('f', 'force', None, _('force push')),
5863 ('r', 'rev', [],
5866 ('r', 'rev', [],
5864 _('a changeset intended to be included in the destination'),
5867 _('a changeset intended to be included in the destination'),
5865 _('REV')),
5868 _('REV')),
5866 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5869 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5867 ('b', 'branch', [],
5870 ('b', 'branch', [],
5868 _('a specific branch you would like to push'), _('BRANCH')),
5871 _('a specific branch you would like to push'), _('BRANCH')),
5869 ('', 'new-branch', False, _('allow pushing a new branch')),
5872 ('', 'new-branch', False, _('allow pushing a new branch')),
5870 ] + remoteopts,
5873 ] + remoteopts,
5871 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5874 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5872 def push(ui, repo, dest=None, **opts):
5875 def push(ui, repo, dest=None, **opts):
5873 """push changes to the specified destination
5876 """push changes to the specified destination
5874
5877
5875 Push changesets from the local repository to the specified
5878 Push changesets from the local repository to the specified
5876 destination.
5879 destination.
5877
5880
5878 This operation is symmetrical to pull: it is identical to a pull
5881 This operation is symmetrical to pull: it is identical to a pull
5879 in the destination repository from the current one.
5882 in the destination repository from the current one.
5880
5883
5881 By default, push will not allow creation of new heads at the
5884 By default, push will not allow creation of new heads at the
5882 destination, since multiple heads would make it unclear which head
5885 destination, since multiple heads would make it unclear which head
5883 to use. In this situation, it is recommended to pull and merge
5886 to use. In this situation, it is recommended to pull and merge
5884 before pushing.
5887 before pushing.
5885
5888
5886 Use --new-branch if you want to allow push to create a new named
5889 Use --new-branch if you want to allow push to create a new named
5887 branch that is not present at the destination. This allows you to
5890 branch that is not present at the destination. This allows you to
5888 only create a new branch without forcing other changes.
5891 only create a new branch without forcing other changes.
5889
5892
5890 .. note::
5893 .. note::
5891
5894
5892 Extra care should be taken with the -f/--force option,
5895 Extra care should be taken with the -f/--force option,
5893 which will push all new heads on all branches, an action which will
5896 which will push all new heads on all branches, an action which will
5894 almost always cause confusion for collaborators.
5897 almost always cause confusion for collaborators.
5895
5898
5896 If -r/--rev is used, the specified revision and all its ancestors
5899 If -r/--rev is used, the specified revision and all its ancestors
5897 will be pushed to the remote repository.
5900 will be pushed to the remote repository.
5898
5901
5899 If -B/--bookmark is used, the specified bookmarked revision, its
5902 If -B/--bookmark is used, the specified bookmarked revision, its
5900 ancestors, and the bookmark will be pushed to the remote
5903 ancestors, and the bookmark will be pushed to the remote
5901 repository. Specifying ``.`` is equivalent to specifying the active
5904 repository. Specifying ``.`` is equivalent to specifying the active
5902 bookmark's name.
5905 bookmark's name.
5903
5906
5904 Please see :hg:`help urls` for important details about ``ssh://``
5907 Please see :hg:`help urls` for important details about ``ssh://``
5905 URLs. If DESTINATION is omitted, a default path will be used.
5908 URLs. If DESTINATION is omitted, a default path will be used.
5906
5909
5907 Returns 0 if push was successful, 1 if nothing to push.
5910 Returns 0 if push was successful, 1 if nothing to push.
5908 """
5911 """
5909
5912
5910 if opts.get('bookmark'):
5913 if opts.get('bookmark'):
5911 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5914 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5912 for b in opts['bookmark']:
5915 for b in opts['bookmark']:
5913 # translate -B options to -r so changesets get pushed
5916 # translate -B options to -r so changesets get pushed
5914 b = repo._bookmarks.expandname(b)
5917 b = repo._bookmarks.expandname(b)
5915 if b in repo._bookmarks:
5918 if b in repo._bookmarks:
5916 opts.setdefault('rev', []).append(b)
5919 opts.setdefault('rev', []).append(b)
5917 else:
5920 else:
5918 # if we try to push a deleted bookmark, translate it to null
5921 # if we try to push a deleted bookmark, translate it to null
5919 # this lets simultaneous -r, -b options continue working
5922 # this lets simultaneous -r, -b options continue working
5920 opts.setdefault('rev', []).append("null")
5923 opts.setdefault('rev', []).append("null")
5921
5924
5922 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5925 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5923 if not path:
5926 if not path:
5924 raise error.Abort(_('default repository not configured!'),
5927 raise error.Abort(_('default repository not configured!'),
5925 hint=_('see the "path" section in "hg help config"'))
5928 hint=_('see the "path" section in "hg help config"'))
5926 dest = path.pushloc or path.loc
5929 dest = path.pushloc or path.loc
5927 branches = (path.branch, opts.get('branch') or [])
5930 branches = (path.branch, opts.get('branch') or [])
5928 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5931 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5929 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5932 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5930 other = hg.peer(repo, opts, dest)
5933 other = hg.peer(repo, opts, dest)
5931
5934
5932 if revs:
5935 if revs:
5933 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5936 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5934 if not revs:
5937 if not revs:
5935 raise error.Abort(_("specified revisions evaluate to an empty set"),
5938 raise error.Abort(_("specified revisions evaluate to an empty set"),
5936 hint=_("use different revision arguments"))
5939 hint=_("use different revision arguments"))
5937 elif path.pushrev:
5940 elif path.pushrev:
5938 # It doesn't make any sense to specify ancestor revisions. So limit
5941 # It doesn't make any sense to specify ancestor revisions. So limit
5939 # to DAG heads to make discovery simpler.
5942 # to DAG heads to make discovery simpler.
5940 expr = revset.formatspec('heads(%r)', path.pushrev)
5943 expr = revset.formatspec('heads(%r)', path.pushrev)
5941 revs = scmutil.revrange(repo, [expr])
5944 revs = scmutil.revrange(repo, [expr])
5942 revs = [repo[rev].node() for rev in revs]
5945 revs = [repo[rev].node() for rev in revs]
5943 if not revs:
5946 if not revs:
5944 raise error.Abort(_('default push revset for path evaluates to an '
5947 raise error.Abort(_('default push revset for path evaluates to an '
5945 'empty set'))
5948 'empty set'))
5946
5949
5947 repo._subtoppath = dest
5950 repo._subtoppath = dest
5948 try:
5951 try:
5949 # push subrepos depth-first for coherent ordering
5952 # push subrepos depth-first for coherent ordering
5950 c = repo['']
5953 c = repo['']
5951 subs = c.substate # only repos that are committed
5954 subs = c.substate # only repos that are committed
5952 for s in sorted(subs):
5955 for s in sorted(subs):
5953 result = c.sub(s).push(opts)
5956 result = c.sub(s).push(opts)
5954 if result == 0:
5957 if result == 0:
5955 return not result
5958 return not result
5956 finally:
5959 finally:
5957 del repo._subtoppath
5960 del repo._subtoppath
5958 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5961 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5959 newbranch=opts.get('new_branch'),
5962 newbranch=opts.get('new_branch'),
5960 bookmarks=opts.get('bookmark', ()),
5963 bookmarks=opts.get('bookmark', ()),
5961 opargs=opts.get('opargs'))
5964 opargs=opts.get('opargs'))
5962
5965
5963 result = not pushop.cgresult
5966 result = not pushop.cgresult
5964
5967
5965 if pushop.bkresult is not None:
5968 if pushop.bkresult is not None:
5966 if pushop.bkresult == 2:
5969 if pushop.bkresult == 2:
5967 result = 2
5970 result = 2
5968 elif not result and pushop.bkresult:
5971 elif not result and pushop.bkresult:
5969 result = 2
5972 result = 2
5970
5973
5971 return result
5974 return result
5972
5975
5973 @command('recover', [])
5976 @command('recover', [])
5974 def recover(ui, repo):
5977 def recover(ui, repo):
5975 """roll back an interrupted transaction
5978 """roll back an interrupted transaction
5976
5979
5977 Recover from an interrupted commit or pull.
5980 Recover from an interrupted commit or pull.
5978
5981
5979 This command tries to fix the repository status after an
5982 This command tries to fix the repository status after an
5980 interrupted operation. It should only be necessary when Mercurial
5983 interrupted operation. It should only be necessary when Mercurial
5981 suggests it.
5984 suggests it.
5982
5985
5983 Returns 0 if successful, 1 if nothing to recover or verify fails.
5986 Returns 0 if successful, 1 if nothing to recover or verify fails.
5984 """
5987 """
5985 if repo.recover():
5988 if repo.recover():
5986 return hg.verify(repo)
5989 return hg.verify(repo)
5987 return 1
5990 return 1
5988
5991
5989 @command('^remove|rm',
5992 @command('^remove|rm',
5990 [('A', 'after', None, _('record delete for missing files')),
5993 [('A', 'after', None, _('record delete for missing files')),
5991 ('f', 'force', None,
5994 ('f', 'force', None,
5992 _('forget added files, delete modified files')),
5995 _('forget added files, delete modified files')),
5993 ] + subrepoopts + walkopts,
5996 ] + subrepoopts + walkopts,
5994 _('[OPTION]... FILE...'),
5997 _('[OPTION]... FILE...'),
5995 inferrepo=True)
5998 inferrepo=True)
5996 def remove(ui, repo, *pats, **opts):
5999 def remove(ui, repo, *pats, **opts):
5997 """remove the specified files on the next commit
6000 """remove the specified files on the next commit
5998
6001
5999 Schedule the indicated files for removal from the current branch.
6002 Schedule the indicated files for removal from the current branch.
6000
6003
6001 This command schedules the files to be removed at the next commit.
6004 This command schedules the files to be removed at the next commit.
6002 To undo a remove before that, see :hg:`revert`. To undo added
6005 To undo a remove before that, see :hg:`revert`. To undo added
6003 files, see :hg:`forget`.
6006 files, see :hg:`forget`.
6004
6007
6005 .. container:: verbose
6008 .. container:: verbose
6006
6009
6007 -A/--after can be used to remove only files that have already
6010 -A/--after can be used to remove only files that have already
6008 been deleted, -f/--force can be used to force deletion, and -Af
6011 been deleted, -f/--force can be used to force deletion, and -Af
6009 can be used to remove files from the next revision without
6012 can be used to remove files from the next revision without
6010 deleting them from the working directory.
6013 deleting them from the working directory.
6011
6014
6012 The following table details the behavior of remove for different
6015 The following table details the behavior of remove for different
6013 file states (columns) and option combinations (rows). The file
6016 file states (columns) and option combinations (rows). The file
6014 states are Added [A], Clean [C], Modified [M] and Missing [!]
6017 states are Added [A], Clean [C], Modified [M] and Missing [!]
6015 (as reported by :hg:`status`). The actions are Warn, Remove
6018 (as reported by :hg:`status`). The actions are Warn, Remove
6016 (from branch) and Delete (from disk):
6019 (from branch) and Delete (from disk):
6017
6020
6018 ========= == == == ==
6021 ========= == == == ==
6019 opt/state A C M !
6022 opt/state A C M !
6020 ========= == == == ==
6023 ========= == == == ==
6021 none W RD W R
6024 none W RD W R
6022 -f R RD RD R
6025 -f R RD RD R
6023 -A W W W R
6026 -A W W W R
6024 -Af R R R R
6027 -Af R R R R
6025 ========= == == == ==
6028 ========= == == == ==
6026
6029
6027 .. note::
6030 .. note::
6028
6031
6029 :hg:`remove` never deletes files in Added [A] state from the
6032 :hg:`remove` never deletes files in Added [A] state from the
6030 working directory, not even if ``--force`` is specified.
6033 working directory, not even if ``--force`` is specified.
6031
6034
6032 Returns 0 on success, 1 if any warnings encountered.
6035 Returns 0 on success, 1 if any warnings encountered.
6033 """
6036 """
6034
6037
6035 after, force = opts.get('after'), opts.get('force')
6038 after, force = opts.get('after'), opts.get('force')
6036 if not pats and not after:
6039 if not pats and not after:
6037 raise error.Abort(_('no files specified'))
6040 raise error.Abort(_('no files specified'))
6038
6041
6039 m = scmutil.match(repo[None], pats, opts)
6042 m = scmutil.match(repo[None], pats, opts)
6040 subrepos = opts.get('subrepos')
6043 subrepos = opts.get('subrepos')
6041 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6044 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6042
6045
6043 @command('rename|move|mv',
6046 @command('rename|move|mv',
6044 [('A', 'after', None, _('record a rename that has already occurred')),
6047 [('A', 'after', None, _('record a rename that has already occurred')),
6045 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6048 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6046 ] + walkopts + dryrunopts,
6049 ] + walkopts + dryrunopts,
6047 _('[OPTION]... SOURCE... DEST'))
6050 _('[OPTION]... SOURCE... DEST'))
6048 def rename(ui, repo, *pats, **opts):
6051 def rename(ui, repo, *pats, **opts):
6049 """rename files; equivalent of copy + remove
6052 """rename files; equivalent of copy + remove
6050
6053
6051 Mark dest as copies of sources; mark sources for deletion. If dest
6054 Mark dest as copies of sources; mark sources for deletion. If dest
6052 is a directory, copies are put in that directory. If dest is a
6055 is a directory, copies are put in that directory. If dest is a
6053 file, there can only be one source.
6056 file, there can only be one source.
6054
6057
6055 By default, this command copies the contents of files as they
6058 By default, this command copies the contents of files as they
6056 exist in the working directory. If invoked with -A/--after, the
6059 exist in the working directory. If invoked with -A/--after, the
6057 operation is recorded, but no copying is performed.
6060 operation is recorded, but no copying is performed.
6058
6061
6059 This command takes effect at the next commit. To undo a rename
6062 This command takes effect at the next commit. To undo a rename
6060 before that, see :hg:`revert`.
6063 before that, see :hg:`revert`.
6061
6064
6062 Returns 0 on success, 1 if errors are encountered.
6065 Returns 0 on success, 1 if errors are encountered.
6063 """
6066 """
6064 with repo.wlock(False):
6067 with repo.wlock(False):
6065 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6068 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6066
6069
6067 @command('resolve',
6070 @command('resolve',
6068 [('a', 'all', None, _('select all unresolved files')),
6071 [('a', 'all', None, _('select all unresolved files')),
6069 ('l', 'list', None, _('list state of files needing merge')),
6072 ('l', 'list', None, _('list state of files needing merge')),
6070 ('m', 'mark', None, _('mark files as resolved')),
6073 ('m', 'mark', None, _('mark files as resolved')),
6071 ('u', 'unmark', None, _('mark files as unresolved')),
6074 ('u', 'unmark', None, _('mark files as unresolved')),
6072 ('n', 'no-status', None, _('hide status prefix'))]
6075 ('n', 'no-status', None, _('hide status prefix'))]
6073 + mergetoolopts + walkopts + formatteropts,
6076 + mergetoolopts + walkopts + formatteropts,
6074 _('[OPTION]... [FILE]...'),
6077 _('[OPTION]... [FILE]...'),
6075 inferrepo=True)
6078 inferrepo=True)
6076 def resolve(ui, repo, *pats, **opts):
6079 def resolve(ui, repo, *pats, **opts):
6077 """redo merges or set/view the merge status of files
6080 """redo merges or set/view the merge status of files
6078
6081
6079 Merges with unresolved conflicts are often the result of
6082 Merges with unresolved conflicts are often the result of
6080 non-interactive merging using the ``internal:merge`` configuration
6083 non-interactive merging using the ``internal:merge`` configuration
6081 setting, or a command-line merge tool like ``diff3``. The resolve
6084 setting, or a command-line merge tool like ``diff3``. The resolve
6082 command is used to manage the files involved in a merge, after
6085 command is used to manage the files involved in a merge, after
6083 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6086 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6084 working directory must have two parents). See :hg:`help
6087 working directory must have two parents). See :hg:`help
6085 merge-tools` for information on configuring merge tools.
6088 merge-tools` for information on configuring merge tools.
6086
6089
6087 The resolve command can be used in the following ways:
6090 The resolve command can be used in the following ways:
6088
6091
6089 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6092 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6090 files, discarding any previous merge attempts. Re-merging is not
6093 files, discarding any previous merge attempts. Re-merging is not
6091 performed for files already marked as resolved. Use ``--all/-a``
6094 performed for files already marked as resolved. Use ``--all/-a``
6092 to select all unresolved files. ``--tool`` can be used to specify
6095 to select all unresolved files. ``--tool`` can be used to specify
6093 the merge tool used for the given files. It overrides the HGMERGE
6096 the merge tool used for the given files. It overrides the HGMERGE
6094 environment variable and your configuration files. Previous file
6097 environment variable and your configuration files. Previous file
6095 contents are saved with a ``.orig`` suffix.
6098 contents are saved with a ``.orig`` suffix.
6096
6099
6097 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6100 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6098 (e.g. after having manually fixed-up the files). The default is
6101 (e.g. after having manually fixed-up the files). The default is
6099 to mark all unresolved files.
6102 to mark all unresolved files.
6100
6103
6101 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6104 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6102 default is to mark all resolved files.
6105 default is to mark all resolved files.
6103
6106
6104 - :hg:`resolve -l`: list files which had or still have conflicts.
6107 - :hg:`resolve -l`: list files which had or still have conflicts.
6105 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6108 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6106
6109
6107 .. note::
6110 .. note::
6108
6111
6109 Mercurial will not let you commit files with unresolved merge
6112 Mercurial will not let you commit files with unresolved merge
6110 conflicts. You must use :hg:`resolve -m ...` before you can
6113 conflicts. You must use :hg:`resolve -m ...` before you can
6111 commit after a conflicting merge.
6114 commit after a conflicting merge.
6112
6115
6113 Returns 0 on success, 1 if any files fail a resolve attempt.
6116 Returns 0 on success, 1 if any files fail a resolve attempt.
6114 """
6117 """
6115
6118
6116 flaglist = 'all mark unmark list no_status'.split()
6119 flaglist = 'all mark unmark list no_status'.split()
6117 all, mark, unmark, show, nostatus = \
6120 all, mark, unmark, show, nostatus = \
6118 [opts.get(o) for o in flaglist]
6121 [opts.get(o) for o in flaglist]
6119
6122
6120 if (show and (mark or unmark)) or (mark and unmark):
6123 if (show and (mark or unmark)) or (mark and unmark):
6121 raise error.Abort(_("too many options specified"))
6124 raise error.Abort(_("too many options specified"))
6122 if pats and all:
6125 if pats and all:
6123 raise error.Abort(_("can't specify --all and patterns"))
6126 raise error.Abort(_("can't specify --all and patterns"))
6124 if not (all or pats or show or mark or unmark):
6127 if not (all or pats or show or mark or unmark):
6125 raise error.Abort(_('no files or directories specified'),
6128 raise error.Abort(_('no files or directories specified'),
6126 hint=('use --all to re-merge all unresolved files'))
6129 hint=('use --all to re-merge all unresolved files'))
6127
6130
6128 if show:
6131 if show:
6129 fm = ui.formatter('resolve', opts)
6132 fm = ui.formatter('resolve', opts)
6130 ms = mergemod.mergestate.read(repo)
6133 ms = mergemod.mergestate.read(repo)
6131 m = scmutil.match(repo[None], pats, opts)
6134 m = scmutil.match(repo[None], pats, opts)
6132 for f in ms:
6135 for f in ms:
6133 if not m(f):
6136 if not m(f):
6134 continue
6137 continue
6135 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6138 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6136 'd': 'driverresolved'}[ms[f]]
6139 'd': 'driverresolved'}[ms[f]]
6137 fm.startitem()
6140 fm.startitem()
6138 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6141 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6139 fm.write('path', '%s\n', f, label=l)
6142 fm.write('path', '%s\n', f, label=l)
6140 fm.end()
6143 fm.end()
6141 return 0
6144 return 0
6142
6145
6143 with repo.wlock():
6146 with repo.wlock():
6144 ms = mergemod.mergestate.read(repo)
6147 ms = mergemod.mergestate.read(repo)
6145
6148
6146 if not (ms.active() or repo.dirstate.p2() != nullid):
6149 if not (ms.active() or repo.dirstate.p2() != nullid):
6147 raise error.Abort(
6150 raise error.Abort(
6148 _('resolve command not applicable when not merging'))
6151 _('resolve command not applicable when not merging'))
6149
6152
6150 wctx = repo[None]
6153 wctx = repo[None]
6151
6154
6152 if ms.mergedriver and ms.mdstate() == 'u':
6155 if ms.mergedriver and ms.mdstate() == 'u':
6153 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6156 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6154 ms.commit()
6157 ms.commit()
6155 # allow mark and unmark to go through
6158 # allow mark and unmark to go through
6156 if not mark and not unmark and not proceed:
6159 if not mark and not unmark and not proceed:
6157 return 1
6160 return 1
6158
6161
6159 m = scmutil.match(wctx, pats, opts)
6162 m = scmutil.match(wctx, pats, opts)
6160 ret = 0
6163 ret = 0
6161 didwork = False
6164 didwork = False
6162 runconclude = False
6165 runconclude = False
6163
6166
6164 tocomplete = []
6167 tocomplete = []
6165 for f in ms:
6168 for f in ms:
6166 if not m(f):
6169 if not m(f):
6167 continue
6170 continue
6168
6171
6169 didwork = True
6172 didwork = True
6170
6173
6171 # don't let driver-resolved files be marked, and run the conclude
6174 # don't let driver-resolved files be marked, and run the conclude
6172 # step if asked to resolve
6175 # step if asked to resolve
6173 if ms[f] == "d":
6176 if ms[f] == "d":
6174 exact = m.exact(f)
6177 exact = m.exact(f)
6175 if mark:
6178 if mark:
6176 if exact:
6179 if exact:
6177 ui.warn(_('not marking %s as it is driver-resolved\n')
6180 ui.warn(_('not marking %s as it is driver-resolved\n')
6178 % f)
6181 % f)
6179 elif unmark:
6182 elif unmark:
6180 if exact:
6183 if exact:
6181 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6184 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6182 % f)
6185 % f)
6183 else:
6186 else:
6184 runconclude = True
6187 runconclude = True
6185 continue
6188 continue
6186
6189
6187 if mark:
6190 if mark:
6188 ms.mark(f, "r")
6191 ms.mark(f, "r")
6189 elif unmark:
6192 elif unmark:
6190 ms.mark(f, "u")
6193 ms.mark(f, "u")
6191 else:
6194 else:
6192 # backup pre-resolve (merge uses .orig for its own purposes)
6195 # backup pre-resolve (merge uses .orig for its own purposes)
6193 a = repo.wjoin(f)
6196 a = repo.wjoin(f)
6194 try:
6197 try:
6195 util.copyfile(a, a + ".resolve")
6198 util.copyfile(a, a + ".resolve")
6196 except (IOError, OSError) as inst:
6199 except (IOError, OSError) as inst:
6197 if inst.errno != errno.ENOENT:
6200 if inst.errno != errno.ENOENT:
6198 raise
6201 raise
6199
6202
6200 try:
6203 try:
6201 # preresolve file
6204 # preresolve file
6202 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6205 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6203 'resolve')
6206 'resolve')
6204 complete, r = ms.preresolve(f, wctx)
6207 complete, r = ms.preresolve(f, wctx)
6205 if not complete:
6208 if not complete:
6206 tocomplete.append(f)
6209 tocomplete.append(f)
6207 elif r:
6210 elif r:
6208 ret = 1
6211 ret = 1
6209 finally:
6212 finally:
6210 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6213 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6211 ms.commit()
6214 ms.commit()
6212
6215
6213 # replace filemerge's .orig file with our resolve file, but only
6216 # replace filemerge's .orig file with our resolve file, but only
6214 # for merges that are complete
6217 # for merges that are complete
6215 if complete:
6218 if complete:
6216 try:
6219 try:
6217 util.rename(a + ".resolve",
6220 util.rename(a + ".resolve",
6218 scmutil.origpath(ui, repo, a))
6221 scmutil.origpath(ui, repo, a))
6219 except OSError as inst:
6222 except OSError as inst:
6220 if inst.errno != errno.ENOENT:
6223 if inst.errno != errno.ENOENT:
6221 raise
6224 raise
6222
6225
6223 for f in tocomplete:
6226 for f in tocomplete:
6224 try:
6227 try:
6225 # resolve file
6228 # resolve file
6226 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6229 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6227 'resolve')
6230 'resolve')
6228 r = ms.resolve(f, wctx)
6231 r = ms.resolve(f, wctx)
6229 if r:
6232 if r:
6230 ret = 1
6233 ret = 1
6231 finally:
6234 finally:
6232 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6235 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6233 ms.commit()
6236 ms.commit()
6234
6237
6235 # replace filemerge's .orig file with our resolve file
6238 # replace filemerge's .orig file with our resolve file
6236 a = repo.wjoin(f)
6239 a = repo.wjoin(f)
6237 try:
6240 try:
6238 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6241 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6239 except OSError as inst:
6242 except OSError as inst:
6240 if inst.errno != errno.ENOENT:
6243 if inst.errno != errno.ENOENT:
6241 raise
6244 raise
6242
6245
6243 ms.commit()
6246 ms.commit()
6244 ms.recordactions()
6247 ms.recordactions()
6245
6248
6246 if not didwork and pats:
6249 if not didwork and pats:
6247 hint = None
6250 hint = None
6248 if not any([p for p in pats if p.find(':') >= 0]):
6251 if not any([p for p in pats if p.find(':') >= 0]):
6249 pats = ['path:%s' % p for p in pats]
6252 pats = ['path:%s' % p for p in pats]
6250 m = scmutil.match(wctx, pats, opts)
6253 m = scmutil.match(wctx, pats, opts)
6251 for f in ms:
6254 for f in ms:
6252 if not m(f):
6255 if not m(f):
6253 continue
6256 continue
6254 flags = ''.join(['-%s ' % o[0] for o in flaglist
6257 flags = ''.join(['-%s ' % o[0] for o in flaglist
6255 if opts.get(o)])
6258 if opts.get(o)])
6256 hint = _("(try: hg resolve %s%s)\n") % (
6259 hint = _("(try: hg resolve %s%s)\n") % (
6257 flags,
6260 flags,
6258 ' '.join(pats))
6261 ' '.join(pats))
6259 break
6262 break
6260 ui.warn(_("arguments do not match paths that need resolving\n"))
6263 ui.warn(_("arguments do not match paths that need resolving\n"))
6261 if hint:
6264 if hint:
6262 ui.warn(hint)
6265 ui.warn(hint)
6263 elif ms.mergedriver and ms.mdstate() != 's':
6266 elif ms.mergedriver and ms.mdstate() != 's':
6264 # run conclude step when either a driver-resolved file is requested
6267 # run conclude step when either a driver-resolved file is requested
6265 # or there are no driver-resolved files
6268 # or there are no driver-resolved files
6266 # we can't use 'ret' to determine whether any files are unresolved
6269 # we can't use 'ret' to determine whether any files are unresolved
6267 # because we might not have tried to resolve some
6270 # because we might not have tried to resolve some
6268 if ((runconclude or not list(ms.driverresolved()))
6271 if ((runconclude or not list(ms.driverresolved()))
6269 and not list(ms.unresolved())):
6272 and not list(ms.unresolved())):
6270 proceed = mergemod.driverconclude(repo, ms, wctx)
6273 proceed = mergemod.driverconclude(repo, ms, wctx)
6271 ms.commit()
6274 ms.commit()
6272 if not proceed:
6275 if not proceed:
6273 return 1
6276 return 1
6274
6277
6275 # Nudge users into finishing an unfinished operation
6278 # Nudge users into finishing an unfinished operation
6276 unresolvedf = list(ms.unresolved())
6279 unresolvedf = list(ms.unresolved())
6277 driverresolvedf = list(ms.driverresolved())
6280 driverresolvedf = list(ms.driverresolved())
6278 if not unresolvedf and not driverresolvedf:
6281 if not unresolvedf and not driverresolvedf:
6279 ui.status(_('(no more unresolved files)\n'))
6282 ui.status(_('(no more unresolved files)\n'))
6280 cmdutil.checkafterresolved(repo)
6283 cmdutil.checkafterresolved(repo)
6281 elif not unresolvedf:
6284 elif not unresolvedf:
6282 ui.status(_('(no more unresolved files -- '
6285 ui.status(_('(no more unresolved files -- '
6283 'run "hg resolve --all" to conclude)\n'))
6286 'run "hg resolve --all" to conclude)\n'))
6284
6287
6285 return ret
6288 return ret
6286
6289
6287 @command('revert',
6290 @command('revert',
6288 [('a', 'all', None, _('revert all changes when no arguments given')),
6291 [('a', 'all', None, _('revert all changes when no arguments given')),
6289 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6292 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6290 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6293 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6291 ('C', 'no-backup', None, _('do not save backup copies of files')),
6294 ('C', 'no-backup', None, _('do not save backup copies of files')),
6292 ('i', 'interactive', None,
6295 ('i', 'interactive', None,
6293 _('interactively select the changes (EXPERIMENTAL)')),
6296 _('interactively select the changes (EXPERIMENTAL)')),
6294 ] + walkopts + dryrunopts,
6297 ] + walkopts + dryrunopts,
6295 _('[OPTION]... [-r REV] [NAME]...'))
6298 _('[OPTION]... [-r REV] [NAME]...'))
6296 def revert(ui, repo, *pats, **opts):
6299 def revert(ui, repo, *pats, **opts):
6297 """restore files to their checkout state
6300 """restore files to their checkout state
6298
6301
6299 .. note::
6302 .. note::
6300
6303
6301 To check out earlier revisions, you should use :hg:`update REV`.
6304 To check out earlier revisions, you should use :hg:`update REV`.
6302 To cancel an uncommitted merge (and lose your changes),
6305 To cancel an uncommitted merge (and lose your changes),
6303 use :hg:`update --clean .`.
6306 use :hg:`update --clean .`.
6304
6307
6305 With no revision specified, revert the specified files or directories
6308 With no revision specified, revert the specified files or directories
6306 to the contents they had in the parent of the working directory.
6309 to the contents they had in the parent of the working directory.
6307 This restores the contents of files to an unmodified
6310 This restores the contents of files to an unmodified
6308 state and unschedules adds, removes, copies, and renames. If the
6311 state and unschedules adds, removes, copies, and renames. If the
6309 working directory has two parents, you must explicitly specify a
6312 working directory has two parents, you must explicitly specify a
6310 revision.
6313 revision.
6311
6314
6312 Using the -r/--rev or -d/--date options, revert the given files or
6315 Using the -r/--rev or -d/--date options, revert the given files or
6313 directories to their states as of a specific revision. Because
6316 directories to their states as of a specific revision. Because
6314 revert does not change the working directory parents, this will
6317 revert does not change the working directory parents, this will
6315 cause these files to appear modified. This can be helpful to "back
6318 cause these files to appear modified. This can be helpful to "back
6316 out" some or all of an earlier change. See :hg:`backout` for a
6319 out" some or all of an earlier change. See :hg:`backout` for a
6317 related method.
6320 related method.
6318
6321
6319 Modified files are saved with a .orig suffix before reverting.
6322 Modified files are saved with a .orig suffix before reverting.
6320 To disable these backups, use --no-backup. It is possible to store
6323 To disable these backups, use --no-backup. It is possible to store
6321 the backup files in a custom directory relative to the root of the
6324 the backup files in a custom directory relative to the root of the
6322 repository by setting the ``ui.origbackuppath`` configuration
6325 repository by setting the ``ui.origbackuppath`` configuration
6323 option.
6326 option.
6324
6327
6325 See :hg:`help dates` for a list of formats valid for -d/--date.
6328 See :hg:`help dates` for a list of formats valid for -d/--date.
6326
6329
6327 See :hg:`help backout` for a way to reverse the effect of an
6330 See :hg:`help backout` for a way to reverse the effect of an
6328 earlier changeset.
6331 earlier changeset.
6329
6332
6330 Returns 0 on success.
6333 Returns 0 on success.
6331 """
6334 """
6332
6335
6333 if opts.get("date"):
6336 if opts.get("date"):
6334 if opts.get("rev"):
6337 if opts.get("rev"):
6335 raise error.Abort(_("you can't specify a revision and a date"))
6338 raise error.Abort(_("you can't specify a revision and a date"))
6336 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6339 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6337
6340
6338 parent, p2 = repo.dirstate.parents()
6341 parent, p2 = repo.dirstate.parents()
6339 if not opts.get('rev') and p2 != nullid:
6342 if not opts.get('rev') and p2 != nullid:
6340 # revert after merge is a trap for new users (issue2915)
6343 # revert after merge is a trap for new users (issue2915)
6341 raise error.Abort(_('uncommitted merge with no revision specified'),
6344 raise error.Abort(_('uncommitted merge with no revision specified'),
6342 hint=_("use 'hg update' or see 'hg help revert'"))
6345 hint=_("use 'hg update' or see 'hg help revert'"))
6343
6346
6344 ctx = scmutil.revsingle(repo, opts.get('rev'))
6347 ctx = scmutil.revsingle(repo, opts.get('rev'))
6345
6348
6346 if (not (pats or opts.get('include') or opts.get('exclude') or
6349 if (not (pats or opts.get('include') or opts.get('exclude') or
6347 opts.get('all') or opts.get('interactive'))):
6350 opts.get('all') or opts.get('interactive'))):
6348 msg = _("no files or directories specified")
6351 msg = _("no files or directories specified")
6349 if p2 != nullid:
6352 if p2 != nullid:
6350 hint = _("uncommitted merge, use --all to discard all changes,"
6353 hint = _("uncommitted merge, use --all to discard all changes,"
6351 " or 'hg update -C .' to abort the merge")
6354 " or 'hg update -C .' to abort the merge")
6352 raise error.Abort(msg, hint=hint)
6355 raise error.Abort(msg, hint=hint)
6353 dirty = any(repo.status())
6356 dirty = any(repo.status())
6354 node = ctx.node()
6357 node = ctx.node()
6355 if node != parent:
6358 if node != parent:
6356 if dirty:
6359 if dirty:
6357 hint = _("uncommitted changes, use --all to discard all"
6360 hint = _("uncommitted changes, use --all to discard all"
6358 " changes, or 'hg update %s' to update") % ctx.rev()
6361 " changes, or 'hg update %s' to update") % ctx.rev()
6359 else:
6362 else:
6360 hint = _("use --all to revert all files,"
6363 hint = _("use --all to revert all files,"
6361 " or 'hg update %s' to update") % ctx.rev()
6364 " or 'hg update %s' to update") % ctx.rev()
6362 elif dirty:
6365 elif dirty:
6363 hint = _("uncommitted changes, use --all to discard all changes")
6366 hint = _("uncommitted changes, use --all to discard all changes")
6364 else:
6367 else:
6365 hint = _("use --all to revert all files")
6368 hint = _("use --all to revert all files")
6366 raise error.Abort(msg, hint=hint)
6369 raise error.Abort(msg, hint=hint)
6367
6370
6368 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6371 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6369
6372
6370 @command('rollback', dryrunopts +
6373 @command('rollback', dryrunopts +
6371 [('f', 'force', False, _('ignore safety measures'))])
6374 [('f', 'force', False, _('ignore safety measures'))])
6372 def rollback(ui, repo, **opts):
6375 def rollback(ui, repo, **opts):
6373 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6376 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6374
6377
6375 Please use :hg:`commit --amend` instead of rollback to correct
6378 Please use :hg:`commit --amend` instead of rollback to correct
6376 mistakes in the last commit.
6379 mistakes in the last commit.
6377
6380
6378 This command should be used with care. There is only one level of
6381 This command should be used with care. There is only one level of
6379 rollback, and there is no way to undo a rollback. It will also
6382 rollback, and there is no way to undo a rollback. It will also
6380 restore the dirstate at the time of the last transaction, losing
6383 restore the dirstate at the time of the last transaction, losing
6381 any dirstate changes since that time. This command does not alter
6384 any dirstate changes since that time. This command does not alter
6382 the working directory.
6385 the working directory.
6383
6386
6384 Transactions are used to encapsulate the effects of all commands
6387 Transactions are used to encapsulate the effects of all commands
6385 that create new changesets or propagate existing changesets into a
6388 that create new changesets or propagate existing changesets into a
6386 repository.
6389 repository.
6387
6390
6388 .. container:: verbose
6391 .. container:: verbose
6389
6392
6390 For example, the following commands are transactional, and their
6393 For example, the following commands are transactional, and their
6391 effects can be rolled back:
6394 effects can be rolled back:
6392
6395
6393 - commit
6396 - commit
6394 - import
6397 - import
6395 - pull
6398 - pull
6396 - push (with this repository as the destination)
6399 - push (with this repository as the destination)
6397 - unbundle
6400 - unbundle
6398
6401
6399 To avoid permanent data loss, rollback will refuse to rollback a
6402 To avoid permanent data loss, rollback will refuse to rollback a
6400 commit transaction if it isn't checked out. Use --force to
6403 commit transaction if it isn't checked out. Use --force to
6401 override this protection.
6404 override this protection.
6402
6405
6403 The rollback command can be entirely disabled by setting the
6406 The rollback command can be entirely disabled by setting the
6404 ``ui.rollback`` configuration setting to false. If you're here
6407 ``ui.rollback`` configuration setting to false. If you're here
6405 because you want to use rollback and it's disabled, you can
6408 because you want to use rollback and it's disabled, you can
6406 re-enable the command by setting ``ui.rollback`` to true.
6409 re-enable the command by setting ``ui.rollback`` to true.
6407
6410
6408 This command is not intended for use on public repositories. Once
6411 This command is not intended for use on public repositories. Once
6409 changes are visible for pull by other users, rolling a transaction
6412 changes are visible for pull by other users, rolling a transaction
6410 back locally is ineffective (someone else may already have pulled
6413 back locally is ineffective (someone else may already have pulled
6411 the changes). Furthermore, a race is possible with readers of the
6414 the changes). Furthermore, a race is possible with readers of the
6412 repository; for example an in-progress pull from the repository
6415 repository; for example an in-progress pull from the repository
6413 may fail if a rollback is performed.
6416 may fail if a rollback is performed.
6414
6417
6415 Returns 0 on success, 1 if no rollback data is available.
6418 Returns 0 on success, 1 if no rollback data is available.
6416 """
6419 """
6417 if not ui.configbool('ui', 'rollback', True):
6420 if not ui.configbool('ui', 'rollback', True):
6418 raise error.Abort(_('rollback is disabled because it is unsafe'),
6421 raise error.Abort(_('rollback is disabled because it is unsafe'),
6419 hint=('see `hg help -v rollback` for information'))
6422 hint=('see `hg help -v rollback` for information'))
6420 return repo.rollback(dryrun=opts.get('dry_run'),
6423 return repo.rollback(dryrun=opts.get('dry_run'),
6421 force=opts.get('force'))
6424 force=opts.get('force'))
6422
6425
6423 @command('root', [])
6426 @command('root', [])
6424 def root(ui, repo):
6427 def root(ui, repo):
6425 """print the root (top) of the current working directory
6428 """print the root (top) of the current working directory
6426
6429
6427 Print the root directory of the current repository.
6430 Print the root directory of the current repository.
6428
6431
6429 Returns 0 on success.
6432 Returns 0 on success.
6430 """
6433 """
6431 ui.write(repo.root + "\n")
6434 ui.write(repo.root + "\n")
6432
6435
6433 @command('^serve',
6436 @command('^serve',
6434 [('A', 'accesslog', '', _('name of access log file to write to'),
6437 [('A', 'accesslog', '', _('name of access log file to write to'),
6435 _('FILE')),
6438 _('FILE')),
6436 ('d', 'daemon', None, _('run server in background')),
6439 ('d', 'daemon', None, _('run server in background')),
6437 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6440 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6438 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6441 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6439 # use string type, then we can check if something was passed
6442 # use string type, then we can check if something was passed
6440 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6443 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6441 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6444 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6442 _('ADDR')),
6445 _('ADDR')),
6443 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6446 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6444 _('PREFIX')),
6447 _('PREFIX')),
6445 ('n', 'name', '',
6448 ('n', 'name', '',
6446 _('name to show in web pages (default: working directory)'), _('NAME')),
6449 _('name to show in web pages (default: working directory)'), _('NAME')),
6447 ('', 'web-conf', '',
6450 ('', 'web-conf', '',
6448 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6451 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6449 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6452 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6450 _('FILE')),
6453 _('FILE')),
6451 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6454 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6452 ('', 'stdio', None, _('for remote clients')),
6455 ('', 'stdio', None, _('for remote clients')),
6453 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6456 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6454 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6457 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6455 ('', 'style', '', _('template style to use'), _('STYLE')),
6458 ('', 'style', '', _('template style to use'), _('STYLE')),
6456 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6459 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6457 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6460 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6458 _('[OPTION]...'),
6461 _('[OPTION]...'),
6459 optionalrepo=True)
6462 optionalrepo=True)
6460 def serve(ui, repo, **opts):
6463 def serve(ui, repo, **opts):
6461 """start stand-alone webserver
6464 """start stand-alone webserver
6462
6465
6463 Start a local HTTP repository browser and pull server. You can use
6466 Start a local HTTP repository browser and pull server. You can use
6464 this for ad-hoc sharing and browsing of repositories. It is
6467 this for ad-hoc sharing and browsing of repositories. It is
6465 recommended to use a real web server to serve a repository for
6468 recommended to use a real web server to serve a repository for
6466 longer periods of time.
6469 longer periods of time.
6467
6470
6468 Please note that the server does not implement access control.
6471 Please note that the server does not implement access control.
6469 This means that, by default, anybody can read from the server and
6472 This means that, by default, anybody can read from the server and
6470 nobody can write to it by default. Set the ``web.allow_push``
6473 nobody can write to it by default. Set the ``web.allow_push``
6471 option to ``*`` to allow everybody to push to the server. You
6474 option to ``*`` to allow everybody to push to the server. You
6472 should use a real web server if you need to authenticate users.
6475 should use a real web server if you need to authenticate users.
6473
6476
6474 By default, the server logs accesses to stdout and errors to
6477 By default, the server logs accesses to stdout and errors to
6475 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6478 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6476 files.
6479 files.
6477
6480
6478 To have the server choose a free port number to listen on, specify
6481 To have the server choose a free port number to listen on, specify
6479 a port number of 0; in this case, the server will print the port
6482 a port number of 0; in this case, the server will print the port
6480 number it uses.
6483 number it uses.
6481
6484
6482 Returns 0 on success.
6485 Returns 0 on success.
6483 """
6486 """
6484
6487
6485 if opts["stdio"] and opts["cmdserver"]:
6488 if opts["stdio"] and opts["cmdserver"]:
6486 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6489 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6487
6490
6488 if opts["stdio"]:
6491 if opts["stdio"]:
6489 if repo is None:
6492 if repo is None:
6490 raise error.RepoError(_("there is no Mercurial repository here"
6493 raise error.RepoError(_("there is no Mercurial repository here"
6491 " (.hg not found)"))
6494 " (.hg not found)"))
6492 s = sshserver.sshserver(ui, repo)
6495 s = sshserver.sshserver(ui, repo)
6493 s.serve_forever()
6496 s.serve_forever()
6494
6497
6495 if opts["cmdserver"]:
6498 if opts["cmdserver"]:
6496 service = commandserver.createservice(ui, repo, opts)
6499 service = commandserver.createservice(ui, repo, opts)
6497 else:
6500 else:
6498 service = hgweb.createservice(ui, repo, opts)
6501 service = hgweb.createservice(ui, repo, opts)
6499 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6502 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6500
6503
6501 @command('^status|st',
6504 @command('^status|st',
6502 [('A', 'all', None, _('show status of all files')),
6505 [('A', 'all', None, _('show status of all files')),
6503 ('m', 'modified', None, _('show only modified files')),
6506 ('m', 'modified', None, _('show only modified files')),
6504 ('a', 'added', None, _('show only added files')),
6507 ('a', 'added', None, _('show only added files')),
6505 ('r', 'removed', None, _('show only removed files')),
6508 ('r', 'removed', None, _('show only removed files')),
6506 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6509 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6507 ('c', 'clean', None, _('show only files without changes')),
6510 ('c', 'clean', None, _('show only files without changes')),
6508 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6511 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6509 ('i', 'ignored', None, _('show only ignored files')),
6512 ('i', 'ignored', None, _('show only ignored files')),
6510 ('n', 'no-status', None, _('hide status prefix')),
6513 ('n', 'no-status', None, _('hide status prefix')),
6511 ('C', 'copies', None, _('show source of copied files')),
6514 ('C', 'copies', None, _('show source of copied files')),
6512 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6515 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6513 ('', 'rev', [], _('show difference from revision'), _('REV')),
6516 ('', 'rev', [], _('show difference from revision'), _('REV')),
6514 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6517 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6515 ] + walkopts + subrepoopts + formatteropts,
6518 ] + walkopts + subrepoopts + formatteropts,
6516 _('[OPTION]... [FILE]...'),
6519 _('[OPTION]... [FILE]...'),
6517 inferrepo=True)
6520 inferrepo=True)
6518 def status(ui, repo, *pats, **opts):
6521 def status(ui, repo, *pats, **opts):
6519 """show changed files in the working directory
6522 """show changed files in the working directory
6520
6523
6521 Show status of files in the repository. If names are given, only
6524 Show status of files in the repository. If names are given, only
6522 files that match are shown. Files that are clean or ignored or
6525 files that match are shown. Files that are clean or ignored or
6523 the source of a copy/move operation, are not listed unless
6526 the source of a copy/move operation, are not listed unless
6524 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6527 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6525 Unless options described with "show only ..." are given, the
6528 Unless options described with "show only ..." are given, the
6526 options -mardu are used.
6529 options -mardu are used.
6527
6530
6528 Option -q/--quiet hides untracked (unknown and ignored) files
6531 Option -q/--quiet hides untracked (unknown and ignored) files
6529 unless explicitly requested with -u/--unknown or -i/--ignored.
6532 unless explicitly requested with -u/--unknown or -i/--ignored.
6530
6533
6531 .. note::
6534 .. note::
6532
6535
6533 :hg:`status` may appear to disagree with diff if permissions have
6536 :hg:`status` may appear to disagree with diff if permissions have
6534 changed or a merge has occurred. The standard diff format does
6537 changed or a merge has occurred. The standard diff format does
6535 not report permission changes and diff only reports changes
6538 not report permission changes and diff only reports changes
6536 relative to one merge parent.
6539 relative to one merge parent.
6537
6540
6538 If one revision is given, it is used as the base revision.
6541 If one revision is given, it is used as the base revision.
6539 If two revisions are given, the differences between them are
6542 If two revisions are given, the differences between them are
6540 shown. The --change option can also be used as a shortcut to list
6543 shown. The --change option can also be used as a shortcut to list
6541 the changed files of a revision from its first parent.
6544 the changed files of a revision from its first parent.
6542
6545
6543 The codes used to show the status of files are::
6546 The codes used to show the status of files are::
6544
6547
6545 M = modified
6548 M = modified
6546 A = added
6549 A = added
6547 R = removed
6550 R = removed
6548 C = clean
6551 C = clean
6549 ! = missing (deleted by non-hg command, but still tracked)
6552 ! = missing (deleted by non-hg command, but still tracked)
6550 ? = not tracked
6553 ? = not tracked
6551 I = ignored
6554 I = ignored
6552 = origin of the previous file (with --copies)
6555 = origin of the previous file (with --copies)
6553
6556
6554 .. container:: verbose
6557 .. container:: verbose
6555
6558
6556 Examples:
6559 Examples:
6557
6560
6558 - show changes in the working directory relative to a
6561 - show changes in the working directory relative to a
6559 changeset::
6562 changeset::
6560
6563
6561 hg status --rev 9353
6564 hg status --rev 9353
6562
6565
6563 - show changes in the working directory relative to the
6566 - show changes in the working directory relative to the
6564 current directory (see :hg:`help patterns` for more information)::
6567 current directory (see :hg:`help patterns` for more information)::
6565
6568
6566 hg status re:
6569 hg status re:
6567
6570
6568 - show all changes including copies in an existing changeset::
6571 - show all changes including copies in an existing changeset::
6569
6572
6570 hg status --copies --change 9353
6573 hg status --copies --change 9353
6571
6574
6572 - get a NUL separated list of added files, suitable for xargs::
6575 - get a NUL separated list of added files, suitable for xargs::
6573
6576
6574 hg status -an0
6577 hg status -an0
6575
6578
6576 Returns 0 on success.
6579 Returns 0 on success.
6577 """
6580 """
6578
6581
6579 revs = opts.get('rev')
6582 revs = opts.get('rev')
6580 change = opts.get('change')
6583 change = opts.get('change')
6581
6584
6582 if revs and change:
6585 if revs and change:
6583 msg = _('cannot specify --rev and --change at the same time')
6586 msg = _('cannot specify --rev and --change at the same time')
6584 raise error.Abort(msg)
6587 raise error.Abort(msg)
6585 elif change:
6588 elif change:
6586 node2 = scmutil.revsingle(repo, change, None).node()
6589 node2 = scmutil.revsingle(repo, change, None).node()
6587 node1 = repo[node2].p1().node()
6590 node1 = repo[node2].p1().node()
6588 else:
6591 else:
6589 node1, node2 = scmutil.revpair(repo, revs)
6592 node1, node2 = scmutil.revpair(repo, revs)
6590
6593
6591 if pats:
6594 if pats:
6592 cwd = repo.getcwd()
6595 cwd = repo.getcwd()
6593 else:
6596 else:
6594 cwd = ''
6597 cwd = ''
6595
6598
6596 if opts.get('print0'):
6599 if opts.get('print0'):
6597 end = '\0'
6600 end = '\0'
6598 else:
6601 else:
6599 end = '\n'
6602 end = '\n'
6600 copy = {}
6603 copy = {}
6601 states = 'modified added removed deleted unknown ignored clean'.split()
6604 states = 'modified added removed deleted unknown ignored clean'.split()
6602 show = [k for k in states if opts.get(k)]
6605 show = [k for k in states if opts.get(k)]
6603 if opts.get('all'):
6606 if opts.get('all'):
6604 show += ui.quiet and (states[:4] + ['clean']) or states
6607 show += ui.quiet and (states[:4] + ['clean']) or states
6605 if not show:
6608 if not show:
6606 if ui.quiet:
6609 if ui.quiet:
6607 show = states[:4]
6610 show = states[:4]
6608 else:
6611 else:
6609 show = states[:5]
6612 show = states[:5]
6610
6613
6611 m = scmutil.match(repo[node2], pats, opts)
6614 m = scmutil.match(repo[node2], pats, opts)
6612 stat = repo.status(node1, node2, m,
6615 stat = repo.status(node1, node2, m,
6613 'ignored' in show, 'clean' in show, 'unknown' in show,
6616 'ignored' in show, 'clean' in show, 'unknown' in show,
6614 opts.get('subrepos'))
6617 opts.get('subrepos'))
6615 changestates = zip(states, 'MAR!?IC', stat)
6618 changestates = zip(states, 'MAR!?IC', stat)
6616
6619
6617 if (opts.get('all') or opts.get('copies')
6620 if (opts.get('all') or opts.get('copies')
6618 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6621 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6619 copy = copies.pathcopies(repo[node1], repo[node2], m)
6622 copy = copies.pathcopies(repo[node1], repo[node2], m)
6620
6623
6621 fm = ui.formatter('status', opts)
6624 fm = ui.formatter('status', opts)
6622 fmt = '%s' + end
6625 fmt = '%s' + end
6623 showchar = not opts.get('no_status')
6626 showchar = not opts.get('no_status')
6624
6627
6625 for state, char, files in changestates:
6628 for state, char, files in changestates:
6626 if state in show:
6629 if state in show:
6627 label = 'status.' + state
6630 label = 'status.' + state
6628 for f in files:
6631 for f in files:
6629 fm.startitem()
6632 fm.startitem()
6630 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6633 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6631 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6634 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6632 if f in copy:
6635 if f in copy:
6633 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6636 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6634 label='status.copied')
6637 label='status.copied')
6635 fm.end()
6638 fm.end()
6636
6639
6637 @command('^summary|sum',
6640 @command('^summary|sum',
6638 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6641 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6639 def summary(ui, repo, **opts):
6642 def summary(ui, repo, **opts):
6640 """summarize working directory state
6643 """summarize working directory state
6641
6644
6642 This generates a brief summary of the working directory state,
6645 This generates a brief summary of the working directory state,
6643 including parents, branch, commit status, phase and available updates.
6646 including parents, branch, commit status, phase and available updates.
6644
6647
6645 With the --remote option, this will check the default paths for
6648 With the --remote option, this will check the default paths for
6646 incoming and outgoing changes. This can be time-consuming.
6649 incoming and outgoing changes. This can be time-consuming.
6647
6650
6648 Returns 0 on success.
6651 Returns 0 on success.
6649 """
6652 """
6650
6653
6651 ctx = repo[None]
6654 ctx = repo[None]
6652 parents = ctx.parents()
6655 parents = ctx.parents()
6653 pnode = parents[0].node()
6656 pnode = parents[0].node()
6654 marks = []
6657 marks = []
6655
6658
6656 ms = None
6659 ms = None
6657 try:
6660 try:
6658 ms = mergemod.mergestate.read(repo)
6661 ms = mergemod.mergestate.read(repo)
6659 except error.UnsupportedMergeRecords as e:
6662 except error.UnsupportedMergeRecords as e:
6660 s = ' '.join(e.recordtypes)
6663 s = ' '.join(e.recordtypes)
6661 ui.warn(
6664 ui.warn(
6662 _('warning: merge state has unsupported record types: %s\n') % s)
6665 _('warning: merge state has unsupported record types: %s\n') % s)
6663 unresolved = 0
6666 unresolved = 0
6664 else:
6667 else:
6665 unresolved = [f for f in ms if ms[f] == 'u']
6668 unresolved = [f for f in ms if ms[f] == 'u']
6666
6669
6667 for p in parents:
6670 for p in parents:
6668 # label with log.changeset (instead of log.parent) since this
6671 # label with log.changeset (instead of log.parent) since this
6669 # shows a working directory parent *changeset*:
6672 # shows a working directory parent *changeset*:
6670 # i18n: column positioning for "hg summary"
6673 # i18n: column positioning for "hg summary"
6671 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6674 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6672 label='log.changeset changeset.%s' % p.phasestr())
6675 label='log.changeset changeset.%s' % p.phasestr())
6673 ui.write(' '.join(p.tags()), label='log.tag')
6676 ui.write(' '.join(p.tags()), label='log.tag')
6674 if p.bookmarks():
6677 if p.bookmarks():
6675 marks.extend(p.bookmarks())
6678 marks.extend(p.bookmarks())
6676 if p.rev() == -1:
6679 if p.rev() == -1:
6677 if not len(repo):
6680 if not len(repo):
6678 ui.write(_(' (empty repository)'))
6681 ui.write(_(' (empty repository)'))
6679 else:
6682 else:
6680 ui.write(_(' (no revision checked out)'))
6683 ui.write(_(' (no revision checked out)'))
6681 ui.write('\n')
6684 ui.write('\n')
6682 if p.description():
6685 if p.description():
6683 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6686 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6684 label='log.summary')
6687 label='log.summary')
6685
6688
6686 branch = ctx.branch()
6689 branch = ctx.branch()
6687 bheads = repo.branchheads(branch)
6690 bheads = repo.branchheads(branch)
6688 # i18n: column positioning for "hg summary"
6691 # i18n: column positioning for "hg summary"
6689 m = _('branch: %s\n') % branch
6692 m = _('branch: %s\n') % branch
6690 if branch != 'default':
6693 if branch != 'default':
6691 ui.write(m, label='log.branch')
6694 ui.write(m, label='log.branch')
6692 else:
6695 else:
6693 ui.status(m, label='log.branch')
6696 ui.status(m, label='log.branch')
6694
6697
6695 if marks:
6698 if marks:
6696 active = repo._activebookmark
6699 active = repo._activebookmark
6697 # i18n: column positioning for "hg summary"
6700 # i18n: column positioning for "hg summary"
6698 ui.write(_('bookmarks:'), label='log.bookmark')
6701 ui.write(_('bookmarks:'), label='log.bookmark')
6699 if active is not None:
6702 if active is not None:
6700 if active in marks:
6703 if active in marks:
6701 ui.write(' *' + active, label=activebookmarklabel)
6704 ui.write(' *' + active, label=activebookmarklabel)
6702 marks.remove(active)
6705 marks.remove(active)
6703 else:
6706 else:
6704 ui.write(' [%s]' % active, label=activebookmarklabel)
6707 ui.write(' [%s]' % active, label=activebookmarklabel)
6705 for m in marks:
6708 for m in marks:
6706 ui.write(' ' + m, label='log.bookmark')
6709 ui.write(' ' + m, label='log.bookmark')
6707 ui.write('\n', label='log.bookmark')
6710 ui.write('\n', label='log.bookmark')
6708
6711
6709 status = repo.status(unknown=True)
6712 status = repo.status(unknown=True)
6710
6713
6711 c = repo.dirstate.copies()
6714 c = repo.dirstate.copies()
6712 copied, renamed = [], []
6715 copied, renamed = [], []
6713 for d, s in c.iteritems():
6716 for d, s in c.iteritems():
6714 if s in status.removed:
6717 if s in status.removed:
6715 status.removed.remove(s)
6718 status.removed.remove(s)
6716 renamed.append(d)
6719 renamed.append(d)
6717 else:
6720 else:
6718 copied.append(d)
6721 copied.append(d)
6719 if d in status.added:
6722 if d in status.added:
6720 status.added.remove(d)
6723 status.added.remove(d)
6721
6724
6722 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6725 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6723
6726
6724 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6727 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6725 (ui.label(_('%d added'), 'status.added'), status.added),
6728 (ui.label(_('%d added'), 'status.added'), status.added),
6726 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6729 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6727 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6730 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6728 (ui.label(_('%d copied'), 'status.copied'), copied),
6731 (ui.label(_('%d copied'), 'status.copied'), copied),
6729 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6732 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6730 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6733 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6731 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6734 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6732 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6735 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6733 t = []
6736 t = []
6734 for l, s in labels:
6737 for l, s in labels:
6735 if s:
6738 if s:
6736 t.append(l % len(s))
6739 t.append(l % len(s))
6737
6740
6738 t = ', '.join(t)
6741 t = ', '.join(t)
6739 cleanworkdir = False
6742 cleanworkdir = False
6740
6743
6741 if repo.vfs.exists('graftstate'):
6744 if repo.vfs.exists('graftstate'):
6742 t += _(' (graft in progress)')
6745 t += _(' (graft in progress)')
6743 if repo.vfs.exists('updatestate'):
6746 if repo.vfs.exists('updatestate'):
6744 t += _(' (interrupted update)')
6747 t += _(' (interrupted update)')
6745 elif len(parents) > 1:
6748 elif len(parents) > 1:
6746 t += _(' (merge)')
6749 t += _(' (merge)')
6747 elif branch != parents[0].branch():
6750 elif branch != parents[0].branch():
6748 t += _(' (new branch)')
6751 t += _(' (new branch)')
6749 elif (parents[0].closesbranch() and
6752 elif (parents[0].closesbranch() and
6750 pnode in repo.branchheads(branch, closed=True)):
6753 pnode in repo.branchheads(branch, closed=True)):
6751 t += _(' (head closed)')
6754 t += _(' (head closed)')
6752 elif not (status.modified or status.added or status.removed or renamed or
6755 elif not (status.modified or status.added or status.removed or renamed or
6753 copied or subs):
6756 copied or subs):
6754 t += _(' (clean)')
6757 t += _(' (clean)')
6755 cleanworkdir = True
6758 cleanworkdir = True
6756 elif pnode not in bheads:
6759 elif pnode not in bheads:
6757 t += _(' (new branch head)')
6760 t += _(' (new branch head)')
6758
6761
6759 if parents:
6762 if parents:
6760 pendingphase = max(p.phase() for p in parents)
6763 pendingphase = max(p.phase() for p in parents)
6761 else:
6764 else:
6762 pendingphase = phases.public
6765 pendingphase = phases.public
6763
6766
6764 if pendingphase > phases.newcommitphase(ui):
6767 if pendingphase > phases.newcommitphase(ui):
6765 t += ' (%s)' % phases.phasenames[pendingphase]
6768 t += ' (%s)' % phases.phasenames[pendingphase]
6766
6769
6767 if cleanworkdir:
6770 if cleanworkdir:
6768 # i18n: column positioning for "hg summary"
6771 # i18n: column positioning for "hg summary"
6769 ui.status(_('commit: %s\n') % t.strip())
6772 ui.status(_('commit: %s\n') % t.strip())
6770 else:
6773 else:
6771 # i18n: column positioning for "hg summary"
6774 # i18n: column positioning for "hg summary"
6772 ui.write(_('commit: %s\n') % t.strip())
6775 ui.write(_('commit: %s\n') % t.strip())
6773
6776
6774 # all ancestors of branch heads - all ancestors of parent = new csets
6777 # all ancestors of branch heads - all ancestors of parent = new csets
6775 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6778 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6776 bheads))
6779 bheads))
6777
6780
6778 if new == 0:
6781 if new == 0:
6779 # i18n: column positioning for "hg summary"
6782 # i18n: column positioning for "hg summary"
6780 ui.status(_('update: (current)\n'))
6783 ui.status(_('update: (current)\n'))
6781 elif pnode not in bheads:
6784 elif pnode not in bheads:
6782 # i18n: column positioning for "hg summary"
6785 # i18n: column positioning for "hg summary"
6783 ui.write(_('update: %d new changesets (update)\n') % new)
6786 ui.write(_('update: %d new changesets (update)\n') % new)
6784 else:
6787 else:
6785 # i18n: column positioning for "hg summary"
6788 # i18n: column positioning for "hg summary"
6786 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6789 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6787 (new, len(bheads)))
6790 (new, len(bheads)))
6788
6791
6789 t = []
6792 t = []
6790 draft = len(repo.revs('draft()'))
6793 draft = len(repo.revs('draft()'))
6791 if draft:
6794 if draft:
6792 t.append(_('%d draft') % draft)
6795 t.append(_('%d draft') % draft)
6793 secret = len(repo.revs('secret()'))
6796 secret = len(repo.revs('secret()'))
6794 if secret:
6797 if secret:
6795 t.append(_('%d secret') % secret)
6798 t.append(_('%d secret') % secret)
6796
6799
6797 if draft or secret:
6800 if draft or secret:
6798 ui.status(_('phases: %s\n') % ', '.join(t))
6801 ui.status(_('phases: %s\n') % ', '.join(t))
6799
6802
6800 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6803 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6801 for trouble in ("unstable", "divergent", "bumped"):
6804 for trouble in ("unstable", "divergent", "bumped"):
6802 numtrouble = len(repo.revs(trouble + "()"))
6805 numtrouble = len(repo.revs(trouble + "()"))
6803 # We write all the possibilities to ease translation
6806 # We write all the possibilities to ease translation
6804 troublemsg = {
6807 troublemsg = {
6805 "unstable": _("unstable: %d changesets"),
6808 "unstable": _("unstable: %d changesets"),
6806 "divergent": _("divergent: %d changesets"),
6809 "divergent": _("divergent: %d changesets"),
6807 "bumped": _("bumped: %d changesets"),
6810 "bumped": _("bumped: %d changesets"),
6808 }
6811 }
6809 if numtrouble > 0:
6812 if numtrouble > 0:
6810 ui.status(troublemsg[trouble] % numtrouble + "\n")
6813 ui.status(troublemsg[trouble] % numtrouble + "\n")
6811
6814
6812 cmdutil.summaryhooks(ui, repo)
6815 cmdutil.summaryhooks(ui, repo)
6813
6816
6814 if opts.get('remote'):
6817 if opts.get('remote'):
6815 needsincoming, needsoutgoing = True, True
6818 needsincoming, needsoutgoing = True, True
6816 else:
6819 else:
6817 needsincoming, needsoutgoing = False, False
6820 needsincoming, needsoutgoing = False, False
6818 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6821 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6819 if i:
6822 if i:
6820 needsincoming = True
6823 needsincoming = True
6821 if o:
6824 if o:
6822 needsoutgoing = True
6825 needsoutgoing = True
6823 if not needsincoming and not needsoutgoing:
6826 if not needsincoming and not needsoutgoing:
6824 return
6827 return
6825
6828
6826 def getincoming():
6829 def getincoming():
6827 source, branches = hg.parseurl(ui.expandpath('default'))
6830 source, branches = hg.parseurl(ui.expandpath('default'))
6828 sbranch = branches[0]
6831 sbranch = branches[0]
6829 try:
6832 try:
6830 other = hg.peer(repo, {}, source)
6833 other = hg.peer(repo, {}, source)
6831 except error.RepoError:
6834 except error.RepoError:
6832 if opts.get('remote'):
6835 if opts.get('remote'):
6833 raise
6836 raise
6834 return source, sbranch, None, None, None
6837 return source, sbranch, None, None, None
6835 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6838 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6836 if revs:
6839 if revs:
6837 revs = [other.lookup(rev) for rev in revs]
6840 revs = [other.lookup(rev) for rev in revs]
6838 ui.debug('comparing with %s\n' % util.hidepassword(source))
6841 ui.debug('comparing with %s\n' % util.hidepassword(source))
6839 repo.ui.pushbuffer()
6842 repo.ui.pushbuffer()
6840 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6843 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6841 repo.ui.popbuffer()
6844 repo.ui.popbuffer()
6842 return source, sbranch, other, commoninc, commoninc[1]
6845 return source, sbranch, other, commoninc, commoninc[1]
6843
6846
6844 if needsincoming:
6847 if needsincoming:
6845 source, sbranch, sother, commoninc, incoming = getincoming()
6848 source, sbranch, sother, commoninc, incoming = getincoming()
6846 else:
6849 else:
6847 source = sbranch = sother = commoninc = incoming = None
6850 source = sbranch = sother = commoninc = incoming = None
6848
6851
6849 def getoutgoing():
6852 def getoutgoing():
6850 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6853 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6851 dbranch = branches[0]
6854 dbranch = branches[0]
6852 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6855 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6853 if source != dest:
6856 if source != dest:
6854 try:
6857 try:
6855 dother = hg.peer(repo, {}, dest)
6858 dother = hg.peer(repo, {}, dest)
6856 except error.RepoError:
6859 except error.RepoError:
6857 if opts.get('remote'):
6860 if opts.get('remote'):
6858 raise
6861 raise
6859 return dest, dbranch, None, None
6862 return dest, dbranch, None, None
6860 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6863 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6861 elif sother is None:
6864 elif sother is None:
6862 # there is no explicit destination peer, but source one is invalid
6865 # there is no explicit destination peer, but source one is invalid
6863 return dest, dbranch, None, None
6866 return dest, dbranch, None, None
6864 else:
6867 else:
6865 dother = sother
6868 dother = sother
6866 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6869 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6867 common = None
6870 common = None
6868 else:
6871 else:
6869 common = commoninc
6872 common = commoninc
6870 if revs:
6873 if revs:
6871 revs = [repo.lookup(rev) for rev in revs]
6874 revs = [repo.lookup(rev) for rev in revs]
6872 repo.ui.pushbuffer()
6875 repo.ui.pushbuffer()
6873 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6876 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6874 commoninc=common)
6877 commoninc=common)
6875 repo.ui.popbuffer()
6878 repo.ui.popbuffer()
6876 return dest, dbranch, dother, outgoing
6879 return dest, dbranch, dother, outgoing
6877
6880
6878 if needsoutgoing:
6881 if needsoutgoing:
6879 dest, dbranch, dother, outgoing = getoutgoing()
6882 dest, dbranch, dother, outgoing = getoutgoing()
6880 else:
6883 else:
6881 dest = dbranch = dother = outgoing = None
6884 dest = dbranch = dother = outgoing = None
6882
6885
6883 if opts.get('remote'):
6886 if opts.get('remote'):
6884 t = []
6887 t = []
6885 if incoming:
6888 if incoming:
6886 t.append(_('1 or more incoming'))
6889 t.append(_('1 or more incoming'))
6887 o = outgoing.missing
6890 o = outgoing.missing
6888 if o:
6891 if o:
6889 t.append(_('%d outgoing') % len(o))
6892 t.append(_('%d outgoing') % len(o))
6890 other = dother or sother
6893 other = dother or sother
6891 if 'bookmarks' in other.listkeys('namespaces'):
6894 if 'bookmarks' in other.listkeys('namespaces'):
6892 counts = bookmarks.summary(repo, other)
6895 counts = bookmarks.summary(repo, other)
6893 if counts[0] > 0:
6896 if counts[0] > 0:
6894 t.append(_('%d incoming bookmarks') % counts[0])
6897 t.append(_('%d incoming bookmarks') % counts[0])
6895 if counts[1] > 0:
6898 if counts[1] > 0:
6896 t.append(_('%d outgoing bookmarks') % counts[1])
6899 t.append(_('%d outgoing bookmarks') % counts[1])
6897
6900
6898 if t:
6901 if t:
6899 # i18n: column positioning for "hg summary"
6902 # i18n: column positioning for "hg summary"
6900 ui.write(_('remote: %s\n') % (', '.join(t)))
6903 ui.write(_('remote: %s\n') % (', '.join(t)))
6901 else:
6904 else:
6902 # i18n: column positioning for "hg summary"
6905 # i18n: column positioning for "hg summary"
6903 ui.status(_('remote: (synced)\n'))
6906 ui.status(_('remote: (synced)\n'))
6904
6907
6905 cmdutil.summaryremotehooks(ui, repo, opts,
6908 cmdutil.summaryremotehooks(ui, repo, opts,
6906 ((source, sbranch, sother, commoninc),
6909 ((source, sbranch, sother, commoninc),
6907 (dest, dbranch, dother, outgoing)))
6910 (dest, dbranch, dother, outgoing)))
6908
6911
6909 @command('tag',
6912 @command('tag',
6910 [('f', 'force', None, _('force tag')),
6913 [('f', 'force', None, _('force tag')),
6911 ('l', 'local', None, _('make the tag local')),
6914 ('l', 'local', None, _('make the tag local')),
6912 ('r', 'rev', '', _('revision to tag'), _('REV')),
6915 ('r', 'rev', '', _('revision to tag'), _('REV')),
6913 ('', 'remove', None, _('remove a tag')),
6916 ('', 'remove', None, _('remove a tag')),
6914 # -l/--local is already there, commitopts cannot be used
6917 # -l/--local is already there, commitopts cannot be used
6915 ('e', 'edit', None, _('invoke editor on commit messages')),
6918 ('e', 'edit', None, _('invoke editor on commit messages')),
6916 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6919 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6917 ] + commitopts2,
6920 ] + commitopts2,
6918 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6921 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6919 def tag(ui, repo, name1, *names, **opts):
6922 def tag(ui, repo, name1, *names, **opts):
6920 """add one or more tags for the current or given revision
6923 """add one or more tags for the current or given revision
6921
6924
6922 Name a particular revision using <name>.
6925 Name a particular revision using <name>.
6923
6926
6924 Tags are used to name particular revisions of the repository and are
6927 Tags are used to name particular revisions of the repository and are
6925 very useful to compare different revisions, to go back to significant
6928 very useful to compare different revisions, to go back to significant
6926 earlier versions or to mark branch points as releases, etc. Changing
6929 earlier versions or to mark branch points as releases, etc. Changing
6927 an existing tag is normally disallowed; use -f/--force to override.
6930 an existing tag is normally disallowed; use -f/--force to override.
6928
6931
6929 If no revision is given, the parent of the working directory is
6932 If no revision is given, the parent of the working directory is
6930 used.
6933 used.
6931
6934
6932 To facilitate version control, distribution, and merging of tags,
6935 To facilitate version control, distribution, and merging of tags,
6933 they are stored as a file named ".hgtags" which is managed similarly
6936 they are stored as a file named ".hgtags" which is managed similarly
6934 to other project files and can be hand-edited if necessary. This
6937 to other project files and can be hand-edited if necessary. This
6935 also means that tagging creates a new commit. The file
6938 also means that tagging creates a new commit. The file
6936 ".hg/localtags" is used for local tags (not shared among
6939 ".hg/localtags" is used for local tags (not shared among
6937 repositories).
6940 repositories).
6938
6941
6939 Tag commits are usually made at the head of a branch. If the parent
6942 Tag commits are usually made at the head of a branch. If the parent
6940 of the working directory is not a branch head, :hg:`tag` aborts; use
6943 of the working directory is not a branch head, :hg:`tag` aborts; use
6941 -f/--force to force the tag commit to be based on a non-head
6944 -f/--force to force the tag commit to be based on a non-head
6942 changeset.
6945 changeset.
6943
6946
6944 See :hg:`help dates` for a list of formats valid for -d/--date.
6947 See :hg:`help dates` for a list of formats valid for -d/--date.
6945
6948
6946 Since tag names have priority over branch names during revision
6949 Since tag names have priority over branch names during revision
6947 lookup, using an existing branch name as a tag name is discouraged.
6950 lookup, using an existing branch name as a tag name is discouraged.
6948
6951
6949 Returns 0 on success.
6952 Returns 0 on success.
6950 """
6953 """
6951 wlock = lock = None
6954 wlock = lock = None
6952 try:
6955 try:
6953 wlock = repo.wlock()
6956 wlock = repo.wlock()
6954 lock = repo.lock()
6957 lock = repo.lock()
6955 rev_ = "."
6958 rev_ = "."
6956 names = [t.strip() for t in (name1,) + names]
6959 names = [t.strip() for t in (name1,) + names]
6957 if len(names) != len(set(names)):
6960 if len(names) != len(set(names)):
6958 raise error.Abort(_('tag names must be unique'))
6961 raise error.Abort(_('tag names must be unique'))
6959 for n in names:
6962 for n in names:
6960 scmutil.checknewlabel(repo, n, 'tag')
6963 scmutil.checknewlabel(repo, n, 'tag')
6961 if not n:
6964 if not n:
6962 raise error.Abort(_('tag names cannot consist entirely of '
6965 raise error.Abort(_('tag names cannot consist entirely of '
6963 'whitespace'))
6966 'whitespace'))
6964 if opts.get('rev') and opts.get('remove'):
6967 if opts.get('rev') and opts.get('remove'):
6965 raise error.Abort(_("--rev and --remove are incompatible"))
6968 raise error.Abort(_("--rev and --remove are incompatible"))
6966 if opts.get('rev'):
6969 if opts.get('rev'):
6967 rev_ = opts['rev']
6970 rev_ = opts['rev']
6968 message = opts.get('message')
6971 message = opts.get('message')
6969 if opts.get('remove'):
6972 if opts.get('remove'):
6970 if opts.get('local'):
6973 if opts.get('local'):
6971 expectedtype = 'local'
6974 expectedtype = 'local'
6972 else:
6975 else:
6973 expectedtype = 'global'
6976 expectedtype = 'global'
6974
6977
6975 for n in names:
6978 for n in names:
6976 if not repo.tagtype(n):
6979 if not repo.tagtype(n):
6977 raise error.Abort(_("tag '%s' does not exist") % n)
6980 raise error.Abort(_("tag '%s' does not exist") % n)
6978 if repo.tagtype(n) != expectedtype:
6981 if repo.tagtype(n) != expectedtype:
6979 if expectedtype == 'global':
6982 if expectedtype == 'global':
6980 raise error.Abort(_("tag '%s' is not a global tag") % n)
6983 raise error.Abort(_("tag '%s' is not a global tag") % n)
6981 else:
6984 else:
6982 raise error.Abort(_("tag '%s' is not a local tag") % n)
6985 raise error.Abort(_("tag '%s' is not a local tag") % n)
6983 rev_ = 'null'
6986 rev_ = 'null'
6984 if not message:
6987 if not message:
6985 # we don't translate commit messages
6988 # we don't translate commit messages
6986 message = 'Removed tag %s' % ', '.join(names)
6989 message = 'Removed tag %s' % ', '.join(names)
6987 elif not opts.get('force'):
6990 elif not opts.get('force'):
6988 for n in names:
6991 for n in names:
6989 if n in repo.tags():
6992 if n in repo.tags():
6990 raise error.Abort(_("tag '%s' already exists "
6993 raise error.Abort(_("tag '%s' already exists "
6991 "(use -f to force)") % n)
6994 "(use -f to force)") % n)
6992 if not opts.get('local'):
6995 if not opts.get('local'):
6993 p1, p2 = repo.dirstate.parents()
6996 p1, p2 = repo.dirstate.parents()
6994 if p2 != nullid:
6997 if p2 != nullid:
6995 raise error.Abort(_('uncommitted merge'))
6998 raise error.Abort(_('uncommitted merge'))
6996 bheads = repo.branchheads()
6999 bheads = repo.branchheads()
6997 if not opts.get('force') and bheads and p1 not in bheads:
7000 if not opts.get('force') and bheads and p1 not in bheads:
6998 raise error.Abort(_('not at a branch head (use -f to force)'))
7001 raise error.Abort(_('not at a branch head (use -f to force)'))
6999 r = scmutil.revsingle(repo, rev_).node()
7002 r = scmutil.revsingle(repo, rev_).node()
7000
7003
7001 if not message:
7004 if not message:
7002 # we don't translate commit messages
7005 # we don't translate commit messages
7003 message = ('Added tag %s for changeset %s' %
7006 message = ('Added tag %s for changeset %s' %
7004 (', '.join(names), short(r)))
7007 (', '.join(names), short(r)))
7005
7008
7006 date = opts.get('date')
7009 date = opts.get('date')
7007 if date:
7010 if date:
7008 date = util.parsedate(date)
7011 date = util.parsedate(date)
7009
7012
7010 if opts.get('remove'):
7013 if opts.get('remove'):
7011 editform = 'tag.remove'
7014 editform = 'tag.remove'
7012 else:
7015 else:
7013 editform = 'tag.add'
7016 editform = 'tag.add'
7014 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7017 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7015
7018
7016 # don't allow tagging the null rev
7019 # don't allow tagging the null rev
7017 if (not opts.get('remove') and
7020 if (not opts.get('remove') and
7018 scmutil.revsingle(repo, rev_).rev() == nullrev):
7021 scmutil.revsingle(repo, rev_).rev() == nullrev):
7019 raise error.Abort(_("cannot tag null revision"))
7022 raise error.Abort(_("cannot tag null revision"))
7020
7023
7021 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7024 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7022 editor=editor)
7025 editor=editor)
7023 finally:
7026 finally:
7024 release(lock, wlock)
7027 release(lock, wlock)
7025
7028
7026 @command('tags', formatteropts, '')
7029 @command('tags', formatteropts, '')
7027 def tags(ui, repo, **opts):
7030 def tags(ui, repo, **opts):
7028 """list repository tags
7031 """list repository tags
7029
7032
7030 This lists both regular and local tags. When the -v/--verbose
7033 This lists both regular and local tags. When the -v/--verbose
7031 switch is used, a third column "local" is printed for local tags.
7034 switch is used, a third column "local" is printed for local tags.
7032 When the -q/--quiet switch is used, only the tag name is printed.
7035 When the -q/--quiet switch is used, only the tag name is printed.
7033
7036
7034 Returns 0 on success.
7037 Returns 0 on success.
7035 """
7038 """
7036
7039
7037 fm = ui.formatter('tags', opts)
7040 fm = ui.formatter('tags', opts)
7038 hexfunc = fm.hexfunc
7041 hexfunc = fm.hexfunc
7039 tagtype = ""
7042 tagtype = ""
7040
7043
7041 for t, n in reversed(repo.tagslist()):
7044 for t, n in reversed(repo.tagslist()):
7042 hn = hexfunc(n)
7045 hn = hexfunc(n)
7043 label = 'tags.normal'
7046 label = 'tags.normal'
7044 tagtype = ''
7047 tagtype = ''
7045 if repo.tagtype(t) == 'local':
7048 if repo.tagtype(t) == 'local':
7046 label = 'tags.local'
7049 label = 'tags.local'
7047 tagtype = 'local'
7050 tagtype = 'local'
7048
7051
7049 fm.startitem()
7052 fm.startitem()
7050 fm.write('tag', '%s', t, label=label)
7053 fm.write('tag', '%s', t, label=label)
7051 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7054 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7052 fm.condwrite(not ui.quiet, 'rev node', fmt,
7055 fm.condwrite(not ui.quiet, 'rev node', fmt,
7053 repo.changelog.rev(n), hn, label=label)
7056 repo.changelog.rev(n), hn, label=label)
7054 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7057 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7055 tagtype, label=label)
7058 tagtype, label=label)
7056 fm.plain('\n')
7059 fm.plain('\n')
7057 fm.end()
7060 fm.end()
7058
7061
7059 @command('tip',
7062 @command('tip',
7060 [('p', 'patch', None, _('show patch')),
7063 [('p', 'patch', None, _('show patch')),
7061 ('g', 'git', None, _('use git extended diff format')),
7064 ('g', 'git', None, _('use git extended diff format')),
7062 ] + templateopts,
7065 ] + templateopts,
7063 _('[-p] [-g]'))
7066 _('[-p] [-g]'))
7064 def tip(ui, repo, **opts):
7067 def tip(ui, repo, **opts):
7065 """show the tip revision (DEPRECATED)
7068 """show the tip revision (DEPRECATED)
7066
7069
7067 The tip revision (usually just called the tip) is the changeset
7070 The tip revision (usually just called the tip) is the changeset
7068 most recently added to the repository (and therefore the most
7071 most recently added to the repository (and therefore the most
7069 recently changed head).
7072 recently changed head).
7070
7073
7071 If you have just made a commit, that commit will be the tip. If
7074 If you have just made a commit, that commit will be the tip. If
7072 you have just pulled changes from another repository, the tip of
7075 you have just pulled changes from another repository, the tip of
7073 that repository becomes the current tip. The "tip" tag is special
7076 that repository becomes the current tip. The "tip" tag is special
7074 and cannot be renamed or assigned to a different changeset.
7077 and cannot be renamed or assigned to a different changeset.
7075
7078
7076 This command is deprecated, please use :hg:`heads` instead.
7079 This command is deprecated, please use :hg:`heads` instead.
7077
7080
7078 Returns 0 on success.
7081 Returns 0 on success.
7079 """
7082 """
7080 displayer = cmdutil.show_changeset(ui, repo, opts)
7083 displayer = cmdutil.show_changeset(ui, repo, opts)
7081 displayer.show(repo['tip'])
7084 displayer.show(repo['tip'])
7082 displayer.close()
7085 displayer.close()
7083
7086
7084 @command('unbundle',
7087 @command('unbundle',
7085 [('u', 'update', None,
7088 [('u', 'update', None,
7086 _('update to new branch head if changesets were unbundled'))],
7089 _('update to new branch head if changesets were unbundled'))],
7087 _('[-u] FILE...'))
7090 _('[-u] FILE...'))
7088 def unbundle(ui, repo, fname1, *fnames, **opts):
7091 def unbundle(ui, repo, fname1, *fnames, **opts):
7089 """apply one or more changegroup files
7092 """apply one or more changegroup files
7090
7093
7091 Apply one or more compressed changegroup files generated by the
7094 Apply one or more compressed changegroup files generated by the
7092 bundle command.
7095 bundle command.
7093
7096
7094 Returns 0 on success, 1 if an update has unresolved files.
7097 Returns 0 on success, 1 if an update has unresolved files.
7095 """
7098 """
7096 fnames = (fname1,) + fnames
7099 fnames = (fname1,) + fnames
7097
7100
7098 with repo.lock():
7101 with repo.lock():
7099 for fname in fnames:
7102 for fname in fnames:
7100 f = hg.openpath(ui, fname)
7103 f = hg.openpath(ui, fname)
7101 gen = exchange.readbundle(ui, f, fname)
7104 gen = exchange.readbundle(ui, f, fname)
7102 if isinstance(gen, bundle2.unbundle20):
7105 if isinstance(gen, bundle2.unbundle20):
7103 tr = repo.transaction('unbundle')
7106 tr = repo.transaction('unbundle')
7104 try:
7107 try:
7105 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7108 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7106 url='bundle:' + fname)
7109 url='bundle:' + fname)
7107 tr.close()
7110 tr.close()
7108 except error.BundleUnknownFeatureError as exc:
7111 except error.BundleUnknownFeatureError as exc:
7109 raise error.Abort(_('%s: unknown bundle feature, %s')
7112 raise error.Abort(_('%s: unknown bundle feature, %s')
7110 % (fname, exc),
7113 % (fname, exc),
7111 hint=_("see https://mercurial-scm.org/"
7114 hint=_("see https://mercurial-scm.org/"
7112 "wiki/BundleFeature for more "
7115 "wiki/BundleFeature for more "
7113 "information"))
7116 "information"))
7114 finally:
7117 finally:
7115 if tr:
7118 if tr:
7116 tr.release()
7119 tr.release()
7117 changes = [r.get('return', 0)
7120 changes = [r.get('return', 0)
7118 for r in op.records['changegroup']]
7121 for r in op.records['changegroup']]
7119 modheads = changegroup.combineresults(changes)
7122 modheads = changegroup.combineresults(changes)
7120 elif isinstance(gen, streamclone.streamcloneapplier):
7123 elif isinstance(gen, streamclone.streamcloneapplier):
7121 raise error.Abort(
7124 raise error.Abort(
7122 _('packed bundles cannot be applied with '
7125 _('packed bundles cannot be applied with '
7123 '"hg unbundle"'),
7126 '"hg unbundle"'),
7124 hint=_('use "hg debugapplystreamclonebundle"'))
7127 hint=_('use "hg debugapplystreamclonebundle"'))
7125 else:
7128 else:
7126 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7129 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7127
7130
7128 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7131 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7129
7132
7130 @command('^update|up|checkout|co',
7133 @command('^update|up|checkout|co',
7131 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7134 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7132 ('c', 'check', None, _('require clean working directory')),
7135 ('c', 'check', None, _('require clean working directory')),
7133 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7136 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7134 ('r', 'rev', '', _('revision'), _('REV'))
7137 ('r', 'rev', '', _('revision'), _('REV'))
7135 ] + mergetoolopts,
7138 ] + mergetoolopts,
7136 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7139 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7137 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7140 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7138 tool=None):
7141 tool=None):
7139 """update working directory (or switch revisions)
7142 """update working directory (or switch revisions)
7140
7143
7141 Update the repository's working directory to the specified
7144 Update the repository's working directory to the specified
7142 changeset. If no changeset is specified, update to the tip of the
7145 changeset. If no changeset is specified, update to the tip of the
7143 current named branch and move the active bookmark (see :hg:`help
7146 current named branch and move the active bookmark (see :hg:`help
7144 bookmarks`).
7147 bookmarks`).
7145
7148
7146 Update sets the working directory's parent revision to the specified
7149 Update sets the working directory's parent revision to the specified
7147 changeset (see :hg:`help parents`).
7150 changeset (see :hg:`help parents`).
7148
7151
7149 If the changeset is not a descendant or ancestor of the working
7152 If the changeset is not a descendant or ancestor of the working
7150 directory's parent, the update is aborted. With the -c/--check
7153 directory's parent, the update is aborted. With the -c/--check
7151 option, the working directory is checked for uncommitted changes; if
7154 option, the working directory is checked for uncommitted changes; if
7152 none are found, the working directory is updated to the specified
7155 none are found, the working directory is updated to the specified
7153 changeset.
7156 changeset.
7154
7157
7155 .. container:: verbose
7158 .. container:: verbose
7156
7159
7157 The following rules apply when the working directory contains
7160 The following rules apply when the working directory contains
7158 uncommitted changes:
7161 uncommitted changes:
7159
7162
7160 1. If neither -c/--check nor -C/--clean is specified, and if
7163 1. If neither -c/--check nor -C/--clean is specified, and if
7161 the requested changeset is an ancestor or descendant of
7164 the requested changeset is an ancestor or descendant of
7162 the working directory's parent, the uncommitted changes
7165 the working directory's parent, the uncommitted changes
7163 are merged into the requested changeset and the merged
7166 are merged into the requested changeset and the merged
7164 result is left uncommitted. If the requested changeset is
7167 result is left uncommitted. If the requested changeset is
7165 not an ancestor or descendant (that is, it is on another
7168 not an ancestor or descendant (that is, it is on another
7166 branch), the update is aborted and the uncommitted changes
7169 branch), the update is aborted and the uncommitted changes
7167 are preserved.
7170 are preserved.
7168
7171
7169 2. With the -c/--check option, the update is aborted and the
7172 2. With the -c/--check option, the update is aborted and the
7170 uncommitted changes are preserved.
7173 uncommitted changes are preserved.
7171
7174
7172 3. With the -C/--clean option, uncommitted changes are discarded and
7175 3. With the -C/--clean option, uncommitted changes are discarded and
7173 the working directory is updated to the requested changeset.
7176 the working directory is updated to the requested changeset.
7174
7177
7175 To cancel an uncommitted merge (and lose your changes), use
7178 To cancel an uncommitted merge (and lose your changes), use
7176 :hg:`update --clean .`.
7179 :hg:`update --clean .`.
7177
7180
7178 Use null as the changeset to remove the working directory (like
7181 Use null as the changeset to remove the working directory (like
7179 :hg:`clone -U`).
7182 :hg:`clone -U`).
7180
7183
7181 If you want to revert just one file to an older revision, use
7184 If you want to revert just one file to an older revision, use
7182 :hg:`revert [-r REV] NAME`.
7185 :hg:`revert [-r REV] NAME`.
7183
7186
7184 See :hg:`help dates` for a list of formats valid for -d/--date.
7187 See :hg:`help dates` for a list of formats valid for -d/--date.
7185
7188
7186 Returns 0 on success, 1 if there are unresolved files.
7189 Returns 0 on success, 1 if there are unresolved files.
7187 """
7190 """
7188 if rev and node:
7191 if rev and node:
7189 raise error.Abort(_("please specify just one revision"))
7192 raise error.Abort(_("please specify just one revision"))
7190
7193
7191 if rev is None or rev == '':
7194 if rev is None or rev == '':
7192 rev = node
7195 rev = node
7193
7196
7194 if date and rev is not None:
7197 if date and rev is not None:
7195 raise error.Abort(_("you can't specify a revision and a date"))
7198 raise error.Abort(_("you can't specify a revision and a date"))
7196
7199
7197 if check and clean:
7200 if check and clean:
7198 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7201 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7199
7202
7200 with repo.wlock():
7203 with repo.wlock():
7201 cmdutil.clearunfinished(repo)
7204 cmdutil.clearunfinished(repo)
7202
7205
7203 if date:
7206 if date:
7204 rev = cmdutil.finddate(ui, repo, date)
7207 rev = cmdutil.finddate(ui, repo, date)
7205
7208
7206 # if we defined a bookmark, we have to remember the original name
7209 # if we defined a bookmark, we have to remember the original name
7207 brev = rev
7210 brev = rev
7208 rev = scmutil.revsingle(repo, rev, rev).rev()
7211 rev = scmutil.revsingle(repo, rev, rev).rev()
7209
7212
7210 if check:
7213 if check:
7211 cmdutil.bailifchanged(repo, merge=False)
7214 cmdutil.bailifchanged(repo, merge=False)
7212
7215
7213 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7216 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7214
7217
7215 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7218 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7216
7219
7217 @command('verify', [])
7220 @command('verify', [])
7218 def verify(ui, repo):
7221 def verify(ui, repo):
7219 """verify the integrity of the repository
7222 """verify the integrity of the repository
7220
7223
7221 Verify the integrity of the current repository.
7224 Verify the integrity of the current repository.
7222
7225
7223 This will perform an extensive check of the repository's
7226 This will perform an extensive check of the repository's
7224 integrity, validating the hashes and checksums of each entry in
7227 integrity, validating the hashes and checksums of each entry in
7225 the changelog, manifest, and tracked files, as well as the
7228 the changelog, manifest, and tracked files, as well as the
7226 integrity of their crosslinks and indices.
7229 integrity of their crosslinks and indices.
7227
7230
7228 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7231 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7229 for more information about recovery from corruption of the
7232 for more information about recovery from corruption of the
7230 repository.
7233 repository.
7231
7234
7232 Returns 0 on success, 1 if errors are encountered.
7235 Returns 0 on success, 1 if errors are encountered.
7233 """
7236 """
7234 return hg.verify(repo)
7237 return hg.verify(repo)
7235
7238
7236 @command('version', [], norepo=True)
7239 @command('version', [], norepo=True)
7237 def version_(ui):
7240 def version_(ui):
7238 """output version and copyright information"""
7241 """output version and copyright information"""
7239 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7242 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7240 % util.version())
7243 % util.version())
7241 ui.status(_(
7244 ui.status(_(
7242 "(see https://mercurial-scm.org for more information)\n"
7245 "(see https://mercurial-scm.org for more information)\n"
7243 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7246 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7244 "This is free software; see the source for copying conditions. "
7247 "This is free software; see the source for copying conditions. "
7245 "There is NO\nwarranty; "
7248 "There is NO\nwarranty; "
7246 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7249 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7247 ))
7250 ))
7248
7251
7249 ui.note(_("\nEnabled extensions:\n\n"))
7252 ui.note(_("\nEnabled extensions:\n\n"))
7250 if ui.verbose:
7253 if ui.verbose:
7251 # format names and versions into columns
7254 # format names and versions into columns
7252 names = []
7255 names = []
7253 vers = []
7256 vers = []
7254 place = []
7257 place = []
7255 for name, module in extensions.extensions():
7258 for name, module in extensions.extensions():
7256 names.append(name)
7259 names.append(name)
7257 vers.append(extensions.moduleversion(module))
7260 vers.append(extensions.moduleversion(module))
7258 if extensions.ismoduleinternal(module):
7261 if extensions.ismoduleinternal(module):
7259 place.append(_("internal"))
7262 place.append(_("internal"))
7260 else:
7263 else:
7261 place.append(_("external"))
7264 place.append(_("external"))
7262 if names:
7265 if names:
7263 maxnamelen = max(len(n) for n in names)
7266 maxnamelen = max(len(n) for n in names)
7264 for i, name in enumerate(names):
7267 for i, name in enumerate(names):
7265 ui.write(" %-*s %s %s\n" %
7268 ui.write(" %-*s %s %s\n" %
7266 (maxnamelen, name, place[i], vers[i]))
7269 (maxnamelen, name, place[i], vers[i]))
7267
7270
7268 def loadcmdtable(ui, name, cmdtable):
7271 def loadcmdtable(ui, name, cmdtable):
7269 """Load command functions from specified cmdtable
7272 """Load command functions from specified cmdtable
7270 """
7273 """
7271 overrides = [cmd for cmd in cmdtable if cmd in table]
7274 overrides = [cmd for cmd in cmdtable if cmd in table]
7272 if overrides:
7275 if overrides:
7273 ui.warn(_("extension '%s' overrides commands: %s\n")
7276 ui.warn(_("extension '%s' overrides commands: %s\n")
7274 % (name, " ".join(overrides)))
7277 % (name, " ".join(overrides)))
7275 table.update(cmdtable)
7278 table.update(cmdtable)
@@ -1,607 +1,607 b''
1 # help.py - help data for mercurial
1 # help.py - help data for mercurial
2 #
2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import itertools
10 import itertools
11 import os
11 import os
12 import textwrap
12 import textwrap
13
13
14 from .i18n import (
14 from .i18n import (
15 _,
15 _,
16 gettext,
16 gettext,
17 )
17 )
18 from . import (
18 from . import (
19 cmdutil,
19 cmdutil,
20 encoding,
20 encoding,
21 error,
21 error,
22 extensions,
22 extensions,
23 filemerge,
23 filemerge,
24 fileset,
24 fileset,
25 minirst,
25 minirst,
26 revset,
26 revset,
27 templatefilters,
27 templatefilters,
28 templatekw,
28 templatekw,
29 templater,
29 templater,
30 util,
30 util,
31 )
31 )
32 from .hgweb import (
32 from .hgweb import (
33 webcommands,
33 webcommands,
34 )
34 )
35
35
36 _exclkeywords = [
36 _exclkeywords = [
37 "(DEPRECATED)",
37 "(DEPRECATED)",
38 "(EXPERIMENTAL)",
38 "(EXPERIMENTAL)",
39 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
39 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
40 _("(DEPRECATED)"),
40 _("(DEPRECATED)"),
41 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
41 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
42 _("(EXPERIMENTAL)"),
42 _("(EXPERIMENTAL)"),
43 ]
43 ]
44
44
45 def listexts(header, exts, indent=1, showdeprecated=False):
45 def listexts(header, exts, indent=1, showdeprecated=False):
46 '''return a text listing of the given extensions'''
46 '''return a text listing of the given extensions'''
47 rst = []
47 rst = []
48 if exts:
48 if exts:
49 for name, desc in sorted(exts.iteritems()):
49 for name, desc in sorted(exts.iteritems()):
50 if not showdeprecated and any(w in desc for w in _exclkeywords):
50 if not showdeprecated and any(w in desc for w in _exclkeywords):
51 continue
51 continue
52 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
52 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
53 if rst:
53 if rst:
54 rst.insert(0, '\n%s\n\n' % header)
54 rst.insert(0, '\n%s\n\n' % header)
55 return rst
55 return rst
56
56
57 def extshelp(ui):
57 def extshelp(ui):
58 rst = loaddoc('extensions')(ui).splitlines(True)
58 rst = loaddoc('extensions')(ui).splitlines(True)
59 rst.extend(listexts(
59 rst.extend(listexts(
60 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
60 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
61 rst.extend(listexts(_('disabled extensions:'), extensions.disabled()))
61 rst.extend(listexts(_('disabled extensions:'), extensions.disabled()))
62 doc = ''.join(rst)
62 doc = ''.join(rst)
63 return doc
63 return doc
64
64
65 def optrst(header, options, verbose):
65 def optrst(header, options, verbose):
66 data = []
66 data = []
67 multioccur = False
67 multioccur = False
68 for option in options:
68 for option in options:
69 if len(option) == 5:
69 if len(option) == 5:
70 shortopt, longopt, default, desc, optlabel = option
70 shortopt, longopt, default, desc, optlabel = option
71 else:
71 else:
72 shortopt, longopt, default, desc = option
72 shortopt, longopt, default, desc = option
73 optlabel = _("VALUE") # default label
73 optlabel = _("VALUE") # default label
74
74
75 if not verbose and any(w in desc for w in _exclkeywords):
75 if not verbose and any(w in desc for w in _exclkeywords):
76 continue
76 continue
77
77
78 so = ''
78 so = ''
79 if shortopt:
79 if shortopt:
80 so = '-' + shortopt
80 so = '-' + shortopt
81 lo = '--' + longopt
81 lo = '--' + longopt
82 if default:
82 if default:
83 desc += _(" (default: %s)") % default
83 desc += _(" (default: %s)") % default
84
84
85 if isinstance(default, list):
85 if isinstance(default, list):
86 lo += " %s [+]" % optlabel
86 lo += " %s [+]" % optlabel
87 multioccur = True
87 multioccur = True
88 elif (default is not None) and not isinstance(default, bool):
88 elif (default is not None) and not isinstance(default, bool):
89 lo += " %s" % optlabel
89 lo += " %s" % optlabel
90
90
91 data.append((so, lo, desc))
91 data.append((so, lo, desc))
92
92
93 if multioccur:
93 if multioccur:
94 header += (_(" ([+] can be repeated)"))
94 header += (_(" ([+] can be repeated)"))
95
95
96 rst = ['\n%s:\n\n' % header]
96 rst = ['\n%s:\n\n' % header]
97 rst.extend(minirst.maketable(data, 1))
97 rst.extend(minirst.maketable(data, 1))
98
98
99 return ''.join(rst)
99 return ''.join(rst)
100
100
101 def indicateomitted(rst, omitted, notomitted=None):
101 def indicateomitted(rst, omitted, notomitted=None):
102 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
102 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
103 if notomitted:
103 if notomitted:
104 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
104 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
105
105
106 def filtercmd(ui, cmd, kw, doc):
106 def filtercmd(ui, cmd, kw, doc):
107 if not ui.debugflag and cmd.startswith("debug") and kw != "debug":
107 if not ui.debugflag and cmd.startswith("debug") and kw != "debug":
108 return True
108 return True
109 if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
109 if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
110 return True
110 return True
111 return False
111 return False
112
112
113 def topicmatch(ui, kw):
113 def topicmatch(ui, kw):
114 """Return help topics matching kw.
114 """Return help topics matching kw.
115
115
116 Returns {'section': [(name, summary), ...], ...} where section is
116 Returns {'section': [(name, summary), ...], ...} where section is
117 one of topics, commands, extensions, or extensioncommands.
117 one of topics, commands, extensions, or extensioncommands.
118 """
118 """
119 kw = encoding.lower(kw)
119 kw = encoding.lower(kw)
120 def lowercontains(container):
120 def lowercontains(container):
121 return kw in encoding.lower(container) # translated in helptable
121 return kw in encoding.lower(container) # translated in helptable
122 results = {'topics': [],
122 results = {'topics': [],
123 'commands': [],
123 'commands': [],
124 'extensions': [],
124 'extensions': [],
125 'extensioncommands': [],
125 'extensioncommands': [],
126 }
126 }
127 for names, header, doc in helptable:
127 for names, header, doc in helptable:
128 # Old extensions may use a str as doc.
128 # Old extensions may use a str as doc.
129 if (sum(map(lowercontains, names))
129 if (sum(map(lowercontains, names))
130 or lowercontains(header)
130 or lowercontains(header)
131 or (callable(doc) and lowercontains(doc(ui)))):
131 or (callable(doc) and lowercontains(doc(ui)))):
132 results['topics'].append((names[0], header))
132 results['topics'].append((names[0], header))
133 from . import commands # avoid cycle
133 from . import commands # avoid cycle
134 for cmd, entry in commands.table.iteritems():
134 for cmd, entry in commands.table.iteritems():
135 if len(entry) == 3:
135 if len(entry) == 3:
136 summary = entry[2]
136 summary = entry[2]
137 else:
137 else:
138 summary = ''
138 summary = ''
139 # translate docs *before* searching there
139 # translate docs *before* searching there
140 docs = _(getattr(entry[0], '__doc__', None)) or ''
140 docs = _(getattr(entry[0], '__doc__', None)) or ''
141 if kw in cmd or lowercontains(summary) or lowercontains(docs):
141 if kw in cmd or lowercontains(summary) or lowercontains(docs):
142 doclines = docs.splitlines()
142 doclines = docs.splitlines()
143 if doclines:
143 if doclines:
144 summary = doclines[0]
144 summary = doclines[0]
145 cmdname = cmd.partition('|')[0].lstrip('^')
145 cmdname = cmd.partition('|')[0].lstrip('^')
146 if filtercmd(ui, cmdname, kw, docs):
146 if filtercmd(ui, cmdname, kw, docs):
147 continue
147 continue
148 results['commands'].append((cmdname, summary))
148 results['commands'].append((cmdname, summary))
149 for name, docs in itertools.chain(
149 for name, docs in itertools.chain(
150 extensions.enabled(False).iteritems(),
150 extensions.enabled(False).iteritems(),
151 extensions.disabled().iteritems()):
151 extensions.disabled().iteritems()):
152 if not docs:
152 if not docs:
153 continue
153 continue
154 mod = extensions.load(ui, name, '')
154 mod = extensions.load(ui, name, '')
155 name = name.rpartition('.')[-1]
155 name = name.rpartition('.')[-1]
156 if lowercontains(name) or lowercontains(docs):
156 if lowercontains(name) or lowercontains(docs):
157 # extension docs are already translated
157 # extension docs are already translated
158 results['extensions'].append((name, docs.splitlines()[0]))
158 results['extensions'].append((name, docs.splitlines()[0]))
159 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
159 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
160 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
160 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
161 cmdname = cmd.partition('|')[0].lstrip('^')
161 cmdname = cmd.partition('|')[0].lstrip('^')
162 if entry[0].__doc__:
162 if entry[0].__doc__:
163 cmddoc = gettext(entry[0].__doc__).splitlines()[0]
163 cmddoc = gettext(entry[0].__doc__).splitlines()[0]
164 else:
164 else:
165 cmddoc = _('(no help text available)')
165 cmddoc = _('(no help text available)')
166 if filtercmd(ui, cmdname, kw, cmddoc):
166 if filtercmd(ui, cmdname, kw, cmddoc):
167 continue
167 continue
168 results['extensioncommands'].append((cmdname, cmddoc))
168 results['extensioncommands'].append((cmdname, cmddoc))
169 return results
169 return results
170
170
171 def loaddoc(topic, subdir=None):
171 def loaddoc(topic, subdir=None):
172 """Return a delayed loader for help/topic.txt."""
172 """Return a delayed loader for help/topic.txt."""
173
173
174 def loader(ui):
174 def loader(ui):
175 docdir = os.path.join(util.datapath, 'help')
175 docdir = os.path.join(util.datapath, 'help')
176 if subdir:
176 if subdir:
177 docdir = os.path.join(docdir, subdir)
177 docdir = os.path.join(docdir, subdir)
178 path = os.path.join(docdir, topic + ".txt")
178 path = os.path.join(docdir, topic + ".txt")
179 doc = gettext(util.readfile(path))
179 doc = gettext(util.readfile(path))
180 for rewriter in helphooks.get(topic, []):
180 for rewriter in helphooks.get(topic, []):
181 doc = rewriter(ui, topic, doc)
181 doc = rewriter(ui, topic, doc)
182 return doc
182 return doc
183
183
184 return loader
184 return loader
185
185
186 internalstable = sorted([
186 internalstable = sorted([
187 (['bundles'], _('container for exchange of repository data'),
187 (['bundles'], _('Bundles'),
188 loaddoc('bundles', subdir='internals')),
188 loaddoc('bundles', subdir='internals')),
189 (['changegroups'], _('representation of revlog data'),
189 (['changegroups'], _('Changegroups'),
190 loaddoc('changegroups', subdir='internals')),
190 loaddoc('changegroups', subdir='internals')),
191 (['requirements'], _('repository requirements'),
191 (['requirements'], _('Repository Requirements'),
192 loaddoc('requirements', subdir='internals')),
192 loaddoc('requirements', subdir='internals')),
193 (['revlogs'], _('revision storage mechanism'),
193 (['revlogs'], _('Revision Logs'),
194 loaddoc('revlogs', subdir='internals')),
194 loaddoc('revlogs', subdir='internals')),
195 ])
195 ])
196
196
197 def internalshelp(ui):
197 def internalshelp(ui):
198 """Generate the index for the "internals" topic."""
198 """Generate the index for the "internals" topic."""
199 lines = []
199 lines = []
200 for names, header, doc in internalstable:
200 for names, header, doc in internalstable:
201 lines.append(' :%s: %s\n' % (names[0], header))
201 lines.append(' :%s: %s\n' % (names[0], header))
202
202
203 return ''.join(lines)
203 return ''.join(lines)
204
204
205 helptable = sorted([
205 helptable = sorted([
206 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
206 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
207 (["dates"], _("Date Formats"), loaddoc('dates')),
207 (["dates"], _("Date Formats"), loaddoc('dates')),
208 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
208 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
209 (['environment', 'env'], _('Environment Variables'),
209 (['environment', 'env'], _('Environment Variables'),
210 loaddoc('environment')),
210 loaddoc('environment')),
211 (['revisions', 'revs'], _('Specifying Single Revisions'),
211 (['revisions', 'revs'], _('Specifying Single Revisions'),
212 loaddoc('revisions')),
212 loaddoc('revisions')),
213 (['multirevs', 'mrevs'], _('Specifying Multiple Revisions'),
213 (['multirevs', 'mrevs'], _('Specifying Multiple Revisions'),
214 loaddoc('multirevs')),
214 loaddoc('multirevs')),
215 (['revsets', 'revset'], _("Specifying Revision Sets"), loaddoc('revsets')),
215 (['revsets', 'revset'], _("Specifying Revision Sets"), loaddoc('revsets')),
216 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
216 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
217 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
217 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
218 (['merge-tools', 'mergetools'], _('Merge Tools'), loaddoc('merge-tools')),
218 (['merge-tools', 'mergetools'], _('Merge Tools'), loaddoc('merge-tools')),
219 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
219 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
220 loaddoc('templates')),
220 loaddoc('templates')),
221 (['urls'], _('URL Paths'), loaddoc('urls')),
221 (['urls'], _('URL Paths'), loaddoc('urls')),
222 (["extensions"], _("Using Additional Features"), extshelp),
222 (["extensions"], _("Using Additional Features"), extshelp),
223 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
223 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
224 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
224 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
225 (["glossary"], _("Glossary"), loaddoc('glossary')),
225 (["glossary"], _("Glossary"), loaddoc('glossary')),
226 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
226 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
227 loaddoc('hgignore')),
227 loaddoc('hgignore')),
228 (["phases"], _("Working with Phases"), loaddoc('phases')),
228 (["phases"], _("Working with Phases"), loaddoc('phases')),
229 (['scripting'], _('Using Mercurial from scripts and automation'),
229 (['scripting'], _('Using Mercurial from scripts and automation'),
230 loaddoc('scripting')),
230 loaddoc('scripting')),
231 (['internals'], _("Technical implementation topics"),
231 (['internals'], _("Technical implementation topics"),
232 internalshelp),
232 internalshelp),
233 ])
233 ])
234
234
235 # Maps topics with sub-topics to a list of their sub-topics.
235 # Maps topics with sub-topics to a list of their sub-topics.
236 subtopics = {
236 subtopics = {
237 'internals': internalstable,
237 'internals': internalstable,
238 }
238 }
239
239
240 # Map topics to lists of callable taking the current topic help and
240 # Map topics to lists of callable taking the current topic help and
241 # returning the updated version
241 # returning the updated version
242 helphooks = {}
242 helphooks = {}
243
243
244 def addtopichook(topic, rewriter):
244 def addtopichook(topic, rewriter):
245 helphooks.setdefault(topic, []).append(rewriter)
245 helphooks.setdefault(topic, []).append(rewriter)
246
246
247 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
247 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
248 """Extract docstring from the items key to function mapping, build a
248 """Extract docstring from the items key to function mapping, build a
249 single documentation block and use it to overwrite the marker in doc.
249 single documentation block and use it to overwrite the marker in doc.
250 """
250 """
251 entries = []
251 entries = []
252 for name in sorted(items):
252 for name in sorted(items):
253 text = (items[name].__doc__ or '').rstrip()
253 text = (items[name].__doc__ or '').rstrip()
254 if (not text
254 if (not text
255 or not ui.verbose and any(w in text for w in _exclkeywords)):
255 or not ui.verbose and any(w in text for w in _exclkeywords)):
256 continue
256 continue
257 text = gettext(text)
257 text = gettext(text)
258 if dedent:
258 if dedent:
259 text = textwrap.dedent(text)
259 text = textwrap.dedent(text)
260 lines = text.splitlines()
260 lines = text.splitlines()
261 doclines = [(lines[0])]
261 doclines = [(lines[0])]
262 for l in lines[1:]:
262 for l in lines[1:]:
263 # Stop once we find some Python doctest
263 # Stop once we find some Python doctest
264 if l.strip().startswith('>>>'):
264 if l.strip().startswith('>>>'):
265 break
265 break
266 if dedent:
266 if dedent:
267 doclines.append(l.rstrip())
267 doclines.append(l.rstrip())
268 else:
268 else:
269 doclines.append(' ' + l.strip())
269 doclines.append(' ' + l.strip())
270 entries.append('\n'.join(doclines))
270 entries.append('\n'.join(doclines))
271 entries = '\n\n'.join(entries)
271 entries = '\n\n'.join(entries)
272 return doc.replace(marker, entries)
272 return doc.replace(marker, entries)
273
273
274 def addtopicsymbols(topic, marker, symbols, dedent=False):
274 def addtopicsymbols(topic, marker, symbols, dedent=False):
275 def add(ui, topic, doc):
275 def add(ui, topic, doc):
276 return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
276 return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
277 addtopichook(topic, add)
277 addtopichook(topic, add)
278
278
279 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
279 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
280 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
280 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
281 filemerge.internalsdoc)
281 filemerge.internalsdoc)
282 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
282 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
283 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
283 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
284 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
284 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
285 addtopicsymbols('templates', '.. functionsmarker', templater.funcs)
285 addtopicsymbols('templates', '.. functionsmarker', templater.funcs)
286 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
286 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
287 dedent=True)
287 dedent=True)
288
288
289 def help_(ui, name, unknowncmd=False, full=True, subtopic=None, **opts):
289 def help_(ui, name, unknowncmd=False, full=True, subtopic=None, **opts):
290 '''
290 '''
291 Generate the help for 'name' as unformatted restructured text. If
291 Generate the help for 'name' as unformatted restructured text. If
292 'name' is None, describe the commands available.
292 'name' is None, describe the commands available.
293 '''
293 '''
294
294
295 from . import commands # avoid cycle
295 from . import commands # avoid cycle
296
296
297 def helpcmd(name, subtopic=None):
297 def helpcmd(name, subtopic=None):
298 try:
298 try:
299 aliases, entry = cmdutil.findcmd(name, commands.table,
299 aliases, entry = cmdutil.findcmd(name, commands.table,
300 strict=unknowncmd)
300 strict=unknowncmd)
301 except error.AmbiguousCommand as inst:
301 except error.AmbiguousCommand as inst:
302 # py3k fix: except vars can't be used outside the scope of the
302 # py3k fix: except vars can't be used outside the scope of the
303 # except block, nor can be used inside a lambda. python issue4617
303 # except block, nor can be used inside a lambda. python issue4617
304 prefix = inst.args[0]
304 prefix = inst.args[0]
305 select = lambda c: c.lstrip('^').startswith(prefix)
305 select = lambda c: c.lstrip('^').startswith(prefix)
306 rst = helplist(select)
306 rst = helplist(select)
307 return rst
307 return rst
308
308
309 rst = []
309 rst = []
310
310
311 # check if it's an invalid alias and display its error if it is
311 # check if it's an invalid alias and display its error if it is
312 if getattr(entry[0], 'badalias', None):
312 if getattr(entry[0], 'badalias', None):
313 rst.append(entry[0].badalias + '\n')
313 rst.append(entry[0].badalias + '\n')
314 if entry[0].unknowncmd:
314 if entry[0].unknowncmd:
315 try:
315 try:
316 rst.extend(helpextcmd(entry[0].cmdname))
316 rst.extend(helpextcmd(entry[0].cmdname))
317 except error.UnknownCommand:
317 except error.UnknownCommand:
318 pass
318 pass
319 return rst
319 return rst
320
320
321 # synopsis
321 # synopsis
322 if len(entry) > 2:
322 if len(entry) > 2:
323 if entry[2].startswith('hg'):
323 if entry[2].startswith('hg'):
324 rst.append("%s\n" % entry[2])
324 rst.append("%s\n" % entry[2])
325 else:
325 else:
326 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
326 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
327 else:
327 else:
328 rst.append('hg %s\n' % aliases[0])
328 rst.append('hg %s\n' % aliases[0])
329 # aliases
329 # aliases
330 if full and not ui.quiet and len(aliases) > 1:
330 if full and not ui.quiet and len(aliases) > 1:
331 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
331 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
332 rst.append('\n')
332 rst.append('\n')
333
333
334 # description
334 # description
335 doc = gettext(entry[0].__doc__)
335 doc = gettext(entry[0].__doc__)
336 if not doc:
336 if not doc:
337 doc = _("(no help text available)")
337 doc = _("(no help text available)")
338 if util.safehasattr(entry[0], 'definition'): # aliased command
338 if util.safehasattr(entry[0], 'definition'): # aliased command
339 source = entry[0].source
339 source = entry[0].source
340 if entry[0].definition.startswith('!'): # shell alias
340 if entry[0].definition.startswith('!'): # shell alias
341 doc = (_('shell alias for::\n\n %s\n\ndefined by: %s\n') %
341 doc = (_('shell alias for::\n\n %s\n\ndefined by: %s\n') %
342 (entry[0].definition[1:], source))
342 (entry[0].definition[1:], source))
343 else:
343 else:
344 doc = (_('alias for: hg %s\n\n%s\n\ndefined by: %s\n') %
344 doc = (_('alias for: hg %s\n\n%s\n\ndefined by: %s\n') %
345 (entry[0].definition, doc, source))
345 (entry[0].definition, doc, source))
346 doc = doc.splitlines(True)
346 doc = doc.splitlines(True)
347 if ui.quiet or not full:
347 if ui.quiet or not full:
348 rst.append(doc[0])
348 rst.append(doc[0])
349 else:
349 else:
350 rst.extend(doc)
350 rst.extend(doc)
351 rst.append('\n')
351 rst.append('\n')
352
352
353 # check if this command shadows a non-trivial (multi-line)
353 # check if this command shadows a non-trivial (multi-line)
354 # extension help text
354 # extension help text
355 try:
355 try:
356 mod = extensions.find(name)
356 mod = extensions.find(name)
357 doc = gettext(mod.__doc__) or ''
357 doc = gettext(mod.__doc__) or ''
358 if '\n' in doc.strip():
358 if '\n' in doc.strip():
359 msg = _('(use "hg help -e %s" to show help for '
359 msg = _('(use "hg help -e %s" to show help for '
360 'the %s extension)') % (name, name)
360 'the %s extension)') % (name, name)
361 rst.append('\n%s\n' % msg)
361 rst.append('\n%s\n' % msg)
362 except KeyError:
362 except KeyError:
363 pass
363 pass
364
364
365 # options
365 # options
366 if not ui.quiet and entry[1]:
366 if not ui.quiet and entry[1]:
367 rst.append(optrst(_("options"), entry[1], ui.verbose))
367 rst.append(optrst(_("options"), entry[1], ui.verbose))
368
368
369 if ui.verbose:
369 if ui.verbose:
370 rst.append(optrst(_("global options"),
370 rst.append(optrst(_("global options"),
371 commands.globalopts, ui.verbose))
371 commands.globalopts, ui.verbose))
372
372
373 if not ui.verbose:
373 if not ui.verbose:
374 if not full:
374 if not full:
375 rst.append(_('\n(use "hg %s -h" to show more help)\n')
375 rst.append(_('\n(use "hg %s -h" to show more help)\n')
376 % name)
376 % name)
377 elif not ui.quiet:
377 elif not ui.quiet:
378 rst.append(_('\n(some details hidden, use --verbose '
378 rst.append(_('\n(some details hidden, use --verbose '
379 'to show complete help)'))
379 'to show complete help)'))
380
380
381 return rst
381 return rst
382
382
383
383
384 def helplist(select=None, **opts):
384 def helplist(select=None, **opts):
385 # list of commands
385 # list of commands
386 if name == "shortlist":
386 if name == "shortlist":
387 header = _('basic commands:\n\n')
387 header = _('basic commands:\n\n')
388 elif name == "debug":
388 elif name == "debug":
389 header = _('debug commands (internal and unsupported):\n\n')
389 header = _('debug commands (internal and unsupported):\n\n')
390 else:
390 else:
391 header = _('list of commands:\n\n')
391 header = _('list of commands:\n\n')
392
392
393 h = {}
393 h = {}
394 cmds = {}
394 cmds = {}
395 for c, e in commands.table.iteritems():
395 for c, e in commands.table.iteritems():
396 f = c.partition("|")[0]
396 f = c.partition("|")[0]
397 if select and not select(f):
397 if select and not select(f):
398 continue
398 continue
399 if (not select and name != 'shortlist' and
399 if (not select and name != 'shortlist' and
400 e[0].__module__ != commands.__name__):
400 e[0].__module__ != commands.__name__):
401 continue
401 continue
402 if name == "shortlist" and not f.startswith("^"):
402 if name == "shortlist" and not f.startswith("^"):
403 continue
403 continue
404 f = f.lstrip("^")
404 f = f.lstrip("^")
405 doc = e[0].__doc__
405 doc = e[0].__doc__
406 if filtercmd(ui, f, name, doc):
406 if filtercmd(ui, f, name, doc):
407 continue
407 continue
408 doc = gettext(doc)
408 doc = gettext(doc)
409 if not doc:
409 if not doc:
410 doc = _("(no help text available)")
410 doc = _("(no help text available)")
411 h[f] = doc.splitlines()[0].rstrip()
411 h[f] = doc.splitlines()[0].rstrip()
412 cmds[f] = c.lstrip("^")
412 cmds[f] = c.lstrip("^")
413
413
414 rst = []
414 rst = []
415 if not h:
415 if not h:
416 if not ui.quiet:
416 if not ui.quiet:
417 rst.append(_('no commands defined\n'))
417 rst.append(_('no commands defined\n'))
418 return rst
418 return rst
419
419
420 if not ui.quiet:
420 if not ui.quiet:
421 rst.append(header)
421 rst.append(header)
422 fns = sorted(h)
422 fns = sorted(h)
423 for f in fns:
423 for f in fns:
424 if ui.verbose:
424 if ui.verbose:
425 commacmds = cmds[f].replace("|",", ")
425 commacmds = cmds[f].replace("|",", ")
426 rst.append(" :%s: %s\n" % (commacmds, h[f]))
426 rst.append(" :%s: %s\n" % (commacmds, h[f]))
427 else:
427 else:
428 rst.append(' :%s: %s\n' % (f, h[f]))
428 rst.append(' :%s: %s\n' % (f, h[f]))
429
429
430 ex = opts.get
430 ex = opts.get
431 anyopts = (ex('keyword') or not (ex('command') or ex('extension')))
431 anyopts = (ex('keyword') or not (ex('command') or ex('extension')))
432 if not name and anyopts:
432 if not name and anyopts:
433 exts = listexts(_('enabled extensions:'), extensions.enabled())
433 exts = listexts(_('enabled extensions:'), extensions.enabled())
434 if exts:
434 if exts:
435 rst.append('\n')
435 rst.append('\n')
436 rst.extend(exts)
436 rst.extend(exts)
437
437
438 rst.append(_("\nadditional help topics:\n\n"))
438 rst.append(_("\nadditional help topics:\n\n"))
439 topics = []
439 topics = []
440 for names, header, doc in helptable:
440 for names, header, doc in helptable:
441 topics.append((names[0], header))
441 topics.append((names[0], header))
442 for t, desc in topics:
442 for t, desc in topics:
443 rst.append(" :%s: %s\n" % (t, desc))
443 rst.append(" :%s: %s\n" % (t, desc))
444
444
445 if ui.quiet:
445 if ui.quiet:
446 pass
446 pass
447 elif ui.verbose:
447 elif ui.verbose:
448 rst.append('\n%s\n' % optrst(_("global options"),
448 rst.append('\n%s\n' % optrst(_("global options"),
449 commands.globalopts, ui.verbose))
449 commands.globalopts, ui.verbose))
450 if name == 'shortlist':
450 if name == 'shortlist':
451 rst.append(_('\n(use "hg help" for the full list '
451 rst.append(_('\n(use "hg help" for the full list '
452 'of commands)\n'))
452 'of commands)\n'))
453 else:
453 else:
454 if name == 'shortlist':
454 if name == 'shortlist':
455 rst.append(_('\n(use "hg help" for the full list of commands '
455 rst.append(_('\n(use "hg help" for the full list of commands '
456 'or "hg -v" for details)\n'))
456 'or "hg -v" for details)\n'))
457 elif name and not full:
457 elif name and not full:
458 rst.append(_('\n(use "hg help %s" to show the full help '
458 rst.append(_('\n(use "hg help %s" to show the full help '
459 'text)\n') % name)
459 'text)\n') % name)
460 elif name and cmds and name in cmds.keys():
460 elif name and cmds and name in cmds.keys():
461 rst.append(_('\n(use "hg help -v -e %s" to show built-in '
461 rst.append(_('\n(use "hg help -v -e %s" to show built-in '
462 'aliases and global options)\n') % name)
462 'aliases and global options)\n') % name)
463 else:
463 else:
464 rst.append(_('\n(use "hg help -v%s" to show built-in aliases '
464 rst.append(_('\n(use "hg help -v%s" to show built-in aliases '
465 'and global options)\n')
465 'and global options)\n')
466 % (name and " " + name or ""))
466 % (name and " " + name or ""))
467 return rst
467 return rst
468
468
469 def helptopic(name, subtopic=None):
469 def helptopic(name, subtopic=None):
470 # Look for sub-topic entry first.
470 # Look for sub-topic entry first.
471 header, doc = None, None
471 header, doc = None, None
472 if subtopic and name in subtopics:
472 if subtopic and name in subtopics:
473 for names, header, doc in subtopics[name]:
473 for names, header, doc in subtopics[name]:
474 if subtopic in names:
474 if subtopic in names:
475 break
475 break
476
476
477 if not header:
477 if not header:
478 for names, header, doc in helptable:
478 for names, header, doc in helptable:
479 if name in names:
479 if name in names:
480 break
480 break
481 else:
481 else:
482 raise error.UnknownCommand(name)
482 raise error.UnknownCommand(name)
483
483
484 rst = [minirst.section(header)]
484 rst = [minirst.section(header)]
485
485
486 # description
486 # description
487 if not doc:
487 if not doc:
488 rst.append(" %s\n" % _("(no help text available)"))
488 rst.append(" %s\n" % _("(no help text available)"))
489 if callable(doc):
489 if callable(doc):
490 rst += [" %s\n" % l for l in doc(ui).splitlines()]
490 rst += [" %s\n" % l for l in doc(ui).splitlines()]
491
491
492 if not ui.verbose:
492 if not ui.verbose:
493 omitted = _('(some details hidden, use --verbose'
493 omitted = _('(some details hidden, use --verbose'
494 ' to show complete help)')
494 ' to show complete help)')
495 indicateomitted(rst, omitted)
495 indicateomitted(rst, omitted)
496
496
497 try:
497 try:
498 cmdutil.findcmd(name, commands.table)
498 cmdutil.findcmd(name, commands.table)
499 rst.append(_('\nuse "hg help -c %s" to see help for '
499 rst.append(_('\nuse "hg help -c %s" to see help for '
500 'the %s command\n') % (name, name))
500 'the %s command\n') % (name, name))
501 except error.UnknownCommand:
501 except error.UnknownCommand:
502 pass
502 pass
503 return rst
503 return rst
504
504
505 def helpext(name, subtopic=None):
505 def helpext(name, subtopic=None):
506 try:
506 try:
507 mod = extensions.find(name)
507 mod = extensions.find(name)
508 doc = gettext(mod.__doc__) or _('no help text available')
508 doc = gettext(mod.__doc__) or _('no help text available')
509 except KeyError:
509 except KeyError:
510 mod = None
510 mod = None
511 doc = extensions.disabledext(name)
511 doc = extensions.disabledext(name)
512 if not doc:
512 if not doc:
513 raise error.UnknownCommand(name)
513 raise error.UnknownCommand(name)
514
514
515 if '\n' not in doc:
515 if '\n' not in doc:
516 head, tail = doc, ""
516 head, tail = doc, ""
517 else:
517 else:
518 head, tail = doc.split('\n', 1)
518 head, tail = doc.split('\n', 1)
519 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
519 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
520 if tail:
520 if tail:
521 rst.extend(tail.splitlines(True))
521 rst.extend(tail.splitlines(True))
522 rst.append('\n')
522 rst.append('\n')
523
523
524 if not ui.verbose:
524 if not ui.verbose:
525 omitted = _('(some details hidden, use --verbose'
525 omitted = _('(some details hidden, use --verbose'
526 ' to show complete help)')
526 ' to show complete help)')
527 indicateomitted(rst, omitted)
527 indicateomitted(rst, omitted)
528
528
529 if mod:
529 if mod:
530 try:
530 try:
531 ct = mod.cmdtable
531 ct = mod.cmdtable
532 except AttributeError:
532 except AttributeError:
533 ct = {}
533 ct = {}
534 modcmds = set([c.partition('|')[0] for c in ct])
534 modcmds = set([c.partition('|')[0] for c in ct])
535 rst.extend(helplist(modcmds.__contains__))
535 rst.extend(helplist(modcmds.__contains__))
536 else:
536 else:
537 rst.append(_('(use "hg help extensions" for information on enabling'
537 rst.append(_('(use "hg help extensions" for information on enabling'
538 ' extensions)\n'))
538 ' extensions)\n'))
539 return rst
539 return rst
540
540
541 def helpextcmd(name, subtopic=None):
541 def helpextcmd(name, subtopic=None):
542 cmd, ext, mod = extensions.disabledcmd(ui, name,
542 cmd, ext, mod = extensions.disabledcmd(ui, name,
543 ui.configbool('ui', 'strict'))
543 ui.configbool('ui', 'strict'))
544 doc = gettext(mod.__doc__).splitlines()[0]
544 doc = gettext(mod.__doc__).splitlines()[0]
545
545
546 rst = listexts(_("'%s' is provided by the following "
546 rst = listexts(_("'%s' is provided by the following "
547 "extension:") % cmd, {ext: doc}, indent=4,
547 "extension:") % cmd, {ext: doc}, indent=4,
548 showdeprecated=True)
548 showdeprecated=True)
549 rst.append('\n')
549 rst.append('\n')
550 rst.append(_('(use "hg help extensions" for information on enabling '
550 rst.append(_('(use "hg help extensions" for information on enabling '
551 'extensions)\n'))
551 'extensions)\n'))
552 return rst
552 return rst
553
553
554
554
555 rst = []
555 rst = []
556 kw = opts.get('keyword')
556 kw = opts.get('keyword')
557 if kw or name is None and any(opts[o] for o in opts):
557 if kw or name is None and any(opts[o] for o in opts):
558 matches = topicmatch(ui, name or '')
558 matches = topicmatch(ui, name or '')
559 helpareas = []
559 helpareas = []
560 if opts.get('extension'):
560 if opts.get('extension'):
561 helpareas += [('extensions', _('Extensions'))]
561 helpareas += [('extensions', _('Extensions'))]
562 if opts.get('command'):
562 if opts.get('command'):
563 helpareas += [('commands', _('Commands'))]
563 helpareas += [('commands', _('Commands'))]
564 if not helpareas:
564 if not helpareas:
565 helpareas = [('topics', _('Topics')),
565 helpareas = [('topics', _('Topics')),
566 ('commands', _('Commands')),
566 ('commands', _('Commands')),
567 ('extensions', _('Extensions')),
567 ('extensions', _('Extensions')),
568 ('extensioncommands', _('Extension Commands'))]
568 ('extensioncommands', _('Extension Commands'))]
569 for t, title in helpareas:
569 for t, title in helpareas:
570 if matches[t]:
570 if matches[t]:
571 rst.append('%s:\n\n' % title)
571 rst.append('%s:\n\n' % title)
572 rst.extend(minirst.maketable(sorted(matches[t]), 1))
572 rst.extend(minirst.maketable(sorted(matches[t]), 1))
573 rst.append('\n')
573 rst.append('\n')
574 if not rst:
574 if not rst:
575 msg = _('no matches')
575 msg = _('no matches')
576 hint = _('try "hg help" for a list of topics')
576 hint = _('try "hg help" for a list of topics')
577 raise error.Abort(msg, hint=hint)
577 raise error.Abort(msg, hint=hint)
578 elif name and name != 'shortlist':
578 elif name and name != 'shortlist':
579 queries = []
579 queries = []
580 if unknowncmd:
580 if unknowncmd:
581 queries += [helpextcmd]
581 queries += [helpextcmd]
582 if opts.get('extension'):
582 if opts.get('extension'):
583 queries += [helpext]
583 queries += [helpext]
584 if opts.get('command'):
584 if opts.get('command'):
585 queries += [helpcmd]
585 queries += [helpcmd]
586 if not queries:
586 if not queries:
587 queries = (helptopic, helpcmd, helpext, helpextcmd)
587 queries = (helptopic, helpcmd, helpext, helpextcmd)
588 for f in queries:
588 for f in queries:
589 try:
589 try:
590 rst = f(name, subtopic)
590 rst = f(name, subtopic)
591 break
591 break
592 except error.UnknownCommand:
592 except error.UnknownCommand:
593 pass
593 pass
594 else:
594 else:
595 if unknowncmd:
595 if unknowncmd:
596 raise error.UnknownCommand(name)
596 raise error.UnknownCommand(name)
597 else:
597 else:
598 msg = _('no such help topic: %s') % name
598 msg = _('no such help topic: %s') % name
599 hint = _('try "hg help --keyword %s"') % name
599 hint = _('try "hg help --keyword %s"') % name
600 raise error.Abort(msg, hint=hint)
600 raise error.Abort(msg, hint=hint)
601 else:
601 else:
602 # program name
602 # program name
603 if not ui.quiet:
603 if not ui.quiet:
604 rst = [_("Mercurial Distributed SCM\n"), '\n']
604 rst = [_("Mercurial Distributed SCM\n"), '\n']
605 rst.extend(helplist(None, **opts))
605 rst.extend(helplist(None, **opts))
606
606
607 return ''.join(rst)
607 return ''.join(rst)
@@ -1,97 +1,94 b''
1 Bundles
2 =======
3
4 A bundle is a container for repository data.
1 A bundle is a container for repository data.
5
2
6 Bundles are used as standalone files as well as the interchange format
3 Bundles are used as standalone files as well as the interchange format
7 over the wire protocol used when two Mercurial peers communicate with
4 over the wire protocol used when two Mercurial peers communicate with
8 each other.
5 each other.
9
6
10 Headers
7 Headers
11 -------
8 =======
12
9
13 Bundles produced since Mercurial 0.7 (September 2005) have a 4 byte
10 Bundles produced since Mercurial 0.7 (September 2005) have a 4 byte
14 header identifying the major bundle type. The header always begins with
11 header identifying the major bundle type. The header always begins with
15 ``HG`` and the follow 2 bytes indicate the bundle type/version. Some
12 ``HG`` and the follow 2 bytes indicate the bundle type/version. Some
16 bundle types have additional data after this 4 byte header.
13 bundle types have additional data after this 4 byte header.
17
14
18 The following sections describe each bundle header/type.
15 The following sections describe each bundle header/type.
19
16
20 HG10
17 HG10
21 ----
18 ----
22
19
23 ``HG10`` headers indicate a *changegroup bundle*. This is the original
20 ``HG10`` headers indicate a *changegroup bundle*. This is the original
24 bundle format, so it is sometimes referred to as *bundle1*. It has been
21 bundle format, so it is sometimes referred to as *bundle1*. It has been
25 present since version 0.7 (released September 2005).
22 present since version 0.7 (released September 2005).
26
23
27 This header is followed by 2 bytes indicating the compression algorithm
24 This header is followed by 2 bytes indicating the compression algorithm
28 used for data that follows. All subsequent data following this
25 used for data that follows. All subsequent data following this
29 compression identifier is compressed according to the algorithm/method
26 compression identifier is compressed according to the algorithm/method
30 specified.
27 specified.
31
28
32 Supported algorithms include the following.
29 Supported algorithms include the following.
33
30
34 ``BZ``
31 ``BZ``
35 *bzip2* compression.
32 *bzip2* compression.
36
33
37 Bzip2 compressors emit a leading ``BZ`` header. Mercurial uses this
34 Bzip2 compressors emit a leading ``BZ`` header. Mercurial uses this
38 leading ``BZ`` as part of the bundle header. Therefore consumers
35 leading ``BZ`` as part of the bundle header. Therefore consumers
39 of bzip2 bundles need to *seed* the bzip2 decompressor with ``BZ`` or
36 of bzip2 bundles need to *seed* the bzip2 decompressor with ``BZ`` or
40 seek the input stream back to the beginning of the algorithm component
37 seek the input stream back to the beginning of the algorithm component
41 of the bundle header so that decompressor input is valid. This behavior
38 of the bundle header so that decompressor input is valid. This behavior
42 is unique among supported compression algorithms.
39 is unique among supported compression algorithms.
43
40
44 Supported since version 0.7 (released December 2006).
41 Supported since version 0.7 (released December 2006).
45
42
46 ``GZ``
43 ``GZ``
47 *zlib* compression.
44 *zlib* compression.
48
45
49 Supported since version 0.9.2 (released December 2006).
46 Supported since version 0.9.2 (released December 2006).
50
47
51 ``UN``
48 ``UN``
52 *Uncompressed* or no compression. Unmodified changegroup data follows.
49 *Uncompressed* or no compression. Unmodified changegroup data follows.
53
50
54 Supported since version 0.9.2 (released December 2006).
51 Supported since version 0.9.2 (released December 2006).
55
52
56 3rd party extensions may implement their own compression. However, no
53 3rd party extensions may implement their own compression. However, no
57 authority reserves values for their compression algorithm identifiers.
54 authority reserves values for their compression algorithm identifiers.
58
55
59 HG2X
56 HG2X
60 ----
57 ----
61
58
62 ``HG2X`` headers (where ``X`` is any value) denote a *bundle2* bundle.
59 ``HG2X`` headers (where ``X`` is any value) denote a *bundle2* bundle.
63 Bundle2 bundles are a container format for various kinds of repository
60 Bundle2 bundles are a container format for various kinds of repository
64 data and capabilities, beyond changegroup data (which was the only data
61 data and capabilities, beyond changegroup data (which was the only data
65 supported by ``HG10`` bundles.
62 supported by ``HG10`` bundles.
66
63
67 ``HG20`` is currently the only defined bundle2 version.
64 ``HG20`` is currently the only defined bundle2 version.
68
65
69 The ``HG20`` format is not yet documented here. See the inline comments
66 The ``HG20`` format is not yet documented here. See the inline comments
70 in ``mercurial/exchange.py`` for now.
67 in ``mercurial/exchange.py`` for now.
71
68
72 Initial ``HG20`` support was added in Mercurial 3.0 (released May
69 Initial ``HG20`` support was added in Mercurial 3.0 (released May
73 2014). However, bundle2 bundles were hidden behind an experimental flag
70 2014). However, bundle2 bundles were hidden behind an experimental flag
74 until version 3.5 (released August 2015), when they were enabled in the
71 until version 3.5 (released August 2015), when they were enabled in the
75 wire protocol. Various commands (including ``hg bundle``) did not
72 wire protocol. Various commands (including ``hg bundle``) did not
76 support generating bundle2 files until Mercurial 3.6 (released November
73 support generating bundle2 files until Mercurial 3.6 (released November
77 2015).
74 2015).
78
75
79 HGS1
76 HGS1
80 ----
77 ----
81
78
82 *Experimental*
79 *Experimental*
83
80
84 A ``HGS1`` header indicates a *streaming clone bundle*. This is a bundle
81 A ``HGS1`` header indicates a *streaming clone bundle*. This is a bundle
85 that contains raw revlog data from a repository store. (Typically revlog
82 that contains raw revlog data from a repository store. (Typically revlog
86 data is exchanged in the form of changegroups.)
83 data is exchanged in the form of changegroups.)
87
84
88 The purpose of *streaming clone bundles* are to *clone* repository data
85 The purpose of *streaming clone bundles* are to *clone* repository data
89 very efficiently.
86 very efficiently.
90
87
91 The ``HGS1`` header is always followed by 2 bytes indicating a
88 The ``HGS1`` header is always followed by 2 bytes indicating a
92 compression algorithm of the data that follows. Only ``UN``
89 compression algorithm of the data that follows. Only ``UN``
93 (uncompressed data) is currently allowed.
90 (uncompressed data) is currently allowed.
94
91
95 ``HGS1UN`` support was added as an experimental feature in version 3.6
92 ``HGS1UN`` support was added as an experimental feature in version 3.6
96 (released November 2015) as part of the initial offering of the *clone
93 (released November 2015) as part of the initial offering of the *clone
97 bundles* feature.
94 bundles* feature.
@@ -1,157 +1,153 b''
1 Changegroups
2 ============
3
4 Changegroups are representations of repository revlog data, specifically
1 Changegroups are representations of repository revlog data, specifically
5 the changelog, manifest, and filelogs.
2 the changelog, manifest, and filelogs.
6
3
7 There are 3 versions of changegroups: ``1``, ``2``, and ``3``. From a
4 There are 3 versions of changegroups: ``1``, ``2``, and ``3``. From a
8 high-level, versions ``1`` and ``2`` are almost exactly the same, with
5 high-level, versions ``1`` and ``2`` are almost exactly the same, with
9 the only difference being a header on entries in the changeset
6 the only difference being a header on entries in the changeset
10 segment. Version ``3`` adds support for exchanging treemanifests and
7 segment. Version ``3`` adds support for exchanging treemanifests and
11 includes revlog flags in the delta header.
8 includes revlog flags in the delta header.
12
9
13 Changegroups consists of 3 logical segments::
10 Changegroups consists of 3 logical segments::
14
11
15 +---------------------------------+
12 +---------------------------------+
16 | | | |
13 | | | |
17 | changeset | manifest | filelogs |
14 | changeset | manifest | filelogs |
18 | | | |
15 | | | |
19 +---------------------------------+
16 +---------------------------------+
20
17
21 The principle building block of each segment is a *chunk*. A *chunk*
18 The principle building block of each segment is a *chunk*. A *chunk*
22 is a framed piece of data::
19 is a framed piece of data::
23
20
24 +---------------------------------------+
21 +---------------------------------------+
25 | | |
22 | | |
26 | length | data |
23 | length | data |
27 | (32 bits) | <length> bytes |
24 | (32 bits) | <length> bytes |
28 | | |
25 | | |
29 +---------------------------------------+
26 +---------------------------------------+
30
27
31 Each chunk starts with a 32-bit big-endian signed integer indicating
28 Each chunk starts with a 32-bit big-endian signed integer indicating
32 the length of the raw data that follows.
29 the length of the raw data that follows.
33
30
34 There is a special case chunk that has 0 length (``0x00000000``). We
31 There is a special case chunk that has 0 length (``0x00000000``). We
35 call this an *empty chunk*.
32 call this an *empty chunk*.
36
33
37 Delta Groups
34 Delta Groups
38 ------------
35 ============
39
36
40 A *delta group* expresses the content of a revlog as a series of deltas,
37 A *delta group* expresses the content of a revlog as a series of deltas,
41 or patches against previous revisions.
38 or patches against previous revisions.
42
39
43 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
40 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
44 to signal the end of the delta group::
41 to signal the end of the delta group::
45
42
46 +------------------------------------------------------------------------+
43 +------------------------------------------------------------------------+
47 | | | | | |
44 | | | | | |
48 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
45 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
49 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
46 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
50 | | | | | |
47 | | | | | |
51 +------------------------------------------------------------+-----------+
48 +------------------------------------------------------------+-----------+
52
49
53 Each *chunk*'s data consists of the following::
50 Each *chunk*'s data consists of the following::
54
51
55 +-----------------------------------------+
52 +-----------------------------------------+
56 | | | |
53 | | | |
57 | delta header | mdiff header | delta |
54 | delta header | mdiff header | delta |
58 | (various) | (12 bytes) | (various) |
55 | (various) | (12 bytes) | (various) |
59 | | | |
56 | | | |
60 +-----------------------------------------+
57 +-----------------------------------------+
61
58
62 The *length* field is the byte length of the remaining 3 logical pieces
59 The *length* field is the byte length of the remaining 3 logical pieces
63 of data. The *delta* is a diff from an existing entry in the changelog.
60 of data. The *delta* is a diff from an existing entry in the changelog.
64
61
65 The *delta header* is different between versions ``1``, ``2``, and
62 The *delta header* is different between versions ``1``, ``2``, and
66 ``3`` of the changegroup format.
63 ``3`` of the changegroup format.
67
64
68 Version 1::
65 Version 1::
69
66
70 +------------------------------------------------------+
67 +------------------------------------------------------+
71 | | | | |
68 | | | | |
72 | node | p1 node | p2 node | link node |
69 | node | p1 node | p2 node | link node |
73 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
70 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
74 | | | | |
71 | | | | |
75 +------------------------------------------------------+
72 +------------------------------------------------------+
76
73
77 Version 2::
74 Version 2::
78
75
79 +------------------------------------------------------------------+
76 +------------------------------------------------------------------+
80 | | | | | |
77 | | | | | |
81 | node | p1 node | p2 node | base node | link node |
78 | node | p1 node | p2 node | base node | link node |
82 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
79 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
83 | | | | | |
80 | | | | | |
84 +------------------------------------------------------------------+
81 +------------------------------------------------------------------+
85
82
86 Version 3::
83 Version 3::
87
84
88 +------------------------------------------------------------------------------+
85 +------------------------------------------------------------------------------+
89 | | | | | | |
86 | | | | | | |
90 | node | p1 node | p2 node | base node | link node | flags |
87 | node | p1 node | p2 node | base node | link node | flags |
91 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
88 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
92 | | | | | | |
89 | | | | | | |
93 +------------------------------------------------------------------------------+
90 +------------------------------------------------------------------------------+
94
91
95 The *mdiff header* consists of 3 32-bit big-endian signed integers
92 The *mdiff header* consists of 3 32-bit big-endian signed integers
96 describing offsets at which to apply the following delta content::
93 describing offsets at which to apply the following delta content::
97
94
98 +-------------------------------------+
95 +-------------------------------------+
99 | | | |
96 | | | |
100 | offset | old length | new length |
97 | offset | old length | new length |
101 | (32 bits) | (32 bits) | (32 bits) |
98 | (32 bits) | (32 bits) | (32 bits) |
102 | | | |
99 | | | |
103 +-------------------------------------+
100 +-------------------------------------+
104
101
105 In version 1, the delta is always applied against the previous node from
102 In version 1, the delta is always applied against the previous node from
106 the changegroup or the first parent if this is the first entry in the
103 the changegroup or the first parent if this is the first entry in the
107 changegroup.
104 changegroup.
108
105
109 In version 2, the delta base node is encoded in the entry in the
106 In version 2, the delta base node is encoded in the entry in the
110 changegroup. This allows the delta to be expressed against any parent,
107 changegroup. This allows the delta to be expressed against any parent,
111 which can result in smaller deltas and more efficient encoding of data.
108 which can result in smaller deltas and more efficient encoding of data.
112
109
113 Changeset Segment
110 Changeset Segment
114 -----------------
111 =================
115
112
116 The *changeset segment* consists of a single *delta group* holding
113 The *changeset segment* consists of a single *delta group* holding
117 changelog data. It is followed by an *empty chunk* to denote the
114 changelog data. It is followed by an *empty chunk* to denote the
118 boundary to the *manifests segment*.
115 boundary to the *manifests segment*.
119
116
120 Manifest Segment
117 Manifest Segment
121 ----------------
118 ================
122
119
123 The *manifest segment* consists of a single *delta group* holding
120 The *manifest segment* consists of a single *delta group* holding
124 manifest data. It is followed by an *empty chunk* to denote the boundary
121 manifest data. It is followed by an *empty chunk* to denote the boundary
125 to the *filelogs segment*.
122 to the *filelogs segment*.
126
123
127 Filelogs Segment
124 Filelogs Segment
128 ----------------
125 ================
129
126
130 The *filelogs* segment consists of multiple sub-segments, each
127 The *filelogs* segment consists of multiple sub-segments, each
131 corresponding to an individual file whose data is being described::
128 corresponding to an individual file whose data is being described::
132
129
133 +--------------------------------------+
130 +--------------------------------------+
134 | | | | |
131 | | | | |
135 | filelog0 | filelog1 | filelog2 | ... |
132 | filelog0 | filelog1 | filelog2 | ... |
136 | | | | |
133 | | | | |
137 +--------------------------------------+
134 +--------------------------------------+
138
135
139 In version ``3`` of the changegroup format, filelogs may include
136 In version ``3`` of the changegroup format, filelogs may include
140 directory logs when treemanifests are in use. directory logs are
137 directory logs when treemanifests are in use. directory logs are
141 identified by having a trailing '/' on their filename (see below).
138 identified by having a trailing '/' on their filename (see below).
142
139
143 The final filelog sub-segment is followed by an *empty chunk* to denote
140 The final filelog sub-segment is followed by an *empty chunk* to denote
144 the end of the segment and the overall changegroup.
141 the end of the segment and the overall changegroup.
145
142
146 Each filelog sub-segment consists of the following::
143 Each filelog sub-segment consists of the following::
147
144
148 +------------------------------------------+
145 +------------------------------------------+
149 | | | |
146 | | | |
150 | filename size | filename | delta group |
147 | filename size | filename | delta group |
151 | (32 bits) | (various) | (various) |
148 | (32 bits) | (various) | (various) |
152 | | | |
149 | | | |
153 +------------------------------------------+
150 +------------------------------------------+
154
151
155 That is, a *chunk* consisting of the filename (not terminated or padded)
152 That is, a *chunk* consisting of the filename (not terminated or padded)
156 followed by N chunks constituting the *delta group* for this file.
153 followed by N chunks constituting the *delta group* for this file.
157
@@ -1,110 +1,108 b''
1 Requirements
2 ============
3
1
4 Repositories contain a file (``.hg/requires``) containing a list of
2 Repositories contain a file (``.hg/requires``) containing a list of
5 features/capabilities that are *required* for clients to interface
3 features/capabilities that are *required* for clients to interface
6 with the repository. This file has been present in Mercurial since
4 with the repository. This file has been present in Mercurial since
7 version 0.9.2 (released December 2006).
5 version 0.9.2 (released December 2006).
8
6
9 One of the first things clients do when opening a repository is read
7 One of the first things clients do when opening a repository is read
10 ``.hg/requires`` and verify that all listed requirements are supported,
8 ``.hg/requires`` and verify that all listed requirements are supported,
11 aborting if not. Requirements are therefore a strong mechanism to
9 aborting if not. Requirements are therefore a strong mechanism to
12 prevent incompatible clients from reading from unknown repository
10 prevent incompatible clients from reading from unknown repository
13 formats or even corrupting them by writing to them.
11 formats or even corrupting them by writing to them.
14
12
15 Extensions may add requirements. When they do this, clients not running
13 Extensions may add requirements. When they do this, clients not running
16 an extension will be unable to read from repositories.
14 an extension will be unable to read from repositories.
17
15
18 The following sections describe the requirements defined by the
16 The following sections describe the requirements defined by the
19 Mercurial core distribution.
17 Mercurial core distribution.
20
18
21 revlogv1
19 revlogv1
22 --------
20 ========
23
21
24 When present, revlogs are version 1 (RevlogNG). RevlogNG was introduced
22 When present, revlogs are version 1 (RevlogNG). RevlogNG was introduced
25 in 2006. The ``revlogv1`` requirement has been enabled by default
23 in 2006. The ``revlogv1`` requirement has been enabled by default
26 since the ``requires`` file was introduced in Mercurial 0.9.2.
24 since the ``requires`` file was introduced in Mercurial 0.9.2.
27
25
28 If this requirement is not present, version 0 revlogs are assumed.
26 If this requirement is not present, version 0 revlogs are assumed.
29
27
30 store
28 store
31 -----
29 =====
32
30
33 The *store* repository layout should be used.
31 The *store* repository layout should be used.
34
32
35 This requirement has been enabled by default since the ``requires`` file
33 This requirement has been enabled by default since the ``requires`` file
36 was introduced in Mercurial 0.9.2.
34 was introduced in Mercurial 0.9.2.
37
35
38 fncache
36 fncache
39 -------
37 =======
40
38
41 The *fncache* repository layout should be used.
39 The *fncache* repository layout should be used.
42
40
43 The *fncache* layout hash encodes filenames with long paths and
41 The *fncache* layout hash encodes filenames with long paths and
44 encodes reserved filenames.
42 encodes reserved filenames.
45
43
46 This requirement is enabled by default when the *store* requirement is
44 This requirement is enabled by default when the *store* requirement is
47 enabled (which is the default behavior). It was introduced in Mercurial
45 enabled (which is the default behavior). It was introduced in Mercurial
48 1.1 (released December 2008).
46 1.1 (released December 2008).
49
47
50 shared
48 shared
51 ------
49 ======
52
50
53 Denotes that the store for a repository is shared from another location
51 Denotes that the store for a repository is shared from another location
54 (defined by the ``.hg/sharedpath`` file).
52 (defined by the ``.hg/sharedpath`` file).
55
53
56 This requirement is set when a repository is created via :hg:`share`.
54 This requirement is set when a repository is created via :hg:`share`.
57
55
58 The requirement was added in Mercurial 1.3 (released July 2009).
56 The requirement was added in Mercurial 1.3 (released July 2009).
59
57
60 dotencode
58 dotencode
61 ---------
59 =========
62
60
63 The *dotencode* repository layout should be used.
61 The *dotencode* repository layout should be used.
64
62
65 The *dotencode* layout encodes the first period or space in filenames
63 The *dotencode* layout encodes the first period or space in filenames
66 to prevent issues on OS X and Windows.
64 to prevent issues on OS X and Windows.
67
65
68 This requirement is enabled by default when the *store* requirement
66 This requirement is enabled by default when the *store* requirement
69 is enabled (which is the default behavior). It was introduced in
67 is enabled (which is the default behavior). It was introduced in
70 Mercurial 1.7 (released November 2010).
68 Mercurial 1.7 (released November 2010).
71
69
72 parentdelta
70 parentdelta
73 -----------
71 ===========
74
72
75 Denotes a revlog delta encoding format that was experimental and
73 Denotes a revlog delta encoding format that was experimental and
76 replaced by *generaldelta*. It should not be seen in the wild because
74 replaced by *generaldelta*. It should not be seen in the wild because
77 it was never enabled by default.
75 it was never enabled by default.
78
76
79 This requirement was added in Mercurial 1.7 and removed in Mercurial
77 This requirement was added in Mercurial 1.7 and removed in Mercurial
80 1.9.
78 1.9.
81
79
82 generaldelta
80 generaldelta
83 ------------
81 ============
84
82
85 Revlogs should be created with the *generaldelta* flag enabled. The
83 Revlogs should be created with the *generaldelta* flag enabled. The
86 generaldelta flag will cause deltas to be encoded against a parent
84 generaldelta flag will cause deltas to be encoded against a parent
87 revision instead of the previous revision in the revlog.
85 revision instead of the previous revision in the revlog.
88
86
89 Support for this requirement was added in Mercurial 1.9 (released
87 Support for this requirement was added in Mercurial 1.9 (released
90 July 2011). The requirement was disabled on new repositories by
88 July 2011). The requirement was disabled on new repositories by
91 default until Mercurial 3.7 (released February 2016).
89 default until Mercurial 3.7 (released February 2016).
92
90
93 manifestv2
91 manifestv2
94 ----------
92 ==========
95
93
96 Denotes that version 2 of manifests are being used.
94 Denotes that version 2 of manifests are being used.
97
95
98 Support for this requirement was added in Mercurial 3.4 (released
96 Support for this requirement was added in Mercurial 3.4 (released
99 May 2015). The requirement is currently experimental and is disabled
97 May 2015). The requirement is currently experimental and is disabled
100 by default.
98 by default.
101
99
102 treemanifest
100 treemanifest
103 ------------
101 ============
104
102
105 Denotes that tree manifests are being used. Tree manifests are
103 Denotes that tree manifests are being used. Tree manifests are
106 one manifest per directory (as opposed to a single flat manifest).
104 one manifest per directory (as opposed to a single flat manifest).
107
105
108 Support for this requirement was added in Mercurial 3.4 (released
106 Support for this requirement was added in Mercurial 3.4 (released
109 August 2015). The requirement is currently experimental and is
107 August 2015). The requirement is currently experimental and is
110 disabled by default.
108 disabled by default.
@@ -1,201 +1,198 b''
1 Revlogs
2 =======
3
4 Revision logs - or *revlogs* - are an append only data structure for
1 Revision logs - or *revlogs* - are an append only data structure for
5 storing discrete entries, or *revisions*. They are the primary storage
2 storing discrete entries, or *revisions*. They are the primary storage
6 mechanism of repository data.
3 mechanism of repository data.
7
4
8 Revlogs effectively model a directed acyclic graph (DAG). Each node
5 Revlogs effectively model a directed acyclic graph (DAG). Each node
9 has edges to 1 or 2 *parent* nodes. Each node contains metadata and
6 has edges to 1 or 2 *parent* nodes. Each node contains metadata and
10 the raw value for that node.
7 the raw value for that node.
11
8
12 Revlogs consist of entries which have metadata and revision data.
9 Revlogs consist of entries which have metadata and revision data.
13 Metadata includes the hash of the revision's content, sizes, and
10 Metadata includes the hash of the revision's content, sizes, and
14 links to its *parent* entries. The collective metadata is referred
11 links to its *parent* entries. The collective metadata is referred
15 to as the *index* and the revision data is the *data*.
12 to as the *index* and the revision data is the *data*.
16
13
17 Revision data is stored as a series of compressed deltas against previous
14 Revision data is stored as a series of compressed deltas against previous
18 revisions.
15 revisions.
19
16
20 Revlogs are written in an append-only fashion. We never need to rewrite
17 Revlogs are written in an append-only fashion. We never need to rewrite
21 a file to insert nor do we need to remove data. Rolling back in-progress
18 a file to insert nor do we need to remove data. Rolling back in-progress
22 writes can be performed by truncating files. Read locks can be avoided
19 writes can be performed by truncating files. Read locks can be avoided
23 using simple techniques. This means that references to other data in
20 using simple techniques. This means that references to other data in
24 the same revlog *always* refer to a previous entry.
21 the same revlog *always* refer to a previous entry.
25
22
26 Revlogs can be modeled as 0-indexed arrays. The first revision is
23 Revlogs can be modeled as 0-indexed arrays. The first revision is
27 revision #0 and the second is revision #1. The revision -1 is typically
24 revision #0 and the second is revision #1. The revision -1 is typically
28 used to mean *does not exist* or *not defined*.
25 used to mean *does not exist* or *not defined*.
29
26
30 File Format
27 File Format
31 -----------
28 ===========
32
29
33 A revlog begins with a 32-bit big endian integer holding version info
30 A revlog begins with a 32-bit big endian integer holding version info
34 and feature flags. This integer is shared with the first revision
31 and feature flags. This integer is shared with the first revision
35 entry.
32 entry.
36
33
37 This integer is logically divided into 2 16-bit shorts. The least
34 This integer is logically divided into 2 16-bit shorts. The least
38 significant half of the integer is the format/version short. The other
35 significant half of the integer is the format/version short. The other
39 short holds feature flags that dictate behavior of the revlog.
36 short holds feature flags that dictate behavior of the revlog.
40
37
41 Only 1 bit of the format/version short is currently used. Remaining
38 Only 1 bit of the format/version short is currently used. Remaining
42 bits are reserved for future use.
39 bits are reserved for future use.
43
40
44 The following values for the format/version short are defined:
41 The following values for the format/version short are defined:
45
42
46 0
43 0
47 The original revlog version.
44 The original revlog version.
48 1
45 1
49 RevlogNG (*next generation*). It replaced version 0 when it was
46 RevlogNG (*next generation*). It replaced version 0 when it was
50 implemented in 2006.
47 implemented in 2006.
51
48
52 The feature flags short consists of bit flags. Where 0 is the least
49 The feature flags short consists of bit flags. Where 0 is the least
53 significant bit, the following bit offsets define flags:
50 significant bit, the following bit offsets define flags:
54
51
55 0
52 0
56 Store revision data inline.
53 Store revision data inline.
57 1
54 1
58 Generaldelta encoding.
55 Generaldelta encoding.
59
56
60 2-15
57 2-15
61 Reserved for future use.
58 Reserved for future use.
62
59
63 The following header values are common:
60 The following header values are common:
64
61
65 00 00 00 01
62 00 00 00 01
66 RevlogNG
63 RevlogNG
67 00 01 00 01
64 00 01 00 01
68 RevlogNG + inline
65 RevlogNG + inline
69 00 02 00 01
66 00 02 00 01
70 RevlogNG + generaldelta
67 RevlogNG + generaldelta
71 00 03 00 01
68 00 03 00 01
72 RevlogNG + inline + generaldelta
69 RevlogNG + inline + generaldelta
73
70
74 Following the 32-bit header is the remainder of the first index entry.
71 Following the 32-bit header is the remainder of the first index entry.
75 Following that are remaining *index* data. Inlined revision data is
72 Following that are remaining *index* data. Inlined revision data is
76 possibly located between index entries. More on this layout is described
73 possibly located between index entries. More on this layout is described
77 below.
74 below.
78
75
79 RevlogNG Format
76 RevlogNG Format
80 ---------------
77 ===============
81
78
82 RevlogNG (version 1) begins with an index describing the revisions in
79 RevlogNG (version 1) begins with an index describing the revisions in
83 the revlog. If the ``inline`` flag is set, revision data is stored inline,
80 the revlog. If the ``inline`` flag is set, revision data is stored inline,
84 or between index entries (as opposed to in a separate container).
81 or between index entries (as opposed to in a separate container).
85
82
86 Each index entry is 64 bytes. The byte layout of each entry is as
83 Each index entry is 64 bytes. The byte layout of each entry is as
87 follows, with byte 0 being the first byte (all data stored as big endian):
84 follows, with byte 0 being the first byte (all data stored as big endian):
88
85
89 0-3 (4 bytes) (rev 0 only)
86 0-3 (4 bytes) (rev 0 only)
90 Revlog header
87 Revlog header
91 0-5 (6 bytes)
88 0-5 (6 bytes)
92 Absolute offset of revision data from beginning of revlog.
89 Absolute offset of revision data from beginning of revlog.
93 6-7 (2 bytes)
90 6-7 (2 bytes)
94 Bit flags impacting revision behavior.
91 Bit flags impacting revision behavior.
95 8-11 (4 bytes)
92 8-11 (4 bytes)
96 Compressed length of revision data / chunk as stored in revlog.
93 Compressed length of revision data / chunk as stored in revlog.
97 12-15 (4 bytes)
94 12-15 (4 bytes)
98 Uncompressed length of revision data / chunk.
95 Uncompressed length of revision data / chunk.
99 16-19 (4 bytes)
96 16-19 (4 bytes)
100 Base or previous revision this revision's delta was produced against.
97 Base or previous revision this revision's delta was produced against.
101 -1 means this revision holds full text (as opposed to a delta).
98 -1 means this revision holds full text (as opposed to a delta).
102 For generaldelta repos, this is the previous revision in the delta
99 For generaldelta repos, this is the previous revision in the delta
103 chain. For non-generaldelta repos, this is the base or first
100 chain. For non-generaldelta repos, this is the base or first
104 revision in the delta chain.
101 revision in the delta chain.
105 20-23 (4 bytes)
102 20-23 (4 bytes)
106 A revision this revision is *linked* to. This allows a revision in
103 A revision this revision is *linked* to. This allows a revision in
107 one revlog to be forever associated with a revision in another
104 one revlog to be forever associated with a revision in another
108 revlog. For example, a file's revlog may point to the changelog
105 revlog. For example, a file's revlog may point to the changelog
109 revision that introduced it.
106 revision that introduced it.
110 24-27 (4 bytes)
107 24-27 (4 bytes)
111 Revision of 1st parent. -1 indicates no parent.
108 Revision of 1st parent. -1 indicates no parent.
112 28-31 (4 bytes)
109 28-31 (4 bytes)
113 Revision of 2nd parent. -1 indicates no 2nd parent.
110 Revision of 2nd parent. -1 indicates no 2nd parent.
114 32-63 (32 bytes)
111 32-63 (32 bytes)
115 Hash of revision's full text. Currently, SHA-1 is used and only
112 Hash of revision's full text. Currently, SHA-1 is used and only
116 the first 20 bytes of this field are used. The rest of the bytes
113 the first 20 bytes of this field are used. The rest of the bytes
117 are ignored and should be stored as \0.
114 are ignored and should be stored as \0.
118
115
119 If inline revision data is being stored, the compressed revision data
116 If inline revision data is being stored, the compressed revision data
120 (of length from bytes offset 8-11 from the index entry) immediately
117 (of length from bytes offset 8-11 from the index entry) immediately
121 follows the index entry. There is no header on the revision data. There
118 follows the index entry. There is no header on the revision data. There
122 is no padding between it and the index entries before and after.
119 is no padding between it and the index entries before and after.
123
120
124 If revision data is not inline, then raw revision data is stored in a
121 If revision data is not inline, then raw revision data is stored in a
125 separate byte container. The offsets from bytes 0-5 and the compressed
122 separate byte container. The offsets from bytes 0-5 and the compressed
126 length from bytes 8-11 define how to access this data.
123 length from bytes 8-11 define how to access this data.
127
124
128 The first 4 bytes of the revlog are shared between the revlog header
125 The first 4 bytes of the revlog are shared between the revlog header
129 and the 6 byte absolute offset field from the first revlog entry.
126 and the 6 byte absolute offset field from the first revlog entry.
130
127
131 Delta Chains
128 Delta Chains
132 ------------
129 ============
133
130
134 Revision data is encoded as a chain of *chunks*. Each chain begins with
131 Revision data is encoded as a chain of *chunks*. Each chain begins with
135 the compressed original full text for that revision. Each subsequent
132 the compressed original full text for that revision. Each subsequent
136 *chunk* is a *delta* against the previous revision. We therefore call
133 *chunk* is a *delta* against the previous revision. We therefore call
137 these chains of chunks/deltas *delta chains*.
134 these chains of chunks/deltas *delta chains*.
138
135
139 The full text for a revision is reconstructed by loading the original
136 The full text for a revision is reconstructed by loading the original
140 full text for the base revision of a *delta chain* and then applying
137 full text for the base revision of a *delta chain* and then applying
141 *deltas* until the target revision is reconstructed.
138 *deltas* until the target revision is reconstructed.
142
139
143 *Delta chains* are limited in length so lookup time is bound. They are
140 *Delta chains* are limited in length so lookup time is bound. They are
144 limited to ~2x the length of the revision's data. The linear distance
141 limited to ~2x the length of the revision's data. The linear distance
145 between the base chunk and the final chunk is also limited so the
142 between the base chunk and the final chunk is also limited so the
146 amount of read I/O to load all chunks in the delta chain is bound.
143 amount of read I/O to load all chunks in the delta chain is bound.
147
144
148 Deltas and delta chains are either computed against the previous
145 Deltas and delta chains are either computed against the previous
149 revision in the revlog or another revision (almost certainly one of
146 revision in the revlog or another revision (almost certainly one of
150 the parents of the revision). Historically, deltas were computed against
147 the parents of the revision). Historically, deltas were computed against
151 the previous revision. The *generaldelta* revlog feature flag (enabled
148 the previous revision. The *generaldelta* revlog feature flag (enabled
152 by default in Mercurial 3.7) activates the mode where deltas are
149 by default in Mercurial 3.7) activates the mode where deltas are
153 computed against an arbitrary revision (almost certainly a parent revision).
150 computed against an arbitrary revision (almost certainly a parent revision).
154
151
155 File Storage
152 File Storage
156 ------------
153 ============
157
154
158 Revlogs logically consist of an index (metadata of entries) and
155 Revlogs logically consist of an index (metadata of entries) and
159 revision data. This data may be stored together in a single file or in
156 revision data. This data may be stored together in a single file or in
160 separate files. The mechanism used is indicated by the ``inline`` feature
157 separate files. The mechanism used is indicated by the ``inline`` feature
161 flag on the revlog.
158 flag on the revlog.
162
159
163 Mercurial's behavior is to use inline storage until a revlog reaches a
160 Mercurial's behavior is to use inline storage until a revlog reaches a
164 certain size, at which point it will be converted to non-inline. The
161 certain size, at which point it will be converted to non-inline. The
165 reason there is a size limit on inline storage is to establish an upper
162 reason there is a size limit on inline storage is to establish an upper
166 bound on how much data must be read to load the index. It would be a waste
163 bound on how much data must be read to load the index. It would be a waste
167 to read tens or hundreds of extra megabytes of data just to access the
164 to read tens or hundreds of extra megabytes of data just to access the
168 index data.
165 index data.
169
166
170 The actual layout of revlog files on disk is governed by the repository's
167 The actual layout of revlog files on disk is governed by the repository's
171 *store format*. Typically, a ``.i`` file represents the index revlog
168 *store format*. Typically, a ``.i`` file represents the index revlog
172 (possibly containing inline data) and a ``.d`` file holds the revision data.
169 (possibly containing inline data) and a ``.d`` file holds the revision data.
173
170
174 Revision Entries
171 Revision Entries
175 ----------------
172 ================
176
173
177 Revision entries consist of an optional 1 byte header followed by an
174 Revision entries consist of an optional 1 byte header followed by an
178 encoding of the revision data. The headers are as follows:
175 encoding of the revision data. The headers are as follows:
179
176
180 \0 (0x00)
177 \0 (0x00)
181 Revision data is the entirety of the entry, including this header.
178 Revision data is the entirety of the entry, including this header.
182 u (0x75)
179 u (0x75)
183 Raw revision data follows.
180 Raw revision data follows.
184 x (0x78)
181 x (0x78)
185 zlib (RFC 1950) data.
182 zlib (RFC 1950) data.
186
183
187 The 0x78 value is actually the first byte of the zlib header (CMF byte).
184 The 0x78 value is actually the first byte of the zlib header (CMF byte).
188
185
189 Hash Computation
186 Hash Computation
190 ----------------
187 ================
191
188
192 The hash of the revision is stored in the index and is used both as a primary
189 The hash of the revision is stored in the index and is used both as a primary
193 key and for data integrity verification.
190 key and for data integrity verification.
194
191
195 Currently, SHA-1 is the only supported hashing algorithm. To obtain the SHA-1
192 Currently, SHA-1 is the only supported hashing algorithm. To obtain the SHA-1
196 hash of a revision:
193 hash of a revision:
197
194
198 1. Hash the parent nodes
195 1. Hash the parent nodes
199 2. Hash the fulltext of the revision
196 2. Hash the fulltext of the revision
200
197
201 The 20 byte node ids of the parents are fed into the hasher in ascending order.
198 The 20 byte node ids of the parents are fed into the hasher in ascending order.
@@ -1,3156 +1,3155 b''
1 Short help:
1 Short help:
2
2
3 $ hg
3 $ hg
4 Mercurial Distributed SCM
4 Mercurial Distributed SCM
5
5
6 basic commands:
6 basic commands:
7
7
8 add add the specified files on the next commit
8 add add the specified files on the next commit
9 annotate show changeset information by line for each file
9 annotate show changeset information by line for each file
10 clone make a copy of an existing repository
10 clone make a copy of an existing repository
11 commit commit the specified files or all outstanding changes
11 commit commit the specified files or all outstanding changes
12 diff diff repository (or selected files)
12 diff diff repository (or selected files)
13 export dump the header and diffs for one or more changesets
13 export dump the header and diffs for one or more changesets
14 forget forget the specified files on the next commit
14 forget forget the specified files on the next commit
15 init create a new repository in the given directory
15 init create a new repository in the given directory
16 log show revision history of entire repository or files
16 log show revision history of entire repository or files
17 merge merge another revision into working directory
17 merge merge another revision into working directory
18 pull pull changes from the specified source
18 pull pull changes from the specified source
19 push push changes to the specified destination
19 push push changes to the specified destination
20 remove remove the specified files on the next commit
20 remove remove the specified files on the next commit
21 serve start stand-alone webserver
21 serve start stand-alone webserver
22 status show changed files in the working directory
22 status show changed files in the working directory
23 summary summarize working directory state
23 summary summarize working directory state
24 update update working directory (or switch revisions)
24 update update working directory (or switch revisions)
25
25
26 (use "hg help" for the full list of commands or "hg -v" for details)
26 (use "hg help" for the full list of commands or "hg -v" for details)
27
27
28 $ hg -q
28 $ hg -q
29 add add the specified files on the next commit
29 add add the specified files on the next commit
30 annotate show changeset information by line for each file
30 annotate show changeset information by line for each file
31 clone make a copy of an existing repository
31 clone make a copy of an existing repository
32 commit commit the specified files or all outstanding changes
32 commit commit the specified files or all outstanding changes
33 diff diff repository (or selected files)
33 diff diff repository (or selected files)
34 export dump the header and diffs for one or more changesets
34 export dump the header and diffs for one or more changesets
35 forget forget the specified files on the next commit
35 forget forget the specified files on the next commit
36 init create a new repository in the given directory
36 init create a new repository in the given directory
37 log show revision history of entire repository or files
37 log show revision history of entire repository or files
38 merge merge another revision into working directory
38 merge merge another revision into working directory
39 pull pull changes from the specified source
39 pull pull changes from the specified source
40 push push changes to the specified destination
40 push push changes to the specified destination
41 remove remove the specified files on the next commit
41 remove remove the specified files on the next commit
42 serve start stand-alone webserver
42 serve start stand-alone webserver
43 status show changed files in the working directory
43 status show changed files in the working directory
44 summary summarize working directory state
44 summary summarize working directory state
45 update update working directory (or switch revisions)
45 update update working directory (or switch revisions)
46
46
47 $ hg help
47 $ hg help
48 Mercurial Distributed SCM
48 Mercurial Distributed SCM
49
49
50 list of commands:
50 list of commands:
51
51
52 add add the specified files on the next commit
52 add add the specified files on the next commit
53 addremove add all new files, delete all missing files
53 addremove add all new files, delete all missing files
54 annotate show changeset information by line for each file
54 annotate show changeset information by line for each file
55 archive create an unversioned archive of a repository revision
55 archive create an unversioned archive of a repository revision
56 backout reverse effect of earlier changeset
56 backout reverse effect of earlier changeset
57 bisect subdivision search of changesets
57 bisect subdivision search of changesets
58 bookmarks create a new bookmark or list existing bookmarks
58 bookmarks create a new bookmark or list existing bookmarks
59 branch set or show the current branch name
59 branch set or show the current branch name
60 branches list repository named branches
60 branches list repository named branches
61 bundle create a changegroup file
61 bundle create a changegroup file
62 cat output the current or given revision of files
62 cat output the current or given revision of files
63 clone make a copy of an existing repository
63 clone make a copy of an existing repository
64 commit commit the specified files or all outstanding changes
64 commit commit the specified files or all outstanding changes
65 config show combined config settings from all hgrc files
65 config show combined config settings from all hgrc files
66 copy mark files as copied for the next commit
66 copy mark files as copied for the next commit
67 diff diff repository (or selected files)
67 diff diff repository (or selected files)
68 export dump the header and diffs for one or more changesets
68 export dump the header and diffs for one or more changesets
69 files list tracked files
69 files list tracked files
70 forget forget the specified files on the next commit
70 forget forget the specified files on the next commit
71 graft copy changes from other branches onto the current branch
71 graft copy changes from other branches onto the current branch
72 grep search for a pattern in specified files and revisions
72 grep search for a pattern in specified files and revisions
73 heads show branch heads
73 heads show branch heads
74 help show help for a given topic or a help overview
74 help show help for a given topic or a help overview
75 identify identify the working directory or specified revision
75 identify identify the working directory or specified revision
76 import import an ordered set of patches
76 import import an ordered set of patches
77 incoming show new changesets found in source
77 incoming show new changesets found in source
78 init create a new repository in the given directory
78 init create a new repository in the given directory
79 log show revision history of entire repository or files
79 log show revision history of entire repository or files
80 manifest output the current or given revision of the project manifest
80 manifest output the current or given revision of the project manifest
81 merge merge another revision into working directory
81 merge merge another revision into working directory
82 outgoing show changesets not found in the destination
82 outgoing show changesets not found in the destination
83 paths show aliases for remote repositories
83 paths show aliases for remote repositories
84 phase set or show the current phase name
84 phase set or show the current phase name
85 pull pull changes from the specified source
85 pull pull changes from the specified source
86 push push changes to the specified destination
86 push push changes to the specified destination
87 recover roll back an interrupted transaction
87 recover roll back an interrupted transaction
88 remove remove the specified files on the next commit
88 remove remove the specified files on the next commit
89 rename rename files; equivalent of copy + remove
89 rename rename files; equivalent of copy + remove
90 resolve redo merges or set/view the merge status of files
90 resolve redo merges or set/view the merge status of files
91 revert restore files to their checkout state
91 revert restore files to their checkout state
92 root print the root (top) of the current working directory
92 root print the root (top) of the current working directory
93 serve start stand-alone webserver
93 serve start stand-alone webserver
94 status show changed files in the working directory
94 status show changed files in the working directory
95 summary summarize working directory state
95 summary summarize working directory state
96 tag add one or more tags for the current or given revision
96 tag add one or more tags for the current or given revision
97 tags list repository tags
97 tags list repository tags
98 unbundle apply one or more changegroup files
98 unbundle apply one or more changegroup files
99 update update working directory (or switch revisions)
99 update update working directory (or switch revisions)
100 verify verify the integrity of the repository
100 verify verify the integrity of the repository
101 version output version and copyright information
101 version output version and copyright information
102
102
103 additional help topics:
103 additional help topics:
104
104
105 config Configuration Files
105 config Configuration Files
106 dates Date Formats
106 dates Date Formats
107 diffs Diff Formats
107 diffs Diff Formats
108 environment Environment Variables
108 environment Environment Variables
109 extensions Using Additional Features
109 extensions Using Additional Features
110 filesets Specifying File Sets
110 filesets Specifying File Sets
111 glossary Glossary
111 glossary Glossary
112 hgignore Syntax for Mercurial Ignore Files
112 hgignore Syntax for Mercurial Ignore Files
113 hgweb Configuring hgweb
113 hgweb Configuring hgweb
114 internals Technical implementation topics
114 internals Technical implementation topics
115 merge-tools Merge Tools
115 merge-tools Merge Tools
116 multirevs Specifying Multiple Revisions
116 multirevs Specifying Multiple Revisions
117 patterns File Name Patterns
117 patterns File Name Patterns
118 phases Working with Phases
118 phases Working with Phases
119 revisions Specifying Single Revisions
119 revisions Specifying Single Revisions
120 revsets Specifying Revision Sets
120 revsets Specifying Revision Sets
121 scripting Using Mercurial from scripts and automation
121 scripting Using Mercurial from scripts and automation
122 subrepos Subrepositories
122 subrepos Subrepositories
123 templating Template Usage
123 templating Template Usage
124 urls URL Paths
124 urls URL Paths
125
125
126 (use "hg help -v" to show built-in aliases and global options)
126 (use "hg help -v" to show built-in aliases and global options)
127
127
128 $ hg -q help
128 $ hg -q help
129 add add the specified files on the next commit
129 add add the specified files on the next commit
130 addremove add all new files, delete all missing files
130 addremove add all new files, delete all missing files
131 annotate show changeset information by line for each file
131 annotate show changeset information by line for each file
132 archive create an unversioned archive of a repository revision
132 archive create an unversioned archive of a repository revision
133 backout reverse effect of earlier changeset
133 backout reverse effect of earlier changeset
134 bisect subdivision search of changesets
134 bisect subdivision search of changesets
135 bookmarks create a new bookmark or list existing bookmarks
135 bookmarks create a new bookmark or list existing bookmarks
136 branch set or show the current branch name
136 branch set or show the current branch name
137 branches list repository named branches
137 branches list repository named branches
138 bundle create a changegroup file
138 bundle create a changegroup file
139 cat output the current or given revision of files
139 cat output the current or given revision of files
140 clone make a copy of an existing repository
140 clone make a copy of an existing repository
141 commit commit the specified files or all outstanding changes
141 commit commit the specified files or all outstanding changes
142 config show combined config settings from all hgrc files
142 config show combined config settings from all hgrc files
143 copy mark files as copied for the next commit
143 copy mark files as copied for the next commit
144 diff diff repository (or selected files)
144 diff diff repository (or selected files)
145 export dump the header and diffs for one or more changesets
145 export dump the header and diffs for one or more changesets
146 files list tracked files
146 files list tracked files
147 forget forget the specified files on the next commit
147 forget forget the specified files on the next commit
148 graft copy changes from other branches onto the current branch
148 graft copy changes from other branches onto the current branch
149 grep search for a pattern in specified files and revisions
149 grep search for a pattern in specified files and revisions
150 heads show branch heads
150 heads show branch heads
151 help show help for a given topic or a help overview
151 help show help for a given topic or a help overview
152 identify identify the working directory or specified revision
152 identify identify the working directory or specified revision
153 import import an ordered set of patches
153 import import an ordered set of patches
154 incoming show new changesets found in source
154 incoming show new changesets found in source
155 init create a new repository in the given directory
155 init create a new repository in the given directory
156 log show revision history of entire repository or files
156 log show revision history of entire repository or files
157 manifest output the current or given revision of the project manifest
157 manifest output the current or given revision of the project manifest
158 merge merge another revision into working directory
158 merge merge another revision into working directory
159 outgoing show changesets not found in the destination
159 outgoing show changesets not found in the destination
160 paths show aliases for remote repositories
160 paths show aliases for remote repositories
161 phase set or show the current phase name
161 phase set or show the current phase name
162 pull pull changes from the specified source
162 pull pull changes from the specified source
163 push push changes to the specified destination
163 push push changes to the specified destination
164 recover roll back an interrupted transaction
164 recover roll back an interrupted transaction
165 remove remove the specified files on the next commit
165 remove remove the specified files on the next commit
166 rename rename files; equivalent of copy + remove
166 rename rename files; equivalent of copy + remove
167 resolve redo merges or set/view the merge status of files
167 resolve redo merges or set/view the merge status of files
168 revert restore files to their checkout state
168 revert restore files to their checkout state
169 root print the root (top) of the current working directory
169 root print the root (top) of the current working directory
170 serve start stand-alone webserver
170 serve start stand-alone webserver
171 status show changed files in the working directory
171 status show changed files in the working directory
172 summary summarize working directory state
172 summary summarize working directory state
173 tag add one or more tags for the current or given revision
173 tag add one or more tags for the current or given revision
174 tags list repository tags
174 tags list repository tags
175 unbundle apply one or more changegroup files
175 unbundle apply one or more changegroup files
176 update update working directory (or switch revisions)
176 update update working directory (or switch revisions)
177 verify verify the integrity of the repository
177 verify verify the integrity of the repository
178 version output version and copyright information
178 version output version and copyright information
179
179
180 additional help topics:
180 additional help topics:
181
181
182 config Configuration Files
182 config Configuration Files
183 dates Date Formats
183 dates Date Formats
184 diffs Diff Formats
184 diffs Diff Formats
185 environment Environment Variables
185 environment Environment Variables
186 extensions Using Additional Features
186 extensions Using Additional Features
187 filesets Specifying File Sets
187 filesets Specifying File Sets
188 glossary Glossary
188 glossary Glossary
189 hgignore Syntax for Mercurial Ignore Files
189 hgignore Syntax for Mercurial Ignore Files
190 hgweb Configuring hgweb
190 hgweb Configuring hgweb
191 internals Technical implementation topics
191 internals Technical implementation topics
192 merge-tools Merge Tools
192 merge-tools Merge Tools
193 multirevs Specifying Multiple Revisions
193 multirevs Specifying Multiple Revisions
194 patterns File Name Patterns
194 patterns File Name Patterns
195 phases Working with Phases
195 phases Working with Phases
196 revisions Specifying Single Revisions
196 revisions Specifying Single Revisions
197 revsets Specifying Revision Sets
197 revsets Specifying Revision Sets
198 scripting Using Mercurial from scripts and automation
198 scripting Using Mercurial from scripts and automation
199 subrepos Subrepositories
199 subrepos Subrepositories
200 templating Template Usage
200 templating Template Usage
201 urls URL Paths
201 urls URL Paths
202
202
203 Test extension help:
203 Test extension help:
204 $ hg help extensions --config extensions.rebase= --config extensions.children=
204 $ hg help extensions --config extensions.rebase= --config extensions.children=
205 Using Additional Features
205 Using Additional Features
206 """""""""""""""""""""""""
206 """""""""""""""""""""""""
207
207
208 Mercurial has the ability to add new features through the use of
208 Mercurial has the ability to add new features through the use of
209 extensions. Extensions may add new commands, add options to existing
209 extensions. Extensions may add new commands, add options to existing
210 commands, change the default behavior of commands, or implement hooks.
210 commands, change the default behavior of commands, or implement hooks.
211
211
212 To enable the "foo" extension, either shipped with Mercurial or in the
212 To enable the "foo" extension, either shipped with Mercurial or in the
213 Python search path, create an entry for it in your configuration file,
213 Python search path, create an entry for it in your configuration file,
214 like this:
214 like this:
215
215
216 [extensions]
216 [extensions]
217 foo =
217 foo =
218
218
219 You may also specify the full path to an extension:
219 You may also specify the full path to an extension:
220
220
221 [extensions]
221 [extensions]
222 myfeature = ~/.hgext/myfeature.py
222 myfeature = ~/.hgext/myfeature.py
223
223
224 See 'hg help config' for more information on configuration files.
224 See 'hg help config' for more information on configuration files.
225
225
226 Extensions are not loaded by default for a variety of reasons: they can
226 Extensions are not loaded by default for a variety of reasons: they can
227 increase startup overhead; they may be meant for advanced usage only; they
227 increase startup overhead; they may be meant for advanced usage only; they
228 may provide potentially dangerous abilities (such as letting you destroy
228 may provide potentially dangerous abilities (such as letting you destroy
229 or modify history); they might not be ready for prime time; or they may
229 or modify history); they might not be ready for prime time; or they may
230 alter some usual behaviors of stock Mercurial. It is thus up to the user
230 alter some usual behaviors of stock Mercurial. It is thus up to the user
231 to activate extensions as needed.
231 to activate extensions as needed.
232
232
233 To explicitly disable an extension enabled in a configuration file of
233 To explicitly disable an extension enabled in a configuration file of
234 broader scope, prepend its path with !:
234 broader scope, prepend its path with !:
235
235
236 [extensions]
236 [extensions]
237 # disabling extension bar residing in /path/to/extension/bar.py
237 # disabling extension bar residing in /path/to/extension/bar.py
238 bar = !/path/to/extension/bar.py
238 bar = !/path/to/extension/bar.py
239 # ditto, but no path was supplied for extension baz
239 # ditto, but no path was supplied for extension baz
240 baz = !
240 baz = !
241
241
242 enabled extensions:
242 enabled extensions:
243
243
244 chgserver command server extension for cHg (EXPERIMENTAL) (?)
244 chgserver command server extension for cHg (EXPERIMENTAL) (?)
245 children command to display child changesets (DEPRECATED)
245 children command to display child changesets (DEPRECATED)
246 rebase command to move sets of revisions to a different ancestor
246 rebase command to move sets of revisions to a different ancestor
247
247
248 disabled extensions:
248 disabled extensions:
249
249
250 acl hooks for controlling repository access
250 acl hooks for controlling repository access
251 blackbox log repository events to a blackbox for debugging
251 blackbox log repository events to a blackbox for debugging
252 bugzilla hooks for integrating with the Bugzilla bug tracker
252 bugzilla hooks for integrating with the Bugzilla bug tracker
253 censor erase file content at a given revision
253 censor erase file content at a given revision
254 churn command to display statistics about repository history
254 churn command to display statistics about repository history
255 clonebundles advertise pre-generated bundles to seed clones
255 clonebundles advertise pre-generated bundles to seed clones
256 color colorize output from some commands
256 color colorize output from some commands
257 convert import revisions from foreign VCS repositories into
257 convert import revisions from foreign VCS repositories into
258 Mercurial
258 Mercurial
259 eol automatically manage newlines in repository files
259 eol automatically manage newlines in repository files
260 extdiff command to allow external programs to compare revisions
260 extdiff command to allow external programs to compare revisions
261 factotum http authentication with factotum
261 factotum http authentication with factotum
262 gpg commands to sign and verify changesets
262 gpg commands to sign and verify changesets
263 hgk browse the repository in a graphical way
263 hgk browse the repository in a graphical way
264 highlight syntax highlighting for hgweb (requires Pygments)
264 highlight syntax highlighting for hgweb (requires Pygments)
265 histedit interactive history editing
265 histedit interactive history editing
266 keyword expand keywords in tracked files
266 keyword expand keywords in tracked files
267 largefiles track large binary files
267 largefiles track large binary files
268 mq manage a stack of patches
268 mq manage a stack of patches
269 notify hooks for sending email push notifications
269 notify hooks for sending email push notifications
270 pager browse command output with an external pager
270 pager browse command output with an external pager
271 patchbomb command to send changesets as (a series of) patch emails
271 patchbomb command to send changesets as (a series of) patch emails
272 purge command to delete untracked files from the working
272 purge command to delete untracked files from the working
273 directory
273 directory
274 relink recreates hardlinks between repository clones
274 relink recreates hardlinks between repository clones
275 schemes extend schemes with shortcuts to repository swarms
275 schemes extend schemes with shortcuts to repository swarms
276 share share a common history between several working directories
276 share share a common history between several working directories
277 shelve save and restore changes to the working directory
277 shelve save and restore changes to the working directory
278 strip strip changesets and their descendants from history
278 strip strip changesets and their descendants from history
279 transplant command to transplant changesets from another branch
279 transplant command to transplant changesets from another branch
280 win32mbcs allow the use of MBCS paths with problematic encodings
280 win32mbcs allow the use of MBCS paths with problematic encodings
281 zeroconf discover and advertise repositories on the local network
281 zeroconf discover and advertise repositories on the local network
282
282
283 Verify that extension keywords appear in help templates
283 Verify that extension keywords appear in help templates
284
284
285 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
285 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
286
286
287 Test short command list with verbose option
287 Test short command list with verbose option
288
288
289 $ hg -v help shortlist
289 $ hg -v help shortlist
290 Mercurial Distributed SCM
290 Mercurial Distributed SCM
291
291
292 basic commands:
292 basic commands:
293
293
294 add add the specified files on the next commit
294 add add the specified files on the next commit
295 annotate, blame
295 annotate, blame
296 show changeset information by line for each file
296 show changeset information by line for each file
297 clone make a copy of an existing repository
297 clone make a copy of an existing repository
298 commit, ci commit the specified files or all outstanding changes
298 commit, ci commit the specified files or all outstanding changes
299 diff diff repository (or selected files)
299 diff diff repository (or selected files)
300 export dump the header and diffs for one or more changesets
300 export dump the header and diffs for one or more changesets
301 forget forget the specified files on the next commit
301 forget forget the specified files on the next commit
302 init create a new repository in the given directory
302 init create a new repository in the given directory
303 log, history show revision history of entire repository or files
303 log, history show revision history of entire repository or files
304 merge merge another revision into working directory
304 merge merge another revision into working directory
305 pull pull changes from the specified source
305 pull pull changes from the specified source
306 push push changes to the specified destination
306 push push changes to the specified destination
307 remove, rm remove the specified files on the next commit
307 remove, rm remove the specified files on the next commit
308 serve start stand-alone webserver
308 serve start stand-alone webserver
309 status, st show changed files in the working directory
309 status, st show changed files in the working directory
310 summary, sum summarize working directory state
310 summary, sum summarize working directory state
311 update, up, checkout, co
311 update, up, checkout, co
312 update working directory (or switch revisions)
312 update working directory (or switch revisions)
313
313
314 global options ([+] can be repeated):
314 global options ([+] can be repeated):
315
315
316 -R --repository REPO repository root directory or name of overlay bundle
316 -R --repository REPO repository root directory or name of overlay bundle
317 file
317 file
318 --cwd DIR change working directory
318 --cwd DIR change working directory
319 -y --noninteractive do not prompt, automatically pick the first choice for
319 -y --noninteractive do not prompt, automatically pick the first choice for
320 all prompts
320 all prompts
321 -q --quiet suppress output
321 -q --quiet suppress output
322 -v --verbose enable additional output
322 -v --verbose enable additional output
323 --config CONFIG [+] set/override config option (use 'section.name=value')
323 --config CONFIG [+] set/override config option (use 'section.name=value')
324 --debug enable debugging output
324 --debug enable debugging output
325 --debugger start debugger
325 --debugger start debugger
326 --encoding ENCODE set the charset encoding (default: ascii)
326 --encoding ENCODE set the charset encoding (default: ascii)
327 --encodingmode MODE set the charset encoding mode (default: strict)
327 --encodingmode MODE set the charset encoding mode (default: strict)
328 --traceback always print a traceback on exception
328 --traceback always print a traceback on exception
329 --time time how long the command takes
329 --time time how long the command takes
330 --profile print command execution profile
330 --profile print command execution profile
331 --version output version information and exit
331 --version output version information and exit
332 -h --help display help and exit
332 -h --help display help and exit
333 --hidden consider hidden changesets
333 --hidden consider hidden changesets
334
334
335 (use "hg help" for the full list of commands)
335 (use "hg help" for the full list of commands)
336
336
337 $ hg add -h
337 $ hg add -h
338 hg add [OPTION]... [FILE]...
338 hg add [OPTION]... [FILE]...
339
339
340 add the specified files on the next commit
340 add the specified files on the next commit
341
341
342 Schedule files to be version controlled and added to the repository.
342 Schedule files to be version controlled and added to the repository.
343
343
344 The files will be added to the repository at the next commit. To undo an
344 The files will be added to the repository at the next commit. To undo an
345 add before that, see 'hg forget'.
345 add before that, see 'hg forget'.
346
346
347 If no names are given, add all files to the repository (except files
347 If no names are given, add all files to the repository (except files
348 matching ".hgignore").
348 matching ".hgignore").
349
349
350 Returns 0 if all files are successfully added.
350 Returns 0 if all files are successfully added.
351
351
352 options ([+] can be repeated):
352 options ([+] can be repeated):
353
353
354 -I --include PATTERN [+] include names matching the given patterns
354 -I --include PATTERN [+] include names matching the given patterns
355 -X --exclude PATTERN [+] exclude names matching the given patterns
355 -X --exclude PATTERN [+] exclude names matching the given patterns
356 -S --subrepos recurse into subrepositories
356 -S --subrepos recurse into subrepositories
357 -n --dry-run do not perform actions, just print output
357 -n --dry-run do not perform actions, just print output
358
358
359 (some details hidden, use --verbose to show complete help)
359 (some details hidden, use --verbose to show complete help)
360
360
361 Verbose help for add
361 Verbose help for add
362
362
363 $ hg add -hv
363 $ hg add -hv
364 hg add [OPTION]... [FILE]...
364 hg add [OPTION]... [FILE]...
365
365
366 add the specified files on the next commit
366 add the specified files on the next commit
367
367
368 Schedule files to be version controlled and added to the repository.
368 Schedule files to be version controlled and added to the repository.
369
369
370 The files will be added to the repository at the next commit. To undo an
370 The files will be added to the repository at the next commit. To undo an
371 add before that, see 'hg forget'.
371 add before that, see 'hg forget'.
372
372
373 If no names are given, add all files to the repository (except files
373 If no names are given, add all files to the repository (except files
374 matching ".hgignore").
374 matching ".hgignore").
375
375
376 Examples:
376 Examples:
377
377
378 - New (unknown) files are added automatically by 'hg add':
378 - New (unknown) files are added automatically by 'hg add':
379
379
380 $ ls
380 $ ls
381 foo.c
381 foo.c
382 $ hg status
382 $ hg status
383 ? foo.c
383 ? foo.c
384 $ hg add
384 $ hg add
385 adding foo.c
385 adding foo.c
386 $ hg status
386 $ hg status
387 A foo.c
387 A foo.c
388
388
389 - Specific files to be added can be specified:
389 - Specific files to be added can be specified:
390
390
391 $ ls
391 $ ls
392 bar.c foo.c
392 bar.c foo.c
393 $ hg status
393 $ hg status
394 ? bar.c
394 ? bar.c
395 ? foo.c
395 ? foo.c
396 $ hg add bar.c
396 $ hg add bar.c
397 $ hg status
397 $ hg status
398 A bar.c
398 A bar.c
399 ? foo.c
399 ? foo.c
400
400
401 Returns 0 if all files are successfully added.
401 Returns 0 if all files are successfully added.
402
402
403 options ([+] can be repeated):
403 options ([+] can be repeated):
404
404
405 -I --include PATTERN [+] include names matching the given patterns
405 -I --include PATTERN [+] include names matching the given patterns
406 -X --exclude PATTERN [+] exclude names matching the given patterns
406 -X --exclude PATTERN [+] exclude names matching the given patterns
407 -S --subrepos recurse into subrepositories
407 -S --subrepos recurse into subrepositories
408 -n --dry-run do not perform actions, just print output
408 -n --dry-run do not perform actions, just print output
409
409
410 global options ([+] can be repeated):
410 global options ([+] can be repeated):
411
411
412 -R --repository REPO repository root directory or name of overlay bundle
412 -R --repository REPO repository root directory or name of overlay bundle
413 file
413 file
414 --cwd DIR change working directory
414 --cwd DIR change working directory
415 -y --noninteractive do not prompt, automatically pick the first choice for
415 -y --noninteractive do not prompt, automatically pick the first choice for
416 all prompts
416 all prompts
417 -q --quiet suppress output
417 -q --quiet suppress output
418 -v --verbose enable additional output
418 -v --verbose enable additional output
419 --config CONFIG [+] set/override config option (use 'section.name=value')
419 --config CONFIG [+] set/override config option (use 'section.name=value')
420 --debug enable debugging output
420 --debug enable debugging output
421 --debugger start debugger
421 --debugger start debugger
422 --encoding ENCODE set the charset encoding (default: ascii)
422 --encoding ENCODE set the charset encoding (default: ascii)
423 --encodingmode MODE set the charset encoding mode (default: strict)
423 --encodingmode MODE set the charset encoding mode (default: strict)
424 --traceback always print a traceback on exception
424 --traceback always print a traceback on exception
425 --time time how long the command takes
425 --time time how long the command takes
426 --profile print command execution profile
426 --profile print command execution profile
427 --version output version information and exit
427 --version output version information and exit
428 -h --help display help and exit
428 -h --help display help and exit
429 --hidden consider hidden changesets
429 --hidden consider hidden changesets
430
430
431 Test the textwidth config option
431 Test the textwidth config option
432
432
433 $ hg root -h --config ui.textwidth=50
433 $ hg root -h --config ui.textwidth=50
434 hg root
434 hg root
435
435
436 print the root (top) of the current working
436 print the root (top) of the current working
437 directory
437 directory
438
438
439 Print the root directory of the current
439 Print the root directory of the current
440 repository.
440 repository.
441
441
442 Returns 0 on success.
442 Returns 0 on success.
443
443
444 (some details hidden, use --verbose to show
444 (some details hidden, use --verbose to show
445 complete help)
445 complete help)
446
446
447 Test help option with version option
447 Test help option with version option
448
448
449 $ hg add -h --version
449 $ hg add -h --version
450 Mercurial Distributed SCM (version *) (glob)
450 Mercurial Distributed SCM (version *) (glob)
451 (see https://mercurial-scm.org for more information)
451 (see https://mercurial-scm.org for more information)
452
452
453 Copyright (C) 2005-2016 Matt Mackall and others
453 Copyright (C) 2005-2016 Matt Mackall and others
454 This is free software; see the source for copying conditions. There is NO
454 This is free software; see the source for copying conditions. There is NO
455 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
455 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
456
456
457 $ hg add --skjdfks
457 $ hg add --skjdfks
458 hg add: option --skjdfks not recognized
458 hg add: option --skjdfks not recognized
459 hg add [OPTION]... [FILE]...
459 hg add [OPTION]... [FILE]...
460
460
461 add the specified files on the next commit
461 add the specified files on the next commit
462
462
463 options ([+] can be repeated):
463 options ([+] can be repeated):
464
464
465 -I --include PATTERN [+] include names matching the given patterns
465 -I --include PATTERN [+] include names matching the given patterns
466 -X --exclude PATTERN [+] exclude names matching the given patterns
466 -X --exclude PATTERN [+] exclude names matching the given patterns
467 -S --subrepos recurse into subrepositories
467 -S --subrepos recurse into subrepositories
468 -n --dry-run do not perform actions, just print output
468 -n --dry-run do not perform actions, just print output
469
469
470 (use "hg add -h" to show more help)
470 (use "hg add -h" to show more help)
471 [255]
471 [255]
472
472
473 Test ambiguous command help
473 Test ambiguous command help
474
474
475 $ hg help ad
475 $ hg help ad
476 list of commands:
476 list of commands:
477
477
478 add add the specified files on the next commit
478 add add the specified files on the next commit
479 addremove add all new files, delete all missing files
479 addremove add all new files, delete all missing files
480
480
481 (use "hg help -v ad" to show built-in aliases and global options)
481 (use "hg help -v ad" to show built-in aliases and global options)
482
482
483 Test command without options
483 Test command without options
484
484
485 $ hg help verify
485 $ hg help verify
486 hg verify
486 hg verify
487
487
488 verify the integrity of the repository
488 verify the integrity of the repository
489
489
490 Verify the integrity of the current repository.
490 Verify the integrity of the current repository.
491
491
492 This will perform an extensive check of the repository's integrity,
492 This will perform an extensive check of the repository's integrity,
493 validating the hashes and checksums of each entry in the changelog,
493 validating the hashes and checksums of each entry in the changelog,
494 manifest, and tracked files, as well as the integrity of their crosslinks
494 manifest, and tracked files, as well as the integrity of their crosslinks
495 and indices.
495 and indices.
496
496
497 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
497 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
498 information about recovery from corruption of the repository.
498 information about recovery from corruption of the repository.
499
499
500 Returns 0 on success, 1 if errors are encountered.
500 Returns 0 on success, 1 if errors are encountered.
501
501
502 (some details hidden, use --verbose to show complete help)
502 (some details hidden, use --verbose to show complete help)
503
503
504 $ hg help diff
504 $ hg help diff
505 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
505 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
506
506
507 diff repository (or selected files)
507 diff repository (or selected files)
508
508
509 Show differences between revisions for the specified files.
509 Show differences between revisions for the specified files.
510
510
511 Differences between files are shown using the unified diff format.
511 Differences between files are shown using the unified diff format.
512
512
513 Note:
513 Note:
514 'hg diff' may generate unexpected results for merges, as it will
514 'hg diff' may generate unexpected results for merges, as it will
515 default to comparing against the working directory's first parent
515 default to comparing against the working directory's first parent
516 changeset if no revisions are specified.
516 changeset if no revisions are specified.
517
517
518 When two revision arguments are given, then changes are shown between
518 When two revision arguments are given, then changes are shown between
519 those revisions. If only one revision is specified then that revision is
519 those revisions. If only one revision is specified then that revision is
520 compared to the working directory, and, when no revisions are specified,
520 compared to the working directory, and, when no revisions are specified,
521 the working directory files are compared to its first parent.
521 the working directory files are compared to its first parent.
522
522
523 Alternatively you can specify -c/--change with a revision to see the
523 Alternatively you can specify -c/--change with a revision to see the
524 changes in that changeset relative to its first parent.
524 changes in that changeset relative to its first parent.
525
525
526 Without the -a/--text option, diff will avoid generating diffs of files it
526 Without the -a/--text option, diff will avoid generating diffs of files it
527 detects as binary. With -a, diff will generate a diff anyway, probably
527 detects as binary. With -a, diff will generate a diff anyway, probably
528 with undesirable results.
528 with undesirable results.
529
529
530 Use the -g/--git option to generate diffs in the git extended diff format.
530 Use the -g/--git option to generate diffs in the git extended diff format.
531 For more information, read 'hg help diffs'.
531 For more information, read 'hg help diffs'.
532
532
533 Returns 0 on success.
533 Returns 0 on success.
534
534
535 options ([+] can be repeated):
535 options ([+] can be repeated):
536
536
537 -r --rev REV [+] revision
537 -r --rev REV [+] revision
538 -c --change REV change made by revision
538 -c --change REV change made by revision
539 -a --text treat all files as text
539 -a --text treat all files as text
540 -g --git use git extended diff format
540 -g --git use git extended diff format
541 --nodates omit dates from diff headers
541 --nodates omit dates from diff headers
542 --noprefix omit a/ and b/ prefixes from filenames
542 --noprefix omit a/ and b/ prefixes from filenames
543 -p --show-function show which function each change is in
543 -p --show-function show which function each change is in
544 --reverse produce a diff that undoes the changes
544 --reverse produce a diff that undoes the changes
545 -w --ignore-all-space ignore white space when comparing lines
545 -w --ignore-all-space ignore white space when comparing lines
546 -b --ignore-space-change ignore changes in the amount of white space
546 -b --ignore-space-change ignore changes in the amount of white space
547 -B --ignore-blank-lines ignore changes whose lines are all blank
547 -B --ignore-blank-lines ignore changes whose lines are all blank
548 -U --unified NUM number of lines of context to show
548 -U --unified NUM number of lines of context to show
549 --stat output diffstat-style summary of changes
549 --stat output diffstat-style summary of changes
550 --root DIR produce diffs relative to subdirectory
550 --root DIR produce diffs relative to subdirectory
551 -I --include PATTERN [+] include names matching the given patterns
551 -I --include PATTERN [+] include names matching the given patterns
552 -X --exclude PATTERN [+] exclude names matching the given patterns
552 -X --exclude PATTERN [+] exclude names matching the given patterns
553 -S --subrepos recurse into subrepositories
553 -S --subrepos recurse into subrepositories
554
554
555 (some details hidden, use --verbose to show complete help)
555 (some details hidden, use --verbose to show complete help)
556
556
557 $ hg help status
557 $ hg help status
558 hg status [OPTION]... [FILE]...
558 hg status [OPTION]... [FILE]...
559
559
560 aliases: st
560 aliases: st
561
561
562 show changed files in the working directory
562 show changed files in the working directory
563
563
564 Show status of files in the repository. If names are given, only files
564 Show status of files in the repository. If names are given, only files
565 that match are shown. Files that are clean or ignored or the source of a
565 that match are shown. Files that are clean or ignored or the source of a
566 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
566 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
567 -C/--copies or -A/--all are given. Unless options described with "show
567 -C/--copies or -A/--all are given. Unless options described with "show
568 only ..." are given, the options -mardu are used.
568 only ..." are given, the options -mardu are used.
569
569
570 Option -q/--quiet hides untracked (unknown and ignored) files unless
570 Option -q/--quiet hides untracked (unknown and ignored) files unless
571 explicitly requested with -u/--unknown or -i/--ignored.
571 explicitly requested with -u/--unknown or -i/--ignored.
572
572
573 Note:
573 Note:
574 'hg status' may appear to disagree with diff if permissions have
574 'hg status' may appear to disagree with diff if permissions have
575 changed or a merge has occurred. The standard diff format does not
575 changed or a merge has occurred. The standard diff format does not
576 report permission changes and diff only reports changes relative to one
576 report permission changes and diff only reports changes relative to one
577 merge parent.
577 merge parent.
578
578
579 If one revision is given, it is used as the base revision. If two
579 If one revision is given, it is used as the base revision. If two
580 revisions are given, the differences between them are shown. The --change
580 revisions are given, the differences between them are shown. The --change
581 option can also be used as a shortcut to list the changed files of a
581 option can also be used as a shortcut to list the changed files of a
582 revision from its first parent.
582 revision from its first parent.
583
583
584 The codes used to show the status of files are:
584 The codes used to show the status of files are:
585
585
586 M = modified
586 M = modified
587 A = added
587 A = added
588 R = removed
588 R = removed
589 C = clean
589 C = clean
590 ! = missing (deleted by non-hg command, but still tracked)
590 ! = missing (deleted by non-hg command, but still tracked)
591 ? = not tracked
591 ? = not tracked
592 I = ignored
592 I = ignored
593 = origin of the previous file (with --copies)
593 = origin of the previous file (with --copies)
594
594
595 Returns 0 on success.
595 Returns 0 on success.
596
596
597 options ([+] can be repeated):
597 options ([+] can be repeated):
598
598
599 -A --all show status of all files
599 -A --all show status of all files
600 -m --modified show only modified files
600 -m --modified show only modified files
601 -a --added show only added files
601 -a --added show only added files
602 -r --removed show only removed files
602 -r --removed show only removed files
603 -d --deleted show only deleted (but tracked) files
603 -d --deleted show only deleted (but tracked) files
604 -c --clean show only files without changes
604 -c --clean show only files without changes
605 -u --unknown show only unknown (not tracked) files
605 -u --unknown show only unknown (not tracked) files
606 -i --ignored show only ignored files
606 -i --ignored show only ignored files
607 -n --no-status hide status prefix
607 -n --no-status hide status prefix
608 -C --copies show source of copied files
608 -C --copies show source of copied files
609 -0 --print0 end filenames with NUL, for use with xargs
609 -0 --print0 end filenames with NUL, for use with xargs
610 --rev REV [+] show difference from revision
610 --rev REV [+] show difference from revision
611 --change REV list the changed files of a revision
611 --change REV list the changed files of a revision
612 -I --include PATTERN [+] include names matching the given patterns
612 -I --include PATTERN [+] include names matching the given patterns
613 -X --exclude PATTERN [+] exclude names matching the given patterns
613 -X --exclude PATTERN [+] exclude names matching the given patterns
614 -S --subrepos recurse into subrepositories
614 -S --subrepos recurse into subrepositories
615
615
616 (some details hidden, use --verbose to show complete help)
616 (some details hidden, use --verbose to show complete help)
617
617
618 $ hg -q help status
618 $ hg -q help status
619 hg status [OPTION]... [FILE]...
619 hg status [OPTION]... [FILE]...
620
620
621 show changed files in the working directory
621 show changed files in the working directory
622
622
623 $ hg help foo
623 $ hg help foo
624 abort: no such help topic: foo
624 abort: no such help topic: foo
625 (try "hg help --keyword foo")
625 (try "hg help --keyword foo")
626 [255]
626 [255]
627
627
628 $ hg skjdfks
628 $ hg skjdfks
629 hg: unknown command 'skjdfks'
629 hg: unknown command 'skjdfks'
630 Mercurial Distributed SCM
630 Mercurial Distributed SCM
631
631
632 basic commands:
632 basic commands:
633
633
634 add add the specified files on the next commit
634 add add the specified files on the next commit
635 annotate show changeset information by line for each file
635 annotate show changeset information by line for each file
636 clone make a copy of an existing repository
636 clone make a copy of an existing repository
637 commit commit the specified files or all outstanding changes
637 commit commit the specified files or all outstanding changes
638 diff diff repository (or selected files)
638 diff diff repository (or selected files)
639 export dump the header and diffs for one or more changesets
639 export dump the header and diffs for one or more changesets
640 forget forget the specified files on the next commit
640 forget forget the specified files on the next commit
641 init create a new repository in the given directory
641 init create a new repository in the given directory
642 log show revision history of entire repository or files
642 log show revision history of entire repository or files
643 merge merge another revision into working directory
643 merge merge another revision into working directory
644 pull pull changes from the specified source
644 pull pull changes from the specified source
645 push push changes to the specified destination
645 push push changes to the specified destination
646 remove remove the specified files on the next commit
646 remove remove the specified files on the next commit
647 serve start stand-alone webserver
647 serve start stand-alone webserver
648 status show changed files in the working directory
648 status show changed files in the working directory
649 summary summarize working directory state
649 summary summarize working directory state
650 update update working directory (or switch revisions)
650 update update working directory (or switch revisions)
651
651
652 (use "hg help" for the full list of commands or "hg -v" for details)
652 (use "hg help" for the full list of commands or "hg -v" for details)
653 [255]
653 [255]
654
654
655
655
656 Make sure that we don't run afoul of the help system thinking that
656 Make sure that we don't run afoul of the help system thinking that
657 this is a section and erroring out weirdly.
657 this is a section and erroring out weirdly.
658
658
659 $ hg .log
659 $ hg .log
660 hg: unknown command '.log'
660 hg: unknown command '.log'
661 (did you mean log?)
661 (did you mean log?)
662 [255]
662 [255]
663
663
664 $ hg log.
664 $ hg log.
665 hg: unknown command 'log.'
665 hg: unknown command 'log.'
666 (did you mean log?)
666 (did you mean log?)
667 [255]
667 [255]
668 $ hg pu.lh
668 $ hg pu.lh
669 hg: unknown command 'pu.lh'
669 hg: unknown command 'pu.lh'
670 (did you mean one of pull, push?)
670 (did you mean one of pull, push?)
671 [255]
671 [255]
672
672
673 $ cat > helpext.py <<EOF
673 $ cat > helpext.py <<EOF
674 > import os
674 > import os
675 > from mercurial import cmdutil, commands
675 > from mercurial import cmdutil, commands
676 >
676 >
677 > cmdtable = {}
677 > cmdtable = {}
678 > command = cmdutil.command(cmdtable)
678 > command = cmdutil.command(cmdtable)
679 >
679 >
680 > @command('nohelp',
680 > @command('nohelp',
681 > [('', 'longdesc', 3, 'x'*90),
681 > [('', 'longdesc', 3, 'x'*90),
682 > ('n', '', None, 'normal desc'),
682 > ('n', '', None, 'normal desc'),
683 > ('', 'newline', '', 'line1\nline2')],
683 > ('', 'newline', '', 'line1\nline2')],
684 > 'hg nohelp',
684 > 'hg nohelp',
685 > norepo=True)
685 > norepo=True)
686 > @command('debugoptDEP', [('', 'dopt', None, 'option is (DEPRECATED)')])
686 > @command('debugoptDEP', [('', 'dopt', None, 'option is (DEPRECATED)')])
687 > @command('debugoptEXP', [('', 'eopt', None, 'option is (EXPERIMENTAL)')])
687 > @command('debugoptEXP', [('', 'eopt', None, 'option is (EXPERIMENTAL)')])
688 > def nohelp(ui, *args, **kwargs):
688 > def nohelp(ui, *args, **kwargs):
689 > pass
689 > pass
690 >
690 >
691 > def uisetup(ui):
691 > def uisetup(ui):
692 > ui.setconfig('alias', 'shellalias', '!echo hi', 'helpext')
692 > ui.setconfig('alias', 'shellalias', '!echo hi', 'helpext')
693 > ui.setconfig('alias', 'hgalias', 'summary', 'helpext')
693 > ui.setconfig('alias', 'hgalias', 'summary', 'helpext')
694 >
694 >
695 > EOF
695 > EOF
696 $ echo '[extensions]' >> $HGRCPATH
696 $ echo '[extensions]' >> $HGRCPATH
697 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
697 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
698
698
699 Test for aliases
699 Test for aliases
700
700
701 $ hg help hgalias
701 $ hg help hgalias
702 hg hgalias [--remote]
702 hg hgalias [--remote]
703
703
704 alias for: hg summary
704 alias for: hg summary
705
705
706 summarize working directory state
706 summarize working directory state
707
707
708 This generates a brief summary of the working directory state, including
708 This generates a brief summary of the working directory state, including
709 parents, branch, commit status, phase and available updates.
709 parents, branch, commit status, phase and available updates.
710
710
711 With the --remote option, this will check the default paths for incoming
711 With the --remote option, this will check the default paths for incoming
712 and outgoing changes. This can be time-consuming.
712 and outgoing changes. This can be time-consuming.
713
713
714 Returns 0 on success.
714 Returns 0 on success.
715
715
716 defined by: helpext
716 defined by: helpext
717
717
718 options:
718 options:
719
719
720 --remote check for push and pull
720 --remote check for push and pull
721
721
722 (some details hidden, use --verbose to show complete help)
722 (some details hidden, use --verbose to show complete help)
723
723
724 $ hg help shellalias
724 $ hg help shellalias
725 hg shellalias
725 hg shellalias
726
726
727 shell alias for:
727 shell alias for:
728
728
729 echo hi
729 echo hi
730
730
731 defined by: helpext
731 defined by: helpext
732
732
733 (some details hidden, use --verbose to show complete help)
733 (some details hidden, use --verbose to show complete help)
734
734
735 Test command with no help text
735 Test command with no help text
736
736
737 $ hg help nohelp
737 $ hg help nohelp
738 hg nohelp
738 hg nohelp
739
739
740 (no help text available)
740 (no help text available)
741
741
742 options:
742 options:
743
743
744 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
744 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
745 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
745 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
746 -n -- normal desc
746 -n -- normal desc
747 --newline VALUE line1 line2
747 --newline VALUE line1 line2
748
748
749 (some details hidden, use --verbose to show complete help)
749 (some details hidden, use --verbose to show complete help)
750
750
751 $ hg help -k nohelp
751 $ hg help -k nohelp
752 Commands:
752 Commands:
753
753
754 nohelp hg nohelp
754 nohelp hg nohelp
755
755
756 Extension Commands:
756 Extension Commands:
757
757
758 nohelp (no help text available)
758 nohelp (no help text available)
759
759
760 Test that default list of commands omits extension commands
760 Test that default list of commands omits extension commands
761
761
762 $ hg help
762 $ hg help
763 Mercurial Distributed SCM
763 Mercurial Distributed SCM
764
764
765 list of commands:
765 list of commands:
766
766
767 add add the specified files on the next commit
767 add add the specified files on the next commit
768 addremove add all new files, delete all missing files
768 addremove add all new files, delete all missing files
769 annotate show changeset information by line for each file
769 annotate show changeset information by line for each file
770 archive create an unversioned archive of a repository revision
770 archive create an unversioned archive of a repository revision
771 backout reverse effect of earlier changeset
771 backout reverse effect of earlier changeset
772 bisect subdivision search of changesets
772 bisect subdivision search of changesets
773 bookmarks create a new bookmark or list existing bookmarks
773 bookmarks create a new bookmark or list existing bookmarks
774 branch set or show the current branch name
774 branch set or show the current branch name
775 branches list repository named branches
775 branches list repository named branches
776 bundle create a changegroup file
776 bundle create a changegroup file
777 cat output the current or given revision of files
777 cat output the current or given revision of files
778 clone make a copy of an existing repository
778 clone make a copy of an existing repository
779 commit commit the specified files or all outstanding changes
779 commit commit the specified files or all outstanding changes
780 config show combined config settings from all hgrc files
780 config show combined config settings from all hgrc files
781 copy mark files as copied for the next commit
781 copy mark files as copied for the next commit
782 diff diff repository (or selected files)
782 diff diff repository (or selected files)
783 export dump the header and diffs for one or more changesets
783 export dump the header and diffs for one or more changesets
784 files list tracked files
784 files list tracked files
785 forget forget the specified files on the next commit
785 forget forget the specified files on the next commit
786 graft copy changes from other branches onto the current branch
786 graft copy changes from other branches onto the current branch
787 grep search for a pattern in specified files and revisions
787 grep search for a pattern in specified files and revisions
788 heads show branch heads
788 heads show branch heads
789 help show help for a given topic or a help overview
789 help show help for a given topic or a help overview
790 identify identify the working directory or specified revision
790 identify identify the working directory or specified revision
791 import import an ordered set of patches
791 import import an ordered set of patches
792 incoming show new changesets found in source
792 incoming show new changesets found in source
793 init create a new repository in the given directory
793 init create a new repository in the given directory
794 log show revision history of entire repository or files
794 log show revision history of entire repository or files
795 manifest output the current or given revision of the project manifest
795 manifest output the current or given revision of the project manifest
796 merge merge another revision into working directory
796 merge merge another revision into working directory
797 outgoing show changesets not found in the destination
797 outgoing show changesets not found in the destination
798 paths show aliases for remote repositories
798 paths show aliases for remote repositories
799 phase set or show the current phase name
799 phase set or show the current phase name
800 pull pull changes from the specified source
800 pull pull changes from the specified source
801 push push changes to the specified destination
801 push push changes to the specified destination
802 recover roll back an interrupted transaction
802 recover roll back an interrupted transaction
803 remove remove the specified files on the next commit
803 remove remove the specified files on the next commit
804 rename rename files; equivalent of copy + remove
804 rename rename files; equivalent of copy + remove
805 resolve redo merges or set/view the merge status of files
805 resolve redo merges or set/view the merge status of files
806 revert restore files to their checkout state
806 revert restore files to their checkout state
807 root print the root (top) of the current working directory
807 root print the root (top) of the current working directory
808 serve start stand-alone webserver
808 serve start stand-alone webserver
809 status show changed files in the working directory
809 status show changed files in the working directory
810 summary summarize working directory state
810 summary summarize working directory state
811 tag add one or more tags for the current or given revision
811 tag add one or more tags for the current or given revision
812 tags list repository tags
812 tags list repository tags
813 unbundle apply one or more changegroup files
813 unbundle apply one or more changegroup files
814 update update working directory (or switch revisions)
814 update update working directory (or switch revisions)
815 verify verify the integrity of the repository
815 verify verify the integrity of the repository
816 version output version and copyright information
816 version output version and copyright information
817
817
818 enabled extensions:
818 enabled extensions:
819
819
820 helpext (no help text available)
820 helpext (no help text available)
821
821
822 additional help topics:
822 additional help topics:
823
823
824 config Configuration Files
824 config Configuration Files
825 dates Date Formats
825 dates Date Formats
826 diffs Diff Formats
826 diffs Diff Formats
827 environment Environment Variables
827 environment Environment Variables
828 extensions Using Additional Features
828 extensions Using Additional Features
829 filesets Specifying File Sets
829 filesets Specifying File Sets
830 glossary Glossary
830 glossary Glossary
831 hgignore Syntax for Mercurial Ignore Files
831 hgignore Syntax for Mercurial Ignore Files
832 hgweb Configuring hgweb
832 hgweb Configuring hgweb
833 internals Technical implementation topics
833 internals Technical implementation topics
834 merge-tools Merge Tools
834 merge-tools Merge Tools
835 multirevs Specifying Multiple Revisions
835 multirevs Specifying Multiple Revisions
836 patterns File Name Patterns
836 patterns File Name Patterns
837 phases Working with Phases
837 phases Working with Phases
838 revisions Specifying Single Revisions
838 revisions Specifying Single Revisions
839 revsets Specifying Revision Sets
839 revsets Specifying Revision Sets
840 scripting Using Mercurial from scripts and automation
840 scripting Using Mercurial from scripts and automation
841 subrepos Subrepositories
841 subrepos Subrepositories
842 templating Template Usage
842 templating Template Usage
843 urls URL Paths
843 urls URL Paths
844
844
845 (use "hg help -v" to show built-in aliases and global options)
845 (use "hg help -v" to show built-in aliases and global options)
846
846
847
847
848 Test list of internal help commands
848 Test list of internal help commands
849
849
850 $ hg help debug
850 $ hg help debug
851 debug commands (internal and unsupported):
851 debug commands (internal and unsupported):
852
852
853 debugancestor
853 debugancestor
854 find the ancestor revision of two revisions in a given index
854 find the ancestor revision of two revisions in a given index
855 debugapplystreamclonebundle
855 debugapplystreamclonebundle
856 apply a stream clone bundle file
856 apply a stream clone bundle file
857 debugbuilddag
857 debugbuilddag
858 builds a repo with a given DAG from scratch in the current
858 builds a repo with a given DAG from scratch in the current
859 empty repo
859 empty repo
860 debugbundle lists the contents of a bundle
860 debugbundle lists the contents of a bundle
861 debugcheckstate
861 debugcheckstate
862 validate the correctness of the current dirstate
862 validate the correctness of the current dirstate
863 debugcommands
863 debugcommands
864 list all available commands and options
864 list all available commands and options
865 debugcomplete
865 debugcomplete
866 returns the completion list associated with the given command
866 returns the completion list associated with the given command
867 debugcreatestreamclonebundle
867 debugcreatestreamclonebundle
868 create a stream clone bundle file
868 create a stream clone bundle file
869 debugdag format the changelog or an index DAG as a concise textual
869 debugdag format the changelog or an index DAG as a concise textual
870 description
870 description
871 debugdata dump the contents of a data file revision
871 debugdata dump the contents of a data file revision
872 debugdate parse and display a date
872 debugdate parse and display a date
873 debugdeltachain
873 debugdeltachain
874 dump information about delta chains in a revlog
874 dump information about delta chains in a revlog
875 debugdirstate
875 debugdirstate
876 show the contents of the current dirstate
876 show the contents of the current dirstate
877 debugdiscovery
877 debugdiscovery
878 runs the changeset discovery protocol in isolation
878 runs the changeset discovery protocol in isolation
879 debugextensions
879 debugextensions
880 show information about active extensions
880 show information about active extensions
881 debugfileset parse and apply a fileset specification
881 debugfileset parse and apply a fileset specification
882 debugfsinfo show information detected about current filesystem
882 debugfsinfo show information detected about current filesystem
883 debuggetbundle
883 debuggetbundle
884 retrieves a bundle from a repo
884 retrieves a bundle from a repo
885 debugignore display the combined ignore pattern and information about
885 debugignore display the combined ignore pattern and information about
886 ignored files
886 ignored files
887 debugindex dump the contents of an index file
887 debugindex dump the contents of an index file
888 debugindexdot
888 debugindexdot
889 dump an index DAG as a graphviz dot file
889 dump an index DAG as a graphviz dot file
890 debuginstall test Mercurial installation
890 debuginstall test Mercurial installation
891 debugknown test whether node ids are known to a repo
891 debugknown test whether node ids are known to a repo
892 debuglocks show or modify state of locks
892 debuglocks show or modify state of locks
893 debugmergestate
893 debugmergestate
894 print merge state
894 print merge state
895 debugnamecomplete
895 debugnamecomplete
896 complete "names" - tags, open branch names, bookmark names
896 complete "names" - tags, open branch names, bookmark names
897 debugobsolete
897 debugobsolete
898 create arbitrary obsolete marker
898 create arbitrary obsolete marker
899 debugoptDEP (no help text available)
899 debugoptDEP (no help text available)
900 debugoptEXP (no help text available)
900 debugoptEXP (no help text available)
901 debugpathcomplete
901 debugpathcomplete
902 complete part or all of a tracked path
902 complete part or all of a tracked path
903 debugpushkey access the pushkey key/value protocol
903 debugpushkey access the pushkey key/value protocol
904 debugpvec (no help text available)
904 debugpvec (no help text available)
905 debugrebuilddirstate
905 debugrebuilddirstate
906 rebuild the dirstate as it would look like for the given
906 rebuild the dirstate as it would look like for the given
907 revision
907 revision
908 debugrebuildfncache
908 debugrebuildfncache
909 rebuild the fncache file
909 rebuild the fncache file
910 debugrename dump rename information
910 debugrename dump rename information
911 debugrevlog show data and statistics about a revlog
911 debugrevlog show data and statistics about a revlog
912 debugrevspec parse and apply a revision specification
912 debugrevspec parse and apply a revision specification
913 debugsetparents
913 debugsetparents
914 manually set the parents of the current working directory
914 manually set the parents of the current working directory
915 debugsub (no help text available)
915 debugsub (no help text available)
916 debugsuccessorssets
916 debugsuccessorssets
917 show set of successors for revision
917 show set of successors for revision
918 debugtemplate
918 debugtemplate
919 parse and apply a template
919 parse and apply a template
920 debugwalk show how files match on given patterns
920 debugwalk show how files match on given patterns
921 debugwireargs
921 debugwireargs
922 (no help text available)
922 (no help text available)
923
923
924 (use "hg help -v debug" to show built-in aliases and global options)
924 (use "hg help -v debug" to show built-in aliases and global options)
925
925
926 internals topic renders index of available sub-topics
926 internals topic renders index of available sub-topics
927
927
928 $ hg help internals
928 $ hg help internals
929 Technical implementation topics
929 Technical implementation topics
930 """""""""""""""""""""""""""""""
930 """""""""""""""""""""""""""""""
931
931
932 bundles container for exchange of repository data
932 bundles Bundles
933 changegroups representation of revlog data
933 changegroups Changegroups
934 requirements repository requirements
934 requirements Repository Requirements
935 revlogs revision storage mechanism
935 revlogs Revision Logs
936
936
937 sub-topics can be accessed
937 sub-topics can be accessed
938
938
939 $ hg help internals.changegroups
939 $ hg help internals.changegroups
940 Changegroups
940 Changegroups
941 ============
941 """"""""""""
942
942
943 Changegroups are representations of repository revlog data, specifically
943 Changegroups are representations of repository revlog data, specifically
944 the changelog, manifest, and filelogs.
944 the changelog, manifest, and filelogs.
945
945
946 There are 3 versions of changegroups: "1", "2", and "3". From a high-
946 There are 3 versions of changegroups: "1", "2", and "3". From a high-
947 level, versions "1" and "2" are almost exactly the same, with the only
947 level, versions "1" and "2" are almost exactly the same, with the only
948 difference being a header on entries in the changeset segment. Version "3"
948 difference being a header on entries in the changeset segment. Version "3"
949 adds support for exchanging treemanifests and includes revlog flags in the
949 adds support for exchanging treemanifests and includes revlog flags in the
950 delta header.
950 delta header.
951
951
952 Changegroups consists of 3 logical segments:
952 Changegroups consists of 3 logical segments:
953
953
954 +---------------------------------+
954 +---------------------------------+
955 | | | |
955 | | | |
956 | changeset | manifest | filelogs |
956 | changeset | manifest | filelogs |
957 | | | |
957 | | | |
958 +---------------------------------+
958 +---------------------------------+
959
959
960 The principle building block of each segment is a *chunk*. A *chunk* is a
960 The principle building block of each segment is a *chunk*. A *chunk* is a
961 framed piece of data:
961 framed piece of data:
962
962
963 +---------------------------------------+
963 +---------------------------------------+
964 | | |
964 | | |
965 | length | data |
965 | length | data |
966 | (32 bits) | <length> bytes |
966 | (32 bits) | <length> bytes |
967 | | |
967 | | |
968 +---------------------------------------+
968 +---------------------------------------+
969
969
970 Each chunk starts with a 32-bit big-endian signed integer indicating the
970 Each chunk starts with a 32-bit big-endian signed integer indicating the
971 length of the raw data that follows.
971 length of the raw data that follows.
972
972
973 There is a special case chunk that has 0 length ("0x00000000"). We call
973 There is a special case chunk that has 0 length ("0x00000000"). We call
974 this an *empty chunk*.
974 this an *empty chunk*.
975
975
976 Delta Groups
976 Delta Groups
977 ------------
977 ============
978
978
979 A *delta group* expresses the content of a revlog as a series of deltas,
979 A *delta group* expresses the content of a revlog as a series of deltas,
980 or patches against previous revisions.
980 or patches against previous revisions.
981
981
982 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
982 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
983 to signal the end of the delta group:
983 to signal the end of the delta group:
984
984
985 +------------------------------------------------------------------------+
985 +------------------------------------------------------------------------+
986 | | | | | |
986 | | | | | |
987 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
987 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
988 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
988 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
989 | | | | | |
989 | | | | | |
990 +------------------------------------------------------------+-----------+
990 +------------------------------------------------------------+-----------+
991
991
992 Each *chunk*'s data consists of the following:
992 Each *chunk*'s data consists of the following:
993
993
994 +-----------------------------------------+
994 +-----------------------------------------+
995 | | | |
995 | | | |
996 | delta header | mdiff header | delta |
996 | delta header | mdiff header | delta |
997 | (various) | (12 bytes) | (various) |
997 | (various) | (12 bytes) | (various) |
998 | | | |
998 | | | |
999 +-----------------------------------------+
999 +-----------------------------------------+
1000
1000
1001 The *length* field is the byte length of the remaining 3 logical pieces of
1001 The *length* field is the byte length of the remaining 3 logical pieces of
1002 data. The *delta* is a diff from an existing entry in the changelog.
1002 data. The *delta* is a diff from an existing entry in the changelog.
1003
1003
1004 The *delta header* is different between versions "1", "2", and "3" of the
1004 The *delta header* is different between versions "1", "2", and "3" of the
1005 changegroup format.
1005 changegroup format.
1006
1006
1007 Version 1:
1007 Version 1:
1008
1008
1009 +------------------------------------------------------+
1009 +------------------------------------------------------+
1010 | | | | |
1010 | | | | |
1011 | node | p1 node | p2 node | link node |
1011 | node | p1 node | p2 node | link node |
1012 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1012 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1013 | | | | |
1013 | | | | |
1014 +------------------------------------------------------+
1014 +------------------------------------------------------+
1015
1015
1016 Version 2:
1016 Version 2:
1017
1017
1018 +------------------------------------------------------------------+
1018 +------------------------------------------------------------------+
1019 | | | | | |
1019 | | | | | |
1020 | node | p1 node | p2 node | base node | link node |
1020 | node | p1 node | p2 node | base node | link node |
1021 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1021 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1022 | | | | | |
1022 | | | | | |
1023 +------------------------------------------------------------------+
1023 +------------------------------------------------------------------+
1024
1024
1025 Version 3:
1025 Version 3:
1026
1026
1027 +------------------------------------------------------------------------------+
1027 +------------------------------------------------------------------------------+
1028 | | | | | | |
1028 | | | | | | |
1029 | node | p1 node | p2 node | base node | link node | flags |
1029 | node | p1 node | p2 node | base node | link node | flags |
1030 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1030 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1031 | | | | | | |
1031 | | | | | | |
1032 +------------------------------------------------------------------------------+
1032 +------------------------------------------------------------------------------+
1033
1033
1034 The *mdiff header* consists of 3 32-bit big-endian signed integers
1034 The *mdiff header* consists of 3 32-bit big-endian signed integers
1035 describing offsets at which to apply the following delta content:
1035 describing offsets at which to apply the following delta content:
1036
1036
1037 +-------------------------------------+
1037 +-------------------------------------+
1038 | | | |
1038 | | | |
1039 | offset | old length | new length |
1039 | offset | old length | new length |
1040 | (32 bits) | (32 bits) | (32 bits) |
1040 | (32 bits) | (32 bits) | (32 bits) |
1041 | | | |
1041 | | | |
1042 +-------------------------------------+
1042 +-------------------------------------+
1043
1043
1044 In version 1, the delta is always applied against the previous node from
1044 In version 1, the delta is always applied against the previous node from
1045 the changegroup or the first parent if this is the first entry in the
1045 the changegroup or the first parent if this is the first entry in the
1046 changegroup.
1046 changegroup.
1047
1047
1048 In version 2, the delta base node is encoded in the entry in the
1048 In version 2, the delta base node is encoded in the entry in the
1049 changegroup. This allows the delta to be expressed against any parent,
1049 changegroup. This allows the delta to be expressed against any parent,
1050 which can result in smaller deltas and more efficient encoding of data.
1050 which can result in smaller deltas and more efficient encoding of data.
1051
1051
1052 Changeset Segment
1052 Changeset Segment
1053 -----------------
1053 =================
1054
1054
1055 The *changeset segment* consists of a single *delta group* holding
1055 The *changeset segment* consists of a single *delta group* holding
1056 changelog data. It is followed by an *empty chunk* to denote the boundary
1056 changelog data. It is followed by an *empty chunk* to denote the boundary
1057 to the *manifests segment*.
1057 to the *manifests segment*.
1058
1058
1059 Manifest Segment
1059 Manifest Segment
1060 ----------------
1060 ================
1061
1061
1062 The *manifest segment* consists of a single *delta group* holding manifest
1062 The *manifest segment* consists of a single *delta group* holding manifest
1063 data. It is followed by an *empty chunk* to denote the boundary to the
1063 data. It is followed by an *empty chunk* to denote the boundary to the
1064 *filelogs segment*.
1064 *filelogs segment*.
1065
1065
1066 Filelogs Segment
1066 Filelogs Segment
1067 ----------------
1067 ================
1068
1068
1069 The *filelogs* segment consists of multiple sub-segments, each
1069 The *filelogs* segment consists of multiple sub-segments, each
1070 corresponding to an individual file whose data is being described:
1070 corresponding to an individual file whose data is being described:
1071
1071
1072 +--------------------------------------+
1072 +--------------------------------------+
1073 | | | | |
1073 | | | | |
1074 | filelog0 | filelog1 | filelog2 | ... |
1074 | filelog0 | filelog1 | filelog2 | ... |
1075 | | | | |
1075 | | | | |
1076 +--------------------------------------+
1076 +--------------------------------------+
1077
1077
1078 In version "3" of the changegroup format, filelogs may include directory
1078 In version "3" of the changegroup format, filelogs may include directory
1079 logs when treemanifests are in use. directory logs are identified by
1079 logs when treemanifests are in use. directory logs are identified by
1080 having a trailing '/' on their filename (see below).
1080 having a trailing '/' on their filename (see below).
1081
1081
1082 The final filelog sub-segment is followed by an *empty chunk* to denote
1082 The final filelog sub-segment is followed by an *empty chunk* to denote
1083 the end of the segment and the overall changegroup.
1083 the end of the segment and the overall changegroup.
1084
1084
1085 Each filelog sub-segment consists of the following:
1085 Each filelog sub-segment consists of the following:
1086
1086
1087 +------------------------------------------+
1087 +------------------------------------------+
1088 | | | |
1088 | | | |
1089 | filename size | filename | delta group |
1089 | filename size | filename | delta group |
1090 | (32 bits) | (various) | (various) |
1090 | (32 bits) | (various) | (various) |
1091 | | | |
1091 | | | |
1092 +------------------------------------------+
1092 +------------------------------------------+
1093
1093
1094 That is, a *chunk* consisting of the filename (not terminated or padded)
1094 That is, a *chunk* consisting of the filename (not terminated or padded)
1095 followed by N chunks constituting the *delta group* for this file.
1095 followed by N chunks constituting the *delta group* for this file.
1096
1096
1097 Test list of commands with command with no help text
1097 Test list of commands with command with no help text
1098
1098
1099 $ hg help helpext
1099 $ hg help helpext
1100 helpext extension - no help text available
1100 helpext extension - no help text available
1101
1101
1102 list of commands:
1102 list of commands:
1103
1103
1104 nohelp (no help text available)
1104 nohelp (no help text available)
1105
1105
1106 (use "hg help -v helpext" to show built-in aliases and global options)
1106 (use "hg help -v helpext" to show built-in aliases and global options)
1107
1107
1108
1108
1109 test deprecated and experimental options are hidden in command help
1109 test deprecated and experimental options are hidden in command help
1110 $ hg help debugoptDEP
1110 $ hg help debugoptDEP
1111 hg debugoptDEP
1111 hg debugoptDEP
1112
1112
1113 (no help text available)
1113 (no help text available)
1114
1114
1115 options:
1115 options:
1116
1116
1117 (some details hidden, use --verbose to show complete help)
1117 (some details hidden, use --verbose to show complete help)
1118
1118
1119 $ hg help debugoptEXP
1119 $ hg help debugoptEXP
1120 hg debugoptEXP
1120 hg debugoptEXP
1121
1121
1122 (no help text available)
1122 (no help text available)
1123
1123
1124 options:
1124 options:
1125
1125
1126 (some details hidden, use --verbose to show complete help)
1126 (some details hidden, use --verbose to show complete help)
1127
1127
1128 test deprecated and experimental options is shown with -v
1128 test deprecated and experimental options is shown with -v
1129 $ hg help -v debugoptDEP | grep dopt
1129 $ hg help -v debugoptDEP | grep dopt
1130 --dopt option is (DEPRECATED)
1130 --dopt option is (DEPRECATED)
1131 $ hg help -v debugoptEXP | grep eopt
1131 $ hg help -v debugoptEXP | grep eopt
1132 --eopt option is (EXPERIMENTAL)
1132 --eopt option is (EXPERIMENTAL)
1133
1133
1134 #if gettext
1134 #if gettext
1135 test deprecated option is hidden with translation with untranslated description
1135 test deprecated option is hidden with translation with untranslated description
1136 (use many globy for not failing on changed transaction)
1136 (use many globy for not failing on changed transaction)
1137 $ LANGUAGE=sv hg help debugoptDEP
1137 $ LANGUAGE=sv hg help debugoptDEP
1138 hg debugoptDEP
1138 hg debugoptDEP
1139
1139
1140 (*) (glob)
1140 (*) (glob)
1141
1141
1142 options:
1142 options:
1143
1143
1144 (some details hidden, use --verbose to show complete help)
1144 (some details hidden, use --verbose to show complete help)
1145 #endif
1145 #endif
1146
1146
1147 Test commands that collide with topics (issue4240)
1147 Test commands that collide with topics (issue4240)
1148
1148
1149 $ hg config -hq
1149 $ hg config -hq
1150 hg config [-u] [NAME]...
1150 hg config [-u] [NAME]...
1151
1151
1152 show combined config settings from all hgrc files
1152 show combined config settings from all hgrc files
1153 $ hg showconfig -hq
1153 $ hg showconfig -hq
1154 hg config [-u] [NAME]...
1154 hg config [-u] [NAME]...
1155
1155
1156 show combined config settings from all hgrc files
1156 show combined config settings from all hgrc files
1157
1157
1158 Test a help topic
1158 Test a help topic
1159
1159
1160 $ hg help revs
1160 $ hg help revs
1161 Specifying Single Revisions
1161 Specifying Single Revisions
1162 """""""""""""""""""""""""""
1162 """""""""""""""""""""""""""
1163
1163
1164 Mercurial supports several ways to specify individual revisions.
1164 Mercurial supports several ways to specify individual revisions.
1165
1165
1166 A plain integer is treated as a revision number. Negative integers are
1166 A plain integer is treated as a revision number. Negative integers are
1167 treated as sequential offsets from the tip, with -1 denoting the tip, -2
1167 treated as sequential offsets from the tip, with -1 denoting the tip, -2
1168 denoting the revision prior to the tip, and so forth.
1168 denoting the revision prior to the tip, and so forth.
1169
1169
1170 A 40-digit hexadecimal string is treated as a unique revision identifier.
1170 A 40-digit hexadecimal string is treated as a unique revision identifier.
1171
1171
1172 A hexadecimal string less than 40 characters long is treated as a unique
1172 A hexadecimal string less than 40 characters long is treated as a unique
1173 revision identifier and is referred to as a short-form identifier. A
1173 revision identifier and is referred to as a short-form identifier. A
1174 short-form identifier is only valid if it is the prefix of exactly one
1174 short-form identifier is only valid if it is the prefix of exactly one
1175 full-length identifier.
1175 full-length identifier.
1176
1176
1177 Any other string is treated as a bookmark, tag, or branch name. A bookmark
1177 Any other string is treated as a bookmark, tag, or branch name. A bookmark
1178 is a movable pointer to a revision. A tag is a permanent name associated
1178 is a movable pointer to a revision. A tag is a permanent name associated
1179 with a revision. A branch name denotes the tipmost open branch head of
1179 with a revision. A branch name denotes the tipmost open branch head of
1180 that branch - or if they are all closed, the tipmost closed head of the
1180 that branch - or if they are all closed, the tipmost closed head of the
1181 branch. Bookmark, tag, and branch names must not contain the ":"
1181 branch. Bookmark, tag, and branch names must not contain the ":"
1182 character.
1182 character.
1183
1183
1184 The reserved name "tip" always identifies the most recent revision.
1184 The reserved name "tip" always identifies the most recent revision.
1185
1185
1186 The reserved name "null" indicates the null revision. This is the revision
1186 The reserved name "null" indicates the null revision. This is the revision
1187 of an empty repository, and the parent of revision 0.
1187 of an empty repository, and the parent of revision 0.
1188
1188
1189 The reserved name "." indicates the working directory parent. If no
1189 The reserved name "." indicates the working directory parent. If no
1190 working directory is checked out, it is equivalent to null. If an
1190 working directory is checked out, it is equivalent to null. If an
1191 uncommitted merge is in progress, "." is the revision of the first parent.
1191 uncommitted merge is in progress, "." is the revision of the first parent.
1192
1192
1193 Test repeated config section name
1193 Test repeated config section name
1194
1194
1195 $ hg help config.host
1195 $ hg help config.host
1196 "http_proxy.host"
1196 "http_proxy.host"
1197 Host name and (optional) port of the proxy server, for example
1197 Host name and (optional) port of the proxy server, for example
1198 "myproxy:8000".
1198 "myproxy:8000".
1199
1199
1200 "smtp.host"
1200 "smtp.host"
1201 Host name of mail server, e.g. "mail.example.com".
1201 Host name of mail server, e.g. "mail.example.com".
1202
1202
1203 Unrelated trailing paragraphs shouldn't be included
1203 Unrelated trailing paragraphs shouldn't be included
1204
1204
1205 $ hg help config.extramsg | grep '^$'
1205 $ hg help config.extramsg | grep '^$'
1206
1206
1207
1207
1208 Test capitalized section name
1208 Test capitalized section name
1209
1209
1210 $ hg help scripting.HGPLAIN > /dev/null
1210 $ hg help scripting.HGPLAIN > /dev/null
1211
1211
1212 Help subsection:
1212 Help subsection:
1213
1213
1214 $ hg help config.charsets |grep "Email example:" > /dev/null
1214 $ hg help config.charsets |grep "Email example:" > /dev/null
1215 [1]
1215 [1]
1216
1216
1217 Show nested definitions
1217 Show nested definitions
1218 ("profiling.type"[break]"ls"[break]"stat"[break])
1218 ("profiling.type"[break]"ls"[break]"stat"[break])
1219
1219
1220 $ hg help config.type | egrep '^$'|wc -l
1220 $ hg help config.type | egrep '^$'|wc -l
1221 \s*3 (re)
1221 \s*3 (re)
1222
1222
1223 Separate sections from subsections
1223 Separate sections from subsections
1224
1224
1225 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1225 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1226 "format"
1226 "format"
1227 --------
1227 --------
1228
1228
1229 "usegeneraldelta"
1229 "usegeneraldelta"
1230
1230
1231 "dotencode"
1231 "dotencode"
1232
1232
1233 "usefncache"
1233 "usefncache"
1234
1234
1235 "usestore"
1235 "usestore"
1236
1236
1237 "profiling"
1237 "profiling"
1238 -----------
1238 -----------
1239
1239
1240 "format"
1240 "format"
1241
1241
1242 "progress"
1242 "progress"
1243 ----------
1243 ----------
1244
1244
1245 "format"
1245 "format"
1246
1246
1247
1247
1248 Last item in help config.*:
1248 Last item in help config.*:
1249
1249
1250 $ hg help config.`hg help config|grep '^ "'| \
1250 $ hg help config.`hg help config|grep '^ "'| \
1251 > tail -1|sed 's![ "]*!!g'`| \
1251 > tail -1|sed 's![ "]*!!g'`| \
1252 > grep "hg help -c config" > /dev/null
1252 > grep "hg help -c config" > /dev/null
1253 [1]
1253 [1]
1254
1254
1255 note to use help -c for general hg help config:
1255 note to use help -c for general hg help config:
1256
1256
1257 $ hg help config |grep "hg help -c config" > /dev/null
1257 $ hg help config |grep "hg help -c config" > /dev/null
1258
1258
1259 Test templating help
1259 Test templating help
1260
1260
1261 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1261 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1262 desc String. The text of the changeset description.
1262 desc String. The text of the changeset description.
1263 diffstat String. Statistics of changes with the following format:
1263 diffstat String. Statistics of changes with the following format:
1264 firstline Any text. Returns the first line of text.
1264 firstline Any text. Returns the first line of text.
1265 nonempty Any text. Returns '(none)' if the string is empty.
1265 nonempty Any text. Returns '(none)' if the string is empty.
1266
1266
1267 Test deprecated items
1267 Test deprecated items
1268
1268
1269 $ hg help -v templating | grep currentbookmark
1269 $ hg help -v templating | grep currentbookmark
1270 currentbookmark
1270 currentbookmark
1271 $ hg help templating | (grep currentbookmark || true)
1271 $ hg help templating | (grep currentbookmark || true)
1272
1272
1273 Test help hooks
1273 Test help hooks
1274
1274
1275 $ cat > helphook1.py <<EOF
1275 $ cat > helphook1.py <<EOF
1276 > from mercurial import help
1276 > from mercurial import help
1277 >
1277 >
1278 > def rewrite(ui, topic, doc):
1278 > def rewrite(ui, topic, doc):
1279 > return doc + '\nhelphook1\n'
1279 > return doc + '\nhelphook1\n'
1280 >
1280 >
1281 > def extsetup(ui):
1281 > def extsetup(ui):
1282 > help.addtopichook('revsets', rewrite)
1282 > help.addtopichook('revsets', rewrite)
1283 > EOF
1283 > EOF
1284 $ cat > helphook2.py <<EOF
1284 $ cat > helphook2.py <<EOF
1285 > from mercurial import help
1285 > from mercurial import help
1286 >
1286 >
1287 > def rewrite(ui, topic, doc):
1287 > def rewrite(ui, topic, doc):
1288 > return doc + '\nhelphook2\n'
1288 > return doc + '\nhelphook2\n'
1289 >
1289 >
1290 > def extsetup(ui):
1290 > def extsetup(ui):
1291 > help.addtopichook('revsets', rewrite)
1291 > help.addtopichook('revsets', rewrite)
1292 > EOF
1292 > EOF
1293 $ echo '[extensions]' >> $HGRCPATH
1293 $ echo '[extensions]' >> $HGRCPATH
1294 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1294 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1295 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1295 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1296 $ hg help revsets | grep helphook
1296 $ hg help revsets | grep helphook
1297 helphook1
1297 helphook1
1298 helphook2
1298 helphook2
1299
1299
1300 help -c should only show debug --debug
1300 help -c should only show debug --debug
1301
1301
1302 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1302 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1303 [1]
1303 [1]
1304
1304
1305 help -c should only show deprecated for -v
1305 help -c should only show deprecated for -v
1306
1306
1307 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1307 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1308 [1]
1308 [1]
1309
1309
1310 Test -s / --system
1310 Test -s / --system
1311
1311
1312 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1312 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1313 > wc -l | sed -e 's/ //g'
1313 > wc -l | sed -e 's/ //g'
1314 0
1314 0
1315 $ hg help config.files --system unix | grep 'USER' | \
1315 $ hg help config.files --system unix | grep 'USER' | \
1316 > wc -l | sed -e 's/ //g'
1316 > wc -l | sed -e 's/ //g'
1317 0
1317 0
1318
1318
1319 Test -e / -c / -k combinations
1319 Test -e / -c / -k combinations
1320
1320
1321 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1321 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1322 Commands:
1322 Commands:
1323 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1323 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1324 Extensions:
1324 Extensions:
1325 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1325 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1326 Topics:
1326 Topics:
1327 Commands:
1327 Commands:
1328 Extensions:
1328 Extensions:
1329 Extension Commands:
1329 Extension Commands:
1330 $ hg help -c schemes
1330 $ hg help -c schemes
1331 abort: no such help topic: schemes
1331 abort: no such help topic: schemes
1332 (try "hg help --keyword schemes")
1332 (try "hg help --keyword schemes")
1333 [255]
1333 [255]
1334 $ hg help -e schemes |head -1
1334 $ hg help -e schemes |head -1
1335 schemes extension - extend schemes with shortcuts to repository swarms
1335 schemes extension - extend schemes with shortcuts to repository swarms
1336 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1336 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1337 Commands:
1337 Commands:
1338 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1338 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1339 Extensions:
1339 Extensions:
1340 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1340 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1341 Extensions:
1341 Extensions:
1342 Commands:
1342 Commands:
1343 $ hg help -c commit > /dev/null
1343 $ hg help -c commit > /dev/null
1344 $ hg help -e -c commit > /dev/null
1344 $ hg help -e -c commit > /dev/null
1345 $ hg help -e commit > /dev/null
1345 $ hg help -e commit > /dev/null
1346 abort: no such help topic: commit
1346 abort: no such help topic: commit
1347 (try "hg help --keyword commit")
1347 (try "hg help --keyword commit")
1348 [255]
1348 [255]
1349
1349
1350 Test keyword search help
1350 Test keyword search help
1351
1351
1352 $ cat > prefixedname.py <<EOF
1352 $ cat > prefixedname.py <<EOF
1353 > '''matched against word "clone"
1353 > '''matched against word "clone"
1354 > '''
1354 > '''
1355 > EOF
1355 > EOF
1356 $ echo '[extensions]' >> $HGRCPATH
1356 $ echo '[extensions]' >> $HGRCPATH
1357 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1357 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1358 $ hg help -k clone
1358 $ hg help -k clone
1359 Topics:
1359 Topics:
1360
1360
1361 config Configuration Files
1361 config Configuration Files
1362 extensions Using Additional Features
1362 extensions Using Additional Features
1363 glossary Glossary
1363 glossary Glossary
1364 phases Working with Phases
1364 phases Working with Phases
1365 subrepos Subrepositories
1365 subrepos Subrepositories
1366 urls URL Paths
1366 urls URL Paths
1367
1367
1368 Commands:
1368 Commands:
1369
1369
1370 bookmarks create a new bookmark or list existing bookmarks
1370 bookmarks create a new bookmark or list existing bookmarks
1371 clone make a copy of an existing repository
1371 clone make a copy of an existing repository
1372 paths show aliases for remote repositories
1372 paths show aliases for remote repositories
1373 update update working directory (or switch revisions)
1373 update update working directory (or switch revisions)
1374
1374
1375 Extensions:
1375 Extensions:
1376
1376
1377 clonebundles advertise pre-generated bundles to seed clones
1377 clonebundles advertise pre-generated bundles to seed clones
1378 prefixedname matched against word "clone"
1378 prefixedname matched against word "clone"
1379 relink recreates hardlinks between repository clones
1379 relink recreates hardlinks between repository clones
1380
1380
1381 Extension Commands:
1381 Extension Commands:
1382
1382
1383 qclone clone main and patch repository at same time
1383 qclone clone main and patch repository at same time
1384
1384
1385 Test unfound topic
1385 Test unfound topic
1386
1386
1387 $ hg help nonexistingtopicthatwillneverexisteverever
1387 $ hg help nonexistingtopicthatwillneverexisteverever
1388 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1388 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1389 (try "hg help --keyword nonexistingtopicthatwillneverexisteverever")
1389 (try "hg help --keyword nonexistingtopicthatwillneverexisteverever")
1390 [255]
1390 [255]
1391
1391
1392 Test unfound keyword
1392 Test unfound keyword
1393
1393
1394 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1394 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1395 abort: no matches
1395 abort: no matches
1396 (try "hg help" for a list of topics)
1396 (try "hg help" for a list of topics)
1397 [255]
1397 [255]
1398
1398
1399 Test omit indicating for help
1399 Test omit indicating for help
1400
1400
1401 $ cat > addverboseitems.py <<EOF
1401 $ cat > addverboseitems.py <<EOF
1402 > '''extension to test omit indicating.
1402 > '''extension to test omit indicating.
1403 >
1403 >
1404 > This paragraph is never omitted (for extension)
1404 > This paragraph is never omitted (for extension)
1405 >
1405 >
1406 > .. container:: verbose
1406 > .. container:: verbose
1407 >
1407 >
1408 > This paragraph is omitted,
1408 > This paragraph is omitted,
1409 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1409 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1410 >
1410 >
1411 > This paragraph is never omitted, too (for extension)
1411 > This paragraph is never omitted, too (for extension)
1412 > '''
1412 > '''
1413 >
1413 >
1414 > from mercurial import help, commands
1414 > from mercurial import help, commands
1415 > testtopic = """This paragraph is never omitted (for topic).
1415 > testtopic = """This paragraph is never omitted (for topic).
1416 >
1416 >
1417 > .. container:: verbose
1417 > .. container:: verbose
1418 >
1418 >
1419 > This paragraph is omitted,
1419 > This paragraph is omitted,
1420 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1420 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1421 >
1421 >
1422 > This paragraph is never omitted, too (for topic)
1422 > This paragraph is never omitted, too (for topic)
1423 > """
1423 > """
1424 > def extsetup(ui):
1424 > def extsetup(ui):
1425 > help.helptable.append((["topic-containing-verbose"],
1425 > help.helptable.append((["topic-containing-verbose"],
1426 > "This is the topic to test omit indicating.",
1426 > "This is the topic to test omit indicating.",
1427 > lambda ui: testtopic))
1427 > lambda ui: testtopic))
1428 > EOF
1428 > EOF
1429 $ echo '[extensions]' >> $HGRCPATH
1429 $ echo '[extensions]' >> $HGRCPATH
1430 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1430 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1431 $ hg help addverboseitems
1431 $ hg help addverboseitems
1432 addverboseitems extension - extension to test omit indicating.
1432 addverboseitems extension - extension to test omit indicating.
1433
1433
1434 This paragraph is never omitted (for extension)
1434 This paragraph is never omitted (for extension)
1435
1435
1436 This paragraph is never omitted, too (for extension)
1436 This paragraph is never omitted, too (for extension)
1437
1437
1438 (some details hidden, use --verbose to show complete help)
1438 (some details hidden, use --verbose to show complete help)
1439
1439
1440 no commands defined
1440 no commands defined
1441 $ hg help -v addverboseitems
1441 $ hg help -v addverboseitems
1442 addverboseitems extension - extension to test omit indicating.
1442 addverboseitems extension - extension to test omit indicating.
1443
1443
1444 This paragraph is never omitted (for extension)
1444 This paragraph is never omitted (for extension)
1445
1445
1446 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1446 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1447 extension)
1447 extension)
1448
1448
1449 This paragraph is never omitted, too (for extension)
1449 This paragraph is never omitted, too (for extension)
1450
1450
1451 no commands defined
1451 no commands defined
1452 $ hg help topic-containing-verbose
1452 $ hg help topic-containing-verbose
1453 This is the topic to test omit indicating.
1453 This is the topic to test omit indicating.
1454 """"""""""""""""""""""""""""""""""""""""""
1454 """"""""""""""""""""""""""""""""""""""""""
1455
1455
1456 This paragraph is never omitted (for topic).
1456 This paragraph is never omitted (for topic).
1457
1457
1458 This paragraph is never omitted, too (for topic)
1458 This paragraph is never omitted, too (for topic)
1459
1459
1460 (some details hidden, use --verbose to show complete help)
1460 (some details hidden, use --verbose to show complete help)
1461 $ hg help -v topic-containing-verbose
1461 $ hg help -v topic-containing-verbose
1462 This is the topic to test omit indicating.
1462 This is the topic to test omit indicating.
1463 """"""""""""""""""""""""""""""""""""""""""
1463 """"""""""""""""""""""""""""""""""""""""""
1464
1464
1465 This paragraph is never omitted (for topic).
1465 This paragraph is never omitted (for topic).
1466
1466
1467 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1467 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1468 topic)
1468 topic)
1469
1469
1470 This paragraph is never omitted, too (for topic)
1470 This paragraph is never omitted, too (for topic)
1471
1471
1472 Test section lookup
1472 Test section lookup
1473
1473
1474 $ hg help revset.merge
1474 $ hg help revset.merge
1475 "merge()"
1475 "merge()"
1476 Changeset is a merge changeset.
1476 Changeset is a merge changeset.
1477
1477
1478 $ hg help glossary.dag
1478 $ hg help glossary.dag
1479 DAG
1479 DAG
1480 The repository of changesets of a distributed version control system
1480 The repository of changesets of a distributed version control system
1481 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1481 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1482 of nodes and edges, where nodes correspond to changesets and edges
1482 of nodes and edges, where nodes correspond to changesets and edges
1483 imply a parent -> child relation. This graph can be visualized by
1483 imply a parent -> child relation. This graph can be visualized by
1484 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1484 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1485 limited by the requirement for children to have at most two parents.
1485 limited by the requirement for children to have at most two parents.
1486
1486
1487
1487
1488 $ hg help hgrc.paths
1488 $ hg help hgrc.paths
1489 "paths"
1489 "paths"
1490 -------
1490 -------
1491
1491
1492 Assigns symbolic names and behavior to repositories.
1492 Assigns symbolic names and behavior to repositories.
1493
1493
1494 Options are symbolic names defining the URL or directory that is the
1494 Options are symbolic names defining the URL or directory that is the
1495 location of the repository. Example:
1495 location of the repository. Example:
1496
1496
1497 [paths]
1497 [paths]
1498 my_server = https://example.com/my_repo
1498 my_server = https://example.com/my_repo
1499 local_path = /home/me/repo
1499 local_path = /home/me/repo
1500
1500
1501 These symbolic names can be used from the command line. To pull from
1501 These symbolic names can be used from the command line. To pull from
1502 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1502 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1503 local_path'.
1503 local_path'.
1504
1504
1505 Options containing colons (":") denote sub-options that can influence
1505 Options containing colons (":") denote sub-options that can influence
1506 behavior for that specific path. Example:
1506 behavior for that specific path. Example:
1507
1507
1508 [paths]
1508 [paths]
1509 my_server = https://example.com/my_path
1509 my_server = https://example.com/my_path
1510 my_server:pushurl = ssh://example.com/my_path
1510 my_server:pushurl = ssh://example.com/my_path
1511
1511
1512 The following sub-options can be defined:
1512 The following sub-options can be defined:
1513
1513
1514 "pushurl"
1514 "pushurl"
1515 The URL to use for push operations. If not defined, the location
1515 The URL to use for push operations. If not defined, the location
1516 defined by the path's main entry is used.
1516 defined by the path's main entry is used.
1517
1517
1518 "pushrev"
1518 "pushrev"
1519 A revset defining which revisions to push by default.
1519 A revset defining which revisions to push by default.
1520
1520
1521 When 'hg push' is executed without a "-r" argument, the revset defined
1521 When 'hg push' is executed without a "-r" argument, the revset defined
1522 by this sub-option is evaluated to determine what to push.
1522 by this sub-option is evaluated to determine what to push.
1523
1523
1524 For example, a value of "." will push the working directory's revision
1524 For example, a value of "." will push the working directory's revision
1525 by default.
1525 by default.
1526
1526
1527 Revsets specifying bookmarks will not result in the bookmark being
1527 Revsets specifying bookmarks will not result in the bookmark being
1528 pushed.
1528 pushed.
1529
1529
1530 The following special named paths exist:
1530 The following special named paths exist:
1531
1531
1532 "default"
1532 "default"
1533 The URL or directory to use when no source or remote is specified.
1533 The URL or directory to use when no source or remote is specified.
1534
1534
1535 'hg clone' will automatically define this path to the location the
1535 'hg clone' will automatically define this path to the location the
1536 repository was cloned from.
1536 repository was cloned from.
1537
1537
1538 "default-push"
1538 "default-push"
1539 (deprecated) The URL or directory for the default 'hg push' location.
1539 (deprecated) The URL or directory for the default 'hg push' location.
1540 "default:pushurl" should be used instead.
1540 "default:pushurl" should be used instead.
1541
1541
1542 $ hg help glossary.mcguffin
1542 $ hg help glossary.mcguffin
1543 abort: help section not found
1543 abort: help section not found
1544 [255]
1544 [255]
1545
1545
1546 $ hg help glossary.mc.guffin
1546 $ hg help glossary.mc.guffin
1547 abort: help section not found
1547 abort: help section not found
1548 [255]
1548 [255]
1549
1549
1550 $ hg help template.files
1550 $ hg help template.files
1551 files List of strings. All files modified, added, or removed by
1551 files List of strings. All files modified, added, or removed by
1552 this changeset.
1552 this changeset.
1553
1553
1554 Test section lookup by translated message
1554 Test section lookup by translated message
1555
1555
1556 str.lower() instead of encoding.lower(str) on translated message might
1556 str.lower() instead of encoding.lower(str) on translated message might
1557 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1557 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1558 as the second or later byte of multi-byte character.
1558 as the second or later byte of multi-byte character.
1559
1559
1560 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1560 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1561 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1561 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1562 replacement makes message meaningless.
1562 replacement makes message meaningless.
1563
1563
1564 This tests that section lookup by translated string isn't broken by
1564 This tests that section lookup by translated string isn't broken by
1565 such str.lower().
1565 such str.lower().
1566
1566
1567 $ python <<EOF
1567 $ python <<EOF
1568 > def escape(s):
1568 > def escape(s):
1569 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1569 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1570 > # translation of "record" in ja_JP.cp932
1570 > # translation of "record" in ja_JP.cp932
1571 > upper = "\x8bL\x98^"
1571 > upper = "\x8bL\x98^"
1572 > # str.lower()-ed section name should be treated as different one
1572 > # str.lower()-ed section name should be treated as different one
1573 > lower = "\x8bl\x98^"
1573 > lower = "\x8bl\x98^"
1574 > with open('ambiguous.py', 'w') as fp:
1574 > with open('ambiguous.py', 'w') as fp:
1575 > fp.write("""# ambiguous section names in ja_JP.cp932
1575 > fp.write("""# ambiguous section names in ja_JP.cp932
1576 > u'''summary of extension
1576 > u'''summary of extension
1577 >
1577 >
1578 > %s
1578 > %s
1579 > ----
1579 > ----
1580 >
1580 >
1581 > Upper name should show only this message
1581 > Upper name should show only this message
1582 >
1582 >
1583 > %s
1583 > %s
1584 > ----
1584 > ----
1585 >
1585 >
1586 > Lower name should show only this message
1586 > Lower name should show only this message
1587 >
1587 >
1588 > subsequent section
1588 > subsequent section
1589 > ------------------
1589 > ------------------
1590 >
1590 >
1591 > This should be hidden at "hg help ambiguous" with section name.
1591 > This should be hidden at "hg help ambiguous" with section name.
1592 > '''
1592 > '''
1593 > """ % (escape(upper), escape(lower)))
1593 > """ % (escape(upper), escape(lower)))
1594 > EOF
1594 > EOF
1595
1595
1596 $ cat >> $HGRCPATH <<EOF
1596 $ cat >> $HGRCPATH <<EOF
1597 > [extensions]
1597 > [extensions]
1598 > ambiguous = ./ambiguous.py
1598 > ambiguous = ./ambiguous.py
1599 > EOF
1599 > EOF
1600
1600
1601 $ python <<EOF | sh
1601 $ python <<EOF | sh
1602 > upper = "\x8bL\x98^"
1602 > upper = "\x8bL\x98^"
1603 > print "hg --encoding cp932 help -e ambiguous.%s" % upper
1603 > print "hg --encoding cp932 help -e ambiguous.%s" % upper
1604 > EOF
1604 > EOF
1605 \x8bL\x98^ (esc)
1605 \x8bL\x98^ (esc)
1606 ----
1606 ----
1607
1607
1608 Upper name should show only this message
1608 Upper name should show only this message
1609
1609
1610
1610
1611 $ python <<EOF | sh
1611 $ python <<EOF | sh
1612 > lower = "\x8bl\x98^"
1612 > lower = "\x8bl\x98^"
1613 > print "hg --encoding cp932 help -e ambiguous.%s" % lower
1613 > print "hg --encoding cp932 help -e ambiguous.%s" % lower
1614 > EOF
1614 > EOF
1615 \x8bl\x98^ (esc)
1615 \x8bl\x98^ (esc)
1616 ----
1616 ----
1617
1617
1618 Lower name should show only this message
1618 Lower name should show only this message
1619
1619
1620
1620
1621 $ cat >> $HGRCPATH <<EOF
1621 $ cat >> $HGRCPATH <<EOF
1622 > [extensions]
1622 > [extensions]
1623 > ambiguous = !
1623 > ambiguous = !
1624 > EOF
1624 > EOF
1625
1625
1626 Test dynamic list of merge tools only shows up once
1626 Test dynamic list of merge tools only shows up once
1627 $ hg help merge-tools
1627 $ hg help merge-tools
1628 Merge Tools
1628 Merge Tools
1629 """""""""""
1629 """""""""""
1630
1630
1631 To merge files Mercurial uses merge tools.
1631 To merge files Mercurial uses merge tools.
1632
1632
1633 A merge tool combines two different versions of a file into a merged file.
1633 A merge tool combines two different versions of a file into a merged file.
1634 Merge tools are given the two files and the greatest common ancestor of
1634 Merge tools are given the two files and the greatest common ancestor of
1635 the two file versions, so they can determine the changes made on both
1635 the two file versions, so they can determine the changes made on both
1636 branches.
1636 branches.
1637
1637
1638 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1638 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1639 backout' and in several extensions.
1639 backout' and in several extensions.
1640
1640
1641 Usually, the merge tool tries to automatically reconcile the files by
1641 Usually, the merge tool tries to automatically reconcile the files by
1642 combining all non-overlapping changes that occurred separately in the two
1642 combining all non-overlapping changes that occurred separately in the two
1643 different evolutions of the same initial base file. Furthermore, some
1643 different evolutions of the same initial base file. Furthermore, some
1644 interactive merge programs make it easier to manually resolve conflicting
1644 interactive merge programs make it easier to manually resolve conflicting
1645 merges, either in a graphical way, or by inserting some conflict markers.
1645 merges, either in a graphical way, or by inserting some conflict markers.
1646 Mercurial does not include any interactive merge programs but relies on
1646 Mercurial does not include any interactive merge programs but relies on
1647 external tools for that.
1647 external tools for that.
1648
1648
1649 Available merge tools
1649 Available merge tools
1650 =====================
1650 =====================
1651
1651
1652 External merge tools and their properties are configured in the merge-
1652 External merge tools and their properties are configured in the merge-
1653 tools configuration section - see hgrc(5) - but they can often just be
1653 tools configuration section - see hgrc(5) - but they can often just be
1654 named by their executable.
1654 named by their executable.
1655
1655
1656 A merge tool is generally usable if its executable can be found on the
1656 A merge tool is generally usable if its executable can be found on the
1657 system and if it can handle the merge. The executable is found if it is an
1657 system and if it can handle the merge. The executable is found if it is an
1658 absolute or relative executable path or the name of an application in the
1658 absolute or relative executable path or the name of an application in the
1659 executable search path. The tool is assumed to be able to handle the merge
1659 executable search path. The tool is assumed to be able to handle the merge
1660 if it can handle symlinks if the file is a symlink, if it can handle
1660 if it can handle symlinks if the file is a symlink, if it can handle
1661 binary files if the file is binary, and if a GUI is available if the tool
1661 binary files if the file is binary, and if a GUI is available if the tool
1662 requires a GUI.
1662 requires a GUI.
1663
1663
1664 There are some internal merge tools which can be used. The internal merge
1664 There are some internal merge tools which can be used. The internal merge
1665 tools are:
1665 tools are:
1666
1666
1667 ":dump"
1667 ":dump"
1668 Creates three versions of the files to merge, containing the contents of
1668 Creates three versions of the files to merge, containing the contents of
1669 local, other and base. These files can then be used to perform a merge
1669 local, other and base. These files can then be used to perform a merge
1670 manually. If the file to be merged is named "a.txt", these files will
1670 manually. If the file to be merged is named "a.txt", these files will
1671 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1671 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1672 they will be placed in the same directory as "a.txt".
1672 they will be placed in the same directory as "a.txt".
1673
1673
1674 ":fail"
1674 ":fail"
1675 Rather than attempting to merge files that were modified on both
1675 Rather than attempting to merge files that were modified on both
1676 branches, it marks them as unresolved. The resolve command must be used
1676 branches, it marks them as unresolved. The resolve command must be used
1677 to resolve these conflicts.
1677 to resolve these conflicts.
1678
1678
1679 ":local"
1679 ":local"
1680 Uses the local 'p1()' version of files as the merged version.
1680 Uses the local 'p1()' version of files as the merged version.
1681
1681
1682 ":merge"
1682 ":merge"
1683 Uses the internal non-interactive simple merge algorithm for merging
1683 Uses the internal non-interactive simple merge algorithm for merging
1684 files. It will fail if there are any conflicts and leave markers in the
1684 files. It will fail if there are any conflicts and leave markers in the
1685 partially merged file. Markers will have two sections, one for each side
1685 partially merged file. Markers will have two sections, one for each side
1686 of merge.
1686 of merge.
1687
1687
1688 ":merge-local"
1688 ":merge-local"
1689 Like :merge, but resolve all conflicts non-interactively in favor of the
1689 Like :merge, but resolve all conflicts non-interactively in favor of the
1690 local 'p1()' changes.
1690 local 'p1()' changes.
1691
1691
1692 ":merge-other"
1692 ":merge-other"
1693 Like :merge, but resolve all conflicts non-interactively in favor of the
1693 Like :merge, but resolve all conflicts non-interactively in favor of the
1694 other 'p2()' changes.
1694 other 'p2()' changes.
1695
1695
1696 ":merge3"
1696 ":merge3"
1697 Uses the internal non-interactive simple merge algorithm for merging
1697 Uses the internal non-interactive simple merge algorithm for merging
1698 files. It will fail if there are any conflicts and leave markers in the
1698 files. It will fail if there are any conflicts and leave markers in the
1699 partially merged file. Marker will have three sections, one from each
1699 partially merged file. Marker will have three sections, one from each
1700 side of the merge and one for the base content.
1700 side of the merge and one for the base content.
1701
1701
1702 ":other"
1702 ":other"
1703 Uses the other 'p2()' version of files as the merged version.
1703 Uses the other 'p2()' version of files as the merged version.
1704
1704
1705 ":prompt"
1705 ":prompt"
1706 Asks the user which of the local 'p1()' or the other 'p2()' version to
1706 Asks the user which of the local 'p1()' or the other 'p2()' version to
1707 keep as the merged version.
1707 keep as the merged version.
1708
1708
1709 ":tagmerge"
1709 ":tagmerge"
1710 Uses the internal tag merge algorithm (experimental).
1710 Uses the internal tag merge algorithm (experimental).
1711
1711
1712 ":union"
1712 ":union"
1713 Uses the internal non-interactive simple merge algorithm for merging
1713 Uses the internal non-interactive simple merge algorithm for merging
1714 files. It will use both left and right sides for conflict regions. No
1714 files. It will use both left and right sides for conflict regions. No
1715 markers are inserted.
1715 markers are inserted.
1716
1716
1717 Internal tools are always available and do not require a GUI but will by
1717 Internal tools are always available and do not require a GUI but will by
1718 default not handle symlinks or binary files.
1718 default not handle symlinks or binary files.
1719
1719
1720 Choosing a merge tool
1720 Choosing a merge tool
1721 =====================
1721 =====================
1722
1722
1723 Mercurial uses these rules when deciding which merge tool to use:
1723 Mercurial uses these rules when deciding which merge tool to use:
1724
1724
1725 1. If a tool has been specified with the --tool option to merge or
1725 1. If a tool has been specified with the --tool option to merge or
1726 resolve, it is used. If it is the name of a tool in the merge-tools
1726 resolve, it is used. If it is the name of a tool in the merge-tools
1727 configuration, its configuration is used. Otherwise the specified tool
1727 configuration, its configuration is used. Otherwise the specified tool
1728 must be executable by the shell.
1728 must be executable by the shell.
1729 2. If the "HGMERGE" environment variable is present, its value is used and
1729 2. If the "HGMERGE" environment variable is present, its value is used and
1730 must be executable by the shell.
1730 must be executable by the shell.
1731 3. If the filename of the file to be merged matches any of the patterns in
1731 3. If the filename of the file to be merged matches any of the patterns in
1732 the merge-patterns configuration section, the first usable merge tool
1732 the merge-patterns configuration section, the first usable merge tool
1733 corresponding to a matching pattern is used. Here, binary capabilities
1733 corresponding to a matching pattern is used. Here, binary capabilities
1734 of the merge tool are not considered.
1734 of the merge tool are not considered.
1735 4. If ui.merge is set it will be considered next. If the value is not the
1735 4. If ui.merge is set it will be considered next. If the value is not the
1736 name of a configured tool, the specified value is used and must be
1736 name of a configured tool, the specified value is used and must be
1737 executable by the shell. Otherwise the named tool is used if it is
1737 executable by the shell. Otherwise the named tool is used if it is
1738 usable.
1738 usable.
1739 5. If any usable merge tools are present in the merge-tools configuration
1739 5. If any usable merge tools are present in the merge-tools configuration
1740 section, the one with the highest priority is used.
1740 section, the one with the highest priority is used.
1741 6. If a program named "hgmerge" can be found on the system, it is used -
1741 6. If a program named "hgmerge" can be found on the system, it is used -
1742 but it will by default not be used for symlinks and binary files.
1742 but it will by default not be used for symlinks and binary files.
1743 7. If the file to be merged is not binary and is not a symlink, then
1743 7. If the file to be merged is not binary and is not a symlink, then
1744 internal ":merge" is used.
1744 internal ":merge" is used.
1745 8. The merge of the file fails and must be resolved before commit.
1745 8. The merge of the file fails and must be resolved before commit.
1746
1746
1747 Note:
1747 Note:
1748 After selecting a merge program, Mercurial will by default attempt to
1748 After selecting a merge program, Mercurial will by default attempt to
1749 merge the files using a simple merge algorithm first. Only if it
1749 merge the files using a simple merge algorithm first. Only if it
1750 doesn't succeed because of conflicting changes Mercurial will actually
1750 doesn't succeed because of conflicting changes Mercurial will actually
1751 execute the merge program. Whether to use the simple merge algorithm
1751 execute the merge program. Whether to use the simple merge algorithm
1752 first can be controlled by the premerge setting of the merge tool.
1752 first can be controlled by the premerge setting of the merge tool.
1753 Premerge is enabled by default unless the file is binary or a symlink.
1753 Premerge is enabled by default unless the file is binary or a symlink.
1754
1754
1755 See the merge-tools and ui sections of hgrc(5) for details on the
1755 See the merge-tools and ui sections of hgrc(5) for details on the
1756 configuration of merge tools.
1756 configuration of merge tools.
1757
1757
1758 Test usage of section marks in help documents
1758 Test usage of section marks in help documents
1759
1759
1760 $ cd "$TESTDIR"/../doc
1760 $ cd "$TESTDIR"/../doc
1761 $ python check-seclevel.py
1761 $ python check-seclevel.py
1762 $ cd $TESTTMP
1762 $ cd $TESTTMP
1763
1763
1764 #if serve
1764 #if serve
1765
1765
1766 Test the help pages in hgweb.
1766 Test the help pages in hgweb.
1767
1767
1768 Dish up an empty repo; serve it cold.
1768 Dish up an empty repo; serve it cold.
1769
1769
1770 $ hg init "$TESTTMP/test"
1770 $ hg init "$TESTTMP/test"
1771 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1771 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1772 $ cat hg.pid >> $DAEMON_PIDS
1772 $ cat hg.pid >> $DAEMON_PIDS
1773
1773
1774 $ get-with-headers.py 127.0.0.1:$HGPORT "help"
1774 $ get-with-headers.py 127.0.0.1:$HGPORT "help"
1775 200 Script output follows
1775 200 Script output follows
1776
1776
1777 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1777 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1778 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1778 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1779 <head>
1779 <head>
1780 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1780 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1781 <meta name="robots" content="index, nofollow" />
1781 <meta name="robots" content="index, nofollow" />
1782 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1782 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1783 <script type="text/javascript" src="/static/mercurial.js"></script>
1783 <script type="text/javascript" src="/static/mercurial.js"></script>
1784
1784
1785 <title>Help: Index</title>
1785 <title>Help: Index</title>
1786 </head>
1786 </head>
1787 <body>
1787 <body>
1788
1788
1789 <div class="container">
1789 <div class="container">
1790 <div class="menu">
1790 <div class="menu">
1791 <div class="logo">
1791 <div class="logo">
1792 <a href="https://mercurial-scm.org/">
1792 <a href="https://mercurial-scm.org/">
1793 <img src="/static/hglogo.png" alt="mercurial" /></a>
1793 <img src="/static/hglogo.png" alt="mercurial" /></a>
1794 </div>
1794 </div>
1795 <ul>
1795 <ul>
1796 <li><a href="/shortlog">log</a></li>
1796 <li><a href="/shortlog">log</a></li>
1797 <li><a href="/graph">graph</a></li>
1797 <li><a href="/graph">graph</a></li>
1798 <li><a href="/tags">tags</a></li>
1798 <li><a href="/tags">tags</a></li>
1799 <li><a href="/bookmarks">bookmarks</a></li>
1799 <li><a href="/bookmarks">bookmarks</a></li>
1800 <li><a href="/branches">branches</a></li>
1800 <li><a href="/branches">branches</a></li>
1801 </ul>
1801 </ul>
1802 <ul>
1802 <ul>
1803 <li class="active">help</li>
1803 <li class="active">help</li>
1804 </ul>
1804 </ul>
1805 </div>
1805 </div>
1806
1806
1807 <div class="main">
1807 <div class="main">
1808 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1808 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1809 <form class="search" action="/log">
1809 <form class="search" action="/log">
1810
1810
1811 <p><input name="rev" id="search1" type="text" size="30" /></p>
1811 <p><input name="rev" id="search1" type="text" size="30" /></p>
1812 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1812 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1813 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1813 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1814 </form>
1814 </form>
1815 <table class="bigtable">
1815 <table class="bigtable">
1816 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
1816 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
1817
1817
1818 <tr><td>
1818 <tr><td>
1819 <a href="/help/config">
1819 <a href="/help/config">
1820 config
1820 config
1821 </a>
1821 </a>
1822 </td><td>
1822 </td><td>
1823 Configuration Files
1823 Configuration Files
1824 </td></tr>
1824 </td></tr>
1825 <tr><td>
1825 <tr><td>
1826 <a href="/help/dates">
1826 <a href="/help/dates">
1827 dates
1827 dates
1828 </a>
1828 </a>
1829 </td><td>
1829 </td><td>
1830 Date Formats
1830 Date Formats
1831 </td></tr>
1831 </td></tr>
1832 <tr><td>
1832 <tr><td>
1833 <a href="/help/diffs">
1833 <a href="/help/diffs">
1834 diffs
1834 diffs
1835 </a>
1835 </a>
1836 </td><td>
1836 </td><td>
1837 Diff Formats
1837 Diff Formats
1838 </td></tr>
1838 </td></tr>
1839 <tr><td>
1839 <tr><td>
1840 <a href="/help/environment">
1840 <a href="/help/environment">
1841 environment
1841 environment
1842 </a>
1842 </a>
1843 </td><td>
1843 </td><td>
1844 Environment Variables
1844 Environment Variables
1845 </td></tr>
1845 </td></tr>
1846 <tr><td>
1846 <tr><td>
1847 <a href="/help/extensions">
1847 <a href="/help/extensions">
1848 extensions
1848 extensions
1849 </a>
1849 </a>
1850 </td><td>
1850 </td><td>
1851 Using Additional Features
1851 Using Additional Features
1852 </td></tr>
1852 </td></tr>
1853 <tr><td>
1853 <tr><td>
1854 <a href="/help/filesets">
1854 <a href="/help/filesets">
1855 filesets
1855 filesets
1856 </a>
1856 </a>
1857 </td><td>
1857 </td><td>
1858 Specifying File Sets
1858 Specifying File Sets
1859 </td></tr>
1859 </td></tr>
1860 <tr><td>
1860 <tr><td>
1861 <a href="/help/glossary">
1861 <a href="/help/glossary">
1862 glossary
1862 glossary
1863 </a>
1863 </a>
1864 </td><td>
1864 </td><td>
1865 Glossary
1865 Glossary
1866 </td></tr>
1866 </td></tr>
1867 <tr><td>
1867 <tr><td>
1868 <a href="/help/hgignore">
1868 <a href="/help/hgignore">
1869 hgignore
1869 hgignore
1870 </a>
1870 </a>
1871 </td><td>
1871 </td><td>
1872 Syntax for Mercurial Ignore Files
1872 Syntax for Mercurial Ignore Files
1873 </td></tr>
1873 </td></tr>
1874 <tr><td>
1874 <tr><td>
1875 <a href="/help/hgweb">
1875 <a href="/help/hgweb">
1876 hgweb
1876 hgweb
1877 </a>
1877 </a>
1878 </td><td>
1878 </td><td>
1879 Configuring hgweb
1879 Configuring hgweb
1880 </td></tr>
1880 </td></tr>
1881 <tr><td>
1881 <tr><td>
1882 <a href="/help/internals">
1882 <a href="/help/internals">
1883 internals
1883 internals
1884 </a>
1884 </a>
1885 </td><td>
1885 </td><td>
1886 Technical implementation topics
1886 Technical implementation topics
1887 </td></tr>
1887 </td></tr>
1888 <tr><td>
1888 <tr><td>
1889 <a href="/help/merge-tools">
1889 <a href="/help/merge-tools">
1890 merge-tools
1890 merge-tools
1891 </a>
1891 </a>
1892 </td><td>
1892 </td><td>
1893 Merge Tools
1893 Merge Tools
1894 </td></tr>
1894 </td></tr>
1895 <tr><td>
1895 <tr><td>
1896 <a href="/help/multirevs">
1896 <a href="/help/multirevs">
1897 multirevs
1897 multirevs
1898 </a>
1898 </a>
1899 </td><td>
1899 </td><td>
1900 Specifying Multiple Revisions
1900 Specifying Multiple Revisions
1901 </td></tr>
1901 </td></tr>
1902 <tr><td>
1902 <tr><td>
1903 <a href="/help/patterns">
1903 <a href="/help/patterns">
1904 patterns
1904 patterns
1905 </a>
1905 </a>
1906 </td><td>
1906 </td><td>
1907 File Name Patterns
1907 File Name Patterns
1908 </td></tr>
1908 </td></tr>
1909 <tr><td>
1909 <tr><td>
1910 <a href="/help/phases">
1910 <a href="/help/phases">
1911 phases
1911 phases
1912 </a>
1912 </a>
1913 </td><td>
1913 </td><td>
1914 Working with Phases
1914 Working with Phases
1915 </td></tr>
1915 </td></tr>
1916 <tr><td>
1916 <tr><td>
1917 <a href="/help/revisions">
1917 <a href="/help/revisions">
1918 revisions
1918 revisions
1919 </a>
1919 </a>
1920 </td><td>
1920 </td><td>
1921 Specifying Single Revisions
1921 Specifying Single Revisions
1922 </td></tr>
1922 </td></tr>
1923 <tr><td>
1923 <tr><td>
1924 <a href="/help/revsets">
1924 <a href="/help/revsets">
1925 revsets
1925 revsets
1926 </a>
1926 </a>
1927 </td><td>
1927 </td><td>
1928 Specifying Revision Sets
1928 Specifying Revision Sets
1929 </td></tr>
1929 </td></tr>
1930 <tr><td>
1930 <tr><td>
1931 <a href="/help/scripting">
1931 <a href="/help/scripting">
1932 scripting
1932 scripting
1933 </a>
1933 </a>
1934 </td><td>
1934 </td><td>
1935 Using Mercurial from scripts and automation
1935 Using Mercurial from scripts and automation
1936 </td></tr>
1936 </td></tr>
1937 <tr><td>
1937 <tr><td>
1938 <a href="/help/subrepos">
1938 <a href="/help/subrepos">
1939 subrepos
1939 subrepos
1940 </a>
1940 </a>
1941 </td><td>
1941 </td><td>
1942 Subrepositories
1942 Subrepositories
1943 </td></tr>
1943 </td></tr>
1944 <tr><td>
1944 <tr><td>
1945 <a href="/help/templating">
1945 <a href="/help/templating">
1946 templating
1946 templating
1947 </a>
1947 </a>
1948 </td><td>
1948 </td><td>
1949 Template Usage
1949 Template Usage
1950 </td></tr>
1950 </td></tr>
1951 <tr><td>
1951 <tr><td>
1952 <a href="/help/urls">
1952 <a href="/help/urls">
1953 urls
1953 urls
1954 </a>
1954 </a>
1955 </td><td>
1955 </td><td>
1956 URL Paths
1956 URL Paths
1957 </td></tr>
1957 </td></tr>
1958 <tr><td>
1958 <tr><td>
1959 <a href="/help/topic-containing-verbose">
1959 <a href="/help/topic-containing-verbose">
1960 topic-containing-verbose
1960 topic-containing-verbose
1961 </a>
1961 </a>
1962 </td><td>
1962 </td><td>
1963 This is the topic to test omit indicating.
1963 This is the topic to test omit indicating.
1964 </td></tr>
1964 </td></tr>
1965
1965
1966
1966
1967 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1967 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1968
1968
1969 <tr><td>
1969 <tr><td>
1970 <a href="/help/add">
1970 <a href="/help/add">
1971 add
1971 add
1972 </a>
1972 </a>
1973 </td><td>
1973 </td><td>
1974 add the specified files on the next commit
1974 add the specified files on the next commit
1975 </td></tr>
1975 </td></tr>
1976 <tr><td>
1976 <tr><td>
1977 <a href="/help/annotate">
1977 <a href="/help/annotate">
1978 annotate
1978 annotate
1979 </a>
1979 </a>
1980 </td><td>
1980 </td><td>
1981 show changeset information by line for each file
1981 show changeset information by line for each file
1982 </td></tr>
1982 </td></tr>
1983 <tr><td>
1983 <tr><td>
1984 <a href="/help/clone">
1984 <a href="/help/clone">
1985 clone
1985 clone
1986 </a>
1986 </a>
1987 </td><td>
1987 </td><td>
1988 make a copy of an existing repository
1988 make a copy of an existing repository
1989 </td></tr>
1989 </td></tr>
1990 <tr><td>
1990 <tr><td>
1991 <a href="/help/commit">
1991 <a href="/help/commit">
1992 commit
1992 commit
1993 </a>
1993 </a>
1994 </td><td>
1994 </td><td>
1995 commit the specified files or all outstanding changes
1995 commit the specified files or all outstanding changes
1996 </td></tr>
1996 </td></tr>
1997 <tr><td>
1997 <tr><td>
1998 <a href="/help/diff">
1998 <a href="/help/diff">
1999 diff
1999 diff
2000 </a>
2000 </a>
2001 </td><td>
2001 </td><td>
2002 diff repository (or selected files)
2002 diff repository (or selected files)
2003 </td></tr>
2003 </td></tr>
2004 <tr><td>
2004 <tr><td>
2005 <a href="/help/export">
2005 <a href="/help/export">
2006 export
2006 export
2007 </a>
2007 </a>
2008 </td><td>
2008 </td><td>
2009 dump the header and diffs for one or more changesets
2009 dump the header and diffs for one or more changesets
2010 </td></tr>
2010 </td></tr>
2011 <tr><td>
2011 <tr><td>
2012 <a href="/help/forget">
2012 <a href="/help/forget">
2013 forget
2013 forget
2014 </a>
2014 </a>
2015 </td><td>
2015 </td><td>
2016 forget the specified files on the next commit
2016 forget the specified files on the next commit
2017 </td></tr>
2017 </td></tr>
2018 <tr><td>
2018 <tr><td>
2019 <a href="/help/init">
2019 <a href="/help/init">
2020 init
2020 init
2021 </a>
2021 </a>
2022 </td><td>
2022 </td><td>
2023 create a new repository in the given directory
2023 create a new repository in the given directory
2024 </td></tr>
2024 </td></tr>
2025 <tr><td>
2025 <tr><td>
2026 <a href="/help/log">
2026 <a href="/help/log">
2027 log
2027 log
2028 </a>
2028 </a>
2029 </td><td>
2029 </td><td>
2030 show revision history of entire repository or files
2030 show revision history of entire repository or files
2031 </td></tr>
2031 </td></tr>
2032 <tr><td>
2032 <tr><td>
2033 <a href="/help/merge">
2033 <a href="/help/merge">
2034 merge
2034 merge
2035 </a>
2035 </a>
2036 </td><td>
2036 </td><td>
2037 merge another revision into working directory
2037 merge another revision into working directory
2038 </td></tr>
2038 </td></tr>
2039 <tr><td>
2039 <tr><td>
2040 <a href="/help/pull">
2040 <a href="/help/pull">
2041 pull
2041 pull
2042 </a>
2042 </a>
2043 </td><td>
2043 </td><td>
2044 pull changes from the specified source
2044 pull changes from the specified source
2045 </td></tr>
2045 </td></tr>
2046 <tr><td>
2046 <tr><td>
2047 <a href="/help/push">
2047 <a href="/help/push">
2048 push
2048 push
2049 </a>
2049 </a>
2050 </td><td>
2050 </td><td>
2051 push changes to the specified destination
2051 push changes to the specified destination
2052 </td></tr>
2052 </td></tr>
2053 <tr><td>
2053 <tr><td>
2054 <a href="/help/remove">
2054 <a href="/help/remove">
2055 remove
2055 remove
2056 </a>
2056 </a>
2057 </td><td>
2057 </td><td>
2058 remove the specified files on the next commit
2058 remove the specified files on the next commit
2059 </td></tr>
2059 </td></tr>
2060 <tr><td>
2060 <tr><td>
2061 <a href="/help/serve">
2061 <a href="/help/serve">
2062 serve
2062 serve
2063 </a>
2063 </a>
2064 </td><td>
2064 </td><td>
2065 start stand-alone webserver
2065 start stand-alone webserver
2066 </td></tr>
2066 </td></tr>
2067 <tr><td>
2067 <tr><td>
2068 <a href="/help/status">
2068 <a href="/help/status">
2069 status
2069 status
2070 </a>
2070 </a>
2071 </td><td>
2071 </td><td>
2072 show changed files in the working directory
2072 show changed files in the working directory
2073 </td></tr>
2073 </td></tr>
2074 <tr><td>
2074 <tr><td>
2075 <a href="/help/summary">
2075 <a href="/help/summary">
2076 summary
2076 summary
2077 </a>
2077 </a>
2078 </td><td>
2078 </td><td>
2079 summarize working directory state
2079 summarize working directory state
2080 </td></tr>
2080 </td></tr>
2081 <tr><td>
2081 <tr><td>
2082 <a href="/help/update">
2082 <a href="/help/update">
2083 update
2083 update
2084 </a>
2084 </a>
2085 </td><td>
2085 </td><td>
2086 update working directory (or switch revisions)
2086 update working directory (or switch revisions)
2087 </td></tr>
2087 </td></tr>
2088
2088
2089
2089
2090
2090
2091 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2091 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2092
2092
2093 <tr><td>
2093 <tr><td>
2094 <a href="/help/addremove">
2094 <a href="/help/addremove">
2095 addremove
2095 addremove
2096 </a>
2096 </a>
2097 </td><td>
2097 </td><td>
2098 add all new files, delete all missing files
2098 add all new files, delete all missing files
2099 </td></tr>
2099 </td></tr>
2100 <tr><td>
2100 <tr><td>
2101 <a href="/help/archive">
2101 <a href="/help/archive">
2102 archive
2102 archive
2103 </a>
2103 </a>
2104 </td><td>
2104 </td><td>
2105 create an unversioned archive of a repository revision
2105 create an unversioned archive of a repository revision
2106 </td></tr>
2106 </td></tr>
2107 <tr><td>
2107 <tr><td>
2108 <a href="/help/backout">
2108 <a href="/help/backout">
2109 backout
2109 backout
2110 </a>
2110 </a>
2111 </td><td>
2111 </td><td>
2112 reverse effect of earlier changeset
2112 reverse effect of earlier changeset
2113 </td></tr>
2113 </td></tr>
2114 <tr><td>
2114 <tr><td>
2115 <a href="/help/bisect">
2115 <a href="/help/bisect">
2116 bisect
2116 bisect
2117 </a>
2117 </a>
2118 </td><td>
2118 </td><td>
2119 subdivision search of changesets
2119 subdivision search of changesets
2120 </td></tr>
2120 </td></tr>
2121 <tr><td>
2121 <tr><td>
2122 <a href="/help/bookmarks">
2122 <a href="/help/bookmarks">
2123 bookmarks
2123 bookmarks
2124 </a>
2124 </a>
2125 </td><td>
2125 </td><td>
2126 create a new bookmark or list existing bookmarks
2126 create a new bookmark or list existing bookmarks
2127 </td></tr>
2127 </td></tr>
2128 <tr><td>
2128 <tr><td>
2129 <a href="/help/branch">
2129 <a href="/help/branch">
2130 branch
2130 branch
2131 </a>
2131 </a>
2132 </td><td>
2132 </td><td>
2133 set or show the current branch name
2133 set or show the current branch name
2134 </td></tr>
2134 </td></tr>
2135 <tr><td>
2135 <tr><td>
2136 <a href="/help/branches">
2136 <a href="/help/branches">
2137 branches
2137 branches
2138 </a>
2138 </a>
2139 </td><td>
2139 </td><td>
2140 list repository named branches
2140 list repository named branches
2141 </td></tr>
2141 </td></tr>
2142 <tr><td>
2142 <tr><td>
2143 <a href="/help/bundle">
2143 <a href="/help/bundle">
2144 bundle
2144 bundle
2145 </a>
2145 </a>
2146 </td><td>
2146 </td><td>
2147 create a changegroup file
2147 create a changegroup file
2148 </td></tr>
2148 </td></tr>
2149 <tr><td>
2149 <tr><td>
2150 <a href="/help/cat">
2150 <a href="/help/cat">
2151 cat
2151 cat
2152 </a>
2152 </a>
2153 </td><td>
2153 </td><td>
2154 output the current or given revision of files
2154 output the current or given revision of files
2155 </td></tr>
2155 </td></tr>
2156 <tr><td>
2156 <tr><td>
2157 <a href="/help/config">
2157 <a href="/help/config">
2158 config
2158 config
2159 </a>
2159 </a>
2160 </td><td>
2160 </td><td>
2161 show combined config settings from all hgrc files
2161 show combined config settings from all hgrc files
2162 </td></tr>
2162 </td></tr>
2163 <tr><td>
2163 <tr><td>
2164 <a href="/help/copy">
2164 <a href="/help/copy">
2165 copy
2165 copy
2166 </a>
2166 </a>
2167 </td><td>
2167 </td><td>
2168 mark files as copied for the next commit
2168 mark files as copied for the next commit
2169 </td></tr>
2169 </td></tr>
2170 <tr><td>
2170 <tr><td>
2171 <a href="/help/files">
2171 <a href="/help/files">
2172 files
2172 files
2173 </a>
2173 </a>
2174 </td><td>
2174 </td><td>
2175 list tracked files
2175 list tracked files
2176 </td></tr>
2176 </td></tr>
2177 <tr><td>
2177 <tr><td>
2178 <a href="/help/graft">
2178 <a href="/help/graft">
2179 graft
2179 graft
2180 </a>
2180 </a>
2181 </td><td>
2181 </td><td>
2182 copy changes from other branches onto the current branch
2182 copy changes from other branches onto the current branch
2183 </td></tr>
2183 </td></tr>
2184 <tr><td>
2184 <tr><td>
2185 <a href="/help/grep">
2185 <a href="/help/grep">
2186 grep
2186 grep
2187 </a>
2187 </a>
2188 </td><td>
2188 </td><td>
2189 search for a pattern in specified files and revisions
2189 search for a pattern in specified files and revisions
2190 </td></tr>
2190 </td></tr>
2191 <tr><td>
2191 <tr><td>
2192 <a href="/help/heads">
2192 <a href="/help/heads">
2193 heads
2193 heads
2194 </a>
2194 </a>
2195 </td><td>
2195 </td><td>
2196 show branch heads
2196 show branch heads
2197 </td></tr>
2197 </td></tr>
2198 <tr><td>
2198 <tr><td>
2199 <a href="/help/help">
2199 <a href="/help/help">
2200 help
2200 help
2201 </a>
2201 </a>
2202 </td><td>
2202 </td><td>
2203 show help for a given topic or a help overview
2203 show help for a given topic or a help overview
2204 </td></tr>
2204 </td></tr>
2205 <tr><td>
2205 <tr><td>
2206 <a href="/help/hgalias">
2206 <a href="/help/hgalias">
2207 hgalias
2207 hgalias
2208 </a>
2208 </a>
2209 </td><td>
2209 </td><td>
2210 summarize working directory state
2210 summarize working directory state
2211 </td></tr>
2211 </td></tr>
2212 <tr><td>
2212 <tr><td>
2213 <a href="/help/identify">
2213 <a href="/help/identify">
2214 identify
2214 identify
2215 </a>
2215 </a>
2216 </td><td>
2216 </td><td>
2217 identify the working directory or specified revision
2217 identify the working directory or specified revision
2218 </td></tr>
2218 </td></tr>
2219 <tr><td>
2219 <tr><td>
2220 <a href="/help/import">
2220 <a href="/help/import">
2221 import
2221 import
2222 </a>
2222 </a>
2223 </td><td>
2223 </td><td>
2224 import an ordered set of patches
2224 import an ordered set of patches
2225 </td></tr>
2225 </td></tr>
2226 <tr><td>
2226 <tr><td>
2227 <a href="/help/incoming">
2227 <a href="/help/incoming">
2228 incoming
2228 incoming
2229 </a>
2229 </a>
2230 </td><td>
2230 </td><td>
2231 show new changesets found in source
2231 show new changesets found in source
2232 </td></tr>
2232 </td></tr>
2233 <tr><td>
2233 <tr><td>
2234 <a href="/help/manifest">
2234 <a href="/help/manifest">
2235 manifest
2235 manifest
2236 </a>
2236 </a>
2237 </td><td>
2237 </td><td>
2238 output the current or given revision of the project manifest
2238 output the current or given revision of the project manifest
2239 </td></tr>
2239 </td></tr>
2240 <tr><td>
2240 <tr><td>
2241 <a href="/help/nohelp">
2241 <a href="/help/nohelp">
2242 nohelp
2242 nohelp
2243 </a>
2243 </a>
2244 </td><td>
2244 </td><td>
2245 (no help text available)
2245 (no help text available)
2246 </td></tr>
2246 </td></tr>
2247 <tr><td>
2247 <tr><td>
2248 <a href="/help/outgoing">
2248 <a href="/help/outgoing">
2249 outgoing
2249 outgoing
2250 </a>
2250 </a>
2251 </td><td>
2251 </td><td>
2252 show changesets not found in the destination
2252 show changesets not found in the destination
2253 </td></tr>
2253 </td></tr>
2254 <tr><td>
2254 <tr><td>
2255 <a href="/help/paths">
2255 <a href="/help/paths">
2256 paths
2256 paths
2257 </a>
2257 </a>
2258 </td><td>
2258 </td><td>
2259 show aliases for remote repositories
2259 show aliases for remote repositories
2260 </td></tr>
2260 </td></tr>
2261 <tr><td>
2261 <tr><td>
2262 <a href="/help/phase">
2262 <a href="/help/phase">
2263 phase
2263 phase
2264 </a>
2264 </a>
2265 </td><td>
2265 </td><td>
2266 set or show the current phase name
2266 set or show the current phase name
2267 </td></tr>
2267 </td></tr>
2268 <tr><td>
2268 <tr><td>
2269 <a href="/help/recover">
2269 <a href="/help/recover">
2270 recover
2270 recover
2271 </a>
2271 </a>
2272 </td><td>
2272 </td><td>
2273 roll back an interrupted transaction
2273 roll back an interrupted transaction
2274 </td></tr>
2274 </td></tr>
2275 <tr><td>
2275 <tr><td>
2276 <a href="/help/rename">
2276 <a href="/help/rename">
2277 rename
2277 rename
2278 </a>
2278 </a>
2279 </td><td>
2279 </td><td>
2280 rename files; equivalent of copy + remove
2280 rename files; equivalent of copy + remove
2281 </td></tr>
2281 </td></tr>
2282 <tr><td>
2282 <tr><td>
2283 <a href="/help/resolve">
2283 <a href="/help/resolve">
2284 resolve
2284 resolve
2285 </a>
2285 </a>
2286 </td><td>
2286 </td><td>
2287 redo merges or set/view the merge status of files
2287 redo merges or set/view the merge status of files
2288 </td></tr>
2288 </td></tr>
2289 <tr><td>
2289 <tr><td>
2290 <a href="/help/revert">
2290 <a href="/help/revert">
2291 revert
2291 revert
2292 </a>
2292 </a>
2293 </td><td>
2293 </td><td>
2294 restore files to their checkout state
2294 restore files to their checkout state
2295 </td></tr>
2295 </td></tr>
2296 <tr><td>
2296 <tr><td>
2297 <a href="/help/root">
2297 <a href="/help/root">
2298 root
2298 root
2299 </a>
2299 </a>
2300 </td><td>
2300 </td><td>
2301 print the root (top) of the current working directory
2301 print the root (top) of the current working directory
2302 </td></tr>
2302 </td></tr>
2303 <tr><td>
2303 <tr><td>
2304 <a href="/help/shellalias">
2304 <a href="/help/shellalias">
2305 shellalias
2305 shellalias
2306 </a>
2306 </a>
2307 </td><td>
2307 </td><td>
2308 (no help text available)
2308 (no help text available)
2309 </td></tr>
2309 </td></tr>
2310 <tr><td>
2310 <tr><td>
2311 <a href="/help/tag">
2311 <a href="/help/tag">
2312 tag
2312 tag
2313 </a>
2313 </a>
2314 </td><td>
2314 </td><td>
2315 add one or more tags for the current or given revision
2315 add one or more tags for the current or given revision
2316 </td></tr>
2316 </td></tr>
2317 <tr><td>
2317 <tr><td>
2318 <a href="/help/tags">
2318 <a href="/help/tags">
2319 tags
2319 tags
2320 </a>
2320 </a>
2321 </td><td>
2321 </td><td>
2322 list repository tags
2322 list repository tags
2323 </td></tr>
2323 </td></tr>
2324 <tr><td>
2324 <tr><td>
2325 <a href="/help/unbundle">
2325 <a href="/help/unbundle">
2326 unbundle
2326 unbundle
2327 </a>
2327 </a>
2328 </td><td>
2328 </td><td>
2329 apply one or more changegroup files
2329 apply one or more changegroup files
2330 </td></tr>
2330 </td></tr>
2331 <tr><td>
2331 <tr><td>
2332 <a href="/help/verify">
2332 <a href="/help/verify">
2333 verify
2333 verify
2334 </a>
2334 </a>
2335 </td><td>
2335 </td><td>
2336 verify the integrity of the repository
2336 verify the integrity of the repository
2337 </td></tr>
2337 </td></tr>
2338 <tr><td>
2338 <tr><td>
2339 <a href="/help/version">
2339 <a href="/help/version">
2340 version
2340 version
2341 </a>
2341 </a>
2342 </td><td>
2342 </td><td>
2343 output version and copyright information
2343 output version and copyright information
2344 </td></tr>
2344 </td></tr>
2345
2345
2346
2346
2347 </table>
2347 </table>
2348 </div>
2348 </div>
2349 </div>
2349 </div>
2350
2350
2351 <script type="text/javascript">process_dates()</script>
2351 <script type="text/javascript">process_dates()</script>
2352
2352
2353
2353
2354 </body>
2354 </body>
2355 </html>
2355 </html>
2356
2356
2357
2357
2358 $ get-with-headers.py 127.0.0.1:$HGPORT "help/add"
2358 $ get-with-headers.py 127.0.0.1:$HGPORT "help/add"
2359 200 Script output follows
2359 200 Script output follows
2360
2360
2361 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2361 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2362 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2362 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2363 <head>
2363 <head>
2364 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2364 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2365 <meta name="robots" content="index, nofollow" />
2365 <meta name="robots" content="index, nofollow" />
2366 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2366 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2367 <script type="text/javascript" src="/static/mercurial.js"></script>
2367 <script type="text/javascript" src="/static/mercurial.js"></script>
2368
2368
2369 <title>Help: add</title>
2369 <title>Help: add</title>
2370 </head>
2370 </head>
2371 <body>
2371 <body>
2372
2372
2373 <div class="container">
2373 <div class="container">
2374 <div class="menu">
2374 <div class="menu">
2375 <div class="logo">
2375 <div class="logo">
2376 <a href="https://mercurial-scm.org/">
2376 <a href="https://mercurial-scm.org/">
2377 <img src="/static/hglogo.png" alt="mercurial" /></a>
2377 <img src="/static/hglogo.png" alt="mercurial" /></a>
2378 </div>
2378 </div>
2379 <ul>
2379 <ul>
2380 <li><a href="/shortlog">log</a></li>
2380 <li><a href="/shortlog">log</a></li>
2381 <li><a href="/graph">graph</a></li>
2381 <li><a href="/graph">graph</a></li>
2382 <li><a href="/tags">tags</a></li>
2382 <li><a href="/tags">tags</a></li>
2383 <li><a href="/bookmarks">bookmarks</a></li>
2383 <li><a href="/bookmarks">bookmarks</a></li>
2384 <li><a href="/branches">branches</a></li>
2384 <li><a href="/branches">branches</a></li>
2385 </ul>
2385 </ul>
2386 <ul>
2386 <ul>
2387 <li class="active"><a href="/help">help</a></li>
2387 <li class="active"><a href="/help">help</a></li>
2388 </ul>
2388 </ul>
2389 </div>
2389 </div>
2390
2390
2391 <div class="main">
2391 <div class="main">
2392 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2392 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2393 <h3>Help: add</h3>
2393 <h3>Help: add</h3>
2394
2394
2395 <form class="search" action="/log">
2395 <form class="search" action="/log">
2396
2396
2397 <p><input name="rev" id="search1" type="text" size="30" /></p>
2397 <p><input name="rev" id="search1" type="text" size="30" /></p>
2398 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2398 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2399 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2399 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2400 </form>
2400 </form>
2401 <div id="doc">
2401 <div id="doc">
2402 <p>
2402 <p>
2403 hg add [OPTION]... [FILE]...
2403 hg add [OPTION]... [FILE]...
2404 </p>
2404 </p>
2405 <p>
2405 <p>
2406 add the specified files on the next commit
2406 add the specified files on the next commit
2407 </p>
2407 </p>
2408 <p>
2408 <p>
2409 Schedule files to be version controlled and added to the
2409 Schedule files to be version controlled and added to the
2410 repository.
2410 repository.
2411 </p>
2411 </p>
2412 <p>
2412 <p>
2413 The files will be added to the repository at the next commit. To
2413 The files will be added to the repository at the next commit. To
2414 undo an add before that, see 'hg forget'.
2414 undo an add before that, see 'hg forget'.
2415 </p>
2415 </p>
2416 <p>
2416 <p>
2417 If no names are given, add all files to the repository (except
2417 If no names are given, add all files to the repository (except
2418 files matching &quot;.hgignore&quot;).
2418 files matching &quot;.hgignore&quot;).
2419 </p>
2419 </p>
2420 <p>
2420 <p>
2421 Examples:
2421 Examples:
2422 </p>
2422 </p>
2423 <ul>
2423 <ul>
2424 <li> New (unknown) files are added automatically by 'hg add':
2424 <li> New (unknown) files are added automatically by 'hg add':
2425 <pre>
2425 <pre>
2426 \$ ls (re)
2426 \$ ls (re)
2427 foo.c
2427 foo.c
2428 \$ hg status (re)
2428 \$ hg status (re)
2429 ? foo.c
2429 ? foo.c
2430 \$ hg add (re)
2430 \$ hg add (re)
2431 adding foo.c
2431 adding foo.c
2432 \$ hg status (re)
2432 \$ hg status (re)
2433 A foo.c
2433 A foo.c
2434 </pre>
2434 </pre>
2435 <li> Specific files to be added can be specified:
2435 <li> Specific files to be added can be specified:
2436 <pre>
2436 <pre>
2437 \$ ls (re)
2437 \$ ls (re)
2438 bar.c foo.c
2438 bar.c foo.c
2439 \$ hg status (re)
2439 \$ hg status (re)
2440 ? bar.c
2440 ? bar.c
2441 ? foo.c
2441 ? foo.c
2442 \$ hg add bar.c (re)
2442 \$ hg add bar.c (re)
2443 \$ hg status (re)
2443 \$ hg status (re)
2444 A bar.c
2444 A bar.c
2445 ? foo.c
2445 ? foo.c
2446 </pre>
2446 </pre>
2447 </ul>
2447 </ul>
2448 <p>
2448 <p>
2449 Returns 0 if all files are successfully added.
2449 Returns 0 if all files are successfully added.
2450 </p>
2450 </p>
2451 <p>
2451 <p>
2452 options ([+] can be repeated):
2452 options ([+] can be repeated):
2453 </p>
2453 </p>
2454 <table>
2454 <table>
2455 <tr><td>-I</td>
2455 <tr><td>-I</td>
2456 <td>--include PATTERN [+]</td>
2456 <td>--include PATTERN [+]</td>
2457 <td>include names matching the given patterns</td></tr>
2457 <td>include names matching the given patterns</td></tr>
2458 <tr><td>-X</td>
2458 <tr><td>-X</td>
2459 <td>--exclude PATTERN [+]</td>
2459 <td>--exclude PATTERN [+]</td>
2460 <td>exclude names matching the given patterns</td></tr>
2460 <td>exclude names matching the given patterns</td></tr>
2461 <tr><td>-S</td>
2461 <tr><td>-S</td>
2462 <td>--subrepos</td>
2462 <td>--subrepos</td>
2463 <td>recurse into subrepositories</td></tr>
2463 <td>recurse into subrepositories</td></tr>
2464 <tr><td>-n</td>
2464 <tr><td>-n</td>
2465 <td>--dry-run</td>
2465 <td>--dry-run</td>
2466 <td>do not perform actions, just print output</td></tr>
2466 <td>do not perform actions, just print output</td></tr>
2467 </table>
2467 </table>
2468 <p>
2468 <p>
2469 global options ([+] can be repeated):
2469 global options ([+] can be repeated):
2470 </p>
2470 </p>
2471 <table>
2471 <table>
2472 <tr><td>-R</td>
2472 <tr><td>-R</td>
2473 <td>--repository REPO</td>
2473 <td>--repository REPO</td>
2474 <td>repository root directory or name of overlay bundle file</td></tr>
2474 <td>repository root directory or name of overlay bundle file</td></tr>
2475 <tr><td></td>
2475 <tr><td></td>
2476 <td>--cwd DIR</td>
2476 <td>--cwd DIR</td>
2477 <td>change working directory</td></tr>
2477 <td>change working directory</td></tr>
2478 <tr><td>-y</td>
2478 <tr><td>-y</td>
2479 <td>--noninteractive</td>
2479 <td>--noninteractive</td>
2480 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2480 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2481 <tr><td>-q</td>
2481 <tr><td>-q</td>
2482 <td>--quiet</td>
2482 <td>--quiet</td>
2483 <td>suppress output</td></tr>
2483 <td>suppress output</td></tr>
2484 <tr><td>-v</td>
2484 <tr><td>-v</td>
2485 <td>--verbose</td>
2485 <td>--verbose</td>
2486 <td>enable additional output</td></tr>
2486 <td>enable additional output</td></tr>
2487 <tr><td></td>
2487 <tr><td></td>
2488 <td>--config CONFIG [+]</td>
2488 <td>--config CONFIG [+]</td>
2489 <td>set/override config option (use 'section.name=value')</td></tr>
2489 <td>set/override config option (use 'section.name=value')</td></tr>
2490 <tr><td></td>
2490 <tr><td></td>
2491 <td>--debug</td>
2491 <td>--debug</td>
2492 <td>enable debugging output</td></tr>
2492 <td>enable debugging output</td></tr>
2493 <tr><td></td>
2493 <tr><td></td>
2494 <td>--debugger</td>
2494 <td>--debugger</td>
2495 <td>start debugger</td></tr>
2495 <td>start debugger</td></tr>
2496 <tr><td></td>
2496 <tr><td></td>
2497 <td>--encoding ENCODE</td>
2497 <td>--encoding ENCODE</td>
2498 <td>set the charset encoding (default: ascii)</td></tr>
2498 <td>set the charset encoding (default: ascii)</td></tr>
2499 <tr><td></td>
2499 <tr><td></td>
2500 <td>--encodingmode MODE</td>
2500 <td>--encodingmode MODE</td>
2501 <td>set the charset encoding mode (default: strict)</td></tr>
2501 <td>set the charset encoding mode (default: strict)</td></tr>
2502 <tr><td></td>
2502 <tr><td></td>
2503 <td>--traceback</td>
2503 <td>--traceback</td>
2504 <td>always print a traceback on exception</td></tr>
2504 <td>always print a traceback on exception</td></tr>
2505 <tr><td></td>
2505 <tr><td></td>
2506 <td>--time</td>
2506 <td>--time</td>
2507 <td>time how long the command takes</td></tr>
2507 <td>time how long the command takes</td></tr>
2508 <tr><td></td>
2508 <tr><td></td>
2509 <td>--profile</td>
2509 <td>--profile</td>
2510 <td>print command execution profile</td></tr>
2510 <td>print command execution profile</td></tr>
2511 <tr><td></td>
2511 <tr><td></td>
2512 <td>--version</td>
2512 <td>--version</td>
2513 <td>output version information and exit</td></tr>
2513 <td>output version information and exit</td></tr>
2514 <tr><td>-h</td>
2514 <tr><td>-h</td>
2515 <td>--help</td>
2515 <td>--help</td>
2516 <td>display help and exit</td></tr>
2516 <td>display help and exit</td></tr>
2517 <tr><td></td>
2517 <tr><td></td>
2518 <td>--hidden</td>
2518 <td>--hidden</td>
2519 <td>consider hidden changesets</td></tr>
2519 <td>consider hidden changesets</td></tr>
2520 </table>
2520 </table>
2521
2521
2522 </div>
2522 </div>
2523 </div>
2523 </div>
2524 </div>
2524 </div>
2525
2525
2526 <script type="text/javascript">process_dates()</script>
2526 <script type="text/javascript">process_dates()</script>
2527
2527
2528
2528
2529 </body>
2529 </body>
2530 </html>
2530 </html>
2531
2531
2532
2532
2533 $ get-with-headers.py 127.0.0.1:$HGPORT "help/remove"
2533 $ get-with-headers.py 127.0.0.1:$HGPORT "help/remove"
2534 200 Script output follows
2534 200 Script output follows
2535
2535
2536 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2536 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2537 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2537 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2538 <head>
2538 <head>
2539 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2539 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2540 <meta name="robots" content="index, nofollow" />
2540 <meta name="robots" content="index, nofollow" />
2541 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2541 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2542 <script type="text/javascript" src="/static/mercurial.js"></script>
2542 <script type="text/javascript" src="/static/mercurial.js"></script>
2543
2543
2544 <title>Help: remove</title>
2544 <title>Help: remove</title>
2545 </head>
2545 </head>
2546 <body>
2546 <body>
2547
2547
2548 <div class="container">
2548 <div class="container">
2549 <div class="menu">
2549 <div class="menu">
2550 <div class="logo">
2550 <div class="logo">
2551 <a href="https://mercurial-scm.org/">
2551 <a href="https://mercurial-scm.org/">
2552 <img src="/static/hglogo.png" alt="mercurial" /></a>
2552 <img src="/static/hglogo.png" alt="mercurial" /></a>
2553 </div>
2553 </div>
2554 <ul>
2554 <ul>
2555 <li><a href="/shortlog">log</a></li>
2555 <li><a href="/shortlog">log</a></li>
2556 <li><a href="/graph">graph</a></li>
2556 <li><a href="/graph">graph</a></li>
2557 <li><a href="/tags">tags</a></li>
2557 <li><a href="/tags">tags</a></li>
2558 <li><a href="/bookmarks">bookmarks</a></li>
2558 <li><a href="/bookmarks">bookmarks</a></li>
2559 <li><a href="/branches">branches</a></li>
2559 <li><a href="/branches">branches</a></li>
2560 </ul>
2560 </ul>
2561 <ul>
2561 <ul>
2562 <li class="active"><a href="/help">help</a></li>
2562 <li class="active"><a href="/help">help</a></li>
2563 </ul>
2563 </ul>
2564 </div>
2564 </div>
2565
2565
2566 <div class="main">
2566 <div class="main">
2567 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2567 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2568 <h3>Help: remove</h3>
2568 <h3>Help: remove</h3>
2569
2569
2570 <form class="search" action="/log">
2570 <form class="search" action="/log">
2571
2571
2572 <p><input name="rev" id="search1" type="text" size="30" /></p>
2572 <p><input name="rev" id="search1" type="text" size="30" /></p>
2573 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2573 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2574 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2574 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2575 </form>
2575 </form>
2576 <div id="doc">
2576 <div id="doc">
2577 <p>
2577 <p>
2578 hg remove [OPTION]... FILE...
2578 hg remove [OPTION]... FILE...
2579 </p>
2579 </p>
2580 <p>
2580 <p>
2581 aliases: rm
2581 aliases: rm
2582 </p>
2582 </p>
2583 <p>
2583 <p>
2584 remove the specified files on the next commit
2584 remove the specified files on the next commit
2585 </p>
2585 </p>
2586 <p>
2586 <p>
2587 Schedule the indicated files for removal from the current branch.
2587 Schedule the indicated files for removal from the current branch.
2588 </p>
2588 </p>
2589 <p>
2589 <p>
2590 This command schedules the files to be removed at the next commit.
2590 This command schedules the files to be removed at the next commit.
2591 To undo a remove before that, see 'hg revert'. To undo added
2591 To undo a remove before that, see 'hg revert'. To undo added
2592 files, see 'hg forget'.
2592 files, see 'hg forget'.
2593 </p>
2593 </p>
2594 <p>
2594 <p>
2595 -A/--after can be used to remove only files that have already
2595 -A/--after can be used to remove only files that have already
2596 been deleted, -f/--force can be used to force deletion, and -Af
2596 been deleted, -f/--force can be used to force deletion, and -Af
2597 can be used to remove files from the next revision without
2597 can be used to remove files from the next revision without
2598 deleting them from the working directory.
2598 deleting them from the working directory.
2599 </p>
2599 </p>
2600 <p>
2600 <p>
2601 The following table details the behavior of remove for different
2601 The following table details the behavior of remove for different
2602 file states (columns) and option combinations (rows). The file
2602 file states (columns) and option combinations (rows). The file
2603 states are Added [A], Clean [C], Modified [M] and Missing [!]
2603 states are Added [A], Clean [C], Modified [M] and Missing [!]
2604 (as reported by 'hg status'). The actions are Warn, Remove
2604 (as reported by 'hg status'). The actions are Warn, Remove
2605 (from branch) and Delete (from disk):
2605 (from branch) and Delete (from disk):
2606 </p>
2606 </p>
2607 <table>
2607 <table>
2608 <tr><td>opt/state</td>
2608 <tr><td>opt/state</td>
2609 <td>A</td>
2609 <td>A</td>
2610 <td>C</td>
2610 <td>C</td>
2611 <td>M</td>
2611 <td>M</td>
2612 <td>!</td></tr>
2612 <td>!</td></tr>
2613 <tr><td>none</td>
2613 <tr><td>none</td>
2614 <td>W</td>
2614 <td>W</td>
2615 <td>RD</td>
2615 <td>RD</td>
2616 <td>W</td>
2616 <td>W</td>
2617 <td>R</td></tr>
2617 <td>R</td></tr>
2618 <tr><td>-f</td>
2618 <tr><td>-f</td>
2619 <td>R</td>
2619 <td>R</td>
2620 <td>RD</td>
2620 <td>RD</td>
2621 <td>RD</td>
2621 <td>RD</td>
2622 <td>R</td></tr>
2622 <td>R</td></tr>
2623 <tr><td>-A</td>
2623 <tr><td>-A</td>
2624 <td>W</td>
2624 <td>W</td>
2625 <td>W</td>
2625 <td>W</td>
2626 <td>W</td>
2626 <td>W</td>
2627 <td>R</td></tr>
2627 <td>R</td></tr>
2628 <tr><td>-Af</td>
2628 <tr><td>-Af</td>
2629 <td>R</td>
2629 <td>R</td>
2630 <td>R</td>
2630 <td>R</td>
2631 <td>R</td>
2631 <td>R</td>
2632 <td>R</td></tr>
2632 <td>R</td></tr>
2633 </table>
2633 </table>
2634 <p>
2634 <p>
2635 <b>Note:</b>
2635 <b>Note:</b>
2636 </p>
2636 </p>
2637 <p>
2637 <p>
2638 'hg remove' never deletes files in Added [A] state from the
2638 'hg remove' never deletes files in Added [A] state from the
2639 working directory, not even if &quot;--force&quot; is specified.
2639 working directory, not even if &quot;--force&quot; is specified.
2640 </p>
2640 </p>
2641 <p>
2641 <p>
2642 Returns 0 on success, 1 if any warnings encountered.
2642 Returns 0 on success, 1 if any warnings encountered.
2643 </p>
2643 </p>
2644 <p>
2644 <p>
2645 options ([+] can be repeated):
2645 options ([+] can be repeated):
2646 </p>
2646 </p>
2647 <table>
2647 <table>
2648 <tr><td>-A</td>
2648 <tr><td>-A</td>
2649 <td>--after</td>
2649 <td>--after</td>
2650 <td>record delete for missing files</td></tr>
2650 <td>record delete for missing files</td></tr>
2651 <tr><td>-f</td>
2651 <tr><td>-f</td>
2652 <td>--force</td>
2652 <td>--force</td>
2653 <td>forget added files, delete modified files</td></tr>
2653 <td>forget added files, delete modified files</td></tr>
2654 <tr><td>-S</td>
2654 <tr><td>-S</td>
2655 <td>--subrepos</td>
2655 <td>--subrepos</td>
2656 <td>recurse into subrepositories</td></tr>
2656 <td>recurse into subrepositories</td></tr>
2657 <tr><td>-I</td>
2657 <tr><td>-I</td>
2658 <td>--include PATTERN [+]</td>
2658 <td>--include PATTERN [+]</td>
2659 <td>include names matching the given patterns</td></tr>
2659 <td>include names matching the given patterns</td></tr>
2660 <tr><td>-X</td>
2660 <tr><td>-X</td>
2661 <td>--exclude PATTERN [+]</td>
2661 <td>--exclude PATTERN [+]</td>
2662 <td>exclude names matching the given patterns</td></tr>
2662 <td>exclude names matching the given patterns</td></tr>
2663 </table>
2663 </table>
2664 <p>
2664 <p>
2665 global options ([+] can be repeated):
2665 global options ([+] can be repeated):
2666 </p>
2666 </p>
2667 <table>
2667 <table>
2668 <tr><td>-R</td>
2668 <tr><td>-R</td>
2669 <td>--repository REPO</td>
2669 <td>--repository REPO</td>
2670 <td>repository root directory or name of overlay bundle file</td></tr>
2670 <td>repository root directory or name of overlay bundle file</td></tr>
2671 <tr><td></td>
2671 <tr><td></td>
2672 <td>--cwd DIR</td>
2672 <td>--cwd DIR</td>
2673 <td>change working directory</td></tr>
2673 <td>change working directory</td></tr>
2674 <tr><td>-y</td>
2674 <tr><td>-y</td>
2675 <td>--noninteractive</td>
2675 <td>--noninteractive</td>
2676 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2676 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2677 <tr><td>-q</td>
2677 <tr><td>-q</td>
2678 <td>--quiet</td>
2678 <td>--quiet</td>
2679 <td>suppress output</td></tr>
2679 <td>suppress output</td></tr>
2680 <tr><td>-v</td>
2680 <tr><td>-v</td>
2681 <td>--verbose</td>
2681 <td>--verbose</td>
2682 <td>enable additional output</td></tr>
2682 <td>enable additional output</td></tr>
2683 <tr><td></td>
2683 <tr><td></td>
2684 <td>--config CONFIG [+]</td>
2684 <td>--config CONFIG [+]</td>
2685 <td>set/override config option (use 'section.name=value')</td></tr>
2685 <td>set/override config option (use 'section.name=value')</td></tr>
2686 <tr><td></td>
2686 <tr><td></td>
2687 <td>--debug</td>
2687 <td>--debug</td>
2688 <td>enable debugging output</td></tr>
2688 <td>enable debugging output</td></tr>
2689 <tr><td></td>
2689 <tr><td></td>
2690 <td>--debugger</td>
2690 <td>--debugger</td>
2691 <td>start debugger</td></tr>
2691 <td>start debugger</td></tr>
2692 <tr><td></td>
2692 <tr><td></td>
2693 <td>--encoding ENCODE</td>
2693 <td>--encoding ENCODE</td>
2694 <td>set the charset encoding (default: ascii)</td></tr>
2694 <td>set the charset encoding (default: ascii)</td></tr>
2695 <tr><td></td>
2695 <tr><td></td>
2696 <td>--encodingmode MODE</td>
2696 <td>--encodingmode MODE</td>
2697 <td>set the charset encoding mode (default: strict)</td></tr>
2697 <td>set the charset encoding mode (default: strict)</td></tr>
2698 <tr><td></td>
2698 <tr><td></td>
2699 <td>--traceback</td>
2699 <td>--traceback</td>
2700 <td>always print a traceback on exception</td></tr>
2700 <td>always print a traceback on exception</td></tr>
2701 <tr><td></td>
2701 <tr><td></td>
2702 <td>--time</td>
2702 <td>--time</td>
2703 <td>time how long the command takes</td></tr>
2703 <td>time how long the command takes</td></tr>
2704 <tr><td></td>
2704 <tr><td></td>
2705 <td>--profile</td>
2705 <td>--profile</td>
2706 <td>print command execution profile</td></tr>
2706 <td>print command execution profile</td></tr>
2707 <tr><td></td>
2707 <tr><td></td>
2708 <td>--version</td>
2708 <td>--version</td>
2709 <td>output version information and exit</td></tr>
2709 <td>output version information and exit</td></tr>
2710 <tr><td>-h</td>
2710 <tr><td>-h</td>
2711 <td>--help</td>
2711 <td>--help</td>
2712 <td>display help and exit</td></tr>
2712 <td>display help and exit</td></tr>
2713 <tr><td></td>
2713 <tr><td></td>
2714 <td>--hidden</td>
2714 <td>--hidden</td>
2715 <td>consider hidden changesets</td></tr>
2715 <td>consider hidden changesets</td></tr>
2716 </table>
2716 </table>
2717
2717
2718 </div>
2718 </div>
2719 </div>
2719 </div>
2720 </div>
2720 </div>
2721
2721
2722 <script type="text/javascript">process_dates()</script>
2722 <script type="text/javascript">process_dates()</script>
2723
2723
2724
2724
2725 </body>
2725 </body>
2726 </html>
2726 </html>
2727
2727
2728
2728
2729 $ get-with-headers.py 127.0.0.1:$HGPORT "help/revisions"
2729 $ get-with-headers.py 127.0.0.1:$HGPORT "help/revisions"
2730 200 Script output follows
2730 200 Script output follows
2731
2731
2732 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2732 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2733 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2733 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2734 <head>
2734 <head>
2735 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2735 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2736 <meta name="robots" content="index, nofollow" />
2736 <meta name="robots" content="index, nofollow" />
2737 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2737 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2738 <script type="text/javascript" src="/static/mercurial.js"></script>
2738 <script type="text/javascript" src="/static/mercurial.js"></script>
2739
2739
2740 <title>Help: revisions</title>
2740 <title>Help: revisions</title>
2741 </head>
2741 </head>
2742 <body>
2742 <body>
2743
2743
2744 <div class="container">
2744 <div class="container">
2745 <div class="menu">
2745 <div class="menu">
2746 <div class="logo">
2746 <div class="logo">
2747 <a href="https://mercurial-scm.org/">
2747 <a href="https://mercurial-scm.org/">
2748 <img src="/static/hglogo.png" alt="mercurial" /></a>
2748 <img src="/static/hglogo.png" alt="mercurial" /></a>
2749 </div>
2749 </div>
2750 <ul>
2750 <ul>
2751 <li><a href="/shortlog">log</a></li>
2751 <li><a href="/shortlog">log</a></li>
2752 <li><a href="/graph">graph</a></li>
2752 <li><a href="/graph">graph</a></li>
2753 <li><a href="/tags">tags</a></li>
2753 <li><a href="/tags">tags</a></li>
2754 <li><a href="/bookmarks">bookmarks</a></li>
2754 <li><a href="/bookmarks">bookmarks</a></li>
2755 <li><a href="/branches">branches</a></li>
2755 <li><a href="/branches">branches</a></li>
2756 </ul>
2756 </ul>
2757 <ul>
2757 <ul>
2758 <li class="active"><a href="/help">help</a></li>
2758 <li class="active"><a href="/help">help</a></li>
2759 </ul>
2759 </ul>
2760 </div>
2760 </div>
2761
2761
2762 <div class="main">
2762 <div class="main">
2763 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2763 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2764 <h3>Help: revisions</h3>
2764 <h3>Help: revisions</h3>
2765
2765
2766 <form class="search" action="/log">
2766 <form class="search" action="/log">
2767
2767
2768 <p><input name="rev" id="search1" type="text" size="30" /></p>
2768 <p><input name="rev" id="search1" type="text" size="30" /></p>
2769 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2769 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2770 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2770 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2771 </form>
2771 </form>
2772 <div id="doc">
2772 <div id="doc">
2773 <h1>Specifying Single Revisions</h1>
2773 <h1>Specifying Single Revisions</h1>
2774 <p>
2774 <p>
2775 Mercurial supports several ways to specify individual revisions.
2775 Mercurial supports several ways to specify individual revisions.
2776 </p>
2776 </p>
2777 <p>
2777 <p>
2778 A plain integer is treated as a revision number. Negative integers are
2778 A plain integer is treated as a revision number. Negative integers are
2779 treated as sequential offsets from the tip, with -1 denoting the tip,
2779 treated as sequential offsets from the tip, with -1 denoting the tip,
2780 -2 denoting the revision prior to the tip, and so forth.
2780 -2 denoting the revision prior to the tip, and so forth.
2781 </p>
2781 </p>
2782 <p>
2782 <p>
2783 A 40-digit hexadecimal string is treated as a unique revision
2783 A 40-digit hexadecimal string is treated as a unique revision
2784 identifier.
2784 identifier.
2785 </p>
2785 </p>
2786 <p>
2786 <p>
2787 A hexadecimal string less than 40 characters long is treated as a
2787 A hexadecimal string less than 40 characters long is treated as a
2788 unique revision identifier and is referred to as a short-form
2788 unique revision identifier and is referred to as a short-form
2789 identifier. A short-form identifier is only valid if it is the prefix
2789 identifier. A short-form identifier is only valid if it is the prefix
2790 of exactly one full-length identifier.
2790 of exactly one full-length identifier.
2791 </p>
2791 </p>
2792 <p>
2792 <p>
2793 Any other string is treated as a bookmark, tag, or branch name. A
2793 Any other string is treated as a bookmark, tag, or branch name. A
2794 bookmark is a movable pointer to a revision. A tag is a permanent name
2794 bookmark is a movable pointer to a revision. A tag is a permanent name
2795 associated with a revision. A branch name denotes the tipmost open branch head
2795 associated with a revision. A branch name denotes the tipmost open branch head
2796 of that branch - or if they are all closed, the tipmost closed head of the
2796 of that branch - or if they are all closed, the tipmost closed head of the
2797 branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
2797 branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
2798 </p>
2798 </p>
2799 <p>
2799 <p>
2800 The reserved name &quot;tip&quot; always identifies the most recent revision.
2800 The reserved name &quot;tip&quot; always identifies the most recent revision.
2801 </p>
2801 </p>
2802 <p>
2802 <p>
2803 The reserved name &quot;null&quot; indicates the null revision. This is the
2803 The reserved name &quot;null&quot; indicates the null revision. This is the
2804 revision of an empty repository, and the parent of revision 0.
2804 revision of an empty repository, and the parent of revision 0.
2805 </p>
2805 </p>
2806 <p>
2806 <p>
2807 The reserved name &quot;.&quot; indicates the working directory parent. If no
2807 The reserved name &quot;.&quot; indicates the working directory parent. If no
2808 working directory is checked out, it is equivalent to null. If an
2808 working directory is checked out, it is equivalent to null. If an
2809 uncommitted merge is in progress, &quot;.&quot; is the revision of the first
2809 uncommitted merge is in progress, &quot;.&quot; is the revision of the first
2810 parent.
2810 parent.
2811 </p>
2811 </p>
2812
2812
2813 </div>
2813 </div>
2814 </div>
2814 </div>
2815 </div>
2815 </div>
2816
2816
2817 <script type="text/javascript">process_dates()</script>
2817 <script type="text/javascript">process_dates()</script>
2818
2818
2819
2819
2820 </body>
2820 </body>
2821 </html>
2821 </html>
2822
2822
2823
2823
2824 Sub-topic indexes rendered properly
2824 Sub-topic indexes rendered properly
2825
2825
2826 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals"
2826 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals"
2827 200 Script output follows
2827 200 Script output follows
2828
2828
2829 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2829 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2830 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2830 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2831 <head>
2831 <head>
2832 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2832 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2833 <meta name="robots" content="index, nofollow" />
2833 <meta name="robots" content="index, nofollow" />
2834 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2834 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2835 <script type="text/javascript" src="/static/mercurial.js"></script>
2835 <script type="text/javascript" src="/static/mercurial.js"></script>
2836
2836
2837 <title>Help: internals</title>
2837 <title>Help: internals</title>
2838 </head>
2838 </head>
2839 <body>
2839 <body>
2840
2840
2841 <div class="container">
2841 <div class="container">
2842 <div class="menu">
2842 <div class="menu">
2843 <div class="logo">
2843 <div class="logo">
2844 <a href="https://mercurial-scm.org/">
2844 <a href="https://mercurial-scm.org/">
2845 <img src="/static/hglogo.png" alt="mercurial" /></a>
2845 <img src="/static/hglogo.png" alt="mercurial" /></a>
2846 </div>
2846 </div>
2847 <ul>
2847 <ul>
2848 <li><a href="/shortlog">log</a></li>
2848 <li><a href="/shortlog">log</a></li>
2849 <li><a href="/graph">graph</a></li>
2849 <li><a href="/graph">graph</a></li>
2850 <li><a href="/tags">tags</a></li>
2850 <li><a href="/tags">tags</a></li>
2851 <li><a href="/bookmarks">bookmarks</a></li>
2851 <li><a href="/bookmarks">bookmarks</a></li>
2852 <li><a href="/branches">branches</a></li>
2852 <li><a href="/branches">branches</a></li>
2853 </ul>
2853 </ul>
2854 <ul>
2854 <ul>
2855 <li><a href="/help">help</a></li>
2855 <li><a href="/help">help</a></li>
2856 </ul>
2856 </ul>
2857 </div>
2857 </div>
2858
2858
2859 <div class="main">
2859 <div class="main">
2860 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2860 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2861 <form class="search" action="/log">
2861 <form class="search" action="/log">
2862
2862
2863 <p><input name="rev" id="search1" type="text" size="30" /></p>
2863 <p><input name="rev" id="search1" type="text" size="30" /></p>
2864 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2864 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2865 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2865 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2866 </form>
2866 </form>
2867 <table class="bigtable">
2867 <table class="bigtable">
2868 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
2868 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
2869
2869
2870 <tr><td>
2870 <tr><td>
2871 <a href="/help/internals.bundles">
2871 <a href="/help/internals.bundles">
2872 bundles
2872 bundles
2873 </a>
2873 </a>
2874 </td><td>
2874 </td><td>
2875 container for exchange of repository data
2875 Bundles
2876 </td></tr>
2876 </td></tr>
2877 <tr><td>
2877 <tr><td>
2878 <a href="/help/internals.changegroups">
2878 <a href="/help/internals.changegroups">
2879 changegroups
2879 changegroups
2880 </a>
2880 </a>
2881 </td><td>
2881 </td><td>
2882 representation of revlog data
2882 Changegroups
2883 </td></tr>
2883 </td></tr>
2884 <tr><td>
2884 <tr><td>
2885 <a href="/help/internals.requirements">
2885 <a href="/help/internals.requirements">
2886 requirements
2886 requirements
2887 </a>
2887 </a>
2888 </td><td>
2888 </td><td>
2889 repository requirements
2889 Repository Requirements
2890 </td></tr>
2890 </td></tr>
2891 <tr><td>
2891 <tr><td>
2892 <a href="/help/internals.revlogs">
2892 <a href="/help/internals.revlogs">
2893 revlogs
2893 revlogs
2894 </a>
2894 </a>
2895 </td><td>
2895 </td><td>
2896 revision storage mechanism
2896 Revision Logs
2897 </td></tr>
2897 </td></tr>
2898
2898
2899
2899
2900
2900
2901
2901
2902
2902
2903 </table>
2903 </table>
2904 </div>
2904 </div>
2905 </div>
2905 </div>
2906
2906
2907 <script type="text/javascript">process_dates()</script>
2907 <script type="text/javascript">process_dates()</script>
2908
2908
2909
2909
2910 </body>
2910 </body>
2911 </html>
2911 </html>
2912
2912
2913
2913
2914 Sub-topic topics rendered properly
2914 Sub-topic topics rendered properly
2915
2915
2916 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals.changegroups"
2916 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals.changegroups"
2917 200 Script output follows
2917 200 Script output follows
2918
2918
2919 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2919 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2920 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2920 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2921 <head>
2921 <head>
2922 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2922 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2923 <meta name="robots" content="index, nofollow" />
2923 <meta name="robots" content="index, nofollow" />
2924 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2924 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2925 <script type="text/javascript" src="/static/mercurial.js"></script>
2925 <script type="text/javascript" src="/static/mercurial.js"></script>
2926
2926
2927 <title>Help: internals.changegroups</title>
2927 <title>Help: internals.changegroups</title>
2928 </head>
2928 </head>
2929 <body>
2929 <body>
2930
2930
2931 <div class="container">
2931 <div class="container">
2932 <div class="menu">
2932 <div class="menu">
2933 <div class="logo">
2933 <div class="logo">
2934 <a href="https://mercurial-scm.org/">
2934 <a href="https://mercurial-scm.org/">
2935 <img src="/static/hglogo.png" alt="mercurial" /></a>
2935 <img src="/static/hglogo.png" alt="mercurial" /></a>
2936 </div>
2936 </div>
2937 <ul>
2937 <ul>
2938 <li><a href="/shortlog">log</a></li>
2938 <li><a href="/shortlog">log</a></li>
2939 <li><a href="/graph">graph</a></li>
2939 <li><a href="/graph">graph</a></li>
2940 <li><a href="/tags">tags</a></li>
2940 <li><a href="/tags">tags</a></li>
2941 <li><a href="/bookmarks">bookmarks</a></li>
2941 <li><a href="/bookmarks">bookmarks</a></li>
2942 <li><a href="/branches">branches</a></li>
2942 <li><a href="/branches">branches</a></li>
2943 </ul>
2943 </ul>
2944 <ul>
2944 <ul>
2945 <li class="active"><a href="/help">help</a></li>
2945 <li class="active"><a href="/help">help</a></li>
2946 </ul>
2946 </ul>
2947 </div>
2947 </div>
2948
2948
2949 <div class="main">
2949 <div class="main">
2950 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2950 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2951 <h3>Help: internals.changegroups</h3>
2951 <h3>Help: internals.changegroups</h3>
2952
2952
2953 <form class="search" action="/log">
2953 <form class="search" action="/log">
2954
2954
2955 <p><input name="rev" id="search1" type="text" size="30" /></p>
2955 <p><input name="rev" id="search1" type="text" size="30" /></p>
2956 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2956 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2957 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2957 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2958 </form>
2958 </form>
2959 <div id="doc">
2959 <div id="doc">
2960 <h1>representation of revlog data</h1>
2960 <h1>Changegroups</h1>
2961 <h2>Changegroups</h2>
2962 <p>
2961 <p>
2963 Changegroups are representations of repository revlog data, specifically
2962 Changegroups are representations of repository revlog data, specifically
2964 the changelog, manifest, and filelogs.
2963 the changelog, manifest, and filelogs.
2965 </p>
2964 </p>
2966 <p>
2965 <p>
2967 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
2966 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
2968 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with
2967 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with
2969 the only difference being a header on entries in the changeset
2968 the only difference being a header on entries in the changeset
2970 segment. Version &quot;3&quot; adds support for exchanging treemanifests and
2969 segment. Version &quot;3&quot; adds support for exchanging treemanifests and
2971 includes revlog flags in the delta header.
2970 includes revlog flags in the delta header.
2972 </p>
2971 </p>
2973 <p>
2972 <p>
2974 Changegroups consists of 3 logical segments:
2973 Changegroups consists of 3 logical segments:
2975 </p>
2974 </p>
2976 <pre>
2975 <pre>
2977 +---------------------------------+
2976 +---------------------------------+
2978 | | | |
2977 | | | |
2979 | changeset | manifest | filelogs |
2978 | changeset | manifest | filelogs |
2980 | | | |
2979 | | | |
2981 +---------------------------------+
2980 +---------------------------------+
2982 </pre>
2981 </pre>
2983 <p>
2982 <p>
2984 The principle building block of each segment is a *chunk*. A *chunk*
2983 The principle building block of each segment is a *chunk*. A *chunk*
2985 is a framed piece of data:
2984 is a framed piece of data:
2986 </p>
2985 </p>
2987 <pre>
2986 <pre>
2988 +---------------------------------------+
2987 +---------------------------------------+
2989 | | |
2988 | | |
2990 | length | data |
2989 | length | data |
2991 | (32 bits) | &lt;length&gt; bytes |
2990 | (32 bits) | &lt;length&gt; bytes |
2992 | | |
2991 | | |
2993 +---------------------------------------+
2992 +---------------------------------------+
2994 </pre>
2993 </pre>
2995 <p>
2994 <p>
2996 Each chunk starts with a 32-bit big-endian signed integer indicating
2995 Each chunk starts with a 32-bit big-endian signed integer indicating
2997 the length of the raw data that follows.
2996 the length of the raw data that follows.
2998 </p>
2997 </p>
2999 <p>
2998 <p>
3000 There is a special case chunk that has 0 length (&quot;0x00000000&quot;). We
2999 There is a special case chunk that has 0 length (&quot;0x00000000&quot;). We
3001 call this an *empty chunk*.
3000 call this an *empty chunk*.
3002 </p>
3001 </p>
3003 <h3>Delta Groups</h3>
3002 <h2>Delta Groups</h2>
3004 <p>
3003 <p>
3005 A *delta group* expresses the content of a revlog as a series of deltas,
3004 A *delta group* expresses the content of a revlog as a series of deltas,
3006 or patches against previous revisions.
3005 or patches against previous revisions.
3007 </p>
3006 </p>
3008 <p>
3007 <p>
3009 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3008 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3010 to signal the end of the delta group:
3009 to signal the end of the delta group:
3011 </p>
3010 </p>
3012 <pre>
3011 <pre>
3013 +------------------------------------------------------------------------+
3012 +------------------------------------------------------------------------+
3014 | | | | | |
3013 | | | | | |
3015 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3014 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3016 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
3015 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
3017 | | | | | |
3016 | | | | | |
3018 +------------------------------------------------------------+-----------+
3017 +------------------------------------------------------------+-----------+
3019 </pre>
3018 </pre>
3020 <p>
3019 <p>
3021 Each *chunk*'s data consists of the following:
3020 Each *chunk*'s data consists of the following:
3022 </p>
3021 </p>
3023 <pre>
3022 <pre>
3024 +-----------------------------------------+
3023 +-----------------------------------------+
3025 | | | |
3024 | | | |
3026 | delta header | mdiff header | delta |
3025 | delta header | mdiff header | delta |
3027 | (various) | (12 bytes) | (various) |
3026 | (various) | (12 bytes) | (various) |
3028 | | | |
3027 | | | |
3029 +-----------------------------------------+
3028 +-----------------------------------------+
3030 </pre>
3029 </pre>
3031 <p>
3030 <p>
3032 The *length* field is the byte length of the remaining 3 logical pieces
3031 The *length* field is the byte length of the remaining 3 logical pieces
3033 of data. The *delta* is a diff from an existing entry in the changelog.
3032 of data. The *delta* is a diff from an existing entry in the changelog.
3034 </p>
3033 </p>
3035 <p>
3034 <p>
3036 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3035 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3037 &quot;3&quot; of the changegroup format.
3036 &quot;3&quot; of the changegroup format.
3038 </p>
3037 </p>
3039 <p>
3038 <p>
3040 Version 1:
3039 Version 1:
3041 </p>
3040 </p>
3042 <pre>
3041 <pre>
3043 +------------------------------------------------------+
3042 +------------------------------------------------------+
3044 | | | | |
3043 | | | | |
3045 | node | p1 node | p2 node | link node |
3044 | node | p1 node | p2 node | link node |
3046 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3045 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3047 | | | | |
3046 | | | | |
3048 +------------------------------------------------------+
3047 +------------------------------------------------------+
3049 </pre>
3048 </pre>
3050 <p>
3049 <p>
3051 Version 2:
3050 Version 2:
3052 </p>
3051 </p>
3053 <pre>
3052 <pre>
3054 +------------------------------------------------------------------+
3053 +------------------------------------------------------------------+
3055 | | | | | |
3054 | | | | | |
3056 | node | p1 node | p2 node | base node | link node |
3055 | node | p1 node | p2 node | base node | link node |
3057 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3056 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3058 | | | | | |
3057 | | | | | |
3059 +------------------------------------------------------------------+
3058 +------------------------------------------------------------------+
3060 </pre>
3059 </pre>
3061 <p>
3060 <p>
3062 Version 3:
3061 Version 3:
3063 </p>
3062 </p>
3064 <pre>
3063 <pre>
3065 +------------------------------------------------------------------------------+
3064 +------------------------------------------------------------------------------+
3066 | | | | | | |
3065 | | | | | | |
3067 | node | p1 node | p2 node | base node | link node | flags |
3066 | node | p1 node | p2 node | base node | link node | flags |
3068 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3067 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3069 | | | | | | |
3068 | | | | | | |
3070 +------------------------------------------------------------------------------+
3069 +------------------------------------------------------------------------------+
3071 </pre>
3070 </pre>
3072 <p>
3071 <p>
3073 The *mdiff header* consists of 3 32-bit big-endian signed integers
3072 The *mdiff header* consists of 3 32-bit big-endian signed integers
3074 describing offsets at which to apply the following delta content:
3073 describing offsets at which to apply the following delta content:
3075 </p>
3074 </p>
3076 <pre>
3075 <pre>
3077 +-------------------------------------+
3076 +-------------------------------------+
3078 | | | |
3077 | | | |
3079 | offset | old length | new length |
3078 | offset | old length | new length |
3080 | (32 bits) | (32 bits) | (32 bits) |
3079 | (32 bits) | (32 bits) | (32 bits) |
3081 | | | |
3080 | | | |
3082 +-------------------------------------+
3081 +-------------------------------------+
3083 </pre>
3082 </pre>
3084 <p>
3083 <p>
3085 In version 1, the delta is always applied against the previous node from
3084 In version 1, the delta is always applied against the previous node from
3086 the changegroup or the first parent if this is the first entry in the
3085 the changegroup or the first parent if this is the first entry in the
3087 changegroup.
3086 changegroup.
3088 </p>
3087 </p>
3089 <p>
3088 <p>
3090 In version 2, the delta base node is encoded in the entry in the
3089 In version 2, the delta base node is encoded in the entry in the
3091 changegroup. This allows the delta to be expressed against any parent,
3090 changegroup. This allows the delta to be expressed against any parent,
3092 which can result in smaller deltas and more efficient encoding of data.
3091 which can result in smaller deltas and more efficient encoding of data.
3093 </p>
3092 </p>
3094 <h3>Changeset Segment</h3>
3093 <h2>Changeset Segment</h2>
3095 <p>
3094 <p>
3096 The *changeset segment* consists of a single *delta group* holding
3095 The *changeset segment* consists of a single *delta group* holding
3097 changelog data. It is followed by an *empty chunk* to denote the
3096 changelog data. It is followed by an *empty chunk* to denote the
3098 boundary to the *manifests segment*.
3097 boundary to the *manifests segment*.
3099 </p>
3098 </p>
3100 <h3>Manifest Segment</h3>
3099 <h2>Manifest Segment</h2>
3101 <p>
3100 <p>
3102 The *manifest segment* consists of a single *delta group* holding
3101 The *manifest segment* consists of a single *delta group* holding
3103 manifest data. It is followed by an *empty chunk* to denote the boundary
3102 manifest data. It is followed by an *empty chunk* to denote the boundary
3104 to the *filelogs segment*.
3103 to the *filelogs segment*.
3105 </p>
3104 </p>
3106 <h3>Filelogs Segment</h3>
3105 <h2>Filelogs Segment</h2>
3107 <p>
3106 <p>
3108 The *filelogs* segment consists of multiple sub-segments, each
3107 The *filelogs* segment consists of multiple sub-segments, each
3109 corresponding to an individual file whose data is being described:
3108 corresponding to an individual file whose data is being described:
3110 </p>
3109 </p>
3111 <pre>
3110 <pre>
3112 +--------------------------------------+
3111 +--------------------------------------+
3113 | | | | |
3112 | | | | |
3114 | filelog0 | filelog1 | filelog2 | ... |
3113 | filelog0 | filelog1 | filelog2 | ... |
3115 | | | | |
3114 | | | | |
3116 +--------------------------------------+
3115 +--------------------------------------+
3117 </pre>
3116 </pre>
3118 <p>
3117 <p>
3119 In version &quot;3&quot; of the changegroup format, filelogs may include
3118 In version &quot;3&quot; of the changegroup format, filelogs may include
3120 directory logs when treemanifests are in use. directory logs are
3119 directory logs when treemanifests are in use. directory logs are
3121 identified by having a trailing '/' on their filename (see below).
3120 identified by having a trailing '/' on their filename (see below).
3122 </p>
3121 </p>
3123 <p>
3122 <p>
3124 The final filelog sub-segment is followed by an *empty chunk* to denote
3123 The final filelog sub-segment is followed by an *empty chunk* to denote
3125 the end of the segment and the overall changegroup.
3124 the end of the segment and the overall changegroup.
3126 </p>
3125 </p>
3127 <p>
3126 <p>
3128 Each filelog sub-segment consists of the following:
3127 Each filelog sub-segment consists of the following:
3129 </p>
3128 </p>
3130 <pre>
3129 <pre>
3131 +------------------------------------------+
3130 +------------------------------------------+
3132 | | | |
3131 | | | |
3133 | filename size | filename | delta group |
3132 | filename size | filename | delta group |
3134 | (32 bits) | (various) | (various) |
3133 | (32 bits) | (various) | (various) |
3135 | | | |
3134 | | | |
3136 +------------------------------------------+
3135 +------------------------------------------+
3137 </pre>
3136 </pre>
3138 <p>
3137 <p>
3139 That is, a *chunk* consisting of the filename (not terminated or padded)
3138 That is, a *chunk* consisting of the filename (not terminated or padded)
3140 followed by N chunks constituting the *delta group* for this file.
3139 followed by N chunks constituting the *delta group* for this file.
3141 </p>
3140 </p>
3142
3141
3143 </div>
3142 </div>
3144 </div>
3143 </div>
3145 </div>
3144 </div>
3146
3145
3147 <script type="text/javascript">process_dates()</script>
3146 <script type="text/javascript">process_dates()</script>
3148
3147
3149
3148
3150 </body>
3149 </body>
3151 </html>
3150 </html>
3152
3151
3153
3152
3154 $ killdaemons.py
3153 $ killdaemons.py
3155
3154
3156 #endif
3155 #endif
General Comments 0
You need to be logged in to leave comments. Login now