##// END OF EJS Templates
id: add some help examples
Matt Mackall -
r15112:24f54894 default
parent child Browse files
Show More
@@ -1,5301 +1,5317 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 node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge
18 import dagparser, context, simplemerge
19 import random, setdiscovery, treediscovery, dagutil
19 import random, setdiscovery, treediscovery, dagutil
20
20
21 table = {}
21 table = {}
22
22
23 command = cmdutil.command(table)
23 command = cmdutil.command(table)
24
24
25 # common command options
25 # common command options
26
26
27 globalopts = [
27 globalopts = [
28 ('R', 'repository', '',
28 ('R', 'repository', '',
29 _('repository root directory or name of overlay bundle file'),
29 _('repository root directory or name of overlay bundle file'),
30 _('REPO')),
30 _('REPO')),
31 ('', 'cwd', '',
31 ('', 'cwd', '',
32 _('change working directory'), _('DIR')),
32 _('change working directory'), _('DIR')),
33 ('y', 'noninteractive', None,
33 ('y', 'noninteractive', None,
34 _('do not prompt, automatically pick the first choice for all prompts')),
34 _('do not prompt, automatically pick the first choice for all prompts')),
35 ('q', 'quiet', None, _('suppress output')),
35 ('q', 'quiet', None, _('suppress output')),
36 ('v', 'verbose', None, _('enable additional output')),
36 ('v', 'verbose', None, _('enable additional output')),
37 ('', 'config', [],
37 ('', 'config', [],
38 _('set/override config option (use \'section.name=value\')'),
38 _('set/override config option (use \'section.name=value\')'),
39 _('CONFIG')),
39 _('CONFIG')),
40 ('', 'debug', None, _('enable debugging output')),
40 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debugger', None, _('start debugger')),
41 ('', 'debugger', None, _('start debugger')),
42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 _('ENCODE')),
43 _('ENCODE')),
44 ('', 'encodingmode', encoding.encodingmode,
44 ('', 'encodingmode', encoding.encodingmode,
45 _('set the charset encoding mode'), _('MODE')),
45 _('set the charset encoding mode'), _('MODE')),
46 ('', 'traceback', None, _('always print a traceback on exception')),
46 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'time', None, _('time how long the command takes')),
47 ('', 'time', None, _('time how long the command takes')),
48 ('', 'profile', None, _('print command execution profile')),
48 ('', 'profile', None, _('print command execution profile')),
49 ('', 'version', None, _('output version information and exit')),
49 ('', 'version', None, _('output version information and exit')),
50 ('h', 'help', None, _('display help and exit')),
50 ('h', 'help', None, _('display help and exit')),
51 ]
51 ]
52
52
53 dryrunopts = [('n', 'dry-run', None,
53 dryrunopts = [('n', 'dry-run', None,
54 _('do not perform actions, just print output'))]
54 _('do not perform actions, just print output'))]
55
55
56 remoteopts = [
56 remoteopts = [
57 ('e', 'ssh', '',
57 ('e', 'ssh', '',
58 _('specify ssh command to use'), _('CMD')),
58 _('specify ssh command to use'), _('CMD')),
59 ('', 'remotecmd', '',
59 ('', 'remotecmd', '',
60 _('specify hg command to run on the remote side'), _('CMD')),
60 _('specify hg command to run on the remote side'), _('CMD')),
61 ('', 'insecure', None,
61 ('', 'insecure', None,
62 _('do not verify server certificate (ignoring web.cacerts config)')),
62 _('do not verify server certificate (ignoring web.cacerts config)')),
63 ]
63 ]
64
64
65 walkopts = [
65 walkopts = [
66 ('I', 'include', [],
66 ('I', 'include', [],
67 _('include names matching the given patterns'), _('PATTERN')),
67 _('include names matching the given patterns'), _('PATTERN')),
68 ('X', 'exclude', [],
68 ('X', 'exclude', [],
69 _('exclude names matching the given patterns'), _('PATTERN')),
69 _('exclude names matching the given patterns'), _('PATTERN')),
70 ]
70 ]
71
71
72 commitopts = [
72 commitopts = [
73 ('m', 'message', '',
73 ('m', 'message', '',
74 _('use text as commit message'), _('TEXT')),
74 _('use text as commit message'), _('TEXT')),
75 ('l', 'logfile', '',
75 ('l', 'logfile', '',
76 _('read commit message from file'), _('FILE')),
76 _('read commit message from file'), _('FILE')),
77 ]
77 ]
78
78
79 commitopts2 = [
79 commitopts2 = [
80 ('d', 'date', '',
80 ('d', 'date', '',
81 _('record the specified date as commit date'), _('DATE')),
81 _('record the specified date as commit date'), _('DATE')),
82 ('u', 'user', '',
82 ('u', 'user', '',
83 _('record the specified user as committer'), _('USER')),
83 _('record the specified user as committer'), _('USER')),
84 ]
84 ]
85
85
86 templateopts = [
86 templateopts = [
87 ('', 'style', '',
87 ('', 'style', '',
88 _('display using template map file'), _('STYLE')),
88 _('display using template map file'), _('STYLE')),
89 ('', 'template', '',
89 ('', 'template', '',
90 _('display with template'), _('TEMPLATE')),
90 _('display with template'), _('TEMPLATE')),
91 ]
91 ]
92
92
93 logopts = [
93 logopts = [
94 ('p', 'patch', None, _('show patch')),
94 ('p', 'patch', None, _('show patch')),
95 ('g', 'git', None, _('use git extended diff format')),
95 ('g', 'git', None, _('use git extended diff format')),
96 ('l', 'limit', '',
96 ('l', 'limit', '',
97 _('limit number of changes displayed'), _('NUM')),
97 _('limit number of changes displayed'), _('NUM')),
98 ('M', 'no-merges', None, _('do not show merges')),
98 ('M', 'no-merges', None, _('do not show merges')),
99 ('', 'stat', None, _('output diffstat-style summary of changes')),
99 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ] + templateopts
100 ] + templateopts
101
101
102 diffopts = [
102 diffopts = [
103 ('a', 'text', None, _('treat all files as text')),
103 ('a', 'text', None, _('treat all files as text')),
104 ('g', 'git', None, _('use git extended diff format')),
104 ('g', 'git', None, _('use git extended diff format')),
105 ('', 'nodates', None, _('omit dates from diff headers'))
105 ('', 'nodates', None, _('omit dates from diff headers'))
106 ]
106 ]
107
107
108 diffopts2 = [
108 diffopts2 = [
109 ('p', 'show-function', None, _('show which function each change is in')),
109 ('p', 'show-function', None, _('show which function each change is in')),
110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
111 ('w', 'ignore-all-space', None,
111 ('w', 'ignore-all-space', None,
112 _('ignore white space when comparing lines')),
112 _('ignore white space when comparing lines')),
113 ('b', 'ignore-space-change', None,
113 ('b', 'ignore-space-change', None,
114 _('ignore changes in the amount of white space')),
114 _('ignore changes in the amount of white space')),
115 ('B', 'ignore-blank-lines', None,
115 ('B', 'ignore-blank-lines', None,
116 _('ignore changes whose lines are all blank')),
116 _('ignore changes whose lines are all blank')),
117 ('U', 'unified', '',
117 ('U', 'unified', '',
118 _('number of lines of context to show'), _('NUM')),
118 _('number of lines of context to show'), _('NUM')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
120 ]
120 ]
121
121
122 mergetoolopts = [
122 mergetoolopts = [
123 ('t', 'tool', '', _('specify merge tool')),
123 ('t', 'tool', '', _('specify merge tool')),
124 ]
124 ]
125
125
126 similarityopts = [
126 similarityopts = [
127 ('s', 'similarity', '',
127 ('s', 'similarity', '',
128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
129 ]
129 ]
130
130
131 subrepoopts = [
131 subrepoopts = [
132 ('S', 'subrepos', None,
132 ('S', 'subrepos', None,
133 _('recurse into subrepositories'))
133 _('recurse into subrepositories'))
134 ]
134 ]
135
135
136 # Commands start here, listed alphabetically
136 # Commands start here, listed alphabetically
137
137
138 @command('^add',
138 @command('^add',
139 walkopts + subrepoopts + dryrunopts,
139 walkopts + subrepoopts + dryrunopts,
140 _('[OPTION]... [FILE]...'))
140 _('[OPTION]... [FILE]...'))
141 def add(ui, repo, *pats, **opts):
141 def add(ui, repo, *pats, **opts):
142 """add the specified files on the next commit
142 """add the specified files on the next commit
143
143
144 Schedule files to be version controlled and added to the
144 Schedule files to be version controlled and added to the
145 repository.
145 repository.
146
146
147 The files will be added to the repository at the next commit. To
147 The files will be added to the repository at the next commit. To
148 undo an add before that, see :hg:`forget`.
148 undo an add before that, see :hg:`forget`.
149
149
150 If no names are given, add all files to the repository.
150 If no names are given, add all files to the repository.
151
151
152 .. container:: verbose
152 .. container:: verbose
153
153
154 An example showing how new (unknown) files are added
154 An example showing how new (unknown) files are added
155 automatically by :hg:`add`::
155 automatically by :hg:`add`::
156
156
157 $ ls
157 $ ls
158 foo.c
158 foo.c
159 $ hg status
159 $ hg status
160 ? foo.c
160 ? foo.c
161 $ hg add
161 $ hg add
162 adding foo.c
162 adding foo.c
163 $ hg status
163 $ hg status
164 A foo.c
164 A foo.c
165
165
166 Returns 0 if all files are successfully added.
166 Returns 0 if all files are successfully added.
167 """
167 """
168
168
169 m = scmutil.match(repo[None], pats, opts)
169 m = scmutil.match(repo[None], pats, opts)
170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
171 opts.get('subrepos'), prefix="")
171 opts.get('subrepos'), prefix="")
172 return rejected and 1 or 0
172 return rejected and 1 or 0
173
173
174 @command('addremove',
174 @command('addremove',
175 similarityopts + walkopts + dryrunopts,
175 similarityopts + walkopts + dryrunopts,
176 _('[OPTION]... [FILE]...'))
176 _('[OPTION]... [FILE]...'))
177 def addremove(ui, repo, *pats, **opts):
177 def addremove(ui, repo, *pats, **opts):
178 """add all new files, delete all missing files
178 """add all new files, delete all missing files
179
179
180 Add all new files and remove all missing files from the
180 Add all new files and remove all missing files from the
181 repository.
181 repository.
182
182
183 New files are ignored if they match any of the patterns in
183 New files are ignored if they match any of the patterns in
184 ``.hgignore``. As with add, these changes take effect at the next
184 ``.hgignore``. As with add, these changes take effect at the next
185 commit.
185 commit.
186
186
187 Use the -s/--similarity option to detect renamed files. With a
187 Use the -s/--similarity option to detect renamed files. With a
188 parameter greater than 0, this compares every removed file with
188 parameter greater than 0, this compares every removed file with
189 every added file and records those similar enough as renames. This
189 every added file and records those similar enough as renames. This
190 option takes a percentage between 0 (disabled) and 100 (files must
190 option takes a percentage between 0 (disabled) and 100 (files must
191 be identical) as its parameter. Detecting renamed files this way
191 be identical) as its parameter. Detecting renamed files this way
192 can be expensive. After using this option, :hg:`status -C` can be
192 can be expensive. After using this option, :hg:`status -C` can be
193 used to check which files were identified as moved or renamed.
193 used to check which files were identified as moved or renamed.
194
194
195 Returns 0 if all files are successfully added.
195 Returns 0 if all files are successfully added.
196 """
196 """
197 try:
197 try:
198 sim = float(opts.get('similarity') or 100)
198 sim = float(opts.get('similarity') or 100)
199 except ValueError:
199 except ValueError:
200 raise util.Abort(_('similarity must be a number'))
200 raise util.Abort(_('similarity must be a number'))
201 if sim < 0 or sim > 100:
201 if sim < 0 or sim > 100:
202 raise util.Abort(_('similarity must be between 0 and 100'))
202 raise util.Abort(_('similarity must be between 0 and 100'))
203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
204
204
205 @command('^annotate|blame',
205 @command('^annotate|blame',
206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
207 ('', 'follow', None,
207 ('', 'follow', None,
208 _('follow copies/renames and list the filename (DEPRECATED)')),
208 _('follow copies/renames and list the filename (DEPRECATED)')),
209 ('', 'no-follow', None, _("don't follow copies and renames")),
209 ('', 'no-follow', None, _("don't follow copies and renames")),
210 ('a', 'text', None, _('treat all files as text')),
210 ('a', 'text', None, _('treat all files as text')),
211 ('u', 'user', None, _('list the author (long with -v)')),
211 ('u', 'user', None, _('list the author (long with -v)')),
212 ('f', 'file', None, _('list the filename')),
212 ('f', 'file', None, _('list the filename')),
213 ('d', 'date', None, _('list the date (short with -q)')),
213 ('d', 'date', None, _('list the date (short with -q)')),
214 ('n', 'number', None, _('list the revision number (default)')),
214 ('n', 'number', None, _('list the revision number (default)')),
215 ('c', 'changeset', None, _('list the changeset')),
215 ('c', 'changeset', None, _('list the changeset')),
216 ('l', 'line-number', None, _('show line number at the first appearance'))
216 ('l', 'line-number', None, _('show line number at the first appearance'))
217 ] + walkopts,
217 ] + walkopts,
218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
219 def annotate(ui, repo, *pats, **opts):
219 def annotate(ui, repo, *pats, **opts):
220 """show changeset information by line for each file
220 """show changeset information by line for each file
221
221
222 List changes in files, showing the revision id responsible for
222 List changes in files, showing the revision id responsible for
223 each line
223 each line
224
224
225 This command is useful for discovering when a change was made and
225 This command is useful for discovering when a change was made and
226 by whom.
226 by whom.
227
227
228 Without the -a/--text option, annotate will avoid processing files
228 Without the -a/--text option, annotate will avoid processing files
229 it detects as binary. With -a, annotate will annotate the file
229 it detects as binary. With -a, annotate will annotate the file
230 anyway, although the results will probably be neither useful
230 anyway, although the results will probably be neither useful
231 nor desirable.
231 nor desirable.
232
232
233 Returns 0 on success.
233 Returns 0 on success.
234 """
234 """
235 if opts.get('follow'):
235 if opts.get('follow'):
236 # --follow is deprecated and now just an alias for -f/--file
236 # --follow is deprecated and now just an alias for -f/--file
237 # to mimic the behavior of Mercurial before version 1.5
237 # to mimic the behavior of Mercurial before version 1.5
238 opts['file'] = True
238 opts['file'] = True
239
239
240 datefunc = ui.quiet and util.shortdate or util.datestr
240 datefunc = ui.quiet and util.shortdate or util.datestr
241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
242
242
243 if not pats:
243 if not pats:
244 raise util.Abort(_('at least one filename or pattern is required'))
244 raise util.Abort(_('at least one filename or pattern is required'))
245
245
246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
247 ('number', ' ', lambda x: str(x[0].rev())),
247 ('number', ' ', lambda x: str(x[0].rev())),
248 ('changeset', ' ', lambda x: short(x[0].node())),
248 ('changeset', ' ', lambda x: short(x[0].node())),
249 ('date', ' ', getdate),
249 ('date', ' ', getdate),
250 ('file', ' ', lambda x: x[0].path()),
250 ('file', ' ', lambda x: x[0].path()),
251 ('line_number', ':', lambda x: str(x[1])),
251 ('line_number', ':', lambda x: str(x[1])),
252 ]
252 ]
253
253
254 if (not opts.get('user') and not opts.get('changeset')
254 if (not opts.get('user') and not opts.get('changeset')
255 and not opts.get('date') and not opts.get('file')):
255 and not opts.get('date') and not opts.get('file')):
256 opts['number'] = True
256 opts['number'] = True
257
257
258 linenumber = opts.get('line_number') is not None
258 linenumber = opts.get('line_number') is not None
259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
260 raise util.Abort(_('at least one of -n/-c is required for -l'))
260 raise util.Abort(_('at least one of -n/-c is required for -l'))
261
261
262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
264
264
265 def bad(x, y):
265 def bad(x, y):
266 raise util.Abort("%s: %s" % (x, y))
266 raise util.Abort("%s: %s" % (x, y))
267
267
268 ctx = scmutil.revsingle(repo, opts.get('rev'))
268 ctx = scmutil.revsingle(repo, opts.get('rev'))
269 m = scmutil.match(ctx, pats, opts)
269 m = scmutil.match(ctx, pats, opts)
270 m.bad = bad
270 m.bad = bad
271 follow = not opts.get('no_follow')
271 follow = not opts.get('no_follow')
272 for abs in ctx.walk(m):
272 for abs in ctx.walk(m):
273 fctx = ctx[abs]
273 fctx = ctx[abs]
274 if not opts.get('text') and util.binary(fctx.data()):
274 if not opts.get('text') and util.binary(fctx.data()):
275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
276 continue
276 continue
277
277
278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
279 pieces = []
279 pieces = []
280
280
281 for f, sep in funcmap:
281 for f, sep in funcmap:
282 l = [f(n) for n, dummy in lines]
282 l = [f(n) for n, dummy in lines]
283 if l:
283 if l:
284 sized = [(x, encoding.colwidth(x)) for x in l]
284 sized = [(x, encoding.colwidth(x)) for x in l]
285 ml = max([w for x, w in sized])
285 ml = max([w for x, w in sized])
286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
287 for x, w in sized])
287 for x, w in sized])
288
288
289 if pieces:
289 if pieces:
290 for p, l in zip(zip(*pieces), lines):
290 for p, l in zip(zip(*pieces), lines):
291 ui.write("%s: %s" % ("".join(p), l[1]))
291 ui.write("%s: %s" % ("".join(p), l[1]))
292
292
293 @command('archive',
293 @command('archive',
294 [('', 'no-decode', None, _('do not pass files through decoders')),
294 [('', 'no-decode', None, _('do not pass files through decoders')),
295 ('p', 'prefix', '', _('directory prefix for files in archive'),
295 ('p', 'prefix', '', _('directory prefix for files in archive'),
296 _('PREFIX')),
296 _('PREFIX')),
297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
299 ] + subrepoopts + walkopts,
299 ] + subrepoopts + walkopts,
300 _('[OPTION]... DEST'))
300 _('[OPTION]... DEST'))
301 def archive(ui, repo, dest, **opts):
301 def archive(ui, repo, dest, **opts):
302 '''create an unversioned archive of a repository revision
302 '''create an unversioned archive of a repository revision
303
303
304 By default, the revision used is the parent of the working
304 By default, the revision used is the parent of the working
305 directory; use -r/--rev to specify a different revision.
305 directory; use -r/--rev to specify a different revision.
306
306
307 The archive type is automatically detected based on file
307 The archive type is automatically detected based on file
308 extension (or override using -t/--type).
308 extension (or override using -t/--type).
309
309
310 .. container:: verbose
310 .. container:: verbose
311
311
312 Examples:
312 Examples:
313
313
314 - create a zip file containing the 1.0 release::
314 - create a zip file containing the 1.0 release::
315
315
316 hg archive -r 1.0 project-1.0.zip
316 hg archive -r 1.0 project-1.0.zip
317
317
318 - create a tarball excluding .hg files::
318 - create a tarball excluding .hg files::
319
319
320 hg archive project.tar.gz -X ".hg*"
320 hg archive project.tar.gz -X ".hg*"
321
321
322 Valid types are:
322 Valid types are:
323
323
324 :``files``: a directory full of files (default)
324 :``files``: a directory full of files (default)
325 :``tar``: tar archive, uncompressed
325 :``tar``: tar archive, uncompressed
326 :``tbz2``: tar archive, compressed using bzip2
326 :``tbz2``: tar archive, compressed using bzip2
327 :``tgz``: tar archive, compressed using gzip
327 :``tgz``: tar archive, compressed using gzip
328 :``uzip``: zip archive, uncompressed
328 :``uzip``: zip archive, uncompressed
329 :``zip``: zip archive, compressed using deflate
329 :``zip``: zip archive, compressed using deflate
330
330
331 The exact name of the destination archive or directory is given
331 The exact name of the destination archive or directory is given
332 using a format string; see :hg:`help export` for details.
332 using a format string; see :hg:`help export` for details.
333
333
334 Each member added to an archive file has a directory prefix
334 Each member added to an archive file has a directory prefix
335 prepended. Use -p/--prefix to specify a format string for the
335 prepended. Use -p/--prefix to specify a format string for the
336 prefix. The default is the basename of the archive, with suffixes
336 prefix. The default is the basename of the archive, with suffixes
337 removed.
337 removed.
338
338
339 Returns 0 on success.
339 Returns 0 on success.
340 '''
340 '''
341
341
342 ctx = scmutil.revsingle(repo, opts.get('rev'))
342 ctx = scmutil.revsingle(repo, opts.get('rev'))
343 if not ctx:
343 if not ctx:
344 raise util.Abort(_('no working directory: please specify a revision'))
344 raise util.Abort(_('no working directory: please specify a revision'))
345 node = ctx.node()
345 node = ctx.node()
346 dest = cmdutil.makefilename(repo, dest, node)
346 dest = cmdutil.makefilename(repo, dest, node)
347 if os.path.realpath(dest) == repo.root:
347 if os.path.realpath(dest) == repo.root:
348 raise util.Abort(_('repository root cannot be destination'))
348 raise util.Abort(_('repository root cannot be destination'))
349
349
350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
351 prefix = opts.get('prefix')
351 prefix = opts.get('prefix')
352
352
353 if dest == '-':
353 if dest == '-':
354 if kind == 'files':
354 if kind == 'files':
355 raise util.Abort(_('cannot archive plain files to stdout'))
355 raise util.Abort(_('cannot archive plain files to stdout'))
356 dest = cmdutil.makefileobj(repo, dest)
356 dest = cmdutil.makefileobj(repo, dest)
357 if not prefix:
357 if not prefix:
358 prefix = os.path.basename(repo.root) + '-%h'
358 prefix = os.path.basename(repo.root) + '-%h'
359
359
360 prefix = cmdutil.makefilename(repo, prefix, node)
360 prefix = cmdutil.makefilename(repo, prefix, node)
361 matchfn = scmutil.match(ctx, [], opts)
361 matchfn = scmutil.match(ctx, [], opts)
362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
363 matchfn, prefix, subrepos=opts.get('subrepos'))
363 matchfn, prefix, subrepos=opts.get('subrepos'))
364
364
365 @command('backout',
365 @command('backout',
366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
367 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
367 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
368 ('r', 'rev', '', _('revision to backout'), _('REV')),
368 ('r', 'rev', '', _('revision to backout'), _('REV')),
369 ] + mergetoolopts + walkopts + commitopts + commitopts2,
369 ] + mergetoolopts + walkopts + commitopts + commitopts2,
370 _('[OPTION]... [-r] REV'))
370 _('[OPTION]... [-r] REV'))
371 def backout(ui, repo, node=None, rev=None, **opts):
371 def backout(ui, repo, node=None, rev=None, **opts):
372 '''reverse effect of earlier changeset
372 '''reverse effect of earlier changeset
373
373
374 Prepare a new changeset with the effect of REV undone in the
374 Prepare a new changeset with the effect of REV undone in the
375 current working directory.
375 current working directory.
376
376
377 If REV is the parent of the working directory, then this new changeset
377 If REV is the parent of the working directory, then this new changeset
378 is committed automatically. Otherwise, hg needs to merge the
378 is committed automatically. Otherwise, hg needs to merge the
379 changes and the merged result is left uncommitted.
379 changes and the merged result is left uncommitted.
380
380
381 By default, the pending changeset will have one parent,
381 By default, the pending changeset will have one parent,
382 maintaining a linear history. With --merge, the pending changeset
382 maintaining a linear history. With --merge, the pending changeset
383 will instead have two parents: the old parent of the working
383 will instead have two parents: the old parent of the working
384 directory and a new child of REV that simply undoes REV.
384 directory and a new child of REV that simply undoes REV.
385
385
386 Before version 1.7, the behavior without --merge was equivalent to
386 Before version 1.7, the behavior without --merge was equivalent to
387 specifying --merge followed by :hg:`update --clean .` to cancel
387 specifying --merge followed by :hg:`update --clean .` to cancel
388 the merge and leave the child of REV as a head to be merged
388 the merge and leave the child of REV as a head to be merged
389 separately.
389 separately.
390
390
391 See :hg:`help dates` for a list of formats valid for -d/--date.
391 See :hg:`help dates` for a list of formats valid for -d/--date.
392
392
393 Returns 0 on success.
393 Returns 0 on success.
394 '''
394 '''
395 if rev and node:
395 if rev and node:
396 raise util.Abort(_("please specify just one revision"))
396 raise util.Abort(_("please specify just one revision"))
397
397
398 if not rev:
398 if not rev:
399 rev = node
399 rev = node
400
400
401 if not rev:
401 if not rev:
402 raise util.Abort(_("please specify a revision to backout"))
402 raise util.Abort(_("please specify a revision to backout"))
403
403
404 date = opts.get('date')
404 date = opts.get('date')
405 if date:
405 if date:
406 opts['date'] = util.parsedate(date)
406 opts['date'] = util.parsedate(date)
407
407
408 cmdutil.bailifchanged(repo)
408 cmdutil.bailifchanged(repo)
409 node = scmutil.revsingle(repo, rev).node()
409 node = scmutil.revsingle(repo, rev).node()
410
410
411 op1, op2 = repo.dirstate.parents()
411 op1, op2 = repo.dirstate.parents()
412 a = repo.changelog.ancestor(op1, node)
412 a = repo.changelog.ancestor(op1, node)
413 if a != node:
413 if a != node:
414 raise util.Abort(_('cannot backout change on a different branch'))
414 raise util.Abort(_('cannot backout change on a different branch'))
415
415
416 p1, p2 = repo.changelog.parents(node)
416 p1, p2 = repo.changelog.parents(node)
417 if p1 == nullid:
417 if p1 == nullid:
418 raise util.Abort(_('cannot backout a change with no parents'))
418 raise util.Abort(_('cannot backout a change with no parents'))
419 if p2 != nullid:
419 if p2 != nullid:
420 if not opts.get('parent'):
420 if not opts.get('parent'):
421 raise util.Abort(_('cannot backout a merge changeset without '
421 raise util.Abort(_('cannot backout a merge changeset without '
422 '--parent'))
422 '--parent'))
423 p = repo.lookup(opts['parent'])
423 p = repo.lookup(opts['parent'])
424 if p not in (p1, p2):
424 if p not in (p1, p2):
425 raise util.Abort(_('%s is not a parent of %s') %
425 raise util.Abort(_('%s is not a parent of %s') %
426 (short(p), short(node)))
426 (short(p), short(node)))
427 parent = p
427 parent = p
428 else:
428 else:
429 if opts.get('parent'):
429 if opts.get('parent'):
430 raise util.Abort(_('cannot use --parent on non-merge changeset'))
430 raise util.Abort(_('cannot use --parent on non-merge changeset'))
431 parent = p1
431 parent = p1
432
432
433 # the backout should appear on the same branch
433 # the backout should appear on the same branch
434 branch = repo.dirstate.branch()
434 branch = repo.dirstate.branch()
435 hg.clean(repo, node, show_stats=False)
435 hg.clean(repo, node, show_stats=False)
436 repo.dirstate.setbranch(branch)
436 repo.dirstate.setbranch(branch)
437 revert_opts = opts.copy()
437 revert_opts = opts.copy()
438 revert_opts['date'] = None
438 revert_opts['date'] = None
439 revert_opts['all'] = True
439 revert_opts['all'] = True
440 revert_opts['rev'] = hex(parent)
440 revert_opts['rev'] = hex(parent)
441 revert_opts['no_backup'] = None
441 revert_opts['no_backup'] = None
442 revert(ui, repo, **revert_opts)
442 revert(ui, repo, **revert_opts)
443 if not opts.get('merge') and op1 != node:
443 if not opts.get('merge') and op1 != node:
444 try:
444 try:
445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
446 return hg.update(repo, op1)
446 return hg.update(repo, op1)
447 finally:
447 finally:
448 ui.setconfig('ui', 'forcemerge', '')
448 ui.setconfig('ui', 'forcemerge', '')
449
449
450 commit_opts = opts.copy()
450 commit_opts = opts.copy()
451 commit_opts['addremove'] = False
451 commit_opts['addremove'] = False
452 if not commit_opts['message'] and not commit_opts['logfile']:
452 if not commit_opts['message'] and not commit_opts['logfile']:
453 # we don't translate commit messages
453 # we don't translate commit messages
454 commit_opts['message'] = "Backed out changeset %s" % short(node)
454 commit_opts['message'] = "Backed out changeset %s" % short(node)
455 commit_opts['force_editor'] = True
455 commit_opts['force_editor'] = True
456 commit(ui, repo, **commit_opts)
456 commit(ui, repo, **commit_opts)
457 def nice(node):
457 def nice(node):
458 return '%d:%s' % (repo.changelog.rev(node), short(node))
458 return '%d:%s' % (repo.changelog.rev(node), short(node))
459 ui.status(_('changeset %s backs out changeset %s\n') %
459 ui.status(_('changeset %s backs out changeset %s\n') %
460 (nice(repo.changelog.tip()), nice(node)))
460 (nice(repo.changelog.tip()), nice(node)))
461 if opts.get('merge') and op1 != node:
461 if opts.get('merge') and op1 != node:
462 hg.clean(repo, op1, show_stats=False)
462 hg.clean(repo, op1, show_stats=False)
463 ui.status(_('merging with changeset %s\n')
463 ui.status(_('merging with changeset %s\n')
464 % nice(repo.changelog.tip()))
464 % nice(repo.changelog.tip()))
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.merge(repo, hex(repo.changelog.tip()))
467 return hg.merge(repo, hex(repo.changelog.tip()))
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470 return 0
470 return 0
471
471
472 @command('bisect',
472 @command('bisect',
473 [('r', 'reset', False, _('reset bisect state')),
473 [('r', 'reset', False, _('reset bisect state')),
474 ('g', 'good', False, _('mark changeset good')),
474 ('g', 'good', False, _('mark changeset good')),
475 ('b', 'bad', False, _('mark changeset bad')),
475 ('b', 'bad', False, _('mark changeset bad')),
476 ('s', 'skip', False, _('skip testing changeset')),
476 ('s', 'skip', False, _('skip testing changeset')),
477 ('e', 'extend', False, _('extend the bisect range')),
477 ('e', 'extend', False, _('extend the bisect range')),
478 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
478 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
479 ('U', 'noupdate', False, _('do not update to target'))],
479 ('U', 'noupdate', False, _('do not update to target'))],
480 _("[-gbsr] [-U] [-c CMD] [REV]"))
480 _("[-gbsr] [-U] [-c CMD] [REV]"))
481 def bisect(ui, repo, rev=None, extra=None, command=None,
481 def bisect(ui, repo, rev=None, extra=None, command=None,
482 reset=None, good=None, bad=None, skip=None, extend=None,
482 reset=None, good=None, bad=None, skip=None, extend=None,
483 noupdate=None):
483 noupdate=None):
484 """subdivision search of changesets
484 """subdivision search of changesets
485
485
486 This command helps to find changesets which introduce problems. To
486 This command helps to find changesets which introduce problems. To
487 use, mark the earliest changeset you know exhibits the problem as
487 use, mark the earliest changeset you know exhibits the problem as
488 bad, then mark the latest changeset which is free from the problem
488 bad, then mark the latest changeset which is free from the problem
489 as good. Bisect will update your working directory to a revision
489 as good. Bisect will update your working directory to a revision
490 for testing (unless the -U/--noupdate option is specified). Once
490 for testing (unless the -U/--noupdate option is specified). Once
491 you have performed tests, mark the working directory as good or
491 you have performed tests, mark the working directory as good or
492 bad, and bisect will either update to another candidate changeset
492 bad, and bisect will either update to another candidate changeset
493 or announce that it has found the bad revision.
493 or announce that it has found the bad revision.
494
494
495 As a shortcut, you can also use the revision argument to mark a
495 As a shortcut, you can also use the revision argument to mark a
496 revision as good or bad without checking it out first.
496 revision as good or bad without checking it out first.
497
497
498 If you supply a command, it will be used for automatic bisection.
498 If you supply a command, it will be used for automatic bisection.
499 Its exit status will be used to mark revisions as good or bad:
499 Its exit status will be used to mark revisions as good or bad:
500 status 0 means good, 125 means to skip the revision, 127
500 status 0 means good, 125 means to skip the revision, 127
501 (command not found) will abort the bisection, and any other
501 (command not found) will abort the bisection, and any other
502 non-zero exit status means the revision is bad.
502 non-zero exit status means the revision is bad.
503
503
504 Returns 0 on success.
504 Returns 0 on success.
505 """
505 """
506 def extendbisectrange(nodes, good):
506 def extendbisectrange(nodes, good):
507 # bisect is incomplete when it ends on a merge node and
507 # bisect is incomplete when it ends on a merge node and
508 # one of the parent was not checked.
508 # one of the parent was not checked.
509 parents = repo[nodes[0]].parents()
509 parents = repo[nodes[0]].parents()
510 if len(parents) > 1:
510 if len(parents) > 1:
511 side = good and state['bad'] or state['good']
511 side = good and state['bad'] or state['good']
512 num = len(set(i.node() for i in parents) & set(side))
512 num = len(set(i.node() for i in parents) & set(side))
513 if num == 1:
513 if num == 1:
514 return parents[0].ancestor(parents[1])
514 return parents[0].ancestor(parents[1])
515 return None
515 return None
516
516
517 def print_result(nodes, good):
517 def print_result(nodes, good):
518 displayer = cmdutil.show_changeset(ui, repo, {})
518 displayer = cmdutil.show_changeset(ui, repo, {})
519 if len(nodes) == 1:
519 if len(nodes) == 1:
520 # narrowed it down to a single revision
520 # narrowed it down to a single revision
521 if good:
521 if good:
522 ui.write(_("The first good revision is:\n"))
522 ui.write(_("The first good revision is:\n"))
523 else:
523 else:
524 ui.write(_("The first bad revision is:\n"))
524 ui.write(_("The first bad revision is:\n"))
525 displayer.show(repo[nodes[0]])
525 displayer.show(repo[nodes[0]])
526 extendnode = extendbisectrange(nodes, good)
526 extendnode = extendbisectrange(nodes, good)
527 if extendnode is not None:
527 if extendnode is not None:
528 ui.write(_('Not all ancestors of this changeset have been'
528 ui.write(_('Not all ancestors of this changeset have been'
529 ' checked.\nUse bisect --extend to continue the '
529 ' checked.\nUse bisect --extend to continue the '
530 'bisection from\nthe common ancestor, %s.\n')
530 'bisection from\nthe common ancestor, %s.\n')
531 % extendnode)
531 % extendnode)
532 else:
532 else:
533 # multiple possible revisions
533 # multiple possible revisions
534 if good:
534 if good:
535 ui.write(_("Due to skipped revisions, the first "
535 ui.write(_("Due to skipped revisions, the first "
536 "good revision could be any of:\n"))
536 "good revision could be any of:\n"))
537 else:
537 else:
538 ui.write(_("Due to skipped revisions, the first "
538 ui.write(_("Due to skipped revisions, the first "
539 "bad revision could be any of:\n"))
539 "bad revision could be any of:\n"))
540 for n in nodes:
540 for n in nodes:
541 displayer.show(repo[n])
541 displayer.show(repo[n])
542 displayer.close()
542 displayer.close()
543
543
544 def check_state(state, interactive=True):
544 def check_state(state, interactive=True):
545 if not state['good'] or not state['bad']:
545 if not state['good'] or not state['bad']:
546 if (good or bad or skip or reset) and interactive:
546 if (good or bad or skip or reset) and interactive:
547 return
547 return
548 if not state['good']:
548 if not state['good']:
549 raise util.Abort(_('cannot bisect (no known good revisions)'))
549 raise util.Abort(_('cannot bisect (no known good revisions)'))
550 else:
550 else:
551 raise util.Abort(_('cannot bisect (no known bad revisions)'))
551 raise util.Abort(_('cannot bisect (no known bad revisions)'))
552 return True
552 return True
553
553
554 # backward compatibility
554 # backward compatibility
555 if rev in "good bad reset init".split():
555 if rev in "good bad reset init".split():
556 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
556 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
557 cmd, rev, extra = rev, extra, None
557 cmd, rev, extra = rev, extra, None
558 if cmd == "good":
558 if cmd == "good":
559 good = True
559 good = True
560 elif cmd == "bad":
560 elif cmd == "bad":
561 bad = True
561 bad = True
562 else:
562 else:
563 reset = True
563 reset = True
564 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
564 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
565 raise util.Abort(_('incompatible arguments'))
565 raise util.Abort(_('incompatible arguments'))
566
566
567 if reset:
567 if reset:
568 p = repo.join("bisect.state")
568 p = repo.join("bisect.state")
569 if os.path.exists(p):
569 if os.path.exists(p):
570 os.unlink(p)
570 os.unlink(p)
571 return
571 return
572
572
573 state = hbisect.load_state(repo)
573 state = hbisect.load_state(repo)
574
574
575 if command:
575 if command:
576 changesets = 1
576 changesets = 1
577 try:
577 try:
578 while changesets:
578 while changesets:
579 # update state
579 # update state
580 status = util.system(command, out=ui.fout)
580 status = util.system(command, out=ui.fout)
581 if status == 125:
581 if status == 125:
582 transition = "skip"
582 transition = "skip"
583 elif status == 0:
583 elif status == 0:
584 transition = "good"
584 transition = "good"
585 # status < 0 means process was killed
585 # status < 0 means process was killed
586 elif status == 127:
586 elif status == 127:
587 raise util.Abort(_("failed to execute %s") % command)
587 raise util.Abort(_("failed to execute %s") % command)
588 elif status < 0:
588 elif status < 0:
589 raise util.Abort(_("%s killed") % command)
589 raise util.Abort(_("%s killed") % command)
590 else:
590 else:
591 transition = "bad"
591 transition = "bad"
592 ctx = scmutil.revsingle(repo, rev)
592 ctx = scmutil.revsingle(repo, rev)
593 rev = None # clear for future iterations
593 rev = None # clear for future iterations
594 state[transition].append(ctx.node())
594 state[transition].append(ctx.node())
595 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
595 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
596 check_state(state, interactive=False)
596 check_state(state, interactive=False)
597 # bisect
597 # bisect
598 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
598 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
599 # update to next check
599 # update to next check
600 cmdutil.bailifchanged(repo)
600 cmdutil.bailifchanged(repo)
601 hg.clean(repo, nodes[0], show_stats=False)
601 hg.clean(repo, nodes[0], show_stats=False)
602 finally:
602 finally:
603 hbisect.save_state(repo, state)
603 hbisect.save_state(repo, state)
604 print_result(nodes, good)
604 print_result(nodes, good)
605 return
605 return
606
606
607 # update state
607 # update state
608
608
609 if rev:
609 if rev:
610 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
610 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
611 else:
611 else:
612 nodes = [repo.lookup('.')]
612 nodes = [repo.lookup('.')]
613
613
614 if good or bad or skip:
614 if good or bad or skip:
615 if good:
615 if good:
616 state['good'] += nodes
616 state['good'] += nodes
617 elif bad:
617 elif bad:
618 state['bad'] += nodes
618 state['bad'] += nodes
619 elif skip:
619 elif skip:
620 state['skip'] += nodes
620 state['skip'] += nodes
621 hbisect.save_state(repo, state)
621 hbisect.save_state(repo, state)
622
622
623 if not check_state(state):
623 if not check_state(state):
624 return
624 return
625
625
626 # actually bisect
626 # actually bisect
627 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
627 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
628 if extend:
628 if extend:
629 if not changesets:
629 if not changesets:
630 extendnode = extendbisectrange(nodes, good)
630 extendnode = extendbisectrange(nodes, good)
631 if extendnode is not None:
631 if extendnode is not None:
632 ui.write(_("Extending search to changeset %d:%s\n"
632 ui.write(_("Extending search to changeset %d:%s\n"
633 % (extendnode.rev(), extendnode)))
633 % (extendnode.rev(), extendnode)))
634 if noupdate:
634 if noupdate:
635 return
635 return
636 cmdutil.bailifchanged(repo)
636 cmdutil.bailifchanged(repo)
637 return hg.clean(repo, extendnode.node())
637 return hg.clean(repo, extendnode.node())
638 raise util.Abort(_("nothing to extend"))
638 raise util.Abort(_("nothing to extend"))
639
639
640 if changesets == 0:
640 if changesets == 0:
641 print_result(nodes, good)
641 print_result(nodes, good)
642 else:
642 else:
643 assert len(nodes) == 1 # only a single node can be tested next
643 assert len(nodes) == 1 # only a single node can be tested next
644 node = nodes[0]
644 node = nodes[0]
645 # compute the approximate number of remaining tests
645 # compute the approximate number of remaining tests
646 tests, size = 0, 2
646 tests, size = 0, 2
647 while size <= changesets:
647 while size <= changesets:
648 tests, size = tests + 1, size * 2
648 tests, size = tests + 1, size * 2
649 rev = repo.changelog.rev(node)
649 rev = repo.changelog.rev(node)
650 ui.write(_("Testing changeset %d:%s "
650 ui.write(_("Testing changeset %d:%s "
651 "(%d changesets remaining, ~%d tests)\n")
651 "(%d changesets remaining, ~%d tests)\n")
652 % (rev, short(node), changesets, tests))
652 % (rev, short(node), changesets, tests))
653 if not noupdate:
653 if not noupdate:
654 cmdutil.bailifchanged(repo)
654 cmdutil.bailifchanged(repo)
655 return hg.clean(repo, node)
655 return hg.clean(repo, node)
656
656
657 @command('bookmarks',
657 @command('bookmarks',
658 [('f', 'force', False, _('force')),
658 [('f', 'force', False, _('force')),
659 ('r', 'rev', '', _('revision'), _('REV')),
659 ('r', 'rev', '', _('revision'), _('REV')),
660 ('d', 'delete', False, _('delete a given bookmark')),
660 ('d', 'delete', False, _('delete a given bookmark')),
661 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
661 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
662 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
662 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
663 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
663 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
664 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
664 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
665 rename=None, inactive=False):
665 rename=None, inactive=False):
666 '''track a line of development with movable markers
666 '''track a line of development with movable markers
667
667
668 Bookmarks are pointers to certain commits that move when
668 Bookmarks are pointers to certain commits that move when
669 committing. Bookmarks are local. They can be renamed, copied and
669 committing. Bookmarks are local. They can be renamed, copied and
670 deleted. It is possible to use bookmark names in :hg:`merge` and
670 deleted. It is possible to use bookmark names in :hg:`merge` and
671 :hg:`update` to merge and update respectively to a given bookmark.
671 :hg:`update` to merge and update respectively to a given bookmark.
672
672
673 You can use :hg:`bookmark NAME` to set a bookmark on the working
673 You can use :hg:`bookmark NAME` to set a bookmark on the working
674 directory's parent revision with the given name. If you specify
674 directory's parent revision with the given name. If you specify
675 a revision using -r REV (where REV may be an existing bookmark),
675 a revision using -r REV (where REV may be an existing bookmark),
676 the bookmark is assigned to that revision.
676 the bookmark is assigned to that revision.
677
677
678 Bookmarks can be pushed and pulled between repositories (see :hg:`help
678 Bookmarks can be pushed and pulled between repositories (see :hg:`help
679 push` and :hg:`help pull`). This requires both the local and remote
679 push` and :hg:`help pull`). This requires both the local and remote
680 repositories to support bookmarks. For versions prior to 1.8, this means
680 repositories to support bookmarks. For versions prior to 1.8, this means
681 the bookmarks extension must be enabled.
681 the bookmarks extension must be enabled.
682 '''
682 '''
683 hexfn = ui.debugflag and hex or short
683 hexfn = ui.debugflag and hex or short
684 marks = repo._bookmarks
684 marks = repo._bookmarks
685 cur = repo.changectx('.').node()
685 cur = repo.changectx('.').node()
686
686
687 if rename:
687 if rename:
688 if rename not in marks:
688 if rename not in marks:
689 raise util.Abort(_("bookmark '%s' does not exist") % rename)
689 raise util.Abort(_("bookmark '%s' does not exist") % rename)
690 if mark in marks and not force:
690 if mark in marks and not force:
691 raise util.Abort(_("bookmark '%s' already exists "
691 raise util.Abort(_("bookmark '%s' already exists "
692 "(use -f to force)") % mark)
692 "(use -f to force)") % mark)
693 if mark is None:
693 if mark is None:
694 raise util.Abort(_("new bookmark name required"))
694 raise util.Abort(_("new bookmark name required"))
695 marks[mark] = marks[rename]
695 marks[mark] = marks[rename]
696 if repo._bookmarkcurrent == rename and not inactive:
696 if repo._bookmarkcurrent == rename and not inactive:
697 bookmarks.setcurrent(repo, mark)
697 bookmarks.setcurrent(repo, mark)
698 del marks[rename]
698 del marks[rename]
699 bookmarks.write(repo)
699 bookmarks.write(repo)
700 return
700 return
701
701
702 if delete:
702 if delete:
703 if mark is None:
703 if mark is None:
704 raise util.Abort(_("bookmark name required"))
704 raise util.Abort(_("bookmark name required"))
705 if mark not in marks:
705 if mark not in marks:
706 raise util.Abort(_("bookmark '%s' does not exist") % mark)
706 raise util.Abort(_("bookmark '%s' does not exist") % mark)
707 if mark == repo._bookmarkcurrent:
707 if mark == repo._bookmarkcurrent:
708 bookmarks.setcurrent(repo, None)
708 bookmarks.setcurrent(repo, None)
709 del marks[mark]
709 del marks[mark]
710 bookmarks.write(repo)
710 bookmarks.write(repo)
711 return
711 return
712
712
713 if mark is not None:
713 if mark is not None:
714 if "\n" in mark:
714 if "\n" in mark:
715 raise util.Abort(_("bookmark name cannot contain newlines"))
715 raise util.Abort(_("bookmark name cannot contain newlines"))
716 mark = mark.strip()
716 mark = mark.strip()
717 if not mark:
717 if not mark:
718 raise util.Abort(_("bookmark names cannot consist entirely of "
718 raise util.Abort(_("bookmark names cannot consist entirely of "
719 "whitespace"))
719 "whitespace"))
720 if inactive and mark == repo._bookmarkcurrent:
720 if inactive and mark == repo._bookmarkcurrent:
721 bookmarks.setcurrent(repo, None)
721 bookmarks.setcurrent(repo, None)
722 return
722 return
723 if mark in marks and not force:
723 if mark in marks and not force:
724 raise util.Abort(_("bookmark '%s' already exists "
724 raise util.Abort(_("bookmark '%s' already exists "
725 "(use -f to force)") % mark)
725 "(use -f to force)") % mark)
726 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
726 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
727 and not force):
727 and not force):
728 raise util.Abort(
728 raise util.Abort(
729 _("a bookmark cannot have the name of an existing branch"))
729 _("a bookmark cannot have the name of an existing branch"))
730 if rev:
730 if rev:
731 marks[mark] = repo.lookup(rev)
731 marks[mark] = repo.lookup(rev)
732 else:
732 else:
733 marks[mark] = repo.changectx('.').node()
733 marks[mark] = repo.changectx('.').node()
734 if not inactive and repo.changectx('.').node() == marks[mark]:
734 if not inactive and repo.changectx('.').node() == marks[mark]:
735 bookmarks.setcurrent(repo, mark)
735 bookmarks.setcurrent(repo, mark)
736 bookmarks.write(repo)
736 bookmarks.write(repo)
737 return
737 return
738
738
739 if mark is None:
739 if mark is None:
740 if rev:
740 if rev:
741 raise util.Abort(_("bookmark name required"))
741 raise util.Abort(_("bookmark name required"))
742 if len(marks) == 0:
742 if len(marks) == 0:
743 ui.status(_("no bookmarks set\n"))
743 ui.status(_("no bookmarks set\n"))
744 else:
744 else:
745 for bmark, n in sorted(marks.iteritems()):
745 for bmark, n in sorted(marks.iteritems()):
746 current = repo._bookmarkcurrent
746 current = repo._bookmarkcurrent
747 if bmark == current and n == cur:
747 if bmark == current and n == cur:
748 prefix, label = '*', 'bookmarks.current'
748 prefix, label = '*', 'bookmarks.current'
749 else:
749 else:
750 prefix, label = ' ', ''
750 prefix, label = ' ', ''
751
751
752 if ui.quiet:
752 if ui.quiet:
753 ui.write("%s\n" % bmark, label=label)
753 ui.write("%s\n" % bmark, label=label)
754 else:
754 else:
755 ui.write(" %s %-25s %d:%s\n" % (
755 ui.write(" %s %-25s %d:%s\n" % (
756 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
756 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
757 label=label)
757 label=label)
758 return
758 return
759
759
760 @command('branch',
760 @command('branch',
761 [('f', 'force', None,
761 [('f', 'force', None,
762 _('set branch name even if it shadows an existing branch')),
762 _('set branch name even if it shadows an existing branch')),
763 ('C', 'clean', None, _('reset branch name to parent branch name'))],
763 ('C', 'clean', None, _('reset branch name to parent branch name'))],
764 _('[-fC] [NAME]'))
764 _('[-fC] [NAME]'))
765 def branch(ui, repo, label=None, **opts):
765 def branch(ui, repo, label=None, **opts):
766 """set or show the current branch name
766 """set or show the current branch name
767
767
768 With no argument, show the current branch name. With one argument,
768 With no argument, show the current branch name. With one argument,
769 set the working directory branch name (the branch will not exist
769 set the working directory branch name (the branch will not exist
770 in the repository until the next commit). Standard practice
770 in the repository until the next commit). Standard practice
771 recommends that primary development take place on the 'default'
771 recommends that primary development take place on the 'default'
772 branch.
772 branch.
773
773
774 Unless -f/--force is specified, branch will not let you set a
774 Unless -f/--force is specified, branch will not let you set a
775 branch name that already exists, even if it's inactive.
775 branch name that already exists, even if it's inactive.
776
776
777 Use -C/--clean to reset the working directory branch to that of
777 Use -C/--clean to reset the working directory branch to that of
778 the parent of the working directory, negating a previous branch
778 the parent of the working directory, negating a previous branch
779 change.
779 change.
780
780
781 Use the command :hg:`update` to switch to an existing branch. Use
781 Use the command :hg:`update` to switch to an existing branch. Use
782 :hg:`commit --close-branch` to mark this branch as closed.
782 :hg:`commit --close-branch` to mark this branch as closed.
783
783
784 .. note::
784 .. note::
785
785
786 Branch names are permanent. Use :hg:`bookmark` to create a
786 Branch names are permanent. Use :hg:`bookmark` to create a
787 light-weight bookmark instead. See :hg:`help glossary` for more
787 light-weight bookmark instead. See :hg:`help glossary` for more
788 information about named branches and bookmarks.
788 information about named branches and bookmarks.
789
789
790 Returns 0 on success.
790 Returns 0 on success.
791 """
791 """
792
792
793 if opts.get('clean'):
793 if opts.get('clean'):
794 label = repo[None].p1().branch()
794 label = repo[None].p1().branch()
795 repo.dirstate.setbranch(label)
795 repo.dirstate.setbranch(label)
796 ui.status(_('reset working directory to branch %s\n') % label)
796 ui.status(_('reset working directory to branch %s\n') % label)
797 elif label:
797 elif label:
798 if not opts.get('force') and label in repo.branchtags():
798 if not opts.get('force') and label in repo.branchtags():
799 if label not in [p.branch() for p in repo.parents()]:
799 if label not in [p.branch() for p in repo.parents()]:
800 raise util.Abort(_('a branch of the same name already exists'),
800 raise util.Abort(_('a branch of the same name already exists'),
801 # i18n: "it" refers to an existing branch
801 # i18n: "it" refers to an existing branch
802 hint=_("use 'hg update' to switch to it"))
802 hint=_("use 'hg update' to switch to it"))
803 repo.dirstate.setbranch(label)
803 repo.dirstate.setbranch(label)
804 ui.status(_('marked working directory as branch %s\n') % label)
804 ui.status(_('marked working directory as branch %s\n') % label)
805 else:
805 else:
806 ui.write("%s\n" % repo.dirstate.branch())
806 ui.write("%s\n" % repo.dirstate.branch())
807
807
808 @command('branches',
808 @command('branches',
809 [('a', 'active', False, _('show only branches that have unmerged heads')),
809 [('a', 'active', False, _('show only branches that have unmerged heads')),
810 ('c', 'closed', False, _('show normal and closed branches'))],
810 ('c', 'closed', False, _('show normal and closed branches'))],
811 _('[-ac]'))
811 _('[-ac]'))
812 def branches(ui, repo, active=False, closed=False):
812 def branches(ui, repo, active=False, closed=False):
813 """list repository named branches
813 """list repository named branches
814
814
815 List the repository's named branches, indicating which ones are
815 List the repository's named branches, indicating which ones are
816 inactive. If -c/--closed is specified, also list branches which have
816 inactive. If -c/--closed is specified, also list branches which have
817 been marked closed (see :hg:`commit --close-branch`).
817 been marked closed (see :hg:`commit --close-branch`).
818
818
819 If -a/--active is specified, only show active branches. A branch
819 If -a/--active is specified, only show active branches. A branch
820 is considered active if it contains repository heads.
820 is considered active if it contains repository heads.
821
821
822 Use the command :hg:`update` to switch to an existing branch.
822 Use the command :hg:`update` to switch to an existing branch.
823
823
824 Returns 0.
824 Returns 0.
825 """
825 """
826
826
827 hexfunc = ui.debugflag and hex or short
827 hexfunc = ui.debugflag and hex or short
828 activebranches = [repo[n].branch() for n in repo.heads()]
828 activebranches = [repo[n].branch() for n in repo.heads()]
829 def testactive(tag, node):
829 def testactive(tag, node):
830 realhead = tag in activebranches
830 realhead = tag in activebranches
831 open = node in repo.branchheads(tag, closed=False)
831 open = node in repo.branchheads(tag, closed=False)
832 return realhead and open
832 return realhead and open
833 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
833 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
834 for tag, node in repo.branchtags().items()],
834 for tag, node in repo.branchtags().items()],
835 reverse=True)
835 reverse=True)
836
836
837 for isactive, node, tag in branches:
837 for isactive, node, tag in branches:
838 if (not active) or isactive:
838 if (not active) or isactive:
839 if ui.quiet:
839 if ui.quiet:
840 ui.write("%s\n" % tag)
840 ui.write("%s\n" % tag)
841 else:
841 else:
842 hn = repo.lookup(node)
842 hn = repo.lookup(node)
843 if isactive:
843 if isactive:
844 label = 'branches.active'
844 label = 'branches.active'
845 notice = ''
845 notice = ''
846 elif hn not in repo.branchheads(tag, closed=False):
846 elif hn not in repo.branchheads(tag, closed=False):
847 if not closed:
847 if not closed:
848 continue
848 continue
849 label = 'branches.closed'
849 label = 'branches.closed'
850 notice = _(' (closed)')
850 notice = _(' (closed)')
851 else:
851 else:
852 label = 'branches.inactive'
852 label = 'branches.inactive'
853 notice = _(' (inactive)')
853 notice = _(' (inactive)')
854 if tag == repo.dirstate.branch():
854 if tag == repo.dirstate.branch():
855 label = 'branches.current'
855 label = 'branches.current'
856 rev = str(node).rjust(31 - encoding.colwidth(tag))
856 rev = str(node).rjust(31 - encoding.colwidth(tag))
857 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
857 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
858 tag = ui.label(tag, label)
858 tag = ui.label(tag, label)
859 ui.write("%s %s%s\n" % (tag, rev, notice))
859 ui.write("%s %s%s\n" % (tag, rev, notice))
860
860
861 @command('bundle',
861 @command('bundle',
862 [('f', 'force', None, _('run even when the destination is unrelated')),
862 [('f', 'force', None, _('run even when the destination is unrelated')),
863 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
863 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
864 _('REV')),
864 _('REV')),
865 ('b', 'branch', [], _('a specific branch you would like to bundle'),
865 ('b', 'branch', [], _('a specific branch you would like to bundle'),
866 _('BRANCH')),
866 _('BRANCH')),
867 ('', 'base', [],
867 ('', 'base', [],
868 _('a base changeset assumed to be available at the destination'),
868 _('a base changeset assumed to be available at the destination'),
869 _('REV')),
869 _('REV')),
870 ('a', 'all', None, _('bundle all changesets in the repository')),
870 ('a', 'all', None, _('bundle all changesets in the repository')),
871 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
871 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
872 ] + remoteopts,
872 ] + remoteopts,
873 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
873 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
874 def bundle(ui, repo, fname, dest=None, **opts):
874 def bundle(ui, repo, fname, dest=None, **opts):
875 """create a changegroup file
875 """create a changegroup file
876
876
877 Generate a compressed changegroup file collecting changesets not
877 Generate a compressed changegroup file collecting changesets not
878 known to be in another repository.
878 known to be in another repository.
879
879
880 If you omit the destination repository, then hg assumes the
880 If you omit the destination repository, then hg assumes the
881 destination will have all the nodes you specify with --base
881 destination will have all the nodes you specify with --base
882 parameters. To create a bundle containing all changesets, use
882 parameters. To create a bundle containing all changesets, use
883 -a/--all (or --base null).
883 -a/--all (or --base null).
884
884
885 You can change compression method with the -t/--type option.
885 You can change compression method with the -t/--type option.
886 The available compression methods are: none, bzip2, and
886 The available compression methods are: none, bzip2, and
887 gzip (by default, bundles are compressed using bzip2).
887 gzip (by default, bundles are compressed using bzip2).
888
888
889 The bundle file can then be transferred using conventional means
889 The bundle file can then be transferred using conventional means
890 and applied to another repository with the unbundle or pull
890 and applied to another repository with the unbundle or pull
891 command. This is useful when direct push and pull are not
891 command. This is useful when direct push and pull are not
892 available or when exporting an entire repository is undesirable.
892 available or when exporting an entire repository is undesirable.
893
893
894 Applying bundles preserves all changeset contents including
894 Applying bundles preserves all changeset contents including
895 permissions, copy/rename information, and revision history.
895 permissions, copy/rename information, and revision history.
896
896
897 Returns 0 on success, 1 if no changes found.
897 Returns 0 on success, 1 if no changes found.
898 """
898 """
899 revs = None
899 revs = None
900 if 'rev' in opts:
900 if 'rev' in opts:
901 revs = scmutil.revrange(repo, opts['rev'])
901 revs = scmutil.revrange(repo, opts['rev'])
902
902
903 if opts.get('all'):
903 if opts.get('all'):
904 base = ['null']
904 base = ['null']
905 else:
905 else:
906 base = scmutil.revrange(repo, opts.get('base'))
906 base = scmutil.revrange(repo, opts.get('base'))
907 if base:
907 if base:
908 if dest:
908 if dest:
909 raise util.Abort(_("--base is incompatible with specifying "
909 raise util.Abort(_("--base is incompatible with specifying "
910 "a destination"))
910 "a destination"))
911 common = [repo.lookup(rev) for rev in base]
911 common = [repo.lookup(rev) for rev in base]
912 heads = revs and map(repo.lookup, revs) or revs
912 heads = revs and map(repo.lookup, revs) or revs
913 else:
913 else:
914 dest = ui.expandpath(dest or 'default-push', dest or 'default')
914 dest = ui.expandpath(dest or 'default-push', dest or 'default')
915 dest, branches = hg.parseurl(dest, opts.get('branch'))
915 dest, branches = hg.parseurl(dest, opts.get('branch'))
916 other = hg.peer(repo, opts, dest)
916 other = hg.peer(repo, opts, dest)
917 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
917 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
918 heads = revs and map(repo.lookup, revs) or revs
918 heads = revs and map(repo.lookup, revs) or revs
919 common, outheads = discovery.findcommonoutgoing(repo, other,
919 common, outheads = discovery.findcommonoutgoing(repo, other,
920 onlyheads=heads,
920 onlyheads=heads,
921 force=opts.get('force'))
921 force=opts.get('force'))
922
922
923 cg = repo.getbundle('bundle', common=common, heads=heads)
923 cg = repo.getbundle('bundle', common=common, heads=heads)
924 if not cg:
924 if not cg:
925 ui.status(_("no changes found\n"))
925 ui.status(_("no changes found\n"))
926 return 1
926 return 1
927
927
928 bundletype = opts.get('type', 'bzip2').lower()
928 bundletype = opts.get('type', 'bzip2').lower()
929 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
929 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
930 bundletype = btypes.get(bundletype)
930 bundletype = btypes.get(bundletype)
931 if bundletype not in changegroup.bundletypes:
931 if bundletype not in changegroup.bundletypes:
932 raise util.Abort(_('unknown bundle type specified with --type'))
932 raise util.Abort(_('unknown bundle type specified with --type'))
933
933
934 changegroup.writebundle(cg, fname, bundletype)
934 changegroup.writebundle(cg, fname, bundletype)
935
935
936 @command('cat',
936 @command('cat',
937 [('o', 'output', '',
937 [('o', 'output', '',
938 _('print output to file with formatted name'), _('FORMAT')),
938 _('print output to file with formatted name'), _('FORMAT')),
939 ('r', 'rev', '', _('print the given revision'), _('REV')),
939 ('r', 'rev', '', _('print the given revision'), _('REV')),
940 ('', 'decode', None, _('apply any matching decode filter')),
940 ('', 'decode', None, _('apply any matching decode filter')),
941 ] + walkopts,
941 ] + walkopts,
942 _('[OPTION]... FILE...'))
942 _('[OPTION]... FILE...'))
943 def cat(ui, repo, file1, *pats, **opts):
943 def cat(ui, repo, file1, *pats, **opts):
944 """output the current or given revision of files
944 """output the current or given revision of files
945
945
946 Print the specified files as they were at the given revision. If
946 Print the specified files as they were at the given revision. If
947 no revision is given, the parent of the working directory is used,
947 no revision is given, the parent of the working directory is used,
948 or tip if no revision is checked out.
948 or tip if no revision is checked out.
949
949
950 Output may be to a file, in which case the name of the file is
950 Output may be to a file, in which case the name of the file is
951 given using a format string. The formatting rules are the same as
951 given using a format string. The formatting rules are the same as
952 for the export command, with the following additions:
952 for the export command, with the following additions:
953
953
954 :``%s``: basename of file being printed
954 :``%s``: basename of file being printed
955 :``%d``: dirname of file being printed, or '.' if in repository root
955 :``%d``: dirname of file being printed, or '.' if in repository root
956 :``%p``: root-relative path name of file being printed
956 :``%p``: root-relative path name of file being printed
957
957
958 Returns 0 on success.
958 Returns 0 on success.
959 """
959 """
960 ctx = scmutil.revsingle(repo, opts.get('rev'))
960 ctx = scmutil.revsingle(repo, opts.get('rev'))
961 err = 1
961 err = 1
962 m = scmutil.match(ctx, (file1,) + pats, opts)
962 m = scmutil.match(ctx, (file1,) + pats, opts)
963 for abs in ctx.walk(m):
963 for abs in ctx.walk(m):
964 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
964 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
965 pathname=abs)
965 pathname=abs)
966 data = ctx[abs].data()
966 data = ctx[abs].data()
967 if opts.get('decode'):
967 if opts.get('decode'):
968 data = repo.wwritedata(abs, data)
968 data = repo.wwritedata(abs, data)
969 fp.write(data)
969 fp.write(data)
970 fp.close()
970 fp.close()
971 err = 0
971 err = 0
972 return err
972 return err
973
973
974 @command('^clone',
974 @command('^clone',
975 [('U', 'noupdate', None,
975 [('U', 'noupdate', None,
976 _('the clone will include an empty working copy (only a repository)')),
976 _('the clone will include an empty working copy (only a repository)')),
977 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
977 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
978 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
978 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
979 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
979 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
980 ('', 'pull', None, _('use pull protocol to copy metadata')),
980 ('', 'pull', None, _('use pull protocol to copy metadata')),
981 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
981 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
982 ] + remoteopts,
982 ] + remoteopts,
983 _('[OPTION]... SOURCE [DEST]'))
983 _('[OPTION]... SOURCE [DEST]'))
984 def clone(ui, source, dest=None, **opts):
984 def clone(ui, source, dest=None, **opts):
985 """make a copy of an existing repository
985 """make a copy of an existing repository
986
986
987 Create a copy of an existing repository in a new directory.
987 Create a copy of an existing repository in a new directory.
988
988
989 If no destination directory name is specified, it defaults to the
989 If no destination directory name is specified, it defaults to the
990 basename of the source.
990 basename of the source.
991
991
992 The location of the source is added to the new repository's
992 The location of the source is added to the new repository's
993 ``.hg/hgrc`` file, as the default to be used for future pulls.
993 ``.hg/hgrc`` file, as the default to be used for future pulls.
994
994
995 See :hg:`help urls` for valid source format details.
995 See :hg:`help urls` for valid source format details.
996
996
997 It is possible to specify an ``ssh://`` URL as the destination, but no
997 It is possible to specify an ``ssh://`` URL as the destination, but no
998 ``.hg/hgrc`` and working directory will be created on the remote side.
998 ``.hg/hgrc`` and working directory will be created on the remote side.
999 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
999 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
1000
1000
1001 A set of changesets (tags, or branch names) to pull may be specified
1001 A set of changesets (tags, or branch names) to pull may be specified
1002 by listing each changeset (tag, or branch name) with -r/--rev.
1002 by listing each changeset (tag, or branch name) with -r/--rev.
1003 If -r/--rev is used, the cloned repository will contain only a subset
1003 If -r/--rev is used, the cloned repository will contain only a subset
1004 of the changesets of the source repository. Only the set of changesets
1004 of the changesets of the source repository. Only the set of changesets
1005 defined by all -r/--rev options (including all their ancestors)
1005 defined by all -r/--rev options (including all their ancestors)
1006 will be pulled into the destination repository.
1006 will be pulled into the destination repository.
1007 No subsequent changesets (including subsequent tags) will be present
1007 No subsequent changesets (including subsequent tags) will be present
1008 in the destination.
1008 in the destination.
1009
1009
1010 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
1010 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
1011 local source repositories.
1011 local source repositories.
1012
1012
1013 For efficiency, hardlinks are used for cloning whenever the source
1013 For efficiency, hardlinks are used for cloning whenever the source
1014 and destination are on the same filesystem (note this applies only
1014 and destination are on the same filesystem (note this applies only
1015 to the repository data, not to the working directory). Some
1015 to the repository data, not to the working directory). Some
1016 filesystems, such as AFS, implement hardlinking incorrectly, but
1016 filesystems, such as AFS, implement hardlinking incorrectly, but
1017 do not report errors. In these cases, use the --pull option to
1017 do not report errors. In these cases, use the --pull option to
1018 avoid hardlinking.
1018 avoid hardlinking.
1019
1019
1020 In some cases, you can clone repositories and the working directory
1020 In some cases, you can clone repositories and the working directory
1021 using full hardlinks with ::
1021 using full hardlinks with ::
1022
1022
1023 $ cp -al REPO REPOCLONE
1023 $ cp -al REPO REPOCLONE
1024
1024
1025 This is the fastest way to clone, but it is not always safe. The
1025 This is the fastest way to clone, but it is not always safe. The
1026 operation is not atomic (making sure REPO is not modified during
1026 operation is not atomic (making sure REPO is not modified during
1027 the operation is up to you) and you have to make sure your editor
1027 the operation is up to you) and you have to make sure your editor
1028 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1028 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1029 this is not compatible with certain extensions that place their
1029 this is not compatible with certain extensions that place their
1030 metadata under the .hg directory, such as mq.
1030 metadata under the .hg directory, such as mq.
1031
1031
1032 Mercurial will update the working directory to the first applicable
1032 Mercurial will update the working directory to the first applicable
1033 revision from this list:
1033 revision from this list:
1034
1034
1035 a) null if -U or the source repository has no changesets
1035 a) null if -U or the source repository has no changesets
1036 b) if -u . and the source repository is local, the first parent of
1036 b) if -u . and the source repository is local, the first parent of
1037 the source repository's working directory
1037 the source repository's working directory
1038 c) the changeset specified with -u (if a branch name, this means the
1038 c) the changeset specified with -u (if a branch name, this means the
1039 latest head of that branch)
1039 latest head of that branch)
1040 d) the changeset specified with -r
1040 d) the changeset specified with -r
1041 e) the tipmost head specified with -b
1041 e) the tipmost head specified with -b
1042 f) the tipmost head specified with the url#branch source syntax
1042 f) the tipmost head specified with the url#branch source syntax
1043 g) the tipmost head of the default branch
1043 g) the tipmost head of the default branch
1044 h) tip
1044 h) tip
1045
1045
1046 Returns 0 on success.
1046 Returns 0 on success.
1047 """
1047 """
1048 if opts.get('noupdate') and opts.get('updaterev'):
1048 if opts.get('noupdate') and opts.get('updaterev'):
1049 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1049 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1050
1050
1051 r = hg.clone(ui, opts, source, dest,
1051 r = hg.clone(ui, opts, source, dest,
1052 pull=opts.get('pull'),
1052 pull=opts.get('pull'),
1053 stream=opts.get('uncompressed'),
1053 stream=opts.get('uncompressed'),
1054 rev=opts.get('rev'),
1054 rev=opts.get('rev'),
1055 update=opts.get('updaterev') or not opts.get('noupdate'),
1055 update=opts.get('updaterev') or not opts.get('noupdate'),
1056 branch=opts.get('branch'))
1056 branch=opts.get('branch'))
1057
1057
1058 return r is None
1058 return r is None
1059
1059
1060 @command('^commit|ci',
1060 @command('^commit|ci',
1061 [('A', 'addremove', None,
1061 [('A', 'addremove', None,
1062 _('mark new/missing files as added/removed before committing')),
1062 _('mark new/missing files as added/removed before committing')),
1063 ('', 'close-branch', None,
1063 ('', 'close-branch', None,
1064 _('mark a branch as closed, hiding it from the branch list')),
1064 _('mark a branch as closed, hiding it from the branch list')),
1065 ] + walkopts + commitopts + commitopts2,
1065 ] + walkopts + commitopts + commitopts2,
1066 _('[OPTION]... [FILE]...'))
1066 _('[OPTION]... [FILE]...'))
1067 def commit(ui, repo, *pats, **opts):
1067 def commit(ui, repo, *pats, **opts):
1068 """commit the specified files or all outstanding changes
1068 """commit the specified files or all outstanding changes
1069
1069
1070 Commit changes to the given files into the repository. Unlike a
1070 Commit changes to the given files into the repository. Unlike a
1071 centralized SCM, this operation is a local operation. See
1071 centralized SCM, this operation is a local operation. See
1072 :hg:`push` for a way to actively distribute your changes.
1072 :hg:`push` for a way to actively distribute your changes.
1073
1073
1074 If a list of files is omitted, all changes reported by :hg:`status`
1074 If a list of files is omitted, all changes reported by :hg:`status`
1075 will be committed.
1075 will be committed.
1076
1076
1077 If you are committing the result of a merge, do not provide any
1077 If you are committing the result of a merge, do not provide any
1078 filenames or -I/-X filters.
1078 filenames or -I/-X filters.
1079
1079
1080 If no commit message is specified, Mercurial starts your
1080 If no commit message is specified, Mercurial starts your
1081 configured editor where you can enter a message. In case your
1081 configured editor where you can enter a message. In case your
1082 commit fails, you will find a backup of your message in
1082 commit fails, you will find a backup of your message in
1083 ``.hg/last-message.txt``.
1083 ``.hg/last-message.txt``.
1084
1084
1085 See :hg:`help dates` for a list of formats valid for -d/--date.
1085 See :hg:`help dates` for a list of formats valid for -d/--date.
1086
1086
1087 Returns 0 on success, 1 if nothing changed.
1087 Returns 0 on success, 1 if nothing changed.
1088 """
1088 """
1089 extra = {}
1089 extra = {}
1090 if opts.get('close_branch'):
1090 if opts.get('close_branch'):
1091 if repo['.'].node() not in repo.branchheads():
1091 if repo['.'].node() not in repo.branchheads():
1092 # The topo heads set is included in the branch heads set of the
1092 # The topo heads set is included in the branch heads set of the
1093 # current branch, so it's sufficient to test branchheads
1093 # current branch, so it's sufficient to test branchheads
1094 raise util.Abort(_('can only close branch heads'))
1094 raise util.Abort(_('can only close branch heads'))
1095 extra['close'] = 1
1095 extra['close'] = 1
1096 e = cmdutil.commiteditor
1096 e = cmdutil.commiteditor
1097 if opts.get('force_editor'):
1097 if opts.get('force_editor'):
1098 e = cmdutil.commitforceeditor
1098 e = cmdutil.commitforceeditor
1099
1099
1100 def commitfunc(ui, repo, message, match, opts):
1100 def commitfunc(ui, repo, message, match, opts):
1101 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1101 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1102 editor=e, extra=extra)
1102 editor=e, extra=extra)
1103
1103
1104 branch = repo[None].branch()
1104 branch = repo[None].branch()
1105 bheads = repo.branchheads(branch)
1105 bheads = repo.branchheads(branch)
1106
1106
1107 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1107 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1108 if not node:
1108 if not node:
1109 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1109 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1110 if stat[3]:
1110 if stat[3]:
1111 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1111 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1112 % len(stat[3]))
1112 % len(stat[3]))
1113 else:
1113 else:
1114 ui.status(_("nothing changed\n"))
1114 ui.status(_("nothing changed\n"))
1115 return 1
1115 return 1
1116
1116
1117 ctx = repo[node]
1117 ctx = repo[node]
1118 parents = ctx.parents()
1118 parents = ctx.parents()
1119
1119
1120 if (bheads and node not in bheads and not
1120 if (bheads and node not in bheads and not
1121 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1121 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1122 ui.status(_('created new head\n'))
1122 ui.status(_('created new head\n'))
1123 # The message is not printed for initial roots. For the other
1123 # The message is not printed for initial roots. For the other
1124 # changesets, it is printed in the following situations:
1124 # changesets, it is printed in the following situations:
1125 #
1125 #
1126 # Par column: for the 2 parents with ...
1126 # Par column: for the 2 parents with ...
1127 # N: null or no parent
1127 # N: null or no parent
1128 # B: parent is on another named branch
1128 # B: parent is on another named branch
1129 # C: parent is a regular non head changeset
1129 # C: parent is a regular non head changeset
1130 # H: parent was a branch head of the current branch
1130 # H: parent was a branch head of the current branch
1131 # Msg column: whether we print "created new head" message
1131 # Msg column: whether we print "created new head" message
1132 # In the following, it is assumed that there already exists some
1132 # In the following, it is assumed that there already exists some
1133 # initial branch heads of the current branch, otherwise nothing is
1133 # initial branch heads of the current branch, otherwise nothing is
1134 # printed anyway.
1134 # printed anyway.
1135 #
1135 #
1136 # Par Msg Comment
1136 # Par Msg Comment
1137 # NN y additional topo root
1137 # NN y additional topo root
1138 #
1138 #
1139 # BN y additional branch root
1139 # BN y additional branch root
1140 # CN y additional topo head
1140 # CN y additional topo head
1141 # HN n usual case
1141 # HN n usual case
1142 #
1142 #
1143 # BB y weird additional branch root
1143 # BB y weird additional branch root
1144 # CB y branch merge
1144 # CB y branch merge
1145 # HB n merge with named branch
1145 # HB n merge with named branch
1146 #
1146 #
1147 # CC y additional head from merge
1147 # CC y additional head from merge
1148 # CH n merge with a head
1148 # CH n merge with a head
1149 #
1149 #
1150 # HH n head merge: head count decreases
1150 # HH n head merge: head count decreases
1151
1151
1152 if not opts.get('close_branch'):
1152 if not opts.get('close_branch'):
1153 for r in parents:
1153 for r in parents:
1154 if r.extra().get('close') and r.branch() == branch:
1154 if r.extra().get('close') and r.branch() == branch:
1155 ui.status(_('reopening closed branch head %d\n') % r)
1155 ui.status(_('reopening closed branch head %d\n') % r)
1156
1156
1157 if ui.debugflag:
1157 if ui.debugflag:
1158 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1158 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1159 elif ui.verbose:
1159 elif ui.verbose:
1160 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1160 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1161
1161
1162 @command('copy|cp',
1162 @command('copy|cp',
1163 [('A', 'after', None, _('record a copy that has already occurred')),
1163 [('A', 'after', None, _('record a copy that has already occurred')),
1164 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1164 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1165 ] + walkopts + dryrunopts,
1165 ] + walkopts + dryrunopts,
1166 _('[OPTION]... [SOURCE]... DEST'))
1166 _('[OPTION]... [SOURCE]... DEST'))
1167 def copy(ui, repo, *pats, **opts):
1167 def copy(ui, repo, *pats, **opts):
1168 """mark files as copied for the next commit
1168 """mark files as copied for the next commit
1169
1169
1170 Mark dest as having copies of source files. If dest is a
1170 Mark dest as having copies of source files. If dest is a
1171 directory, copies are put in that directory. If dest is a file,
1171 directory, copies are put in that directory. If dest is a file,
1172 the source must be a single file.
1172 the source must be a single file.
1173
1173
1174 By default, this command copies the contents of files as they
1174 By default, this command copies the contents of files as they
1175 exist in the working directory. If invoked with -A/--after, the
1175 exist in the working directory. If invoked with -A/--after, the
1176 operation is recorded, but no copying is performed.
1176 operation is recorded, but no copying is performed.
1177
1177
1178 This command takes effect with the next commit. To undo a copy
1178 This command takes effect with the next commit. To undo a copy
1179 before that, see :hg:`revert`.
1179 before that, see :hg:`revert`.
1180
1180
1181 Returns 0 on success, 1 if errors are encountered.
1181 Returns 0 on success, 1 if errors are encountered.
1182 """
1182 """
1183 wlock = repo.wlock(False)
1183 wlock = repo.wlock(False)
1184 try:
1184 try:
1185 return cmdutil.copy(ui, repo, pats, opts)
1185 return cmdutil.copy(ui, repo, pats, opts)
1186 finally:
1186 finally:
1187 wlock.release()
1187 wlock.release()
1188
1188
1189 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1189 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1190 def debugancestor(ui, repo, *args):
1190 def debugancestor(ui, repo, *args):
1191 """find the ancestor revision of two revisions in a given index"""
1191 """find the ancestor revision of two revisions in a given index"""
1192 if len(args) == 3:
1192 if len(args) == 3:
1193 index, rev1, rev2 = args
1193 index, rev1, rev2 = args
1194 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1194 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1195 lookup = r.lookup
1195 lookup = r.lookup
1196 elif len(args) == 2:
1196 elif len(args) == 2:
1197 if not repo:
1197 if not repo:
1198 raise util.Abort(_("there is no Mercurial repository here "
1198 raise util.Abort(_("there is no Mercurial repository here "
1199 "(.hg not found)"))
1199 "(.hg not found)"))
1200 rev1, rev2 = args
1200 rev1, rev2 = args
1201 r = repo.changelog
1201 r = repo.changelog
1202 lookup = repo.lookup
1202 lookup = repo.lookup
1203 else:
1203 else:
1204 raise util.Abort(_('either two or three arguments required'))
1204 raise util.Abort(_('either two or three arguments required'))
1205 a = r.ancestor(lookup(rev1), lookup(rev2))
1205 a = r.ancestor(lookup(rev1), lookup(rev2))
1206 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1206 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1207
1207
1208 @command('debugbuilddag',
1208 @command('debugbuilddag',
1209 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1209 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1210 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1210 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1211 ('n', 'new-file', None, _('add new file at each rev'))],
1211 ('n', 'new-file', None, _('add new file at each rev'))],
1212 _('[OPTION]... [TEXT]'))
1212 _('[OPTION]... [TEXT]'))
1213 def debugbuilddag(ui, repo, text=None,
1213 def debugbuilddag(ui, repo, text=None,
1214 mergeable_file=False,
1214 mergeable_file=False,
1215 overwritten_file=False,
1215 overwritten_file=False,
1216 new_file=False):
1216 new_file=False):
1217 """builds a repo with a given DAG from scratch in the current empty repo
1217 """builds a repo with a given DAG from scratch in the current empty repo
1218
1218
1219 The description of the DAG is read from stdin if not given on the
1219 The description of the DAG is read from stdin if not given on the
1220 command line.
1220 command line.
1221
1221
1222 Elements:
1222 Elements:
1223
1223
1224 - "+n" is a linear run of n nodes based on the current default parent
1224 - "+n" is a linear run of n nodes based on the current default parent
1225 - "." is a single node based on the current default parent
1225 - "." is a single node based on the current default parent
1226 - "$" resets the default parent to null (implied at the start);
1226 - "$" resets the default parent to null (implied at the start);
1227 otherwise the default parent is always the last node created
1227 otherwise the default parent is always the last node created
1228 - "<p" sets the default parent to the backref p
1228 - "<p" sets the default parent to the backref p
1229 - "*p" is a fork at parent p, which is a backref
1229 - "*p" is a fork at parent p, which is a backref
1230 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1230 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1231 - "/p2" is a merge of the preceding node and p2
1231 - "/p2" is a merge of the preceding node and p2
1232 - ":tag" defines a local tag for the preceding node
1232 - ":tag" defines a local tag for the preceding node
1233 - "@branch" sets the named branch for subsequent nodes
1233 - "@branch" sets the named branch for subsequent nodes
1234 - "#...\\n" is a comment up to the end of the line
1234 - "#...\\n" is a comment up to the end of the line
1235
1235
1236 Whitespace between the above elements is ignored.
1236 Whitespace between the above elements is ignored.
1237
1237
1238 A backref is either
1238 A backref is either
1239
1239
1240 - a number n, which references the node curr-n, where curr is the current
1240 - a number n, which references the node curr-n, where curr is the current
1241 node, or
1241 node, or
1242 - the name of a local tag you placed earlier using ":tag", or
1242 - the name of a local tag you placed earlier using ":tag", or
1243 - empty to denote the default parent.
1243 - empty to denote the default parent.
1244
1244
1245 All string valued-elements are either strictly alphanumeric, or must
1245 All string valued-elements are either strictly alphanumeric, or must
1246 be enclosed in double quotes ("..."), with "\\" as escape character.
1246 be enclosed in double quotes ("..."), with "\\" as escape character.
1247 """
1247 """
1248
1248
1249 if text is None:
1249 if text is None:
1250 ui.status(_("reading DAG from stdin\n"))
1250 ui.status(_("reading DAG from stdin\n"))
1251 text = ui.fin.read()
1251 text = ui.fin.read()
1252
1252
1253 cl = repo.changelog
1253 cl = repo.changelog
1254 if len(cl) > 0:
1254 if len(cl) > 0:
1255 raise util.Abort(_('repository is not empty'))
1255 raise util.Abort(_('repository is not empty'))
1256
1256
1257 # determine number of revs in DAG
1257 # determine number of revs in DAG
1258 total = 0
1258 total = 0
1259 for type, data in dagparser.parsedag(text):
1259 for type, data in dagparser.parsedag(text):
1260 if type == 'n':
1260 if type == 'n':
1261 total += 1
1261 total += 1
1262
1262
1263 if mergeable_file:
1263 if mergeable_file:
1264 linesperrev = 2
1264 linesperrev = 2
1265 # make a file with k lines per rev
1265 # make a file with k lines per rev
1266 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1266 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1267 initialmergedlines.append("")
1267 initialmergedlines.append("")
1268
1268
1269 tags = []
1269 tags = []
1270
1270
1271 tr = repo.transaction("builddag")
1271 tr = repo.transaction("builddag")
1272 try:
1272 try:
1273
1273
1274 at = -1
1274 at = -1
1275 atbranch = 'default'
1275 atbranch = 'default'
1276 nodeids = []
1276 nodeids = []
1277 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1277 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1278 for type, data in dagparser.parsedag(text):
1278 for type, data in dagparser.parsedag(text):
1279 if type == 'n':
1279 if type == 'n':
1280 ui.note('node %s\n' % str(data))
1280 ui.note('node %s\n' % str(data))
1281 id, ps = data
1281 id, ps = data
1282
1282
1283 files = []
1283 files = []
1284 fctxs = {}
1284 fctxs = {}
1285
1285
1286 p2 = None
1286 p2 = None
1287 if mergeable_file:
1287 if mergeable_file:
1288 fn = "mf"
1288 fn = "mf"
1289 p1 = repo[ps[0]]
1289 p1 = repo[ps[0]]
1290 if len(ps) > 1:
1290 if len(ps) > 1:
1291 p2 = repo[ps[1]]
1291 p2 = repo[ps[1]]
1292 pa = p1.ancestor(p2)
1292 pa = p1.ancestor(p2)
1293 base, local, other = [x[fn].data() for x in pa, p1, p2]
1293 base, local, other = [x[fn].data() for x in pa, p1, p2]
1294 m3 = simplemerge.Merge3Text(base, local, other)
1294 m3 = simplemerge.Merge3Text(base, local, other)
1295 ml = [l.strip() for l in m3.merge_lines()]
1295 ml = [l.strip() for l in m3.merge_lines()]
1296 ml.append("")
1296 ml.append("")
1297 elif at > 0:
1297 elif at > 0:
1298 ml = p1[fn].data().split("\n")
1298 ml = p1[fn].data().split("\n")
1299 else:
1299 else:
1300 ml = initialmergedlines
1300 ml = initialmergedlines
1301 ml[id * linesperrev] += " r%i" % id
1301 ml[id * linesperrev] += " r%i" % id
1302 mergedtext = "\n".join(ml)
1302 mergedtext = "\n".join(ml)
1303 files.append(fn)
1303 files.append(fn)
1304 fctxs[fn] = context.memfilectx(fn, mergedtext)
1304 fctxs[fn] = context.memfilectx(fn, mergedtext)
1305
1305
1306 if overwritten_file:
1306 if overwritten_file:
1307 fn = "of"
1307 fn = "of"
1308 files.append(fn)
1308 files.append(fn)
1309 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1309 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1310
1310
1311 if new_file:
1311 if new_file:
1312 fn = "nf%i" % id
1312 fn = "nf%i" % id
1313 files.append(fn)
1313 files.append(fn)
1314 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1314 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1315 if len(ps) > 1:
1315 if len(ps) > 1:
1316 if not p2:
1316 if not p2:
1317 p2 = repo[ps[1]]
1317 p2 = repo[ps[1]]
1318 for fn in p2:
1318 for fn in p2:
1319 if fn.startswith("nf"):
1319 if fn.startswith("nf"):
1320 files.append(fn)
1320 files.append(fn)
1321 fctxs[fn] = p2[fn]
1321 fctxs[fn] = p2[fn]
1322
1322
1323 def fctxfn(repo, cx, path):
1323 def fctxfn(repo, cx, path):
1324 return fctxs.get(path)
1324 return fctxs.get(path)
1325
1325
1326 if len(ps) == 0 or ps[0] < 0:
1326 if len(ps) == 0 or ps[0] < 0:
1327 pars = [None, None]
1327 pars = [None, None]
1328 elif len(ps) == 1:
1328 elif len(ps) == 1:
1329 pars = [nodeids[ps[0]], None]
1329 pars = [nodeids[ps[0]], None]
1330 else:
1330 else:
1331 pars = [nodeids[p] for p in ps]
1331 pars = [nodeids[p] for p in ps]
1332 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1332 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1333 date=(id, 0),
1333 date=(id, 0),
1334 user="debugbuilddag",
1334 user="debugbuilddag",
1335 extra={'branch': atbranch})
1335 extra={'branch': atbranch})
1336 nodeid = repo.commitctx(cx)
1336 nodeid = repo.commitctx(cx)
1337 nodeids.append(nodeid)
1337 nodeids.append(nodeid)
1338 at = id
1338 at = id
1339 elif type == 'l':
1339 elif type == 'l':
1340 id, name = data
1340 id, name = data
1341 ui.note('tag %s\n' % name)
1341 ui.note('tag %s\n' % name)
1342 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1342 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1343 elif type == 'a':
1343 elif type == 'a':
1344 ui.note('branch %s\n' % data)
1344 ui.note('branch %s\n' % data)
1345 atbranch = data
1345 atbranch = data
1346 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1346 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1347 tr.close()
1347 tr.close()
1348 finally:
1348 finally:
1349 ui.progress(_('building'), None)
1349 ui.progress(_('building'), None)
1350 tr.release()
1350 tr.release()
1351
1351
1352 if tags:
1352 if tags:
1353 repo.opener.write("localtags", "".join(tags))
1353 repo.opener.write("localtags", "".join(tags))
1354
1354
1355 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1355 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1356 def debugbundle(ui, bundlepath, all=None, **opts):
1356 def debugbundle(ui, bundlepath, all=None, **opts):
1357 """lists the contents of a bundle"""
1357 """lists the contents of a bundle"""
1358 f = url.open(ui, bundlepath)
1358 f = url.open(ui, bundlepath)
1359 try:
1359 try:
1360 gen = changegroup.readbundle(f, bundlepath)
1360 gen = changegroup.readbundle(f, bundlepath)
1361 if all:
1361 if all:
1362 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1362 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1363
1363
1364 def showchunks(named):
1364 def showchunks(named):
1365 ui.write("\n%s\n" % named)
1365 ui.write("\n%s\n" % named)
1366 chain = None
1366 chain = None
1367 while True:
1367 while True:
1368 chunkdata = gen.deltachunk(chain)
1368 chunkdata = gen.deltachunk(chain)
1369 if not chunkdata:
1369 if not chunkdata:
1370 break
1370 break
1371 node = chunkdata['node']
1371 node = chunkdata['node']
1372 p1 = chunkdata['p1']
1372 p1 = chunkdata['p1']
1373 p2 = chunkdata['p2']
1373 p2 = chunkdata['p2']
1374 cs = chunkdata['cs']
1374 cs = chunkdata['cs']
1375 deltabase = chunkdata['deltabase']
1375 deltabase = chunkdata['deltabase']
1376 delta = chunkdata['delta']
1376 delta = chunkdata['delta']
1377 ui.write("%s %s %s %s %s %s\n" %
1377 ui.write("%s %s %s %s %s %s\n" %
1378 (hex(node), hex(p1), hex(p2),
1378 (hex(node), hex(p1), hex(p2),
1379 hex(cs), hex(deltabase), len(delta)))
1379 hex(cs), hex(deltabase), len(delta)))
1380 chain = node
1380 chain = node
1381
1381
1382 chunkdata = gen.changelogheader()
1382 chunkdata = gen.changelogheader()
1383 showchunks("changelog")
1383 showchunks("changelog")
1384 chunkdata = gen.manifestheader()
1384 chunkdata = gen.manifestheader()
1385 showchunks("manifest")
1385 showchunks("manifest")
1386 while True:
1386 while True:
1387 chunkdata = gen.filelogheader()
1387 chunkdata = gen.filelogheader()
1388 if not chunkdata:
1388 if not chunkdata:
1389 break
1389 break
1390 fname = chunkdata['filename']
1390 fname = chunkdata['filename']
1391 showchunks(fname)
1391 showchunks(fname)
1392 else:
1392 else:
1393 chunkdata = gen.changelogheader()
1393 chunkdata = gen.changelogheader()
1394 chain = None
1394 chain = None
1395 while True:
1395 while True:
1396 chunkdata = gen.deltachunk(chain)
1396 chunkdata = gen.deltachunk(chain)
1397 if not chunkdata:
1397 if not chunkdata:
1398 break
1398 break
1399 node = chunkdata['node']
1399 node = chunkdata['node']
1400 ui.write("%s\n" % hex(node))
1400 ui.write("%s\n" % hex(node))
1401 chain = node
1401 chain = node
1402 finally:
1402 finally:
1403 f.close()
1403 f.close()
1404
1404
1405 @command('debugcheckstate', [], '')
1405 @command('debugcheckstate', [], '')
1406 def debugcheckstate(ui, repo):
1406 def debugcheckstate(ui, repo):
1407 """validate the correctness of the current dirstate"""
1407 """validate the correctness of the current dirstate"""
1408 parent1, parent2 = repo.dirstate.parents()
1408 parent1, parent2 = repo.dirstate.parents()
1409 m1 = repo[parent1].manifest()
1409 m1 = repo[parent1].manifest()
1410 m2 = repo[parent2].manifest()
1410 m2 = repo[parent2].manifest()
1411 errors = 0
1411 errors = 0
1412 for f in repo.dirstate:
1412 for f in repo.dirstate:
1413 state = repo.dirstate[f]
1413 state = repo.dirstate[f]
1414 if state in "nr" and f not in m1:
1414 if state in "nr" and f not in m1:
1415 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1415 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1416 errors += 1
1416 errors += 1
1417 if state in "a" and f in m1:
1417 if state in "a" and f in m1:
1418 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1418 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1419 errors += 1
1419 errors += 1
1420 if state in "m" and f not in m1 and f not in m2:
1420 if state in "m" and f not in m1 and f not in m2:
1421 ui.warn(_("%s in state %s, but not in either manifest\n") %
1421 ui.warn(_("%s in state %s, but not in either manifest\n") %
1422 (f, state))
1422 (f, state))
1423 errors += 1
1423 errors += 1
1424 for f in m1:
1424 for f in m1:
1425 state = repo.dirstate[f]
1425 state = repo.dirstate[f]
1426 if state not in "nrm":
1426 if state not in "nrm":
1427 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1427 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1428 errors += 1
1428 errors += 1
1429 if errors:
1429 if errors:
1430 error = _(".hg/dirstate inconsistent with current parent's manifest")
1430 error = _(".hg/dirstate inconsistent with current parent's manifest")
1431 raise util.Abort(error)
1431 raise util.Abort(error)
1432
1432
1433 @command('debugcommands', [], _('[COMMAND]'))
1433 @command('debugcommands', [], _('[COMMAND]'))
1434 def debugcommands(ui, cmd='', *args):
1434 def debugcommands(ui, cmd='', *args):
1435 """list all available commands and options"""
1435 """list all available commands and options"""
1436 for cmd, vals in sorted(table.iteritems()):
1436 for cmd, vals in sorted(table.iteritems()):
1437 cmd = cmd.split('|')[0].strip('^')
1437 cmd = cmd.split('|')[0].strip('^')
1438 opts = ', '.join([i[1] for i in vals[1]])
1438 opts = ', '.join([i[1] for i in vals[1]])
1439 ui.write('%s: %s\n' % (cmd, opts))
1439 ui.write('%s: %s\n' % (cmd, opts))
1440
1440
1441 @command('debugcomplete',
1441 @command('debugcomplete',
1442 [('o', 'options', None, _('show the command options'))],
1442 [('o', 'options', None, _('show the command options'))],
1443 _('[-o] CMD'))
1443 _('[-o] CMD'))
1444 def debugcomplete(ui, cmd='', **opts):
1444 def debugcomplete(ui, cmd='', **opts):
1445 """returns the completion list associated with the given command"""
1445 """returns the completion list associated with the given command"""
1446
1446
1447 if opts.get('options'):
1447 if opts.get('options'):
1448 options = []
1448 options = []
1449 otables = [globalopts]
1449 otables = [globalopts]
1450 if cmd:
1450 if cmd:
1451 aliases, entry = cmdutil.findcmd(cmd, table, False)
1451 aliases, entry = cmdutil.findcmd(cmd, table, False)
1452 otables.append(entry[1])
1452 otables.append(entry[1])
1453 for t in otables:
1453 for t in otables:
1454 for o in t:
1454 for o in t:
1455 if "(DEPRECATED)" in o[3]:
1455 if "(DEPRECATED)" in o[3]:
1456 continue
1456 continue
1457 if o[0]:
1457 if o[0]:
1458 options.append('-%s' % o[0])
1458 options.append('-%s' % o[0])
1459 options.append('--%s' % o[1])
1459 options.append('--%s' % o[1])
1460 ui.write("%s\n" % "\n".join(options))
1460 ui.write("%s\n" % "\n".join(options))
1461 return
1461 return
1462
1462
1463 cmdlist = cmdutil.findpossible(cmd, table)
1463 cmdlist = cmdutil.findpossible(cmd, table)
1464 if ui.verbose:
1464 if ui.verbose:
1465 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1465 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1466 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1466 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1467
1467
1468 @command('debugdag',
1468 @command('debugdag',
1469 [('t', 'tags', None, _('use tags as labels')),
1469 [('t', 'tags', None, _('use tags as labels')),
1470 ('b', 'branches', None, _('annotate with branch names')),
1470 ('b', 'branches', None, _('annotate with branch names')),
1471 ('', 'dots', None, _('use dots for runs')),
1471 ('', 'dots', None, _('use dots for runs')),
1472 ('s', 'spaces', None, _('separate elements by spaces'))],
1472 ('s', 'spaces', None, _('separate elements by spaces'))],
1473 _('[OPTION]... [FILE [REV]...]'))
1473 _('[OPTION]... [FILE [REV]...]'))
1474 def debugdag(ui, repo, file_=None, *revs, **opts):
1474 def debugdag(ui, repo, file_=None, *revs, **opts):
1475 """format the changelog or an index DAG as a concise textual description
1475 """format the changelog or an index DAG as a concise textual description
1476
1476
1477 If you pass a revlog index, the revlog's DAG is emitted. If you list
1477 If you pass a revlog index, the revlog's DAG is emitted. If you list
1478 revision numbers, they get labelled in the output as rN.
1478 revision numbers, they get labelled in the output as rN.
1479
1479
1480 Otherwise, the changelog DAG of the current repo is emitted.
1480 Otherwise, the changelog DAG of the current repo is emitted.
1481 """
1481 """
1482 spaces = opts.get('spaces')
1482 spaces = opts.get('spaces')
1483 dots = opts.get('dots')
1483 dots = opts.get('dots')
1484 if file_:
1484 if file_:
1485 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1485 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1486 revs = set((int(r) for r in revs))
1486 revs = set((int(r) for r in revs))
1487 def events():
1487 def events():
1488 for r in rlog:
1488 for r in rlog:
1489 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1489 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1490 if r in revs:
1490 if r in revs:
1491 yield 'l', (r, "r%i" % r)
1491 yield 'l', (r, "r%i" % r)
1492 elif repo:
1492 elif repo:
1493 cl = repo.changelog
1493 cl = repo.changelog
1494 tags = opts.get('tags')
1494 tags = opts.get('tags')
1495 branches = opts.get('branches')
1495 branches = opts.get('branches')
1496 if tags:
1496 if tags:
1497 labels = {}
1497 labels = {}
1498 for l, n in repo.tags().items():
1498 for l, n in repo.tags().items():
1499 labels.setdefault(cl.rev(n), []).append(l)
1499 labels.setdefault(cl.rev(n), []).append(l)
1500 def events():
1500 def events():
1501 b = "default"
1501 b = "default"
1502 for r in cl:
1502 for r in cl:
1503 if branches:
1503 if branches:
1504 newb = cl.read(cl.node(r))[5]['branch']
1504 newb = cl.read(cl.node(r))[5]['branch']
1505 if newb != b:
1505 if newb != b:
1506 yield 'a', newb
1506 yield 'a', newb
1507 b = newb
1507 b = newb
1508 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1508 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1509 if tags:
1509 if tags:
1510 ls = labels.get(r)
1510 ls = labels.get(r)
1511 if ls:
1511 if ls:
1512 for l in ls:
1512 for l in ls:
1513 yield 'l', (r, l)
1513 yield 'l', (r, l)
1514 else:
1514 else:
1515 raise util.Abort(_('need repo for changelog dag'))
1515 raise util.Abort(_('need repo for changelog dag'))
1516
1516
1517 for line in dagparser.dagtextlines(events(),
1517 for line in dagparser.dagtextlines(events(),
1518 addspaces=spaces,
1518 addspaces=spaces,
1519 wraplabels=True,
1519 wraplabels=True,
1520 wrapannotations=True,
1520 wrapannotations=True,
1521 wrapnonlinear=dots,
1521 wrapnonlinear=dots,
1522 usedots=dots,
1522 usedots=dots,
1523 maxlinewidth=70):
1523 maxlinewidth=70):
1524 ui.write(line)
1524 ui.write(line)
1525 ui.write("\n")
1525 ui.write("\n")
1526
1526
1527 @command('debugdata',
1527 @command('debugdata',
1528 [('c', 'changelog', False, _('open changelog')),
1528 [('c', 'changelog', False, _('open changelog')),
1529 ('m', 'manifest', False, _('open manifest'))],
1529 ('m', 'manifest', False, _('open manifest'))],
1530 _('-c|-m|FILE REV'))
1530 _('-c|-m|FILE REV'))
1531 def debugdata(ui, repo, file_, rev = None, **opts):
1531 def debugdata(ui, repo, file_, rev = None, **opts):
1532 """dump the contents of a data file revision"""
1532 """dump the contents of a data file revision"""
1533 if opts.get('changelog') or opts.get('manifest'):
1533 if opts.get('changelog') or opts.get('manifest'):
1534 file_, rev = None, file_
1534 file_, rev = None, file_
1535 elif rev is None:
1535 elif rev is None:
1536 raise error.CommandError('debugdata', _('invalid arguments'))
1536 raise error.CommandError('debugdata', _('invalid arguments'))
1537 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1537 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1538 try:
1538 try:
1539 ui.write(r.revision(r.lookup(rev)))
1539 ui.write(r.revision(r.lookup(rev)))
1540 except KeyError:
1540 except KeyError:
1541 raise util.Abort(_('invalid revision identifier %s') % rev)
1541 raise util.Abort(_('invalid revision identifier %s') % rev)
1542
1542
1543 @command('debugdate',
1543 @command('debugdate',
1544 [('e', 'extended', None, _('try extended date formats'))],
1544 [('e', 'extended', None, _('try extended date formats'))],
1545 _('[-e] DATE [RANGE]'))
1545 _('[-e] DATE [RANGE]'))
1546 def debugdate(ui, date, range=None, **opts):
1546 def debugdate(ui, date, range=None, **opts):
1547 """parse and display a date"""
1547 """parse and display a date"""
1548 if opts["extended"]:
1548 if opts["extended"]:
1549 d = util.parsedate(date, util.extendeddateformats)
1549 d = util.parsedate(date, util.extendeddateformats)
1550 else:
1550 else:
1551 d = util.parsedate(date)
1551 d = util.parsedate(date)
1552 ui.write("internal: %s %s\n" % d)
1552 ui.write("internal: %s %s\n" % d)
1553 ui.write("standard: %s\n" % util.datestr(d))
1553 ui.write("standard: %s\n" % util.datestr(d))
1554 if range:
1554 if range:
1555 m = util.matchdate(range)
1555 m = util.matchdate(range)
1556 ui.write("match: %s\n" % m(d[0]))
1556 ui.write("match: %s\n" % m(d[0]))
1557
1557
1558 @command('debugdiscovery',
1558 @command('debugdiscovery',
1559 [('', 'old', None, _('use old-style discovery')),
1559 [('', 'old', None, _('use old-style discovery')),
1560 ('', 'nonheads', None,
1560 ('', 'nonheads', None,
1561 _('use old-style discovery with non-heads included')),
1561 _('use old-style discovery with non-heads included')),
1562 ] + remoteopts,
1562 ] + remoteopts,
1563 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1563 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1564 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1564 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1565 """runs the changeset discovery protocol in isolation"""
1565 """runs the changeset discovery protocol in isolation"""
1566 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1566 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1567 remote = hg.peer(repo, opts, remoteurl)
1567 remote = hg.peer(repo, opts, remoteurl)
1568 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1568 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1569
1569
1570 # make sure tests are repeatable
1570 # make sure tests are repeatable
1571 random.seed(12323)
1571 random.seed(12323)
1572
1572
1573 def doit(localheads, remoteheads):
1573 def doit(localheads, remoteheads):
1574 if opts.get('old'):
1574 if opts.get('old'):
1575 if localheads:
1575 if localheads:
1576 raise util.Abort('cannot use localheads with old style discovery')
1576 raise util.Abort('cannot use localheads with old style discovery')
1577 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1577 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1578 force=True)
1578 force=True)
1579 common = set(common)
1579 common = set(common)
1580 if not opts.get('nonheads'):
1580 if not opts.get('nonheads'):
1581 ui.write("unpruned common: %s\n" % " ".join([short(n)
1581 ui.write("unpruned common: %s\n" % " ".join([short(n)
1582 for n in common]))
1582 for n in common]))
1583 dag = dagutil.revlogdag(repo.changelog)
1583 dag = dagutil.revlogdag(repo.changelog)
1584 all = dag.ancestorset(dag.internalizeall(common))
1584 all = dag.ancestorset(dag.internalizeall(common))
1585 common = dag.externalizeall(dag.headsetofconnecteds(all))
1585 common = dag.externalizeall(dag.headsetofconnecteds(all))
1586 else:
1586 else:
1587 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1587 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1588 common = set(common)
1588 common = set(common)
1589 rheads = set(hds)
1589 rheads = set(hds)
1590 lheads = set(repo.heads())
1590 lheads = set(repo.heads())
1591 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1591 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1592 if lheads <= common:
1592 if lheads <= common:
1593 ui.write("local is subset\n")
1593 ui.write("local is subset\n")
1594 elif rheads <= common:
1594 elif rheads <= common:
1595 ui.write("remote is subset\n")
1595 ui.write("remote is subset\n")
1596
1596
1597 serverlogs = opts.get('serverlog')
1597 serverlogs = opts.get('serverlog')
1598 if serverlogs:
1598 if serverlogs:
1599 for filename in serverlogs:
1599 for filename in serverlogs:
1600 logfile = open(filename, 'r')
1600 logfile = open(filename, 'r')
1601 try:
1601 try:
1602 line = logfile.readline()
1602 line = logfile.readline()
1603 while line:
1603 while line:
1604 parts = line.strip().split(';')
1604 parts = line.strip().split(';')
1605 op = parts[1]
1605 op = parts[1]
1606 if op == 'cg':
1606 if op == 'cg':
1607 pass
1607 pass
1608 elif op == 'cgss':
1608 elif op == 'cgss':
1609 doit(parts[2].split(' '), parts[3].split(' '))
1609 doit(parts[2].split(' '), parts[3].split(' '))
1610 elif op == 'unb':
1610 elif op == 'unb':
1611 doit(parts[3].split(' '), parts[2].split(' '))
1611 doit(parts[3].split(' '), parts[2].split(' '))
1612 line = logfile.readline()
1612 line = logfile.readline()
1613 finally:
1613 finally:
1614 logfile.close()
1614 logfile.close()
1615
1615
1616 else:
1616 else:
1617 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1617 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1618 opts.get('remote_head'))
1618 opts.get('remote_head'))
1619 localrevs = opts.get('local_head')
1619 localrevs = opts.get('local_head')
1620 doit(localrevs, remoterevs)
1620 doit(localrevs, remoterevs)
1621
1621
1622 @command('debugfileset', [], ('REVSPEC'))
1622 @command('debugfileset', [], ('REVSPEC'))
1623 def debugfileset(ui, repo, expr):
1623 def debugfileset(ui, repo, expr):
1624 '''parse and apply a fileset specification'''
1624 '''parse and apply a fileset specification'''
1625 if ui.verbose:
1625 if ui.verbose:
1626 tree = fileset.parse(expr)[0]
1626 tree = fileset.parse(expr)[0]
1627 ui.note(tree, "\n")
1627 ui.note(tree, "\n")
1628
1628
1629 for f in fileset.getfileset(repo[None], expr):
1629 for f in fileset.getfileset(repo[None], expr):
1630 ui.write("%s\n" % f)
1630 ui.write("%s\n" % f)
1631
1631
1632 @command('debugfsinfo', [], _('[PATH]'))
1632 @command('debugfsinfo', [], _('[PATH]'))
1633 def debugfsinfo(ui, path = "."):
1633 def debugfsinfo(ui, path = "."):
1634 """show information detected about current filesystem"""
1634 """show information detected about current filesystem"""
1635 util.writefile('.debugfsinfo', '')
1635 util.writefile('.debugfsinfo', '')
1636 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1636 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1637 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1637 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1638 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1638 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1639 and 'yes' or 'no'))
1639 and 'yes' or 'no'))
1640 os.unlink('.debugfsinfo')
1640 os.unlink('.debugfsinfo')
1641
1641
1642 @command('debuggetbundle',
1642 @command('debuggetbundle',
1643 [('H', 'head', [], _('id of head node'), _('ID')),
1643 [('H', 'head', [], _('id of head node'), _('ID')),
1644 ('C', 'common', [], _('id of common node'), _('ID')),
1644 ('C', 'common', [], _('id of common node'), _('ID')),
1645 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1645 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1646 _('REPO FILE [-H|-C ID]...'))
1646 _('REPO FILE [-H|-C ID]...'))
1647 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1647 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1648 """retrieves a bundle from a repo
1648 """retrieves a bundle from a repo
1649
1649
1650 Every ID must be a full-length hex node id string. Saves the bundle to the
1650 Every ID must be a full-length hex node id string. Saves the bundle to the
1651 given file.
1651 given file.
1652 """
1652 """
1653 repo = hg.peer(ui, opts, repopath)
1653 repo = hg.peer(ui, opts, repopath)
1654 if not repo.capable('getbundle'):
1654 if not repo.capable('getbundle'):
1655 raise util.Abort("getbundle() not supported by target repository")
1655 raise util.Abort("getbundle() not supported by target repository")
1656 args = {}
1656 args = {}
1657 if common:
1657 if common:
1658 args['common'] = [bin(s) for s in common]
1658 args['common'] = [bin(s) for s in common]
1659 if head:
1659 if head:
1660 args['heads'] = [bin(s) for s in head]
1660 args['heads'] = [bin(s) for s in head]
1661 bundle = repo.getbundle('debug', **args)
1661 bundle = repo.getbundle('debug', **args)
1662
1662
1663 bundletype = opts.get('type', 'bzip2').lower()
1663 bundletype = opts.get('type', 'bzip2').lower()
1664 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1664 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1665 bundletype = btypes.get(bundletype)
1665 bundletype = btypes.get(bundletype)
1666 if bundletype not in changegroup.bundletypes:
1666 if bundletype not in changegroup.bundletypes:
1667 raise util.Abort(_('unknown bundle type specified with --type'))
1667 raise util.Abort(_('unknown bundle type specified with --type'))
1668 changegroup.writebundle(bundle, bundlepath, bundletype)
1668 changegroup.writebundle(bundle, bundlepath, bundletype)
1669
1669
1670 @command('debugignore', [], '')
1670 @command('debugignore', [], '')
1671 def debugignore(ui, repo, *values, **opts):
1671 def debugignore(ui, repo, *values, **opts):
1672 """display the combined ignore pattern"""
1672 """display the combined ignore pattern"""
1673 ignore = repo.dirstate._ignore
1673 ignore = repo.dirstate._ignore
1674 includepat = getattr(ignore, 'includepat', None)
1674 includepat = getattr(ignore, 'includepat', None)
1675 if includepat is not None:
1675 if includepat is not None:
1676 ui.write("%s\n" % includepat)
1676 ui.write("%s\n" % includepat)
1677 else:
1677 else:
1678 raise util.Abort(_("no ignore patterns found"))
1678 raise util.Abort(_("no ignore patterns found"))
1679
1679
1680 @command('debugindex',
1680 @command('debugindex',
1681 [('c', 'changelog', False, _('open changelog')),
1681 [('c', 'changelog', False, _('open changelog')),
1682 ('m', 'manifest', False, _('open manifest')),
1682 ('m', 'manifest', False, _('open manifest')),
1683 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1683 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1684 _('[-f FORMAT] -c|-m|FILE'))
1684 _('[-f FORMAT] -c|-m|FILE'))
1685 def debugindex(ui, repo, file_ = None, **opts):
1685 def debugindex(ui, repo, file_ = None, **opts):
1686 """dump the contents of an index file"""
1686 """dump the contents of an index file"""
1687 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1687 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1688 format = opts.get('format', 0)
1688 format = opts.get('format', 0)
1689 if format not in (0, 1):
1689 if format not in (0, 1):
1690 raise util.Abort(_("unknown format %d") % format)
1690 raise util.Abort(_("unknown format %d") % format)
1691
1691
1692 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1692 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1693 if generaldelta:
1693 if generaldelta:
1694 basehdr = ' delta'
1694 basehdr = ' delta'
1695 else:
1695 else:
1696 basehdr = ' base'
1696 basehdr = ' base'
1697
1697
1698 if format == 0:
1698 if format == 0:
1699 ui.write(" rev offset length " + basehdr + " linkrev"
1699 ui.write(" rev offset length " + basehdr + " linkrev"
1700 " nodeid p1 p2\n")
1700 " nodeid p1 p2\n")
1701 elif format == 1:
1701 elif format == 1:
1702 ui.write(" rev flag offset length"
1702 ui.write(" rev flag offset length"
1703 " size " + basehdr + " link p1 p2 nodeid\n")
1703 " size " + basehdr + " link p1 p2 nodeid\n")
1704
1704
1705 for i in r:
1705 for i in r:
1706 node = r.node(i)
1706 node = r.node(i)
1707 if generaldelta:
1707 if generaldelta:
1708 base = r.deltaparent(i)
1708 base = r.deltaparent(i)
1709 else:
1709 else:
1710 base = r.chainbase(i)
1710 base = r.chainbase(i)
1711 if format == 0:
1711 if format == 0:
1712 try:
1712 try:
1713 pp = r.parents(node)
1713 pp = r.parents(node)
1714 except:
1714 except:
1715 pp = [nullid, nullid]
1715 pp = [nullid, nullid]
1716 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1716 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1717 i, r.start(i), r.length(i), base, r.linkrev(i),
1717 i, r.start(i), r.length(i), base, r.linkrev(i),
1718 short(node), short(pp[0]), short(pp[1])))
1718 short(node), short(pp[0]), short(pp[1])))
1719 elif format == 1:
1719 elif format == 1:
1720 pr = r.parentrevs(i)
1720 pr = r.parentrevs(i)
1721 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1721 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1722 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1722 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1723 base, r.linkrev(i), pr[0], pr[1], short(node)))
1723 base, r.linkrev(i), pr[0], pr[1], short(node)))
1724
1724
1725 @command('debugindexdot', [], _('FILE'))
1725 @command('debugindexdot', [], _('FILE'))
1726 def debugindexdot(ui, repo, file_):
1726 def debugindexdot(ui, repo, file_):
1727 """dump an index DAG as a graphviz dot file"""
1727 """dump an index DAG as a graphviz dot file"""
1728 r = None
1728 r = None
1729 if repo:
1729 if repo:
1730 filelog = repo.file(file_)
1730 filelog = repo.file(file_)
1731 if len(filelog):
1731 if len(filelog):
1732 r = filelog
1732 r = filelog
1733 if not r:
1733 if not r:
1734 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1734 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1735 ui.write("digraph G {\n")
1735 ui.write("digraph G {\n")
1736 for i in r:
1736 for i in r:
1737 node = r.node(i)
1737 node = r.node(i)
1738 pp = r.parents(node)
1738 pp = r.parents(node)
1739 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1739 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1740 if pp[1] != nullid:
1740 if pp[1] != nullid:
1741 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1741 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1742 ui.write("}\n")
1742 ui.write("}\n")
1743
1743
1744 @command('debuginstall', [], '')
1744 @command('debuginstall', [], '')
1745 def debuginstall(ui):
1745 def debuginstall(ui):
1746 '''test Mercurial installation
1746 '''test Mercurial installation
1747
1747
1748 Returns 0 on success.
1748 Returns 0 on success.
1749 '''
1749 '''
1750
1750
1751 def writetemp(contents):
1751 def writetemp(contents):
1752 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1752 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1753 f = os.fdopen(fd, "wb")
1753 f = os.fdopen(fd, "wb")
1754 f.write(contents)
1754 f.write(contents)
1755 f.close()
1755 f.close()
1756 return name
1756 return name
1757
1757
1758 problems = 0
1758 problems = 0
1759
1759
1760 # encoding
1760 # encoding
1761 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1761 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1762 try:
1762 try:
1763 encoding.fromlocal("test")
1763 encoding.fromlocal("test")
1764 except util.Abort, inst:
1764 except util.Abort, inst:
1765 ui.write(" %s\n" % inst)
1765 ui.write(" %s\n" % inst)
1766 ui.write(_(" (check that your locale is properly set)\n"))
1766 ui.write(_(" (check that your locale is properly set)\n"))
1767 problems += 1
1767 problems += 1
1768
1768
1769 # compiled modules
1769 # compiled modules
1770 ui.status(_("Checking installed modules (%s)...\n")
1770 ui.status(_("Checking installed modules (%s)...\n")
1771 % os.path.dirname(__file__))
1771 % os.path.dirname(__file__))
1772 try:
1772 try:
1773 import bdiff, mpatch, base85, osutil
1773 import bdiff, mpatch, base85, osutil
1774 except Exception, inst:
1774 except Exception, inst:
1775 ui.write(" %s\n" % inst)
1775 ui.write(" %s\n" % inst)
1776 ui.write(_(" One or more extensions could not be found"))
1776 ui.write(_(" One or more extensions could not be found"))
1777 ui.write(_(" (check that you compiled the extensions)\n"))
1777 ui.write(_(" (check that you compiled the extensions)\n"))
1778 problems += 1
1778 problems += 1
1779
1779
1780 # templates
1780 # templates
1781 ui.status(_("Checking templates...\n"))
1781 ui.status(_("Checking templates...\n"))
1782 try:
1782 try:
1783 import templater
1783 import templater
1784 templater.templater(templater.templatepath("map-cmdline.default"))
1784 templater.templater(templater.templatepath("map-cmdline.default"))
1785 except Exception, inst:
1785 except Exception, inst:
1786 ui.write(" %s\n" % inst)
1786 ui.write(" %s\n" % inst)
1787 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1787 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1788 problems += 1
1788 problems += 1
1789
1789
1790 # editor
1790 # editor
1791 ui.status(_("Checking commit editor...\n"))
1791 ui.status(_("Checking commit editor...\n"))
1792 editor = ui.geteditor()
1792 editor = ui.geteditor()
1793 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1793 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1794 if not cmdpath:
1794 if not cmdpath:
1795 if editor == 'vi':
1795 if editor == 'vi':
1796 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1796 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1797 ui.write(_(" (specify a commit editor in your configuration"
1797 ui.write(_(" (specify a commit editor in your configuration"
1798 " file)\n"))
1798 " file)\n"))
1799 else:
1799 else:
1800 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1800 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1801 ui.write(_(" (specify a commit editor in your configuration"
1801 ui.write(_(" (specify a commit editor in your configuration"
1802 " file)\n"))
1802 " file)\n"))
1803 problems += 1
1803 problems += 1
1804
1804
1805 # check username
1805 # check username
1806 ui.status(_("Checking username...\n"))
1806 ui.status(_("Checking username...\n"))
1807 try:
1807 try:
1808 ui.username()
1808 ui.username()
1809 except util.Abort, e:
1809 except util.Abort, e:
1810 ui.write(" %s\n" % e)
1810 ui.write(" %s\n" % e)
1811 ui.write(_(" (specify a username in your configuration file)\n"))
1811 ui.write(_(" (specify a username in your configuration file)\n"))
1812 problems += 1
1812 problems += 1
1813
1813
1814 if not problems:
1814 if not problems:
1815 ui.status(_("No problems detected\n"))
1815 ui.status(_("No problems detected\n"))
1816 else:
1816 else:
1817 ui.write(_("%s problems detected,"
1817 ui.write(_("%s problems detected,"
1818 " please check your install!\n") % problems)
1818 " please check your install!\n") % problems)
1819
1819
1820 return problems
1820 return problems
1821
1821
1822 @command('debugknown', [], _('REPO ID...'))
1822 @command('debugknown', [], _('REPO ID...'))
1823 def debugknown(ui, repopath, *ids, **opts):
1823 def debugknown(ui, repopath, *ids, **opts):
1824 """test whether node ids are known to a repo
1824 """test whether node ids are known to a repo
1825
1825
1826 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1826 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1827 indicating unknown/known.
1827 indicating unknown/known.
1828 """
1828 """
1829 repo = hg.peer(ui, opts, repopath)
1829 repo = hg.peer(ui, opts, repopath)
1830 if not repo.capable('known'):
1830 if not repo.capable('known'):
1831 raise util.Abort("known() not supported by target repository")
1831 raise util.Abort("known() not supported by target repository")
1832 flags = repo.known([bin(s) for s in ids])
1832 flags = repo.known([bin(s) for s in ids])
1833 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1833 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1834
1834
1835 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1835 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1836 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1836 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1837 '''access the pushkey key/value protocol
1837 '''access the pushkey key/value protocol
1838
1838
1839 With two args, list the keys in the given namespace.
1839 With two args, list the keys in the given namespace.
1840
1840
1841 With five args, set a key to new if it currently is set to old.
1841 With five args, set a key to new if it currently is set to old.
1842 Reports success or failure.
1842 Reports success or failure.
1843 '''
1843 '''
1844
1844
1845 target = hg.peer(ui, {}, repopath)
1845 target = hg.peer(ui, {}, repopath)
1846 if keyinfo:
1846 if keyinfo:
1847 key, old, new = keyinfo
1847 key, old, new = keyinfo
1848 r = target.pushkey(namespace, key, old, new)
1848 r = target.pushkey(namespace, key, old, new)
1849 ui.status(str(r) + '\n')
1849 ui.status(str(r) + '\n')
1850 return not r
1850 return not r
1851 else:
1851 else:
1852 for k, v in target.listkeys(namespace).iteritems():
1852 for k, v in target.listkeys(namespace).iteritems():
1853 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1853 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1854 v.encode('string-escape')))
1854 v.encode('string-escape')))
1855
1855
1856 @command('debugrebuildstate',
1856 @command('debugrebuildstate',
1857 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1857 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1858 _('[-r REV] [REV]'))
1858 _('[-r REV] [REV]'))
1859 def debugrebuildstate(ui, repo, rev="tip"):
1859 def debugrebuildstate(ui, repo, rev="tip"):
1860 """rebuild the dirstate as it would look like for the given revision"""
1860 """rebuild the dirstate as it would look like for the given revision"""
1861 ctx = scmutil.revsingle(repo, rev)
1861 ctx = scmutil.revsingle(repo, rev)
1862 wlock = repo.wlock()
1862 wlock = repo.wlock()
1863 try:
1863 try:
1864 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1864 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1865 finally:
1865 finally:
1866 wlock.release()
1866 wlock.release()
1867
1867
1868 @command('debugrename',
1868 @command('debugrename',
1869 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1869 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1870 _('[-r REV] FILE'))
1870 _('[-r REV] FILE'))
1871 def debugrename(ui, repo, file1, *pats, **opts):
1871 def debugrename(ui, repo, file1, *pats, **opts):
1872 """dump rename information"""
1872 """dump rename information"""
1873
1873
1874 ctx = scmutil.revsingle(repo, opts.get('rev'))
1874 ctx = scmutil.revsingle(repo, opts.get('rev'))
1875 m = scmutil.match(ctx, (file1,) + pats, opts)
1875 m = scmutil.match(ctx, (file1,) + pats, opts)
1876 for abs in ctx.walk(m):
1876 for abs in ctx.walk(m):
1877 fctx = ctx[abs]
1877 fctx = ctx[abs]
1878 o = fctx.filelog().renamed(fctx.filenode())
1878 o = fctx.filelog().renamed(fctx.filenode())
1879 rel = m.rel(abs)
1879 rel = m.rel(abs)
1880 if o:
1880 if o:
1881 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1881 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1882 else:
1882 else:
1883 ui.write(_("%s not renamed\n") % rel)
1883 ui.write(_("%s not renamed\n") % rel)
1884
1884
1885 @command('debugrevlog',
1885 @command('debugrevlog',
1886 [('c', 'changelog', False, _('open changelog')),
1886 [('c', 'changelog', False, _('open changelog')),
1887 ('m', 'manifest', False, _('open manifest')),
1887 ('m', 'manifest', False, _('open manifest')),
1888 ('d', 'dump', False, _('dump index data'))],
1888 ('d', 'dump', False, _('dump index data'))],
1889 _('-c|-m|FILE'))
1889 _('-c|-m|FILE'))
1890 def debugrevlog(ui, repo, file_ = None, **opts):
1890 def debugrevlog(ui, repo, file_ = None, **opts):
1891 """show data and statistics about a revlog"""
1891 """show data and statistics about a revlog"""
1892 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1892 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1893
1893
1894 if opts.get("dump"):
1894 if opts.get("dump"):
1895 numrevs = len(r)
1895 numrevs = len(r)
1896 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1896 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1897 " rawsize totalsize compression heads\n")
1897 " rawsize totalsize compression heads\n")
1898 ts = 0
1898 ts = 0
1899 heads = set()
1899 heads = set()
1900 for rev in xrange(numrevs):
1900 for rev in xrange(numrevs):
1901 dbase = r.deltaparent(rev)
1901 dbase = r.deltaparent(rev)
1902 if dbase == -1:
1902 if dbase == -1:
1903 dbase = rev
1903 dbase = rev
1904 cbase = r.chainbase(rev)
1904 cbase = r.chainbase(rev)
1905 p1, p2 = r.parentrevs(rev)
1905 p1, p2 = r.parentrevs(rev)
1906 rs = r.rawsize(rev)
1906 rs = r.rawsize(rev)
1907 ts = ts + rs
1907 ts = ts + rs
1908 heads -= set(r.parentrevs(rev))
1908 heads -= set(r.parentrevs(rev))
1909 heads.add(rev)
1909 heads.add(rev)
1910 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1910 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1911 (rev, p1, p2, r.start(rev), r.end(rev),
1911 (rev, p1, p2, r.start(rev), r.end(rev),
1912 r.start(dbase), r.start(cbase),
1912 r.start(dbase), r.start(cbase),
1913 r.start(p1), r.start(p2),
1913 r.start(p1), r.start(p2),
1914 rs, ts, ts / r.end(rev), len(heads)))
1914 rs, ts, ts / r.end(rev), len(heads)))
1915 return 0
1915 return 0
1916
1916
1917 v = r.version
1917 v = r.version
1918 format = v & 0xFFFF
1918 format = v & 0xFFFF
1919 flags = []
1919 flags = []
1920 gdelta = False
1920 gdelta = False
1921 if v & revlog.REVLOGNGINLINEDATA:
1921 if v & revlog.REVLOGNGINLINEDATA:
1922 flags.append('inline')
1922 flags.append('inline')
1923 if v & revlog.REVLOGGENERALDELTA:
1923 if v & revlog.REVLOGGENERALDELTA:
1924 gdelta = True
1924 gdelta = True
1925 flags.append('generaldelta')
1925 flags.append('generaldelta')
1926 if not flags:
1926 if not flags:
1927 flags = ['(none)']
1927 flags = ['(none)']
1928
1928
1929 nummerges = 0
1929 nummerges = 0
1930 numfull = 0
1930 numfull = 0
1931 numprev = 0
1931 numprev = 0
1932 nump1 = 0
1932 nump1 = 0
1933 nump2 = 0
1933 nump2 = 0
1934 numother = 0
1934 numother = 0
1935 nump1prev = 0
1935 nump1prev = 0
1936 nump2prev = 0
1936 nump2prev = 0
1937 chainlengths = []
1937 chainlengths = []
1938
1938
1939 datasize = [None, 0, 0L]
1939 datasize = [None, 0, 0L]
1940 fullsize = [None, 0, 0L]
1940 fullsize = [None, 0, 0L]
1941 deltasize = [None, 0, 0L]
1941 deltasize = [None, 0, 0L]
1942
1942
1943 def addsize(size, l):
1943 def addsize(size, l):
1944 if l[0] is None or size < l[0]:
1944 if l[0] is None or size < l[0]:
1945 l[0] = size
1945 l[0] = size
1946 if size > l[1]:
1946 if size > l[1]:
1947 l[1] = size
1947 l[1] = size
1948 l[2] += size
1948 l[2] += size
1949
1949
1950 numrevs = len(r)
1950 numrevs = len(r)
1951 for rev in xrange(numrevs):
1951 for rev in xrange(numrevs):
1952 p1, p2 = r.parentrevs(rev)
1952 p1, p2 = r.parentrevs(rev)
1953 delta = r.deltaparent(rev)
1953 delta = r.deltaparent(rev)
1954 if format > 0:
1954 if format > 0:
1955 addsize(r.rawsize(rev), datasize)
1955 addsize(r.rawsize(rev), datasize)
1956 if p2 != nullrev:
1956 if p2 != nullrev:
1957 nummerges += 1
1957 nummerges += 1
1958 size = r.length(rev)
1958 size = r.length(rev)
1959 if delta == nullrev:
1959 if delta == nullrev:
1960 chainlengths.append(0)
1960 chainlengths.append(0)
1961 numfull += 1
1961 numfull += 1
1962 addsize(size, fullsize)
1962 addsize(size, fullsize)
1963 else:
1963 else:
1964 chainlengths.append(chainlengths[delta] + 1)
1964 chainlengths.append(chainlengths[delta] + 1)
1965 addsize(size, deltasize)
1965 addsize(size, deltasize)
1966 if delta == rev - 1:
1966 if delta == rev - 1:
1967 numprev += 1
1967 numprev += 1
1968 if delta == p1:
1968 if delta == p1:
1969 nump1prev += 1
1969 nump1prev += 1
1970 elif delta == p2:
1970 elif delta == p2:
1971 nump2prev += 1
1971 nump2prev += 1
1972 elif delta == p1:
1972 elif delta == p1:
1973 nump1 += 1
1973 nump1 += 1
1974 elif delta == p2:
1974 elif delta == p2:
1975 nump2 += 1
1975 nump2 += 1
1976 elif delta != nullrev:
1976 elif delta != nullrev:
1977 numother += 1
1977 numother += 1
1978
1978
1979 numdeltas = numrevs - numfull
1979 numdeltas = numrevs - numfull
1980 numoprev = numprev - nump1prev - nump2prev
1980 numoprev = numprev - nump1prev - nump2prev
1981 totalrawsize = datasize[2]
1981 totalrawsize = datasize[2]
1982 datasize[2] /= numrevs
1982 datasize[2] /= numrevs
1983 fulltotal = fullsize[2]
1983 fulltotal = fullsize[2]
1984 fullsize[2] /= numfull
1984 fullsize[2] /= numfull
1985 deltatotal = deltasize[2]
1985 deltatotal = deltasize[2]
1986 deltasize[2] /= numrevs - numfull
1986 deltasize[2] /= numrevs - numfull
1987 totalsize = fulltotal + deltatotal
1987 totalsize = fulltotal + deltatotal
1988 avgchainlen = sum(chainlengths) / numrevs
1988 avgchainlen = sum(chainlengths) / numrevs
1989 compratio = totalrawsize / totalsize
1989 compratio = totalrawsize / totalsize
1990
1990
1991 basedfmtstr = '%%%dd\n'
1991 basedfmtstr = '%%%dd\n'
1992 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1992 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1993
1993
1994 def dfmtstr(max):
1994 def dfmtstr(max):
1995 return basedfmtstr % len(str(max))
1995 return basedfmtstr % len(str(max))
1996 def pcfmtstr(max, padding=0):
1996 def pcfmtstr(max, padding=0):
1997 return basepcfmtstr % (len(str(max)), ' ' * padding)
1997 return basepcfmtstr % (len(str(max)), ' ' * padding)
1998
1998
1999 def pcfmt(value, total):
1999 def pcfmt(value, total):
2000 return (value, 100 * float(value) / total)
2000 return (value, 100 * float(value) / total)
2001
2001
2002 ui.write('format : %d\n' % format)
2002 ui.write('format : %d\n' % format)
2003 ui.write('flags : %s\n' % ', '.join(flags))
2003 ui.write('flags : %s\n' % ', '.join(flags))
2004
2004
2005 ui.write('\n')
2005 ui.write('\n')
2006 fmt = pcfmtstr(totalsize)
2006 fmt = pcfmtstr(totalsize)
2007 fmt2 = dfmtstr(totalsize)
2007 fmt2 = dfmtstr(totalsize)
2008 ui.write('revisions : ' + fmt2 % numrevs)
2008 ui.write('revisions : ' + fmt2 % numrevs)
2009 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2009 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2010 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2010 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2011 ui.write('revisions : ' + fmt2 % numrevs)
2011 ui.write('revisions : ' + fmt2 % numrevs)
2012 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2012 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2013 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2013 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2014 ui.write('revision size : ' + fmt2 % totalsize)
2014 ui.write('revision size : ' + fmt2 % totalsize)
2015 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2015 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2016 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2016 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2017
2017
2018 ui.write('\n')
2018 ui.write('\n')
2019 fmt = dfmtstr(max(avgchainlen, compratio))
2019 fmt = dfmtstr(max(avgchainlen, compratio))
2020 ui.write('avg chain length : ' + fmt % avgchainlen)
2020 ui.write('avg chain length : ' + fmt % avgchainlen)
2021 ui.write('compression ratio : ' + fmt % compratio)
2021 ui.write('compression ratio : ' + fmt % compratio)
2022
2022
2023 if format > 0:
2023 if format > 0:
2024 ui.write('\n')
2024 ui.write('\n')
2025 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2025 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2026 % tuple(datasize))
2026 % tuple(datasize))
2027 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2027 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2028 % tuple(fullsize))
2028 % tuple(fullsize))
2029 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2029 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2030 % tuple(deltasize))
2030 % tuple(deltasize))
2031
2031
2032 if numdeltas > 0:
2032 if numdeltas > 0:
2033 ui.write('\n')
2033 ui.write('\n')
2034 fmt = pcfmtstr(numdeltas)
2034 fmt = pcfmtstr(numdeltas)
2035 fmt2 = pcfmtstr(numdeltas, 4)
2035 fmt2 = pcfmtstr(numdeltas, 4)
2036 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2036 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2037 if numprev > 0:
2037 if numprev > 0:
2038 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2038 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2039 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2039 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2040 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2040 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2041 if gdelta:
2041 if gdelta:
2042 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2042 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2043 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2043 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2044 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2044 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2045
2045
2046 @command('debugrevspec', [], ('REVSPEC'))
2046 @command('debugrevspec', [], ('REVSPEC'))
2047 def debugrevspec(ui, repo, expr):
2047 def debugrevspec(ui, repo, expr):
2048 '''parse and apply a revision specification'''
2048 '''parse and apply a revision specification'''
2049 if ui.verbose:
2049 if ui.verbose:
2050 tree = revset.parse(expr)[0]
2050 tree = revset.parse(expr)[0]
2051 ui.note(tree, "\n")
2051 ui.note(tree, "\n")
2052 newtree = revset.findaliases(ui, tree)
2052 newtree = revset.findaliases(ui, tree)
2053 if newtree != tree:
2053 if newtree != tree:
2054 ui.note(newtree, "\n")
2054 ui.note(newtree, "\n")
2055 func = revset.match(ui, expr)
2055 func = revset.match(ui, expr)
2056 for c in func(repo, range(len(repo))):
2056 for c in func(repo, range(len(repo))):
2057 ui.write("%s\n" % c)
2057 ui.write("%s\n" % c)
2058
2058
2059 @command('debugsetparents', [], _('REV1 [REV2]'))
2059 @command('debugsetparents', [], _('REV1 [REV2]'))
2060 def debugsetparents(ui, repo, rev1, rev2=None):
2060 def debugsetparents(ui, repo, rev1, rev2=None):
2061 """manually set the parents of the current working directory
2061 """manually set the parents of the current working directory
2062
2062
2063 This is useful for writing repository conversion tools, but should
2063 This is useful for writing repository conversion tools, but should
2064 be used with care.
2064 be used with care.
2065
2065
2066 Returns 0 on success.
2066 Returns 0 on success.
2067 """
2067 """
2068
2068
2069 r1 = scmutil.revsingle(repo, rev1).node()
2069 r1 = scmutil.revsingle(repo, rev1).node()
2070 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2070 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2071
2071
2072 wlock = repo.wlock()
2072 wlock = repo.wlock()
2073 try:
2073 try:
2074 repo.dirstate.setparents(r1, r2)
2074 repo.dirstate.setparents(r1, r2)
2075 finally:
2075 finally:
2076 wlock.release()
2076 wlock.release()
2077
2077
2078 @command('debugstate',
2078 @command('debugstate',
2079 [('', 'nodates', None, _('do not display the saved mtime')),
2079 [('', 'nodates', None, _('do not display the saved mtime')),
2080 ('', 'datesort', None, _('sort by saved mtime'))],
2080 ('', 'datesort', None, _('sort by saved mtime'))],
2081 _('[OPTION]...'))
2081 _('[OPTION]...'))
2082 def debugstate(ui, repo, nodates=None, datesort=None):
2082 def debugstate(ui, repo, nodates=None, datesort=None):
2083 """show the contents of the current dirstate"""
2083 """show the contents of the current dirstate"""
2084 timestr = ""
2084 timestr = ""
2085 showdate = not nodates
2085 showdate = not nodates
2086 if datesort:
2086 if datesort:
2087 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2087 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2088 else:
2088 else:
2089 keyfunc = None # sort by filename
2089 keyfunc = None # sort by filename
2090 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2090 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2091 if showdate:
2091 if showdate:
2092 if ent[3] == -1:
2092 if ent[3] == -1:
2093 # Pad or slice to locale representation
2093 # Pad or slice to locale representation
2094 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2094 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2095 time.localtime(0)))
2095 time.localtime(0)))
2096 timestr = 'unset'
2096 timestr = 'unset'
2097 timestr = (timestr[:locale_len] +
2097 timestr = (timestr[:locale_len] +
2098 ' ' * (locale_len - len(timestr)))
2098 ' ' * (locale_len - len(timestr)))
2099 else:
2099 else:
2100 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2100 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2101 time.localtime(ent[3]))
2101 time.localtime(ent[3]))
2102 if ent[1] & 020000:
2102 if ent[1] & 020000:
2103 mode = 'lnk'
2103 mode = 'lnk'
2104 else:
2104 else:
2105 mode = '%3o' % (ent[1] & 0777)
2105 mode = '%3o' % (ent[1] & 0777)
2106 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2106 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2107 for f in repo.dirstate.copies():
2107 for f in repo.dirstate.copies():
2108 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2108 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2109
2109
2110 @command('debugsub',
2110 @command('debugsub',
2111 [('r', 'rev', '',
2111 [('r', 'rev', '',
2112 _('revision to check'), _('REV'))],
2112 _('revision to check'), _('REV'))],
2113 _('[-r REV] [REV]'))
2113 _('[-r REV] [REV]'))
2114 def debugsub(ui, repo, rev=None):
2114 def debugsub(ui, repo, rev=None):
2115 ctx = scmutil.revsingle(repo, rev, None)
2115 ctx = scmutil.revsingle(repo, rev, None)
2116 for k, v in sorted(ctx.substate.items()):
2116 for k, v in sorted(ctx.substate.items()):
2117 ui.write('path %s\n' % k)
2117 ui.write('path %s\n' % k)
2118 ui.write(' source %s\n' % v[0])
2118 ui.write(' source %s\n' % v[0])
2119 ui.write(' revision %s\n' % v[1])
2119 ui.write(' revision %s\n' % v[1])
2120
2120
2121 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2121 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2122 def debugwalk(ui, repo, *pats, **opts):
2122 def debugwalk(ui, repo, *pats, **opts):
2123 """show how files match on given patterns"""
2123 """show how files match on given patterns"""
2124 m = scmutil.match(repo[None], pats, opts)
2124 m = scmutil.match(repo[None], pats, opts)
2125 items = list(repo.walk(m))
2125 items = list(repo.walk(m))
2126 if not items:
2126 if not items:
2127 return
2127 return
2128 fmt = 'f %%-%ds %%-%ds %%s' % (
2128 fmt = 'f %%-%ds %%-%ds %%s' % (
2129 max([len(abs) for abs in items]),
2129 max([len(abs) for abs in items]),
2130 max([len(m.rel(abs)) for abs in items]))
2130 max([len(m.rel(abs)) for abs in items]))
2131 for abs in items:
2131 for abs in items:
2132 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2132 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2133 ui.write("%s\n" % line.rstrip())
2133 ui.write("%s\n" % line.rstrip())
2134
2134
2135 @command('debugwireargs',
2135 @command('debugwireargs',
2136 [('', 'three', '', 'three'),
2136 [('', 'three', '', 'three'),
2137 ('', 'four', '', 'four'),
2137 ('', 'four', '', 'four'),
2138 ('', 'five', '', 'five'),
2138 ('', 'five', '', 'five'),
2139 ] + remoteopts,
2139 ] + remoteopts,
2140 _('REPO [OPTIONS]... [ONE [TWO]]'))
2140 _('REPO [OPTIONS]... [ONE [TWO]]'))
2141 def debugwireargs(ui, repopath, *vals, **opts):
2141 def debugwireargs(ui, repopath, *vals, **opts):
2142 repo = hg.peer(ui, opts, repopath)
2142 repo = hg.peer(ui, opts, repopath)
2143 for opt in remoteopts:
2143 for opt in remoteopts:
2144 del opts[opt[1]]
2144 del opts[opt[1]]
2145 args = {}
2145 args = {}
2146 for k, v in opts.iteritems():
2146 for k, v in opts.iteritems():
2147 if v:
2147 if v:
2148 args[k] = v
2148 args[k] = v
2149 # run twice to check that we don't mess up the stream for the next command
2149 # run twice to check that we don't mess up the stream for the next command
2150 res1 = repo.debugwireargs(*vals, **args)
2150 res1 = repo.debugwireargs(*vals, **args)
2151 res2 = repo.debugwireargs(*vals, **args)
2151 res2 = repo.debugwireargs(*vals, **args)
2152 ui.write("%s\n" % res1)
2152 ui.write("%s\n" % res1)
2153 if res1 != res2:
2153 if res1 != res2:
2154 ui.warn("%s\n" % res2)
2154 ui.warn("%s\n" % res2)
2155
2155
2156 @command('^diff',
2156 @command('^diff',
2157 [('r', 'rev', [], _('revision'), _('REV')),
2157 [('r', 'rev', [], _('revision'), _('REV')),
2158 ('c', 'change', '', _('change made by revision'), _('REV'))
2158 ('c', 'change', '', _('change made by revision'), _('REV'))
2159 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2159 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2160 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2160 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2161 def diff(ui, repo, *pats, **opts):
2161 def diff(ui, repo, *pats, **opts):
2162 """diff repository (or selected files)
2162 """diff repository (or selected files)
2163
2163
2164 Show differences between revisions for the specified files.
2164 Show differences between revisions for the specified files.
2165
2165
2166 Differences between files are shown using the unified diff format.
2166 Differences between files are shown using the unified diff format.
2167
2167
2168 .. note::
2168 .. note::
2169 diff may generate unexpected results for merges, as it will
2169 diff may generate unexpected results for merges, as it will
2170 default to comparing against the working directory's first
2170 default to comparing against the working directory's first
2171 parent changeset if no revisions are specified.
2171 parent changeset if no revisions are specified.
2172
2172
2173 When two revision arguments are given, then changes are shown
2173 When two revision arguments are given, then changes are shown
2174 between those revisions. If only one revision is specified then
2174 between those revisions. If only one revision is specified then
2175 that revision is compared to the working directory, and, when no
2175 that revision is compared to the working directory, and, when no
2176 revisions are specified, the working directory files are compared
2176 revisions are specified, the working directory files are compared
2177 to its parent.
2177 to its parent.
2178
2178
2179 Alternatively you can specify -c/--change with a revision to see
2179 Alternatively you can specify -c/--change with a revision to see
2180 the changes in that changeset relative to its first parent.
2180 the changes in that changeset relative to its first parent.
2181
2181
2182 Without the -a/--text option, diff will avoid generating diffs of
2182 Without the -a/--text option, diff will avoid generating diffs of
2183 files it detects as binary. With -a, diff will generate a diff
2183 files it detects as binary. With -a, diff will generate a diff
2184 anyway, probably with undesirable results.
2184 anyway, probably with undesirable results.
2185
2185
2186 Use the -g/--git option to generate diffs in the git extended diff
2186 Use the -g/--git option to generate diffs in the git extended diff
2187 format. For more information, read :hg:`help diffs`.
2187 format. For more information, read :hg:`help diffs`.
2188
2188
2189 .. container:: verbose
2189 .. container:: verbose
2190
2190
2191 Examples:
2191 Examples:
2192
2192
2193 - compare a file in the current working directory to its parent::
2193 - compare a file in the current working directory to its parent::
2194
2194
2195 hg diff foo.c
2195 hg diff foo.c
2196
2196
2197 - compare two historical versions of a directory, with rename info::
2197 - compare two historical versions of a directory, with rename info::
2198
2198
2199 hg diff --git -r 1.0:1.2 lib/
2199 hg diff --git -r 1.0:1.2 lib/
2200
2200
2201 - get change stats relative to the last change on some date::
2201 - get change stats relative to the last change on some date::
2202
2202
2203 hg diff --stat -r "date('may 2')"
2203 hg diff --stat -r "date('may 2')"
2204
2204
2205 - diff all newly-added files that contain a keyword::
2205 - diff all newly-added files that contain a keyword::
2206
2206
2207 hg diff "set:added() and grep(GNU)"
2207 hg diff "set:added() and grep(GNU)"
2208
2208
2209 - compare a revision and its parents::
2209 - compare a revision and its parents::
2210
2210
2211 hg diff -c 9353 # compare against first parent
2211 hg diff -c 9353 # compare against first parent
2212 hg diff -r 9353^:9353 # same using revset syntax
2212 hg diff -r 9353^:9353 # same using revset syntax
2213 hg diff -r 9353^2:9353 # compare against the second parent
2213 hg diff -r 9353^2:9353 # compare against the second parent
2214
2214
2215 Returns 0 on success.
2215 Returns 0 on success.
2216 """
2216 """
2217
2217
2218 revs = opts.get('rev')
2218 revs = opts.get('rev')
2219 change = opts.get('change')
2219 change = opts.get('change')
2220 stat = opts.get('stat')
2220 stat = opts.get('stat')
2221 reverse = opts.get('reverse')
2221 reverse = opts.get('reverse')
2222
2222
2223 if revs and change:
2223 if revs and change:
2224 msg = _('cannot specify --rev and --change at the same time')
2224 msg = _('cannot specify --rev and --change at the same time')
2225 raise util.Abort(msg)
2225 raise util.Abort(msg)
2226 elif change:
2226 elif change:
2227 node2 = scmutil.revsingle(repo, change, None).node()
2227 node2 = scmutil.revsingle(repo, change, None).node()
2228 node1 = repo[node2].p1().node()
2228 node1 = repo[node2].p1().node()
2229 else:
2229 else:
2230 node1, node2 = scmutil.revpair(repo, revs)
2230 node1, node2 = scmutil.revpair(repo, revs)
2231
2231
2232 if reverse:
2232 if reverse:
2233 node1, node2 = node2, node1
2233 node1, node2 = node2, node1
2234
2234
2235 diffopts = patch.diffopts(ui, opts)
2235 diffopts = patch.diffopts(ui, opts)
2236 m = scmutil.match(repo[node2], pats, opts)
2236 m = scmutil.match(repo[node2], pats, opts)
2237 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2237 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2238 listsubrepos=opts.get('subrepos'))
2238 listsubrepos=opts.get('subrepos'))
2239
2239
2240 @command('^export',
2240 @command('^export',
2241 [('o', 'output', '',
2241 [('o', 'output', '',
2242 _('print output to file with formatted name'), _('FORMAT')),
2242 _('print output to file with formatted name'), _('FORMAT')),
2243 ('', 'switch-parent', None, _('diff against the second parent')),
2243 ('', 'switch-parent', None, _('diff against the second parent')),
2244 ('r', 'rev', [], _('revisions to export'), _('REV')),
2244 ('r', 'rev', [], _('revisions to export'), _('REV')),
2245 ] + diffopts,
2245 ] + diffopts,
2246 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2246 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2247 def export(ui, repo, *changesets, **opts):
2247 def export(ui, repo, *changesets, **opts):
2248 """dump the header and diffs for one or more changesets
2248 """dump the header and diffs for one or more changesets
2249
2249
2250 Print the changeset header and diffs for one or more revisions.
2250 Print the changeset header and diffs for one or more revisions.
2251
2251
2252 The information shown in the changeset header is: author, date,
2252 The information shown in the changeset header is: author, date,
2253 branch name (if non-default), changeset hash, parent(s) and commit
2253 branch name (if non-default), changeset hash, parent(s) and commit
2254 comment.
2254 comment.
2255
2255
2256 .. note::
2256 .. note::
2257 export may generate unexpected diff output for merge
2257 export may generate unexpected diff output for merge
2258 changesets, as it will compare the merge changeset against its
2258 changesets, as it will compare the merge changeset against its
2259 first parent only.
2259 first parent only.
2260
2260
2261 Output may be to a file, in which case the name of the file is
2261 Output may be to a file, in which case the name of the file is
2262 given using a format string. The formatting rules are as follows:
2262 given using a format string. The formatting rules are as follows:
2263
2263
2264 :``%%``: literal "%" character
2264 :``%%``: literal "%" character
2265 :``%H``: changeset hash (40 hexadecimal digits)
2265 :``%H``: changeset hash (40 hexadecimal digits)
2266 :``%N``: number of patches being generated
2266 :``%N``: number of patches being generated
2267 :``%R``: changeset revision number
2267 :``%R``: changeset revision number
2268 :``%b``: basename of the exporting repository
2268 :``%b``: basename of the exporting repository
2269 :``%h``: short-form changeset hash (12 hexadecimal digits)
2269 :``%h``: short-form changeset hash (12 hexadecimal digits)
2270 :``%m``: first line of the commit message (only alphanumeric characters)
2270 :``%m``: first line of the commit message (only alphanumeric characters)
2271 :``%n``: zero-padded sequence number, starting at 1
2271 :``%n``: zero-padded sequence number, starting at 1
2272 :``%r``: zero-padded changeset revision number
2272 :``%r``: zero-padded changeset revision number
2273
2273
2274 Without the -a/--text option, export will avoid generating diffs
2274 Without the -a/--text option, export will avoid generating diffs
2275 of files it detects as binary. With -a, export will generate a
2275 of files it detects as binary. With -a, export will generate a
2276 diff anyway, probably with undesirable results.
2276 diff anyway, probably with undesirable results.
2277
2277
2278 Use the -g/--git option to generate diffs in the git extended diff
2278 Use the -g/--git option to generate diffs in the git extended diff
2279 format. See :hg:`help diffs` for more information.
2279 format. See :hg:`help diffs` for more information.
2280
2280
2281 With the --switch-parent option, the diff will be against the
2281 With the --switch-parent option, the diff will be against the
2282 second parent. It can be useful to review a merge.
2282 second parent. It can be useful to review a merge.
2283
2283
2284 .. container:: verbose
2284 .. container:: verbose
2285
2285
2286 Examples:
2286 Examples:
2287
2287
2288 - use export and import to transplant a bugfix to the current
2288 - use export and import to transplant a bugfix to the current
2289 branch::
2289 branch::
2290
2290
2291 hg export -r 9353 | hg import -
2291 hg export -r 9353 | hg import -
2292
2292
2293 - export all the changesets between two revisions to a file with
2293 - export all the changesets between two revisions to a file with
2294 rename information::
2294 rename information::
2295
2295
2296 hg export --git -r 123:150 > changes.txt
2296 hg export --git -r 123:150 > changes.txt
2297
2297
2298 - split outgoing changes into a series of patches with
2298 - split outgoing changes into a series of patches with
2299 descriptive names::
2299 descriptive names::
2300
2300
2301 hg export -r "outgoing()" -o "%n-%m.patch"
2301 hg export -r "outgoing()" -o "%n-%m.patch"
2302
2302
2303 Returns 0 on success.
2303 Returns 0 on success.
2304 """
2304 """
2305 changesets += tuple(opts.get('rev', []))
2305 changesets += tuple(opts.get('rev', []))
2306 if not changesets:
2306 if not changesets:
2307 raise util.Abort(_("export requires at least one changeset"))
2307 raise util.Abort(_("export requires at least one changeset"))
2308 revs = scmutil.revrange(repo, changesets)
2308 revs = scmutil.revrange(repo, changesets)
2309 if len(revs) > 1:
2309 if len(revs) > 1:
2310 ui.note(_('exporting patches:\n'))
2310 ui.note(_('exporting patches:\n'))
2311 else:
2311 else:
2312 ui.note(_('exporting patch:\n'))
2312 ui.note(_('exporting patch:\n'))
2313 cmdutil.export(repo, revs, template=opts.get('output'),
2313 cmdutil.export(repo, revs, template=opts.get('output'),
2314 switch_parent=opts.get('switch_parent'),
2314 switch_parent=opts.get('switch_parent'),
2315 opts=patch.diffopts(ui, opts))
2315 opts=patch.diffopts(ui, opts))
2316
2316
2317 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2317 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2318 def forget(ui, repo, *pats, **opts):
2318 def forget(ui, repo, *pats, **opts):
2319 """forget the specified files on the next commit
2319 """forget the specified files on the next commit
2320
2320
2321 Mark the specified files so they will no longer be tracked
2321 Mark the specified files so they will no longer be tracked
2322 after the next commit.
2322 after the next commit.
2323
2323
2324 This only removes files from the current branch, not from the
2324 This only removes files from the current branch, not from the
2325 entire project history, and it does not delete them from the
2325 entire project history, and it does not delete them from the
2326 working directory.
2326 working directory.
2327
2327
2328 To undo a forget before the next commit, see :hg:`add`.
2328 To undo a forget before the next commit, see :hg:`add`.
2329
2329
2330 Returns 0 on success.
2330 Returns 0 on success.
2331 """
2331 """
2332
2332
2333 if not pats:
2333 if not pats:
2334 raise util.Abort(_('no files specified'))
2334 raise util.Abort(_('no files specified'))
2335
2335
2336 m = scmutil.match(repo[None], pats, opts)
2336 m = scmutil.match(repo[None], pats, opts)
2337 s = repo.status(match=m, clean=True)
2337 s = repo.status(match=m, clean=True)
2338 forget = sorted(s[0] + s[1] + s[3] + s[6])
2338 forget = sorted(s[0] + s[1] + s[3] + s[6])
2339 errs = 0
2339 errs = 0
2340
2340
2341 for f in m.files():
2341 for f in m.files():
2342 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2342 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2343 if os.path.exists(m.rel(f)):
2343 if os.path.exists(m.rel(f)):
2344 ui.warn(_('not removing %s: file is already untracked\n')
2344 ui.warn(_('not removing %s: file is already untracked\n')
2345 % m.rel(f))
2345 % m.rel(f))
2346 errs = 1
2346 errs = 1
2347
2347
2348 for f in forget:
2348 for f in forget:
2349 if ui.verbose or not m.exact(f):
2349 if ui.verbose or not m.exact(f):
2350 ui.status(_('removing %s\n') % m.rel(f))
2350 ui.status(_('removing %s\n') % m.rel(f))
2351
2351
2352 repo[None].forget(forget)
2352 repo[None].forget(forget)
2353 return errs
2353 return errs
2354
2354
2355 @command('grep',
2355 @command('grep',
2356 [('0', 'print0', None, _('end fields with NUL')),
2356 [('0', 'print0', None, _('end fields with NUL')),
2357 ('', 'all', None, _('print all revisions that match')),
2357 ('', 'all', None, _('print all revisions that match')),
2358 ('a', 'text', None, _('treat all files as text')),
2358 ('a', 'text', None, _('treat all files as text')),
2359 ('f', 'follow', None,
2359 ('f', 'follow', None,
2360 _('follow changeset history,'
2360 _('follow changeset history,'
2361 ' or file history across copies and renames')),
2361 ' or file history across copies and renames')),
2362 ('i', 'ignore-case', None, _('ignore case when matching')),
2362 ('i', 'ignore-case', None, _('ignore case when matching')),
2363 ('l', 'files-with-matches', None,
2363 ('l', 'files-with-matches', None,
2364 _('print only filenames and revisions that match')),
2364 _('print only filenames and revisions that match')),
2365 ('n', 'line-number', None, _('print matching line numbers')),
2365 ('n', 'line-number', None, _('print matching line numbers')),
2366 ('r', 'rev', [],
2366 ('r', 'rev', [],
2367 _('only search files changed within revision range'), _('REV')),
2367 _('only search files changed within revision range'), _('REV')),
2368 ('u', 'user', None, _('list the author (long with -v)')),
2368 ('u', 'user', None, _('list the author (long with -v)')),
2369 ('d', 'date', None, _('list the date (short with -q)')),
2369 ('d', 'date', None, _('list the date (short with -q)')),
2370 ] + walkopts,
2370 ] + walkopts,
2371 _('[OPTION]... PATTERN [FILE]...'))
2371 _('[OPTION]... PATTERN [FILE]...'))
2372 def grep(ui, repo, pattern, *pats, **opts):
2372 def grep(ui, repo, pattern, *pats, **opts):
2373 """search for a pattern in specified files and revisions
2373 """search for a pattern in specified files and revisions
2374
2374
2375 Search revisions of files for a regular expression.
2375 Search revisions of files for a regular expression.
2376
2376
2377 This command behaves differently than Unix grep. It only accepts
2377 This command behaves differently than Unix grep. It only accepts
2378 Python/Perl regexps. It searches repository history, not the
2378 Python/Perl regexps. It searches repository history, not the
2379 working directory. It always prints the revision number in which a
2379 working directory. It always prints the revision number in which a
2380 match appears.
2380 match appears.
2381
2381
2382 By default, grep only prints output for the first revision of a
2382 By default, grep only prints output for the first revision of a
2383 file in which it finds a match. To get it to print every revision
2383 file in which it finds a match. To get it to print every revision
2384 that contains a change in match status ("-" for a match that
2384 that contains a change in match status ("-" for a match that
2385 becomes a non-match, or "+" for a non-match that becomes a match),
2385 becomes a non-match, or "+" for a non-match that becomes a match),
2386 use the --all flag.
2386 use the --all flag.
2387
2387
2388 Returns 0 if a match is found, 1 otherwise.
2388 Returns 0 if a match is found, 1 otherwise.
2389 """
2389 """
2390 reflags = 0
2390 reflags = 0
2391 if opts.get('ignore_case'):
2391 if opts.get('ignore_case'):
2392 reflags |= re.I
2392 reflags |= re.I
2393 try:
2393 try:
2394 regexp = re.compile(pattern, reflags)
2394 regexp = re.compile(pattern, reflags)
2395 except re.error, inst:
2395 except re.error, inst:
2396 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2396 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2397 return 1
2397 return 1
2398 sep, eol = ':', '\n'
2398 sep, eol = ':', '\n'
2399 if opts.get('print0'):
2399 if opts.get('print0'):
2400 sep = eol = '\0'
2400 sep = eol = '\0'
2401
2401
2402 getfile = util.lrucachefunc(repo.file)
2402 getfile = util.lrucachefunc(repo.file)
2403
2403
2404 def matchlines(body):
2404 def matchlines(body):
2405 begin = 0
2405 begin = 0
2406 linenum = 0
2406 linenum = 0
2407 while True:
2407 while True:
2408 match = regexp.search(body, begin)
2408 match = regexp.search(body, begin)
2409 if not match:
2409 if not match:
2410 break
2410 break
2411 mstart, mend = match.span()
2411 mstart, mend = match.span()
2412 linenum += body.count('\n', begin, mstart) + 1
2412 linenum += body.count('\n', begin, mstart) + 1
2413 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2413 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2414 begin = body.find('\n', mend) + 1 or len(body)
2414 begin = body.find('\n', mend) + 1 or len(body)
2415 lend = begin - 1
2415 lend = begin - 1
2416 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2416 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2417
2417
2418 class linestate(object):
2418 class linestate(object):
2419 def __init__(self, line, linenum, colstart, colend):
2419 def __init__(self, line, linenum, colstart, colend):
2420 self.line = line
2420 self.line = line
2421 self.linenum = linenum
2421 self.linenum = linenum
2422 self.colstart = colstart
2422 self.colstart = colstart
2423 self.colend = colend
2423 self.colend = colend
2424
2424
2425 def __hash__(self):
2425 def __hash__(self):
2426 return hash((self.linenum, self.line))
2426 return hash((self.linenum, self.line))
2427
2427
2428 def __eq__(self, other):
2428 def __eq__(self, other):
2429 return self.line == other.line
2429 return self.line == other.line
2430
2430
2431 matches = {}
2431 matches = {}
2432 copies = {}
2432 copies = {}
2433 def grepbody(fn, rev, body):
2433 def grepbody(fn, rev, body):
2434 matches[rev].setdefault(fn, [])
2434 matches[rev].setdefault(fn, [])
2435 m = matches[rev][fn]
2435 m = matches[rev][fn]
2436 for lnum, cstart, cend, line in matchlines(body):
2436 for lnum, cstart, cend, line in matchlines(body):
2437 s = linestate(line, lnum, cstart, cend)
2437 s = linestate(line, lnum, cstart, cend)
2438 m.append(s)
2438 m.append(s)
2439
2439
2440 def difflinestates(a, b):
2440 def difflinestates(a, b):
2441 sm = difflib.SequenceMatcher(None, a, b)
2441 sm = difflib.SequenceMatcher(None, a, b)
2442 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2442 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2443 if tag == 'insert':
2443 if tag == 'insert':
2444 for i in xrange(blo, bhi):
2444 for i in xrange(blo, bhi):
2445 yield ('+', b[i])
2445 yield ('+', b[i])
2446 elif tag == 'delete':
2446 elif tag == 'delete':
2447 for i in xrange(alo, ahi):
2447 for i in xrange(alo, ahi):
2448 yield ('-', a[i])
2448 yield ('-', a[i])
2449 elif tag == 'replace':
2449 elif tag == 'replace':
2450 for i in xrange(alo, ahi):
2450 for i in xrange(alo, ahi):
2451 yield ('-', a[i])
2451 yield ('-', a[i])
2452 for i in xrange(blo, bhi):
2452 for i in xrange(blo, bhi):
2453 yield ('+', b[i])
2453 yield ('+', b[i])
2454
2454
2455 def display(fn, ctx, pstates, states):
2455 def display(fn, ctx, pstates, states):
2456 rev = ctx.rev()
2456 rev = ctx.rev()
2457 datefunc = ui.quiet and util.shortdate or util.datestr
2457 datefunc = ui.quiet and util.shortdate or util.datestr
2458 found = False
2458 found = False
2459 filerevmatches = {}
2459 filerevmatches = {}
2460 def binary():
2460 def binary():
2461 flog = getfile(fn)
2461 flog = getfile(fn)
2462 return util.binary(flog.read(ctx.filenode(fn)))
2462 return util.binary(flog.read(ctx.filenode(fn)))
2463
2463
2464 if opts.get('all'):
2464 if opts.get('all'):
2465 iter = difflinestates(pstates, states)
2465 iter = difflinestates(pstates, states)
2466 else:
2466 else:
2467 iter = [('', l) for l in states]
2467 iter = [('', l) for l in states]
2468 for change, l in iter:
2468 for change, l in iter:
2469 cols = [fn, str(rev)]
2469 cols = [fn, str(rev)]
2470 before, match, after = None, None, None
2470 before, match, after = None, None, None
2471 if opts.get('line_number'):
2471 if opts.get('line_number'):
2472 cols.append(str(l.linenum))
2472 cols.append(str(l.linenum))
2473 if opts.get('all'):
2473 if opts.get('all'):
2474 cols.append(change)
2474 cols.append(change)
2475 if opts.get('user'):
2475 if opts.get('user'):
2476 cols.append(ui.shortuser(ctx.user()))
2476 cols.append(ui.shortuser(ctx.user()))
2477 if opts.get('date'):
2477 if opts.get('date'):
2478 cols.append(datefunc(ctx.date()))
2478 cols.append(datefunc(ctx.date()))
2479 if opts.get('files_with_matches'):
2479 if opts.get('files_with_matches'):
2480 c = (fn, rev)
2480 c = (fn, rev)
2481 if c in filerevmatches:
2481 if c in filerevmatches:
2482 continue
2482 continue
2483 filerevmatches[c] = 1
2483 filerevmatches[c] = 1
2484 else:
2484 else:
2485 before = l.line[:l.colstart]
2485 before = l.line[:l.colstart]
2486 match = l.line[l.colstart:l.colend]
2486 match = l.line[l.colstart:l.colend]
2487 after = l.line[l.colend:]
2487 after = l.line[l.colend:]
2488 ui.write(sep.join(cols))
2488 ui.write(sep.join(cols))
2489 if before is not None:
2489 if before is not None:
2490 if not opts.get('text') and binary():
2490 if not opts.get('text') and binary():
2491 ui.write(sep + " Binary file matches")
2491 ui.write(sep + " Binary file matches")
2492 else:
2492 else:
2493 ui.write(sep + before)
2493 ui.write(sep + before)
2494 ui.write(match, label='grep.match')
2494 ui.write(match, label='grep.match')
2495 ui.write(after)
2495 ui.write(after)
2496 ui.write(eol)
2496 ui.write(eol)
2497 found = True
2497 found = True
2498 return found
2498 return found
2499
2499
2500 skip = {}
2500 skip = {}
2501 revfiles = {}
2501 revfiles = {}
2502 matchfn = scmutil.match(repo[None], pats, opts)
2502 matchfn = scmutil.match(repo[None], pats, opts)
2503 found = False
2503 found = False
2504 follow = opts.get('follow')
2504 follow = opts.get('follow')
2505
2505
2506 def prep(ctx, fns):
2506 def prep(ctx, fns):
2507 rev = ctx.rev()
2507 rev = ctx.rev()
2508 pctx = ctx.p1()
2508 pctx = ctx.p1()
2509 parent = pctx.rev()
2509 parent = pctx.rev()
2510 matches.setdefault(rev, {})
2510 matches.setdefault(rev, {})
2511 matches.setdefault(parent, {})
2511 matches.setdefault(parent, {})
2512 files = revfiles.setdefault(rev, [])
2512 files = revfiles.setdefault(rev, [])
2513 for fn in fns:
2513 for fn in fns:
2514 flog = getfile(fn)
2514 flog = getfile(fn)
2515 try:
2515 try:
2516 fnode = ctx.filenode(fn)
2516 fnode = ctx.filenode(fn)
2517 except error.LookupError:
2517 except error.LookupError:
2518 continue
2518 continue
2519
2519
2520 copied = flog.renamed(fnode)
2520 copied = flog.renamed(fnode)
2521 copy = follow and copied and copied[0]
2521 copy = follow and copied and copied[0]
2522 if copy:
2522 if copy:
2523 copies.setdefault(rev, {})[fn] = copy
2523 copies.setdefault(rev, {})[fn] = copy
2524 if fn in skip:
2524 if fn in skip:
2525 if copy:
2525 if copy:
2526 skip[copy] = True
2526 skip[copy] = True
2527 continue
2527 continue
2528 files.append(fn)
2528 files.append(fn)
2529
2529
2530 if fn not in matches[rev]:
2530 if fn not in matches[rev]:
2531 grepbody(fn, rev, flog.read(fnode))
2531 grepbody(fn, rev, flog.read(fnode))
2532
2532
2533 pfn = copy or fn
2533 pfn = copy or fn
2534 if pfn not in matches[parent]:
2534 if pfn not in matches[parent]:
2535 try:
2535 try:
2536 fnode = pctx.filenode(pfn)
2536 fnode = pctx.filenode(pfn)
2537 grepbody(pfn, parent, flog.read(fnode))
2537 grepbody(pfn, parent, flog.read(fnode))
2538 except error.LookupError:
2538 except error.LookupError:
2539 pass
2539 pass
2540
2540
2541 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2541 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2542 rev = ctx.rev()
2542 rev = ctx.rev()
2543 parent = ctx.p1().rev()
2543 parent = ctx.p1().rev()
2544 for fn in sorted(revfiles.get(rev, [])):
2544 for fn in sorted(revfiles.get(rev, [])):
2545 states = matches[rev][fn]
2545 states = matches[rev][fn]
2546 copy = copies.get(rev, {}).get(fn)
2546 copy = copies.get(rev, {}).get(fn)
2547 if fn in skip:
2547 if fn in skip:
2548 if copy:
2548 if copy:
2549 skip[copy] = True
2549 skip[copy] = True
2550 continue
2550 continue
2551 pstates = matches.get(parent, {}).get(copy or fn, [])
2551 pstates = matches.get(parent, {}).get(copy or fn, [])
2552 if pstates or states:
2552 if pstates or states:
2553 r = display(fn, ctx, pstates, states)
2553 r = display(fn, ctx, pstates, states)
2554 found = found or r
2554 found = found or r
2555 if r and not opts.get('all'):
2555 if r and not opts.get('all'):
2556 skip[fn] = True
2556 skip[fn] = True
2557 if copy:
2557 if copy:
2558 skip[copy] = True
2558 skip[copy] = True
2559 del matches[rev]
2559 del matches[rev]
2560 del revfiles[rev]
2560 del revfiles[rev]
2561
2561
2562 return not found
2562 return not found
2563
2563
2564 @command('heads',
2564 @command('heads',
2565 [('r', 'rev', '',
2565 [('r', 'rev', '',
2566 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2566 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2567 ('t', 'topo', False, _('show topological heads only')),
2567 ('t', 'topo', False, _('show topological heads only')),
2568 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2568 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2569 ('c', 'closed', False, _('show normal and closed branch heads')),
2569 ('c', 'closed', False, _('show normal and closed branch heads')),
2570 ] + templateopts,
2570 ] + templateopts,
2571 _('[-ac] [-r STARTREV] [REV]...'))
2571 _('[-ac] [-r STARTREV] [REV]...'))
2572 def heads(ui, repo, *branchrevs, **opts):
2572 def heads(ui, repo, *branchrevs, **opts):
2573 """show current repository heads or show branch heads
2573 """show current repository heads or show branch heads
2574
2574
2575 With no arguments, show all repository branch heads.
2575 With no arguments, show all repository branch heads.
2576
2576
2577 Repository "heads" are changesets with no child changesets. They are
2577 Repository "heads" are changesets with no child changesets. They are
2578 where development generally takes place and are the usual targets
2578 where development generally takes place and are the usual targets
2579 for update and merge operations. Branch heads are changesets that have
2579 for update and merge operations. Branch heads are changesets that have
2580 no child changeset on the same branch.
2580 no child changeset on the same branch.
2581
2581
2582 If one or more REVs are given, only branch heads on the branches
2582 If one or more REVs are given, only branch heads on the branches
2583 associated with the specified changesets are shown. This means
2583 associated with the specified changesets are shown. This means
2584 that you can use :hg:`heads foo` to see the heads on a branch
2584 that you can use :hg:`heads foo` to see the heads on a branch
2585 named ``foo``.
2585 named ``foo``.
2586
2586
2587 If -c/--closed is specified, also show branch heads marked closed
2587 If -c/--closed is specified, also show branch heads marked closed
2588 (see :hg:`commit --close-branch`).
2588 (see :hg:`commit --close-branch`).
2589
2589
2590 If STARTREV is specified, only those heads that are descendants of
2590 If STARTREV is specified, only those heads that are descendants of
2591 STARTREV will be displayed.
2591 STARTREV will be displayed.
2592
2592
2593 If -t/--topo is specified, named branch mechanics will be ignored and only
2593 If -t/--topo is specified, named branch mechanics will be ignored and only
2594 changesets without children will be shown.
2594 changesets without children will be shown.
2595
2595
2596 Returns 0 if matching heads are found, 1 if not.
2596 Returns 0 if matching heads are found, 1 if not.
2597 """
2597 """
2598
2598
2599 start = None
2599 start = None
2600 if 'rev' in opts:
2600 if 'rev' in opts:
2601 start = scmutil.revsingle(repo, opts['rev'], None).node()
2601 start = scmutil.revsingle(repo, opts['rev'], None).node()
2602
2602
2603 if opts.get('topo'):
2603 if opts.get('topo'):
2604 heads = [repo[h] for h in repo.heads(start)]
2604 heads = [repo[h] for h in repo.heads(start)]
2605 else:
2605 else:
2606 heads = []
2606 heads = []
2607 for branch in repo.branchmap():
2607 for branch in repo.branchmap():
2608 heads += repo.branchheads(branch, start, opts.get('closed'))
2608 heads += repo.branchheads(branch, start, opts.get('closed'))
2609 heads = [repo[h] for h in heads]
2609 heads = [repo[h] for h in heads]
2610
2610
2611 if branchrevs:
2611 if branchrevs:
2612 branches = set(repo[br].branch() for br in branchrevs)
2612 branches = set(repo[br].branch() for br in branchrevs)
2613 heads = [h for h in heads if h.branch() in branches]
2613 heads = [h for h in heads if h.branch() in branches]
2614
2614
2615 if opts.get('active') and branchrevs:
2615 if opts.get('active') and branchrevs:
2616 dagheads = repo.heads(start)
2616 dagheads = repo.heads(start)
2617 heads = [h for h in heads if h.node() in dagheads]
2617 heads = [h for h in heads if h.node() in dagheads]
2618
2618
2619 if branchrevs:
2619 if branchrevs:
2620 haveheads = set(h.branch() for h in heads)
2620 haveheads = set(h.branch() for h in heads)
2621 if branches - haveheads:
2621 if branches - haveheads:
2622 headless = ', '.join(b for b in branches - haveheads)
2622 headless = ', '.join(b for b in branches - haveheads)
2623 msg = _('no open branch heads found on branches %s')
2623 msg = _('no open branch heads found on branches %s')
2624 if opts.get('rev'):
2624 if opts.get('rev'):
2625 msg += _(' (started at %s)' % opts['rev'])
2625 msg += _(' (started at %s)' % opts['rev'])
2626 ui.warn((msg + '\n') % headless)
2626 ui.warn((msg + '\n') % headless)
2627
2627
2628 if not heads:
2628 if not heads:
2629 return 1
2629 return 1
2630
2630
2631 heads = sorted(heads, key=lambda x: -x.rev())
2631 heads = sorted(heads, key=lambda x: -x.rev())
2632 displayer = cmdutil.show_changeset(ui, repo, opts)
2632 displayer = cmdutil.show_changeset(ui, repo, opts)
2633 for ctx in heads:
2633 for ctx in heads:
2634 displayer.show(ctx)
2634 displayer.show(ctx)
2635 displayer.close()
2635 displayer.close()
2636
2636
2637 @command('help',
2637 @command('help',
2638 [('e', 'extension', None, _('show only help for extensions')),
2638 [('e', 'extension', None, _('show only help for extensions')),
2639 ('c', 'command', None, _('show only help for commands'))],
2639 ('c', 'command', None, _('show only help for commands'))],
2640 _('[-ec] [TOPIC]'))
2640 _('[-ec] [TOPIC]'))
2641 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2641 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2642 """show help for a given topic or a help overview
2642 """show help for a given topic or a help overview
2643
2643
2644 With no arguments, print a list of commands with short help messages.
2644 With no arguments, print a list of commands with short help messages.
2645
2645
2646 Given a topic, extension, or command name, print help for that
2646 Given a topic, extension, or command name, print help for that
2647 topic.
2647 topic.
2648
2648
2649 Returns 0 if successful.
2649 Returns 0 if successful.
2650 """
2650 """
2651
2651
2652 optlist = []
2652 optlist = []
2653 textwidth = min(ui.termwidth(), 80) - 2
2653 textwidth = min(ui.termwidth(), 80) - 2
2654
2654
2655 # list all option lists
2655 # list all option lists
2656 def opttext(optlist, width):
2656 def opttext(optlist, width):
2657 out = []
2657 out = []
2658 multioccur = False
2658 multioccur = False
2659 for title, options in optlist:
2659 for title, options in optlist:
2660 out.append(("\n%s" % title, None))
2660 out.append(("\n%s" % title, None))
2661 for option in options:
2661 for option in options:
2662 if len(option) == 5:
2662 if len(option) == 5:
2663 shortopt, longopt, default, desc, optlabel = option
2663 shortopt, longopt, default, desc, optlabel = option
2664 else:
2664 else:
2665 shortopt, longopt, default, desc = option
2665 shortopt, longopt, default, desc = option
2666 optlabel = _("VALUE") # default label
2666 optlabel = _("VALUE") # default label
2667
2667
2668 if _("DEPRECATED") in desc and not ui.verbose:
2668 if _("DEPRECATED") in desc and not ui.verbose:
2669 continue
2669 continue
2670 if isinstance(default, list):
2670 if isinstance(default, list):
2671 numqualifier = " %s [+]" % optlabel
2671 numqualifier = " %s [+]" % optlabel
2672 multioccur = True
2672 multioccur = True
2673 elif (default is not None) and not isinstance(default, bool):
2673 elif (default is not None) and not isinstance(default, bool):
2674 numqualifier = " %s" % optlabel
2674 numqualifier = " %s" % optlabel
2675 else:
2675 else:
2676 numqualifier = ""
2676 numqualifier = ""
2677 out.append(("%2s%s" %
2677 out.append(("%2s%s" %
2678 (shortopt and "-%s" % shortopt,
2678 (shortopt and "-%s" % shortopt,
2679 longopt and " --%s%s" %
2679 longopt and " --%s%s" %
2680 (longopt, numqualifier)),
2680 (longopt, numqualifier)),
2681 "%s%s" % (desc,
2681 "%s%s" % (desc,
2682 default
2682 default
2683 and _(" (default: %s)") % default
2683 and _(" (default: %s)") % default
2684 or "")))
2684 or "")))
2685 if multioccur:
2685 if multioccur:
2686 msg = _("\n[+] marked option can be specified multiple times")
2686 msg = _("\n[+] marked option can be specified multiple times")
2687 if ui.verbose and name != 'shortlist':
2687 if ui.verbose and name != 'shortlist':
2688 out.append((msg, None))
2688 out.append((msg, None))
2689 else:
2689 else:
2690 out.insert(-1, (msg, None))
2690 out.insert(-1, (msg, None))
2691
2691
2692 text = ""
2692 text = ""
2693 if out:
2693 if out:
2694 colwidth = encoding.colwidth
2694 colwidth = encoding.colwidth
2695 # normalize: (opt or message, desc or None, width of opt)
2695 # normalize: (opt or message, desc or None, width of opt)
2696 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2696 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2697 for opt, desc in out]
2697 for opt, desc in out]
2698 hanging = max([e[2] for e in entries])
2698 hanging = max([e[2] for e in entries])
2699 for opt, desc, width in entries:
2699 for opt, desc, width in entries:
2700 if desc:
2700 if desc:
2701 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2701 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2702 hangindent = ' ' * (hanging + 3)
2702 hangindent = ' ' * (hanging + 3)
2703 text += '%s\n' % (util.wrap(desc, width,
2703 text += '%s\n' % (util.wrap(desc, width,
2704 initindent=initindent,
2704 initindent=initindent,
2705 hangindent=hangindent))
2705 hangindent=hangindent))
2706 else:
2706 else:
2707 text += "%s\n" % opt
2707 text += "%s\n" % opt
2708
2708
2709 return text
2709 return text
2710
2710
2711 def addglobalopts(aliases):
2711 def addglobalopts(aliases):
2712 if ui.verbose:
2712 if ui.verbose:
2713 optlist.append((_("global options:"), globalopts))
2713 optlist.append((_("global options:"), globalopts))
2714 if name == 'shortlist':
2714 if name == 'shortlist':
2715 optlist.append((_('use "hg help" for the full list '
2715 optlist.append((_('use "hg help" for the full list '
2716 'of commands'), ()))
2716 'of commands'), ()))
2717 else:
2717 else:
2718 if name == 'shortlist':
2718 if name == 'shortlist':
2719 msg = _('use "hg help" for the full list of commands '
2719 msg = _('use "hg help" for the full list of commands '
2720 'or "hg -v" for details')
2720 'or "hg -v" for details')
2721 elif name and not full:
2721 elif name and not full:
2722 msg = _('use "hg help %s" to show the full help text' % name)
2722 msg = _('use "hg help %s" to show the full help text' % name)
2723 elif aliases:
2723 elif aliases:
2724 msg = _('use "hg -v help%s" to show builtin aliases and '
2724 msg = _('use "hg -v help%s" to show builtin aliases and '
2725 'global options') % (name and " " + name or "")
2725 'global options') % (name and " " + name or "")
2726 else:
2726 else:
2727 msg = _('use "hg -v help %s" to show global options') % name
2727 msg = _('use "hg -v help %s" to show global options') % name
2728 optlist.append((msg, ()))
2728 optlist.append((msg, ()))
2729
2729
2730 def helpcmd(name):
2730 def helpcmd(name):
2731 try:
2731 try:
2732 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2732 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2733 except error.AmbiguousCommand, inst:
2733 except error.AmbiguousCommand, inst:
2734 # py3k fix: except vars can't be used outside the scope of the
2734 # py3k fix: except vars can't be used outside the scope of the
2735 # except block, nor can be used inside a lambda. python issue4617
2735 # except block, nor can be used inside a lambda. python issue4617
2736 prefix = inst.args[0]
2736 prefix = inst.args[0]
2737 select = lambda c: c.lstrip('^').startswith(prefix)
2737 select = lambda c: c.lstrip('^').startswith(prefix)
2738 helplist(_('list of commands:\n\n'), select)
2738 helplist(_('list of commands:\n\n'), select)
2739 return
2739 return
2740
2740
2741 # check if it's an invalid alias and display its error if it is
2741 # check if it's an invalid alias and display its error if it is
2742 if getattr(entry[0], 'badalias', False):
2742 if getattr(entry[0], 'badalias', False):
2743 if not unknowncmd:
2743 if not unknowncmd:
2744 entry[0](ui)
2744 entry[0](ui)
2745 return
2745 return
2746
2746
2747 # synopsis
2747 # synopsis
2748 if len(entry) > 2:
2748 if len(entry) > 2:
2749 if entry[2].startswith('hg'):
2749 if entry[2].startswith('hg'):
2750 ui.write("%s\n" % entry[2])
2750 ui.write("%s\n" % entry[2])
2751 else:
2751 else:
2752 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2752 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2753 else:
2753 else:
2754 ui.write('hg %s\n' % aliases[0])
2754 ui.write('hg %s\n' % aliases[0])
2755
2755
2756 # aliases
2756 # aliases
2757 if full and not ui.quiet and len(aliases) > 1:
2757 if full and not ui.quiet and len(aliases) > 1:
2758 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2758 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2759
2759
2760 # description
2760 # description
2761 doc = gettext(entry[0].__doc__)
2761 doc = gettext(entry[0].__doc__)
2762 if not doc:
2762 if not doc:
2763 doc = _("(no help text available)")
2763 doc = _("(no help text available)")
2764 if util.safehasattr(entry[0], 'definition'): # aliased command
2764 if util.safehasattr(entry[0], 'definition'): # aliased command
2765 if entry[0].definition.startswith('!'): # shell alias
2765 if entry[0].definition.startswith('!'): # shell alias
2766 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2766 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2767 else:
2767 else:
2768 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2768 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2769 if ui.quiet or not full:
2769 if ui.quiet or not full:
2770 doc = doc.splitlines()[0]
2770 doc = doc.splitlines()[0]
2771 keep = ui.verbose and ['verbose'] or []
2771 keep = ui.verbose and ['verbose'] or []
2772 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2772 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2773 ui.write("\n%s\n" % formatted)
2773 ui.write("\n%s\n" % formatted)
2774 if pruned:
2774 if pruned:
2775 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2775 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2776
2776
2777 if not ui.quiet:
2777 if not ui.quiet:
2778 # options
2778 # options
2779 if entry[1]:
2779 if entry[1]:
2780 optlist.append((_("options:\n"), entry[1]))
2780 optlist.append((_("options:\n"), entry[1]))
2781
2781
2782 addglobalopts(False)
2782 addglobalopts(False)
2783
2783
2784 # check if this command shadows a non-trivial (multi-line)
2784 # check if this command shadows a non-trivial (multi-line)
2785 # extension help text
2785 # extension help text
2786 try:
2786 try:
2787 mod = extensions.find(name)
2787 mod = extensions.find(name)
2788 doc = gettext(mod.__doc__) or ''
2788 doc = gettext(mod.__doc__) or ''
2789 if '\n' in doc.strip():
2789 if '\n' in doc.strip():
2790 msg = _('use "hg help -e %s" to show help for '
2790 msg = _('use "hg help -e %s" to show help for '
2791 'the %s extension') % (name, name)
2791 'the %s extension') % (name, name)
2792 ui.write('\n%s\n' % msg)
2792 ui.write('\n%s\n' % msg)
2793 except KeyError:
2793 except KeyError:
2794 pass
2794 pass
2795
2795
2796 def helplist(header, select=None):
2796 def helplist(header, select=None):
2797 h = {}
2797 h = {}
2798 cmds = {}
2798 cmds = {}
2799 for c, e in table.iteritems():
2799 for c, e in table.iteritems():
2800 f = c.split("|", 1)[0]
2800 f = c.split("|", 1)[0]
2801 if select and not select(f):
2801 if select and not select(f):
2802 continue
2802 continue
2803 if (not select and name != 'shortlist' and
2803 if (not select and name != 'shortlist' and
2804 e[0].__module__ != __name__):
2804 e[0].__module__ != __name__):
2805 continue
2805 continue
2806 if name == "shortlist" and not f.startswith("^"):
2806 if name == "shortlist" and not f.startswith("^"):
2807 continue
2807 continue
2808 f = f.lstrip("^")
2808 f = f.lstrip("^")
2809 if not ui.debugflag and f.startswith("debug"):
2809 if not ui.debugflag and f.startswith("debug"):
2810 continue
2810 continue
2811 doc = e[0].__doc__
2811 doc = e[0].__doc__
2812 if doc and 'DEPRECATED' in doc and not ui.verbose:
2812 if doc and 'DEPRECATED' in doc and not ui.verbose:
2813 continue
2813 continue
2814 doc = gettext(doc)
2814 doc = gettext(doc)
2815 if not doc:
2815 if not doc:
2816 doc = _("(no help text available)")
2816 doc = _("(no help text available)")
2817 h[f] = doc.splitlines()[0].rstrip()
2817 h[f] = doc.splitlines()[0].rstrip()
2818 cmds[f] = c.lstrip("^")
2818 cmds[f] = c.lstrip("^")
2819
2819
2820 if not h:
2820 if not h:
2821 ui.status(_('no commands defined\n'))
2821 ui.status(_('no commands defined\n'))
2822 return
2822 return
2823
2823
2824 ui.status(header)
2824 ui.status(header)
2825 fns = sorted(h)
2825 fns = sorted(h)
2826 m = max(map(len, fns))
2826 m = max(map(len, fns))
2827 for f in fns:
2827 for f in fns:
2828 if ui.verbose:
2828 if ui.verbose:
2829 commands = cmds[f].replace("|",", ")
2829 commands = cmds[f].replace("|",", ")
2830 ui.write(" %s:\n %s\n"%(commands, h[f]))
2830 ui.write(" %s:\n %s\n"%(commands, h[f]))
2831 else:
2831 else:
2832 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2832 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2833 initindent=' %-*s ' % (m, f),
2833 initindent=' %-*s ' % (m, f),
2834 hangindent=' ' * (m + 4))))
2834 hangindent=' ' * (m + 4))))
2835
2835
2836 if not ui.quiet:
2836 if not ui.quiet:
2837 addglobalopts(True)
2837 addglobalopts(True)
2838
2838
2839 def helptopic(name):
2839 def helptopic(name):
2840 for names, header, doc in help.helptable:
2840 for names, header, doc in help.helptable:
2841 if name in names:
2841 if name in names:
2842 break
2842 break
2843 else:
2843 else:
2844 raise error.UnknownCommand(name)
2844 raise error.UnknownCommand(name)
2845
2845
2846 # description
2846 # description
2847 if not doc:
2847 if not doc:
2848 doc = _("(no help text available)")
2848 doc = _("(no help text available)")
2849 if util.safehasattr(doc, '__call__'):
2849 if util.safehasattr(doc, '__call__'):
2850 doc = doc()
2850 doc = doc()
2851
2851
2852 ui.write("%s\n\n" % header)
2852 ui.write("%s\n\n" % header)
2853 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2853 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2854 try:
2854 try:
2855 cmdutil.findcmd(name, table)
2855 cmdutil.findcmd(name, table)
2856 ui.write(_('\nuse "hg help -c %s" to see help for '
2856 ui.write(_('\nuse "hg help -c %s" to see help for '
2857 'the %s command\n') % (name, name))
2857 'the %s command\n') % (name, name))
2858 except error.UnknownCommand:
2858 except error.UnknownCommand:
2859 pass
2859 pass
2860
2860
2861 def helpext(name):
2861 def helpext(name):
2862 try:
2862 try:
2863 mod = extensions.find(name)
2863 mod = extensions.find(name)
2864 doc = gettext(mod.__doc__) or _('no help text available')
2864 doc = gettext(mod.__doc__) or _('no help text available')
2865 except KeyError:
2865 except KeyError:
2866 mod = None
2866 mod = None
2867 doc = extensions.disabledext(name)
2867 doc = extensions.disabledext(name)
2868 if not doc:
2868 if not doc:
2869 raise error.UnknownCommand(name)
2869 raise error.UnknownCommand(name)
2870
2870
2871 if '\n' not in doc:
2871 if '\n' not in doc:
2872 head, tail = doc, ""
2872 head, tail = doc, ""
2873 else:
2873 else:
2874 head, tail = doc.split('\n', 1)
2874 head, tail = doc.split('\n', 1)
2875 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2875 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2876 if tail:
2876 if tail:
2877 ui.write(minirst.format(tail, textwidth))
2877 ui.write(minirst.format(tail, textwidth))
2878 ui.status('\n\n')
2878 ui.status('\n\n')
2879
2879
2880 if mod:
2880 if mod:
2881 try:
2881 try:
2882 ct = mod.cmdtable
2882 ct = mod.cmdtable
2883 except AttributeError:
2883 except AttributeError:
2884 ct = {}
2884 ct = {}
2885 modcmds = set([c.split('|', 1)[0] for c in ct])
2885 modcmds = set([c.split('|', 1)[0] for c in ct])
2886 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2886 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2887 else:
2887 else:
2888 ui.write(_('use "hg help extensions" for information on enabling '
2888 ui.write(_('use "hg help extensions" for information on enabling '
2889 'extensions\n'))
2889 'extensions\n'))
2890
2890
2891 def helpextcmd(name):
2891 def helpextcmd(name):
2892 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2892 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2893 doc = gettext(mod.__doc__).splitlines()[0]
2893 doc = gettext(mod.__doc__).splitlines()[0]
2894
2894
2895 msg = help.listexts(_("'%s' is provided by the following "
2895 msg = help.listexts(_("'%s' is provided by the following "
2896 "extension:") % cmd, {ext: doc}, indent=4)
2896 "extension:") % cmd, {ext: doc}, indent=4)
2897 ui.write(minirst.format(msg, textwidth))
2897 ui.write(minirst.format(msg, textwidth))
2898 ui.write('\n\n')
2898 ui.write('\n\n')
2899 ui.write(_('use "hg help extensions" for information on enabling '
2899 ui.write(_('use "hg help extensions" for information on enabling '
2900 'extensions\n'))
2900 'extensions\n'))
2901
2901
2902 if name and name != 'shortlist':
2902 if name and name != 'shortlist':
2903 i = None
2903 i = None
2904 if unknowncmd:
2904 if unknowncmd:
2905 queries = (helpextcmd,)
2905 queries = (helpextcmd,)
2906 elif opts.get('extension'):
2906 elif opts.get('extension'):
2907 queries = (helpext,)
2907 queries = (helpext,)
2908 elif opts.get('command'):
2908 elif opts.get('command'):
2909 queries = (helpcmd,)
2909 queries = (helpcmd,)
2910 else:
2910 else:
2911 queries = (helptopic, helpcmd, helpext, helpextcmd)
2911 queries = (helptopic, helpcmd, helpext, helpextcmd)
2912 for f in queries:
2912 for f in queries:
2913 try:
2913 try:
2914 f(name)
2914 f(name)
2915 i = None
2915 i = None
2916 break
2916 break
2917 except error.UnknownCommand, inst:
2917 except error.UnknownCommand, inst:
2918 i = inst
2918 i = inst
2919 if i:
2919 if i:
2920 raise i
2920 raise i
2921
2921
2922 else:
2922 else:
2923 # program name
2923 # program name
2924 ui.status(_("Mercurial Distributed SCM\n"))
2924 ui.status(_("Mercurial Distributed SCM\n"))
2925 ui.status('\n')
2925 ui.status('\n')
2926
2926
2927 # list of commands
2927 # list of commands
2928 if name == "shortlist":
2928 if name == "shortlist":
2929 header = _('basic commands:\n\n')
2929 header = _('basic commands:\n\n')
2930 else:
2930 else:
2931 header = _('list of commands:\n\n')
2931 header = _('list of commands:\n\n')
2932
2932
2933 helplist(header)
2933 helplist(header)
2934 if name != 'shortlist':
2934 if name != 'shortlist':
2935 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2935 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2936 if text:
2936 if text:
2937 ui.write("\n%s\n" % minirst.format(text, textwidth))
2937 ui.write("\n%s\n" % minirst.format(text, textwidth))
2938
2938
2939 if not name:
2939 if not name:
2940 ui.write(_("\nadditional help topics:\n\n"))
2940 ui.write(_("\nadditional help topics:\n\n"))
2941 topics = []
2941 topics = []
2942 for names, header, doc in help.helptable:
2942 for names, header, doc in help.helptable:
2943 topics.append((sorted(names, key=len, reverse=True)[0], header))
2943 topics.append((sorted(names, key=len, reverse=True)[0], header))
2944 topics_len = max([len(s[0]) for s in topics])
2944 topics_len = max([len(s[0]) for s in topics])
2945 for t, desc in topics:
2945 for t, desc in topics:
2946 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2946 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2947
2947
2948 ui.write(opttext(optlist, textwidth))
2948 ui.write(opttext(optlist, textwidth))
2949
2949
2950 @command('identify|id',
2950 @command('identify|id',
2951 [('r', 'rev', '',
2951 [('r', 'rev', '',
2952 _('identify the specified revision'), _('REV')),
2952 _('identify the specified revision'), _('REV')),
2953 ('n', 'num', None, _('show local revision number')),
2953 ('n', 'num', None, _('show local revision number')),
2954 ('i', 'id', None, _('show global revision id')),
2954 ('i', 'id', None, _('show global revision id')),
2955 ('b', 'branch', None, _('show branch')),
2955 ('b', 'branch', None, _('show branch')),
2956 ('t', 'tags', None, _('show tags')),
2956 ('t', 'tags', None, _('show tags')),
2957 ('B', 'bookmarks', None, _('show bookmarks'))],
2957 ('B', 'bookmarks', None, _('show bookmarks'))],
2958 _('[-nibtB] [-r REV] [SOURCE]'))
2958 _('[-nibtB] [-r REV] [SOURCE]'))
2959 def identify(ui, repo, source=None, rev=None,
2959 def identify(ui, repo, source=None, rev=None,
2960 num=None, id=None, branch=None, tags=None, bookmarks=None):
2960 num=None, id=None, branch=None, tags=None, bookmarks=None):
2961 """identify the working copy or specified revision
2961 """identify the working copy or specified revision
2962
2962
2963 Print a summary identifying the repository state at REV using one or
2963 Print a summary identifying the repository state at REV using one or
2964 two parent hash identifiers, followed by a "+" if the working
2964 two parent hash identifiers, followed by a "+" if the working
2965 directory has uncommitted changes, the branch name (if not default),
2965 directory has uncommitted changes, the branch name (if not default),
2966 a list of tags, and a list of bookmarks.
2966 a list of tags, and a list of bookmarks.
2967
2967
2968 When REV is not given, print a summary of the current state of the
2968 When REV is not given, print a summary of the current state of the
2969 repository.
2969 repository.
2970
2970
2971 Specifying a path to a repository root or Mercurial bundle will
2971 Specifying a path to a repository root or Mercurial bundle will
2972 cause lookup to operate on that repository/bundle.
2972 cause lookup to operate on that repository/bundle.
2973
2973
2974 .. container:: verbose
2975
2976 Examples:
2977
2978 - generate a build identifier for the working directory::
2979
2980 hg id --id > build-id.dat
2981
2982 - find the revision corresponding to a tag::
2983
2984 hg id -n -r 1.3
2985
2986 - check the most recent revision of a remote repository::
2987
2988 hg id -r tip http://selenic.com/hg/
2989
2974 Returns 0 if successful.
2990 Returns 0 if successful.
2975 """
2991 """
2976
2992
2977 if not repo and not source:
2993 if not repo and not source:
2978 raise util.Abort(_("there is no Mercurial repository here "
2994 raise util.Abort(_("there is no Mercurial repository here "
2979 "(.hg not found)"))
2995 "(.hg not found)"))
2980
2996
2981 hexfunc = ui.debugflag and hex or short
2997 hexfunc = ui.debugflag and hex or short
2982 default = not (num or id or branch or tags or bookmarks)
2998 default = not (num or id or branch or tags or bookmarks)
2983 output = []
2999 output = []
2984 revs = []
3000 revs = []
2985
3001
2986 if source:
3002 if source:
2987 source, branches = hg.parseurl(ui.expandpath(source))
3003 source, branches = hg.parseurl(ui.expandpath(source))
2988 repo = hg.peer(ui, {}, source)
3004 repo = hg.peer(ui, {}, source)
2989 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3005 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2990
3006
2991 if not repo.local():
3007 if not repo.local():
2992 if num or branch or tags:
3008 if num or branch or tags:
2993 raise util.Abort(
3009 raise util.Abort(
2994 _("can't query remote revision number, branch, or tags"))
3010 _("can't query remote revision number, branch, or tags"))
2995 if not rev and revs:
3011 if not rev and revs:
2996 rev = revs[0]
3012 rev = revs[0]
2997 if not rev:
3013 if not rev:
2998 rev = "tip"
3014 rev = "tip"
2999
3015
3000 remoterev = repo.lookup(rev)
3016 remoterev = repo.lookup(rev)
3001 if default or id:
3017 if default or id:
3002 output = [hexfunc(remoterev)]
3018 output = [hexfunc(remoterev)]
3003
3019
3004 def getbms():
3020 def getbms():
3005 bms = []
3021 bms = []
3006
3022
3007 if 'bookmarks' in repo.listkeys('namespaces'):
3023 if 'bookmarks' in repo.listkeys('namespaces'):
3008 hexremoterev = hex(remoterev)
3024 hexremoterev = hex(remoterev)
3009 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3025 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3010 if bmr == hexremoterev]
3026 if bmr == hexremoterev]
3011
3027
3012 return bms
3028 return bms
3013
3029
3014 if bookmarks:
3030 if bookmarks:
3015 output.extend(getbms())
3031 output.extend(getbms())
3016 elif default and not ui.quiet:
3032 elif default and not ui.quiet:
3017 # multiple bookmarks for a single parent separated by '/'
3033 # multiple bookmarks for a single parent separated by '/'
3018 bm = '/'.join(getbms())
3034 bm = '/'.join(getbms())
3019 if bm:
3035 if bm:
3020 output.append(bm)
3036 output.append(bm)
3021 else:
3037 else:
3022 if not rev:
3038 if not rev:
3023 ctx = repo[None]
3039 ctx = repo[None]
3024 parents = ctx.parents()
3040 parents = ctx.parents()
3025 changed = ""
3041 changed = ""
3026 if default or id or num:
3042 if default or id or num:
3027 changed = util.any(repo.status()) and "+" or ""
3043 changed = util.any(repo.status()) and "+" or ""
3028 if default or id:
3044 if default or id:
3029 output = ["%s%s" %
3045 output = ["%s%s" %
3030 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3046 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3031 if num:
3047 if num:
3032 output.append("%s%s" %
3048 output.append("%s%s" %
3033 ('+'.join([str(p.rev()) for p in parents]), changed))
3049 ('+'.join([str(p.rev()) for p in parents]), changed))
3034 else:
3050 else:
3035 ctx = scmutil.revsingle(repo, rev)
3051 ctx = scmutil.revsingle(repo, rev)
3036 if default or id:
3052 if default or id:
3037 output = [hexfunc(ctx.node())]
3053 output = [hexfunc(ctx.node())]
3038 if num:
3054 if num:
3039 output.append(str(ctx.rev()))
3055 output.append(str(ctx.rev()))
3040
3056
3041 if default and not ui.quiet:
3057 if default and not ui.quiet:
3042 b = ctx.branch()
3058 b = ctx.branch()
3043 if b != 'default':
3059 if b != 'default':
3044 output.append("(%s)" % b)
3060 output.append("(%s)" % b)
3045
3061
3046 # multiple tags for a single parent separated by '/'
3062 # multiple tags for a single parent separated by '/'
3047 t = '/'.join(ctx.tags())
3063 t = '/'.join(ctx.tags())
3048 if t:
3064 if t:
3049 output.append(t)
3065 output.append(t)
3050
3066
3051 # multiple bookmarks for a single parent separated by '/'
3067 # multiple bookmarks for a single parent separated by '/'
3052 bm = '/'.join(ctx.bookmarks())
3068 bm = '/'.join(ctx.bookmarks())
3053 if bm:
3069 if bm:
3054 output.append(bm)
3070 output.append(bm)
3055 else:
3071 else:
3056 if branch:
3072 if branch:
3057 output.append(ctx.branch())
3073 output.append(ctx.branch())
3058
3074
3059 if tags:
3075 if tags:
3060 output.extend(ctx.tags())
3076 output.extend(ctx.tags())
3061
3077
3062 if bookmarks:
3078 if bookmarks:
3063 output.extend(ctx.bookmarks())
3079 output.extend(ctx.bookmarks())
3064
3080
3065 ui.write("%s\n" % ' '.join(output))
3081 ui.write("%s\n" % ' '.join(output))
3066
3082
3067 @command('import|patch',
3083 @command('import|patch',
3068 [('p', 'strip', 1,
3084 [('p', 'strip', 1,
3069 _('directory strip option for patch. This has the same '
3085 _('directory strip option for patch. This has the same '
3070 'meaning as the corresponding patch option'), _('NUM')),
3086 'meaning as the corresponding patch option'), _('NUM')),
3071 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3087 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3072 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3088 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3073 ('', 'no-commit', None,
3089 ('', 'no-commit', None,
3074 _("don't commit, just update the working directory")),
3090 _("don't commit, just update the working directory")),
3075 ('', 'bypass', None,
3091 ('', 'bypass', None,
3076 _("apply patch without touching the working directory")),
3092 _("apply patch without touching the working directory")),
3077 ('', 'exact', None,
3093 ('', 'exact', None,
3078 _('apply patch to the nodes from which it was generated')),
3094 _('apply patch to the nodes from which it was generated')),
3079 ('', 'import-branch', None,
3095 ('', 'import-branch', None,
3080 _('use any branch information in patch (implied by --exact)'))] +
3096 _('use any branch information in patch (implied by --exact)'))] +
3081 commitopts + commitopts2 + similarityopts,
3097 commitopts + commitopts2 + similarityopts,
3082 _('[OPTION]... PATCH...'))
3098 _('[OPTION]... PATCH...'))
3083 def import_(ui, repo, patch1, *patches, **opts):
3099 def import_(ui, repo, patch1, *patches, **opts):
3084 """import an ordered set of patches
3100 """import an ordered set of patches
3085
3101
3086 Import a list of patches and commit them individually (unless
3102 Import a list of patches and commit them individually (unless
3087 --no-commit is specified).
3103 --no-commit is specified).
3088
3104
3089 If there are outstanding changes in the working directory, import
3105 If there are outstanding changes in the working directory, import
3090 will abort unless given the -f/--force flag.
3106 will abort unless given the -f/--force flag.
3091
3107
3092 You can import a patch straight from a mail message. Even patches
3108 You can import a patch straight from a mail message. Even patches
3093 as attachments work (to use the body part, it must have type
3109 as attachments work (to use the body part, it must have type
3094 text/plain or text/x-patch). From and Subject headers of email
3110 text/plain or text/x-patch). From and Subject headers of email
3095 message are used as default committer and commit message. All
3111 message are used as default committer and commit message. All
3096 text/plain body parts before first diff are added to commit
3112 text/plain body parts before first diff are added to commit
3097 message.
3113 message.
3098
3114
3099 If the imported patch was generated by :hg:`export`, user and
3115 If the imported patch was generated by :hg:`export`, user and
3100 description from patch override values from message headers and
3116 description from patch override values from message headers and
3101 body. Values given on command line with -m/--message and -u/--user
3117 body. Values given on command line with -m/--message and -u/--user
3102 override these.
3118 override these.
3103
3119
3104 If --exact is specified, import will set the working directory to
3120 If --exact is specified, import will set the working directory to
3105 the parent of each patch before applying it, and will abort if the
3121 the parent of each patch before applying it, and will abort if the
3106 resulting changeset has a different ID than the one recorded in
3122 resulting changeset has a different ID than the one recorded in
3107 the patch. This may happen due to character set problems or other
3123 the patch. This may happen due to character set problems or other
3108 deficiencies in the text patch format.
3124 deficiencies in the text patch format.
3109
3125
3110 Use --bypass to apply and commit patches directly to the
3126 Use --bypass to apply and commit patches directly to the
3111 repository, not touching the working directory. Without --exact,
3127 repository, not touching the working directory. Without --exact,
3112 patches will be applied on top of the working directory parent
3128 patches will be applied on top of the working directory parent
3113 revision.
3129 revision.
3114
3130
3115 With -s/--similarity, hg will attempt to discover renames and
3131 With -s/--similarity, hg will attempt to discover renames and
3116 copies in the patch in the same way as 'addremove'.
3132 copies in the patch in the same way as 'addremove'.
3117
3133
3118 To read a patch from standard input, use "-" as the patch name. If
3134 To read a patch from standard input, use "-" as the patch name. If
3119 a URL is specified, the patch will be downloaded from it.
3135 a URL is specified, the patch will be downloaded from it.
3120 See :hg:`help dates` for a list of formats valid for -d/--date.
3136 See :hg:`help dates` for a list of formats valid for -d/--date.
3121
3137
3122 Returns 0 on success.
3138 Returns 0 on success.
3123 """
3139 """
3124 patches = (patch1,) + patches
3140 patches = (patch1,) + patches
3125
3141
3126 date = opts.get('date')
3142 date = opts.get('date')
3127 if date:
3143 if date:
3128 opts['date'] = util.parsedate(date)
3144 opts['date'] = util.parsedate(date)
3129
3145
3130 update = not opts.get('bypass')
3146 update = not opts.get('bypass')
3131 if not update and opts.get('no_commit'):
3147 if not update and opts.get('no_commit'):
3132 raise util.Abort(_('cannot use --no-commit with --bypass'))
3148 raise util.Abort(_('cannot use --no-commit with --bypass'))
3133 try:
3149 try:
3134 sim = float(opts.get('similarity') or 0)
3150 sim = float(opts.get('similarity') or 0)
3135 except ValueError:
3151 except ValueError:
3136 raise util.Abort(_('similarity must be a number'))
3152 raise util.Abort(_('similarity must be a number'))
3137 if sim < 0 or sim > 100:
3153 if sim < 0 or sim > 100:
3138 raise util.Abort(_('similarity must be between 0 and 100'))
3154 raise util.Abort(_('similarity must be between 0 and 100'))
3139 if sim and not update:
3155 if sim and not update:
3140 raise util.Abort(_('cannot use --similarity with --bypass'))
3156 raise util.Abort(_('cannot use --similarity with --bypass'))
3141
3157
3142 if (opts.get('exact') or not opts.get('force')) and update:
3158 if (opts.get('exact') or not opts.get('force')) and update:
3143 cmdutil.bailifchanged(repo)
3159 cmdutil.bailifchanged(repo)
3144
3160
3145 d = opts["base"]
3161 d = opts["base"]
3146 strip = opts["strip"]
3162 strip = opts["strip"]
3147 wlock = lock = None
3163 wlock = lock = None
3148 msgs = []
3164 msgs = []
3149
3165
3150 def checkexact(repo, n, nodeid):
3166 def checkexact(repo, n, nodeid):
3151 if opts.get('exact') and hex(n) != nodeid:
3167 if opts.get('exact') and hex(n) != nodeid:
3152 repo.rollback()
3168 repo.rollback()
3153 raise util.Abort(_('patch is damaged or loses information'))
3169 raise util.Abort(_('patch is damaged or loses information'))
3154
3170
3155 def tryone(ui, hunk, parents):
3171 def tryone(ui, hunk, parents):
3156 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3172 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3157 patch.extract(ui, hunk)
3173 patch.extract(ui, hunk)
3158
3174
3159 if not tmpname:
3175 if not tmpname:
3160 return None
3176 return None
3161 commitid = _('to working directory')
3177 commitid = _('to working directory')
3162
3178
3163 try:
3179 try:
3164 cmdline_message = cmdutil.logmessage(ui, opts)
3180 cmdline_message = cmdutil.logmessage(ui, opts)
3165 if cmdline_message:
3181 if cmdline_message:
3166 # pickup the cmdline msg
3182 # pickup the cmdline msg
3167 message = cmdline_message
3183 message = cmdline_message
3168 elif message:
3184 elif message:
3169 # pickup the patch msg
3185 # pickup the patch msg
3170 message = message.strip()
3186 message = message.strip()
3171 else:
3187 else:
3172 # launch the editor
3188 # launch the editor
3173 message = None
3189 message = None
3174 ui.debug('message:\n%s\n' % message)
3190 ui.debug('message:\n%s\n' % message)
3175
3191
3176 if len(parents) == 1:
3192 if len(parents) == 1:
3177 parents.append(repo[nullid])
3193 parents.append(repo[nullid])
3178 if opts.get('exact'):
3194 if opts.get('exact'):
3179 if not nodeid or not p1:
3195 if not nodeid or not p1:
3180 raise util.Abort(_('not a Mercurial patch'))
3196 raise util.Abort(_('not a Mercurial patch'))
3181 p1 = repo[p1]
3197 p1 = repo[p1]
3182 p2 = repo[p2 or nullid]
3198 p2 = repo[p2 or nullid]
3183 elif p2:
3199 elif p2:
3184 try:
3200 try:
3185 p1 = repo[p1]
3201 p1 = repo[p1]
3186 p2 = repo[p2]
3202 p2 = repo[p2]
3187 except error.RepoError:
3203 except error.RepoError:
3188 p1, p2 = parents
3204 p1, p2 = parents
3189 else:
3205 else:
3190 p1, p2 = parents
3206 p1, p2 = parents
3191
3207
3192 n = None
3208 n = None
3193 if update:
3209 if update:
3194 if opts.get('exact') and p1 != parents[0]:
3210 if opts.get('exact') and p1 != parents[0]:
3195 hg.clean(repo, p1.node())
3211 hg.clean(repo, p1.node())
3196 if p1 != parents[0] and p2 != parents[1]:
3212 if p1 != parents[0] and p2 != parents[1]:
3197 repo.dirstate.setparents(p1.node(), p2.node())
3213 repo.dirstate.setparents(p1.node(), p2.node())
3198
3214
3199 if opts.get('exact') or opts.get('import_branch'):
3215 if opts.get('exact') or opts.get('import_branch'):
3200 repo.dirstate.setbranch(branch or 'default')
3216 repo.dirstate.setbranch(branch or 'default')
3201
3217
3202 files = set()
3218 files = set()
3203 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3219 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3204 eolmode=None, similarity=sim / 100.0)
3220 eolmode=None, similarity=sim / 100.0)
3205 files = list(files)
3221 files = list(files)
3206 if opts.get('no_commit'):
3222 if opts.get('no_commit'):
3207 if message:
3223 if message:
3208 msgs.append(message)
3224 msgs.append(message)
3209 else:
3225 else:
3210 if opts.get('exact'):
3226 if opts.get('exact'):
3211 m = None
3227 m = None
3212 else:
3228 else:
3213 m = scmutil.matchfiles(repo, files or [])
3229 m = scmutil.matchfiles(repo, files or [])
3214 n = repo.commit(message, opts.get('user') or user,
3230 n = repo.commit(message, opts.get('user') or user,
3215 opts.get('date') or date, match=m,
3231 opts.get('date') or date, match=m,
3216 editor=cmdutil.commiteditor)
3232 editor=cmdutil.commiteditor)
3217 checkexact(repo, n, nodeid)
3233 checkexact(repo, n, nodeid)
3218 # Force a dirstate write so that the next transaction
3234 # Force a dirstate write so that the next transaction
3219 # backups an up-to-date file.
3235 # backups an up-to-date file.
3220 repo.dirstate.write()
3236 repo.dirstate.write()
3221 else:
3237 else:
3222 if opts.get('exact') or opts.get('import_branch'):
3238 if opts.get('exact') or opts.get('import_branch'):
3223 branch = branch or 'default'
3239 branch = branch or 'default'
3224 else:
3240 else:
3225 branch = p1.branch()
3241 branch = p1.branch()
3226 store = patch.filestore()
3242 store = patch.filestore()
3227 try:
3243 try:
3228 files = set()
3244 files = set()
3229 try:
3245 try:
3230 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3246 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3231 files, eolmode=None)
3247 files, eolmode=None)
3232 except patch.PatchError, e:
3248 except patch.PatchError, e:
3233 raise util.Abort(str(e))
3249 raise util.Abort(str(e))
3234 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3250 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3235 message,
3251 message,
3236 opts.get('user') or user,
3252 opts.get('user') or user,
3237 opts.get('date') or date,
3253 opts.get('date') or date,
3238 branch, files, store,
3254 branch, files, store,
3239 editor=cmdutil.commiteditor)
3255 editor=cmdutil.commiteditor)
3240 repo.savecommitmessage(memctx.description())
3256 repo.savecommitmessage(memctx.description())
3241 n = memctx.commit()
3257 n = memctx.commit()
3242 checkexact(repo, n, nodeid)
3258 checkexact(repo, n, nodeid)
3243 finally:
3259 finally:
3244 store.close()
3260 store.close()
3245 if n:
3261 if n:
3246 commitid = short(n)
3262 commitid = short(n)
3247 return commitid
3263 return commitid
3248 finally:
3264 finally:
3249 os.unlink(tmpname)
3265 os.unlink(tmpname)
3250
3266
3251 try:
3267 try:
3252 wlock = repo.wlock()
3268 wlock = repo.wlock()
3253 lock = repo.lock()
3269 lock = repo.lock()
3254 parents = repo.parents()
3270 parents = repo.parents()
3255 lastcommit = None
3271 lastcommit = None
3256 for p in patches:
3272 for p in patches:
3257 pf = os.path.join(d, p)
3273 pf = os.path.join(d, p)
3258
3274
3259 if pf == '-':
3275 if pf == '-':
3260 ui.status(_("applying patch from stdin\n"))
3276 ui.status(_("applying patch from stdin\n"))
3261 pf = ui.fin
3277 pf = ui.fin
3262 else:
3278 else:
3263 ui.status(_("applying %s\n") % p)
3279 ui.status(_("applying %s\n") % p)
3264 pf = url.open(ui, pf)
3280 pf = url.open(ui, pf)
3265
3281
3266 haspatch = False
3282 haspatch = False
3267 for hunk in patch.split(pf):
3283 for hunk in patch.split(pf):
3268 commitid = tryone(ui, hunk, parents)
3284 commitid = tryone(ui, hunk, parents)
3269 if commitid:
3285 if commitid:
3270 haspatch = True
3286 haspatch = True
3271 if lastcommit:
3287 if lastcommit:
3272 ui.status(_('applied %s\n') % lastcommit)
3288 ui.status(_('applied %s\n') % lastcommit)
3273 lastcommit = commitid
3289 lastcommit = commitid
3274 if update or opts.get('exact'):
3290 if update or opts.get('exact'):
3275 parents = repo.parents()
3291 parents = repo.parents()
3276 else:
3292 else:
3277 parents = [repo[commitid]]
3293 parents = [repo[commitid]]
3278
3294
3279 if not haspatch:
3295 if not haspatch:
3280 raise util.Abort(_('no diffs found'))
3296 raise util.Abort(_('no diffs found'))
3281
3297
3282 if msgs:
3298 if msgs:
3283 repo.savecommitmessage('\n* * *\n'.join(msgs))
3299 repo.savecommitmessage('\n* * *\n'.join(msgs))
3284 finally:
3300 finally:
3285 release(lock, wlock)
3301 release(lock, wlock)
3286
3302
3287 @command('incoming|in',
3303 @command('incoming|in',
3288 [('f', 'force', None,
3304 [('f', 'force', None,
3289 _('run even if remote repository is unrelated')),
3305 _('run even if remote repository is unrelated')),
3290 ('n', 'newest-first', None, _('show newest record first')),
3306 ('n', 'newest-first', None, _('show newest record first')),
3291 ('', 'bundle', '',
3307 ('', 'bundle', '',
3292 _('file to store the bundles into'), _('FILE')),
3308 _('file to store the bundles into'), _('FILE')),
3293 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3309 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3294 ('B', 'bookmarks', False, _("compare bookmarks")),
3310 ('B', 'bookmarks', False, _("compare bookmarks")),
3295 ('b', 'branch', [],
3311 ('b', 'branch', [],
3296 _('a specific branch you would like to pull'), _('BRANCH')),
3312 _('a specific branch you would like to pull'), _('BRANCH')),
3297 ] + logopts + remoteopts + subrepoopts,
3313 ] + logopts + remoteopts + subrepoopts,
3298 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3314 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3299 def incoming(ui, repo, source="default", **opts):
3315 def incoming(ui, repo, source="default", **opts):
3300 """show new changesets found in source
3316 """show new changesets found in source
3301
3317
3302 Show new changesets found in the specified path/URL or the default
3318 Show new changesets found in the specified path/URL or the default
3303 pull location. These are the changesets that would have been pulled
3319 pull location. These are the changesets that would have been pulled
3304 if a pull at the time you issued this command.
3320 if a pull at the time you issued this command.
3305
3321
3306 For remote repository, using --bundle avoids downloading the
3322 For remote repository, using --bundle avoids downloading the
3307 changesets twice if the incoming is followed by a pull.
3323 changesets twice if the incoming is followed by a pull.
3308
3324
3309 See pull for valid source format details.
3325 See pull for valid source format details.
3310
3326
3311 Returns 0 if there are incoming changes, 1 otherwise.
3327 Returns 0 if there are incoming changes, 1 otherwise.
3312 """
3328 """
3313 if opts.get('bundle') and opts.get('subrepos'):
3329 if opts.get('bundle') and opts.get('subrepos'):
3314 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3330 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3315
3331
3316 if opts.get('bookmarks'):
3332 if opts.get('bookmarks'):
3317 source, branches = hg.parseurl(ui.expandpath(source),
3333 source, branches = hg.parseurl(ui.expandpath(source),
3318 opts.get('branch'))
3334 opts.get('branch'))
3319 other = hg.peer(repo, opts, source)
3335 other = hg.peer(repo, opts, source)
3320 if 'bookmarks' not in other.listkeys('namespaces'):
3336 if 'bookmarks' not in other.listkeys('namespaces'):
3321 ui.warn(_("remote doesn't support bookmarks\n"))
3337 ui.warn(_("remote doesn't support bookmarks\n"))
3322 return 0
3338 return 0
3323 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3339 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3324 return bookmarks.diff(ui, repo, other)
3340 return bookmarks.diff(ui, repo, other)
3325
3341
3326 repo._subtoppath = ui.expandpath(source)
3342 repo._subtoppath = ui.expandpath(source)
3327 try:
3343 try:
3328 return hg.incoming(ui, repo, source, opts)
3344 return hg.incoming(ui, repo, source, opts)
3329 finally:
3345 finally:
3330 del repo._subtoppath
3346 del repo._subtoppath
3331
3347
3332
3348
3333 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3349 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3334 def init(ui, dest=".", **opts):
3350 def init(ui, dest=".", **opts):
3335 """create a new repository in the given directory
3351 """create a new repository in the given directory
3336
3352
3337 Initialize a new repository in the given directory. If the given
3353 Initialize a new repository in the given directory. If the given
3338 directory does not exist, it will be created.
3354 directory does not exist, it will be created.
3339
3355
3340 If no directory is given, the current directory is used.
3356 If no directory is given, the current directory is used.
3341
3357
3342 It is possible to specify an ``ssh://`` URL as the destination.
3358 It is possible to specify an ``ssh://`` URL as the destination.
3343 See :hg:`help urls` for more information.
3359 See :hg:`help urls` for more information.
3344
3360
3345 Returns 0 on success.
3361 Returns 0 on success.
3346 """
3362 """
3347 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3363 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3348
3364
3349 @command('locate',
3365 @command('locate',
3350 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3366 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3351 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3367 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3352 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3368 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3353 ] + walkopts,
3369 ] + walkopts,
3354 _('[OPTION]... [PATTERN]...'))
3370 _('[OPTION]... [PATTERN]...'))
3355 def locate(ui, repo, *pats, **opts):
3371 def locate(ui, repo, *pats, **opts):
3356 """locate files matching specific patterns
3372 """locate files matching specific patterns
3357
3373
3358 Print files under Mercurial control in the working directory whose
3374 Print files under Mercurial control in the working directory whose
3359 names match the given patterns.
3375 names match the given patterns.
3360
3376
3361 By default, this command searches all directories in the working
3377 By default, this command searches all directories in the working
3362 directory. To search just the current directory and its
3378 directory. To search just the current directory and its
3363 subdirectories, use "--include .".
3379 subdirectories, use "--include .".
3364
3380
3365 If no patterns are given to match, this command prints the names
3381 If no patterns are given to match, this command prints the names
3366 of all files under Mercurial control in the working directory.
3382 of all files under Mercurial control in the working directory.
3367
3383
3368 If you want to feed the output of this command into the "xargs"
3384 If you want to feed the output of this command into the "xargs"
3369 command, use the -0 option to both this command and "xargs". This
3385 command, use the -0 option to both this command and "xargs". This
3370 will avoid the problem of "xargs" treating single filenames that
3386 will avoid the problem of "xargs" treating single filenames that
3371 contain whitespace as multiple filenames.
3387 contain whitespace as multiple filenames.
3372
3388
3373 Returns 0 if a match is found, 1 otherwise.
3389 Returns 0 if a match is found, 1 otherwise.
3374 """
3390 """
3375 end = opts.get('print0') and '\0' or '\n'
3391 end = opts.get('print0') and '\0' or '\n'
3376 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3392 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3377
3393
3378 ret = 1
3394 ret = 1
3379 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3395 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3380 m.bad = lambda x, y: False
3396 m.bad = lambda x, y: False
3381 for abs in repo[rev].walk(m):
3397 for abs in repo[rev].walk(m):
3382 if not rev and abs not in repo.dirstate:
3398 if not rev and abs not in repo.dirstate:
3383 continue
3399 continue
3384 if opts.get('fullpath'):
3400 if opts.get('fullpath'):
3385 ui.write(repo.wjoin(abs), end)
3401 ui.write(repo.wjoin(abs), end)
3386 else:
3402 else:
3387 ui.write(((pats and m.rel(abs)) or abs), end)
3403 ui.write(((pats and m.rel(abs)) or abs), end)
3388 ret = 0
3404 ret = 0
3389
3405
3390 return ret
3406 return ret
3391
3407
3392 @command('^log|history',
3408 @command('^log|history',
3393 [('f', 'follow', None,
3409 [('f', 'follow', None,
3394 _('follow changeset history, or file history across copies and renames')),
3410 _('follow changeset history, or file history across copies and renames')),
3395 ('', 'follow-first', None,
3411 ('', 'follow-first', None,
3396 _('only follow the first parent of merge changesets')),
3412 _('only follow the first parent of merge changesets')),
3397 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3413 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3398 ('C', 'copies', None, _('show copied files')),
3414 ('C', 'copies', None, _('show copied files')),
3399 ('k', 'keyword', [],
3415 ('k', 'keyword', [],
3400 _('do case-insensitive search for a given text'), _('TEXT')),
3416 _('do case-insensitive search for a given text'), _('TEXT')),
3401 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3417 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3402 ('', 'removed', None, _('include revisions where files were removed')),
3418 ('', 'removed', None, _('include revisions where files were removed')),
3403 ('m', 'only-merges', None, _('show only merges')),
3419 ('m', 'only-merges', None, _('show only merges')),
3404 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3420 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3405 ('', 'only-branch', [],
3421 ('', 'only-branch', [],
3406 _('show only changesets within the given named branch (DEPRECATED)'),
3422 _('show only changesets within the given named branch (DEPRECATED)'),
3407 _('BRANCH')),
3423 _('BRANCH')),
3408 ('b', 'branch', [],
3424 ('b', 'branch', [],
3409 _('show changesets within the given named branch'), _('BRANCH')),
3425 _('show changesets within the given named branch'), _('BRANCH')),
3410 ('P', 'prune', [],
3426 ('P', 'prune', [],
3411 _('do not display revision or any of its ancestors'), _('REV')),
3427 _('do not display revision or any of its ancestors'), _('REV')),
3412 ('', 'hidden', False, _('show hidden changesets')),
3428 ('', 'hidden', False, _('show hidden changesets')),
3413 ] + logopts + walkopts,
3429 ] + logopts + walkopts,
3414 _('[OPTION]... [FILE]'))
3430 _('[OPTION]... [FILE]'))
3415 def log(ui, repo, *pats, **opts):
3431 def log(ui, repo, *pats, **opts):
3416 """show revision history of entire repository or files
3432 """show revision history of entire repository or files
3417
3433
3418 Print the revision history of the specified files or the entire
3434 Print the revision history of the specified files or the entire
3419 project.
3435 project.
3420
3436
3421 If no revision range is specified, the default is ``tip:0`` unless
3437 If no revision range is specified, the default is ``tip:0`` unless
3422 --follow is set, in which case the working directory parent is
3438 --follow is set, in which case the working directory parent is
3423 used as the starting revision.
3439 used as the starting revision.
3424
3440
3425 File history is shown without following rename or copy history of
3441 File history is shown without following rename or copy history of
3426 files. Use -f/--follow with a filename to follow history across
3442 files. Use -f/--follow with a filename to follow history across
3427 renames and copies. --follow without a filename will only show
3443 renames and copies. --follow without a filename will only show
3428 ancestors or descendants of the starting revision.
3444 ancestors or descendants of the starting revision.
3429
3445
3430 By default this command prints revision number and changeset id,
3446 By default this command prints revision number and changeset id,
3431 tags, non-trivial parents, user, date and time, and a summary for
3447 tags, non-trivial parents, user, date and time, and a summary for
3432 each commit. When the -v/--verbose switch is used, the list of
3448 each commit. When the -v/--verbose switch is used, the list of
3433 changed files and full commit message are shown.
3449 changed files and full commit message are shown.
3434
3450
3435 .. note::
3451 .. note::
3436 log -p/--patch may generate unexpected diff output for merge
3452 log -p/--patch may generate unexpected diff output for merge
3437 changesets, as it will only compare the merge changeset against
3453 changesets, as it will only compare the merge changeset against
3438 its first parent. Also, only files different from BOTH parents
3454 its first parent. Also, only files different from BOTH parents
3439 will appear in files:.
3455 will appear in files:.
3440
3456
3441 .. note::
3457 .. note::
3442 for performance reasons, log FILE may omit duplicate changes
3458 for performance reasons, log FILE may omit duplicate changes
3443 made on branches and will not show deletions. To see all
3459 made on branches and will not show deletions. To see all
3444 changes including duplicates and deletions, use the --removed
3460 changes including duplicates and deletions, use the --removed
3445 switch.
3461 switch.
3446
3462
3447 .. container:: verbose
3463 .. container:: verbose
3448
3464
3449 Some examples:
3465 Some examples:
3450
3466
3451 - changesets with full descriptions and file lists::
3467 - changesets with full descriptions and file lists::
3452
3468
3453 hg log -v
3469 hg log -v
3454
3470
3455 - changesets ancestral to the working directory::
3471 - changesets ancestral to the working directory::
3456
3472
3457 hg log -f
3473 hg log -f
3458
3474
3459 - last 10 commits on the current branch::
3475 - last 10 commits on the current branch::
3460
3476
3461 hg log -l 10 -b .
3477 hg log -l 10 -b .
3462
3478
3463 - changesets showing all modifications of a file, including removals::
3479 - changesets showing all modifications of a file, including removals::
3464
3480
3465 hg log --removed file.c
3481 hg log --removed file.c
3466
3482
3467 - all changesets that touch a directory, with diffs, excluding merges::
3483 - all changesets that touch a directory, with diffs, excluding merges::
3468
3484
3469 hg log -Mp lib/
3485 hg log -Mp lib/
3470
3486
3471 - all revision numbers that match a keyword::
3487 - all revision numbers that match a keyword::
3472
3488
3473 hg log -k bug --template "{rev}\\n"
3489 hg log -k bug --template "{rev}\\n"
3474
3490
3475 - check if a given changeset is included is a tagged release::
3491 - check if a given changeset is included is a tagged release::
3476
3492
3477 hg log -r "a21ccf and ancestor(1.9)"
3493 hg log -r "a21ccf and ancestor(1.9)"
3478
3494
3479 - find all changesets by some user in a date range::
3495 - find all changesets by some user in a date range::
3480
3496
3481 hg log -k alice -d "may 2008 to jul 2008"
3497 hg log -k alice -d "may 2008 to jul 2008"
3482
3498
3483 - summary of all changesets after the last tag::
3499 - summary of all changesets after the last tag::
3484
3500
3485 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3501 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3486
3502
3487 See :hg:`help dates` for a list of formats valid for -d/--date.
3503 See :hg:`help dates` for a list of formats valid for -d/--date.
3488
3504
3489 See :hg:`help revisions` and :hg:`help revsets` for more about
3505 See :hg:`help revisions` and :hg:`help revsets` for more about
3490 specifying revisions.
3506 specifying revisions.
3491
3507
3492 Returns 0 on success.
3508 Returns 0 on success.
3493 """
3509 """
3494
3510
3495 matchfn = scmutil.match(repo[None], pats, opts)
3511 matchfn = scmutil.match(repo[None], pats, opts)
3496 limit = cmdutil.loglimit(opts)
3512 limit = cmdutil.loglimit(opts)
3497 count = 0
3513 count = 0
3498
3514
3499 endrev = None
3515 endrev = None
3500 if opts.get('copies') and opts.get('rev'):
3516 if opts.get('copies') and opts.get('rev'):
3501 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3517 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3502
3518
3503 df = False
3519 df = False
3504 if opts["date"]:
3520 if opts["date"]:
3505 df = util.matchdate(opts["date"])
3521 df = util.matchdate(opts["date"])
3506
3522
3507 branches = opts.get('branch', []) + opts.get('only_branch', [])
3523 branches = opts.get('branch', []) + opts.get('only_branch', [])
3508 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3524 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3509
3525
3510 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3526 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3511 def prep(ctx, fns):
3527 def prep(ctx, fns):
3512 rev = ctx.rev()
3528 rev = ctx.rev()
3513 parents = [p for p in repo.changelog.parentrevs(rev)
3529 parents = [p for p in repo.changelog.parentrevs(rev)
3514 if p != nullrev]
3530 if p != nullrev]
3515 if opts.get('no_merges') and len(parents) == 2:
3531 if opts.get('no_merges') and len(parents) == 2:
3516 return
3532 return
3517 if opts.get('only_merges') and len(parents) != 2:
3533 if opts.get('only_merges') and len(parents) != 2:
3518 return
3534 return
3519 if opts.get('branch') and ctx.branch() not in opts['branch']:
3535 if opts.get('branch') and ctx.branch() not in opts['branch']:
3520 return
3536 return
3521 if not opts.get('hidden') and ctx.hidden():
3537 if not opts.get('hidden') and ctx.hidden():
3522 return
3538 return
3523 if df and not df(ctx.date()[0]):
3539 if df and not df(ctx.date()[0]):
3524 return
3540 return
3525 if opts['user'] and not [k for k in opts['user']
3541 if opts['user'] and not [k for k in opts['user']
3526 if k.lower() in ctx.user().lower()]:
3542 if k.lower() in ctx.user().lower()]:
3527 return
3543 return
3528 if opts.get('keyword'):
3544 if opts.get('keyword'):
3529 for k in [kw.lower() for kw in opts['keyword']]:
3545 for k in [kw.lower() for kw in opts['keyword']]:
3530 if (k in ctx.user().lower() or
3546 if (k in ctx.user().lower() or
3531 k in ctx.description().lower() or
3547 k in ctx.description().lower() or
3532 k in " ".join(ctx.files()).lower()):
3548 k in " ".join(ctx.files()).lower()):
3533 break
3549 break
3534 else:
3550 else:
3535 return
3551 return
3536
3552
3537 copies = None
3553 copies = None
3538 if opts.get('copies') and rev:
3554 if opts.get('copies') and rev:
3539 copies = []
3555 copies = []
3540 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3556 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3541 for fn in ctx.files():
3557 for fn in ctx.files():
3542 rename = getrenamed(fn, rev)
3558 rename = getrenamed(fn, rev)
3543 if rename:
3559 if rename:
3544 copies.append((fn, rename[0]))
3560 copies.append((fn, rename[0]))
3545
3561
3546 revmatchfn = None
3562 revmatchfn = None
3547 if opts.get('patch') or opts.get('stat'):
3563 if opts.get('patch') or opts.get('stat'):
3548 if opts.get('follow') or opts.get('follow_first'):
3564 if opts.get('follow') or opts.get('follow_first'):
3549 # note: this might be wrong when following through merges
3565 # note: this might be wrong when following through merges
3550 revmatchfn = scmutil.match(repo[None], fns, default='path')
3566 revmatchfn = scmutil.match(repo[None], fns, default='path')
3551 else:
3567 else:
3552 revmatchfn = matchfn
3568 revmatchfn = matchfn
3553
3569
3554 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3570 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3555
3571
3556 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3572 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3557 if count == limit:
3573 if count == limit:
3558 break
3574 break
3559 if displayer.flush(ctx.rev()):
3575 if displayer.flush(ctx.rev()):
3560 count += 1
3576 count += 1
3561 displayer.close()
3577 displayer.close()
3562
3578
3563 @command('manifest',
3579 @command('manifest',
3564 [('r', 'rev', '', _('revision to display'), _('REV')),
3580 [('r', 'rev', '', _('revision to display'), _('REV')),
3565 ('', 'all', False, _("list files from all revisions"))],
3581 ('', 'all', False, _("list files from all revisions"))],
3566 _('[-r REV]'))
3582 _('[-r REV]'))
3567 def manifest(ui, repo, node=None, rev=None, **opts):
3583 def manifest(ui, repo, node=None, rev=None, **opts):
3568 """output the current or given revision of the project manifest
3584 """output the current or given revision of the project manifest
3569
3585
3570 Print a list of version controlled files for the given revision.
3586 Print a list of version controlled files for the given revision.
3571 If no revision is given, the first parent of the working directory
3587 If no revision is given, the first parent of the working directory
3572 is used, or the null revision if no revision is checked out.
3588 is used, or the null revision if no revision is checked out.
3573
3589
3574 With -v, print file permissions, symlink and executable bits.
3590 With -v, print file permissions, symlink and executable bits.
3575 With --debug, print file revision hashes.
3591 With --debug, print file revision hashes.
3576
3592
3577 If option --all is specified, the list of all files from all revisions
3593 If option --all is specified, the list of all files from all revisions
3578 is printed. This includes deleted and renamed files.
3594 is printed. This includes deleted and renamed files.
3579
3595
3580 Returns 0 on success.
3596 Returns 0 on success.
3581 """
3597 """
3582 if opts.get('all'):
3598 if opts.get('all'):
3583 if rev or node:
3599 if rev or node:
3584 raise util.Abort(_("can't specify a revision with --all"))
3600 raise util.Abort(_("can't specify a revision with --all"))
3585
3601
3586 res = []
3602 res = []
3587 prefix = "data/"
3603 prefix = "data/"
3588 suffix = ".i"
3604 suffix = ".i"
3589 plen = len(prefix)
3605 plen = len(prefix)
3590 slen = len(suffix)
3606 slen = len(suffix)
3591 lock = repo.lock()
3607 lock = repo.lock()
3592 try:
3608 try:
3593 for fn, b, size in repo.store.datafiles():
3609 for fn, b, size in repo.store.datafiles():
3594 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3610 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3595 res.append(fn[plen:-slen])
3611 res.append(fn[plen:-slen])
3596 finally:
3612 finally:
3597 lock.release()
3613 lock.release()
3598 for f in sorted(res):
3614 for f in sorted(res):
3599 ui.write("%s\n" % f)
3615 ui.write("%s\n" % f)
3600 return
3616 return
3601
3617
3602 if rev and node:
3618 if rev and node:
3603 raise util.Abort(_("please specify just one revision"))
3619 raise util.Abort(_("please specify just one revision"))
3604
3620
3605 if not node:
3621 if not node:
3606 node = rev
3622 node = rev
3607
3623
3608 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3624 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3609 ctx = scmutil.revsingle(repo, node)
3625 ctx = scmutil.revsingle(repo, node)
3610 for f in ctx:
3626 for f in ctx:
3611 if ui.debugflag:
3627 if ui.debugflag:
3612 ui.write("%40s " % hex(ctx.manifest()[f]))
3628 ui.write("%40s " % hex(ctx.manifest()[f]))
3613 if ui.verbose:
3629 if ui.verbose:
3614 ui.write(decor[ctx.flags(f)])
3630 ui.write(decor[ctx.flags(f)])
3615 ui.write("%s\n" % f)
3631 ui.write("%s\n" % f)
3616
3632
3617 @command('^merge',
3633 @command('^merge',
3618 [('f', 'force', None, _('force a merge with outstanding changes')),
3634 [('f', 'force', None, _('force a merge with outstanding changes')),
3619 ('r', 'rev', '', _('revision to merge'), _('REV')),
3635 ('r', 'rev', '', _('revision to merge'), _('REV')),
3620 ('P', 'preview', None,
3636 ('P', 'preview', None,
3621 _('review revisions to merge (no merge is performed)'))
3637 _('review revisions to merge (no merge is performed)'))
3622 ] + mergetoolopts,
3638 ] + mergetoolopts,
3623 _('[-P] [-f] [[-r] REV]'))
3639 _('[-P] [-f] [[-r] REV]'))
3624 def merge(ui, repo, node=None, **opts):
3640 def merge(ui, repo, node=None, **opts):
3625 """merge working directory with another revision
3641 """merge working directory with another revision
3626
3642
3627 The current working directory is updated with all changes made in
3643 The current working directory is updated with all changes made in
3628 the requested revision since the last common predecessor revision.
3644 the requested revision since the last common predecessor revision.
3629
3645
3630 Files that changed between either parent are marked as changed for
3646 Files that changed between either parent are marked as changed for
3631 the next commit and a commit must be performed before any further
3647 the next commit and a commit must be performed before any further
3632 updates to the repository are allowed. The next commit will have
3648 updates to the repository are allowed. The next commit will have
3633 two parents.
3649 two parents.
3634
3650
3635 ``--tool`` can be used to specify the merge tool used for file
3651 ``--tool`` can be used to specify the merge tool used for file
3636 merges. It overrides the HGMERGE environment variable and your
3652 merges. It overrides the HGMERGE environment variable and your
3637 configuration files. See :hg:`help merge-tools` for options.
3653 configuration files. See :hg:`help merge-tools` for options.
3638
3654
3639 If no revision is specified, the working directory's parent is a
3655 If no revision is specified, the working directory's parent is a
3640 head revision, and the current branch contains exactly one other
3656 head revision, and the current branch contains exactly one other
3641 head, the other head is merged with by default. Otherwise, an
3657 head, the other head is merged with by default. Otherwise, an
3642 explicit revision with which to merge with must be provided.
3658 explicit revision with which to merge with must be provided.
3643
3659
3644 :hg:`resolve` must be used to resolve unresolved files.
3660 :hg:`resolve` must be used to resolve unresolved files.
3645
3661
3646 To undo an uncommitted merge, use :hg:`update --clean .` which
3662 To undo an uncommitted merge, use :hg:`update --clean .` which
3647 will check out a clean copy of the original merge parent, losing
3663 will check out a clean copy of the original merge parent, losing
3648 all changes.
3664 all changes.
3649
3665
3650 Returns 0 on success, 1 if there are unresolved files.
3666 Returns 0 on success, 1 if there are unresolved files.
3651 """
3667 """
3652
3668
3653 if opts.get('rev') and node:
3669 if opts.get('rev') and node:
3654 raise util.Abort(_("please specify just one revision"))
3670 raise util.Abort(_("please specify just one revision"))
3655 if not node:
3671 if not node:
3656 node = opts.get('rev')
3672 node = opts.get('rev')
3657
3673
3658 if not node:
3674 if not node:
3659 branch = repo[None].branch()
3675 branch = repo[None].branch()
3660 bheads = repo.branchheads(branch)
3676 bheads = repo.branchheads(branch)
3661 if len(bheads) > 2:
3677 if len(bheads) > 2:
3662 raise util.Abort(_("branch '%s' has %d heads - "
3678 raise util.Abort(_("branch '%s' has %d heads - "
3663 "please merge with an explicit rev")
3679 "please merge with an explicit rev")
3664 % (branch, len(bheads)),
3680 % (branch, len(bheads)),
3665 hint=_("run 'hg heads .' to see heads"))
3681 hint=_("run 'hg heads .' to see heads"))
3666
3682
3667 parent = repo.dirstate.p1()
3683 parent = repo.dirstate.p1()
3668 if len(bheads) == 1:
3684 if len(bheads) == 1:
3669 if len(repo.heads()) > 1:
3685 if len(repo.heads()) > 1:
3670 raise util.Abort(_("branch '%s' has one head - "
3686 raise util.Abort(_("branch '%s' has one head - "
3671 "please merge with an explicit rev")
3687 "please merge with an explicit rev")
3672 % branch,
3688 % branch,
3673 hint=_("run 'hg heads' to see all heads"))
3689 hint=_("run 'hg heads' to see all heads"))
3674 msg = _('there is nothing to merge')
3690 msg = _('there is nothing to merge')
3675 if parent != repo.lookup(repo[None].branch()):
3691 if parent != repo.lookup(repo[None].branch()):
3676 msg = _('%s - use "hg update" instead') % msg
3692 msg = _('%s - use "hg update" instead') % msg
3677 raise util.Abort(msg)
3693 raise util.Abort(msg)
3678
3694
3679 if parent not in bheads:
3695 if parent not in bheads:
3680 raise util.Abort(_('working directory not at a head revision'),
3696 raise util.Abort(_('working directory not at a head revision'),
3681 hint=_("use 'hg update' or merge with an "
3697 hint=_("use 'hg update' or merge with an "
3682 "explicit revision"))
3698 "explicit revision"))
3683 node = parent == bheads[0] and bheads[-1] or bheads[0]
3699 node = parent == bheads[0] and bheads[-1] or bheads[0]
3684 else:
3700 else:
3685 node = scmutil.revsingle(repo, node).node()
3701 node = scmutil.revsingle(repo, node).node()
3686
3702
3687 if opts.get('preview'):
3703 if opts.get('preview'):
3688 # find nodes that are ancestors of p2 but not of p1
3704 # find nodes that are ancestors of p2 but not of p1
3689 p1 = repo.lookup('.')
3705 p1 = repo.lookup('.')
3690 p2 = repo.lookup(node)
3706 p2 = repo.lookup(node)
3691 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3707 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3692
3708
3693 displayer = cmdutil.show_changeset(ui, repo, opts)
3709 displayer = cmdutil.show_changeset(ui, repo, opts)
3694 for node in nodes:
3710 for node in nodes:
3695 displayer.show(repo[node])
3711 displayer.show(repo[node])
3696 displayer.close()
3712 displayer.close()
3697 return 0
3713 return 0
3698
3714
3699 try:
3715 try:
3700 # ui.forcemerge is an internal variable, do not document
3716 # ui.forcemerge is an internal variable, do not document
3701 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3717 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3702 return hg.merge(repo, node, force=opts.get('force'))
3718 return hg.merge(repo, node, force=opts.get('force'))
3703 finally:
3719 finally:
3704 ui.setconfig('ui', 'forcemerge', '')
3720 ui.setconfig('ui', 'forcemerge', '')
3705
3721
3706 @command('outgoing|out',
3722 @command('outgoing|out',
3707 [('f', 'force', None, _('run even when the destination is unrelated')),
3723 [('f', 'force', None, _('run even when the destination is unrelated')),
3708 ('r', 'rev', [],
3724 ('r', 'rev', [],
3709 _('a changeset intended to be included in the destination'), _('REV')),
3725 _('a changeset intended to be included in the destination'), _('REV')),
3710 ('n', 'newest-first', None, _('show newest record first')),
3726 ('n', 'newest-first', None, _('show newest record first')),
3711 ('B', 'bookmarks', False, _('compare bookmarks')),
3727 ('B', 'bookmarks', False, _('compare bookmarks')),
3712 ('b', 'branch', [], _('a specific branch you would like to push'),
3728 ('b', 'branch', [], _('a specific branch you would like to push'),
3713 _('BRANCH')),
3729 _('BRANCH')),
3714 ] + logopts + remoteopts + subrepoopts,
3730 ] + logopts + remoteopts + subrepoopts,
3715 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3731 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3716 def outgoing(ui, repo, dest=None, **opts):
3732 def outgoing(ui, repo, dest=None, **opts):
3717 """show changesets not found in the destination
3733 """show changesets not found in the destination
3718
3734
3719 Show changesets not found in the specified destination repository
3735 Show changesets not found in the specified destination repository
3720 or the default push location. These are the changesets that would
3736 or the default push location. These are the changesets that would
3721 be pushed if a push was requested.
3737 be pushed if a push was requested.
3722
3738
3723 See pull for details of valid destination formats.
3739 See pull for details of valid destination formats.
3724
3740
3725 Returns 0 if there are outgoing changes, 1 otherwise.
3741 Returns 0 if there are outgoing changes, 1 otherwise.
3726 """
3742 """
3727
3743
3728 if opts.get('bookmarks'):
3744 if opts.get('bookmarks'):
3729 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3745 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3730 dest, branches = hg.parseurl(dest, opts.get('branch'))
3746 dest, branches = hg.parseurl(dest, opts.get('branch'))
3731 other = hg.peer(repo, opts, dest)
3747 other = hg.peer(repo, opts, dest)
3732 if 'bookmarks' not in other.listkeys('namespaces'):
3748 if 'bookmarks' not in other.listkeys('namespaces'):
3733 ui.warn(_("remote doesn't support bookmarks\n"))
3749 ui.warn(_("remote doesn't support bookmarks\n"))
3734 return 0
3750 return 0
3735 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3751 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3736 return bookmarks.diff(ui, other, repo)
3752 return bookmarks.diff(ui, other, repo)
3737
3753
3738 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3754 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3739 try:
3755 try:
3740 return hg.outgoing(ui, repo, dest, opts)
3756 return hg.outgoing(ui, repo, dest, opts)
3741 finally:
3757 finally:
3742 del repo._subtoppath
3758 del repo._subtoppath
3743
3759
3744 @command('parents',
3760 @command('parents',
3745 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3761 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3746 ] + templateopts,
3762 ] + templateopts,
3747 _('[-r REV] [FILE]'))
3763 _('[-r REV] [FILE]'))
3748 def parents(ui, repo, file_=None, **opts):
3764 def parents(ui, repo, file_=None, **opts):
3749 """show the parents of the working directory or revision
3765 """show the parents of the working directory or revision
3750
3766
3751 Print the working directory's parent revisions. If a revision is
3767 Print the working directory's parent revisions. If a revision is
3752 given via -r/--rev, the parent of that revision will be printed.
3768 given via -r/--rev, the parent of that revision will be printed.
3753 If a file argument is given, the revision in which the file was
3769 If a file argument is given, the revision in which the file was
3754 last changed (before the working directory revision or the
3770 last changed (before the working directory revision or the
3755 argument to --rev if given) is printed.
3771 argument to --rev if given) is printed.
3756
3772
3757 Returns 0 on success.
3773 Returns 0 on success.
3758 """
3774 """
3759
3775
3760 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3776 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3761
3777
3762 if file_:
3778 if file_:
3763 m = scmutil.match(ctx, (file_,), opts)
3779 m = scmutil.match(ctx, (file_,), opts)
3764 if m.anypats() or len(m.files()) != 1:
3780 if m.anypats() or len(m.files()) != 1:
3765 raise util.Abort(_('can only specify an explicit filename'))
3781 raise util.Abort(_('can only specify an explicit filename'))
3766 file_ = m.files()[0]
3782 file_ = m.files()[0]
3767 filenodes = []
3783 filenodes = []
3768 for cp in ctx.parents():
3784 for cp in ctx.parents():
3769 if not cp:
3785 if not cp:
3770 continue
3786 continue
3771 try:
3787 try:
3772 filenodes.append(cp.filenode(file_))
3788 filenodes.append(cp.filenode(file_))
3773 except error.LookupError:
3789 except error.LookupError:
3774 pass
3790 pass
3775 if not filenodes:
3791 if not filenodes:
3776 raise util.Abort(_("'%s' not found in manifest!") % file_)
3792 raise util.Abort(_("'%s' not found in manifest!") % file_)
3777 fl = repo.file(file_)
3793 fl = repo.file(file_)
3778 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3794 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3779 else:
3795 else:
3780 p = [cp.node() for cp in ctx.parents()]
3796 p = [cp.node() for cp in ctx.parents()]
3781
3797
3782 displayer = cmdutil.show_changeset(ui, repo, opts)
3798 displayer = cmdutil.show_changeset(ui, repo, opts)
3783 for n in p:
3799 for n in p:
3784 if n != nullid:
3800 if n != nullid:
3785 displayer.show(repo[n])
3801 displayer.show(repo[n])
3786 displayer.close()
3802 displayer.close()
3787
3803
3788 @command('paths', [], _('[NAME]'))
3804 @command('paths', [], _('[NAME]'))
3789 def paths(ui, repo, search=None):
3805 def paths(ui, repo, search=None):
3790 """show aliases for remote repositories
3806 """show aliases for remote repositories
3791
3807
3792 Show definition of symbolic path name NAME. If no name is given,
3808 Show definition of symbolic path name NAME. If no name is given,
3793 show definition of all available names.
3809 show definition of all available names.
3794
3810
3795 Option -q/--quiet suppresses all output when searching for NAME
3811 Option -q/--quiet suppresses all output when searching for NAME
3796 and shows only the path names when listing all definitions.
3812 and shows only the path names when listing all definitions.
3797
3813
3798 Path names are defined in the [paths] section of your
3814 Path names are defined in the [paths] section of your
3799 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3815 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3800 repository, ``.hg/hgrc`` is used, too.
3816 repository, ``.hg/hgrc`` is used, too.
3801
3817
3802 The path names ``default`` and ``default-push`` have a special
3818 The path names ``default`` and ``default-push`` have a special
3803 meaning. When performing a push or pull operation, they are used
3819 meaning. When performing a push or pull operation, they are used
3804 as fallbacks if no location is specified on the command-line.
3820 as fallbacks if no location is specified on the command-line.
3805 When ``default-push`` is set, it will be used for push and
3821 When ``default-push`` is set, it will be used for push and
3806 ``default`` will be used for pull; otherwise ``default`` is used
3822 ``default`` will be used for pull; otherwise ``default`` is used
3807 as the fallback for both. When cloning a repository, the clone
3823 as the fallback for both. When cloning a repository, the clone
3808 source is written as ``default`` in ``.hg/hgrc``. Note that
3824 source is written as ``default`` in ``.hg/hgrc``. Note that
3809 ``default`` and ``default-push`` apply to all inbound (e.g.
3825 ``default`` and ``default-push`` apply to all inbound (e.g.
3810 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3826 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3811 :hg:`bundle`) operations.
3827 :hg:`bundle`) operations.
3812
3828
3813 See :hg:`help urls` for more information.
3829 See :hg:`help urls` for more information.
3814
3830
3815 Returns 0 on success.
3831 Returns 0 on success.
3816 """
3832 """
3817 if search:
3833 if search:
3818 for name, path in ui.configitems("paths"):
3834 for name, path in ui.configitems("paths"):
3819 if name == search:
3835 if name == search:
3820 ui.status("%s\n" % util.hidepassword(path))
3836 ui.status("%s\n" % util.hidepassword(path))
3821 return
3837 return
3822 if not ui.quiet:
3838 if not ui.quiet:
3823 ui.warn(_("not found!\n"))
3839 ui.warn(_("not found!\n"))
3824 return 1
3840 return 1
3825 else:
3841 else:
3826 for name, path in ui.configitems("paths"):
3842 for name, path in ui.configitems("paths"):
3827 if ui.quiet:
3843 if ui.quiet:
3828 ui.write("%s\n" % name)
3844 ui.write("%s\n" % name)
3829 else:
3845 else:
3830 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3846 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3831
3847
3832 def postincoming(ui, repo, modheads, optupdate, checkout):
3848 def postincoming(ui, repo, modheads, optupdate, checkout):
3833 if modheads == 0:
3849 if modheads == 0:
3834 return
3850 return
3835 if optupdate:
3851 if optupdate:
3836 try:
3852 try:
3837 return hg.update(repo, checkout)
3853 return hg.update(repo, checkout)
3838 except util.Abort, inst:
3854 except util.Abort, inst:
3839 ui.warn(_("not updating: %s\n" % str(inst)))
3855 ui.warn(_("not updating: %s\n" % str(inst)))
3840 return 0
3856 return 0
3841 if modheads > 1:
3857 if modheads > 1:
3842 currentbranchheads = len(repo.branchheads())
3858 currentbranchheads = len(repo.branchheads())
3843 if currentbranchheads == modheads:
3859 if currentbranchheads == modheads:
3844 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3860 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3845 elif currentbranchheads > 1:
3861 elif currentbranchheads > 1:
3846 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3862 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3847 else:
3863 else:
3848 ui.status(_("(run 'hg heads' to see heads)\n"))
3864 ui.status(_("(run 'hg heads' to see heads)\n"))
3849 else:
3865 else:
3850 ui.status(_("(run 'hg update' to get a working copy)\n"))
3866 ui.status(_("(run 'hg update' to get a working copy)\n"))
3851
3867
3852 @command('^pull',
3868 @command('^pull',
3853 [('u', 'update', None,
3869 [('u', 'update', None,
3854 _('update to new branch head if changesets were pulled')),
3870 _('update to new branch head if changesets were pulled')),
3855 ('f', 'force', None, _('run even when remote repository is unrelated')),
3871 ('f', 'force', None, _('run even when remote repository is unrelated')),
3856 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3872 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3857 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3873 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3858 ('b', 'branch', [], _('a specific branch you would like to pull'),
3874 ('b', 'branch', [], _('a specific branch you would like to pull'),
3859 _('BRANCH')),
3875 _('BRANCH')),
3860 ] + remoteopts,
3876 ] + remoteopts,
3861 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3877 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3862 def pull(ui, repo, source="default", **opts):
3878 def pull(ui, repo, source="default", **opts):
3863 """pull changes from the specified source
3879 """pull changes from the specified source
3864
3880
3865 Pull changes from a remote repository to a local one.
3881 Pull changes from a remote repository to a local one.
3866
3882
3867 This finds all changes from the repository at the specified path
3883 This finds all changes from the repository at the specified path
3868 or URL and adds them to a local repository (the current one unless
3884 or URL and adds them to a local repository (the current one unless
3869 -R is specified). By default, this does not update the copy of the
3885 -R is specified). By default, this does not update the copy of the
3870 project in the working directory.
3886 project in the working directory.
3871
3887
3872 Use :hg:`incoming` if you want to see what would have been added
3888 Use :hg:`incoming` if you want to see what would have been added
3873 by a pull at the time you issued this command. If you then decide
3889 by a pull at the time you issued this command. If you then decide
3874 to add those changes to the repository, you should use :hg:`pull
3890 to add those changes to the repository, you should use :hg:`pull
3875 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3891 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3876
3892
3877 If SOURCE is omitted, the 'default' path will be used.
3893 If SOURCE is omitted, the 'default' path will be used.
3878 See :hg:`help urls` for more information.
3894 See :hg:`help urls` for more information.
3879
3895
3880 Returns 0 on success, 1 if an update had unresolved files.
3896 Returns 0 on success, 1 if an update had unresolved files.
3881 """
3897 """
3882 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3898 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3883 other = hg.peer(repo, opts, source)
3899 other = hg.peer(repo, opts, source)
3884 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3900 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3885 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3901 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3886
3902
3887 if opts.get('bookmark'):
3903 if opts.get('bookmark'):
3888 if not revs:
3904 if not revs:
3889 revs = []
3905 revs = []
3890 rb = other.listkeys('bookmarks')
3906 rb = other.listkeys('bookmarks')
3891 for b in opts['bookmark']:
3907 for b in opts['bookmark']:
3892 if b not in rb:
3908 if b not in rb:
3893 raise util.Abort(_('remote bookmark %s not found!') % b)
3909 raise util.Abort(_('remote bookmark %s not found!') % b)
3894 revs.append(rb[b])
3910 revs.append(rb[b])
3895
3911
3896 if revs:
3912 if revs:
3897 try:
3913 try:
3898 revs = [other.lookup(rev) for rev in revs]
3914 revs = [other.lookup(rev) for rev in revs]
3899 except error.CapabilityError:
3915 except error.CapabilityError:
3900 err = _("other repository doesn't support revision lookup, "
3916 err = _("other repository doesn't support revision lookup, "
3901 "so a rev cannot be specified.")
3917 "so a rev cannot be specified.")
3902 raise util.Abort(err)
3918 raise util.Abort(err)
3903
3919
3904 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3920 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3905 bookmarks.updatefromremote(ui, repo, other)
3921 bookmarks.updatefromremote(ui, repo, other)
3906 if checkout:
3922 if checkout:
3907 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3923 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3908 repo._subtoppath = source
3924 repo._subtoppath = source
3909 try:
3925 try:
3910 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3926 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3911
3927
3912 finally:
3928 finally:
3913 del repo._subtoppath
3929 del repo._subtoppath
3914
3930
3915 # update specified bookmarks
3931 # update specified bookmarks
3916 if opts.get('bookmark'):
3932 if opts.get('bookmark'):
3917 for b in opts['bookmark']:
3933 for b in opts['bookmark']:
3918 # explicit pull overrides local bookmark if any
3934 # explicit pull overrides local bookmark if any
3919 ui.status(_("importing bookmark %s\n") % b)
3935 ui.status(_("importing bookmark %s\n") % b)
3920 repo._bookmarks[b] = repo[rb[b]].node()
3936 repo._bookmarks[b] = repo[rb[b]].node()
3921 bookmarks.write(repo)
3937 bookmarks.write(repo)
3922
3938
3923 return ret
3939 return ret
3924
3940
3925 @command('^push',
3941 @command('^push',
3926 [('f', 'force', None, _('force push')),
3942 [('f', 'force', None, _('force push')),
3927 ('r', 'rev', [],
3943 ('r', 'rev', [],
3928 _('a changeset intended to be included in the destination'),
3944 _('a changeset intended to be included in the destination'),
3929 _('REV')),
3945 _('REV')),
3930 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3946 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3931 ('b', 'branch', [],
3947 ('b', 'branch', [],
3932 _('a specific branch you would like to push'), _('BRANCH')),
3948 _('a specific branch you would like to push'), _('BRANCH')),
3933 ('', 'new-branch', False, _('allow pushing a new branch')),
3949 ('', 'new-branch', False, _('allow pushing a new branch')),
3934 ] + remoteopts,
3950 ] + remoteopts,
3935 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3951 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3936 def push(ui, repo, dest=None, **opts):
3952 def push(ui, repo, dest=None, **opts):
3937 """push changes to the specified destination
3953 """push changes to the specified destination
3938
3954
3939 Push changesets from the local repository to the specified
3955 Push changesets from the local repository to the specified
3940 destination.
3956 destination.
3941
3957
3942 This operation is symmetrical to pull: it is identical to a pull
3958 This operation is symmetrical to pull: it is identical to a pull
3943 in the destination repository from the current one.
3959 in the destination repository from the current one.
3944
3960
3945 By default, push will not allow creation of new heads at the
3961 By default, push will not allow creation of new heads at the
3946 destination, since multiple heads would make it unclear which head
3962 destination, since multiple heads would make it unclear which head
3947 to use. In this situation, it is recommended to pull and merge
3963 to use. In this situation, it is recommended to pull and merge
3948 before pushing.
3964 before pushing.
3949
3965
3950 Use --new-branch if you want to allow push to create a new named
3966 Use --new-branch if you want to allow push to create a new named
3951 branch that is not present at the destination. This allows you to
3967 branch that is not present at the destination. This allows you to
3952 only create a new branch without forcing other changes.
3968 only create a new branch without forcing other changes.
3953
3969
3954 Use -f/--force to override the default behavior and push all
3970 Use -f/--force to override the default behavior and push all
3955 changesets on all branches.
3971 changesets on all branches.
3956
3972
3957 If -r/--rev is used, the specified revision and all its ancestors
3973 If -r/--rev is used, the specified revision and all its ancestors
3958 will be pushed to the remote repository.
3974 will be pushed to the remote repository.
3959
3975
3960 Please see :hg:`help urls` for important details about ``ssh://``
3976 Please see :hg:`help urls` for important details about ``ssh://``
3961 URLs. If DESTINATION is omitted, a default path will be used.
3977 URLs. If DESTINATION is omitted, a default path will be used.
3962
3978
3963 Returns 0 if push was successful, 1 if nothing to push.
3979 Returns 0 if push was successful, 1 if nothing to push.
3964 """
3980 """
3965
3981
3966 if opts.get('bookmark'):
3982 if opts.get('bookmark'):
3967 for b in opts['bookmark']:
3983 for b in opts['bookmark']:
3968 # translate -B options to -r so changesets get pushed
3984 # translate -B options to -r so changesets get pushed
3969 if b in repo._bookmarks:
3985 if b in repo._bookmarks:
3970 opts.setdefault('rev', []).append(b)
3986 opts.setdefault('rev', []).append(b)
3971 else:
3987 else:
3972 # if we try to push a deleted bookmark, translate it to null
3988 # if we try to push a deleted bookmark, translate it to null
3973 # this lets simultaneous -r, -b options continue working
3989 # this lets simultaneous -r, -b options continue working
3974 opts.setdefault('rev', []).append("null")
3990 opts.setdefault('rev', []).append("null")
3975
3991
3976 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3992 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3977 dest, branches = hg.parseurl(dest, opts.get('branch'))
3993 dest, branches = hg.parseurl(dest, opts.get('branch'))
3978 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3994 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3979 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3995 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3980 other = hg.peer(repo, opts, dest)
3996 other = hg.peer(repo, opts, dest)
3981 if revs:
3997 if revs:
3982 revs = [repo.lookup(rev) for rev in revs]
3998 revs = [repo.lookup(rev) for rev in revs]
3983
3999
3984 repo._subtoppath = dest
4000 repo._subtoppath = dest
3985 try:
4001 try:
3986 # push subrepos depth-first for coherent ordering
4002 # push subrepos depth-first for coherent ordering
3987 c = repo['']
4003 c = repo['']
3988 subs = c.substate # only repos that are committed
4004 subs = c.substate # only repos that are committed
3989 for s in sorted(subs):
4005 for s in sorted(subs):
3990 if not c.sub(s).push(opts.get('force')):
4006 if not c.sub(s).push(opts.get('force')):
3991 return False
4007 return False
3992 finally:
4008 finally:
3993 del repo._subtoppath
4009 del repo._subtoppath
3994 result = repo.push(other, opts.get('force'), revs=revs,
4010 result = repo.push(other, opts.get('force'), revs=revs,
3995 newbranch=opts.get('new_branch'))
4011 newbranch=opts.get('new_branch'))
3996
4012
3997 result = (result == 0)
4013 result = (result == 0)
3998
4014
3999 if opts.get('bookmark'):
4015 if opts.get('bookmark'):
4000 rb = other.listkeys('bookmarks')
4016 rb = other.listkeys('bookmarks')
4001 for b in opts['bookmark']:
4017 for b in opts['bookmark']:
4002 # explicit push overrides remote bookmark if any
4018 # explicit push overrides remote bookmark if any
4003 if b in repo._bookmarks:
4019 if b in repo._bookmarks:
4004 ui.status(_("exporting bookmark %s\n") % b)
4020 ui.status(_("exporting bookmark %s\n") % b)
4005 new = repo[b].hex()
4021 new = repo[b].hex()
4006 elif b in rb:
4022 elif b in rb:
4007 ui.status(_("deleting remote bookmark %s\n") % b)
4023 ui.status(_("deleting remote bookmark %s\n") % b)
4008 new = '' # delete
4024 new = '' # delete
4009 else:
4025 else:
4010 ui.warn(_('bookmark %s does not exist on the local '
4026 ui.warn(_('bookmark %s does not exist on the local '
4011 'or remote repository!\n') % b)
4027 'or remote repository!\n') % b)
4012 return 2
4028 return 2
4013 old = rb.get(b, '')
4029 old = rb.get(b, '')
4014 r = other.pushkey('bookmarks', b, old, new)
4030 r = other.pushkey('bookmarks', b, old, new)
4015 if not r:
4031 if not r:
4016 ui.warn(_('updating bookmark %s failed!\n') % b)
4032 ui.warn(_('updating bookmark %s failed!\n') % b)
4017 if not result:
4033 if not result:
4018 result = 2
4034 result = 2
4019
4035
4020 return result
4036 return result
4021
4037
4022 @command('recover', [])
4038 @command('recover', [])
4023 def recover(ui, repo):
4039 def recover(ui, repo):
4024 """roll back an interrupted transaction
4040 """roll back an interrupted transaction
4025
4041
4026 Recover from an interrupted commit or pull.
4042 Recover from an interrupted commit or pull.
4027
4043
4028 This command tries to fix the repository status after an
4044 This command tries to fix the repository status after an
4029 interrupted operation. It should only be necessary when Mercurial
4045 interrupted operation. It should only be necessary when Mercurial
4030 suggests it.
4046 suggests it.
4031
4047
4032 Returns 0 if successful, 1 if nothing to recover or verify fails.
4048 Returns 0 if successful, 1 if nothing to recover or verify fails.
4033 """
4049 """
4034 if repo.recover():
4050 if repo.recover():
4035 return hg.verify(repo)
4051 return hg.verify(repo)
4036 return 1
4052 return 1
4037
4053
4038 @command('^remove|rm',
4054 @command('^remove|rm',
4039 [('A', 'after', None, _('record delete for missing files')),
4055 [('A', 'after', None, _('record delete for missing files')),
4040 ('f', 'force', None,
4056 ('f', 'force', None,
4041 _('remove (and delete) file even if added or modified')),
4057 _('remove (and delete) file even if added or modified')),
4042 ] + walkopts,
4058 ] + walkopts,
4043 _('[OPTION]... FILE...'))
4059 _('[OPTION]... FILE...'))
4044 def remove(ui, repo, *pats, **opts):
4060 def remove(ui, repo, *pats, **opts):
4045 """remove the specified files on the next commit
4061 """remove the specified files on the next commit
4046
4062
4047 Schedule the indicated files for removal from the repository.
4063 Schedule the indicated files for removal from the repository.
4048
4064
4049 This only removes files from the current branch, not from the
4065 This only removes files from the current branch, not from the
4050 entire project history. -A/--after can be used to remove only
4066 entire project history. -A/--after can be used to remove only
4051 files that have already been deleted, -f/--force can be used to
4067 files that have already been deleted, -f/--force can be used to
4052 force deletion, and -Af can be used to remove files from the next
4068 force deletion, and -Af can be used to remove files from the next
4053 revision without deleting them from the working directory.
4069 revision without deleting them from the working directory.
4054
4070
4055 The following table details the behavior of remove for different
4071 The following table details the behavior of remove for different
4056 file states (columns) and option combinations (rows). The file
4072 file states (columns) and option combinations (rows). The file
4057 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
4073 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
4058 reported by :hg:`status`). The actions are Warn, Remove (from
4074 reported by :hg:`status`). The actions are Warn, Remove (from
4059 branch) and Delete (from disk):
4075 branch) and Delete (from disk):
4060
4076
4061 ======= == == == ==
4077 ======= == == == ==
4062 A C M !
4078 A C M !
4063 ======= == == == ==
4079 ======= == == == ==
4064 none W RD W R
4080 none W RD W R
4065 -f R RD RD R
4081 -f R RD RD R
4066 -A W W W R
4082 -A W W W R
4067 -Af R R R R
4083 -Af R R R R
4068 ======= == == == ==
4084 ======= == == == ==
4069
4085
4070 Note that remove never deletes files in Added [A] state from the
4086 Note that remove never deletes files in Added [A] state from the
4071 working directory, not even if option --force is specified.
4087 working directory, not even if option --force is specified.
4072
4088
4073 This command schedules the files to be removed at the next commit.
4089 This command schedules the files to be removed at the next commit.
4074 To undo a remove before that, see :hg:`revert`.
4090 To undo a remove before that, see :hg:`revert`.
4075
4091
4076 Returns 0 on success, 1 if any warnings encountered.
4092 Returns 0 on success, 1 if any warnings encountered.
4077 """
4093 """
4078
4094
4079 ret = 0
4095 ret = 0
4080 after, force = opts.get('after'), opts.get('force')
4096 after, force = opts.get('after'), opts.get('force')
4081 if not pats and not after:
4097 if not pats and not after:
4082 raise util.Abort(_('no files specified'))
4098 raise util.Abort(_('no files specified'))
4083
4099
4084 m = scmutil.match(repo[None], pats, opts)
4100 m = scmutil.match(repo[None], pats, opts)
4085 s = repo.status(match=m, clean=True)
4101 s = repo.status(match=m, clean=True)
4086 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4102 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4087
4103
4088 for f in m.files():
4104 for f in m.files():
4089 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4105 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4090 if os.path.exists(m.rel(f)):
4106 if os.path.exists(m.rel(f)):
4091 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4107 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4092 ret = 1
4108 ret = 1
4093
4109
4094 if force:
4110 if force:
4095 list = modified + deleted + clean + added
4111 list = modified + deleted + clean + added
4096 elif after:
4112 elif after:
4097 list = deleted
4113 list = deleted
4098 for f in modified + added + clean:
4114 for f in modified + added + clean:
4099 ui.warn(_('not removing %s: file still exists (use -f'
4115 ui.warn(_('not removing %s: file still exists (use -f'
4100 ' to force removal)\n') % m.rel(f))
4116 ' to force removal)\n') % m.rel(f))
4101 ret = 1
4117 ret = 1
4102 else:
4118 else:
4103 list = deleted + clean
4119 list = deleted + clean
4104 for f in modified:
4120 for f in modified:
4105 ui.warn(_('not removing %s: file is modified (use -f'
4121 ui.warn(_('not removing %s: file is modified (use -f'
4106 ' to force removal)\n') % m.rel(f))
4122 ' to force removal)\n') % m.rel(f))
4107 ret = 1
4123 ret = 1
4108 for f in added:
4124 for f in added:
4109 ui.warn(_('not removing %s: file has been marked for add (use -f'
4125 ui.warn(_('not removing %s: file has been marked for add (use -f'
4110 ' to force removal)\n') % m.rel(f))
4126 ' to force removal)\n') % m.rel(f))
4111 ret = 1
4127 ret = 1
4112
4128
4113 for f in sorted(list):
4129 for f in sorted(list):
4114 if ui.verbose or not m.exact(f):
4130 if ui.verbose or not m.exact(f):
4115 ui.status(_('removing %s\n') % m.rel(f))
4131 ui.status(_('removing %s\n') % m.rel(f))
4116
4132
4117 wlock = repo.wlock()
4133 wlock = repo.wlock()
4118 try:
4134 try:
4119 if not after:
4135 if not after:
4120 for f in list:
4136 for f in list:
4121 if f in added:
4137 if f in added:
4122 continue # we never unlink added files on remove
4138 continue # we never unlink added files on remove
4123 try:
4139 try:
4124 util.unlinkpath(repo.wjoin(f))
4140 util.unlinkpath(repo.wjoin(f))
4125 except OSError, inst:
4141 except OSError, inst:
4126 if inst.errno != errno.ENOENT:
4142 if inst.errno != errno.ENOENT:
4127 raise
4143 raise
4128 repo[None].forget(list)
4144 repo[None].forget(list)
4129 finally:
4145 finally:
4130 wlock.release()
4146 wlock.release()
4131
4147
4132 return ret
4148 return ret
4133
4149
4134 @command('rename|move|mv',
4150 @command('rename|move|mv',
4135 [('A', 'after', None, _('record a rename that has already occurred')),
4151 [('A', 'after', None, _('record a rename that has already occurred')),
4136 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4152 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4137 ] + walkopts + dryrunopts,
4153 ] + walkopts + dryrunopts,
4138 _('[OPTION]... SOURCE... DEST'))
4154 _('[OPTION]... SOURCE... DEST'))
4139 def rename(ui, repo, *pats, **opts):
4155 def rename(ui, repo, *pats, **opts):
4140 """rename files; equivalent of copy + remove
4156 """rename files; equivalent of copy + remove
4141
4157
4142 Mark dest as copies of sources; mark sources for deletion. If dest
4158 Mark dest as copies of sources; mark sources for deletion. If dest
4143 is a directory, copies are put in that directory. If dest is a
4159 is a directory, copies are put in that directory. If dest is a
4144 file, there can only be one source.
4160 file, there can only be one source.
4145
4161
4146 By default, this command copies the contents of files as they
4162 By default, this command copies the contents of files as they
4147 exist in the working directory. If invoked with -A/--after, the
4163 exist in the working directory. If invoked with -A/--after, the
4148 operation is recorded, but no copying is performed.
4164 operation is recorded, but no copying is performed.
4149
4165
4150 This command takes effect at the next commit. To undo a rename
4166 This command takes effect at the next commit. To undo a rename
4151 before that, see :hg:`revert`.
4167 before that, see :hg:`revert`.
4152
4168
4153 Returns 0 on success, 1 if errors are encountered.
4169 Returns 0 on success, 1 if errors are encountered.
4154 """
4170 """
4155 wlock = repo.wlock(False)
4171 wlock = repo.wlock(False)
4156 try:
4172 try:
4157 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4173 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4158 finally:
4174 finally:
4159 wlock.release()
4175 wlock.release()
4160
4176
4161 @command('resolve',
4177 @command('resolve',
4162 [('a', 'all', None, _('select all unresolved files')),
4178 [('a', 'all', None, _('select all unresolved files')),
4163 ('l', 'list', None, _('list state of files needing merge')),
4179 ('l', 'list', None, _('list state of files needing merge')),
4164 ('m', 'mark', None, _('mark files as resolved')),
4180 ('m', 'mark', None, _('mark files as resolved')),
4165 ('u', 'unmark', None, _('mark files as unresolved')),
4181 ('u', 'unmark', None, _('mark files as unresolved')),
4166 ('n', 'no-status', None, _('hide status prefix'))]
4182 ('n', 'no-status', None, _('hide status prefix'))]
4167 + mergetoolopts + walkopts,
4183 + mergetoolopts + walkopts,
4168 _('[OPTION]... [FILE]...'))
4184 _('[OPTION]... [FILE]...'))
4169 def resolve(ui, repo, *pats, **opts):
4185 def resolve(ui, repo, *pats, **opts):
4170 """redo merges or set/view the merge status of files
4186 """redo merges or set/view the merge status of files
4171
4187
4172 Merges with unresolved conflicts are often the result of
4188 Merges with unresolved conflicts are often the result of
4173 non-interactive merging using the ``internal:merge`` configuration
4189 non-interactive merging using the ``internal:merge`` configuration
4174 setting, or a command-line merge tool like ``diff3``. The resolve
4190 setting, or a command-line merge tool like ``diff3``. The resolve
4175 command is used to manage the files involved in a merge, after
4191 command is used to manage the files involved in a merge, after
4176 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4192 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4177 working directory must have two parents).
4193 working directory must have two parents).
4178
4194
4179 The resolve command can be used in the following ways:
4195 The resolve command can be used in the following ways:
4180
4196
4181 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4197 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4182 files, discarding any previous merge attempts. Re-merging is not
4198 files, discarding any previous merge attempts. Re-merging is not
4183 performed for files already marked as resolved. Use ``--all/-a``
4199 performed for files already marked as resolved. Use ``--all/-a``
4184 to select all unresolved files. ``--tool`` can be used to specify
4200 to select all unresolved files. ``--tool`` can be used to specify
4185 the merge tool used for the given files. It overrides the HGMERGE
4201 the merge tool used for the given files. It overrides the HGMERGE
4186 environment variable and your configuration files.
4202 environment variable and your configuration files.
4187
4203
4188 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4204 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4189 (e.g. after having manually fixed-up the files). The default is
4205 (e.g. after having manually fixed-up the files). The default is
4190 to mark all unresolved files.
4206 to mark all unresolved files.
4191
4207
4192 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4208 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4193 default is to mark all resolved files.
4209 default is to mark all resolved files.
4194
4210
4195 - :hg:`resolve -l`: list files which had or still have conflicts.
4211 - :hg:`resolve -l`: list files which had or still have conflicts.
4196 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4212 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4197
4213
4198 Note that Mercurial will not let you commit files with unresolved
4214 Note that Mercurial will not let you commit files with unresolved
4199 merge conflicts. You must use :hg:`resolve -m ...` before you can
4215 merge conflicts. You must use :hg:`resolve -m ...` before you can
4200 commit after a conflicting merge.
4216 commit after a conflicting merge.
4201
4217
4202 Returns 0 on success, 1 if any files fail a resolve attempt.
4218 Returns 0 on success, 1 if any files fail a resolve attempt.
4203 """
4219 """
4204
4220
4205 all, mark, unmark, show, nostatus = \
4221 all, mark, unmark, show, nostatus = \
4206 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4222 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4207
4223
4208 if (show and (mark or unmark)) or (mark and unmark):
4224 if (show and (mark or unmark)) or (mark and unmark):
4209 raise util.Abort(_("too many options specified"))
4225 raise util.Abort(_("too many options specified"))
4210 if pats and all:
4226 if pats and all:
4211 raise util.Abort(_("can't specify --all and patterns"))
4227 raise util.Abort(_("can't specify --all and patterns"))
4212 if not (all or pats or show or mark or unmark):
4228 if not (all or pats or show or mark or unmark):
4213 raise util.Abort(_('no files or directories specified; '
4229 raise util.Abort(_('no files or directories specified; '
4214 'use --all to remerge all files'))
4230 'use --all to remerge all files'))
4215
4231
4216 ms = mergemod.mergestate(repo)
4232 ms = mergemod.mergestate(repo)
4217 m = scmutil.match(repo[None], pats, opts)
4233 m = scmutil.match(repo[None], pats, opts)
4218 ret = 0
4234 ret = 0
4219
4235
4220 for f in ms:
4236 for f in ms:
4221 if m(f):
4237 if m(f):
4222 if show:
4238 if show:
4223 if nostatus:
4239 if nostatus:
4224 ui.write("%s\n" % f)
4240 ui.write("%s\n" % f)
4225 else:
4241 else:
4226 ui.write("%s %s\n" % (ms[f].upper(), f),
4242 ui.write("%s %s\n" % (ms[f].upper(), f),
4227 label='resolve.' +
4243 label='resolve.' +
4228 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4244 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4229 elif mark:
4245 elif mark:
4230 ms.mark(f, "r")
4246 ms.mark(f, "r")
4231 elif unmark:
4247 elif unmark:
4232 ms.mark(f, "u")
4248 ms.mark(f, "u")
4233 else:
4249 else:
4234 wctx = repo[None]
4250 wctx = repo[None]
4235 mctx = wctx.parents()[-1]
4251 mctx = wctx.parents()[-1]
4236
4252
4237 # backup pre-resolve (merge uses .orig for its own purposes)
4253 # backup pre-resolve (merge uses .orig for its own purposes)
4238 a = repo.wjoin(f)
4254 a = repo.wjoin(f)
4239 util.copyfile(a, a + ".resolve")
4255 util.copyfile(a, a + ".resolve")
4240
4256
4241 try:
4257 try:
4242 # resolve file
4258 # resolve file
4243 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4259 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4244 if ms.resolve(f, wctx, mctx):
4260 if ms.resolve(f, wctx, mctx):
4245 ret = 1
4261 ret = 1
4246 finally:
4262 finally:
4247 ui.setconfig('ui', 'forcemerge', '')
4263 ui.setconfig('ui', 'forcemerge', '')
4248
4264
4249 # replace filemerge's .orig file with our resolve file
4265 # replace filemerge's .orig file with our resolve file
4250 util.rename(a + ".resolve", a + ".orig")
4266 util.rename(a + ".resolve", a + ".orig")
4251
4267
4252 ms.commit()
4268 ms.commit()
4253 return ret
4269 return ret
4254
4270
4255 @command('revert',
4271 @command('revert',
4256 [('a', 'all', None, _('revert all changes when no arguments given')),
4272 [('a', 'all', None, _('revert all changes when no arguments given')),
4257 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4273 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4258 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4274 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4259 ('C', 'no-backup', None, _('do not save backup copies of files')),
4275 ('C', 'no-backup', None, _('do not save backup copies of files')),
4260 ] + walkopts + dryrunopts,
4276 ] + walkopts + dryrunopts,
4261 _('[OPTION]... [-r REV] [NAME]...'))
4277 _('[OPTION]... [-r REV] [NAME]...'))
4262 def revert(ui, repo, *pats, **opts):
4278 def revert(ui, repo, *pats, **opts):
4263 """restore files to their checkout state
4279 """restore files to their checkout state
4264
4280
4265 .. note::
4281 .. note::
4266 To check out earlier revisions, you should use :hg:`update REV`.
4282 To check out earlier revisions, you should use :hg:`update REV`.
4267 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4283 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4268
4284
4269 With no revision specified, revert the specified files or directories
4285 With no revision specified, revert the specified files or directories
4270 to the contents they had in the parent of the working directory.
4286 to the contents they had in the parent of the working directory.
4271 This restores the contents of files to an unmodified
4287 This restores the contents of files to an unmodified
4272 state and unschedules adds, removes, copies, and renames. If the
4288 state and unschedules adds, removes, copies, and renames. If the
4273 working directory has two parents, you must explicitly specify a
4289 working directory has two parents, you must explicitly specify a
4274 revision.
4290 revision.
4275
4291
4276 Using the -r/--rev or -d/--date options, revert the given files or
4292 Using the -r/--rev or -d/--date options, revert the given files or
4277 directories to their states as of a specific revision. Because
4293 directories to their states as of a specific revision. Because
4278 revert does not change the working directory parents, this will
4294 revert does not change the working directory parents, this will
4279 cause these files to appear modified. This can be helpful to "back
4295 cause these files to appear modified. This can be helpful to "back
4280 out" some or all of an earlier change. See :hg:`backout` for a
4296 out" some or all of an earlier change. See :hg:`backout` for a
4281 related method.
4297 related method.
4282
4298
4283 Modified files are saved with a .orig suffix before reverting.
4299 Modified files are saved with a .orig suffix before reverting.
4284 To disable these backups, use --no-backup.
4300 To disable these backups, use --no-backup.
4285
4301
4286 See :hg:`help dates` for a list of formats valid for -d/--date.
4302 See :hg:`help dates` for a list of formats valid for -d/--date.
4287
4303
4288 Returns 0 on success.
4304 Returns 0 on success.
4289 """
4305 """
4290
4306
4291 if opts.get("date"):
4307 if opts.get("date"):
4292 if opts.get("rev"):
4308 if opts.get("rev"):
4293 raise util.Abort(_("you can't specify a revision and a date"))
4309 raise util.Abort(_("you can't specify a revision and a date"))
4294 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4310 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4295
4311
4296 parent, p2 = repo.dirstate.parents()
4312 parent, p2 = repo.dirstate.parents()
4297 if not opts.get('rev') and p2 != nullid:
4313 if not opts.get('rev') and p2 != nullid:
4298 # revert after merge is a trap for new users (issue2915)
4314 # revert after merge is a trap for new users (issue2915)
4299 raise util.Abort(_('uncommitted merge with no revision specified'),
4315 raise util.Abort(_('uncommitted merge with no revision specified'),
4300 hint=_('use "hg update" or see "hg help revert"'))
4316 hint=_('use "hg update" or see "hg help revert"'))
4301
4317
4302 ctx = scmutil.revsingle(repo, opts.get('rev'))
4318 ctx = scmutil.revsingle(repo, opts.get('rev'))
4303 node = ctx.node()
4319 node = ctx.node()
4304
4320
4305 if not pats and not opts.get('all'):
4321 if not pats and not opts.get('all'):
4306 msg = _("no files or directories specified")
4322 msg = _("no files or directories specified")
4307 if p2 != nullid:
4323 if p2 != nullid:
4308 hint = _("uncommitted merge, use --all to discard all changes,"
4324 hint = _("uncommitted merge, use --all to discard all changes,"
4309 " or 'hg update -C .' to abort the merge")
4325 " or 'hg update -C .' to abort the merge")
4310 raise util.Abort(msg, hint=hint)
4326 raise util.Abort(msg, hint=hint)
4311 dirty = util.any(repo.status())
4327 dirty = util.any(repo.status())
4312 if node != parent:
4328 if node != parent:
4313 if dirty:
4329 if dirty:
4314 hint = _("uncommitted changes, use --all to discard all"
4330 hint = _("uncommitted changes, use --all to discard all"
4315 " changes, or 'hg update %s' to update") % ctx.rev()
4331 " changes, or 'hg update %s' to update") % ctx.rev()
4316 else:
4332 else:
4317 hint = _("use --all to revert all files,"
4333 hint = _("use --all to revert all files,"
4318 " or 'hg update %s' to update") % ctx.rev()
4334 " or 'hg update %s' to update") % ctx.rev()
4319 elif dirty:
4335 elif dirty:
4320 hint = _("uncommitted changes, use --all to discard all changes")
4336 hint = _("uncommitted changes, use --all to discard all changes")
4321 else:
4337 else:
4322 hint = _("use --all to revert all files")
4338 hint = _("use --all to revert all files")
4323 raise util.Abort(msg, hint=hint)
4339 raise util.Abort(msg, hint=hint)
4324
4340
4325 mf = ctx.manifest()
4341 mf = ctx.manifest()
4326 if node == parent:
4342 if node == parent:
4327 pmf = mf
4343 pmf = mf
4328 else:
4344 else:
4329 pmf = None
4345 pmf = None
4330
4346
4331 # need all matching names in dirstate and manifest of target rev,
4347 # need all matching names in dirstate and manifest of target rev,
4332 # so have to walk both. do not print errors if files exist in one
4348 # so have to walk both. do not print errors if files exist in one
4333 # but not other.
4349 # but not other.
4334
4350
4335 names = {}
4351 names = {}
4336
4352
4337 wlock = repo.wlock()
4353 wlock = repo.wlock()
4338 try:
4354 try:
4339 # walk dirstate.
4355 # walk dirstate.
4340
4356
4341 m = scmutil.match(repo[None], pats, opts)
4357 m = scmutil.match(repo[None], pats, opts)
4342 m.bad = lambda x, y: False
4358 m.bad = lambda x, y: False
4343 for abs in repo.walk(m):
4359 for abs in repo.walk(m):
4344 names[abs] = m.rel(abs), m.exact(abs)
4360 names[abs] = m.rel(abs), m.exact(abs)
4345
4361
4346 # walk target manifest.
4362 # walk target manifest.
4347
4363
4348 def badfn(path, msg):
4364 def badfn(path, msg):
4349 if path in names:
4365 if path in names:
4350 return
4366 return
4351 path_ = path + '/'
4367 path_ = path + '/'
4352 for f in names:
4368 for f in names:
4353 if f.startswith(path_):
4369 if f.startswith(path_):
4354 return
4370 return
4355 ui.warn("%s: %s\n" % (m.rel(path), msg))
4371 ui.warn("%s: %s\n" % (m.rel(path), msg))
4356
4372
4357 m = scmutil.match(repo[node], pats, opts)
4373 m = scmutil.match(repo[node], pats, opts)
4358 m.bad = badfn
4374 m.bad = badfn
4359 for abs in repo[node].walk(m):
4375 for abs in repo[node].walk(m):
4360 if abs not in names:
4376 if abs not in names:
4361 names[abs] = m.rel(abs), m.exact(abs)
4377 names[abs] = m.rel(abs), m.exact(abs)
4362
4378
4363 m = scmutil.matchfiles(repo, names)
4379 m = scmutil.matchfiles(repo, names)
4364 changes = repo.status(match=m)[:4]
4380 changes = repo.status(match=m)[:4]
4365 modified, added, removed, deleted = map(set, changes)
4381 modified, added, removed, deleted = map(set, changes)
4366
4382
4367 # if f is a rename, also revert the source
4383 # if f is a rename, also revert the source
4368 cwd = repo.getcwd()
4384 cwd = repo.getcwd()
4369 for f in added:
4385 for f in added:
4370 src = repo.dirstate.copied(f)
4386 src = repo.dirstate.copied(f)
4371 if src and src not in names and repo.dirstate[src] == 'r':
4387 if src and src not in names and repo.dirstate[src] == 'r':
4372 removed.add(src)
4388 removed.add(src)
4373 names[src] = (repo.pathto(src, cwd), True)
4389 names[src] = (repo.pathto(src, cwd), True)
4374
4390
4375 def removeforget(abs):
4391 def removeforget(abs):
4376 if repo.dirstate[abs] == 'a':
4392 if repo.dirstate[abs] == 'a':
4377 return _('forgetting %s\n')
4393 return _('forgetting %s\n')
4378 return _('removing %s\n')
4394 return _('removing %s\n')
4379
4395
4380 revert = ([], _('reverting %s\n'))
4396 revert = ([], _('reverting %s\n'))
4381 add = ([], _('adding %s\n'))
4397 add = ([], _('adding %s\n'))
4382 remove = ([], removeforget)
4398 remove = ([], removeforget)
4383 undelete = ([], _('undeleting %s\n'))
4399 undelete = ([], _('undeleting %s\n'))
4384
4400
4385 disptable = (
4401 disptable = (
4386 # dispatch table:
4402 # dispatch table:
4387 # file state
4403 # file state
4388 # action if in target manifest
4404 # action if in target manifest
4389 # action if not in target manifest
4405 # action if not in target manifest
4390 # make backup if in target manifest
4406 # make backup if in target manifest
4391 # make backup if not in target manifest
4407 # make backup if not in target manifest
4392 (modified, revert, remove, True, True),
4408 (modified, revert, remove, True, True),
4393 (added, revert, remove, True, False),
4409 (added, revert, remove, True, False),
4394 (removed, undelete, None, False, False),
4410 (removed, undelete, None, False, False),
4395 (deleted, revert, remove, False, False),
4411 (deleted, revert, remove, False, False),
4396 )
4412 )
4397
4413
4398 for abs, (rel, exact) in sorted(names.items()):
4414 for abs, (rel, exact) in sorted(names.items()):
4399 mfentry = mf.get(abs)
4415 mfentry = mf.get(abs)
4400 target = repo.wjoin(abs)
4416 target = repo.wjoin(abs)
4401 def handle(xlist, dobackup):
4417 def handle(xlist, dobackup):
4402 xlist[0].append(abs)
4418 xlist[0].append(abs)
4403 if (dobackup and not opts.get('no_backup') and
4419 if (dobackup and not opts.get('no_backup') and
4404 os.path.lexists(target)):
4420 os.path.lexists(target)):
4405 bakname = "%s.orig" % rel
4421 bakname = "%s.orig" % rel
4406 ui.note(_('saving current version of %s as %s\n') %
4422 ui.note(_('saving current version of %s as %s\n') %
4407 (rel, bakname))
4423 (rel, bakname))
4408 if not opts.get('dry_run'):
4424 if not opts.get('dry_run'):
4409 util.rename(target, bakname)
4425 util.rename(target, bakname)
4410 if ui.verbose or not exact:
4426 if ui.verbose or not exact:
4411 msg = xlist[1]
4427 msg = xlist[1]
4412 if not isinstance(msg, basestring):
4428 if not isinstance(msg, basestring):
4413 msg = msg(abs)
4429 msg = msg(abs)
4414 ui.status(msg % rel)
4430 ui.status(msg % rel)
4415 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4431 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4416 if abs not in table:
4432 if abs not in table:
4417 continue
4433 continue
4418 # file has changed in dirstate
4434 # file has changed in dirstate
4419 if mfentry:
4435 if mfentry:
4420 handle(hitlist, backuphit)
4436 handle(hitlist, backuphit)
4421 elif misslist is not None:
4437 elif misslist is not None:
4422 handle(misslist, backupmiss)
4438 handle(misslist, backupmiss)
4423 break
4439 break
4424 else:
4440 else:
4425 if abs not in repo.dirstate:
4441 if abs not in repo.dirstate:
4426 if mfentry:
4442 if mfentry:
4427 handle(add, True)
4443 handle(add, True)
4428 elif exact:
4444 elif exact:
4429 ui.warn(_('file not managed: %s\n') % rel)
4445 ui.warn(_('file not managed: %s\n') % rel)
4430 continue
4446 continue
4431 # file has not changed in dirstate
4447 # file has not changed in dirstate
4432 if node == parent:
4448 if node == parent:
4433 if exact:
4449 if exact:
4434 ui.warn(_('no changes needed to %s\n') % rel)
4450 ui.warn(_('no changes needed to %s\n') % rel)
4435 continue
4451 continue
4436 if pmf is None:
4452 if pmf is None:
4437 # only need parent manifest in this unlikely case,
4453 # only need parent manifest in this unlikely case,
4438 # so do not read by default
4454 # so do not read by default
4439 pmf = repo[parent].manifest()
4455 pmf = repo[parent].manifest()
4440 if abs in pmf:
4456 if abs in pmf:
4441 if mfentry:
4457 if mfentry:
4442 # if version of file is same in parent and target
4458 # if version of file is same in parent and target
4443 # manifests, do nothing
4459 # manifests, do nothing
4444 if (pmf[abs] != mfentry or
4460 if (pmf[abs] != mfentry or
4445 pmf.flags(abs) != mf.flags(abs)):
4461 pmf.flags(abs) != mf.flags(abs)):
4446 handle(revert, False)
4462 handle(revert, False)
4447 else:
4463 else:
4448 handle(remove, False)
4464 handle(remove, False)
4449
4465
4450 if not opts.get('dry_run'):
4466 if not opts.get('dry_run'):
4451 def checkout(f):
4467 def checkout(f):
4452 fc = ctx[f]
4468 fc = ctx[f]
4453 repo.wwrite(f, fc.data(), fc.flags())
4469 repo.wwrite(f, fc.data(), fc.flags())
4454
4470
4455 audit_path = scmutil.pathauditor(repo.root)
4471 audit_path = scmutil.pathauditor(repo.root)
4456 for f in remove[0]:
4472 for f in remove[0]:
4457 if repo.dirstate[f] == 'a':
4473 if repo.dirstate[f] == 'a':
4458 repo.dirstate.drop(f)
4474 repo.dirstate.drop(f)
4459 continue
4475 continue
4460 audit_path(f)
4476 audit_path(f)
4461 try:
4477 try:
4462 util.unlinkpath(repo.wjoin(f))
4478 util.unlinkpath(repo.wjoin(f))
4463 except OSError:
4479 except OSError:
4464 pass
4480 pass
4465 repo.dirstate.remove(f)
4481 repo.dirstate.remove(f)
4466
4482
4467 normal = None
4483 normal = None
4468 if node == parent:
4484 if node == parent:
4469 # We're reverting to our parent. If possible, we'd like status
4485 # We're reverting to our parent. If possible, we'd like status
4470 # to report the file as clean. We have to use normallookup for
4486 # to report the file as clean. We have to use normallookup for
4471 # merges to avoid losing information about merged/dirty files.
4487 # merges to avoid losing information about merged/dirty files.
4472 if p2 != nullid:
4488 if p2 != nullid:
4473 normal = repo.dirstate.normallookup
4489 normal = repo.dirstate.normallookup
4474 else:
4490 else:
4475 normal = repo.dirstate.normal
4491 normal = repo.dirstate.normal
4476 for f in revert[0]:
4492 for f in revert[0]:
4477 checkout(f)
4493 checkout(f)
4478 if normal:
4494 if normal:
4479 normal(f)
4495 normal(f)
4480
4496
4481 for f in add[0]:
4497 for f in add[0]:
4482 checkout(f)
4498 checkout(f)
4483 repo.dirstate.add(f)
4499 repo.dirstate.add(f)
4484
4500
4485 normal = repo.dirstate.normallookup
4501 normal = repo.dirstate.normallookup
4486 if node == parent and p2 == nullid:
4502 if node == parent and p2 == nullid:
4487 normal = repo.dirstate.normal
4503 normal = repo.dirstate.normal
4488 for f in undelete[0]:
4504 for f in undelete[0]:
4489 checkout(f)
4505 checkout(f)
4490 normal(f)
4506 normal(f)
4491
4507
4492 finally:
4508 finally:
4493 wlock.release()
4509 wlock.release()
4494
4510
4495 @command('rollback', dryrunopts)
4511 @command('rollback', dryrunopts)
4496 def rollback(ui, repo, **opts):
4512 def rollback(ui, repo, **opts):
4497 """roll back the last transaction (dangerous)
4513 """roll back the last transaction (dangerous)
4498
4514
4499 This command should be used with care. There is only one level of
4515 This command should be used with care. There is only one level of
4500 rollback, and there is no way to undo a rollback. It will also
4516 rollback, and there is no way to undo a rollback. It will also
4501 restore the dirstate at the time of the last transaction, losing
4517 restore the dirstate at the time of the last transaction, losing
4502 any dirstate changes since that time. This command does not alter
4518 any dirstate changes since that time. This command does not alter
4503 the working directory.
4519 the working directory.
4504
4520
4505 Transactions are used to encapsulate the effects of all commands
4521 Transactions are used to encapsulate the effects of all commands
4506 that create new changesets or propagate existing changesets into a
4522 that create new changesets or propagate existing changesets into a
4507 repository. For example, the following commands are transactional,
4523 repository. For example, the following commands are transactional,
4508 and their effects can be rolled back:
4524 and their effects can be rolled back:
4509
4525
4510 - commit
4526 - commit
4511 - import
4527 - import
4512 - pull
4528 - pull
4513 - push (with this repository as the destination)
4529 - push (with this repository as the destination)
4514 - unbundle
4530 - unbundle
4515
4531
4516 This command is not intended for use on public repositories. Once
4532 This command is not intended for use on public repositories. Once
4517 changes are visible for pull by other users, rolling a transaction
4533 changes are visible for pull by other users, rolling a transaction
4518 back locally is ineffective (someone else may already have pulled
4534 back locally is ineffective (someone else may already have pulled
4519 the changes). Furthermore, a race is possible with readers of the
4535 the changes). Furthermore, a race is possible with readers of the
4520 repository; for example an in-progress pull from the repository
4536 repository; for example an in-progress pull from the repository
4521 may fail if a rollback is performed.
4537 may fail if a rollback is performed.
4522
4538
4523 Returns 0 on success, 1 if no rollback data is available.
4539 Returns 0 on success, 1 if no rollback data is available.
4524 """
4540 """
4525 return repo.rollback(opts.get('dry_run'))
4541 return repo.rollback(opts.get('dry_run'))
4526
4542
4527 @command('root', [])
4543 @command('root', [])
4528 def root(ui, repo):
4544 def root(ui, repo):
4529 """print the root (top) of the current working directory
4545 """print the root (top) of the current working directory
4530
4546
4531 Print the root directory of the current repository.
4547 Print the root directory of the current repository.
4532
4548
4533 Returns 0 on success.
4549 Returns 0 on success.
4534 """
4550 """
4535 ui.write(repo.root + "\n")
4551 ui.write(repo.root + "\n")
4536
4552
4537 @command('^serve',
4553 @command('^serve',
4538 [('A', 'accesslog', '', _('name of access log file to write to'),
4554 [('A', 'accesslog', '', _('name of access log file to write to'),
4539 _('FILE')),
4555 _('FILE')),
4540 ('d', 'daemon', None, _('run server in background')),
4556 ('d', 'daemon', None, _('run server in background')),
4541 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4557 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4542 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4558 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4543 # use string type, then we can check if something was passed
4559 # use string type, then we can check if something was passed
4544 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4560 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4545 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4561 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4546 _('ADDR')),
4562 _('ADDR')),
4547 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4563 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4548 _('PREFIX')),
4564 _('PREFIX')),
4549 ('n', 'name', '',
4565 ('n', 'name', '',
4550 _('name to show in web pages (default: working directory)'), _('NAME')),
4566 _('name to show in web pages (default: working directory)'), _('NAME')),
4551 ('', 'web-conf', '',
4567 ('', 'web-conf', '',
4552 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4568 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4553 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4569 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4554 _('FILE')),
4570 _('FILE')),
4555 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4571 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4556 ('', 'stdio', None, _('for remote clients')),
4572 ('', 'stdio', None, _('for remote clients')),
4557 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4573 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4558 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4574 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4559 ('', 'style', '', _('template style to use'), _('STYLE')),
4575 ('', 'style', '', _('template style to use'), _('STYLE')),
4560 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4576 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4561 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4577 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4562 _('[OPTION]...'))
4578 _('[OPTION]...'))
4563 def serve(ui, repo, **opts):
4579 def serve(ui, repo, **opts):
4564 """start stand-alone webserver
4580 """start stand-alone webserver
4565
4581
4566 Start a local HTTP repository browser and pull server. You can use
4582 Start a local HTTP repository browser and pull server. You can use
4567 this for ad-hoc sharing and browsing of repositories. It is
4583 this for ad-hoc sharing and browsing of repositories. It is
4568 recommended to use a real web server to serve a repository for
4584 recommended to use a real web server to serve a repository for
4569 longer periods of time.
4585 longer periods of time.
4570
4586
4571 Please note that the server does not implement access control.
4587 Please note that the server does not implement access control.
4572 This means that, by default, anybody can read from the server and
4588 This means that, by default, anybody can read from the server and
4573 nobody can write to it by default. Set the ``web.allow_push``
4589 nobody can write to it by default. Set the ``web.allow_push``
4574 option to ``*`` to allow everybody to push to the server. You
4590 option to ``*`` to allow everybody to push to the server. You
4575 should use a real web server if you need to authenticate users.
4591 should use a real web server if you need to authenticate users.
4576
4592
4577 By default, the server logs accesses to stdout and errors to
4593 By default, the server logs accesses to stdout and errors to
4578 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4594 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4579 files.
4595 files.
4580
4596
4581 To have the server choose a free port number to listen on, specify
4597 To have the server choose a free port number to listen on, specify
4582 a port number of 0; in this case, the server will print the port
4598 a port number of 0; in this case, the server will print the port
4583 number it uses.
4599 number it uses.
4584
4600
4585 Returns 0 on success.
4601 Returns 0 on success.
4586 """
4602 """
4587
4603
4588 if opts["stdio"] and opts["cmdserver"]:
4604 if opts["stdio"] and opts["cmdserver"]:
4589 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4605 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4590
4606
4591 def checkrepo():
4607 def checkrepo():
4592 if repo is None:
4608 if repo is None:
4593 raise error.RepoError(_("There is no Mercurial repository here"
4609 raise error.RepoError(_("There is no Mercurial repository here"
4594 " (.hg not found)"))
4610 " (.hg not found)"))
4595
4611
4596 if opts["stdio"]:
4612 if opts["stdio"]:
4597 checkrepo()
4613 checkrepo()
4598 s = sshserver.sshserver(ui, repo)
4614 s = sshserver.sshserver(ui, repo)
4599 s.serve_forever()
4615 s.serve_forever()
4600
4616
4601 if opts["cmdserver"]:
4617 if opts["cmdserver"]:
4602 checkrepo()
4618 checkrepo()
4603 s = commandserver.server(ui, repo, opts["cmdserver"])
4619 s = commandserver.server(ui, repo, opts["cmdserver"])
4604 return s.serve()
4620 return s.serve()
4605
4621
4606 # this way we can check if something was given in the command-line
4622 # this way we can check if something was given in the command-line
4607 if opts.get('port'):
4623 if opts.get('port'):
4608 opts['port'] = util.getport(opts.get('port'))
4624 opts['port'] = util.getport(opts.get('port'))
4609
4625
4610 baseui = repo and repo.baseui or ui
4626 baseui = repo and repo.baseui or ui
4611 optlist = ("name templates style address port prefix ipv6"
4627 optlist = ("name templates style address port prefix ipv6"
4612 " accesslog errorlog certificate encoding")
4628 " accesslog errorlog certificate encoding")
4613 for o in optlist.split():
4629 for o in optlist.split():
4614 val = opts.get(o, '')
4630 val = opts.get(o, '')
4615 if val in (None, ''): # should check against default options instead
4631 if val in (None, ''): # should check against default options instead
4616 continue
4632 continue
4617 baseui.setconfig("web", o, val)
4633 baseui.setconfig("web", o, val)
4618 if repo and repo.ui != baseui:
4634 if repo and repo.ui != baseui:
4619 repo.ui.setconfig("web", o, val)
4635 repo.ui.setconfig("web", o, val)
4620
4636
4621 o = opts.get('web_conf') or opts.get('webdir_conf')
4637 o = opts.get('web_conf') or opts.get('webdir_conf')
4622 if not o:
4638 if not o:
4623 if not repo:
4639 if not repo:
4624 raise error.RepoError(_("There is no Mercurial repository"
4640 raise error.RepoError(_("There is no Mercurial repository"
4625 " here (.hg not found)"))
4641 " here (.hg not found)"))
4626 o = repo.root
4642 o = repo.root
4627
4643
4628 app = hgweb.hgweb(o, baseui=ui)
4644 app = hgweb.hgweb(o, baseui=ui)
4629
4645
4630 class service(object):
4646 class service(object):
4631 def init(self):
4647 def init(self):
4632 util.setsignalhandler()
4648 util.setsignalhandler()
4633 self.httpd = hgweb.server.create_server(ui, app)
4649 self.httpd = hgweb.server.create_server(ui, app)
4634
4650
4635 if opts['port'] and not ui.verbose:
4651 if opts['port'] and not ui.verbose:
4636 return
4652 return
4637
4653
4638 if self.httpd.prefix:
4654 if self.httpd.prefix:
4639 prefix = self.httpd.prefix.strip('/') + '/'
4655 prefix = self.httpd.prefix.strip('/') + '/'
4640 else:
4656 else:
4641 prefix = ''
4657 prefix = ''
4642
4658
4643 port = ':%d' % self.httpd.port
4659 port = ':%d' % self.httpd.port
4644 if port == ':80':
4660 if port == ':80':
4645 port = ''
4661 port = ''
4646
4662
4647 bindaddr = self.httpd.addr
4663 bindaddr = self.httpd.addr
4648 if bindaddr == '0.0.0.0':
4664 if bindaddr == '0.0.0.0':
4649 bindaddr = '*'
4665 bindaddr = '*'
4650 elif ':' in bindaddr: # IPv6
4666 elif ':' in bindaddr: # IPv6
4651 bindaddr = '[%s]' % bindaddr
4667 bindaddr = '[%s]' % bindaddr
4652
4668
4653 fqaddr = self.httpd.fqaddr
4669 fqaddr = self.httpd.fqaddr
4654 if ':' in fqaddr:
4670 if ':' in fqaddr:
4655 fqaddr = '[%s]' % fqaddr
4671 fqaddr = '[%s]' % fqaddr
4656 if opts['port']:
4672 if opts['port']:
4657 write = ui.status
4673 write = ui.status
4658 else:
4674 else:
4659 write = ui.write
4675 write = ui.write
4660 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4676 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4661 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4677 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4662
4678
4663 def run(self):
4679 def run(self):
4664 self.httpd.serve_forever()
4680 self.httpd.serve_forever()
4665
4681
4666 service = service()
4682 service = service()
4667
4683
4668 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4684 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4669
4685
4670 @command('showconfig|debugconfig',
4686 @command('showconfig|debugconfig',
4671 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4687 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4672 _('[-u] [NAME]...'))
4688 _('[-u] [NAME]...'))
4673 def showconfig(ui, repo, *values, **opts):
4689 def showconfig(ui, repo, *values, **opts):
4674 """show combined config settings from all hgrc files
4690 """show combined config settings from all hgrc files
4675
4691
4676 With no arguments, print names and values of all config items.
4692 With no arguments, print names and values of all config items.
4677
4693
4678 With one argument of the form section.name, print just the value
4694 With one argument of the form section.name, print just the value
4679 of that config item.
4695 of that config item.
4680
4696
4681 With multiple arguments, print names and values of all config
4697 With multiple arguments, print names and values of all config
4682 items with matching section names.
4698 items with matching section names.
4683
4699
4684 With --debug, the source (filename and line number) is printed
4700 With --debug, the source (filename and line number) is printed
4685 for each config item.
4701 for each config item.
4686
4702
4687 Returns 0 on success.
4703 Returns 0 on success.
4688 """
4704 """
4689
4705
4690 for f in scmutil.rcpath():
4706 for f in scmutil.rcpath():
4691 ui.debug('read config from: %s\n' % f)
4707 ui.debug('read config from: %s\n' % f)
4692 untrusted = bool(opts.get('untrusted'))
4708 untrusted = bool(opts.get('untrusted'))
4693 if values:
4709 if values:
4694 sections = [v for v in values if '.' not in v]
4710 sections = [v for v in values if '.' not in v]
4695 items = [v for v in values if '.' in v]
4711 items = [v for v in values if '.' in v]
4696 if len(items) > 1 or items and sections:
4712 if len(items) > 1 or items and sections:
4697 raise util.Abort(_('only one config item permitted'))
4713 raise util.Abort(_('only one config item permitted'))
4698 for section, name, value in ui.walkconfig(untrusted=untrusted):
4714 for section, name, value in ui.walkconfig(untrusted=untrusted):
4699 value = str(value).replace('\n', '\\n')
4715 value = str(value).replace('\n', '\\n')
4700 sectname = section + '.' + name
4716 sectname = section + '.' + name
4701 if values:
4717 if values:
4702 for v in values:
4718 for v in values:
4703 if v == section:
4719 if v == section:
4704 ui.debug('%s: ' %
4720 ui.debug('%s: ' %
4705 ui.configsource(section, name, untrusted))
4721 ui.configsource(section, name, untrusted))
4706 ui.write('%s=%s\n' % (sectname, value))
4722 ui.write('%s=%s\n' % (sectname, value))
4707 elif v == sectname:
4723 elif v == sectname:
4708 ui.debug('%s: ' %
4724 ui.debug('%s: ' %
4709 ui.configsource(section, name, untrusted))
4725 ui.configsource(section, name, untrusted))
4710 ui.write(value, '\n')
4726 ui.write(value, '\n')
4711 else:
4727 else:
4712 ui.debug('%s: ' %
4728 ui.debug('%s: ' %
4713 ui.configsource(section, name, untrusted))
4729 ui.configsource(section, name, untrusted))
4714 ui.write('%s=%s\n' % (sectname, value))
4730 ui.write('%s=%s\n' % (sectname, value))
4715
4731
4716 @command('^status|st',
4732 @command('^status|st',
4717 [('A', 'all', None, _('show status of all files')),
4733 [('A', 'all', None, _('show status of all files')),
4718 ('m', 'modified', None, _('show only modified files')),
4734 ('m', 'modified', None, _('show only modified files')),
4719 ('a', 'added', None, _('show only added files')),
4735 ('a', 'added', None, _('show only added files')),
4720 ('r', 'removed', None, _('show only removed files')),
4736 ('r', 'removed', None, _('show only removed files')),
4721 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4737 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4722 ('c', 'clean', None, _('show only files without changes')),
4738 ('c', 'clean', None, _('show only files without changes')),
4723 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4739 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4724 ('i', 'ignored', None, _('show only ignored files')),
4740 ('i', 'ignored', None, _('show only ignored files')),
4725 ('n', 'no-status', None, _('hide status prefix')),
4741 ('n', 'no-status', None, _('hide status prefix')),
4726 ('C', 'copies', None, _('show source of copied files')),
4742 ('C', 'copies', None, _('show source of copied files')),
4727 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4743 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4728 ('', 'rev', [], _('show difference from revision'), _('REV')),
4744 ('', 'rev', [], _('show difference from revision'), _('REV')),
4729 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4745 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4730 ] + walkopts + subrepoopts,
4746 ] + walkopts + subrepoopts,
4731 _('[OPTION]... [FILE]...'))
4747 _('[OPTION]... [FILE]...'))
4732 def status(ui, repo, *pats, **opts):
4748 def status(ui, repo, *pats, **opts):
4733 """show changed files in the working directory
4749 """show changed files in the working directory
4734
4750
4735 Show status of files in the repository. If names are given, only
4751 Show status of files in the repository. If names are given, only
4736 files that match are shown. Files that are clean or ignored or
4752 files that match are shown. Files that are clean or ignored or
4737 the source of a copy/move operation, are not listed unless
4753 the source of a copy/move operation, are not listed unless
4738 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4754 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4739 Unless options described with "show only ..." are given, the
4755 Unless options described with "show only ..." are given, the
4740 options -mardu are used.
4756 options -mardu are used.
4741
4757
4742 Option -q/--quiet hides untracked (unknown and ignored) files
4758 Option -q/--quiet hides untracked (unknown and ignored) files
4743 unless explicitly requested with -u/--unknown or -i/--ignored.
4759 unless explicitly requested with -u/--unknown or -i/--ignored.
4744
4760
4745 .. note::
4761 .. note::
4746 status may appear to disagree with diff if permissions have
4762 status may appear to disagree with diff if permissions have
4747 changed or a merge has occurred. The standard diff format does
4763 changed or a merge has occurred. The standard diff format does
4748 not report permission changes and diff only reports changes
4764 not report permission changes and diff only reports changes
4749 relative to one merge parent.
4765 relative to one merge parent.
4750
4766
4751 If one revision is given, it is used as the base revision.
4767 If one revision is given, it is used as the base revision.
4752 If two revisions are given, the differences between them are
4768 If two revisions are given, the differences between them are
4753 shown. The --change option can also be used as a shortcut to list
4769 shown. The --change option can also be used as a shortcut to list
4754 the changed files of a revision from its first parent.
4770 the changed files of a revision from its first parent.
4755
4771
4756 The codes used to show the status of files are::
4772 The codes used to show the status of files are::
4757
4773
4758 M = modified
4774 M = modified
4759 A = added
4775 A = added
4760 R = removed
4776 R = removed
4761 C = clean
4777 C = clean
4762 ! = missing (deleted by non-hg command, but still tracked)
4778 ! = missing (deleted by non-hg command, but still tracked)
4763 ? = not tracked
4779 ? = not tracked
4764 I = ignored
4780 I = ignored
4765 = origin of the previous file listed as A (added)
4781 = origin of the previous file listed as A (added)
4766
4782
4767 Returns 0 on success.
4783 Returns 0 on success.
4768 """
4784 """
4769
4785
4770 revs = opts.get('rev')
4786 revs = opts.get('rev')
4771 change = opts.get('change')
4787 change = opts.get('change')
4772
4788
4773 if revs and change:
4789 if revs and change:
4774 msg = _('cannot specify --rev and --change at the same time')
4790 msg = _('cannot specify --rev and --change at the same time')
4775 raise util.Abort(msg)
4791 raise util.Abort(msg)
4776 elif change:
4792 elif change:
4777 node2 = repo.lookup(change)
4793 node2 = repo.lookup(change)
4778 node1 = repo[node2].p1().node()
4794 node1 = repo[node2].p1().node()
4779 else:
4795 else:
4780 node1, node2 = scmutil.revpair(repo, revs)
4796 node1, node2 = scmutil.revpair(repo, revs)
4781
4797
4782 cwd = (pats and repo.getcwd()) or ''
4798 cwd = (pats and repo.getcwd()) or ''
4783 end = opts.get('print0') and '\0' or '\n'
4799 end = opts.get('print0') and '\0' or '\n'
4784 copy = {}
4800 copy = {}
4785 states = 'modified added removed deleted unknown ignored clean'.split()
4801 states = 'modified added removed deleted unknown ignored clean'.split()
4786 show = [k for k in states if opts.get(k)]
4802 show = [k for k in states if opts.get(k)]
4787 if opts.get('all'):
4803 if opts.get('all'):
4788 show += ui.quiet and (states[:4] + ['clean']) or states
4804 show += ui.quiet and (states[:4] + ['clean']) or states
4789 if not show:
4805 if not show:
4790 show = ui.quiet and states[:4] or states[:5]
4806 show = ui.quiet and states[:4] or states[:5]
4791
4807
4792 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4808 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4793 'ignored' in show, 'clean' in show, 'unknown' in show,
4809 'ignored' in show, 'clean' in show, 'unknown' in show,
4794 opts.get('subrepos'))
4810 opts.get('subrepos'))
4795 changestates = zip(states, 'MAR!?IC', stat)
4811 changestates = zip(states, 'MAR!?IC', stat)
4796
4812
4797 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4813 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4798 ctxn = repo[nullid]
4814 ctxn = repo[nullid]
4799 ctx1 = repo[node1]
4815 ctx1 = repo[node1]
4800 ctx2 = repo[node2]
4816 ctx2 = repo[node2]
4801 added = stat[1]
4817 added = stat[1]
4802 if node2 is None:
4818 if node2 is None:
4803 added = stat[0] + stat[1] # merged?
4819 added = stat[0] + stat[1] # merged?
4804
4820
4805 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4821 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4806 if k in added:
4822 if k in added:
4807 copy[k] = v
4823 copy[k] = v
4808 elif v in added:
4824 elif v in added:
4809 copy[v] = k
4825 copy[v] = k
4810
4826
4811 for state, char, files in changestates:
4827 for state, char, files in changestates:
4812 if state in show:
4828 if state in show:
4813 format = "%s %%s%s" % (char, end)
4829 format = "%s %%s%s" % (char, end)
4814 if opts.get('no_status'):
4830 if opts.get('no_status'):
4815 format = "%%s%s" % end
4831 format = "%%s%s" % end
4816
4832
4817 for f in files:
4833 for f in files:
4818 ui.write(format % repo.pathto(f, cwd),
4834 ui.write(format % repo.pathto(f, cwd),
4819 label='status.' + state)
4835 label='status.' + state)
4820 if f in copy:
4836 if f in copy:
4821 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4837 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4822 label='status.copied')
4838 label='status.copied')
4823
4839
4824 @command('^summary|sum',
4840 @command('^summary|sum',
4825 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4841 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4826 def summary(ui, repo, **opts):
4842 def summary(ui, repo, **opts):
4827 """summarize working directory state
4843 """summarize working directory state
4828
4844
4829 This generates a brief summary of the working directory state,
4845 This generates a brief summary of the working directory state,
4830 including parents, branch, commit status, and available updates.
4846 including parents, branch, commit status, and available updates.
4831
4847
4832 With the --remote option, this will check the default paths for
4848 With the --remote option, this will check the default paths for
4833 incoming and outgoing changes. This can be time-consuming.
4849 incoming and outgoing changes. This can be time-consuming.
4834
4850
4835 Returns 0 on success.
4851 Returns 0 on success.
4836 """
4852 """
4837
4853
4838 ctx = repo[None]
4854 ctx = repo[None]
4839 parents = ctx.parents()
4855 parents = ctx.parents()
4840 pnode = parents[0].node()
4856 pnode = parents[0].node()
4841 marks = []
4857 marks = []
4842
4858
4843 for p in parents:
4859 for p in parents:
4844 # label with log.changeset (instead of log.parent) since this
4860 # label with log.changeset (instead of log.parent) since this
4845 # shows a working directory parent *changeset*:
4861 # shows a working directory parent *changeset*:
4846 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4862 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4847 label='log.changeset')
4863 label='log.changeset')
4848 ui.write(' '.join(p.tags()), label='log.tag')
4864 ui.write(' '.join(p.tags()), label='log.tag')
4849 if p.bookmarks():
4865 if p.bookmarks():
4850 marks.extend(p.bookmarks())
4866 marks.extend(p.bookmarks())
4851 if p.rev() == -1:
4867 if p.rev() == -1:
4852 if not len(repo):
4868 if not len(repo):
4853 ui.write(_(' (empty repository)'))
4869 ui.write(_(' (empty repository)'))
4854 else:
4870 else:
4855 ui.write(_(' (no revision checked out)'))
4871 ui.write(_(' (no revision checked out)'))
4856 ui.write('\n')
4872 ui.write('\n')
4857 if p.description():
4873 if p.description():
4858 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4874 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4859 label='log.summary')
4875 label='log.summary')
4860
4876
4861 branch = ctx.branch()
4877 branch = ctx.branch()
4862 bheads = repo.branchheads(branch)
4878 bheads = repo.branchheads(branch)
4863 m = _('branch: %s\n') % branch
4879 m = _('branch: %s\n') % branch
4864 if branch != 'default':
4880 if branch != 'default':
4865 ui.write(m, label='log.branch')
4881 ui.write(m, label='log.branch')
4866 else:
4882 else:
4867 ui.status(m, label='log.branch')
4883 ui.status(m, label='log.branch')
4868
4884
4869 if marks:
4885 if marks:
4870 current = repo._bookmarkcurrent
4886 current = repo._bookmarkcurrent
4871 ui.write(_('bookmarks:'), label='log.bookmark')
4887 ui.write(_('bookmarks:'), label='log.bookmark')
4872 if current is not None:
4888 if current is not None:
4873 try:
4889 try:
4874 marks.remove(current)
4890 marks.remove(current)
4875 ui.write(' *' + current, label='bookmarks.current')
4891 ui.write(' *' + current, label='bookmarks.current')
4876 except ValueError:
4892 except ValueError:
4877 # current bookmark not in parent ctx marks
4893 # current bookmark not in parent ctx marks
4878 pass
4894 pass
4879 for m in marks:
4895 for m in marks:
4880 ui.write(' ' + m, label='log.bookmark')
4896 ui.write(' ' + m, label='log.bookmark')
4881 ui.write('\n', label='log.bookmark')
4897 ui.write('\n', label='log.bookmark')
4882
4898
4883 st = list(repo.status(unknown=True))[:6]
4899 st = list(repo.status(unknown=True))[:6]
4884
4900
4885 c = repo.dirstate.copies()
4901 c = repo.dirstate.copies()
4886 copied, renamed = [], []
4902 copied, renamed = [], []
4887 for d, s in c.iteritems():
4903 for d, s in c.iteritems():
4888 if s in st[2]:
4904 if s in st[2]:
4889 st[2].remove(s)
4905 st[2].remove(s)
4890 renamed.append(d)
4906 renamed.append(d)
4891 else:
4907 else:
4892 copied.append(d)
4908 copied.append(d)
4893 if d in st[1]:
4909 if d in st[1]:
4894 st[1].remove(d)
4910 st[1].remove(d)
4895 st.insert(3, renamed)
4911 st.insert(3, renamed)
4896 st.insert(4, copied)
4912 st.insert(4, copied)
4897
4913
4898 ms = mergemod.mergestate(repo)
4914 ms = mergemod.mergestate(repo)
4899 st.append([f for f in ms if ms[f] == 'u'])
4915 st.append([f for f in ms if ms[f] == 'u'])
4900
4916
4901 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4917 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4902 st.append(subs)
4918 st.append(subs)
4903
4919
4904 labels = [ui.label(_('%d modified'), 'status.modified'),
4920 labels = [ui.label(_('%d modified'), 'status.modified'),
4905 ui.label(_('%d added'), 'status.added'),
4921 ui.label(_('%d added'), 'status.added'),
4906 ui.label(_('%d removed'), 'status.removed'),
4922 ui.label(_('%d removed'), 'status.removed'),
4907 ui.label(_('%d renamed'), 'status.copied'),
4923 ui.label(_('%d renamed'), 'status.copied'),
4908 ui.label(_('%d copied'), 'status.copied'),
4924 ui.label(_('%d copied'), 'status.copied'),
4909 ui.label(_('%d deleted'), 'status.deleted'),
4925 ui.label(_('%d deleted'), 'status.deleted'),
4910 ui.label(_('%d unknown'), 'status.unknown'),
4926 ui.label(_('%d unknown'), 'status.unknown'),
4911 ui.label(_('%d ignored'), 'status.ignored'),
4927 ui.label(_('%d ignored'), 'status.ignored'),
4912 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4928 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4913 ui.label(_('%d subrepos'), 'status.modified')]
4929 ui.label(_('%d subrepos'), 'status.modified')]
4914 t = []
4930 t = []
4915 for s, l in zip(st, labels):
4931 for s, l in zip(st, labels):
4916 if s:
4932 if s:
4917 t.append(l % len(s))
4933 t.append(l % len(s))
4918
4934
4919 t = ', '.join(t)
4935 t = ', '.join(t)
4920 cleanworkdir = False
4936 cleanworkdir = False
4921
4937
4922 if len(parents) > 1:
4938 if len(parents) > 1:
4923 t += _(' (merge)')
4939 t += _(' (merge)')
4924 elif branch != parents[0].branch():
4940 elif branch != parents[0].branch():
4925 t += _(' (new branch)')
4941 t += _(' (new branch)')
4926 elif (parents[0].extra().get('close') and
4942 elif (parents[0].extra().get('close') and
4927 pnode in repo.branchheads(branch, closed=True)):
4943 pnode in repo.branchheads(branch, closed=True)):
4928 t += _(' (head closed)')
4944 t += _(' (head closed)')
4929 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4945 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4930 t += _(' (clean)')
4946 t += _(' (clean)')
4931 cleanworkdir = True
4947 cleanworkdir = True
4932 elif pnode not in bheads:
4948 elif pnode not in bheads:
4933 t += _(' (new branch head)')
4949 t += _(' (new branch head)')
4934
4950
4935 if cleanworkdir:
4951 if cleanworkdir:
4936 ui.status(_('commit: %s\n') % t.strip())
4952 ui.status(_('commit: %s\n') % t.strip())
4937 else:
4953 else:
4938 ui.write(_('commit: %s\n') % t.strip())
4954 ui.write(_('commit: %s\n') % t.strip())
4939
4955
4940 # all ancestors of branch heads - all ancestors of parent = new csets
4956 # all ancestors of branch heads - all ancestors of parent = new csets
4941 new = [0] * len(repo)
4957 new = [0] * len(repo)
4942 cl = repo.changelog
4958 cl = repo.changelog
4943 for a in [cl.rev(n) for n in bheads]:
4959 for a in [cl.rev(n) for n in bheads]:
4944 new[a] = 1
4960 new[a] = 1
4945 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
4961 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
4946 new[a] = 1
4962 new[a] = 1
4947 for a in [p.rev() for p in parents]:
4963 for a in [p.rev() for p in parents]:
4948 if a >= 0:
4964 if a >= 0:
4949 new[a] = 0
4965 new[a] = 0
4950 for a in cl.ancestors(*[p.rev() for p in parents]):
4966 for a in cl.ancestors(*[p.rev() for p in parents]):
4951 new[a] = 0
4967 new[a] = 0
4952 new = sum(new)
4968 new = sum(new)
4953
4969
4954 if new == 0:
4970 if new == 0:
4955 ui.status(_('update: (current)\n'))
4971 ui.status(_('update: (current)\n'))
4956 elif pnode not in bheads:
4972 elif pnode not in bheads:
4957 ui.write(_('update: %d new changesets (update)\n') % new)
4973 ui.write(_('update: %d new changesets (update)\n') % new)
4958 else:
4974 else:
4959 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4975 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4960 (new, len(bheads)))
4976 (new, len(bheads)))
4961
4977
4962 if opts.get('remote'):
4978 if opts.get('remote'):
4963 t = []
4979 t = []
4964 source, branches = hg.parseurl(ui.expandpath('default'))
4980 source, branches = hg.parseurl(ui.expandpath('default'))
4965 other = hg.peer(repo, {}, source)
4981 other = hg.peer(repo, {}, source)
4966 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4982 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4967 ui.debug('comparing with %s\n' % util.hidepassword(source))
4983 ui.debug('comparing with %s\n' % util.hidepassword(source))
4968 repo.ui.pushbuffer()
4984 repo.ui.pushbuffer()
4969 commoninc = discovery.findcommonincoming(repo, other)
4985 commoninc = discovery.findcommonincoming(repo, other)
4970 _common, incoming, _rheads = commoninc
4986 _common, incoming, _rheads = commoninc
4971 repo.ui.popbuffer()
4987 repo.ui.popbuffer()
4972 if incoming:
4988 if incoming:
4973 t.append(_('1 or more incoming'))
4989 t.append(_('1 or more incoming'))
4974
4990
4975 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
4991 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
4976 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
4992 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
4977 if source != dest:
4993 if source != dest:
4978 other = hg.peer(repo, {}, dest)
4994 other = hg.peer(repo, {}, dest)
4979 commoninc = None
4995 commoninc = None
4980 ui.debug('comparing with %s\n' % util.hidepassword(dest))
4996 ui.debug('comparing with %s\n' % util.hidepassword(dest))
4981 repo.ui.pushbuffer()
4997 repo.ui.pushbuffer()
4982 common, outheads = discovery.findcommonoutgoing(repo, other,
4998 common, outheads = discovery.findcommonoutgoing(repo, other,
4983 commoninc=commoninc)
4999 commoninc=commoninc)
4984 repo.ui.popbuffer()
5000 repo.ui.popbuffer()
4985 o = repo.changelog.findmissing(common=common, heads=outheads)
5001 o = repo.changelog.findmissing(common=common, heads=outheads)
4986 if o:
5002 if o:
4987 t.append(_('%d outgoing') % len(o))
5003 t.append(_('%d outgoing') % len(o))
4988 if 'bookmarks' in other.listkeys('namespaces'):
5004 if 'bookmarks' in other.listkeys('namespaces'):
4989 lmarks = repo.listkeys('bookmarks')
5005 lmarks = repo.listkeys('bookmarks')
4990 rmarks = other.listkeys('bookmarks')
5006 rmarks = other.listkeys('bookmarks')
4991 diff = set(rmarks) - set(lmarks)
5007 diff = set(rmarks) - set(lmarks)
4992 if len(diff) > 0:
5008 if len(diff) > 0:
4993 t.append(_('%d incoming bookmarks') % len(diff))
5009 t.append(_('%d incoming bookmarks') % len(diff))
4994 diff = set(lmarks) - set(rmarks)
5010 diff = set(lmarks) - set(rmarks)
4995 if len(diff) > 0:
5011 if len(diff) > 0:
4996 t.append(_('%d outgoing bookmarks') % len(diff))
5012 t.append(_('%d outgoing bookmarks') % len(diff))
4997
5013
4998 if t:
5014 if t:
4999 ui.write(_('remote: %s\n') % (', '.join(t)))
5015 ui.write(_('remote: %s\n') % (', '.join(t)))
5000 else:
5016 else:
5001 ui.status(_('remote: (synced)\n'))
5017 ui.status(_('remote: (synced)\n'))
5002
5018
5003 @command('tag',
5019 @command('tag',
5004 [('f', 'force', None, _('force tag')),
5020 [('f', 'force', None, _('force tag')),
5005 ('l', 'local', None, _('make the tag local')),
5021 ('l', 'local', None, _('make the tag local')),
5006 ('r', 'rev', '', _('revision to tag'), _('REV')),
5022 ('r', 'rev', '', _('revision to tag'), _('REV')),
5007 ('', 'remove', None, _('remove a tag')),
5023 ('', 'remove', None, _('remove a tag')),
5008 # -l/--local is already there, commitopts cannot be used
5024 # -l/--local is already there, commitopts cannot be used
5009 ('e', 'edit', None, _('edit commit message')),
5025 ('e', 'edit', None, _('edit commit message')),
5010 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5026 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5011 ] + commitopts2,
5027 ] + commitopts2,
5012 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5028 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5013 def tag(ui, repo, name1, *names, **opts):
5029 def tag(ui, repo, name1, *names, **opts):
5014 """add one or more tags for the current or given revision
5030 """add one or more tags for the current or given revision
5015
5031
5016 Name a particular revision using <name>.
5032 Name a particular revision using <name>.
5017
5033
5018 Tags are used to name particular revisions of the repository and are
5034 Tags are used to name particular revisions of the repository and are
5019 very useful to compare different revisions, to go back to significant
5035 very useful to compare different revisions, to go back to significant
5020 earlier versions or to mark branch points as releases, etc. Changing
5036 earlier versions or to mark branch points as releases, etc. Changing
5021 an existing tag is normally disallowed; use -f/--force to override.
5037 an existing tag is normally disallowed; use -f/--force to override.
5022
5038
5023 If no revision is given, the parent of the working directory is
5039 If no revision is given, the parent of the working directory is
5024 used, or tip if no revision is checked out.
5040 used, or tip if no revision is checked out.
5025
5041
5026 To facilitate version control, distribution, and merging of tags,
5042 To facilitate version control, distribution, and merging of tags,
5027 they are stored as a file named ".hgtags" which is managed similarly
5043 they are stored as a file named ".hgtags" which is managed similarly
5028 to other project files and can be hand-edited if necessary. This
5044 to other project files and can be hand-edited if necessary. This
5029 also means that tagging creates a new commit. The file
5045 also means that tagging creates a new commit. The file
5030 ".hg/localtags" is used for local tags (not shared among
5046 ".hg/localtags" is used for local tags (not shared among
5031 repositories).
5047 repositories).
5032
5048
5033 Tag commits are usually made at the head of a branch. If the parent
5049 Tag commits are usually made at the head of a branch. If the parent
5034 of the working directory is not a branch head, :hg:`tag` aborts; use
5050 of the working directory is not a branch head, :hg:`tag` aborts; use
5035 -f/--force to force the tag commit to be based on a non-head
5051 -f/--force to force the tag commit to be based on a non-head
5036 changeset.
5052 changeset.
5037
5053
5038 See :hg:`help dates` for a list of formats valid for -d/--date.
5054 See :hg:`help dates` for a list of formats valid for -d/--date.
5039
5055
5040 Since tag names have priority over branch names during revision
5056 Since tag names have priority over branch names during revision
5041 lookup, using an existing branch name as a tag name is discouraged.
5057 lookup, using an existing branch name as a tag name is discouraged.
5042
5058
5043 Returns 0 on success.
5059 Returns 0 on success.
5044 """
5060 """
5045
5061
5046 rev_ = "."
5062 rev_ = "."
5047 names = [t.strip() for t in (name1,) + names]
5063 names = [t.strip() for t in (name1,) + names]
5048 if len(names) != len(set(names)):
5064 if len(names) != len(set(names)):
5049 raise util.Abort(_('tag names must be unique'))
5065 raise util.Abort(_('tag names must be unique'))
5050 for n in names:
5066 for n in names:
5051 if n in ['tip', '.', 'null']:
5067 if n in ['tip', '.', 'null']:
5052 raise util.Abort(_("the name '%s' is reserved") % n)
5068 raise util.Abort(_("the name '%s' is reserved") % n)
5053 if not n:
5069 if not n:
5054 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5070 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5055 if opts.get('rev') and opts.get('remove'):
5071 if opts.get('rev') and opts.get('remove'):
5056 raise util.Abort(_("--rev and --remove are incompatible"))
5072 raise util.Abort(_("--rev and --remove are incompatible"))
5057 if opts.get('rev'):
5073 if opts.get('rev'):
5058 rev_ = opts['rev']
5074 rev_ = opts['rev']
5059 message = opts.get('message')
5075 message = opts.get('message')
5060 if opts.get('remove'):
5076 if opts.get('remove'):
5061 expectedtype = opts.get('local') and 'local' or 'global'
5077 expectedtype = opts.get('local') and 'local' or 'global'
5062 for n in names:
5078 for n in names:
5063 if not repo.tagtype(n):
5079 if not repo.tagtype(n):
5064 raise util.Abort(_("tag '%s' does not exist") % n)
5080 raise util.Abort(_("tag '%s' does not exist") % n)
5065 if repo.tagtype(n) != expectedtype:
5081 if repo.tagtype(n) != expectedtype:
5066 if expectedtype == 'global':
5082 if expectedtype == 'global':
5067 raise util.Abort(_("tag '%s' is not a global tag") % n)
5083 raise util.Abort(_("tag '%s' is not a global tag") % n)
5068 else:
5084 else:
5069 raise util.Abort(_("tag '%s' is not a local tag") % n)
5085 raise util.Abort(_("tag '%s' is not a local tag") % n)
5070 rev_ = nullid
5086 rev_ = nullid
5071 if not message:
5087 if not message:
5072 # we don't translate commit messages
5088 # we don't translate commit messages
5073 message = 'Removed tag %s' % ', '.join(names)
5089 message = 'Removed tag %s' % ', '.join(names)
5074 elif not opts.get('force'):
5090 elif not opts.get('force'):
5075 for n in names:
5091 for n in names:
5076 if n in repo.tags():
5092 if n in repo.tags():
5077 raise util.Abort(_("tag '%s' already exists "
5093 raise util.Abort(_("tag '%s' already exists "
5078 "(use -f to force)") % n)
5094 "(use -f to force)") % n)
5079 if not opts.get('local'):
5095 if not opts.get('local'):
5080 p1, p2 = repo.dirstate.parents()
5096 p1, p2 = repo.dirstate.parents()
5081 if p2 != nullid:
5097 if p2 != nullid:
5082 raise util.Abort(_('uncommitted merge'))
5098 raise util.Abort(_('uncommitted merge'))
5083 bheads = repo.branchheads()
5099 bheads = repo.branchheads()
5084 if not opts.get('force') and bheads and p1 not in bheads:
5100 if not opts.get('force') and bheads and p1 not in bheads:
5085 raise util.Abort(_('not at a branch head (use -f to force)'))
5101 raise util.Abort(_('not at a branch head (use -f to force)'))
5086 r = scmutil.revsingle(repo, rev_).node()
5102 r = scmutil.revsingle(repo, rev_).node()
5087
5103
5088 if not message:
5104 if not message:
5089 # we don't translate commit messages
5105 # we don't translate commit messages
5090 message = ('Added tag %s for changeset %s' %
5106 message = ('Added tag %s for changeset %s' %
5091 (', '.join(names), short(r)))
5107 (', '.join(names), short(r)))
5092
5108
5093 date = opts.get('date')
5109 date = opts.get('date')
5094 if date:
5110 if date:
5095 date = util.parsedate(date)
5111 date = util.parsedate(date)
5096
5112
5097 if opts.get('edit'):
5113 if opts.get('edit'):
5098 message = ui.edit(message, ui.username())
5114 message = ui.edit(message, ui.username())
5099
5115
5100 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5116 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5101
5117
5102 @command('tags', [], '')
5118 @command('tags', [], '')
5103 def tags(ui, repo):
5119 def tags(ui, repo):
5104 """list repository tags
5120 """list repository tags
5105
5121
5106 This lists both regular and local tags. When the -v/--verbose
5122 This lists both regular and local tags. When the -v/--verbose
5107 switch is used, a third column "local" is printed for local tags.
5123 switch is used, a third column "local" is printed for local tags.
5108
5124
5109 Returns 0 on success.
5125 Returns 0 on success.
5110 """
5126 """
5111
5127
5112 hexfunc = ui.debugflag and hex or short
5128 hexfunc = ui.debugflag and hex or short
5113 tagtype = ""
5129 tagtype = ""
5114
5130
5115 for t, n in reversed(repo.tagslist()):
5131 for t, n in reversed(repo.tagslist()):
5116 if ui.quiet:
5132 if ui.quiet:
5117 ui.write("%s\n" % t, label='tags.normal')
5133 ui.write("%s\n" % t, label='tags.normal')
5118 continue
5134 continue
5119
5135
5120 hn = hexfunc(n)
5136 hn = hexfunc(n)
5121 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5137 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5122 rev = ui.label(r, 'log.changeset')
5138 rev = ui.label(r, 'log.changeset')
5123 spaces = " " * (30 - encoding.colwidth(t))
5139 spaces = " " * (30 - encoding.colwidth(t))
5124
5140
5125 tag = ui.label(t, 'tags.normal')
5141 tag = ui.label(t, 'tags.normal')
5126 if ui.verbose:
5142 if ui.verbose:
5127 if repo.tagtype(t) == 'local':
5143 if repo.tagtype(t) == 'local':
5128 tagtype = " local"
5144 tagtype = " local"
5129 tag = ui.label(t, 'tags.local')
5145 tag = ui.label(t, 'tags.local')
5130 else:
5146 else:
5131 tagtype = ""
5147 tagtype = ""
5132 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5148 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5133
5149
5134 @command('tip',
5150 @command('tip',
5135 [('p', 'patch', None, _('show patch')),
5151 [('p', 'patch', None, _('show patch')),
5136 ('g', 'git', None, _('use git extended diff format')),
5152 ('g', 'git', None, _('use git extended diff format')),
5137 ] + templateopts,
5153 ] + templateopts,
5138 _('[-p] [-g]'))
5154 _('[-p] [-g]'))
5139 def tip(ui, repo, **opts):
5155 def tip(ui, repo, **opts):
5140 """show the tip revision
5156 """show the tip revision
5141
5157
5142 The tip revision (usually just called the tip) is the changeset
5158 The tip revision (usually just called the tip) is the changeset
5143 most recently added to the repository (and therefore the most
5159 most recently added to the repository (and therefore the most
5144 recently changed head).
5160 recently changed head).
5145
5161
5146 If you have just made a commit, that commit will be the tip. If
5162 If you have just made a commit, that commit will be the tip. If
5147 you have just pulled changes from another repository, the tip of
5163 you have just pulled changes from another repository, the tip of
5148 that repository becomes the current tip. The "tip" tag is special
5164 that repository becomes the current tip. The "tip" tag is special
5149 and cannot be renamed or assigned to a different changeset.
5165 and cannot be renamed or assigned to a different changeset.
5150
5166
5151 Returns 0 on success.
5167 Returns 0 on success.
5152 """
5168 """
5153 displayer = cmdutil.show_changeset(ui, repo, opts)
5169 displayer = cmdutil.show_changeset(ui, repo, opts)
5154 displayer.show(repo[len(repo) - 1])
5170 displayer.show(repo[len(repo) - 1])
5155 displayer.close()
5171 displayer.close()
5156
5172
5157 @command('unbundle',
5173 @command('unbundle',
5158 [('u', 'update', None,
5174 [('u', 'update', None,
5159 _('update to new branch head if changesets were unbundled'))],
5175 _('update to new branch head if changesets were unbundled'))],
5160 _('[-u] FILE...'))
5176 _('[-u] FILE...'))
5161 def unbundle(ui, repo, fname1, *fnames, **opts):
5177 def unbundle(ui, repo, fname1, *fnames, **opts):
5162 """apply one or more changegroup files
5178 """apply one or more changegroup files
5163
5179
5164 Apply one or more compressed changegroup files generated by the
5180 Apply one or more compressed changegroup files generated by the
5165 bundle command.
5181 bundle command.
5166
5182
5167 Returns 0 on success, 1 if an update has unresolved files.
5183 Returns 0 on success, 1 if an update has unresolved files.
5168 """
5184 """
5169 fnames = (fname1,) + fnames
5185 fnames = (fname1,) + fnames
5170
5186
5171 lock = repo.lock()
5187 lock = repo.lock()
5172 wc = repo['.']
5188 wc = repo['.']
5173 try:
5189 try:
5174 for fname in fnames:
5190 for fname in fnames:
5175 f = url.open(ui, fname)
5191 f = url.open(ui, fname)
5176 gen = changegroup.readbundle(f, fname)
5192 gen = changegroup.readbundle(f, fname)
5177 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5193 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5178 lock=lock)
5194 lock=lock)
5179 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5195 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5180 finally:
5196 finally:
5181 lock.release()
5197 lock.release()
5182 return postincoming(ui, repo, modheads, opts.get('update'), None)
5198 return postincoming(ui, repo, modheads, opts.get('update'), None)
5183
5199
5184 @command('^update|up|checkout|co',
5200 @command('^update|up|checkout|co',
5185 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5201 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5186 ('c', 'check', None,
5202 ('c', 'check', None,
5187 _('update across branches if no uncommitted changes')),
5203 _('update across branches if no uncommitted changes')),
5188 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5204 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5189 ('r', 'rev', '', _('revision'), _('REV'))],
5205 ('r', 'rev', '', _('revision'), _('REV'))],
5190 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5206 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5191 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5207 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5192 """update working directory (or switch revisions)
5208 """update working directory (or switch revisions)
5193
5209
5194 Update the repository's working directory to the specified
5210 Update the repository's working directory to the specified
5195 changeset. If no changeset is specified, update to the tip of the
5211 changeset. If no changeset is specified, update to the tip of the
5196 current named branch.
5212 current named branch.
5197
5213
5198 If the changeset is not a descendant of the working directory's
5214 If the changeset is not a descendant of the working directory's
5199 parent, the update is aborted. With the -c/--check option, the
5215 parent, the update is aborted. With the -c/--check option, the
5200 working directory is checked for uncommitted changes; if none are
5216 working directory is checked for uncommitted changes; if none are
5201 found, the working directory is updated to the specified
5217 found, the working directory is updated to the specified
5202 changeset.
5218 changeset.
5203
5219
5204 Update sets the working directory's parent revison to the specified
5220 Update sets the working directory's parent revison to the specified
5205 changeset (see :hg:`help parents`).
5221 changeset (see :hg:`help parents`).
5206
5222
5207 The following rules apply when the working directory contains
5223 The following rules apply when the working directory contains
5208 uncommitted changes:
5224 uncommitted changes:
5209
5225
5210 1. If neither -c/--check nor -C/--clean is specified, and if
5226 1. If neither -c/--check nor -C/--clean is specified, and if
5211 the requested changeset is an ancestor or descendant of
5227 the requested changeset is an ancestor or descendant of
5212 the working directory's parent, the uncommitted changes
5228 the working directory's parent, the uncommitted changes
5213 are merged into the requested changeset and the merged
5229 are merged into the requested changeset and the merged
5214 result is left uncommitted. If the requested changeset is
5230 result is left uncommitted. If the requested changeset is
5215 not an ancestor or descendant (that is, it is on another
5231 not an ancestor or descendant (that is, it is on another
5216 branch), the update is aborted and the uncommitted changes
5232 branch), the update is aborted and the uncommitted changes
5217 are preserved.
5233 are preserved.
5218
5234
5219 2. With the -c/--check option, the update is aborted and the
5235 2. With the -c/--check option, the update is aborted and the
5220 uncommitted changes are preserved.
5236 uncommitted changes are preserved.
5221
5237
5222 3. With the -C/--clean option, uncommitted changes are discarded and
5238 3. With the -C/--clean option, uncommitted changes are discarded and
5223 the working directory is updated to the requested changeset.
5239 the working directory is updated to the requested changeset.
5224
5240
5225 Use null as the changeset to remove the working directory (like
5241 Use null as the changeset to remove the working directory (like
5226 :hg:`clone -U`).
5242 :hg:`clone -U`).
5227
5243
5228 If you want to revert just one file to an older revision, use
5244 If you want to revert just one file to an older revision, use
5229 :hg:`revert [-r REV] NAME`.
5245 :hg:`revert [-r REV] NAME`.
5230
5246
5231 See :hg:`help dates` for a list of formats valid for -d/--date.
5247 See :hg:`help dates` for a list of formats valid for -d/--date.
5232
5248
5233 Returns 0 on success, 1 if there are unresolved files.
5249 Returns 0 on success, 1 if there are unresolved files.
5234 """
5250 """
5235 if rev and node:
5251 if rev and node:
5236 raise util.Abort(_("please specify just one revision"))
5252 raise util.Abort(_("please specify just one revision"))
5237
5253
5238 if rev is None or rev == '':
5254 if rev is None or rev == '':
5239 rev = node
5255 rev = node
5240
5256
5241 # if we defined a bookmark, we have to remember the original bookmark name
5257 # if we defined a bookmark, we have to remember the original bookmark name
5242 brev = rev
5258 brev = rev
5243 rev = scmutil.revsingle(repo, rev, rev).rev()
5259 rev = scmutil.revsingle(repo, rev, rev).rev()
5244
5260
5245 if check and clean:
5261 if check and clean:
5246 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5262 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5247
5263
5248 if check:
5264 if check:
5249 # we could use dirty() but we can ignore merge and branch trivia
5265 # we could use dirty() but we can ignore merge and branch trivia
5250 c = repo[None]
5266 c = repo[None]
5251 if c.modified() or c.added() or c.removed():
5267 if c.modified() or c.added() or c.removed():
5252 raise util.Abort(_("uncommitted local changes"))
5268 raise util.Abort(_("uncommitted local changes"))
5253
5269
5254 if date:
5270 if date:
5255 if rev is not None:
5271 if rev is not None:
5256 raise util.Abort(_("you can't specify a revision and a date"))
5272 raise util.Abort(_("you can't specify a revision and a date"))
5257 rev = cmdutil.finddate(ui, repo, date)
5273 rev = cmdutil.finddate(ui, repo, date)
5258
5274
5259 if clean or check:
5275 if clean or check:
5260 ret = hg.clean(repo, rev)
5276 ret = hg.clean(repo, rev)
5261 else:
5277 else:
5262 ret = hg.update(repo, rev)
5278 ret = hg.update(repo, rev)
5263
5279
5264 if brev in repo._bookmarks:
5280 if brev in repo._bookmarks:
5265 bookmarks.setcurrent(repo, brev)
5281 bookmarks.setcurrent(repo, brev)
5266
5282
5267 return ret
5283 return ret
5268
5284
5269 @command('verify', [])
5285 @command('verify', [])
5270 def verify(ui, repo):
5286 def verify(ui, repo):
5271 """verify the integrity of the repository
5287 """verify the integrity of the repository
5272
5288
5273 Verify the integrity of the current repository.
5289 Verify the integrity of the current repository.
5274
5290
5275 This will perform an extensive check of the repository's
5291 This will perform an extensive check of the repository's
5276 integrity, validating the hashes and checksums of each entry in
5292 integrity, validating the hashes and checksums of each entry in
5277 the changelog, manifest, and tracked files, as well as the
5293 the changelog, manifest, and tracked files, as well as the
5278 integrity of their crosslinks and indices.
5294 integrity of their crosslinks and indices.
5279
5295
5280 Returns 0 on success, 1 if errors are encountered.
5296 Returns 0 on success, 1 if errors are encountered.
5281 """
5297 """
5282 return hg.verify(repo)
5298 return hg.verify(repo)
5283
5299
5284 @command('version', [])
5300 @command('version', [])
5285 def version_(ui):
5301 def version_(ui):
5286 """output version and copyright information"""
5302 """output version and copyright information"""
5287 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5303 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5288 % util.version())
5304 % util.version())
5289 ui.status(_(
5305 ui.status(_(
5290 "(see http://mercurial.selenic.com for more information)\n"
5306 "(see http://mercurial.selenic.com for more information)\n"
5291 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5307 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5292 "This is free software; see the source for copying conditions. "
5308 "This is free software; see the source for copying conditions. "
5293 "There is NO\nwarranty; "
5309 "There is NO\nwarranty; "
5294 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5310 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5295 ))
5311 ))
5296
5312
5297 norepo = ("clone init version help debugcommands debugcomplete"
5313 norepo = ("clone init version help debugcommands debugcomplete"
5298 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5314 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5299 " debugknown debuggetbundle debugbundle")
5315 " debugknown debuggetbundle debugbundle")
5300 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5316 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5301 " debugdata debugindex debugindexdot debugrevlog")
5317 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now