##// END OF EJS Templates
help: move option list display into subfunctions
Matt Mackall -
r15128:aaf666bd default
parent child Browse files
Show More
@@ -1,5366 +1,5369 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 .. container:: verbose
2330 .. container:: verbose
2331
2331
2332 Examples:
2332 Examples:
2333
2333
2334 - forget newly-added binary files::
2334 - forget newly-added binary files::
2335
2335
2336 hg forget "set:added() and binary()"
2336 hg forget "set:added() and binary()"
2337
2337
2338 - forget files that would be excluded by .hgignore::
2338 - forget files that would be excluded by .hgignore::
2339
2339
2340 hg forget "set:hgignore()"
2340 hg forget "set:hgignore()"
2341
2341
2342 Returns 0 on success.
2342 Returns 0 on success.
2343 """
2343 """
2344
2344
2345 if not pats:
2345 if not pats:
2346 raise util.Abort(_('no files specified'))
2346 raise util.Abort(_('no files specified'))
2347
2347
2348 m = scmutil.match(repo[None], pats, opts)
2348 m = scmutil.match(repo[None], pats, opts)
2349 s = repo.status(match=m, clean=True)
2349 s = repo.status(match=m, clean=True)
2350 forget = sorted(s[0] + s[1] + s[3] + s[6])
2350 forget = sorted(s[0] + s[1] + s[3] + s[6])
2351 errs = 0
2351 errs = 0
2352
2352
2353 for f in m.files():
2353 for f in m.files():
2354 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2354 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2355 if os.path.exists(m.rel(f)):
2355 if os.path.exists(m.rel(f)):
2356 ui.warn(_('not removing %s: file is already untracked\n')
2356 ui.warn(_('not removing %s: file is already untracked\n')
2357 % m.rel(f))
2357 % m.rel(f))
2358 errs = 1
2358 errs = 1
2359
2359
2360 for f in forget:
2360 for f in forget:
2361 if ui.verbose or not m.exact(f):
2361 if ui.verbose or not m.exact(f):
2362 ui.status(_('removing %s\n') % m.rel(f))
2362 ui.status(_('removing %s\n') % m.rel(f))
2363
2363
2364 repo[None].forget(forget)
2364 repo[None].forget(forget)
2365 return errs
2365 return errs
2366
2366
2367 @command('grep',
2367 @command('grep',
2368 [('0', 'print0', None, _('end fields with NUL')),
2368 [('0', 'print0', None, _('end fields with NUL')),
2369 ('', 'all', None, _('print all revisions that match')),
2369 ('', 'all', None, _('print all revisions that match')),
2370 ('a', 'text', None, _('treat all files as text')),
2370 ('a', 'text', None, _('treat all files as text')),
2371 ('f', 'follow', None,
2371 ('f', 'follow', None,
2372 _('follow changeset history,'
2372 _('follow changeset history,'
2373 ' or file history across copies and renames')),
2373 ' or file history across copies and renames')),
2374 ('i', 'ignore-case', None, _('ignore case when matching')),
2374 ('i', 'ignore-case', None, _('ignore case when matching')),
2375 ('l', 'files-with-matches', None,
2375 ('l', 'files-with-matches', None,
2376 _('print only filenames and revisions that match')),
2376 _('print only filenames and revisions that match')),
2377 ('n', 'line-number', None, _('print matching line numbers')),
2377 ('n', 'line-number', None, _('print matching line numbers')),
2378 ('r', 'rev', [],
2378 ('r', 'rev', [],
2379 _('only search files changed within revision range'), _('REV')),
2379 _('only search files changed within revision range'), _('REV')),
2380 ('u', 'user', None, _('list the author (long with -v)')),
2380 ('u', 'user', None, _('list the author (long with -v)')),
2381 ('d', 'date', None, _('list the date (short with -q)')),
2381 ('d', 'date', None, _('list the date (short with -q)')),
2382 ] + walkopts,
2382 ] + walkopts,
2383 _('[OPTION]... PATTERN [FILE]...'))
2383 _('[OPTION]... PATTERN [FILE]...'))
2384 def grep(ui, repo, pattern, *pats, **opts):
2384 def grep(ui, repo, pattern, *pats, **opts):
2385 """search for a pattern in specified files and revisions
2385 """search for a pattern in specified files and revisions
2386
2386
2387 Search revisions of files for a regular expression.
2387 Search revisions of files for a regular expression.
2388
2388
2389 This command behaves differently than Unix grep. It only accepts
2389 This command behaves differently than Unix grep. It only accepts
2390 Python/Perl regexps. It searches repository history, not the
2390 Python/Perl regexps. It searches repository history, not the
2391 working directory. It always prints the revision number in which a
2391 working directory. It always prints the revision number in which a
2392 match appears.
2392 match appears.
2393
2393
2394 By default, grep only prints output for the first revision of a
2394 By default, grep only prints output for the first revision of a
2395 file in which it finds a match. To get it to print every revision
2395 file in which it finds a match. To get it to print every revision
2396 that contains a change in match status ("-" for a match that
2396 that contains a change in match status ("-" for a match that
2397 becomes a non-match, or "+" for a non-match that becomes a match),
2397 becomes a non-match, or "+" for a non-match that becomes a match),
2398 use the --all flag.
2398 use the --all flag.
2399
2399
2400 Returns 0 if a match is found, 1 otherwise.
2400 Returns 0 if a match is found, 1 otherwise.
2401 """
2401 """
2402 reflags = 0
2402 reflags = 0
2403 if opts.get('ignore_case'):
2403 if opts.get('ignore_case'):
2404 reflags |= re.I
2404 reflags |= re.I
2405 try:
2405 try:
2406 regexp = re.compile(pattern, reflags)
2406 regexp = re.compile(pattern, reflags)
2407 except re.error, inst:
2407 except re.error, inst:
2408 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2408 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2409 return 1
2409 return 1
2410 sep, eol = ':', '\n'
2410 sep, eol = ':', '\n'
2411 if opts.get('print0'):
2411 if opts.get('print0'):
2412 sep = eol = '\0'
2412 sep = eol = '\0'
2413
2413
2414 getfile = util.lrucachefunc(repo.file)
2414 getfile = util.lrucachefunc(repo.file)
2415
2415
2416 def matchlines(body):
2416 def matchlines(body):
2417 begin = 0
2417 begin = 0
2418 linenum = 0
2418 linenum = 0
2419 while True:
2419 while True:
2420 match = regexp.search(body, begin)
2420 match = regexp.search(body, begin)
2421 if not match:
2421 if not match:
2422 break
2422 break
2423 mstart, mend = match.span()
2423 mstart, mend = match.span()
2424 linenum += body.count('\n', begin, mstart) + 1
2424 linenum += body.count('\n', begin, mstart) + 1
2425 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2425 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2426 begin = body.find('\n', mend) + 1 or len(body)
2426 begin = body.find('\n', mend) + 1 or len(body)
2427 lend = begin - 1
2427 lend = begin - 1
2428 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2428 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2429
2429
2430 class linestate(object):
2430 class linestate(object):
2431 def __init__(self, line, linenum, colstart, colend):
2431 def __init__(self, line, linenum, colstart, colend):
2432 self.line = line
2432 self.line = line
2433 self.linenum = linenum
2433 self.linenum = linenum
2434 self.colstart = colstart
2434 self.colstart = colstart
2435 self.colend = colend
2435 self.colend = colend
2436
2436
2437 def __hash__(self):
2437 def __hash__(self):
2438 return hash((self.linenum, self.line))
2438 return hash((self.linenum, self.line))
2439
2439
2440 def __eq__(self, other):
2440 def __eq__(self, other):
2441 return self.line == other.line
2441 return self.line == other.line
2442
2442
2443 matches = {}
2443 matches = {}
2444 copies = {}
2444 copies = {}
2445 def grepbody(fn, rev, body):
2445 def grepbody(fn, rev, body):
2446 matches[rev].setdefault(fn, [])
2446 matches[rev].setdefault(fn, [])
2447 m = matches[rev][fn]
2447 m = matches[rev][fn]
2448 for lnum, cstart, cend, line in matchlines(body):
2448 for lnum, cstart, cend, line in matchlines(body):
2449 s = linestate(line, lnum, cstart, cend)
2449 s = linestate(line, lnum, cstart, cend)
2450 m.append(s)
2450 m.append(s)
2451
2451
2452 def difflinestates(a, b):
2452 def difflinestates(a, b):
2453 sm = difflib.SequenceMatcher(None, a, b)
2453 sm = difflib.SequenceMatcher(None, a, b)
2454 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2454 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2455 if tag == 'insert':
2455 if tag == 'insert':
2456 for i in xrange(blo, bhi):
2456 for i in xrange(blo, bhi):
2457 yield ('+', b[i])
2457 yield ('+', b[i])
2458 elif tag == 'delete':
2458 elif tag == 'delete':
2459 for i in xrange(alo, ahi):
2459 for i in xrange(alo, ahi):
2460 yield ('-', a[i])
2460 yield ('-', a[i])
2461 elif tag == 'replace':
2461 elif tag == 'replace':
2462 for i in xrange(alo, ahi):
2462 for i in xrange(alo, ahi):
2463 yield ('-', a[i])
2463 yield ('-', a[i])
2464 for i in xrange(blo, bhi):
2464 for i in xrange(blo, bhi):
2465 yield ('+', b[i])
2465 yield ('+', b[i])
2466
2466
2467 def display(fn, ctx, pstates, states):
2467 def display(fn, ctx, pstates, states):
2468 rev = ctx.rev()
2468 rev = ctx.rev()
2469 datefunc = ui.quiet and util.shortdate or util.datestr
2469 datefunc = ui.quiet and util.shortdate or util.datestr
2470 found = False
2470 found = False
2471 filerevmatches = {}
2471 filerevmatches = {}
2472 def binary():
2472 def binary():
2473 flog = getfile(fn)
2473 flog = getfile(fn)
2474 return util.binary(flog.read(ctx.filenode(fn)))
2474 return util.binary(flog.read(ctx.filenode(fn)))
2475
2475
2476 if opts.get('all'):
2476 if opts.get('all'):
2477 iter = difflinestates(pstates, states)
2477 iter = difflinestates(pstates, states)
2478 else:
2478 else:
2479 iter = [('', l) for l in states]
2479 iter = [('', l) for l in states]
2480 for change, l in iter:
2480 for change, l in iter:
2481 cols = [fn, str(rev)]
2481 cols = [fn, str(rev)]
2482 before, match, after = None, None, None
2482 before, match, after = None, None, None
2483 if opts.get('line_number'):
2483 if opts.get('line_number'):
2484 cols.append(str(l.linenum))
2484 cols.append(str(l.linenum))
2485 if opts.get('all'):
2485 if opts.get('all'):
2486 cols.append(change)
2486 cols.append(change)
2487 if opts.get('user'):
2487 if opts.get('user'):
2488 cols.append(ui.shortuser(ctx.user()))
2488 cols.append(ui.shortuser(ctx.user()))
2489 if opts.get('date'):
2489 if opts.get('date'):
2490 cols.append(datefunc(ctx.date()))
2490 cols.append(datefunc(ctx.date()))
2491 if opts.get('files_with_matches'):
2491 if opts.get('files_with_matches'):
2492 c = (fn, rev)
2492 c = (fn, rev)
2493 if c in filerevmatches:
2493 if c in filerevmatches:
2494 continue
2494 continue
2495 filerevmatches[c] = 1
2495 filerevmatches[c] = 1
2496 else:
2496 else:
2497 before = l.line[:l.colstart]
2497 before = l.line[:l.colstart]
2498 match = l.line[l.colstart:l.colend]
2498 match = l.line[l.colstart:l.colend]
2499 after = l.line[l.colend:]
2499 after = l.line[l.colend:]
2500 ui.write(sep.join(cols))
2500 ui.write(sep.join(cols))
2501 if before is not None:
2501 if before is not None:
2502 if not opts.get('text') and binary():
2502 if not opts.get('text') and binary():
2503 ui.write(sep + " Binary file matches")
2503 ui.write(sep + " Binary file matches")
2504 else:
2504 else:
2505 ui.write(sep + before)
2505 ui.write(sep + before)
2506 ui.write(match, label='grep.match')
2506 ui.write(match, label='grep.match')
2507 ui.write(after)
2507 ui.write(after)
2508 ui.write(eol)
2508 ui.write(eol)
2509 found = True
2509 found = True
2510 return found
2510 return found
2511
2511
2512 skip = {}
2512 skip = {}
2513 revfiles = {}
2513 revfiles = {}
2514 matchfn = scmutil.match(repo[None], pats, opts)
2514 matchfn = scmutil.match(repo[None], pats, opts)
2515 found = False
2515 found = False
2516 follow = opts.get('follow')
2516 follow = opts.get('follow')
2517
2517
2518 def prep(ctx, fns):
2518 def prep(ctx, fns):
2519 rev = ctx.rev()
2519 rev = ctx.rev()
2520 pctx = ctx.p1()
2520 pctx = ctx.p1()
2521 parent = pctx.rev()
2521 parent = pctx.rev()
2522 matches.setdefault(rev, {})
2522 matches.setdefault(rev, {})
2523 matches.setdefault(parent, {})
2523 matches.setdefault(parent, {})
2524 files = revfiles.setdefault(rev, [])
2524 files = revfiles.setdefault(rev, [])
2525 for fn in fns:
2525 for fn in fns:
2526 flog = getfile(fn)
2526 flog = getfile(fn)
2527 try:
2527 try:
2528 fnode = ctx.filenode(fn)
2528 fnode = ctx.filenode(fn)
2529 except error.LookupError:
2529 except error.LookupError:
2530 continue
2530 continue
2531
2531
2532 copied = flog.renamed(fnode)
2532 copied = flog.renamed(fnode)
2533 copy = follow and copied and copied[0]
2533 copy = follow and copied and copied[0]
2534 if copy:
2534 if copy:
2535 copies.setdefault(rev, {})[fn] = copy
2535 copies.setdefault(rev, {})[fn] = copy
2536 if fn in skip:
2536 if fn in skip:
2537 if copy:
2537 if copy:
2538 skip[copy] = True
2538 skip[copy] = True
2539 continue
2539 continue
2540 files.append(fn)
2540 files.append(fn)
2541
2541
2542 if fn not in matches[rev]:
2542 if fn not in matches[rev]:
2543 grepbody(fn, rev, flog.read(fnode))
2543 grepbody(fn, rev, flog.read(fnode))
2544
2544
2545 pfn = copy or fn
2545 pfn = copy or fn
2546 if pfn not in matches[parent]:
2546 if pfn not in matches[parent]:
2547 try:
2547 try:
2548 fnode = pctx.filenode(pfn)
2548 fnode = pctx.filenode(pfn)
2549 grepbody(pfn, parent, flog.read(fnode))
2549 grepbody(pfn, parent, flog.read(fnode))
2550 except error.LookupError:
2550 except error.LookupError:
2551 pass
2551 pass
2552
2552
2553 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2553 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2554 rev = ctx.rev()
2554 rev = ctx.rev()
2555 parent = ctx.p1().rev()
2555 parent = ctx.p1().rev()
2556 for fn in sorted(revfiles.get(rev, [])):
2556 for fn in sorted(revfiles.get(rev, [])):
2557 states = matches[rev][fn]
2557 states = matches[rev][fn]
2558 copy = copies.get(rev, {}).get(fn)
2558 copy = copies.get(rev, {}).get(fn)
2559 if fn in skip:
2559 if fn in skip:
2560 if copy:
2560 if copy:
2561 skip[copy] = True
2561 skip[copy] = True
2562 continue
2562 continue
2563 pstates = matches.get(parent, {}).get(copy or fn, [])
2563 pstates = matches.get(parent, {}).get(copy or fn, [])
2564 if pstates or states:
2564 if pstates or states:
2565 r = display(fn, ctx, pstates, states)
2565 r = display(fn, ctx, pstates, states)
2566 found = found or r
2566 found = found or r
2567 if r and not opts.get('all'):
2567 if r and not opts.get('all'):
2568 skip[fn] = True
2568 skip[fn] = True
2569 if copy:
2569 if copy:
2570 skip[copy] = True
2570 skip[copy] = True
2571 del matches[rev]
2571 del matches[rev]
2572 del revfiles[rev]
2572 del revfiles[rev]
2573
2573
2574 return not found
2574 return not found
2575
2575
2576 @command('heads',
2576 @command('heads',
2577 [('r', 'rev', '',
2577 [('r', 'rev', '',
2578 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2578 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2579 ('t', 'topo', False, _('show topological heads only')),
2579 ('t', 'topo', False, _('show topological heads only')),
2580 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2580 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2581 ('c', 'closed', False, _('show normal and closed branch heads')),
2581 ('c', 'closed', False, _('show normal and closed branch heads')),
2582 ] + templateopts,
2582 ] + templateopts,
2583 _('[-ac] [-r STARTREV] [REV]...'))
2583 _('[-ac] [-r STARTREV] [REV]...'))
2584 def heads(ui, repo, *branchrevs, **opts):
2584 def heads(ui, repo, *branchrevs, **opts):
2585 """show current repository heads or show branch heads
2585 """show current repository heads or show branch heads
2586
2586
2587 With no arguments, show all repository branch heads.
2587 With no arguments, show all repository branch heads.
2588
2588
2589 Repository "heads" are changesets with no child changesets. They are
2589 Repository "heads" are changesets with no child changesets. They are
2590 where development generally takes place and are the usual targets
2590 where development generally takes place and are the usual targets
2591 for update and merge operations. Branch heads are changesets that have
2591 for update and merge operations. Branch heads are changesets that have
2592 no child changeset on the same branch.
2592 no child changeset on the same branch.
2593
2593
2594 If one or more REVs are given, only branch heads on the branches
2594 If one or more REVs are given, only branch heads on the branches
2595 associated with the specified changesets are shown. This means
2595 associated with the specified changesets are shown. This means
2596 that you can use :hg:`heads foo` to see the heads on a branch
2596 that you can use :hg:`heads foo` to see the heads on a branch
2597 named ``foo``.
2597 named ``foo``.
2598
2598
2599 If -c/--closed is specified, also show branch heads marked closed
2599 If -c/--closed is specified, also show branch heads marked closed
2600 (see :hg:`commit --close-branch`).
2600 (see :hg:`commit --close-branch`).
2601
2601
2602 If STARTREV is specified, only those heads that are descendants of
2602 If STARTREV is specified, only those heads that are descendants of
2603 STARTREV will be displayed.
2603 STARTREV will be displayed.
2604
2604
2605 If -t/--topo is specified, named branch mechanics will be ignored and only
2605 If -t/--topo is specified, named branch mechanics will be ignored and only
2606 changesets without children will be shown.
2606 changesets without children will be shown.
2607
2607
2608 Returns 0 if matching heads are found, 1 if not.
2608 Returns 0 if matching heads are found, 1 if not.
2609 """
2609 """
2610
2610
2611 start = None
2611 start = None
2612 if 'rev' in opts:
2612 if 'rev' in opts:
2613 start = scmutil.revsingle(repo, opts['rev'], None).node()
2613 start = scmutil.revsingle(repo, opts['rev'], None).node()
2614
2614
2615 if opts.get('topo'):
2615 if opts.get('topo'):
2616 heads = [repo[h] for h in repo.heads(start)]
2616 heads = [repo[h] for h in repo.heads(start)]
2617 else:
2617 else:
2618 heads = []
2618 heads = []
2619 for branch in repo.branchmap():
2619 for branch in repo.branchmap():
2620 heads += repo.branchheads(branch, start, opts.get('closed'))
2620 heads += repo.branchheads(branch, start, opts.get('closed'))
2621 heads = [repo[h] for h in heads]
2621 heads = [repo[h] for h in heads]
2622
2622
2623 if branchrevs:
2623 if branchrevs:
2624 branches = set(repo[br].branch() for br in branchrevs)
2624 branches = set(repo[br].branch() for br in branchrevs)
2625 heads = [h for h in heads if h.branch() in branches]
2625 heads = [h for h in heads if h.branch() in branches]
2626
2626
2627 if opts.get('active') and branchrevs:
2627 if opts.get('active') and branchrevs:
2628 dagheads = repo.heads(start)
2628 dagheads = repo.heads(start)
2629 heads = [h for h in heads if h.node() in dagheads]
2629 heads = [h for h in heads if h.node() in dagheads]
2630
2630
2631 if branchrevs:
2631 if branchrevs:
2632 haveheads = set(h.branch() for h in heads)
2632 haveheads = set(h.branch() for h in heads)
2633 if branches - haveheads:
2633 if branches - haveheads:
2634 headless = ', '.join(b for b in branches - haveheads)
2634 headless = ', '.join(b for b in branches - haveheads)
2635 msg = _('no open branch heads found on branches %s')
2635 msg = _('no open branch heads found on branches %s')
2636 if opts.get('rev'):
2636 if opts.get('rev'):
2637 msg += _(' (started at %s)' % opts['rev'])
2637 msg += _(' (started at %s)' % opts['rev'])
2638 ui.warn((msg + '\n') % headless)
2638 ui.warn((msg + '\n') % headless)
2639
2639
2640 if not heads:
2640 if not heads:
2641 return 1
2641 return 1
2642
2642
2643 heads = sorted(heads, key=lambda x: -x.rev())
2643 heads = sorted(heads, key=lambda x: -x.rev())
2644 displayer = cmdutil.show_changeset(ui, repo, opts)
2644 displayer = cmdutil.show_changeset(ui, repo, opts)
2645 for ctx in heads:
2645 for ctx in heads:
2646 displayer.show(ctx)
2646 displayer.show(ctx)
2647 displayer.close()
2647 displayer.close()
2648
2648
2649 @command('help',
2649 @command('help',
2650 [('e', 'extension', None, _('show only help for extensions')),
2650 [('e', 'extension', None, _('show only help for extensions')),
2651 ('c', 'command', None, _('show only help for commands'))],
2651 ('c', 'command', None, _('show only help for commands'))],
2652 _('[-ec] [TOPIC]'))
2652 _('[-ec] [TOPIC]'))
2653 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2653 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2654 """show help for a given topic or a help overview
2654 """show help for a given topic or a help overview
2655
2655
2656 With no arguments, print a list of commands with short help messages.
2656 With no arguments, print a list of commands with short help messages.
2657
2657
2658 Given a topic, extension, or command name, print help for that
2658 Given a topic, extension, or command name, print help for that
2659 topic.
2659 topic.
2660
2660
2661 Returns 0 if successful.
2661 Returns 0 if successful.
2662 """
2662 """
2663
2663
2664 optlist = []
2664 optlist = []
2665 textwidth = min(ui.termwidth(), 80) - 2
2665 textwidth = min(ui.termwidth(), 80) - 2
2666
2666
2667 # list all option lists
2667 # list all option lists
2668 def opttext(optlist, width):
2668 def opttext(optlist, width):
2669 out = []
2669 out = []
2670 multioccur = False
2670 multioccur = False
2671 for title, options in optlist:
2671 for title, options in optlist:
2672 out.append(("\n%s" % title, None))
2672 out.append(("\n%s" % title, None))
2673 for option in options:
2673 for option in options:
2674 if len(option) == 5:
2674 if len(option) == 5:
2675 shortopt, longopt, default, desc, optlabel = option
2675 shortopt, longopt, default, desc, optlabel = option
2676 else:
2676 else:
2677 shortopt, longopt, default, desc = option
2677 shortopt, longopt, default, desc = option
2678 optlabel = _("VALUE") # default label
2678 optlabel = _("VALUE") # default label
2679
2679
2680 if _("DEPRECATED") in desc and not ui.verbose:
2680 if _("DEPRECATED") in desc and not ui.verbose:
2681 continue
2681 continue
2682 if isinstance(default, list):
2682 if isinstance(default, list):
2683 numqualifier = " %s [+]" % optlabel
2683 numqualifier = " %s [+]" % optlabel
2684 multioccur = True
2684 multioccur = True
2685 elif (default is not None) and not isinstance(default, bool):
2685 elif (default is not None) and not isinstance(default, bool):
2686 numqualifier = " %s" % optlabel
2686 numqualifier = " %s" % optlabel
2687 else:
2687 else:
2688 numqualifier = ""
2688 numqualifier = ""
2689 out.append(("%2s%s" %
2689 out.append(("%2s%s" %
2690 (shortopt and "-%s" % shortopt,
2690 (shortopt and "-%s" % shortopt,
2691 longopt and " --%s%s" %
2691 longopt and " --%s%s" %
2692 (longopt, numqualifier)),
2692 (longopt, numqualifier)),
2693 "%s%s" % (desc,
2693 "%s%s" % (desc,
2694 default
2694 default
2695 and _(" (default: %s)") % default
2695 and _(" (default: %s)") % default
2696 or "")))
2696 or "")))
2697 if multioccur:
2697 if multioccur:
2698 msg = _("\n[+] marked option can be specified multiple times")
2698 msg = _("\n[+] marked option can be specified multiple times")
2699 if ui.verbose and name != 'shortlist':
2699 if ui.verbose and name != 'shortlist':
2700 out.append((msg, None))
2700 out.append((msg, None))
2701 else:
2701 else:
2702 out.insert(-1, (msg, None))
2702 out.insert(-1, (msg, None))
2703
2703
2704 text = ""
2704 text = ""
2705 if out:
2705 if out:
2706 colwidth = encoding.colwidth
2706 colwidth = encoding.colwidth
2707 # normalize: (opt or message, desc or None, width of opt)
2707 # normalize: (opt or message, desc or None, width of opt)
2708 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2708 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2709 for opt, desc in out]
2709 for opt, desc in out]
2710 hanging = max([e[2] for e in entries])
2710 hanging = max([e[2] for e in entries])
2711 for opt, desc, width in entries:
2711 for opt, desc, width in entries:
2712 if desc:
2712 if desc:
2713 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2713 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2714 hangindent = ' ' * (hanging + 3)
2714 hangindent = ' ' * (hanging + 3)
2715 text += '%s\n' % (util.wrap(desc, width,
2715 text += '%s\n' % (util.wrap(desc, width,
2716 initindent=initindent,
2716 initindent=initindent,
2717 hangindent=hangindent))
2717 hangindent=hangindent))
2718 else:
2718 else:
2719 text += "%s\n" % opt
2719 text += "%s\n" % opt
2720
2720
2721 return text
2721 return text
2722
2722
2723 def addglobalopts(aliases):
2723 def addglobalopts(aliases):
2724 if ui.verbose:
2724 if ui.verbose:
2725 optlist.append((_("global options:"), globalopts))
2725 optlist.append((_("global options:"), globalopts))
2726 if name == 'shortlist':
2726 if name == 'shortlist':
2727 optlist.append((_('use "hg help" for the full list '
2727 optlist.append((_('use "hg help" for the full list '
2728 'of commands'), ()))
2728 'of commands'), ()))
2729 else:
2729 else:
2730 if name == 'shortlist':
2730 if name == 'shortlist':
2731 msg = _('use "hg help" for the full list of commands '
2731 msg = _('use "hg help" for the full list of commands '
2732 'or "hg -v" for details')
2732 'or "hg -v" for details')
2733 elif name and not full:
2733 elif name and not full:
2734 msg = _('use "hg help %s" to show the full help text' % name)
2734 msg = _('use "hg help %s" to show the full help text' % name)
2735 elif aliases:
2735 elif aliases:
2736 msg = _('use "hg -v help%s" to show builtin aliases and '
2736 msg = _('use "hg -v help%s" to show builtin aliases and '
2737 'global options') % (name and " " + name or "")
2737 'global options') % (name and " " + name or "")
2738 else:
2738 else:
2739 msg = _('use "hg -v help %s" to show global options') % name
2739 msg = _('use "hg -v help %s" to show global options') % name
2740 optlist.append((msg, ()))
2740 optlist.append((msg, ()))
2741
2741
2742 def helpcmd(name):
2742 def helpcmd(name):
2743 try:
2743 try:
2744 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2744 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2745 except error.AmbiguousCommand, inst:
2745 except error.AmbiguousCommand, inst:
2746 # py3k fix: except vars can't be used outside the scope of the
2746 # py3k fix: except vars can't be used outside the scope of the
2747 # except block, nor can be used inside a lambda. python issue4617
2747 # except block, nor can be used inside a lambda. python issue4617
2748 prefix = inst.args[0]
2748 prefix = inst.args[0]
2749 select = lambda c: c.lstrip('^').startswith(prefix)
2749 select = lambda c: c.lstrip('^').startswith(prefix)
2750 helplist(select)
2750 helplist(select)
2751 return
2751 return
2752
2752
2753 # check if it's an invalid alias and display its error if it is
2753 # check if it's an invalid alias and display its error if it is
2754 if getattr(entry[0], 'badalias', False):
2754 if getattr(entry[0], 'badalias', False):
2755 if not unknowncmd:
2755 if not unknowncmd:
2756 entry[0](ui)
2756 entry[0](ui)
2757 return
2757 return
2758
2758
2759 # synopsis
2759 # synopsis
2760 if len(entry) > 2:
2760 if len(entry) > 2:
2761 if entry[2].startswith('hg'):
2761 if entry[2].startswith('hg'):
2762 ui.write("%s\n" % entry[2])
2762 ui.write("%s\n" % entry[2])
2763 else:
2763 else:
2764 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2764 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2765 else:
2765 else:
2766 ui.write('hg %s\n' % aliases[0])
2766 ui.write('hg %s\n' % aliases[0])
2767
2767
2768 # aliases
2768 # aliases
2769 if full and not ui.quiet and len(aliases) > 1:
2769 if full and not ui.quiet and len(aliases) > 1:
2770 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2770 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2771
2771
2772 # description
2772 # description
2773 doc = gettext(entry[0].__doc__)
2773 doc = gettext(entry[0].__doc__)
2774 if not doc:
2774 if not doc:
2775 doc = _("(no help text available)")
2775 doc = _("(no help text available)")
2776 if util.safehasattr(entry[0], 'definition'): # aliased command
2776 if util.safehasattr(entry[0], 'definition'): # aliased command
2777 if entry[0].definition.startswith('!'): # shell alias
2777 if entry[0].definition.startswith('!'): # shell alias
2778 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2778 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2779 else:
2779 else:
2780 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2780 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2781 if ui.quiet or not full:
2781 if ui.quiet or not full:
2782 doc = doc.splitlines()[0]
2782 doc = doc.splitlines()[0]
2783 keep = ui.verbose and ['verbose'] or []
2783 keep = ui.verbose and ['verbose'] or []
2784 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2784 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2785 ui.write("\n%s" % formatted)
2785 ui.write("\n%s" % formatted)
2786 if pruned:
2786 if pruned:
2787 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2787 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2788
2788
2789 if not ui.quiet:
2789 if not ui.quiet:
2790 # options
2790 # options
2791 if entry[1]:
2791 if entry[1]:
2792 optlist.append((_("options:\n"), entry[1]))
2792 optlist.append((_("options:\n"), entry[1]))
2793
2793
2794 addglobalopts(False)
2794 addglobalopts(False)
2795
2795
2796 # check if this command shadows a non-trivial (multi-line)
2796 # check if this command shadows a non-trivial (multi-line)
2797 # extension help text
2797 # extension help text
2798 try:
2798 try:
2799 mod = extensions.find(name)
2799 mod = extensions.find(name)
2800 doc = gettext(mod.__doc__) or ''
2800 doc = gettext(mod.__doc__) or ''
2801 if '\n' in doc.strip():
2801 if '\n' in doc.strip():
2802 msg = _('use "hg help -e %s" to show help for '
2802 msg = _('use "hg help -e %s" to show help for '
2803 'the %s extension') % (name, name)
2803 'the %s extension') % (name, name)
2804 ui.write('\n%s\n' % msg)
2804 ui.write('\n%s\n' % msg)
2805 except KeyError:
2805 except KeyError:
2806 pass
2806 pass
2807
2807
2808 ui.write(opttext(optlist, textwidth))
2809
2808 def helplist(select=None):
2810 def helplist(select=None):
2809 # list of commands
2811 # list of commands
2810 if name == "shortlist":
2812 if name == "shortlist":
2811 header = _('basic commands:\n\n')
2813 header = _('basic commands:\n\n')
2812 else:
2814 else:
2813 header = _('list of commands:\n\n')
2815 header = _('list of commands:\n\n')
2814
2816
2815 h = {}
2817 h = {}
2816 cmds = {}
2818 cmds = {}
2817 for c, e in table.iteritems():
2819 for c, e in table.iteritems():
2818 f = c.split("|", 1)[0]
2820 f = c.split("|", 1)[0]
2819 if select and not select(f):
2821 if select and not select(f):
2820 continue
2822 continue
2821 if (not select and name != 'shortlist' and
2823 if (not select and name != 'shortlist' and
2822 e[0].__module__ != __name__):
2824 e[0].__module__ != __name__):
2823 continue
2825 continue
2824 if name == "shortlist" and not f.startswith("^"):
2826 if name == "shortlist" and not f.startswith("^"):
2825 continue
2827 continue
2826 f = f.lstrip("^")
2828 f = f.lstrip("^")
2827 if not ui.debugflag and f.startswith("debug"):
2829 if not ui.debugflag and f.startswith("debug"):
2828 continue
2830 continue
2829 doc = e[0].__doc__
2831 doc = e[0].__doc__
2830 if doc and 'DEPRECATED' in doc and not ui.verbose:
2832 if doc and 'DEPRECATED' in doc and not ui.verbose:
2831 continue
2833 continue
2832 doc = gettext(doc)
2834 doc = gettext(doc)
2833 if not doc:
2835 if not doc:
2834 doc = _("(no help text available)")
2836 doc = _("(no help text available)")
2835 h[f] = doc.splitlines()[0].rstrip()
2837 h[f] = doc.splitlines()[0].rstrip()
2836 cmds[f] = c.lstrip("^")
2838 cmds[f] = c.lstrip("^")
2837
2839
2838 if not h:
2840 if not h:
2839 ui.status(_('no commands defined\n'))
2841 ui.status(_('no commands defined\n'))
2840 return
2842 return
2841
2843
2842 ui.status(header)
2844 ui.status(header)
2843 fns = sorted(h)
2845 fns = sorted(h)
2844 m = max(map(len, fns))
2846 m = max(map(len, fns))
2845 for f in fns:
2847 for f in fns:
2846 if ui.verbose:
2848 if ui.verbose:
2847 commands = cmds[f].replace("|",", ")
2849 commands = cmds[f].replace("|",", ")
2848 ui.write(" %s:\n %s\n"%(commands, h[f]))
2850 ui.write(" %s:\n %s\n"%(commands, h[f]))
2849 else:
2851 else:
2850 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2852 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2851 initindent=' %-*s ' % (m, f),
2853 initindent=' %-*s ' % (m, f),
2852 hangindent=' ' * (m + 4))))
2854 hangindent=' ' * (m + 4))))
2853
2855
2854 if not ui.quiet:
2856 if not ui.quiet:
2855 addglobalopts(True)
2857 addglobalopts(True)
2856
2858
2857 if not name:
2859 if not name:
2858 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2860 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2859 if text:
2861 if text:
2860 ui.write("\n%s" % minirst.format(text, textwidth))
2862 ui.write("\n%s" % minirst.format(text, textwidth))
2861
2863
2862 ui.write(_("\nadditional help topics:\n\n"))
2864 ui.write(_("\nadditional help topics:\n\n"))
2863 topics = []
2865 topics = []
2864 for names, header, doc in help.helptable:
2866 for names, header, doc in help.helptable:
2865 topics.append((sorted(names, key=len, reverse=True)[0], header))
2867 topics.append((sorted(names, key=len, reverse=True)[0], header))
2866 topics_len = max([len(s[0]) for s in topics])
2868 topics_len = max([len(s[0]) for s in topics])
2867 for t, desc in topics:
2869 for t, desc in topics:
2868 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2870 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2869
2871
2872 ui.write(opttext(optlist, textwidth))
2873
2870 def helptopic(name):
2874 def helptopic(name):
2871 for names, header, doc in help.helptable:
2875 for names, header, doc in help.helptable:
2872 if name in names:
2876 if name in names:
2873 break
2877 break
2874 else:
2878 else:
2875 raise error.UnknownCommand(name)
2879 raise error.UnknownCommand(name)
2876
2880
2877 # description
2881 # description
2878 if not doc:
2882 if not doc:
2879 doc = _("(no help text available)")
2883 doc = _("(no help text available)")
2880 if util.safehasattr(doc, '__call__'):
2884 if util.safehasattr(doc, '__call__'):
2881 doc = doc()
2885 doc = doc()
2882
2886
2883 ui.write("%s\n\n" % header)
2887 ui.write("%s\n\n" % header)
2884 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2888 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2885 try:
2889 try:
2886 cmdutil.findcmd(name, table)
2890 cmdutil.findcmd(name, table)
2887 ui.write(_('\nuse "hg help -c %s" to see help for '
2891 ui.write(_('\nuse "hg help -c %s" to see help for '
2888 'the %s command\n') % (name, name))
2892 'the %s command\n') % (name, name))
2889 except error.UnknownCommand:
2893 except error.UnknownCommand:
2890 pass
2894 pass
2891
2895
2892 def helpext(name):
2896 def helpext(name):
2893 try:
2897 try:
2894 mod = extensions.find(name)
2898 mod = extensions.find(name)
2895 doc = gettext(mod.__doc__) or _('no help text available')
2899 doc = gettext(mod.__doc__) or _('no help text available')
2896 except KeyError:
2900 except KeyError:
2897 mod = None
2901 mod = None
2898 doc = extensions.disabledext(name)
2902 doc = extensions.disabledext(name)
2899 if not doc:
2903 if not doc:
2900 raise error.UnknownCommand(name)
2904 raise error.UnknownCommand(name)
2901
2905
2902 if '\n' not in doc:
2906 if '\n' not in doc:
2903 head, tail = doc, ""
2907 head, tail = doc, ""
2904 else:
2908 else:
2905 head, tail = doc.split('\n', 1)
2909 head, tail = doc.split('\n', 1)
2906 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2910 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2907 if tail:
2911 if tail:
2908 ui.write(minirst.format(tail, textwidth))
2912 ui.write(minirst.format(tail, textwidth))
2909 ui.status('\n')
2913 ui.status('\n')
2910
2914
2911 if mod:
2915 if mod:
2912 try:
2916 try:
2913 ct = mod.cmdtable
2917 ct = mod.cmdtable
2914 except AttributeError:
2918 except AttributeError:
2915 ct = {}
2919 ct = {}
2916 modcmds = set([c.split('|', 1)[0] for c in ct])
2920 modcmds = set([c.split('|', 1)[0] for c in ct])
2917 helplist(modcmds.__contains__)
2921 helplist(modcmds.__contains__)
2918 else:
2922 else:
2919 ui.write(_('use "hg help extensions" for information on enabling '
2923 ui.write(_('use "hg help extensions" for information on enabling '
2920 'extensions\n'))
2924 'extensions\n'))
2921
2925
2922 def helpextcmd(name):
2926 def helpextcmd(name):
2923 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2927 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2924 doc = gettext(mod.__doc__).splitlines()[0]
2928 doc = gettext(mod.__doc__).splitlines()[0]
2925
2929
2926 msg = help.listexts(_("'%s' is provided by the following "
2930 msg = help.listexts(_("'%s' is provided by the following "
2927 "extension:") % cmd, {ext: doc}, indent=4)
2931 "extension:") % cmd, {ext: doc}, indent=4)
2928 ui.write(minirst.format(msg, textwidth))
2932 ui.write(minirst.format(msg, textwidth))
2929 ui.write('\n')
2933 ui.write('\n')
2930 ui.write(_('use "hg help extensions" for information on enabling '
2934 ui.write(_('use "hg help extensions" for information on enabling '
2931 'extensions\n'))
2935 'extensions\n'))
2932
2936
2933 if name and name != 'shortlist':
2937 if name and name != 'shortlist':
2934 i = None
2938 i = None
2935 if unknowncmd:
2939 if unknowncmd:
2936 queries = (helpextcmd,)
2940 queries = (helpextcmd,)
2937 elif opts.get('extension'):
2941 elif opts.get('extension'):
2938 queries = (helpext,)
2942 queries = (helpext,)
2939 elif opts.get('command'):
2943 elif opts.get('command'):
2940 queries = (helpcmd,)
2944 queries = (helpcmd,)
2941 else:
2945 else:
2942 queries = (helptopic, helpcmd, helpext, helpextcmd)
2946 queries = (helptopic, helpcmd, helpext, helpextcmd)
2943 for f in queries:
2947 for f in queries:
2944 try:
2948 try:
2945 f(name)
2949 f(name)
2946 i = None
2950 i = None
2947 break
2951 break
2948 except error.UnknownCommand, inst:
2952 except error.UnknownCommand, inst:
2949 i = inst
2953 i = inst
2950 if i:
2954 if i:
2951 raise i
2955 raise i
2952 else:
2956 else:
2953 # program name
2957 # program name
2954 ui.status(_("Mercurial Distributed SCM\n"))
2958 ui.status(_("Mercurial Distributed SCM\n"))
2955 ui.status('\n')
2959 ui.status('\n')
2956 helplist()
2960 helplist()
2957
2961
2958 ui.write(opttext(optlist, textwidth))
2959
2962
2960 @command('identify|id',
2963 @command('identify|id',
2961 [('r', 'rev', '',
2964 [('r', 'rev', '',
2962 _('identify the specified revision'), _('REV')),
2965 _('identify the specified revision'), _('REV')),
2963 ('n', 'num', None, _('show local revision number')),
2966 ('n', 'num', None, _('show local revision number')),
2964 ('i', 'id', None, _('show global revision id')),
2967 ('i', 'id', None, _('show global revision id')),
2965 ('b', 'branch', None, _('show branch')),
2968 ('b', 'branch', None, _('show branch')),
2966 ('t', 'tags', None, _('show tags')),
2969 ('t', 'tags', None, _('show tags')),
2967 ('B', 'bookmarks', None, _('show bookmarks'))],
2970 ('B', 'bookmarks', None, _('show bookmarks'))],
2968 _('[-nibtB] [-r REV] [SOURCE]'))
2971 _('[-nibtB] [-r REV] [SOURCE]'))
2969 def identify(ui, repo, source=None, rev=None,
2972 def identify(ui, repo, source=None, rev=None,
2970 num=None, id=None, branch=None, tags=None, bookmarks=None):
2973 num=None, id=None, branch=None, tags=None, bookmarks=None):
2971 """identify the working copy or specified revision
2974 """identify the working copy or specified revision
2972
2975
2973 Print a summary identifying the repository state at REV using one or
2976 Print a summary identifying the repository state at REV using one or
2974 two parent hash identifiers, followed by a "+" if the working
2977 two parent hash identifiers, followed by a "+" if the working
2975 directory has uncommitted changes, the branch name (if not default),
2978 directory has uncommitted changes, the branch name (if not default),
2976 a list of tags, and a list of bookmarks.
2979 a list of tags, and a list of bookmarks.
2977
2980
2978 When REV is not given, print a summary of the current state of the
2981 When REV is not given, print a summary of the current state of the
2979 repository.
2982 repository.
2980
2983
2981 Specifying a path to a repository root or Mercurial bundle will
2984 Specifying a path to a repository root or Mercurial bundle will
2982 cause lookup to operate on that repository/bundle.
2985 cause lookup to operate on that repository/bundle.
2983
2986
2984 .. container:: verbose
2987 .. container:: verbose
2985
2988
2986 Examples:
2989 Examples:
2987
2990
2988 - generate a build identifier for the working directory::
2991 - generate a build identifier for the working directory::
2989
2992
2990 hg id --id > build-id.dat
2993 hg id --id > build-id.dat
2991
2994
2992 - find the revision corresponding to a tag::
2995 - find the revision corresponding to a tag::
2993
2996
2994 hg id -n -r 1.3
2997 hg id -n -r 1.3
2995
2998
2996 - check the most recent revision of a remote repository::
2999 - check the most recent revision of a remote repository::
2997
3000
2998 hg id -r tip http://selenic.com/hg/
3001 hg id -r tip http://selenic.com/hg/
2999
3002
3000 Returns 0 if successful.
3003 Returns 0 if successful.
3001 """
3004 """
3002
3005
3003 if not repo and not source:
3006 if not repo and not source:
3004 raise util.Abort(_("there is no Mercurial repository here "
3007 raise util.Abort(_("there is no Mercurial repository here "
3005 "(.hg not found)"))
3008 "(.hg not found)"))
3006
3009
3007 hexfunc = ui.debugflag and hex or short
3010 hexfunc = ui.debugflag and hex or short
3008 default = not (num or id or branch or tags or bookmarks)
3011 default = not (num or id or branch or tags or bookmarks)
3009 output = []
3012 output = []
3010 revs = []
3013 revs = []
3011
3014
3012 if source:
3015 if source:
3013 source, branches = hg.parseurl(ui.expandpath(source))
3016 source, branches = hg.parseurl(ui.expandpath(source))
3014 repo = hg.peer(ui, {}, source)
3017 repo = hg.peer(ui, {}, source)
3015 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3018 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3016
3019
3017 if not repo.local():
3020 if not repo.local():
3018 if num or branch or tags:
3021 if num or branch or tags:
3019 raise util.Abort(
3022 raise util.Abort(
3020 _("can't query remote revision number, branch, or tags"))
3023 _("can't query remote revision number, branch, or tags"))
3021 if not rev and revs:
3024 if not rev and revs:
3022 rev = revs[0]
3025 rev = revs[0]
3023 if not rev:
3026 if not rev:
3024 rev = "tip"
3027 rev = "tip"
3025
3028
3026 remoterev = repo.lookup(rev)
3029 remoterev = repo.lookup(rev)
3027 if default or id:
3030 if default or id:
3028 output = [hexfunc(remoterev)]
3031 output = [hexfunc(remoterev)]
3029
3032
3030 def getbms():
3033 def getbms():
3031 bms = []
3034 bms = []
3032
3035
3033 if 'bookmarks' in repo.listkeys('namespaces'):
3036 if 'bookmarks' in repo.listkeys('namespaces'):
3034 hexremoterev = hex(remoterev)
3037 hexremoterev = hex(remoterev)
3035 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3038 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3036 if bmr == hexremoterev]
3039 if bmr == hexremoterev]
3037
3040
3038 return bms
3041 return bms
3039
3042
3040 if bookmarks:
3043 if bookmarks:
3041 output.extend(getbms())
3044 output.extend(getbms())
3042 elif default and not ui.quiet:
3045 elif default and not ui.quiet:
3043 # multiple bookmarks for a single parent separated by '/'
3046 # multiple bookmarks for a single parent separated by '/'
3044 bm = '/'.join(getbms())
3047 bm = '/'.join(getbms())
3045 if bm:
3048 if bm:
3046 output.append(bm)
3049 output.append(bm)
3047 else:
3050 else:
3048 if not rev:
3051 if not rev:
3049 ctx = repo[None]
3052 ctx = repo[None]
3050 parents = ctx.parents()
3053 parents = ctx.parents()
3051 changed = ""
3054 changed = ""
3052 if default or id or num:
3055 if default or id or num:
3053 changed = util.any(repo.status()) and "+" or ""
3056 changed = util.any(repo.status()) and "+" or ""
3054 if default or id:
3057 if default or id:
3055 output = ["%s%s" %
3058 output = ["%s%s" %
3056 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3059 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3057 if num:
3060 if num:
3058 output.append("%s%s" %
3061 output.append("%s%s" %
3059 ('+'.join([str(p.rev()) for p in parents]), changed))
3062 ('+'.join([str(p.rev()) for p in parents]), changed))
3060 else:
3063 else:
3061 ctx = scmutil.revsingle(repo, rev)
3064 ctx = scmutil.revsingle(repo, rev)
3062 if default or id:
3065 if default or id:
3063 output = [hexfunc(ctx.node())]
3066 output = [hexfunc(ctx.node())]
3064 if num:
3067 if num:
3065 output.append(str(ctx.rev()))
3068 output.append(str(ctx.rev()))
3066
3069
3067 if default and not ui.quiet:
3070 if default and not ui.quiet:
3068 b = ctx.branch()
3071 b = ctx.branch()
3069 if b != 'default':
3072 if b != 'default':
3070 output.append("(%s)" % b)
3073 output.append("(%s)" % b)
3071
3074
3072 # multiple tags for a single parent separated by '/'
3075 # multiple tags for a single parent separated by '/'
3073 t = '/'.join(ctx.tags())
3076 t = '/'.join(ctx.tags())
3074 if t:
3077 if t:
3075 output.append(t)
3078 output.append(t)
3076
3079
3077 # multiple bookmarks for a single parent separated by '/'
3080 # multiple bookmarks for a single parent separated by '/'
3078 bm = '/'.join(ctx.bookmarks())
3081 bm = '/'.join(ctx.bookmarks())
3079 if bm:
3082 if bm:
3080 output.append(bm)
3083 output.append(bm)
3081 else:
3084 else:
3082 if branch:
3085 if branch:
3083 output.append(ctx.branch())
3086 output.append(ctx.branch())
3084
3087
3085 if tags:
3088 if tags:
3086 output.extend(ctx.tags())
3089 output.extend(ctx.tags())
3087
3090
3088 if bookmarks:
3091 if bookmarks:
3089 output.extend(ctx.bookmarks())
3092 output.extend(ctx.bookmarks())
3090
3093
3091 ui.write("%s\n" % ' '.join(output))
3094 ui.write("%s\n" % ' '.join(output))
3092
3095
3093 @command('import|patch',
3096 @command('import|patch',
3094 [('p', 'strip', 1,
3097 [('p', 'strip', 1,
3095 _('directory strip option for patch. This has the same '
3098 _('directory strip option for patch. This has the same '
3096 'meaning as the corresponding patch option'), _('NUM')),
3099 'meaning as the corresponding patch option'), _('NUM')),
3097 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3100 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3098 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3101 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3099 ('', 'no-commit', None,
3102 ('', 'no-commit', None,
3100 _("don't commit, just update the working directory")),
3103 _("don't commit, just update the working directory")),
3101 ('', 'bypass', None,
3104 ('', 'bypass', None,
3102 _("apply patch without touching the working directory")),
3105 _("apply patch without touching the working directory")),
3103 ('', 'exact', None,
3106 ('', 'exact', None,
3104 _('apply patch to the nodes from which it was generated')),
3107 _('apply patch to the nodes from which it was generated')),
3105 ('', 'import-branch', None,
3108 ('', 'import-branch', None,
3106 _('use any branch information in patch (implied by --exact)'))] +
3109 _('use any branch information in patch (implied by --exact)'))] +
3107 commitopts + commitopts2 + similarityopts,
3110 commitopts + commitopts2 + similarityopts,
3108 _('[OPTION]... PATCH...'))
3111 _('[OPTION]... PATCH...'))
3109 def import_(ui, repo, patch1, *patches, **opts):
3112 def import_(ui, repo, patch1, *patches, **opts):
3110 """import an ordered set of patches
3113 """import an ordered set of patches
3111
3114
3112 Import a list of patches and commit them individually (unless
3115 Import a list of patches and commit them individually (unless
3113 --no-commit is specified).
3116 --no-commit is specified).
3114
3117
3115 If there are outstanding changes in the working directory, import
3118 If there are outstanding changes in the working directory, import
3116 will abort unless given the -f/--force flag.
3119 will abort unless given the -f/--force flag.
3117
3120
3118 You can import a patch straight from a mail message. Even patches
3121 You can import a patch straight from a mail message. Even patches
3119 as attachments work (to use the body part, it must have type
3122 as attachments work (to use the body part, it must have type
3120 text/plain or text/x-patch). From and Subject headers of email
3123 text/plain or text/x-patch). From and Subject headers of email
3121 message are used as default committer and commit message. All
3124 message are used as default committer and commit message. All
3122 text/plain body parts before first diff are added to commit
3125 text/plain body parts before first diff are added to commit
3123 message.
3126 message.
3124
3127
3125 If the imported patch was generated by :hg:`export`, user and
3128 If the imported patch was generated by :hg:`export`, user and
3126 description from patch override values from message headers and
3129 description from patch override values from message headers and
3127 body. Values given on command line with -m/--message and -u/--user
3130 body. Values given on command line with -m/--message and -u/--user
3128 override these.
3131 override these.
3129
3132
3130 If --exact is specified, import will set the working directory to
3133 If --exact is specified, import will set the working directory to
3131 the parent of each patch before applying it, and will abort if the
3134 the parent of each patch before applying it, and will abort if the
3132 resulting changeset has a different ID than the one recorded in
3135 resulting changeset has a different ID than the one recorded in
3133 the patch. This may happen due to character set problems or other
3136 the patch. This may happen due to character set problems or other
3134 deficiencies in the text patch format.
3137 deficiencies in the text patch format.
3135
3138
3136 Use --bypass to apply and commit patches directly to the
3139 Use --bypass to apply and commit patches directly to the
3137 repository, not touching the working directory. Without --exact,
3140 repository, not touching the working directory. Without --exact,
3138 patches will be applied on top of the working directory parent
3141 patches will be applied on top of the working directory parent
3139 revision.
3142 revision.
3140
3143
3141 With -s/--similarity, hg will attempt to discover renames and
3144 With -s/--similarity, hg will attempt to discover renames and
3142 copies in the patch in the same way as 'addremove'.
3145 copies in the patch in the same way as 'addremove'.
3143
3146
3144 To read a patch from standard input, use "-" as the patch name. If
3147 To read a patch from standard input, use "-" as the patch name. If
3145 a URL is specified, the patch will be downloaded from it.
3148 a URL is specified, the patch will be downloaded from it.
3146 See :hg:`help dates` for a list of formats valid for -d/--date.
3149 See :hg:`help dates` for a list of formats valid for -d/--date.
3147
3150
3148 .. container:: verbose
3151 .. container:: verbose
3149
3152
3150 Examples:
3153 Examples:
3151
3154
3152 - import a traditional patch from a website and detect renames::
3155 - import a traditional patch from a website and detect renames::
3153
3156
3154 hg import -s 80 http://example.com/bugfix.patch
3157 hg import -s 80 http://example.com/bugfix.patch
3155
3158
3156 - import a changeset from an hgweb server::
3159 - import a changeset from an hgweb server::
3157
3160
3158 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3161 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3159
3162
3160 - import all the patches in an Unix-style mbox::
3163 - import all the patches in an Unix-style mbox::
3161
3164
3162 hg import incoming-patches.mbox
3165 hg import incoming-patches.mbox
3163
3166
3164 - attempt to exactly restore an exported changeset (not always
3167 - attempt to exactly restore an exported changeset (not always
3165 possible)::
3168 possible)::
3166
3169
3167 hg import --exact proposed-fix.patch
3170 hg import --exact proposed-fix.patch
3168
3171
3169 Returns 0 on success.
3172 Returns 0 on success.
3170 """
3173 """
3171 patches = (patch1,) + patches
3174 patches = (patch1,) + patches
3172
3175
3173 date = opts.get('date')
3176 date = opts.get('date')
3174 if date:
3177 if date:
3175 opts['date'] = util.parsedate(date)
3178 opts['date'] = util.parsedate(date)
3176
3179
3177 update = not opts.get('bypass')
3180 update = not opts.get('bypass')
3178 if not update and opts.get('no_commit'):
3181 if not update and opts.get('no_commit'):
3179 raise util.Abort(_('cannot use --no-commit with --bypass'))
3182 raise util.Abort(_('cannot use --no-commit with --bypass'))
3180 try:
3183 try:
3181 sim = float(opts.get('similarity') or 0)
3184 sim = float(opts.get('similarity') or 0)
3182 except ValueError:
3185 except ValueError:
3183 raise util.Abort(_('similarity must be a number'))
3186 raise util.Abort(_('similarity must be a number'))
3184 if sim < 0 or sim > 100:
3187 if sim < 0 or sim > 100:
3185 raise util.Abort(_('similarity must be between 0 and 100'))
3188 raise util.Abort(_('similarity must be between 0 and 100'))
3186 if sim and not update:
3189 if sim and not update:
3187 raise util.Abort(_('cannot use --similarity with --bypass'))
3190 raise util.Abort(_('cannot use --similarity with --bypass'))
3188
3191
3189 if (opts.get('exact') or not opts.get('force')) and update:
3192 if (opts.get('exact') or not opts.get('force')) and update:
3190 cmdutil.bailifchanged(repo)
3193 cmdutil.bailifchanged(repo)
3191
3194
3192 d = opts["base"]
3195 d = opts["base"]
3193 strip = opts["strip"]
3196 strip = opts["strip"]
3194 wlock = lock = None
3197 wlock = lock = None
3195 msgs = []
3198 msgs = []
3196
3199
3197 def checkexact(repo, n, nodeid):
3200 def checkexact(repo, n, nodeid):
3198 if opts.get('exact') and hex(n) != nodeid:
3201 if opts.get('exact') and hex(n) != nodeid:
3199 repo.rollback()
3202 repo.rollback()
3200 raise util.Abort(_('patch is damaged or loses information'))
3203 raise util.Abort(_('patch is damaged or loses information'))
3201
3204
3202 def tryone(ui, hunk, parents):
3205 def tryone(ui, hunk, parents):
3203 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3206 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3204 patch.extract(ui, hunk)
3207 patch.extract(ui, hunk)
3205
3208
3206 if not tmpname:
3209 if not tmpname:
3207 return None
3210 return None
3208 commitid = _('to working directory')
3211 commitid = _('to working directory')
3209
3212
3210 try:
3213 try:
3211 cmdline_message = cmdutil.logmessage(ui, opts)
3214 cmdline_message = cmdutil.logmessage(ui, opts)
3212 if cmdline_message:
3215 if cmdline_message:
3213 # pickup the cmdline msg
3216 # pickup the cmdline msg
3214 message = cmdline_message
3217 message = cmdline_message
3215 elif message:
3218 elif message:
3216 # pickup the patch msg
3219 # pickup the patch msg
3217 message = message.strip()
3220 message = message.strip()
3218 else:
3221 else:
3219 # launch the editor
3222 # launch the editor
3220 message = None
3223 message = None
3221 ui.debug('message:\n%s\n' % message)
3224 ui.debug('message:\n%s\n' % message)
3222
3225
3223 if len(parents) == 1:
3226 if len(parents) == 1:
3224 parents.append(repo[nullid])
3227 parents.append(repo[nullid])
3225 if opts.get('exact'):
3228 if opts.get('exact'):
3226 if not nodeid or not p1:
3229 if not nodeid or not p1:
3227 raise util.Abort(_('not a Mercurial patch'))
3230 raise util.Abort(_('not a Mercurial patch'))
3228 p1 = repo[p1]
3231 p1 = repo[p1]
3229 p2 = repo[p2 or nullid]
3232 p2 = repo[p2 or nullid]
3230 elif p2:
3233 elif p2:
3231 try:
3234 try:
3232 p1 = repo[p1]
3235 p1 = repo[p1]
3233 p2 = repo[p2]
3236 p2 = repo[p2]
3234 except error.RepoError:
3237 except error.RepoError:
3235 p1, p2 = parents
3238 p1, p2 = parents
3236 else:
3239 else:
3237 p1, p2 = parents
3240 p1, p2 = parents
3238
3241
3239 n = None
3242 n = None
3240 if update:
3243 if update:
3241 if opts.get('exact') and p1 != parents[0]:
3244 if opts.get('exact') and p1 != parents[0]:
3242 hg.clean(repo, p1.node())
3245 hg.clean(repo, p1.node())
3243 if p1 != parents[0] and p2 != parents[1]:
3246 if p1 != parents[0] and p2 != parents[1]:
3244 repo.dirstate.setparents(p1.node(), p2.node())
3247 repo.dirstate.setparents(p1.node(), p2.node())
3245
3248
3246 if opts.get('exact') or opts.get('import_branch'):
3249 if opts.get('exact') or opts.get('import_branch'):
3247 repo.dirstate.setbranch(branch or 'default')
3250 repo.dirstate.setbranch(branch or 'default')
3248
3251
3249 files = set()
3252 files = set()
3250 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3253 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3251 eolmode=None, similarity=sim / 100.0)
3254 eolmode=None, similarity=sim / 100.0)
3252 files = list(files)
3255 files = list(files)
3253 if opts.get('no_commit'):
3256 if opts.get('no_commit'):
3254 if message:
3257 if message:
3255 msgs.append(message)
3258 msgs.append(message)
3256 else:
3259 else:
3257 if opts.get('exact'):
3260 if opts.get('exact'):
3258 m = None
3261 m = None
3259 else:
3262 else:
3260 m = scmutil.matchfiles(repo, files or [])
3263 m = scmutil.matchfiles(repo, files or [])
3261 n = repo.commit(message, opts.get('user') or user,
3264 n = repo.commit(message, opts.get('user') or user,
3262 opts.get('date') or date, match=m,
3265 opts.get('date') or date, match=m,
3263 editor=cmdutil.commiteditor)
3266 editor=cmdutil.commiteditor)
3264 checkexact(repo, n, nodeid)
3267 checkexact(repo, n, nodeid)
3265 # Force a dirstate write so that the next transaction
3268 # Force a dirstate write so that the next transaction
3266 # backups an up-to-date file.
3269 # backups an up-to-date file.
3267 repo.dirstate.write()
3270 repo.dirstate.write()
3268 else:
3271 else:
3269 if opts.get('exact') or opts.get('import_branch'):
3272 if opts.get('exact') or opts.get('import_branch'):
3270 branch = branch or 'default'
3273 branch = branch or 'default'
3271 else:
3274 else:
3272 branch = p1.branch()
3275 branch = p1.branch()
3273 store = patch.filestore()
3276 store = patch.filestore()
3274 try:
3277 try:
3275 files = set()
3278 files = set()
3276 try:
3279 try:
3277 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3280 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3278 files, eolmode=None)
3281 files, eolmode=None)
3279 except patch.PatchError, e:
3282 except patch.PatchError, e:
3280 raise util.Abort(str(e))
3283 raise util.Abort(str(e))
3281 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3284 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3282 message,
3285 message,
3283 opts.get('user') or user,
3286 opts.get('user') or user,
3284 opts.get('date') or date,
3287 opts.get('date') or date,
3285 branch, files, store,
3288 branch, files, store,
3286 editor=cmdutil.commiteditor)
3289 editor=cmdutil.commiteditor)
3287 repo.savecommitmessage(memctx.description())
3290 repo.savecommitmessage(memctx.description())
3288 n = memctx.commit()
3291 n = memctx.commit()
3289 checkexact(repo, n, nodeid)
3292 checkexact(repo, n, nodeid)
3290 finally:
3293 finally:
3291 store.close()
3294 store.close()
3292 if n:
3295 if n:
3293 commitid = short(n)
3296 commitid = short(n)
3294 return commitid
3297 return commitid
3295 finally:
3298 finally:
3296 os.unlink(tmpname)
3299 os.unlink(tmpname)
3297
3300
3298 try:
3301 try:
3299 wlock = repo.wlock()
3302 wlock = repo.wlock()
3300 lock = repo.lock()
3303 lock = repo.lock()
3301 parents = repo.parents()
3304 parents = repo.parents()
3302 lastcommit = None
3305 lastcommit = None
3303 for p in patches:
3306 for p in patches:
3304 pf = os.path.join(d, p)
3307 pf = os.path.join(d, p)
3305
3308
3306 if pf == '-':
3309 if pf == '-':
3307 ui.status(_("applying patch from stdin\n"))
3310 ui.status(_("applying patch from stdin\n"))
3308 pf = ui.fin
3311 pf = ui.fin
3309 else:
3312 else:
3310 ui.status(_("applying %s\n") % p)
3313 ui.status(_("applying %s\n") % p)
3311 pf = url.open(ui, pf)
3314 pf = url.open(ui, pf)
3312
3315
3313 haspatch = False
3316 haspatch = False
3314 for hunk in patch.split(pf):
3317 for hunk in patch.split(pf):
3315 commitid = tryone(ui, hunk, parents)
3318 commitid = tryone(ui, hunk, parents)
3316 if commitid:
3319 if commitid:
3317 haspatch = True
3320 haspatch = True
3318 if lastcommit:
3321 if lastcommit:
3319 ui.status(_('applied %s\n') % lastcommit)
3322 ui.status(_('applied %s\n') % lastcommit)
3320 lastcommit = commitid
3323 lastcommit = commitid
3321 if update or opts.get('exact'):
3324 if update or opts.get('exact'):
3322 parents = repo.parents()
3325 parents = repo.parents()
3323 else:
3326 else:
3324 parents = [repo[commitid]]
3327 parents = [repo[commitid]]
3325
3328
3326 if not haspatch:
3329 if not haspatch:
3327 raise util.Abort(_('no diffs found'))
3330 raise util.Abort(_('no diffs found'))
3328
3331
3329 if msgs:
3332 if msgs:
3330 repo.savecommitmessage('\n* * *\n'.join(msgs))
3333 repo.savecommitmessage('\n* * *\n'.join(msgs))
3331 finally:
3334 finally:
3332 release(lock, wlock)
3335 release(lock, wlock)
3333
3336
3334 @command('incoming|in',
3337 @command('incoming|in',
3335 [('f', 'force', None,
3338 [('f', 'force', None,
3336 _('run even if remote repository is unrelated')),
3339 _('run even if remote repository is unrelated')),
3337 ('n', 'newest-first', None, _('show newest record first')),
3340 ('n', 'newest-first', None, _('show newest record first')),
3338 ('', 'bundle', '',
3341 ('', 'bundle', '',
3339 _('file to store the bundles into'), _('FILE')),
3342 _('file to store the bundles into'), _('FILE')),
3340 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3343 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3341 ('B', 'bookmarks', False, _("compare bookmarks")),
3344 ('B', 'bookmarks', False, _("compare bookmarks")),
3342 ('b', 'branch', [],
3345 ('b', 'branch', [],
3343 _('a specific branch you would like to pull'), _('BRANCH')),
3346 _('a specific branch you would like to pull'), _('BRANCH')),
3344 ] + logopts + remoteopts + subrepoopts,
3347 ] + logopts + remoteopts + subrepoopts,
3345 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3348 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3346 def incoming(ui, repo, source="default", **opts):
3349 def incoming(ui, repo, source="default", **opts):
3347 """show new changesets found in source
3350 """show new changesets found in source
3348
3351
3349 Show new changesets found in the specified path/URL or the default
3352 Show new changesets found in the specified path/URL or the default
3350 pull location. These are the changesets that would have been pulled
3353 pull location. These are the changesets that would have been pulled
3351 if a pull at the time you issued this command.
3354 if a pull at the time you issued this command.
3352
3355
3353 For remote repository, using --bundle avoids downloading the
3356 For remote repository, using --bundle avoids downloading the
3354 changesets twice if the incoming is followed by a pull.
3357 changesets twice if the incoming is followed by a pull.
3355
3358
3356 See pull for valid source format details.
3359 See pull for valid source format details.
3357
3360
3358 Returns 0 if there are incoming changes, 1 otherwise.
3361 Returns 0 if there are incoming changes, 1 otherwise.
3359 """
3362 """
3360 if opts.get('bundle') and opts.get('subrepos'):
3363 if opts.get('bundle') and opts.get('subrepos'):
3361 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3364 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3362
3365
3363 if opts.get('bookmarks'):
3366 if opts.get('bookmarks'):
3364 source, branches = hg.parseurl(ui.expandpath(source),
3367 source, branches = hg.parseurl(ui.expandpath(source),
3365 opts.get('branch'))
3368 opts.get('branch'))
3366 other = hg.peer(repo, opts, source)
3369 other = hg.peer(repo, opts, source)
3367 if 'bookmarks' not in other.listkeys('namespaces'):
3370 if 'bookmarks' not in other.listkeys('namespaces'):
3368 ui.warn(_("remote doesn't support bookmarks\n"))
3371 ui.warn(_("remote doesn't support bookmarks\n"))
3369 return 0
3372 return 0
3370 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3373 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3371 return bookmarks.diff(ui, repo, other)
3374 return bookmarks.diff(ui, repo, other)
3372
3375
3373 repo._subtoppath = ui.expandpath(source)
3376 repo._subtoppath = ui.expandpath(source)
3374 try:
3377 try:
3375 return hg.incoming(ui, repo, source, opts)
3378 return hg.incoming(ui, repo, source, opts)
3376 finally:
3379 finally:
3377 del repo._subtoppath
3380 del repo._subtoppath
3378
3381
3379
3382
3380 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3383 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3381 def init(ui, dest=".", **opts):
3384 def init(ui, dest=".", **opts):
3382 """create a new repository in the given directory
3385 """create a new repository in the given directory
3383
3386
3384 Initialize a new repository in the given directory. If the given
3387 Initialize a new repository in the given directory. If the given
3385 directory does not exist, it will be created.
3388 directory does not exist, it will be created.
3386
3389
3387 If no directory is given, the current directory is used.
3390 If no directory is given, the current directory is used.
3388
3391
3389 It is possible to specify an ``ssh://`` URL as the destination.
3392 It is possible to specify an ``ssh://`` URL as the destination.
3390 See :hg:`help urls` for more information.
3393 See :hg:`help urls` for more information.
3391
3394
3392 Returns 0 on success.
3395 Returns 0 on success.
3393 """
3396 """
3394 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3397 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3395
3398
3396 @command('locate',
3399 @command('locate',
3397 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3400 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3398 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3401 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3399 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3402 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3400 ] + walkopts,
3403 ] + walkopts,
3401 _('[OPTION]... [PATTERN]...'))
3404 _('[OPTION]... [PATTERN]...'))
3402 def locate(ui, repo, *pats, **opts):
3405 def locate(ui, repo, *pats, **opts):
3403 """locate files matching specific patterns
3406 """locate files matching specific patterns
3404
3407
3405 Print files under Mercurial control in the working directory whose
3408 Print files under Mercurial control in the working directory whose
3406 names match the given patterns.
3409 names match the given patterns.
3407
3410
3408 By default, this command searches all directories in the working
3411 By default, this command searches all directories in the working
3409 directory. To search just the current directory and its
3412 directory. To search just the current directory and its
3410 subdirectories, use "--include .".
3413 subdirectories, use "--include .".
3411
3414
3412 If no patterns are given to match, this command prints the names
3415 If no patterns are given to match, this command prints the names
3413 of all files under Mercurial control in the working directory.
3416 of all files under Mercurial control in the working directory.
3414
3417
3415 If you want to feed the output of this command into the "xargs"
3418 If you want to feed the output of this command into the "xargs"
3416 command, use the -0 option to both this command and "xargs". This
3419 command, use the -0 option to both this command and "xargs". This
3417 will avoid the problem of "xargs" treating single filenames that
3420 will avoid the problem of "xargs" treating single filenames that
3418 contain whitespace as multiple filenames.
3421 contain whitespace as multiple filenames.
3419
3422
3420 Returns 0 if a match is found, 1 otherwise.
3423 Returns 0 if a match is found, 1 otherwise.
3421 """
3424 """
3422 end = opts.get('print0') and '\0' or '\n'
3425 end = opts.get('print0') and '\0' or '\n'
3423 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3426 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3424
3427
3425 ret = 1
3428 ret = 1
3426 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3429 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3427 m.bad = lambda x, y: False
3430 m.bad = lambda x, y: False
3428 for abs in repo[rev].walk(m):
3431 for abs in repo[rev].walk(m):
3429 if not rev and abs not in repo.dirstate:
3432 if not rev and abs not in repo.dirstate:
3430 continue
3433 continue
3431 if opts.get('fullpath'):
3434 if opts.get('fullpath'):
3432 ui.write(repo.wjoin(abs), end)
3435 ui.write(repo.wjoin(abs), end)
3433 else:
3436 else:
3434 ui.write(((pats and m.rel(abs)) or abs), end)
3437 ui.write(((pats and m.rel(abs)) or abs), end)
3435 ret = 0
3438 ret = 0
3436
3439
3437 return ret
3440 return ret
3438
3441
3439 @command('^log|history',
3442 @command('^log|history',
3440 [('f', 'follow', None,
3443 [('f', 'follow', None,
3441 _('follow changeset history, or file history across copies and renames')),
3444 _('follow changeset history, or file history across copies and renames')),
3442 ('', 'follow-first', None,
3445 ('', 'follow-first', None,
3443 _('only follow the first parent of merge changesets')),
3446 _('only follow the first parent of merge changesets')),
3444 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3447 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3445 ('C', 'copies', None, _('show copied files')),
3448 ('C', 'copies', None, _('show copied files')),
3446 ('k', 'keyword', [],
3449 ('k', 'keyword', [],
3447 _('do case-insensitive search for a given text'), _('TEXT')),
3450 _('do case-insensitive search for a given text'), _('TEXT')),
3448 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3451 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3449 ('', 'removed', None, _('include revisions where files were removed')),
3452 ('', 'removed', None, _('include revisions where files were removed')),
3450 ('m', 'only-merges', None, _('show only merges')),
3453 ('m', 'only-merges', None, _('show only merges')),
3451 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3454 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3452 ('', 'only-branch', [],
3455 ('', 'only-branch', [],
3453 _('show only changesets within the given named branch (DEPRECATED)'),
3456 _('show only changesets within the given named branch (DEPRECATED)'),
3454 _('BRANCH')),
3457 _('BRANCH')),
3455 ('b', 'branch', [],
3458 ('b', 'branch', [],
3456 _('show changesets within the given named branch'), _('BRANCH')),
3459 _('show changesets within the given named branch'), _('BRANCH')),
3457 ('P', 'prune', [],
3460 ('P', 'prune', [],
3458 _('do not display revision or any of its ancestors'), _('REV')),
3461 _('do not display revision or any of its ancestors'), _('REV')),
3459 ('', 'hidden', False, _('show hidden changesets')),
3462 ('', 'hidden', False, _('show hidden changesets')),
3460 ] + logopts + walkopts,
3463 ] + logopts + walkopts,
3461 _('[OPTION]... [FILE]'))
3464 _('[OPTION]... [FILE]'))
3462 def log(ui, repo, *pats, **opts):
3465 def log(ui, repo, *pats, **opts):
3463 """show revision history of entire repository or files
3466 """show revision history of entire repository or files
3464
3467
3465 Print the revision history of the specified files or the entire
3468 Print the revision history of the specified files or the entire
3466 project.
3469 project.
3467
3470
3468 If no revision range is specified, the default is ``tip:0`` unless
3471 If no revision range is specified, the default is ``tip:0`` unless
3469 --follow is set, in which case the working directory parent is
3472 --follow is set, in which case the working directory parent is
3470 used as the starting revision.
3473 used as the starting revision.
3471
3474
3472 File history is shown without following rename or copy history of
3475 File history is shown without following rename or copy history of
3473 files. Use -f/--follow with a filename to follow history across
3476 files. Use -f/--follow with a filename to follow history across
3474 renames and copies. --follow without a filename will only show
3477 renames and copies. --follow without a filename will only show
3475 ancestors or descendants of the starting revision.
3478 ancestors or descendants of the starting revision.
3476
3479
3477 By default this command prints revision number and changeset id,
3480 By default this command prints revision number and changeset id,
3478 tags, non-trivial parents, user, date and time, and a summary for
3481 tags, non-trivial parents, user, date and time, and a summary for
3479 each commit. When the -v/--verbose switch is used, the list of
3482 each commit. When the -v/--verbose switch is used, the list of
3480 changed files and full commit message are shown.
3483 changed files and full commit message are shown.
3481
3484
3482 .. note::
3485 .. note::
3483 log -p/--patch may generate unexpected diff output for merge
3486 log -p/--patch may generate unexpected diff output for merge
3484 changesets, as it will only compare the merge changeset against
3487 changesets, as it will only compare the merge changeset against
3485 its first parent. Also, only files different from BOTH parents
3488 its first parent. Also, only files different from BOTH parents
3486 will appear in files:.
3489 will appear in files:.
3487
3490
3488 .. note::
3491 .. note::
3489 for performance reasons, log FILE may omit duplicate changes
3492 for performance reasons, log FILE may omit duplicate changes
3490 made on branches and will not show deletions. To see all
3493 made on branches and will not show deletions. To see all
3491 changes including duplicates and deletions, use the --removed
3494 changes including duplicates and deletions, use the --removed
3492 switch.
3495 switch.
3493
3496
3494 .. container:: verbose
3497 .. container:: verbose
3495
3498
3496 Some examples:
3499 Some examples:
3497
3500
3498 - changesets with full descriptions and file lists::
3501 - changesets with full descriptions and file lists::
3499
3502
3500 hg log -v
3503 hg log -v
3501
3504
3502 - changesets ancestral to the working directory::
3505 - changesets ancestral to the working directory::
3503
3506
3504 hg log -f
3507 hg log -f
3505
3508
3506 - last 10 commits on the current branch::
3509 - last 10 commits on the current branch::
3507
3510
3508 hg log -l 10 -b .
3511 hg log -l 10 -b .
3509
3512
3510 - changesets showing all modifications of a file, including removals::
3513 - changesets showing all modifications of a file, including removals::
3511
3514
3512 hg log --removed file.c
3515 hg log --removed file.c
3513
3516
3514 - all changesets that touch a directory, with diffs, excluding merges::
3517 - all changesets that touch a directory, with diffs, excluding merges::
3515
3518
3516 hg log -Mp lib/
3519 hg log -Mp lib/
3517
3520
3518 - all revision numbers that match a keyword::
3521 - all revision numbers that match a keyword::
3519
3522
3520 hg log -k bug --template "{rev}\\n"
3523 hg log -k bug --template "{rev}\\n"
3521
3524
3522 - check if a given changeset is included is a tagged release::
3525 - check if a given changeset is included is a tagged release::
3523
3526
3524 hg log -r "a21ccf and ancestor(1.9)"
3527 hg log -r "a21ccf and ancestor(1.9)"
3525
3528
3526 - find all changesets by some user in a date range::
3529 - find all changesets by some user in a date range::
3527
3530
3528 hg log -k alice -d "may 2008 to jul 2008"
3531 hg log -k alice -d "may 2008 to jul 2008"
3529
3532
3530 - summary of all changesets after the last tag::
3533 - summary of all changesets after the last tag::
3531
3534
3532 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3535 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3533
3536
3534 See :hg:`help dates` for a list of formats valid for -d/--date.
3537 See :hg:`help dates` for a list of formats valid for -d/--date.
3535
3538
3536 See :hg:`help revisions` and :hg:`help revsets` for more about
3539 See :hg:`help revisions` and :hg:`help revsets` for more about
3537 specifying revisions.
3540 specifying revisions.
3538
3541
3539 Returns 0 on success.
3542 Returns 0 on success.
3540 """
3543 """
3541
3544
3542 matchfn = scmutil.match(repo[None], pats, opts)
3545 matchfn = scmutil.match(repo[None], pats, opts)
3543 limit = cmdutil.loglimit(opts)
3546 limit = cmdutil.loglimit(opts)
3544 count = 0
3547 count = 0
3545
3548
3546 endrev = None
3549 endrev = None
3547 if opts.get('copies') and opts.get('rev'):
3550 if opts.get('copies') and opts.get('rev'):
3548 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3551 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3549
3552
3550 df = False
3553 df = False
3551 if opts["date"]:
3554 if opts["date"]:
3552 df = util.matchdate(opts["date"])
3555 df = util.matchdate(opts["date"])
3553
3556
3554 branches = opts.get('branch', []) + opts.get('only_branch', [])
3557 branches = opts.get('branch', []) + opts.get('only_branch', [])
3555 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3558 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3556
3559
3557 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3560 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3558 def prep(ctx, fns):
3561 def prep(ctx, fns):
3559 rev = ctx.rev()
3562 rev = ctx.rev()
3560 parents = [p for p in repo.changelog.parentrevs(rev)
3563 parents = [p for p in repo.changelog.parentrevs(rev)
3561 if p != nullrev]
3564 if p != nullrev]
3562 if opts.get('no_merges') and len(parents) == 2:
3565 if opts.get('no_merges') and len(parents) == 2:
3563 return
3566 return
3564 if opts.get('only_merges') and len(parents) != 2:
3567 if opts.get('only_merges') and len(parents) != 2:
3565 return
3568 return
3566 if opts.get('branch') and ctx.branch() not in opts['branch']:
3569 if opts.get('branch') and ctx.branch() not in opts['branch']:
3567 return
3570 return
3568 if not opts.get('hidden') and ctx.hidden():
3571 if not opts.get('hidden') and ctx.hidden():
3569 return
3572 return
3570 if df and not df(ctx.date()[0]):
3573 if df and not df(ctx.date()[0]):
3571 return
3574 return
3572 if opts['user'] and not [k for k in opts['user']
3575 if opts['user'] and not [k for k in opts['user']
3573 if k.lower() in ctx.user().lower()]:
3576 if k.lower() in ctx.user().lower()]:
3574 return
3577 return
3575 if opts.get('keyword'):
3578 if opts.get('keyword'):
3576 for k in [kw.lower() for kw in opts['keyword']]:
3579 for k in [kw.lower() for kw in opts['keyword']]:
3577 if (k in ctx.user().lower() or
3580 if (k in ctx.user().lower() or
3578 k in ctx.description().lower() or
3581 k in ctx.description().lower() or
3579 k in " ".join(ctx.files()).lower()):
3582 k in " ".join(ctx.files()).lower()):
3580 break
3583 break
3581 else:
3584 else:
3582 return
3585 return
3583
3586
3584 copies = None
3587 copies = None
3585 if opts.get('copies') and rev:
3588 if opts.get('copies') and rev:
3586 copies = []
3589 copies = []
3587 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3590 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3588 for fn in ctx.files():
3591 for fn in ctx.files():
3589 rename = getrenamed(fn, rev)
3592 rename = getrenamed(fn, rev)
3590 if rename:
3593 if rename:
3591 copies.append((fn, rename[0]))
3594 copies.append((fn, rename[0]))
3592
3595
3593 revmatchfn = None
3596 revmatchfn = None
3594 if opts.get('patch') or opts.get('stat'):
3597 if opts.get('patch') or opts.get('stat'):
3595 if opts.get('follow') or opts.get('follow_first'):
3598 if opts.get('follow') or opts.get('follow_first'):
3596 # note: this might be wrong when following through merges
3599 # note: this might be wrong when following through merges
3597 revmatchfn = scmutil.match(repo[None], fns, default='path')
3600 revmatchfn = scmutil.match(repo[None], fns, default='path')
3598 else:
3601 else:
3599 revmatchfn = matchfn
3602 revmatchfn = matchfn
3600
3603
3601 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3604 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3602
3605
3603 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3606 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3604 if count == limit:
3607 if count == limit:
3605 break
3608 break
3606 if displayer.flush(ctx.rev()):
3609 if displayer.flush(ctx.rev()):
3607 count += 1
3610 count += 1
3608 displayer.close()
3611 displayer.close()
3609
3612
3610 @command('manifest',
3613 @command('manifest',
3611 [('r', 'rev', '', _('revision to display'), _('REV')),
3614 [('r', 'rev', '', _('revision to display'), _('REV')),
3612 ('', 'all', False, _("list files from all revisions"))],
3615 ('', 'all', False, _("list files from all revisions"))],
3613 _('[-r REV]'))
3616 _('[-r REV]'))
3614 def manifest(ui, repo, node=None, rev=None, **opts):
3617 def manifest(ui, repo, node=None, rev=None, **opts):
3615 """output the current or given revision of the project manifest
3618 """output the current or given revision of the project manifest
3616
3619
3617 Print a list of version controlled files for the given revision.
3620 Print a list of version controlled files for the given revision.
3618 If no revision is given, the first parent of the working directory
3621 If no revision is given, the first parent of the working directory
3619 is used, or the null revision if no revision is checked out.
3622 is used, or the null revision if no revision is checked out.
3620
3623
3621 With -v, print file permissions, symlink and executable bits.
3624 With -v, print file permissions, symlink and executable bits.
3622 With --debug, print file revision hashes.
3625 With --debug, print file revision hashes.
3623
3626
3624 If option --all is specified, the list of all files from all revisions
3627 If option --all is specified, the list of all files from all revisions
3625 is printed. This includes deleted and renamed files.
3628 is printed. This includes deleted and renamed files.
3626
3629
3627 Returns 0 on success.
3630 Returns 0 on success.
3628 """
3631 """
3629 if opts.get('all'):
3632 if opts.get('all'):
3630 if rev or node:
3633 if rev or node:
3631 raise util.Abort(_("can't specify a revision with --all"))
3634 raise util.Abort(_("can't specify a revision with --all"))
3632
3635
3633 res = []
3636 res = []
3634 prefix = "data/"
3637 prefix = "data/"
3635 suffix = ".i"
3638 suffix = ".i"
3636 plen = len(prefix)
3639 plen = len(prefix)
3637 slen = len(suffix)
3640 slen = len(suffix)
3638 lock = repo.lock()
3641 lock = repo.lock()
3639 try:
3642 try:
3640 for fn, b, size in repo.store.datafiles():
3643 for fn, b, size in repo.store.datafiles():
3641 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3644 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3642 res.append(fn[plen:-slen])
3645 res.append(fn[plen:-slen])
3643 finally:
3646 finally:
3644 lock.release()
3647 lock.release()
3645 for f in sorted(res):
3648 for f in sorted(res):
3646 ui.write("%s\n" % f)
3649 ui.write("%s\n" % f)
3647 return
3650 return
3648
3651
3649 if rev and node:
3652 if rev and node:
3650 raise util.Abort(_("please specify just one revision"))
3653 raise util.Abort(_("please specify just one revision"))
3651
3654
3652 if not node:
3655 if not node:
3653 node = rev
3656 node = rev
3654
3657
3655 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3658 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3656 ctx = scmutil.revsingle(repo, node)
3659 ctx = scmutil.revsingle(repo, node)
3657 for f in ctx:
3660 for f in ctx:
3658 if ui.debugflag:
3661 if ui.debugflag:
3659 ui.write("%40s " % hex(ctx.manifest()[f]))
3662 ui.write("%40s " % hex(ctx.manifest()[f]))
3660 if ui.verbose:
3663 if ui.verbose:
3661 ui.write(decor[ctx.flags(f)])
3664 ui.write(decor[ctx.flags(f)])
3662 ui.write("%s\n" % f)
3665 ui.write("%s\n" % f)
3663
3666
3664 @command('^merge',
3667 @command('^merge',
3665 [('f', 'force', None, _('force a merge with outstanding changes')),
3668 [('f', 'force', None, _('force a merge with outstanding changes')),
3666 ('r', 'rev', '', _('revision to merge'), _('REV')),
3669 ('r', 'rev', '', _('revision to merge'), _('REV')),
3667 ('P', 'preview', None,
3670 ('P', 'preview', None,
3668 _('review revisions to merge (no merge is performed)'))
3671 _('review revisions to merge (no merge is performed)'))
3669 ] + mergetoolopts,
3672 ] + mergetoolopts,
3670 _('[-P] [-f] [[-r] REV]'))
3673 _('[-P] [-f] [[-r] REV]'))
3671 def merge(ui, repo, node=None, **opts):
3674 def merge(ui, repo, node=None, **opts):
3672 """merge working directory with another revision
3675 """merge working directory with another revision
3673
3676
3674 The current working directory is updated with all changes made in
3677 The current working directory is updated with all changes made in
3675 the requested revision since the last common predecessor revision.
3678 the requested revision since the last common predecessor revision.
3676
3679
3677 Files that changed between either parent are marked as changed for
3680 Files that changed between either parent are marked as changed for
3678 the next commit and a commit must be performed before any further
3681 the next commit and a commit must be performed before any further
3679 updates to the repository are allowed. The next commit will have
3682 updates to the repository are allowed. The next commit will have
3680 two parents.
3683 two parents.
3681
3684
3682 ``--tool`` can be used to specify the merge tool used for file
3685 ``--tool`` can be used to specify the merge tool used for file
3683 merges. It overrides the HGMERGE environment variable and your
3686 merges. It overrides the HGMERGE environment variable and your
3684 configuration files. See :hg:`help merge-tools` for options.
3687 configuration files. See :hg:`help merge-tools` for options.
3685
3688
3686 If no revision is specified, the working directory's parent is a
3689 If no revision is specified, the working directory's parent is a
3687 head revision, and the current branch contains exactly one other
3690 head revision, and the current branch contains exactly one other
3688 head, the other head is merged with by default. Otherwise, an
3691 head, the other head is merged with by default. Otherwise, an
3689 explicit revision with which to merge with must be provided.
3692 explicit revision with which to merge with must be provided.
3690
3693
3691 :hg:`resolve` must be used to resolve unresolved files.
3694 :hg:`resolve` must be used to resolve unresolved files.
3692
3695
3693 To undo an uncommitted merge, use :hg:`update --clean .` which
3696 To undo an uncommitted merge, use :hg:`update --clean .` which
3694 will check out a clean copy of the original merge parent, losing
3697 will check out a clean copy of the original merge parent, losing
3695 all changes.
3698 all changes.
3696
3699
3697 Returns 0 on success, 1 if there are unresolved files.
3700 Returns 0 on success, 1 if there are unresolved files.
3698 """
3701 """
3699
3702
3700 if opts.get('rev') and node:
3703 if opts.get('rev') and node:
3701 raise util.Abort(_("please specify just one revision"))
3704 raise util.Abort(_("please specify just one revision"))
3702 if not node:
3705 if not node:
3703 node = opts.get('rev')
3706 node = opts.get('rev')
3704
3707
3705 if not node:
3708 if not node:
3706 branch = repo[None].branch()
3709 branch = repo[None].branch()
3707 bheads = repo.branchheads(branch)
3710 bheads = repo.branchheads(branch)
3708 if len(bheads) > 2:
3711 if len(bheads) > 2:
3709 raise util.Abort(_("branch '%s' has %d heads - "
3712 raise util.Abort(_("branch '%s' has %d heads - "
3710 "please merge with an explicit rev")
3713 "please merge with an explicit rev")
3711 % (branch, len(bheads)),
3714 % (branch, len(bheads)),
3712 hint=_("run 'hg heads .' to see heads"))
3715 hint=_("run 'hg heads .' to see heads"))
3713
3716
3714 parent = repo.dirstate.p1()
3717 parent = repo.dirstate.p1()
3715 if len(bheads) == 1:
3718 if len(bheads) == 1:
3716 if len(repo.heads()) > 1:
3719 if len(repo.heads()) > 1:
3717 raise util.Abort(_("branch '%s' has one head - "
3720 raise util.Abort(_("branch '%s' has one head - "
3718 "please merge with an explicit rev")
3721 "please merge with an explicit rev")
3719 % branch,
3722 % branch,
3720 hint=_("run 'hg heads' to see all heads"))
3723 hint=_("run 'hg heads' to see all heads"))
3721 msg = _('there is nothing to merge')
3724 msg = _('there is nothing to merge')
3722 if parent != repo.lookup(repo[None].branch()):
3725 if parent != repo.lookup(repo[None].branch()):
3723 msg = _('%s - use "hg update" instead') % msg
3726 msg = _('%s - use "hg update" instead') % msg
3724 raise util.Abort(msg)
3727 raise util.Abort(msg)
3725
3728
3726 if parent not in bheads:
3729 if parent not in bheads:
3727 raise util.Abort(_('working directory not at a head revision'),
3730 raise util.Abort(_('working directory not at a head revision'),
3728 hint=_("use 'hg update' or merge with an "
3731 hint=_("use 'hg update' or merge with an "
3729 "explicit revision"))
3732 "explicit revision"))
3730 node = parent == bheads[0] and bheads[-1] or bheads[0]
3733 node = parent == bheads[0] and bheads[-1] or bheads[0]
3731 else:
3734 else:
3732 node = scmutil.revsingle(repo, node).node()
3735 node = scmutil.revsingle(repo, node).node()
3733
3736
3734 if opts.get('preview'):
3737 if opts.get('preview'):
3735 # find nodes that are ancestors of p2 but not of p1
3738 # find nodes that are ancestors of p2 but not of p1
3736 p1 = repo.lookup('.')
3739 p1 = repo.lookup('.')
3737 p2 = repo.lookup(node)
3740 p2 = repo.lookup(node)
3738 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3741 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3739
3742
3740 displayer = cmdutil.show_changeset(ui, repo, opts)
3743 displayer = cmdutil.show_changeset(ui, repo, opts)
3741 for node in nodes:
3744 for node in nodes:
3742 displayer.show(repo[node])
3745 displayer.show(repo[node])
3743 displayer.close()
3746 displayer.close()
3744 return 0
3747 return 0
3745
3748
3746 try:
3749 try:
3747 # ui.forcemerge is an internal variable, do not document
3750 # ui.forcemerge is an internal variable, do not document
3748 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3751 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3749 return hg.merge(repo, node, force=opts.get('force'))
3752 return hg.merge(repo, node, force=opts.get('force'))
3750 finally:
3753 finally:
3751 ui.setconfig('ui', 'forcemerge', '')
3754 ui.setconfig('ui', 'forcemerge', '')
3752
3755
3753 @command('outgoing|out',
3756 @command('outgoing|out',
3754 [('f', 'force', None, _('run even when the destination is unrelated')),
3757 [('f', 'force', None, _('run even when the destination is unrelated')),
3755 ('r', 'rev', [],
3758 ('r', 'rev', [],
3756 _('a changeset intended to be included in the destination'), _('REV')),
3759 _('a changeset intended to be included in the destination'), _('REV')),
3757 ('n', 'newest-first', None, _('show newest record first')),
3760 ('n', 'newest-first', None, _('show newest record first')),
3758 ('B', 'bookmarks', False, _('compare bookmarks')),
3761 ('B', 'bookmarks', False, _('compare bookmarks')),
3759 ('b', 'branch', [], _('a specific branch you would like to push'),
3762 ('b', 'branch', [], _('a specific branch you would like to push'),
3760 _('BRANCH')),
3763 _('BRANCH')),
3761 ] + logopts + remoteopts + subrepoopts,
3764 ] + logopts + remoteopts + subrepoopts,
3762 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3765 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3763 def outgoing(ui, repo, dest=None, **opts):
3766 def outgoing(ui, repo, dest=None, **opts):
3764 """show changesets not found in the destination
3767 """show changesets not found in the destination
3765
3768
3766 Show changesets not found in the specified destination repository
3769 Show changesets not found in the specified destination repository
3767 or the default push location. These are the changesets that would
3770 or the default push location. These are the changesets that would
3768 be pushed if a push was requested.
3771 be pushed if a push was requested.
3769
3772
3770 See pull for details of valid destination formats.
3773 See pull for details of valid destination formats.
3771
3774
3772 Returns 0 if there are outgoing changes, 1 otherwise.
3775 Returns 0 if there are outgoing changes, 1 otherwise.
3773 """
3776 """
3774
3777
3775 if opts.get('bookmarks'):
3778 if opts.get('bookmarks'):
3776 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3779 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3777 dest, branches = hg.parseurl(dest, opts.get('branch'))
3780 dest, branches = hg.parseurl(dest, opts.get('branch'))
3778 other = hg.peer(repo, opts, dest)
3781 other = hg.peer(repo, opts, dest)
3779 if 'bookmarks' not in other.listkeys('namespaces'):
3782 if 'bookmarks' not in other.listkeys('namespaces'):
3780 ui.warn(_("remote doesn't support bookmarks\n"))
3783 ui.warn(_("remote doesn't support bookmarks\n"))
3781 return 0
3784 return 0
3782 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3785 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3783 return bookmarks.diff(ui, other, repo)
3786 return bookmarks.diff(ui, other, repo)
3784
3787
3785 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3788 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3786 try:
3789 try:
3787 return hg.outgoing(ui, repo, dest, opts)
3790 return hg.outgoing(ui, repo, dest, opts)
3788 finally:
3791 finally:
3789 del repo._subtoppath
3792 del repo._subtoppath
3790
3793
3791 @command('parents',
3794 @command('parents',
3792 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3795 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3793 ] + templateopts,
3796 ] + templateopts,
3794 _('[-r REV] [FILE]'))
3797 _('[-r REV] [FILE]'))
3795 def parents(ui, repo, file_=None, **opts):
3798 def parents(ui, repo, file_=None, **opts):
3796 """show the parents of the working directory or revision
3799 """show the parents of the working directory or revision
3797
3800
3798 Print the working directory's parent revisions. If a revision is
3801 Print the working directory's parent revisions. If a revision is
3799 given via -r/--rev, the parent of that revision will be printed.
3802 given via -r/--rev, the parent of that revision will be printed.
3800 If a file argument is given, the revision in which the file was
3803 If a file argument is given, the revision in which the file was
3801 last changed (before the working directory revision or the
3804 last changed (before the working directory revision or the
3802 argument to --rev if given) is printed.
3805 argument to --rev if given) is printed.
3803
3806
3804 Returns 0 on success.
3807 Returns 0 on success.
3805 """
3808 """
3806
3809
3807 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3810 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3808
3811
3809 if file_:
3812 if file_:
3810 m = scmutil.match(ctx, (file_,), opts)
3813 m = scmutil.match(ctx, (file_,), opts)
3811 if m.anypats() or len(m.files()) != 1:
3814 if m.anypats() or len(m.files()) != 1:
3812 raise util.Abort(_('can only specify an explicit filename'))
3815 raise util.Abort(_('can only specify an explicit filename'))
3813 file_ = m.files()[0]
3816 file_ = m.files()[0]
3814 filenodes = []
3817 filenodes = []
3815 for cp in ctx.parents():
3818 for cp in ctx.parents():
3816 if not cp:
3819 if not cp:
3817 continue
3820 continue
3818 try:
3821 try:
3819 filenodes.append(cp.filenode(file_))
3822 filenodes.append(cp.filenode(file_))
3820 except error.LookupError:
3823 except error.LookupError:
3821 pass
3824 pass
3822 if not filenodes:
3825 if not filenodes:
3823 raise util.Abort(_("'%s' not found in manifest!") % file_)
3826 raise util.Abort(_("'%s' not found in manifest!") % file_)
3824 fl = repo.file(file_)
3827 fl = repo.file(file_)
3825 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3828 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3826 else:
3829 else:
3827 p = [cp.node() for cp in ctx.parents()]
3830 p = [cp.node() for cp in ctx.parents()]
3828
3831
3829 displayer = cmdutil.show_changeset(ui, repo, opts)
3832 displayer = cmdutil.show_changeset(ui, repo, opts)
3830 for n in p:
3833 for n in p:
3831 if n != nullid:
3834 if n != nullid:
3832 displayer.show(repo[n])
3835 displayer.show(repo[n])
3833 displayer.close()
3836 displayer.close()
3834
3837
3835 @command('paths', [], _('[NAME]'))
3838 @command('paths', [], _('[NAME]'))
3836 def paths(ui, repo, search=None):
3839 def paths(ui, repo, search=None):
3837 """show aliases for remote repositories
3840 """show aliases for remote repositories
3838
3841
3839 Show definition of symbolic path name NAME. If no name is given,
3842 Show definition of symbolic path name NAME. If no name is given,
3840 show definition of all available names.
3843 show definition of all available names.
3841
3844
3842 Option -q/--quiet suppresses all output when searching for NAME
3845 Option -q/--quiet suppresses all output when searching for NAME
3843 and shows only the path names when listing all definitions.
3846 and shows only the path names when listing all definitions.
3844
3847
3845 Path names are defined in the [paths] section of your
3848 Path names are defined in the [paths] section of your
3846 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3849 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3847 repository, ``.hg/hgrc`` is used, too.
3850 repository, ``.hg/hgrc`` is used, too.
3848
3851
3849 The path names ``default`` and ``default-push`` have a special
3852 The path names ``default`` and ``default-push`` have a special
3850 meaning. When performing a push or pull operation, they are used
3853 meaning. When performing a push or pull operation, they are used
3851 as fallbacks if no location is specified on the command-line.
3854 as fallbacks if no location is specified on the command-line.
3852 When ``default-push`` is set, it will be used for push and
3855 When ``default-push`` is set, it will be used for push and
3853 ``default`` will be used for pull; otherwise ``default`` is used
3856 ``default`` will be used for pull; otherwise ``default`` is used
3854 as the fallback for both. When cloning a repository, the clone
3857 as the fallback for both. When cloning a repository, the clone
3855 source is written as ``default`` in ``.hg/hgrc``. Note that
3858 source is written as ``default`` in ``.hg/hgrc``. Note that
3856 ``default`` and ``default-push`` apply to all inbound (e.g.
3859 ``default`` and ``default-push`` apply to all inbound (e.g.
3857 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3860 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3858 :hg:`bundle`) operations.
3861 :hg:`bundle`) operations.
3859
3862
3860 See :hg:`help urls` for more information.
3863 See :hg:`help urls` for more information.
3861
3864
3862 Returns 0 on success.
3865 Returns 0 on success.
3863 """
3866 """
3864 if search:
3867 if search:
3865 for name, path in ui.configitems("paths"):
3868 for name, path in ui.configitems("paths"):
3866 if name == search:
3869 if name == search:
3867 ui.status("%s\n" % util.hidepassword(path))
3870 ui.status("%s\n" % util.hidepassword(path))
3868 return
3871 return
3869 if not ui.quiet:
3872 if not ui.quiet:
3870 ui.warn(_("not found!\n"))
3873 ui.warn(_("not found!\n"))
3871 return 1
3874 return 1
3872 else:
3875 else:
3873 for name, path in ui.configitems("paths"):
3876 for name, path in ui.configitems("paths"):
3874 if ui.quiet:
3877 if ui.quiet:
3875 ui.write("%s\n" % name)
3878 ui.write("%s\n" % name)
3876 else:
3879 else:
3877 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3880 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3878
3881
3879 def postincoming(ui, repo, modheads, optupdate, checkout):
3882 def postincoming(ui, repo, modheads, optupdate, checkout):
3880 if modheads == 0:
3883 if modheads == 0:
3881 return
3884 return
3882 if optupdate:
3885 if optupdate:
3883 try:
3886 try:
3884 return hg.update(repo, checkout)
3887 return hg.update(repo, checkout)
3885 except util.Abort, inst:
3888 except util.Abort, inst:
3886 ui.warn(_("not updating: %s\n" % str(inst)))
3889 ui.warn(_("not updating: %s\n" % str(inst)))
3887 return 0
3890 return 0
3888 if modheads > 1:
3891 if modheads > 1:
3889 currentbranchheads = len(repo.branchheads())
3892 currentbranchheads = len(repo.branchheads())
3890 if currentbranchheads == modheads:
3893 if currentbranchheads == modheads:
3891 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3894 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3892 elif currentbranchheads > 1:
3895 elif currentbranchheads > 1:
3893 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3896 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3894 else:
3897 else:
3895 ui.status(_("(run 'hg heads' to see heads)\n"))
3898 ui.status(_("(run 'hg heads' to see heads)\n"))
3896 else:
3899 else:
3897 ui.status(_("(run 'hg update' to get a working copy)\n"))
3900 ui.status(_("(run 'hg update' to get a working copy)\n"))
3898
3901
3899 @command('^pull',
3902 @command('^pull',
3900 [('u', 'update', None,
3903 [('u', 'update', None,
3901 _('update to new branch head if changesets were pulled')),
3904 _('update to new branch head if changesets were pulled')),
3902 ('f', 'force', None, _('run even when remote repository is unrelated')),
3905 ('f', 'force', None, _('run even when remote repository is unrelated')),
3903 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3906 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3904 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3907 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3905 ('b', 'branch', [], _('a specific branch you would like to pull'),
3908 ('b', 'branch', [], _('a specific branch you would like to pull'),
3906 _('BRANCH')),
3909 _('BRANCH')),
3907 ] + remoteopts,
3910 ] + remoteopts,
3908 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3911 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3909 def pull(ui, repo, source="default", **opts):
3912 def pull(ui, repo, source="default", **opts):
3910 """pull changes from the specified source
3913 """pull changes from the specified source
3911
3914
3912 Pull changes from a remote repository to a local one.
3915 Pull changes from a remote repository to a local one.
3913
3916
3914 This finds all changes from the repository at the specified path
3917 This finds all changes from the repository at the specified path
3915 or URL and adds them to a local repository (the current one unless
3918 or URL and adds them to a local repository (the current one unless
3916 -R is specified). By default, this does not update the copy of the
3919 -R is specified). By default, this does not update the copy of the
3917 project in the working directory.
3920 project in the working directory.
3918
3921
3919 Use :hg:`incoming` if you want to see what would have been added
3922 Use :hg:`incoming` if you want to see what would have been added
3920 by a pull at the time you issued this command. If you then decide
3923 by a pull at the time you issued this command. If you then decide
3921 to add those changes to the repository, you should use :hg:`pull
3924 to add those changes to the repository, you should use :hg:`pull
3922 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3925 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3923
3926
3924 If SOURCE is omitted, the 'default' path will be used.
3927 If SOURCE is omitted, the 'default' path will be used.
3925 See :hg:`help urls` for more information.
3928 See :hg:`help urls` for more information.
3926
3929
3927 Returns 0 on success, 1 if an update had unresolved files.
3930 Returns 0 on success, 1 if an update had unresolved files.
3928 """
3931 """
3929 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3932 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3930 other = hg.peer(repo, opts, source)
3933 other = hg.peer(repo, opts, source)
3931 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3934 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3932 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3935 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3933
3936
3934 if opts.get('bookmark'):
3937 if opts.get('bookmark'):
3935 if not revs:
3938 if not revs:
3936 revs = []
3939 revs = []
3937 rb = other.listkeys('bookmarks')
3940 rb = other.listkeys('bookmarks')
3938 for b in opts['bookmark']:
3941 for b in opts['bookmark']:
3939 if b not in rb:
3942 if b not in rb:
3940 raise util.Abort(_('remote bookmark %s not found!') % b)
3943 raise util.Abort(_('remote bookmark %s not found!') % b)
3941 revs.append(rb[b])
3944 revs.append(rb[b])
3942
3945
3943 if revs:
3946 if revs:
3944 try:
3947 try:
3945 revs = [other.lookup(rev) for rev in revs]
3948 revs = [other.lookup(rev) for rev in revs]
3946 except error.CapabilityError:
3949 except error.CapabilityError:
3947 err = _("other repository doesn't support revision lookup, "
3950 err = _("other repository doesn't support revision lookup, "
3948 "so a rev cannot be specified.")
3951 "so a rev cannot be specified.")
3949 raise util.Abort(err)
3952 raise util.Abort(err)
3950
3953
3951 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3954 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3952 bookmarks.updatefromremote(ui, repo, other)
3955 bookmarks.updatefromremote(ui, repo, other)
3953 if checkout:
3956 if checkout:
3954 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3957 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3955 repo._subtoppath = source
3958 repo._subtoppath = source
3956 try:
3959 try:
3957 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3960 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3958
3961
3959 finally:
3962 finally:
3960 del repo._subtoppath
3963 del repo._subtoppath
3961
3964
3962 # update specified bookmarks
3965 # update specified bookmarks
3963 if opts.get('bookmark'):
3966 if opts.get('bookmark'):
3964 for b in opts['bookmark']:
3967 for b in opts['bookmark']:
3965 # explicit pull overrides local bookmark if any
3968 # explicit pull overrides local bookmark if any
3966 ui.status(_("importing bookmark %s\n") % b)
3969 ui.status(_("importing bookmark %s\n") % b)
3967 repo._bookmarks[b] = repo[rb[b]].node()
3970 repo._bookmarks[b] = repo[rb[b]].node()
3968 bookmarks.write(repo)
3971 bookmarks.write(repo)
3969
3972
3970 return ret
3973 return ret
3971
3974
3972 @command('^push',
3975 @command('^push',
3973 [('f', 'force', None, _('force push')),
3976 [('f', 'force', None, _('force push')),
3974 ('r', 'rev', [],
3977 ('r', 'rev', [],
3975 _('a changeset intended to be included in the destination'),
3978 _('a changeset intended to be included in the destination'),
3976 _('REV')),
3979 _('REV')),
3977 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3980 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3978 ('b', 'branch', [],
3981 ('b', 'branch', [],
3979 _('a specific branch you would like to push'), _('BRANCH')),
3982 _('a specific branch you would like to push'), _('BRANCH')),
3980 ('', 'new-branch', False, _('allow pushing a new branch')),
3983 ('', 'new-branch', False, _('allow pushing a new branch')),
3981 ] + remoteopts,
3984 ] + remoteopts,
3982 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3985 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3983 def push(ui, repo, dest=None, **opts):
3986 def push(ui, repo, dest=None, **opts):
3984 """push changes to the specified destination
3987 """push changes to the specified destination
3985
3988
3986 Push changesets from the local repository to the specified
3989 Push changesets from the local repository to the specified
3987 destination.
3990 destination.
3988
3991
3989 This operation is symmetrical to pull: it is identical to a pull
3992 This operation is symmetrical to pull: it is identical to a pull
3990 in the destination repository from the current one.
3993 in the destination repository from the current one.
3991
3994
3992 By default, push will not allow creation of new heads at the
3995 By default, push will not allow creation of new heads at the
3993 destination, since multiple heads would make it unclear which head
3996 destination, since multiple heads would make it unclear which head
3994 to use. In this situation, it is recommended to pull and merge
3997 to use. In this situation, it is recommended to pull and merge
3995 before pushing.
3998 before pushing.
3996
3999
3997 Use --new-branch if you want to allow push to create a new named
4000 Use --new-branch if you want to allow push to create a new named
3998 branch that is not present at the destination. This allows you to
4001 branch that is not present at the destination. This allows you to
3999 only create a new branch without forcing other changes.
4002 only create a new branch without forcing other changes.
4000
4003
4001 Use -f/--force to override the default behavior and push all
4004 Use -f/--force to override the default behavior and push all
4002 changesets on all branches.
4005 changesets on all branches.
4003
4006
4004 If -r/--rev is used, the specified revision and all its ancestors
4007 If -r/--rev is used, the specified revision and all its ancestors
4005 will be pushed to the remote repository.
4008 will be pushed to the remote repository.
4006
4009
4007 Please see :hg:`help urls` for important details about ``ssh://``
4010 Please see :hg:`help urls` for important details about ``ssh://``
4008 URLs. If DESTINATION is omitted, a default path will be used.
4011 URLs. If DESTINATION is omitted, a default path will be used.
4009
4012
4010 Returns 0 if push was successful, 1 if nothing to push.
4013 Returns 0 if push was successful, 1 if nothing to push.
4011 """
4014 """
4012
4015
4013 if opts.get('bookmark'):
4016 if opts.get('bookmark'):
4014 for b in opts['bookmark']:
4017 for b in opts['bookmark']:
4015 # translate -B options to -r so changesets get pushed
4018 # translate -B options to -r so changesets get pushed
4016 if b in repo._bookmarks:
4019 if b in repo._bookmarks:
4017 opts.setdefault('rev', []).append(b)
4020 opts.setdefault('rev', []).append(b)
4018 else:
4021 else:
4019 # if we try to push a deleted bookmark, translate it to null
4022 # if we try to push a deleted bookmark, translate it to null
4020 # this lets simultaneous -r, -b options continue working
4023 # this lets simultaneous -r, -b options continue working
4021 opts.setdefault('rev', []).append("null")
4024 opts.setdefault('rev', []).append("null")
4022
4025
4023 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4026 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4024 dest, branches = hg.parseurl(dest, opts.get('branch'))
4027 dest, branches = hg.parseurl(dest, opts.get('branch'))
4025 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4028 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4026 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4029 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4027 other = hg.peer(repo, opts, dest)
4030 other = hg.peer(repo, opts, dest)
4028 if revs:
4031 if revs:
4029 revs = [repo.lookup(rev) for rev in revs]
4032 revs = [repo.lookup(rev) for rev in revs]
4030
4033
4031 repo._subtoppath = dest
4034 repo._subtoppath = dest
4032 try:
4035 try:
4033 # push subrepos depth-first for coherent ordering
4036 # push subrepos depth-first for coherent ordering
4034 c = repo['']
4037 c = repo['']
4035 subs = c.substate # only repos that are committed
4038 subs = c.substate # only repos that are committed
4036 for s in sorted(subs):
4039 for s in sorted(subs):
4037 if not c.sub(s).push(opts.get('force')):
4040 if not c.sub(s).push(opts.get('force')):
4038 return False
4041 return False
4039 finally:
4042 finally:
4040 del repo._subtoppath
4043 del repo._subtoppath
4041 result = repo.push(other, opts.get('force'), revs=revs,
4044 result = repo.push(other, opts.get('force'), revs=revs,
4042 newbranch=opts.get('new_branch'))
4045 newbranch=opts.get('new_branch'))
4043
4046
4044 result = (result == 0)
4047 result = (result == 0)
4045
4048
4046 if opts.get('bookmark'):
4049 if opts.get('bookmark'):
4047 rb = other.listkeys('bookmarks')
4050 rb = other.listkeys('bookmarks')
4048 for b in opts['bookmark']:
4051 for b in opts['bookmark']:
4049 # explicit push overrides remote bookmark if any
4052 # explicit push overrides remote bookmark if any
4050 if b in repo._bookmarks:
4053 if b in repo._bookmarks:
4051 ui.status(_("exporting bookmark %s\n") % b)
4054 ui.status(_("exporting bookmark %s\n") % b)
4052 new = repo[b].hex()
4055 new = repo[b].hex()
4053 elif b in rb:
4056 elif b in rb:
4054 ui.status(_("deleting remote bookmark %s\n") % b)
4057 ui.status(_("deleting remote bookmark %s\n") % b)
4055 new = '' # delete
4058 new = '' # delete
4056 else:
4059 else:
4057 ui.warn(_('bookmark %s does not exist on the local '
4060 ui.warn(_('bookmark %s does not exist on the local '
4058 'or remote repository!\n') % b)
4061 'or remote repository!\n') % b)
4059 return 2
4062 return 2
4060 old = rb.get(b, '')
4063 old = rb.get(b, '')
4061 r = other.pushkey('bookmarks', b, old, new)
4064 r = other.pushkey('bookmarks', b, old, new)
4062 if not r:
4065 if not r:
4063 ui.warn(_('updating bookmark %s failed!\n') % b)
4066 ui.warn(_('updating bookmark %s failed!\n') % b)
4064 if not result:
4067 if not result:
4065 result = 2
4068 result = 2
4066
4069
4067 return result
4070 return result
4068
4071
4069 @command('recover', [])
4072 @command('recover', [])
4070 def recover(ui, repo):
4073 def recover(ui, repo):
4071 """roll back an interrupted transaction
4074 """roll back an interrupted transaction
4072
4075
4073 Recover from an interrupted commit or pull.
4076 Recover from an interrupted commit or pull.
4074
4077
4075 This command tries to fix the repository status after an
4078 This command tries to fix the repository status after an
4076 interrupted operation. It should only be necessary when Mercurial
4079 interrupted operation. It should only be necessary when Mercurial
4077 suggests it.
4080 suggests it.
4078
4081
4079 Returns 0 if successful, 1 if nothing to recover or verify fails.
4082 Returns 0 if successful, 1 if nothing to recover or verify fails.
4080 """
4083 """
4081 if repo.recover():
4084 if repo.recover():
4082 return hg.verify(repo)
4085 return hg.verify(repo)
4083 return 1
4086 return 1
4084
4087
4085 @command('^remove|rm',
4088 @command('^remove|rm',
4086 [('A', 'after', None, _('record delete for missing files')),
4089 [('A', 'after', None, _('record delete for missing files')),
4087 ('f', 'force', None,
4090 ('f', 'force', None,
4088 _('remove (and delete) file even if added or modified')),
4091 _('remove (and delete) file even if added or modified')),
4089 ] + walkopts,
4092 ] + walkopts,
4090 _('[OPTION]... FILE...'))
4093 _('[OPTION]... FILE...'))
4091 def remove(ui, repo, *pats, **opts):
4094 def remove(ui, repo, *pats, **opts):
4092 """remove the specified files on the next commit
4095 """remove the specified files on the next commit
4093
4096
4094 Schedule the indicated files for removal from the current branch.
4097 Schedule the indicated files for removal from the current branch.
4095
4098
4096 This command schedules the files to be removed at the next commit.
4099 This command schedules the files to be removed at the next commit.
4097 To undo a remove before that, see :hg:`revert`. To undo added
4100 To undo a remove before that, see :hg:`revert`. To undo added
4098 files, see :hg:`forget`.
4101 files, see :hg:`forget`.
4099
4102
4100 .. container:: verbose
4103 .. container:: verbose
4101
4104
4102 -A/--after can be used to remove only files that have already
4105 -A/--after can be used to remove only files that have already
4103 been deleted, -f/--force can be used to force deletion, and -Af
4106 been deleted, -f/--force can be used to force deletion, and -Af
4104 can be used to remove files from the next revision without
4107 can be used to remove files from the next revision without
4105 deleting them from the working directory.
4108 deleting them from the working directory.
4106
4109
4107 The following table details the behavior of remove for different
4110 The following table details the behavior of remove for different
4108 file states (columns) and option combinations (rows). The file
4111 file states (columns) and option combinations (rows). The file
4109 states are Added [A], Clean [C], Modified [M] and Missing [!]
4112 states are Added [A], Clean [C], Modified [M] and Missing [!]
4110 (as reported by :hg:`status`). The actions are Warn, Remove
4113 (as reported by :hg:`status`). The actions are Warn, Remove
4111 (from branch) and Delete (from disk):
4114 (from branch) and Delete (from disk):
4112
4115
4113 ======= == == == ==
4116 ======= == == == ==
4114 A C M !
4117 A C M !
4115 ======= == == == ==
4118 ======= == == == ==
4116 none W RD W R
4119 none W RD W R
4117 -f R RD RD R
4120 -f R RD RD R
4118 -A W W W R
4121 -A W W W R
4119 -Af R R R R
4122 -Af R R R R
4120 ======= == == == ==
4123 ======= == == == ==
4121
4124
4122 Note that remove never deletes files in Added [A] state from the
4125 Note that remove never deletes files in Added [A] state from the
4123 working directory, not even if option --force is specified.
4126 working directory, not even if option --force is specified.
4124
4127
4125 Returns 0 on success, 1 if any warnings encountered.
4128 Returns 0 on success, 1 if any warnings encountered.
4126 """
4129 """
4127
4130
4128 ret = 0
4131 ret = 0
4129 after, force = opts.get('after'), opts.get('force')
4132 after, force = opts.get('after'), opts.get('force')
4130 if not pats and not after:
4133 if not pats and not after:
4131 raise util.Abort(_('no files specified'))
4134 raise util.Abort(_('no files specified'))
4132
4135
4133 m = scmutil.match(repo[None], pats, opts)
4136 m = scmutil.match(repo[None], pats, opts)
4134 s = repo.status(match=m, clean=True)
4137 s = repo.status(match=m, clean=True)
4135 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4138 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4136
4139
4137 for f in m.files():
4140 for f in m.files():
4138 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4141 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4139 if os.path.exists(m.rel(f)):
4142 if os.path.exists(m.rel(f)):
4140 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4143 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4141 ret = 1
4144 ret = 1
4142
4145
4143 if force:
4146 if force:
4144 list = modified + deleted + clean + added
4147 list = modified + deleted + clean + added
4145 elif after:
4148 elif after:
4146 list = deleted
4149 list = deleted
4147 for f in modified + added + clean:
4150 for f in modified + added + clean:
4148 ui.warn(_('not removing %s: file still exists (use -f'
4151 ui.warn(_('not removing %s: file still exists (use -f'
4149 ' to force removal)\n') % m.rel(f))
4152 ' to force removal)\n') % m.rel(f))
4150 ret = 1
4153 ret = 1
4151 else:
4154 else:
4152 list = deleted + clean
4155 list = deleted + clean
4153 for f in modified:
4156 for f in modified:
4154 ui.warn(_('not removing %s: file is modified (use -f'
4157 ui.warn(_('not removing %s: file is modified (use -f'
4155 ' to force removal)\n') % m.rel(f))
4158 ' to force removal)\n') % m.rel(f))
4156 ret = 1
4159 ret = 1
4157 for f in added:
4160 for f in added:
4158 ui.warn(_('not removing %s: file has been marked for add'
4161 ui.warn(_('not removing %s: file has been marked for add'
4159 ' (use forget to undo)\n') % m.rel(f))
4162 ' (use forget to undo)\n') % m.rel(f))
4160 ret = 1
4163 ret = 1
4161
4164
4162 for f in sorted(list):
4165 for f in sorted(list):
4163 if ui.verbose or not m.exact(f):
4166 if ui.verbose or not m.exact(f):
4164 ui.status(_('removing %s\n') % m.rel(f))
4167 ui.status(_('removing %s\n') % m.rel(f))
4165
4168
4166 wlock = repo.wlock()
4169 wlock = repo.wlock()
4167 try:
4170 try:
4168 if not after:
4171 if not after:
4169 for f in list:
4172 for f in list:
4170 if f in added:
4173 if f in added:
4171 continue # we never unlink added files on remove
4174 continue # we never unlink added files on remove
4172 try:
4175 try:
4173 util.unlinkpath(repo.wjoin(f))
4176 util.unlinkpath(repo.wjoin(f))
4174 except OSError, inst:
4177 except OSError, inst:
4175 if inst.errno != errno.ENOENT:
4178 if inst.errno != errno.ENOENT:
4176 raise
4179 raise
4177 repo[None].forget(list)
4180 repo[None].forget(list)
4178 finally:
4181 finally:
4179 wlock.release()
4182 wlock.release()
4180
4183
4181 return ret
4184 return ret
4182
4185
4183 @command('rename|move|mv',
4186 @command('rename|move|mv',
4184 [('A', 'after', None, _('record a rename that has already occurred')),
4187 [('A', 'after', None, _('record a rename that has already occurred')),
4185 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4188 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4186 ] + walkopts + dryrunopts,
4189 ] + walkopts + dryrunopts,
4187 _('[OPTION]... SOURCE... DEST'))
4190 _('[OPTION]... SOURCE... DEST'))
4188 def rename(ui, repo, *pats, **opts):
4191 def rename(ui, repo, *pats, **opts):
4189 """rename files; equivalent of copy + remove
4192 """rename files; equivalent of copy + remove
4190
4193
4191 Mark dest as copies of sources; mark sources for deletion. If dest
4194 Mark dest as copies of sources; mark sources for deletion. If dest
4192 is a directory, copies are put in that directory. If dest is a
4195 is a directory, copies are put in that directory. If dest is a
4193 file, there can only be one source.
4196 file, there can only be one source.
4194
4197
4195 By default, this command copies the contents of files as they
4198 By default, this command copies the contents of files as they
4196 exist in the working directory. If invoked with -A/--after, the
4199 exist in the working directory. If invoked with -A/--after, the
4197 operation is recorded, but no copying is performed.
4200 operation is recorded, but no copying is performed.
4198
4201
4199 This command takes effect at the next commit. To undo a rename
4202 This command takes effect at the next commit. To undo a rename
4200 before that, see :hg:`revert`.
4203 before that, see :hg:`revert`.
4201
4204
4202 Returns 0 on success, 1 if errors are encountered.
4205 Returns 0 on success, 1 if errors are encountered.
4203 """
4206 """
4204 wlock = repo.wlock(False)
4207 wlock = repo.wlock(False)
4205 try:
4208 try:
4206 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4209 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4207 finally:
4210 finally:
4208 wlock.release()
4211 wlock.release()
4209
4212
4210 @command('resolve',
4213 @command('resolve',
4211 [('a', 'all', None, _('select all unresolved files')),
4214 [('a', 'all', None, _('select all unresolved files')),
4212 ('l', 'list', None, _('list state of files needing merge')),
4215 ('l', 'list', None, _('list state of files needing merge')),
4213 ('m', 'mark', None, _('mark files as resolved')),
4216 ('m', 'mark', None, _('mark files as resolved')),
4214 ('u', 'unmark', None, _('mark files as unresolved')),
4217 ('u', 'unmark', None, _('mark files as unresolved')),
4215 ('n', 'no-status', None, _('hide status prefix'))]
4218 ('n', 'no-status', None, _('hide status prefix'))]
4216 + mergetoolopts + walkopts,
4219 + mergetoolopts + walkopts,
4217 _('[OPTION]... [FILE]...'))
4220 _('[OPTION]... [FILE]...'))
4218 def resolve(ui, repo, *pats, **opts):
4221 def resolve(ui, repo, *pats, **opts):
4219 """redo merges or set/view the merge status of files
4222 """redo merges or set/view the merge status of files
4220
4223
4221 Merges with unresolved conflicts are often the result of
4224 Merges with unresolved conflicts are often the result of
4222 non-interactive merging using the ``internal:merge`` configuration
4225 non-interactive merging using the ``internal:merge`` configuration
4223 setting, or a command-line merge tool like ``diff3``. The resolve
4226 setting, or a command-line merge tool like ``diff3``. The resolve
4224 command is used to manage the files involved in a merge, after
4227 command is used to manage the files involved in a merge, after
4225 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4228 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4226 working directory must have two parents).
4229 working directory must have two parents).
4227
4230
4228 The resolve command can be used in the following ways:
4231 The resolve command can be used in the following ways:
4229
4232
4230 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4233 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4231 files, discarding any previous merge attempts. Re-merging is not
4234 files, discarding any previous merge attempts. Re-merging is not
4232 performed for files already marked as resolved. Use ``--all/-a``
4235 performed for files already marked as resolved. Use ``--all/-a``
4233 to select all unresolved files. ``--tool`` can be used to specify
4236 to select all unresolved files. ``--tool`` can be used to specify
4234 the merge tool used for the given files. It overrides the HGMERGE
4237 the merge tool used for the given files. It overrides the HGMERGE
4235 environment variable and your configuration files.
4238 environment variable and your configuration files.
4236
4239
4237 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4240 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4238 (e.g. after having manually fixed-up the files). The default is
4241 (e.g. after having manually fixed-up the files). The default is
4239 to mark all unresolved files.
4242 to mark all unresolved files.
4240
4243
4241 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4244 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4242 default is to mark all resolved files.
4245 default is to mark all resolved files.
4243
4246
4244 - :hg:`resolve -l`: list files which had or still have conflicts.
4247 - :hg:`resolve -l`: list files which had or still have conflicts.
4245 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4248 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4246
4249
4247 Note that Mercurial will not let you commit files with unresolved
4250 Note that Mercurial will not let you commit files with unresolved
4248 merge conflicts. You must use :hg:`resolve -m ...` before you can
4251 merge conflicts. You must use :hg:`resolve -m ...` before you can
4249 commit after a conflicting merge.
4252 commit after a conflicting merge.
4250
4253
4251 Returns 0 on success, 1 if any files fail a resolve attempt.
4254 Returns 0 on success, 1 if any files fail a resolve attempt.
4252 """
4255 """
4253
4256
4254 all, mark, unmark, show, nostatus = \
4257 all, mark, unmark, show, nostatus = \
4255 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4258 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4256
4259
4257 if (show and (mark or unmark)) or (mark and unmark):
4260 if (show and (mark or unmark)) or (mark and unmark):
4258 raise util.Abort(_("too many options specified"))
4261 raise util.Abort(_("too many options specified"))
4259 if pats and all:
4262 if pats and all:
4260 raise util.Abort(_("can't specify --all and patterns"))
4263 raise util.Abort(_("can't specify --all and patterns"))
4261 if not (all or pats or show or mark or unmark):
4264 if not (all or pats or show or mark or unmark):
4262 raise util.Abort(_('no files or directories specified; '
4265 raise util.Abort(_('no files or directories specified; '
4263 'use --all to remerge all files'))
4266 'use --all to remerge all files'))
4264
4267
4265 ms = mergemod.mergestate(repo)
4268 ms = mergemod.mergestate(repo)
4266 m = scmutil.match(repo[None], pats, opts)
4269 m = scmutil.match(repo[None], pats, opts)
4267 ret = 0
4270 ret = 0
4268
4271
4269 for f in ms:
4272 for f in ms:
4270 if m(f):
4273 if m(f):
4271 if show:
4274 if show:
4272 if nostatus:
4275 if nostatus:
4273 ui.write("%s\n" % f)
4276 ui.write("%s\n" % f)
4274 else:
4277 else:
4275 ui.write("%s %s\n" % (ms[f].upper(), f),
4278 ui.write("%s %s\n" % (ms[f].upper(), f),
4276 label='resolve.' +
4279 label='resolve.' +
4277 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4280 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4278 elif mark:
4281 elif mark:
4279 ms.mark(f, "r")
4282 ms.mark(f, "r")
4280 elif unmark:
4283 elif unmark:
4281 ms.mark(f, "u")
4284 ms.mark(f, "u")
4282 else:
4285 else:
4283 wctx = repo[None]
4286 wctx = repo[None]
4284 mctx = wctx.parents()[-1]
4287 mctx = wctx.parents()[-1]
4285
4288
4286 # backup pre-resolve (merge uses .orig for its own purposes)
4289 # backup pre-resolve (merge uses .orig for its own purposes)
4287 a = repo.wjoin(f)
4290 a = repo.wjoin(f)
4288 util.copyfile(a, a + ".resolve")
4291 util.copyfile(a, a + ".resolve")
4289
4292
4290 try:
4293 try:
4291 # resolve file
4294 # resolve file
4292 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4295 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4293 if ms.resolve(f, wctx, mctx):
4296 if ms.resolve(f, wctx, mctx):
4294 ret = 1
4297 ret = 1
4295 finally:
4298 finally:
4296 ui.setconfig('ui', 'forcemerge', '')
4299 ui.setconfig('ui', 'forcemerge', '')
4297
4300
4298 # replace filemerge's .orig file with our resolve file
4301 # replace filemerge's .orig file with our resolve file
4299 util.rename(a + ".resolve", a + ".orig")
4302 util.rename(a + ".resolve", a + ".orig")
4300
4303
4301 ms.commit()
4304 ms.commit()
4302 return ret
4305 return ret
4303
4306
4304 @command('revert',
4307 @command('revert',
4305 [('a', 'all', None, _('revert all changes when no arguments given')),
4308 [('a', 'all', None, _('revert all changes when no arguments given')),
4306 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4309 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4307 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4310 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4308 ('C', 'no-backup', None, _('do not save backup copies of files')),
4311 ('C', 'no-backup', None, _('do not save backup copies of files')),
4309 ] + walkopts + dryrunopts,
4312 ] + walkopts + dryrunopts,
4310 _('[OPTION]... [-r REV] [NAME]...'))
4313 _('[OPTION]... [-r REV] [NAME]...'))
4311 def revert(ui, repo, *pats, **opts):
4314 def revert(ui, repo, *pats, **opts):
4312 """restore files to their checkout state
4315 """restore files to their checkout state
4313
4316
4314 .. note::
4317 .. note::
4315 To check out earlier revisions, you should use :hg:`update REV`.
4318 To check out earlier revisions, you should use :hg:`update REV`.
4316 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4319 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4317
4320
4318 With no revision specified, revert the specified files or directories
4321 With no revision specified, revert the specified files or directories
4319 to the contents they had in the parent of the working directory.
4322 to the contents they had in the parent of the working directory.
4320 This restores the contents of files to an unmodified
4323 This restores the contents of files to an unmodified
4321 state and unschedules adds, removes, copies, and renames. If the
4324 state and unschedules adds, removes, copies, and renames. If the
4322 working directory has two parents, you must explicitly specify a
4325 working directory has two parents, you must explicitly specify a
4323 revision.
4326 revision.
4324
4327
4325 Using the -r/--rev or -d/--date options, revert the given files or
4328 Using the -r/--rev or -d/--date options, revert the given files or
4326 directories to their states as of a specific revision. Because
4329 directories to their states as of a specific revision. Because
4327 revert does not change the working directory parents, this will
4330 revert does not change the working directory parents, this will
4328 cause these files to appear modified. This can be helpful to "back
4331 cause these files to appear modified. This can be helpful to "back
4329 out" some or all of an earlier change. See :hg:`backout` for a
4332 out" some or all of an earlier change. See :hg:`backout` for a
4330 related method.
4333 related method.
4331
4334
4332 Modified files are saved with a .orig suffix before reverting.
4335 Modified files are saved with a .orig suffix before reverting.
4333 To disable these backups, use --no-backup.
4336 To disable these backups, use --no-backup.
4334
4337
4335 See :hg:`help dates` for a list of formats valid for -d/--date.
4338 See :hg:`help dates` for a list of formats valid for -d/--date.
4336
4339
4337 Returns 0 on success.
4340 Returns 0 on success.
4338 """
4341 """
4339
4342
4340 if opts.get("date"):
4343 if opts.get("date"):
4341 if opts.get("rev"):
4344 if opts.get("rev"):
4342 raise util.Abort(_("you can't specify a revision and a date"))
4345 raise util.Abort(_("you can't specify a revision and a date"))
4343 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4346 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4344
4347
4345 parent, p2 = repo.dirstate.parents()
4348 parent, p2 = repo.dirstate.parents()
4346 if not opts.get('rev') and p2 != nullid:
4349 if not opts.get('rev') and p2 != nullid:
4347 # revert after merge is a trap for new users (issue2915)
4350 # revert after merge is a trap for new users (issue2915)
4348 raise util.Abort(_('uncommitted merge with no revision specified'),
4351 raise util.Abort(_('uncommitted merge with no revision specified'),
4349 hint=_('use "hg update" or see "hg help revert"'))
4352 hint=_('use "hg update" or see "hg help revert"'))
4350
4353
4351 ctx = scmutil.revsingle(repo, opts.get('rev'))
4354 ctx = scmutil.revsingle(repo, opts.get('rev'))
4352 node = ctx.node()
4355 node = ctx.node()
4353
4356
4354 if not pats and not opts.get('all'):
4357 if not pats and not opts.get('all'):
4355 msg = _("no files or directories specified")
4358 msg = _("no files or directories specified")
4356 if p2 != nullid:
4359 if p2 != nullid:
4357 hint = _("uncommitted merge, use --all to discard all changes,"
4360 hint = _("uncommitted merge, use --all to discard all changes,"
4358 " or 'hg update -C .' to abort the merge")
4361 " or 'hg update -C .' to abort the merge")
4359 raise util.Abort(msg, hint=hint)
4362 raise util.Abort(msg, hint=hint)
4360 dirty = util.any(repo.status())
4363 dirty = util.any(repo.status())
4361 if node != parent:
4364 if node != parent:
4362 if dirty:
4365 if dirty:
4363 hint = _("uncommitted changes, use --all to discard all"
4366 hint = _("uncommitted changes, use --all to discard all"
4364 " changes, or 'hg update %s' to update") % ctx.rev()
4367 " changes, or 'hg update %s' to update") % ctx.rev()
4365 else:
4368 else:
4366 hint = _("use --all to revert all files,"
4369 hint = _("use --all to revert all files,"
4367 " or 'hg update %s' to update") % ctx.rev()
4370 " or 'hg update %s' to update") % ctx.rev()
4368 elif dirty:
4371 elif dirty:
4369 hint = _("uncommitted changes, use --all to discard all changes")
4372 hint = _("uncommitted changes, use --all to discard all changes")
4370 else:
4373 else:
4371 hint = _("use --all to revert all files")
4374 hint = _("use --all to revert all files")
4372 raise util.Abort(msg, hint=hint)
4375 raise util.Abort(msg, hint=hint)
4373
4376
4374 mf = ctx.manifest()
4377 mf = ctx.manifest()
4375 if node == parent:
4378 if node == parent:
4376 pmf = mf
4379 pmf = mf
4377 else:
4380 else:
4378 pmf = None
4381 pmf = None
4379
4382
4380 # need all matching names in dirstate and manifest of target rev,
4383 # need all matching names in dirstate and manifest of target rev,
4381 # so have to walk both. do not print errors if files exist in one
4384 # so have to walk both. do not print errors if files exist in one
4382 # but not other.
4385 # but not other.
4383
4386
4384 names = {}
4387 names = {}
4385
4388
4386 wlock = repo.wlock()
4389 wlock = repo.wlock()
4387 try:
4390 try:
4388 # walk dirstate.
4391 # walk dirstate.
4389
4392
4390 m = scmutil.match(repo[None], pats, opts)
4393 m = scmutil.match(repo[None], pats, opts)
4391 m.bad = lambda x, y: False
4394 m.bad = lambda x, y: False
4392 for abs in repo.walk(m):
4395 for abs in repo.walk(m):
4393 names[abs] = m.rel(abs), m.exact(abs)
4396 names[abs] = m.rel(abs), m.exact(abs)
4394
4397
4395 # walk target manifest.
4398 # walk target manifest.
4396
4399
4397 def badfn(path, msg):
4400 def badfn(path, msg):
4398 if path in names:
4401 if path in names:
4399 return
4402 return
4400 path_ = path + '/'
4403 path_ = path + '/'
4401 for f in names:
4404 for f in names:
4402 if f.startswith(path_):
4405 if f.startswith(path_):
4403 return
4406 return
4404 ui.warn("%s: %s\n" % (m.rel(path), msg))
4407 ui.warn("%s: %s\n" % (m.rel(path), msg))
4405
4408
4406 m = scmutil.match(repo[node], pats, opts)
4409 m = scmutil.match(repo[node], pats, opts)
4407 m.bad = badfn
4410 m.bad = badfn
4408 for abs in repo[node].walk(m):
4411 for abs in repo[node].walk(m):
4409 if abs not in names:
4412 if abs not in names:
4410 names[abs] = m.rel(abs), m.exact(abs)
4413 names[abs] = m.rel(abs), m.exact(abs)
4411
4414
4412 m = scmutil.matchfiles(repo, names)
4415 m = scmutil.matchfiles(repo, names)
4413 changes = repo.status(match=m)[:4]
4416 changes = repo.status(match=m)[:4]
4414 modified, added, removed, deleted = map(set, changes)
4417 modified, added, removed, deleted = map(set, changes)
4415
4418
4416 # if f is a rename, also revert the source
4419 # if f is a rename, also revert the source
4417 cwd = repo.getcwd()
4420 cwd = repo.getcwd()
4418 for f in added:
4421 for f in added:
4419 src = repo.dirstate.copied(f)
4422 src = repo.dirstate.copied(f)
4420 if src and src not in names and repo.dirstate[src] == 'r':
4423 if src and src not in names and repo.dirstate[src] == 'r':
4421 removed.add(src)
4424 removed.add(src)
4422 names[src] = (repo.pathto(src, cwd), True)
4425 names[src] = (repo.pathto(src, cwd), True)
4423
4426
4424 def removeforget(abs):
4427 def removeforget(abs):
4425 if repo.dirstate[abs] == 'a':
4428 if repo.dirstate[abs] == 'a':
4426 return _('forgetting %s\n')
4429 return _('forgetting %s\n')
4427 return _('removing %s\n')
4430 return _('removing %s\n')
4428
4431
4429 revert = ([], _('reverting %s\n'))
4432 revert = ([], _('reverting %s\n'))
4430 add = ([], _('adding %s\n'))
4433 add = ([], _('adding %s\n'))
4431 remove = ([], removeforget)
4434 remove = ([], removeforget)
4432 undelete = ([], _('undeleting %s\n'))
4435 undelete = ([], _('undeleting %s\n'))
4433
4436
4434 disptable = (
4437 disptable = (
4435 # dispatch table:
4438 # dispatch table:
4436 # file state
4439 # file state
4437 # action if in target manifest
4440 # action if in target manifest
4438 # action if not in target manifest
4441 # action if not in target manifest
4439 # make backup if in target manifest
4442 # make backup if in target manifest
4440 # make backup if not in target manifest
4443 # make backup if not in target manifest
4441 (modified, revert, remove, True, True),
4444 (modified, revert, remove, True, True),
4442 (added, revert, remove, True, False),
4445 (added, revert, remove, True, False),
4443 (removed, undelete, None, False, False),
4446 (removed, undelete, None, False, False),
4444 (deleted, revert, remove, False, False),
4447 (deleted, revert, remove, False, False),
4445 )
4448 )
4446
4449
4447 for abs, (rel, exact) in sorted(names.items()):
4450 for abs, (rel, exact) in sorted(names.items()):
4448 mfentry = mf.get(abs)
4451 mfentry = mf.get(abs)
4449 target = repo.wjoin(abs)
4452 target = repo.wjoin(abs)
4450 def handle(xlist, dobackup):
4453 def handle(xlist, dobackup):
4451 xlist[0].append(abs)
4454 xlist[0].append(abs)
4452 if (dobackup and not opts.get('no_backup') and
4455 if (dobackup and not opts.get('no_backup') and
4453 os.path.lexists(target)):
4456 os.path.lexists(target)):
4454 bakname = "%s.orig" % rel
4457 bakname = "%s.orig" % rel
4455 ui.note(_('saving current version of %s as %s\n') %
4458 ui.note(_('saving current version of %s as %s\n') %
4456 (rel, bakname))
4459 (rel, bakname))
4457 if not opts.get('dry_run'):
4460 if not opts.get('dry_run'):
4458 util.rename(target, bakname)
4461 util.rename(target, bakname)
4459 if ui.verbose or not exact:
4462 if ui.verbose or not exact:
4460 msg = xlist[1]
4463 msg = xlist[1]
4461 if not isinstance(msg, basestring):
4464 if not isinstance(msg, basestring):
4462 msg = msg(abs)
4465 msg = msg(abs)
4463 ui.status(msg % rel)
4466 ui.status(msg % rel)
4464 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4467 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4465 if abs not in table:
4468 if abs not in table:
4466 continue
4469 continue
4467 # file has changed in dirstate
4470 # file has changed in dirstate
4468 if mfentry:
4471 if mfentry:
4469 handle(hitlist, backuphit)
4472 handle(hitlist, backuphit)
4470 elif misslist is not None:
4473 elif misslist is not None:
4471 handle(misslist, backupmiss)
4474 handle(misslist, backupmiss)
4472 break
4475 break
4473 else:
4476 else:
4474 if abs not in repo.dirstate:
4477 if abs not in repo.dirstate:
4475 if mfentry:
4478 if mfentry:
4476 handle(add, True)
4479 handle(add, True)
4477 elif exact:
4480 elif exact:
4478 ui.warn(_('file not managed: %s\n') % rel)
4481 ui.warn(_('file not managed: %s\n') % rel)
4479 continue
4482 continue
4480 # file has not changed in dirstate
4483 # file has not changed in dirstate
4481 if node == parent:
4484 if node == parent:
4482 if exact:
4485 if exact:
4483 ui.warn(_('no changes needed to %s\n') % rel)
4486 ui.warn(_('no changes needed to %s\n') % rel)
4484 continue
4487 continue
4485 if pmf is None:
4488 if pmf is None:
4486 # only need parent manifest in this unlikely case,
4489 # only need parent manifest in this unlikely case,
4487 # so do not read by default
4490 # so do not read by default
4488 pmf = repo[parent].manifest()
4491 pmf = repo[parent].manifest()
4489 if abs in pmf:
4492 if abs in pmf:
4490 if mfentry:
4493 if mfentry:
4491 # if version of file is same in parent and target
4494 # if version of file is same in parent and target
4492 # manifests, do nothing
4495 # manifests, do nothing
4493 if (pmf[abs] != mfentry or
4496 if (pmf[abs] != mfentry or
4494 pmf.flags(abs) != mf.flags(abs)):
4497 pmf.flags(abs) != mf.flags(abs)):
4495 handle(revert, False)
4498 handle(revert, False)
4496 else:
4499 else:
4497 handle(remove, False)
4500 handle(remove, False)
4498
4501
4499 if not opts.get('dry_run'):
4502 if not opts.get('dry_run'):
4500 def checkout(f):
4503 def checkout(f):
4501 fc = ctx[f]
4504 fc = ctx[f]
4502 repo.wwrite(f, fc.data(), fc.flags())
4505 repo.wwrite(f, fc.data(), fc.flags())
4503
4506
4504 audit_path = scmutil.pathauditor(repo.root)
4507 audit_path = scmutil.pathauditor(repo.root)
4505 for f in remove[0]:
4508 for f in remove[0]:
4506 if repo.dirstate[f] == 'a':
4509 if repo.dirstate[f] == 'a':
4507 repo.dirstate.drop(f)
4510 repo.dirstate.drop(f)
4508 continue
4511 continue
4509 audit_path(f)
4512 audit_path(f)
4510 try:
4513 try:
4511 util.unlinkpath(repo.wjoin(f))
4514 util.unlinkpath(repo.wjoin(f))
4512 except OSError:
4515 except OSError:
4513 pass
4516 pass
4514 repo.dirstate.remove(f)
4517 repo.dirstate.remove(f)
4515
4518
4516 normal = None
4519 normal = None
4517 if node == parent:
4520 if node == parent:
4518 # We're reverting to our parent. If possible, we'd like status
4521 # We're reverting to our parent. If possible, we'd like status
4519 # to report the file as clean. We have to use normallookup for
4522 # to report the file as clean. We have to use normallookup for
4520 # merges to avoid losing information about merged/dirty files.
4523 # merges to avoid losing information about merged/dirty files.
4521 if p2 != nullid:
4524 if p2 != nullid:
4522 normal = repo.dirstate.normallookup
4525 normal = repo.dirstate.normallookup
4523 else:
4526 else:
4524 normal = repo.dirstate.normal
4527 normal = repo.dirstate.normal
4525 for f in revert[0]:
4528 for f in revert[0]:
4526 checkout(f)
4529 checkout(f)
4527 if normal:
4530 if normal:
4528 normal(f)
4531 normal(f)
4529
4532
4530 for f in add[0]:
4533 for f in add[0]:
4531 checkout(f)
4534 checkout(f)
4532 repo.dirstate.add(f)
4535 repo.dirstate.add(f)
4533
4536
4534 normal = repo.dirstate.normallookup
4537 normal = repo.dirstate.normallookup
4535 if node == parent and p2 == nullid:
4538 if node == parent and p2 == nullid:
4536 normal = repo.dirstate.normal
4539 normal = repo.dirstate.normal
4537 for f in undelete[0]:
4540 for f in undelete[0]:
4538 checkout(f)
4541 checkout(f)
4539 normal(f)
4542 normal(f)
4540
4543
4541 finally:
4544 finally:
4542 wlock.release()
4545 wlock.release()
4543
4546
4544 @command('rollback', dryrunopts)
4547 @command('rollback', dryrunopts)
4545 def rollback(ui, repo, **opts):
4548 def rollback(ui, repo, **opts):
4546 """roll back the last transaction (dangerous)
4549 """roll back the last transaction (dangerous)
4547
4550
4548 This command should be used with care. There is only one level of
4551 This command should be used with care. There is only one level of
4549 rollback, and there is no way to undo a rollback. It will also
4552 rollback, and there is no way to undo a rollback. It will also
4550 restore the dirstate at the time of the last transaction, losing
4553 restore the dirstate at the time of the last transaction, losing
4551 any dirstate changes since that time. This command does not alter
4554 any dirstate changes since that time. This command does not alter
4552 the working directory.
4555 the working directory.
4553
4556
4554 Transactions are used to encapsulate the effects of all commands
4557 Transactions are used to encapsulate the effects of all commands
4555 that create new changesets or propagate existing changesets into a
4558 that create new changesets or propagate existing changesets into a
4556 repository. For example, the following commands are transactional,
4559 repository. For example, the following commands are transactional,
4557 and their effects can be rolled back:
4560 and their effects can be rolled back:
4558
4561
4559 - commit
4562 - commit
4560 - import
4563 - import
4561 - pull
4564 - pull
4562 - push (with this repository as the destination)
4565 - push (with this repository as the destination)
4563 - unbundle
4566 - unbundle
4564
4567
4565 This command is not intended for use on public repositories. Once
4568 This command is not intended for use on public repositories. Once
4566 changes are visible for pull by other users, rolling a transaction
4569 changes are visible for pull by other users, rolling a transaction
4567 back locally is ineffective (someone else may already have pulled
4570 back locally is ineffective (someone else may already have pulled
4568 the changes). Furthermore, a race is possible with readers of the
4571 the changes). Furthermore, a race is possible with readers of the
4569 repository; for example an in-progress pull from the repository
4572 repository; for example an in-progress pull from the repository
4570 may fail if a rollback is performed.
4573 may fail if a rollback is performed.
4571
4574
4572 Returns 0 on success, 1 if no rollback data is available.
4575 Returns 0 on success, 1 if no rollback data is available.
4573 """
4576 """
4574 return repo.rollback(opts.get('dry_run'))
4577 return repo.rollback(opts.get('dry_run'))
4575
4578
4576 @command('root', [])
4579 @command('root', [])
4577 def root(ui, repo):
4580 def root(ui, repo):
4578 """print the root (top) of the current working directory
4581 """print the root (top) of the current working directory
4579
4582
4580 Print the root directory of the current repository.
4583 Print the root directory of the current repository.
4581
4584
4582 Returns 0 on success.
4585 Returns 0 on success.
4583 """
4586 """
4584 ui.write(repo.root + "\n")
4587 ui.write(repo.root + "\n")
4585
4588
4586 @command('^serve',
4589 @command('^serve',
4587 [('A', 'accesslog', '', _('name of access log file to write to'),
4590 [('A', 'accesslog', '', _('name of access log file to write to'),
4588 _('FILE')),
4591 _('FILE')),
4589 ('d', 'daemon', None, _('run server in background')),
4592 ('d', 'daemon', None, _('run server in background')),
4590 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4593 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4591 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4594 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4592 # use string type, then we can check if something was passed
4595 # use string type, then we can check if something was passed
4593 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4596 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4594 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4597 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4595 _('ADDR')),
4598 _('ADDR')),
4596 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4599 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4597 _('PREFIX')),
4600 _('PREFIX')),
4598 ('n', 'name', '',
4601 ('n', 'name', '',
4599 _('name to show in web pages (default: working directory)'), _('NAME')),
4602 _('name to show in web pages (default: working directory)'), _('NAME')),
4600 ('', 'web-conf', '',
4603 ('', 'web-conf', '',
4601 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4604 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4602 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4605 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4603 _('FILE')),
4606 _('FILE')),
4604 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4607 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4605 ('', 'stdio', None, _('for remote clients')),
4608 ('', 'stdio', None, _('for remote clients')),
4606 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4609 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4607 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4610 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4608 ('', 'style', '', _('template style to use'), _('STYLE')),
4611 ('', 'style', '', _('template style to use'), _('STYLE')),
4609 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4612 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4610 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4613 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4611 _('[OPTION]...'))
4614 _('[OPTION]...'))
4612 def serve(ui, repo, **opts):
4615 def serve(ui, repo, **opts):
4613 """start stand-alone webserver
4616 """start stand-alone webserver
4614
4617
4615 Start a local HTTP repository browser and pull server. You can use
4618 Start a local HTTP repository browser and pull server. You can use
4616 this for ad-hoc sharing and browsing of repositories. It is
4619 this for ad-hoc sharing and browsing of repositories. It is
4617 recommended to use a real web server to serve a repository for
4620 recommended to use a real web server to serve a repository for
4618 longer periods of time.
4621 longer periods of time.
4619
4622
4620 Please note that the server does not implement access control.
4623 Please note that the server does not implement access control.
4621 This means that, by default, anybody can read from the server and
4624 This means that, by default, anybody can read from the server and
4622 nobody can write to it by default. Set the ``web.allow_push``
4625 nobody can write to it by default. Set the ``web.allow_push``
4623 option to ``*`` to allow everybody to push to the server. You
4626 option to ``*`` to allow everybody to push to the server. You
4624 should use a real web server if you need to authenticate users.
4627 should use a real web server if you need to authenticate users.
4625
4628
4626 By default, the server logs accesses to stdout and errors to
4629 By default, the server logs accesses to stdout and errors to
4627 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4630 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4628 files.
4631 files.
4629
4632
4630 To have the server choose a free port number to listen on, specify
4633 To have the server choose a free port number to listen on, specify
4631 a port number of 0; in this case, the server will print the port
4634 a port number of 0; in this case, the server will print the port
4632 number it uses.
4635 number it uses.
4633
4636
4634 Returns 0 on success.
4637 Returns 0 on success.
4635 """
4638 """
4636
4639
4637 if opts["stdio"] and opts["cmdserver"]:
4640 if opts["stdio"] and opts["cmdserver"]:
4638 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4641 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4639
4642
4640 def checkrepo():
4643 def checkrepo():
4641 if repo is None:
4644 if repo is None:
4642 raise error.RepoError(_("There is no Mercurial repository here"
4645 raise error.RepoError(_("There is no Mercurial repository here"
4643 " (.hg not found)"))
4646 " (.hg not found)"))
4644
4647
4645 if opts["stdio"]:
4648 if opts["stdio"]:
4646 checkrepo()
4649 checkrepo()
4647 s = sshserver.sshserver(ui, repo)
4650 s = sshserver.sshserver(ui, repo)
4648 s.serve_forever()
4651 s.serve_forever()
4649
4652
4650 if opts["cmdserver"]:
4653 if opts["cmdserver"]:
4651 checkrepo()
4654 checkrepo()
4652 s = commandserver.server(ui, repo, opts["cmdserver"])
4655 s = commandserver.server(ui, repo, opts["cmdserver"])
4653 return s.serve()
4656 return s.serve()
4654
4657
4655 # this way we can check if something was given in the command-line
4658 # this way we can check if something was given in the command-line
4656 if opts.get('port'):
4659 if opts.get('port'):
4657 opts['port'] = util.getport(opts.get('port'))
4660 opts['port'] = util.getport(opts.get('port'))
4658
4661
4659 baseui = repo and repo.baseui or ui
4662 baseui = repo and repo.baseui or ui
4660 optlist = ("name templates style address port prefix ipv6"
4663 optlist = ("name templates style address port prefix ipv6"
4661 " accesslog errorlog certificate encoding")
4664 " accesslog errorlog certificate encoding")
4662 for o in optlist.split():
4665 for o in optlist.split():
4663 val = opts.get(o, '')
4666 val = opts.get(o, '')
4664 if val in (None, ''): # should check against default options instead
4667 if val in (None, ''): # should check against default options instead
4665 continue
4668 continue
4666 baseui.setconfig("web", o, val)
4669 baseui.setconfig("web", o, val)
4667 if repo and repo.ui != baseui:
4670 if repo and repo.ui != baseui:
4668 repo.ui.setconfig("web", o, val)
4671 repo.ui.setconfig("web", o, val)
4669
4672
4670 o = opts.get('web_conf') or opts.get('webdir_conf')
4673 o = opts.get('web_conf') or opts.get('webdir_conf')
4671 if not o:
4674 if not o:
4672 if not repo:
4675 if not repo:
4673 raise error.RepoError(_("There is no Mercurial repository"
4676 raise error.RepoError(_("There is no Mercurial repository"
4674 " here (.hg not found)"))
4677 " here (.hg not found)"))
4675 o = repo.root
4678 o = repo.root
4676
4679
4677 app = hgweb.hgweb(o, baseui=ui)
4680 app = hgweb.hgweb(o, baseui=ui)
4678
4681
4679 class service(object):
4682 class service(object):
4680 def init(self):
4683 def init(self):
4681 util.setsignalhandler()
4684 util.setsignalhandler()
4682 self.httpd = hgweb.server.create_server(ui, app)
4685 self.httpd = hgweb.server.create_server(ui, app)
4683
4686
4684 if opts['port'] and not ui.verbose:
4687 if opts['port'] and not ui.verbose:
4685 return
4688 return
4686
4689
4687 if self.httpd.prefix:
4690 if self.httpd.prefix:
4688 prefix = self.httpd.prefix.strip('/') + '/'
4691 prefix = self.httpd.prefix.strip('/') + '/'
4689 else:
4692 else:
4690 prefix = ''
4693 prefix = ''
4691
4694
4692 port = ':%d' % self.httpd.port
4695 port = ':%d' % self.httpd.port
4693 if port == ':80':
4696 if port == ':80':
4694 port = ''
4697 port = ''
4695
4698
4696 bindaddr = self.httpd.addr
4699 bindaddr = self.httpd.addr
4697 if bindaddr == '0.0.0.0':
4700 if bindaddr == '0.0.0.0':
4698 bindaddr = '*'
4701 bindaddr = '*'
4699 elif ':' in bindaddr: # IPv6
4702 elif ':' in bindaddr: # IPv6
4700 bindaddr = '[%s]' % bindaddr
4703 bindaddr = '[%s]' % bindaddr
4701
4704
4702 fqaddr = self.httpd.fqaddr
4705 fqaddr = self.httpd.fqaddr
4703 if ':' in fqaddr:
4706 if ':' in fqaddr:
4704 fqaddr = '[%s]' % fqaddr
4707 fqaddr = '[%s]' % fqaddr
4705 if opts['port']:
4708 if opts['port']:
4706 write = ui.status
4709 write = ui.status
4707 else:
4710 else:
4708 write = ui.write
4711 write = ui.write
4709 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4712 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4710 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4713 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4711
4714
4712 def run(self):
4715 def run(self):
4713 self.httpd.serve_forever()
4716 self.httpd.serve_forever()
4714
4717
4715 service = service()
4718 service = service()
4716
4719
4717 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4720 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4718
4721
4719 @command('showconfig|debugconfig',
4722 @command('showconfig|debugconfig',
4720 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4723 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4721 _('[-u] [NAME]...'))
4724 _('[-u] [NAME]...'))
4722 def showconfig(ui, repo, *values, **opts):
4725 def showconfig(ui, repo, *values, **opts):
4723 """show combined config settings from all hgrc files
4726 """show combined config settings from all hgrc files
4724
4727
4725 With no arguments, print names and values of all config items.
4728 With no arguments, print names and values of all config items.
4726
4729
4727 With one argument of the form section.name, print just the value
4730 With one argument of the form section.name, print just the value
4728 of that config item.
4731 of that config item.
4729
4732
4730 With multiple arguments, print names and values of all config
4733 With multiple arguments, print names and values of all config
4731 items with matching section names.
4734 items with matching section names.
4732
4735
4733 With --debug, the source (filename and line number) is printed
4736 With --debug, the source (filename and line number) is printed
4734 for each config item.
4737 for each config item.
4735
4738
4736 Returns 0 on success.
4739 Returns 0 on success.
4737 """
4740 """
4738
4741
4739 for f in scmutil.rcpath():
4742 for f in scmutil.rcpath():
4740 ui.debug('read config from: %s\n' % f)
4743 ui.debug('read config from: %s\n' % f)
4741 untrusted = bool(opts.get('untrusted'))
4744 untrusted = bool(opts.get('untrusted'))
4742 if values:
4745 if values:
4743 sections = [v for v in values if '.' not in v]
4746 sections = [v for v in values if '.' not in v]
4744 items = [v for v in values if '.' in v]
4747 items = [v for v in values if '.' in v]
4745 if len(items) > 1 or items and sections:
4748 if len(items) > 1 or items and sections:
4746 raise util.Abort(_('only one config item permitted'))
4749 raise util.Abort(_('only one config item permitted'))
4747 for section, name, value in ui.walkconfig(untrusted=untrusted):
4750 for section, name, value in ui.walkconfig(untrusted=untrusted):
4748 value = str(value).replace('\n', '\\n')
4751 value = str(value).replace('\n', '\\n')
4749 sectname = section + '.' + name
4752 sectname = section + '.' + name
4750 if values:
4753 if values:
4751 for v in values:
4754 for v in values:
4752 if v == section:
4755 if v == section:
4753 ui.debug('%s: ' %
4756 ui.debug('%s: ' %
4754 ui.configsource(section, name, untrusted))
4757 ui.configsource(section, name, untrusted))
4755 ui.write('%s=%s\n' % (sectname, value))
4758 ui.write('%s=%s\n' % (sectname, value))
4756 elif v == sectname:
4759 elif v == sectname:
4757 ui.debug('%s: ' %
4760 ui.debug('%s: ' %
4758 ui.configsource(section, name, untrusted))
4761 ui.configsource(section, name, untrusted))
4759 ui.write(value, '\n')
4762 ui.write(value, '\n')
4760 else:
4763 else:
4761 ui.debug('%s: ' %
4764 ui.debug('%s: ' %
4762 ui.configsource(section, name, untrusted))
4765 ui.configsource(section, name, untrusted))
4763 ui.write('%s=%s\n' % (sectname, value))
4766 ui.write('%s=%s\n' % (sectname, value))
4764
4767
4765 @command('^status|st',
4768 @command('^status|st',
4766 [('A', 'all', None, _('show status of all files')),
4769 [('A', 'all', None, _('show status of all files')),
4767 ('m', 'modified', None, _('show only modified files')),
4770 ('m', 'modified', None, _('show only modified files')),
4768 ('a', 'added', None, _('show only added files')),
4771 ('a', 'added', None, _('show only added files')),
4769 ('r', 'removed', None, _('show only removed files')),
4772 ('r', 'removed', None, _('show only removed files')),
4770 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4773 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4771 ('c', 'clean', None, _('show only files without changes')),
4774 ('c', 'clean', None, _('show only files without changes')),
4772 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4775 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4773 ('i', 'ignored', None, _('show only ignored files')),
4776 ('i', 'ignored', None, _('show only ignored files')),
4774 ('n', 'no-status', None, _('hide status prefix')),
4777 ('n', 'no-status', None, _('hide status prefix')),
4775 ('C', 'copies', None, _('show source of copied files')),
4778 ('C', 'copies', None, _('show source of copied files')),
4776 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4779 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4777 ('', 'rev', [], _('show difference from revision'), _('REV')),
4780 ('', 'rev', [], _('show difference from revision'), _('REV')),
4778 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4781 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4779 ] + walkopts + subrepoopts,
4782 ] + walkopts + subrepoopts,
4780 _('[OPTION]... [FILE]...'))
4783 _('[OPTION]... [FILE]...'))
4781 def status(ui, repo, *pats, **opts):
4784 def status(ui, repo, *pats, **opts):
4782 """show changed files in the working directory
4785 """show changed files in the working directory
4783
4786
4784 Show status of files in the repository. If names are given, only
4787 Show status of files in the repository. If names are given, only
4785 files that match are shown. Files that are clean or ignored or
4788 files that match are shown. Files that are clean or ignored or
4786 the source of a copy/move operation, are not listed unless
4789 the source of a copy/move operation, are not listed unless
4787 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4790 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4788 Unless options described with "show only ..." are given, the
4791 Unless options described with "show only ..." are given, the
4789 options -mardu are used.
4792 options -mardu are used.
4790
4793
4791 Option -q/--quiet hides untracked (unknown and ignored) files
4794 Option -q/--quiet hides untracked (unknown and ignored) files
4792 unless explicitly requested with -u/--unknown or -i/--ignored.
4795 unless explicitly requested with -u/--unknown or -i/--ignored.
4793
4796
4794 .. note::
4797 .. note::
4795 status may appear to disagree with diff if permissions have
4798 status may appear to disagree with diff if permissions have
4796 changed or a merge has occurred. The standard diff format does
4799 changed or a merge has occurred. The standard diff format does
4797 not report permission changes and diff only reports changes
4800 not report permission changes and diff only reports changes
4798 relative to one merge parent.
4801 relative to one merge parent.
4799
4802
4800 If one revision is given, it is used as the base revision.
4803 If one revision is given, it is used as the base revision.
4801 If two revisions are given, the differences between them are
4804 If two revisions are given, the differences between them are
4802 shown. The --change option can also be used as a shortcut to list
4805 shown. The --change option can also be used as a shortcut to list
4803 the changed files of a revision from its first parent.
4806 the changed files of a revision from its first parent.
4804
4807
4805 The codes used to show the status of files are::
4808 The codes used to show the status of files are::
4806
4809
4807 M = modified
4810 M = modified
4808 A = added
4811 A = added
4809 R = removed
4812 R = removed
4810 C = clean
4813 C = clean
4811 ! = missing (deleted by non-hg command, but still tracked)
4814 ! = missing (deleted by non-hg command, but still tracked)
4812 ? = not tracked
4815 ? = not tracked
4813 I = ignored
4816 I = ignored
4814 = origin of the previous file listed as A (added)
4817 = origin of the previous file listed as A (added)
4815
4818
4816 .. container:: verbose
4819 .. container:: verbose
4817
4820
4818 Examples:
4821 Examples:
4819
4822
4820 - show changes in the working directory relative to a changeset:
4823 - show changes in the working directory relative to a changeset:
4821
4824
4822 hg status --rev 9353
4825 hg status --rev 9353
4823
4826
4824 - show all changes including copies in an existing changeset::
4827 - show all changes including copies in an existing changeset::
4825
4828
4826 hg status --copies --change 9353
4829 hg status --copies --change 9353
4827
4830
4828 - get a NUL separated list of added files, suitable for xargs::
4831 - get a NUL separated list of added files, suitable for xargs::
4829
4832
4830 hg status -an0
4833 hg status -an0
4831
4834
4832 Returns 0 on success.
4835 Returns 0 on success.
4833 """
4836 """
4834
4837
4835 revs = opts.get('rev')
4838 revs = opts.get('rev')
4836 change = opts.get('change')
4839 change = opts.get('change')
4837
4840
4838 if revs and change:
4841 if revs and change:
4839 msg = _('cannot specify --rev and --change at the same time')
4842 msg = _('cannot specify --rev and --change at the same time')
4840 raise util.Abort(msg)
4843 raise util.Abort(msg)
4841 elif change:
4844 elif change:
4842 node2 = repo.lookup(change)
4845 node2 = repo.lookup(change)
4843 node1 = repo[node2].p1().node()
4846 node1 = repo[node2].p1().node()
4844 else:
4847 else:
4845 node1, node2 = scmutil.revpair(repo, revs)
4848 node1, node2 = scmutil.revpair(repo, revs)
4846
4849
4847 cwd = (pats and repo.getcwd()) or ''
4850 cwd = (pats and repo.getcwd()) or ''
4848 end = opts.get('print0') and '\0' or '\n'
4851 end = opts.get('print0') and '\0' or '\n'
4849 copy = {}
4852 copy = {}
4850 states = 'modified added removed deleted unknown ignored clean'.split()
4853 states = 'modified added removed deleted unknown ignored clean'.split()
4851 show = [k for k in states if opts.get(k)]
4854 show = [k for k in states if opts.get(k)]
4852 if opts.get('all'):
4855 if opts.get('all'):
4853 show += ui.quiet and (states[:4] + ['clean']) or states
4856 show += ui.quiet and (states[:4] + ['clean']) or states
4854 if not show:
4857 if not show:
4855 show = ui.quiet and states[:4] or states[:5]
4858 show = ui.quiet and states[:4] or states[:5]
4856
4859
4857 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4860 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4858 'ignored' in show, 'clean' in show, 'unknown' in show,
4861 'ignored' in show, 'clean' in show, 'unknown' in show,
4859 opts.get('subrepos'))
4862 opts.get('subrepos'))
4860 changestates = zip(states, 'MAR!?IC', stat)
4863 changestates = zip(states, 'MAR!?IC', stat)
4861
4864
4862 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4865 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4863 ctxn = repo[nullid]
4866 ctxn = repo[nullid]
4864 ctx1 = repo[node1]
4867 ctx1 = repo[node1]
4865 ctx2 = repo[node2]
4868 ctx2 = repo[node2]
4866 added = stat[1]
4869 added = stat[1]
4867 if node2 is None:
4870 if node2 is None:
4868 added = stat[0] + stat[1] # merged?
4871 added = stat[0] + stat[1] # merged?
4869
4872
4870 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4873 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4871 if k in added:
4874 if k in added:
4872 copy[k] = v
4875 copy[k] = v
4873 elif v in added:
4876 elif v in added:
4874 copy[v] = k
4877 copy[v] = k
4875
4878
4876 for state, char, files in changestates:
4879 for state, char, files in changestates:
4877 if state in show:
4880 if state in show:
4878 format = "%s %%s%s" % (char, end)
4881 format = "%s %%s%s" % (char, end)
4879 if opts.get('no_status'):
4882 if opts.get('no_status'):
4880 format = "%%s%s" % end
4883 format = "%%s%s" % end
4881
4884
4882 for f in files:
4885 for f in files:
4883 ui.write(format % repo.pathto(f, cwd),
4886 ui.write(format % repo.pathto(f, cwd),
4884 label='status.' + state)
4887 label='status.' + state)
4885 if f in copy:
4888 if f in copy:
4886 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4889 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4887 label='status.copied')
4890 label='status.copied')
4888
4891
4889 @command('^summary|sum',
4892 @command('^summary|sum',
4890 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4893 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4891 def summary(ui, repo, **opts):
4894 def summary(ui, repo, **opts):
4892 """summarize working directory state
4895 """summarize working directory state
4893
4896
4894 This generates a brief summary of the working directory state,
4897 This generates a brief summary of the working directory state,
4895 including parents, branch, commit status, and available updates.
4898 including parents, branch, commit status, and available updates.
4896
4899
4897 With the --remote option, this will check the default paths for
4900 With the --remote option, this will check the default paths for
4898 incoming and outgoing changes. This can be time-consuming.
4901 incoming and outgoing changes. This can be time-consuming.
4899
4902
4900 Returns 0 on success.
4903 Returns 0 on success.
4901 """
4904 """
4902
4905
4903 ctx = repo[None]
4906 ctx = repo[None]
4904 parents = ctx.parents()
4907 parents = ctx.parents()
4905 pnode = parents[0].node()
4908 pnode = parents[0].node()
4906 marks = []
4909 marks = []
4907
4910
4908 for p in parents:
4911 for p in parents:
4909 # label with log.changeset (instead of log.parent) since this
4912 # label with log.changeset (instead of log.parent) since this
4910 # shows a working directory parent *changeset*:
4913 # shows a working directory parent *changeset*:
4911 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4914 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4912 label='log.changeset')
4915 label='log.changeset')
4913 ui.write(' '.join(p.tags()), label='log.tag')
4916 ui.write(' '.join(p.tags()), label='log.tag')
4914 if p.bookmarks():
4917 if p.bookmarks():
4915 marks.extend(p.bookmarks())
4918 marks.extend(p.bookmarks())
4916 if p.rev() == -1:
4919 if p.rev() == -1:
4917 if not len(repo):
4920 if not len(repo):
4918 ui.write(_(' (empty repository)'))
4921 ui.write(_(' (empty repository)'))
4919 else:
4922 else:
4920 ui.write(_(' (no revision checked out)'))
4923 ui.write(_(' (no revision checked out)'))
4921 ui.write('\n')
4924 ui.write('\n')
4922 if p.description():
4925 if p.description():
4923 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4926 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4924 label='log.summary')
4927 label='log.summary')
4925
4928
4926 branch = ctx.branch()
4929 branch = ctx.branch()
4927 bheads = repo.branchheads(branch)
4930 bheads = repo.branchheads(branch)
4928 m = _('branch: %s\n') % branch
4931 m = _('branch: %s\n') % branch
4929 if branch != 'default':
4932 if branch != 'default':
4930 ui.write(m, label='log.branch')
4933 ui.write(m, label='log.branch')
4931 else:
4934 else:
4932 ui.status(m, label='log.branch')
4935 ui.status(m, label='log.branch')
4933
4936
4934 if marks:
4937 if marks:
4935 current = repo._bookmarkcurrent
4938 current = repo._bookmarkcurrent
4936 ui.write(_('bookmarks:'), label='log.bookmark')
4939 ui.write(_('bookmarks:'), label='log.bookmark')
4937 if current is not None:
4940 if current is not None:
4938 try:
4941 try:
4939 marks.remove(current)
4942 marks.remove(current)
4940 ui.write(' *' + current, label='bookmarks.current')
4943 ui.write(' *' + current, label='bookmarks.current')
4941 except ValueError:
4944 except ValueError:
4942 # current bookmark not in parent ctx marks
4945 # current bookmark not in parent ctx marks
4943 pass
4946 pass
4944 for m in marks:
4947 for m in marks:
4945 ui.write(' ' + m, label='log.bookmark')
4948 ui.write(' ' + m, label='log.bookmark')
4946 ui.write('\n', label='log.bookmark')
4949 ui.write('\n', label='log.bookmark')
4947
4950
4948 st = list(repo.status(unknown=True))[:6]
4951 st = list(repo.status(unknown=True))[:6]
4949
4952
4950 c = repo.dirstate.copies()
4953 c = repo.dirstate.copies()
4951 copied, renamed = [], []
4954 copied, renamed = [], []
4952 for d, s in c.iteritems():
4955 for d, s in c.iteritems():
4953 if s in st[2]:
4956 if s in st[2]:
4954 st[2].remove(s)
4957 st[2].remove(s)
4955 renamed.append(d)
4958 renamed.append(d)
4956 else:
4959 else:
4957 copied.append(d)
4960 copied.append(d)
4958 if d in st[1]:
4961 if d in st[1]:
4959 st[1].remove(d)
4962 st[1].remove(d)
4960 st.insert(3, renamed)
4963 st.insert(3, renamed)
4961 st.insert(4, copied)
4964 st.insert(4, copied)
4962
4965
4963 ms = mergemod.mergestate(repo)
4966 ms = mergemod.mergestate(repo)
4964 st.append([f for f in ms if ms[f] == 'u'])
4967 st.append([f for f in ms if ms[f] == 'u'])
4965
4968
4966 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4969 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4967 st.append(subs)
4970 st.append(subs)
4968
4971
4969 labels = [ui.label(_('%d modified'), 'status.modified'),
4972 labels = [ui.label(_('%d modified'), 'status.modified'),
4970 ui.label(_('%d added'), 'status.added'),
4973 ui.label(_('%d added'), 'status.added'),
4971 ui.label(_('%d removed'), 'status.removed'),
4974 ui.label(_('%d removed'), 'status.removed'),
4972 ui.label(_('%d renamed'), 'status.copied'),
4975 ui.label(_('%d renamed'), 'status.copied'),
4973 ui.label(_('%d copied'), 'status.copied'),
4976 ui.label(_('%d copied'), 'status.copied'),
4974 ui.label(_('%d deleted'), 'status.deleted'),
4977 ui.label(_('%d deleted'), 'status.deleted'),
4975 ui.label(_('%d unknown'), 'status.unknown'),
4978 ui.label(_('%d unknown'), 'status.unknown'),
4976 ui.label(_('%d ignored'), 'status.ignored'),
4979 ui.label(_('%d ignored'), 'status.ignored'),
4977 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4980 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4978 ui.label(_('%d subrepos'), 'status.modified')]
4981 ui.label(_('%d subrepos'), 'status.modified')]
4979 t = []
4982 t = []
4980 for s, l in zip(st, labels):
4983 for s, l in zip(st, labels):
4981 if s:
4984 if s:
4982 t.append(l % len(s))
4985 t.append(l % len(s))
4983
4986
4984 t = ', '.join(t)
4987 t = ', '.join(t)
4985 cleanworkdir = False
4988 cleanworkdir = False
4986
4989
4987 if len(parents) > 1:
4990 if len(parents) > 1:
4988 t += _(' (merge)')
4991 t += _(' (merge)')
4989 elif branch != parents[0].branch():
4992 elif branch != parents[0].branch():
4990 t += _(' (new branch)')
4993 t += _(' (new branch)')
4991 elif (parents[0].extra().get('close') and
4994 elif (parents[0].extra().get('close') and
4992 pnode in repo.branchheads(branch, closed=True)):
4995 pnode in repo.branchheads(branch, closed=True)):
4993 t += _(' (head closed)')
4996 t += _(' (head closed)')
4994 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4997 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4995 t += _(' (clean)')
4998 t += _(' (clean)')
4996 cleanworkdir = True
4999 cleanworkdir = True
4997 elif pnode not in bheads:
5000 elif pnode not in bheads:
4998 t += _(' (new branch head)')
5001 t += _(' (new branch head)')
4999
5002
5000 if cleanworkdir:
5003 if cleanworkdir:
5001 ui.status(_('commit: %s\n') % t.strip())
5004 ui.status(_('commit: %s\n') % t.strip())
5002 else:
5005 else:
5003 ui.write(_('commit: %s\n') % t.strip())
5006 ui.write(_('commit: %s\n') % t.strip())
5004
5007
5005 # all ancestors of branch heads - all ancestors of parent = new csets
5008 # all ancestors of branch heads - all ancestors of parent = new csets
5006 new = [0] * len(repo)
5009 new = [0] * len(repo)
5007 cl = repo.changelog
5010 cl = repo.changelog
5008 for a in [cl.rev(n) for n in bheads]:
5011 for a in [cl.rev(n) for n in bheads]:
5009 new[a] = 1
5012 new[a] = 1
5010 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5013 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5011 new[a] = 1
5014 new[a] = 1
5012 for a in [p.rev() for p in parents]:
5015 for a in [p.rev() for p in parents]:
5013 if a >= 0:
5016 if a >= 0:
5014 new[a] = 0
5017 new[a] = 0
5015 for a in cl.ancestors(*[p.rev() for p in parents]):
5018 for a in cl.ancestors(*[p.rev() for p in parents]):
5016 new[a] = 0
5019 new[a] = 0
5017 new = sum(new)
5020 new = sum(new)
5018
5021
5019 if new == 0:
5022 if new == 0:
5020 ui.status(_('update: (current)\n'))
5023 ui.status(_('update: (current)\n'))
5021 elif pnode not in bheads:
5024 elif pnode not in bheads:
5022 ui.write(_('update: %d new changesets (update)\n') % new)
5025 ui.write(_('update: %d new changesets (update)\n') % new)
5023 else:
5026 else:
5024 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5027 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5025 (new, len(bheads)))
5028 (new, len(bheads)))
5026
5029
5027 if opts.get('remote'):
5030 if opts.get('remote'):
5028 t = []
5031 t = []
5029 source, branches = hg.parseurl(ui.expandpath('default'))
5032 source, branches = hg.parseurl(ui.expandpath('default'))
5030 other = hg.peer(repo, {}, source)
5033 other = hg.peer(repo, {}, source)
5031 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5034 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5032 ui.debug('comparing with %s\n' % util.hidepassword(source))
5035 ui.debug('comparing with %s\n' % util.hidepassword(source))
5033 repo.ui.pushbuffer()
5036 repo.ui.pushbuffer()
5034 commoninc = discovery.findcommonincoming(repo, other)
5037 commoninc = discovery.findcommonincoming(repo, other)
5035 _common, incoming, _rheads = commoninc
5038 _common, incoming, _rheads = commoninc
5036 repo.ui.popbuffer()
5039 repo.ui.popbuffer()
5037 if incoming:
5040 if incoming:
5038 t.append(_('1 or more incoming'))
5041 t.append(_('1 or more incoming'))
5039
5042
5040 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5043 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5041 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5044 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5042 if source != dest:
5045 if source != dest:
5043 other = hg.peer(repo, {}, dest)
5046 other = hg.peer(repo, {}, dest)
5044 commoninc = None
5047 commoninc = None
5045 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5048 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5046 repo.ui.pushbuffer()
5049 repo.ui.pushbuffer()
5047 common, outheads = discovery.findcommonoutgoing(repo, other,
5050 common, outheads = discovery.findcommonoutgoing(repo, other,
5048 commoninc=commoninc)
5051 commoninc=commoninc)
5049 repo.ui.popbuffer()
5052 repo.ui.popbuffer()
5050 o = repo.changelog.findmissing(common=common, heads=outheads)
5053 o = repo.changelog.findmissing(common=common, heads=outheads)
5051 if o:
5054 if o:
5052 t.append(_('%d outgoing') % len(o))
5055 t.append(_('%d outgoing') % len(o))
5053 if 'bookmarks' in other.listkeys('namespaces'):
5056 if 'bookmarks' in other.listkeys('namespaces'):
5054 lmarks = repo.listkeys('bookmarks')
5057 lmarks = repo.listkeys('bookmarks')
5055 rmarks = other.listkeys('bookmarks')
5058 rmarks = other.listkeys('bookmarks')
5056 diff = set(rmarks) - set(lmarks)
5059 diff = set(rmarks) - set(lmarks)
5057 if len(diff) > 0:
5060 if len(diff) > 0:
5058 t.append(_('%d incoming bookmarks') % len(diff))
5061 t.append(_('%d incoming bookmarks') % len(diff))
5059 diff = set(lmarks) - set(rmarks)
5062 diff = set(lmarks) - set(rmarks)
5060 if len(diff) > 0:
5063 if len(diff) > 0:
5061 t.append(_('%d outgoing bookmarks') % len(diff))
5064 t.append(_('%d outgoing bookmarks') % len(diff))
5062
5065
5063 if t:
5066 if t:
5064 ui.write(_('remote: %s\n') % (', '.join(t)))
5067 ui.write(_('remote: %s\n') % (', '.join(t)))
5065 else:
5068 else:
5066 ui.status(_('remote: (synced)\n'))
5069 ui.status(_('remote: (synced)\n'))
5067
5070
5068 @command('tag',
5071 @command('tag',
5069 [('f', 'force', None, _('force tag')),
5072 [('f', 'force', None, _('force tag')),
5070 ('l', 'local', None, _('make the tag local')),
5073 ('l', 'local', None, _('make the tag local')),
5071 ('r', 'rev', '', _('revision to tag'), _('REV')),
5074 ('r', 'rev', '', _('revision to tag'), _('REV')),
5072 ('', 'remove', None, _('remove a tag')),
5075 ('', 'remove', None, _('remove a tag')),
5073 # -l/--local is already there, commitopts cannot be used
5076 # -l/--local is already there, commitopts cannot be used
5074 ('e', 'edit', None, _('edit commit message')),
5077 ('e', 'edit', None, _('edit commit message')),
5075 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5078 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5076 ] + commitopts2,
5079 ] + commitopts2,
5077 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5080 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5078 def tag(ui, repo, name1, *names, **opts):
5081 def tag(ui, repo, name1, *names, **opts):
5079 """add one or more tags for the current or given revision
5082 """add one or more tags for the current or given revision
5080
5083
5081 Name a particular revision using <name>.
5084 Name a particular revision using <name>.
5082
5085
5083 Tags are used to name particular revisions of the repository and are
5086 Tags are used to name particular revisions of the repository and are
5084 very useful to compare different revisions, to go back to significant
5087 very useful to compare different revisions, to go back to significant
5085 earlier versions or to mark branch points as releases, etc. Changing
5088 earlier versions or to mark branch points as releases, etc. Changing
5086 an existing tag is normally disallowed; use -f/--force to override.
5089 an existing tag is normally disallowed; use -f/--force to override.
5087
5090
5088 If no revision is given, the parent of the working directory is
5091 If no revision is given, the parent of the working directory is
5089 used, or tip if no revision is checked out.
5092 used, or tip if no revision is checked out.
5090
5093
5091 To facilitate version control, distribution, and merging of tags,
5094 To facilitate version control, distribution, and merging of tags,
5092 they are stored as a file named ".hgtags" which is managed similarly
5095 they are stored as a file named ".hgtags" which is managed similarly
5093 to other project files and can be hand-edited if necessary. This
5096 to other project files and can be hand-edited if necessary. This
5094 also means that tagging creates a new commit. The file
5097 also means that tagging creates a new commit. The file
5095 ".hg/localtags" is used for local tags (not shared among
5098 ".hg/localtags" is used for local tags (not shared among
5096 repositories).
5099 repositories).
5097
5100
5098 Tag commits are usually made at the head of a branch. If the parent
5101 Tag commits are usually made at the head of a branch. If the parent
5099 of the working directory is not a branch head, :hg:`tag` aborts; use
5102 of the working directory is not a branch head, :hg:`tag` aborts; use
5100 -f/--force to force the tag commit to be based on a non-head
5103 -f/--force to force the tag commit to be based on a non-head
5101 changeset.
5104 changeset.
5102
5105
5103 See :hg:`help dates` for a list of formats valid for -d/--date.
5106 See :hg:`help dates` for a list of formats valid for -d/--date.
5104
5107
5105 Since tag names have priority over branch names during revision
5108 Since tag names have priority over branch names during revision
5106 lookup, using an existing branch name as a tag name is discouraged.
5109 lookup, using an existing branch name as a tag name is discouraged.
5107
5110
5108 Returns 0 on success.
5111 Returns 0 on success.
5109 """
5112 """
5110
5113
5111 rev_ = "."
5114 rev_ = "."
5112 names = [t.strip() for t in (name1,) + names]
5115 names = [t.strip() for t in (name1,) + names]
5113 if len(names) != len(set(names)):
5116 if len(names) != len(set(names)):
5114 raise util.Abort(_('tag names must be unique'))
5117 raise util.Abort(_('tag names must be unique'))
5115 for n in names:
5118 for n in names:
5116 if n in ['tip', '.', 'null']:
5119 if n in ['tip', '.', 'null']:
5117 raise util.Abort(_("the name '%s' is reserved") % n)
5120 raise util.Abort(_("the name '%s' is reserved") % n)
5118 if not n:
5121 if not n:
5119 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5122 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5120 if opts.get('rev') and opts.get('remove'):
5123 if opts.get('rev') and opts.get('remove'):
5121 raise util.Abort(_("--rev and --remove are incompatible"))
5124 raise util.Abort(_("--rev and --remove are incompatible"))
5122 if opts.get('rev'):
5125 if opts.get('rev'):
5123 rev_ = opts['rev']
5126 rev_ = opts['rev']
5124 message = opts.get('message')
5127 message = opts.get('message')
5125 if opts.get('remove'):
5128 if opts.get('remove'):
5126 expectedtype = opts.get('local') and 'local' or 'global'
5129 expectedtype = opts.get('local') and 'local' or 'global'
5127 for n in names:
5130 for n in names:
5128 if not repo.tagtype(n):
5131 if not repo.tagtype(n):
5129 raise util.Abort(_("tag '%s' does not exist") % n)
5132 raise util.Abort(_("tag '%s' does not exist") % n)
5130 if repo.tagtype(n) != expectedtype:
5133 if repo.tagtype(n) != expectedtype:
5131 if expectedtype == 'global':
5134 if expectedtype == 'global':
5132 raise util.Abort(_("tag '%s' is not a global tag") % n)
5135 raise util.Abort(_("tag '%s' is not a global tag") % n)
5133 else:
5136 else:
5134 raise util.Abort(_("tag '%s' is not a local tag") % n)
5137 raise util.Abort(_("tag '%s' is not a local tag") % n)
5135 rev_ = nullid
5138 rev_ = nullid
5136 if not message:
5139 if not message:
5137 # we don't translate commit messages
5140 # we don't translate commit messages
5138 message = 'Removed tag %s' % ', '.join(names)
5141 message = 'Removed tag %s' % ', '.join(names)
5139 elif not opts.get('force'):
5142 elif not opts.get('force'):
5140 for n in names:
5143 for n in names:
5141 if n in repo.tags():
5144 if n in repo.tags():
5142 raise util.Abort(_("tag '%s' already exists "
5145 raise util.Abort(_("tag '%s' already exists "
5143 "(use -f to force)") % n)
5146 "(use -f to force)") % n)
5144 if not opts.get('local'):
5147 if not opts.get('local'):
5145 p1, p2 = repo.dirstate.parents()
5148 p1, p2 = repo.dirstate.parents()
5146 if p2 != nullid:
5149 if p2 != nullid:
5147 raise util.Abort(_('uncommitted merge'))
5150 raise util.Abort(_('uncommitted merge'))
5148 bheads = repo.branchheads()
5151 bheads = repo.branchheads()
5149 if not opts.get('force') and bheads and p1 not in bheads:
5152 if not opts.get('force') and bheads and p1 not in bheads:
5150 raise util.Abort(_('not at a branch head (use -f to force)'))
5153 raise util.Abort(_('not at a branch head (use -f to force)'))
5151 r = scmutil.revsingle(repo, rev_).node()
5154 r = scmutil.revsingle(repo, rev_).node()
5152
5155
5153 if not message:
5156 if not message:
5154 # we don't translate commit messages
5157 # we don't translate commit messages
5155 message = ('Added tag %s for changeset %s' %
5158 message = ('Added tag %s for changeset %s' %
5156 (', '.join(names), short(r)))
5159 (', '.join(names), short(r)))
5157
5160
5158 date = opts.get('date')
5161 date = opts.get('date')
5159 if date:
5162 if date:
5160 date = util.parsedate(date)
5163 date = util.parsedate(date)
5161
5164
5162 if opts.get('edit'):
5165 if opts.get('edit'):
5163 message = ui.edit(message, ui.username())
5166 message = ui.edit(message, ui.username())
5164
5167
5165 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5168 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5166
5169
5167 @command('tags', [], '')
5170 @command('tags', [], '')
5168 def tags(ui, repo):
5171 def tags(ui, repo):
5169 """list repository tags
5172 """list repository tags
5170
5173
5171 This lists both regular and local tags. When the -v/--verbose
5174 This lists both regular and local tags. When the -v/--verbose
5172 switch is used, a third column "local" is printed for local tags.
5175 switch is used, a third column "local" is printed for local tags.
5173
5176
5174 Returns 0 on success.
5177 Returns 0 on success.
5175 """
5178 """
5176
5179
5177 hexfunc = ui.debugflag and hex or short
5180 hexfunc = ui.debugflag and hex or short
5178 tagtype = ""
5181 tagtype = ""
5179
5182
5180 for t, n in reversed(repo.tagslist()):
5183 for t, n in reversed(repo.tagslist()):
5181 if ui.quiet:
5184 if ui.quiet:
5182 ui.write("%s\n" % t, label='tags.normal')
5185 ui.write("%s\n" % t, label='tags.normal')
5183 continue
5186 continue
5184
5187
5185 hn = hexfunc(n)
5188 hn = hexfunc(n)
5186 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5189 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5187 rev = ui.label(r, 'log.changeset')
5190 rev = ui.label(r, 'log.changeset')
5188 spaces = " " * (30 - encoding.colwidth(t))
5191 spaces = " " * (30 - encoding.colwidth(t))
5189
5192
5190 tag = ui.label(t, 'tags.normal')
5193 tag = ui.label(t, 'tags.normal')
5191 if ui.verbose:
5194 if ui.verbose:
5192 if repo.tagtype(t) == 'local':
5195 if repo.tagtype(t) == 'local':
5193 tagtype = " local"
5196 tagtype = " local"
5194 tag = ui.label(t, 'tags.local')
5197 tag = ui.label(t, 'tags.local')
5195 else:
5198 else:
5196 tagtype = ""
5199 tagtype = ""
5197 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5200 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5198
5201
5199 @command('tip',
5202 @command('tip',
5200 [('p', 'patch', None, _('show patch')),
5203 [('p', 'patch', None, _('show patch')),
5201 ('g', 'git', None, _('use git extended diff format')),
5204 ('g', 'git', None, _('use git extended diff format')),
5202 ] + templateopts,
5205 ] + templateopts,
5203 _('[-p] [-g]'))
5206 _('[-p] [-g]'))
5204 def tip(ui, repo, **opts):
5207 def tip(ui, repo, **opts):
5205 """show the tip revision
5208 """show the tip revision
5206
5209
5207 The tip revision (usually just called the tip) is the changeset
5210 The tip revision (usually just called the tip) is the changeset
5208 most recently added to the repository (and therefore the most
5211 most recently added to the repository (and therefore the most
5209 recently changed head).
5212 recently changed head).
5210
5213
5211 If you have just made a commit, that commit will be the tip. If
5214 If you have just made a commit, that commit will be the tip. If
5212 you have just pulled changes from another repository, the tip of
5215 you have just pulled changes from another repository, the tip of
5213 that repository becomes the current tip. The "tip" tag is special
5216 that repository becomes the current tip. The "tip" tag is special
5214 and cannot be renamed or assigned to a different changeset.
5217 and cannot be renamed or assigned to a different changeset.
5215
5218
5216 Returns 0 on success.
5219 Returns 0 on success.
5217 """
5220 """
5218 displayer = cmdutil.show_changeset(ui, repo, opts)
5221 displayer = cmdutil.show_changeset(ui, repo, opts)
5219 displayer.show(repo[len(repo) - 1])
5222 displayer.show(repo[len(repo) - 1])
5220 displayer.close()
5223 displayer.close()
5221
5224
5222 @command('unbundle',
5225 @command('unbundle',
5223 [('u', 'update', None,
5226 [('u', 'update', None,
5224 _('update to new branch head if changesets were unbundled'))],
5227 _('update to new branch head if changesets were unbundled'))],
5225 _('[-u] FILE...'))
5228 _('[-u] FILE...'))
5226 def unbundle(ui, repo, fname1, *fnames, **opts):
5229 def unbundle(ui, repo, fname1, *fnames, **opts):
5227 """apply one or more changegroup files
5230 """apply one or more changegroup files
5228
5231
5229 Apply one or more compressed changegroup files generated by the
5232 Apply one or more compressed changegroup files generated by the
5230 bundle command.
5233 bundle command.
5231
5234
5232 Returns 0 on success, 1 if an update has unresolved files.
5235 Returns 0 on success, 1 if an update has unresolved files.
5233 """
5236 """
5234 fnames = (fname1,) + fnames
5237 fnames = (fname1,) + fnames
5235
5238
5236 lock = repo.lock()
5239 lock = repo.lock()
5237 wc = repo['.']
5240 wc = repo['.']
5238 try:
5241 try:
5239 for fname in fnames:
5242 for fname in fnames:
5240 f = url.open(ui, fname)
5243 f = url.open(ui, fname)
5241 gen = changegroup.readbundle(f, fname)
5244 gen = changegroup.readbundle(f, fname)
5242 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5245 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5243 lock=lock)
5246 lock=lock)
5244 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5247 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5245 finally:
5248 finally:
5246 lock.release()
5249 lock.release()
5247 return postincoming(ui, repo, modheads, opts.get('update'), None)
5250 return postincoming(ui, repo, modheads, opts.get('update'), None)
5248
5251
5249 @command('^update|up|checkout|co',
5252 @command('^update|up|checkout|co',
5250 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5253 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5251 ('c', 'check', None,
5254 ('c', 'check', None,
5252 _('update across branches if no uncommitted changes')),
5255 _('update across branches if no uncommitted changes')),
5253 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5256 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5254 ('r', 'rev', '', _('revision'), _('REV'))],
5257 ('r', 'rev', '', _('revision'), _('REV'))],
5255 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5258 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5256 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5259 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5257 """update working directory (or switch revisions)
5260 """update working directory (or switch revisions)
5258
5261
5259 Update the repository's working directory to the specified
5262 Update the repository's working directory to the specified
5260 changeset. If no changeset is specified, update to the tip of the
5263 changeset. If no changeset is specified, update to the tip of the
5261 current named branch.
5264 current named branch.
5262
5265
5263 If the changeset is not a descendant of the working directory's
5266 If the changeset is not a descendant of the working directory's
5264 parent, the update is aborted. With the -c/--check option, the
5267 parent, the update is aborted. With the -c/--check option, the
5265 working directory is checked for uncommitted changes; if none are
5268 working directory is checked for uncommitted changes; if none are
5266 found, the working directory is updated to the specified
5269 found, the working directory is updated to the specified
5267 changeset.
5270 changeset.
5268
5271
5269 Update sets the working directory's parent revison to the specified
5272 Update sets the working directory's parent revison to the specified
5270 changeset (see :hg:`help parents`).
5273 changeset (see :hg:`help parents`).
5271
5274
5272 The following rules apply when the working directory contains
5275 The following rules apply when the working directory contains
5273 uncommitted changes:
5276 uncommitted changes:
5274
5277
5275 1. If neither -c/--check nor -C/--clean is specified, and if
5278 1. If neither -c/--check nor -C/--clean is specified, and if
5276 the requested changeset is an ancestor or descendant of
5279 the requested changeset is an ancestor or descendant of
5277 the working directory's parent, the uncommitted changes
5280 the working directory's parent, the uncommitted changes
5278 are merged into the requested changeset and the merged
5281 are merged into the requested changeset and the merged
5279 result is left uncommitted. If the requested changeset is
5282 result is left uncommitted. If the requested changeset is
5280 not an ancestor or descendant (that is, it is on another
5283 not an ancestor or descendant (that is, it is on another
5281 branch), the update is aborted and the uncommitted changes
5284 branch), the update is aborted and the uncommitted changes
5282 are preserved.
5285 are preserved.
5283
5286
5284 2. With the -c/--check option, the update is aborted and the
5287 2. With the -c/--check option, the update is aborted and the
5285 uncommitted changes are preserved.
5288 uncommitted changes are preserved.
5286
5289
5287 3. With the -C/--clean option, uncommitted changes are discarded and
5290 3. With the -C/--clean option, uncommitted changes are discarded and
5288 the working directory is updated to the requested changeset.
5291 the working directory is updated to the requested changeset.
5289
5292
5290 Use null as the changeset to remove the working directory (like
5293 Use null as the changeset to remove the working directory (like
5291 :hg:`clone -U`).
5294 :hg:`clone -U`).
5292
5295
5293 If you want to revert just one file to an older revision, use
5296 If you want to revert just one file to an older revision, use
5294 :hg:`revert [-r REV] NAME`.
5297 :hg:`revert [-r REV] NAME`.
5295
5298
5296 See :hg:`help dates` for a list of formats valid for -d/--date.
5299 See :hg:`help dates` for a list of formats valid for -d/--date.
5297
5300
5298 Returns 0 on success, 1 if there are unresolved files.
5301 Returns 0 on success, 1 if there are unresolved files.
5299 """
5302 """
5300 if rev and node:
5303 if rev and node:
5301 raise util.Abort(_("please specify just one revision"))
5304 raise util.Abort(_("please specify just one revision"))
5302
5305
5303 if rev is None or rev == '':
5306 if rev is None or rev == '':
5304 rev = node
5307 rev = node
5305
5308
5306 # if we defined a bookmark, we have to remember the original bookmark name
5309 # if we defined a bookmark, we have to remember the original bookmark name
5307 brev = rev
5310 brev = rev
5308 rev = scmutil.revsingle(repo, rev, rev).rev()
5311 rev = scmutil.revsingle(repo, rev, rev).rev()
5309
5312
5310 if check and clean:
5313 if check and clean:
5311 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5314 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5312
5315
5313 if check:
5316 if check:
5314 # we could use dirty() but we can ignore merge and branch trivia
5317 # we could use dirty() but we can ignore merge and branch trivia
5315 c = repo[None]
5318 c = repo[None]
5316 if c.modified() or c.added() or c.removed():
5319 if c.modified() or c.added() or c.removed():
5317 raise util.Abort(_("uncommitted local changes"))
5320 raise util.Abort(_("uncommitted local changes"))
5318
5321
5319 if date:
5322 if date:
5320 if rev is not None:
5323 if rev is not None:
5321 raise util.Abort(_("you can't specify a revision and a date"))
5324 raise util.Abort(_("you can't specify a revision and a date"))
5322 rev = cmdutil.finddate(ui, repo, date)
5325 rev = cmdutil.finddate(ui, repo, date)
5323
5326
5324 if clean or check:
5327 if clean or check:
5325 ret = hg.clean(repo, rev)
5328 ret = hg.clean(repo, rev)
5326 else:
5329 else:
5327 ret = hg.update(repo, rev)
5330 ret = hg.update(repo, rev)
5328
5331
5329 if brev in repo._bookmarks:
5332 if brev in repo._bookmarks:
5330 bookmarks.setcurrent(repo, brev)
5333 bookmarks.setcurrent(repo, brev)
5331
5334
5332 return ret
5335 return ret
5333
5336
5334 @command('verify', [])
5337 @command('verify', [])
5335 def verify(ui, repo):
5338 def verify(ui, repo):
5336 """verify the integrity of the repository
5339 """verify the integrity of the repository
5337
5340
5338 Verify the integrity of the current repository.
5341 Verify the integrity of the current repository.
5339
5342
5340 This will perform an extensive check of the repository's
5343 This will perform an extensive check of the repository's
5341 integrity, validating the hashes and checksums of each entry in
5344 integrity, validating the hashes and checksums of each entry in
5342 the changelog, manifest, and tracked files, as well as the
5345 the changelog, manifest, and tracked files, as well as the
5343 integrity of their crosslinks and indices.
5346 integrity of their crosslinks and indices.
5344
5347
5345 Returns 0 on success, 1 if errors are encountered.
5348 Returns 0 on success, 1 if errors are encountered.
5346 """
5349 """
5347 return hg.verify(repo)
5350 return hg.verify(repo)
5348
5351
5349 @command('version', [])
5352 @command('version', [])
5350 def version_(ui):
5353 def version_(ui):
5351 """output version and copyright information"""
5354 """output version and copyright information"""
5352 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5355 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5353 % util.version())
5356 % util.version())
5354 ui.status(_(
5357 ui.status(_(
5355 "(see http://mercurial.selenic.com for more information)\n"
5358 "(see http://mercurial.selenic.com for more information)\n"
5356 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5359 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5357 "This is free software; see the source for copying conditions. "
5360 "This is free software; see the source for copying conditions. "
5358 "There is NO\nwarranty; "
5361 "There is NO\nwarranty; "
5359 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5362 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5360 ))
5363 ))
5361
5364
5362 norepo = ("clone init version help debugcommands debugcomplete"
5365 norepo = ("clone init version help debugcommands debugcomplete"
5363 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5366 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5364 " debugknown debuggetbundle debugbundle")
5367 " debugknown debuggetbundle debugbundle")
5365 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5368 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5366 " debugdata debugindex debugindexdot debugrevlog")
5369 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now