##// END OF EJS Templates
add new option --all to manifest command...
Adrian Buehlmann -
r14399:71938479 default
parent child Browse files
Show More
@@ -1,5051 +1,5074 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, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
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, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser, context, simplemerge
17 import dagparser, context, simplemerge
18 import random, setdiscovery, treediscovery, dagutil
18 import random, setdiscovery, treediscovery, dagutil
19
19
20 table = {}
20 table = {}
21
21
22 command = cmdutil.command(table)
22 command = cmdutil.command(table)
23
23
24 # common command options
24 # common command options
25
25
26 globalopts = [
26 globalopts = [
27 ('R', 'repository', '',
27 ('R', 'repository', '',
28 _('repository root directory or name of overlay bundle file'),
28 _('repository root directory or name of overlay bundle file'),
29 _('REPO')),
29 _('REPO')),
30 ('', 'cwd', '',
30 ('', 'cwd', '',
31 _('change working directory'), _('DIR')),
31 _('change working directory'), _('DIR')),
32 ('y', 'noninteractive', None,
32 ('y', 'noninteractive', None,
33 _('do not prompt, assume \'yes\' for any required answers')),
33 _('do not prompt, assume \'yes\' for any required answers')),
34 ('q', 'quiet', None, _('suppress output')),
34 ('q', 'quiet', None, _('suppress output')),
35 ('v', 'verbose', None, _('enable additional output')),
35 ('v', 'verbose', None, _('enable additional output')),
36 ('', 'config', [],
36 ('', 'config', [],
37 _('set/override config option (use \'section.name=value\')'),
37 _('set/override config option (use \'section.name=value\')'),
38 _('CONFIG')),
38 _('CONFIG')),
39 ('', 'debug', None, _('enable debugging output')),
39 ('', 'debug', None, _('enable debugging output')),
40 ('', 'debugger', None, _('start debugger')),
40 ('', 'debugger', None, _('start debugger')),
41 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
41 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
42 _('ENCODE')),
42 _('ENCODE')),
43 ('', 'encodingmode', encoding.encodingmode,
43 ('', 'encodingmode', encoding.encodingmode,
44 _('set the charset encoding mode'), _('MODE')),
44 _('set the charset encoding mode'), _('MODE')),
45 ('', 'traceback', None, _('always print a traceback on exception')),
45 ('', 'traceback', None, _('always print a traceback on exception')),
46 ('', 'time', None, _('time how long the command takes')),
46 ('', 'time', None, _('time how long the command takes')),
47 ('', 'profile', None, _('print command execution profile')),
47 ('', 'profile', None, _('print command execution profile')),
48 ('', 'version', None, _('output version information and exit')),
48 ('', 'version', None, _('output version information and exit')),
49 ('h', 'help', None, _('display help and exit')),
49 ('h', 'help', None, _('display help and exit')),
50 ]
50 ]
51
51
52 dryrunopts = [('n', 'dry-run', None,
52 dryrunopts = [('n', 'dry-run', None,
53 _('do not perform actions, just print output'))]
53 _('do not perform actions, just print output'))]
54
54
55 remoteopts = [
55 remoteopts = [
56 ('e', 'ssh', '',
56 ('e', 'ssh', '',
57 _('specify ssh command to use'), _('CMD')),
57 _('specify ssh command to use'), _('CMD')),
58 ('', 'remotecmd', '',
58 ('', 'remotecmd', '',
59 _('specify hg command to run on the remote side'), _('CMD')),
59 _('specify hg command to run on the remote side'), _('CMD')),
60 ('', 'insecure', None,
60 ('', 'insecure', None,
61 _('do not verify server certificate (ignoring web.cacerts config)')),
61 _('do not verify server certificate (ignoring web.cacerts config)')),
62 ]
62 ]
63
63
64 walkopts = [
64 walkopts = [
65 ('I', 'include', [],
65 ('I', 'include', [],
66 _('include names matching the given patterns'), _('PATTERN')),
66 _('include names matching the given patterns'), _('PATTERN')),
67 ('X', 'exclude', [],
67 ('X', 'exclude', [],
68 _('exclude names matching the given patterns'), _('PATTERN')),
68 _('exclude names matching the given patterns'), _('PATTERN')),
69 ]
69 ]
70
70
71 commitopts = [
71 commitopts = [
72 ('m', 'message', '',
72 ('m', 'message', '',
73 _('use text as commit message'), _('TEXT')),
73 _('use text as commit message'), _('TEXT')),
74 ('l', 'logfile', '',
74 ('l', 'logfile', '',
75 _('read commit message from file'), _('FILE')),
75 _('read commit message from file'), _('FILE')),
76 ]
76 ]
77
77
78 commitopts2 = [
78 commitopts2 = [
79 ('d', 'date', '',
79 ('d', 'date', '',
80 _('record the specified date as commit date'), _('DATE')),
80 _('record the specified date as commit date'), _('DATE')),
81 ('u', 'user', '',
81 ('u', 'user', '',
82 _('record the specified user as committer'), _('USER')),
82 _('record the specified user as committer'), _('USER')),
83 ]
83 ]
84
84
85 templateopts = [
85 templateopts = [
86 ('', 'style', '',
86 ('', 'style', '',
87 _('display using template map file'), _('STYLE')),
87 _('display using template map file'), _('STYLE')),
88 ('', 'template', '',
88 ('', 'template', '',
89 _('display with template'), _('TEMPLATE')),
89 _('display with template'), _('TEMPLATE')),
90 ]
90 ]
91
91
92 logopts = [
92 logopts = [
93 ('p', 'patch', None, _('show patch')),
93 ('p', 'patch', None, _('show patch')),
94 ('g', 'git', None, _('use git extended diff format')),
94 ('g', 'git', None, _('use git extended diff format')),
95 ('l', 'limit', '',
95 ('l', 'limit', '',
96 _('limit number of changes displayed'), _('NUM')),
96 _('limit number of changes displayed'), _('NUM')),
97 ('M', 'no-merges', None, _('do not show merges')),
97 ('M', 'no-merges', None, _('do not show merges')),
98 ('', 'stat', None, _('output diffstat-style summary of changes')),
98 ('', 'stat', None, _('output diffstat-style summary of changes')),
99 ] + templateopts
99 ] + templateopts
100
100
101 diffopts = [
101 diffopts = [
102 ('a', 'text', None, _('treat all files as text')),
102 ('a', 'text', None, _('treat all files as text')),
103 ('g', 'git', None, _('use git extended diff format')),
103 ('g', 'git', None, _('use git extended diff format')),
104 ('', 'nodates', None, _('omit dates from diff headers'))
104 ('', 'nodates', None, _('omit dates from diff headers'))
105 ]
105 ]
106
106
107 diffopts2 = [
107 diffopts2 = [
108 ('p', 'show-function', None, _('show which function each change is in')),
108 ('p', 'show-function', None, _('show which function each change is in')),
109 ('', 'reverse', None, _('produce a diff that undoes the changes')),
109 ('', 'reverse', None, _('produce a diff that undoes the changes')),
110 ('w', 'ignore-all-space', None,
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
115 _('ignore changes whose lines are all blank')),
116 ('U', 'unified', '',
116 ('U', 'unified', '',
117 _('number of lines of context to show'), _('NUM')),
117 _('number of lines of context to show'), _('NUM')),
118 ('', 'stat', None, _('output diffstat-style summary of changes')),
118 ('', 'stat', None, _('output diffstat-style summary of changes')),
119 ]
119 ]
120
120
121 similarityopts = [
121 similarityopts = [
122 ('s', 'similarity', '',
122 ('s', 'similarity', '',
123 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
123 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
124 ]
124 ]
125
125
126 subrepoopts = [
126 subrepoopts = [
127 ('S', 'subrepos', None,
127 ('S', 'subrepos', None,
128 _('recurse into subrepositories'))
128 _('recurse into subrepositories'))
129 ]
129 ]
130
130
131 # Commands start here, listed alphabetically
131 # Commands start here, listed alphabetically
132
132
133 @command('^add',
133 @command('^add',
134 walkopts + subrepoopts + dryrunopts,
134 walkopts + subrepoopts + dryrunopts,
135 _('[OPTION]... [FILE]...'))
135 _('[OPTION]... [FILE]...'))
136 def add(ui, repo, *pats, **opts):
136 def add(ui, repo, *pats, **opts):
137 """add the specified files on the next commit
137 """add the specified files on the next commit
138
138
139 Schedule files to be version controlled and added to the
139 Schedule files to be version controlled and added to the
140 repository.
140 repository.
141
141
142 The files will be added to the repository at the next commit. To
142 The files will be added to the repository at the next commit. To
143 undo an add before that, see :hg:`forget`.
143 undo an add before that, see :hg:`forget`.
144
144
145 If no names are given, add all files to the repository.
145 If no names are given, add all files to the repository.
146
146
147 .. container:: verbose
147 .. container:: verbose
148
148
149 An example showing how new (unknown) files are added
149 An example showing how new (unknown) files are added
150 automatically by :hg:`add`::
150 automatically by :hg:`add`::
151
151
152 $ ls
152 $ ls
153 foo.c
153 foo.c
154 $ hg status
154 $ hg status
155 ? foo.c
155 ? foo.c
156 $ hg add
156 $ hg add
157 adding foo.c
157 adding foo.c
158 $ hg status
158 $ hg status
159 A foo.c
159 A foo.c
160
160
161 Returns 0 if all files are successfully added.
161 Returns 0 if all files are successfully added.
162 """
162 """
163
163
164 m = scmutil.match(repo, pats, opts)
164 m = scmutil.match(repo, pats, opts)
165 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
165 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
166 opts.get('subrepos'), prefix="")
166 opts.get('subrepos'), prefix="")
167 return rejected and 1 or 0
167 return rejected and 1 or 0
168
168
169 @command('addremove',
169 @command('addremove',
170 similarityopts + walkopts + dryrunopts,
170 similarityopts + walkopts + dryrunopts,
171 _('[OPTION]... [FILE]...'))
171 _('[OPTION]... [FILE]...'))
172 def addremove(ui, repo, *pats, **opts):
172 def addremove(ui, repo, *pats, **opts):
173 """add all new files, delete all missing files
173 """add all new files, delete all missing files
174
174
175 Add all new files and remove all missing files from the
175 Add all new files and remove all missing files from the
176 repository.
176 repository.
177
177
178 New files are ignored if they match any of the patterns in
178 New files are ignored if they match any of the patterns in
179 ``.hgignore``. As with add, these changes take effect at the next
179 ``.hgignore``. As with add, these changes take effect at the next
180 commit.
180 commit.
181
181
182 Use the -s/--similarity option to detect renamed files. With a
182 Use the -s/--similarity option to detect renamed files. With a
183 parameter greater than 0, this compares every removed file with
183 parameter greater than 0, this compares every removed file with
184 every added file and records those similar enough as renames. This
184 every added file and records those similar enough as renames. This
185 option takes a percentage between 0 (disabled) and 100 (files must
185 option takes a percentage between 0 (disabled) and 100 (files must
186 be identical) as its parameter. Detecting renamed files this way
186 be identical) as its parameter. Detecting renamed files this way
187 can be expensive. After using this option, :hg:`status -C` can be
187 can be expensive. After using this option, :hg:`status -C` can be
188 used to check which files were identified as moved or renamed.
188 used to check which files were identified as moved or renamed.
189
189
190 Returns 0 if all files are successfully added.
190 Returns 0 if all files are successfully added.
191 """
191 """
192 try:
192 try:
193 sim = float(opts.get('similarity') or 100)
193 sim = float(opts.get('similarity') or 100)
194 except ValueError:
194 except ValueError:
195 raise util.Abort(_('similarity must be a number'))
195 raise util.Abort(_('similarity must be a number'))
196 if sim < 0 or sim > 100:
196 if sim < 0 or sim > 100:
197 raise util.Abort(_('similarity must be between 0 and 100'))
197 raise util.Abort(_('similarity must be between 0 and 100'))
198 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
198 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
199
199
200 @command('^annotate|blame',
200 @command('^annotate|blame',
201 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
201 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
202 ('', 'follow', None,
202 ('', 'follow', None,
203 _('follow copies/renames and list the filename (DEPRECATED)')),
203 _('follow copies/renames and list the filename (DEPRECATED)')),
204 ('', 'no-follow', None, _("don't follow copies and renames")),
204 ('', 'no-follow', None, _("don't follow copies and renames")),
205 ('a', 'text', None, _('treat all files as text')),
205 ('a', 'text', None, _('treat all files as text')),
206 ('u', 'user', None, _('list the author (long with -v)')),
206 ('u', 'user', None, _('list the author (long with -v)')),
207 ('f', 'file', None, _('list the filename')),
207 ('f', 'file', None, _('list the filename')),
208 ('d', 'date', None, _('list the date (short with -q)')),
208 ('d', 'date', None, _('list the date (short with -q)')),
209 ('n', 'number', None, _('list the revision number (default)')),
209 ('n', 'number', None, _('list the revision number (default)')),
210 ('c', 'changeset', None, _('list the changeset')),
210 ('c', 'changeset', None, _('list the changeset')),
211 ('l', 'line-number', None, _('show line number at the first appearance'))
211 ('l', 'line-number', None, _('show line number at the first appearance'))
212 ] + walkopts,
212 ] + walkopts,
213 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
213 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
214 def annotate(ui, repo, *pats, **opts):
214 def annotate(ui, repo, *pats, **opts):
215 """show changeset information by line for each file
215 """show changeset information by line for each file
216
216
217 List changes in files, showing the revision id responsible for
217 List changes in files, showing the revision id responsible for
218 each line
218 each line
219
219
220 This command is useful for discovering when a change was made and
220 This command is useful for discovering when a change was made and
221 by whom.
221 by whom.
222
222
223 Without the -a/--text option, annotate will avoid processing files
223 Without the -a/--text option, annotate will avoid processing files
224 it detects as binary. With -a, annotate will annotate the file
224 it detects as binary. With -a, annotate will annotate the file
225 anyway, although the results will probably be neither useful
225 anyway, although the results will probably be neither useful
226 nor desirable.
226 nor desirable.
227
227
228 Returns 0 on success.
228 Returns 0 on success.
229 """
229 """
230 if opts.get('follow'):
230 if opts.get('follow'):
231 # --follow is deprecated and now just an alias for -f/--file
231 # --follow is deprecated and now just an alias for -f/--file
232 # to mimic the behavior of Mercurial before version 1.5
232 # to mimic the behavior of Mercurial before version 1.5
233 opts['file'] = True
233 opts['file'] = True
234
234
235 datefunc = ui.quiet and util.shortdate or util.datestr
235 datefunc = ui.quiet and util.shortdate or util.datestr
236 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
236 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
237
237
238 if not pats:
238 if not pats:
239 raise util.Abort(_('at least one filename or pattern is required'))
239 raise util.Abort(_('at least one filename or pattern is required'))
240
240
241 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
241 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
242 ('number', ' ', lambda x: str(x[0].rev())),
242 ('number', ' ', lambda x: str(x[0].rev())),
243 ('changeset', ' ', lambda x: short(x[0].node())),
243 ('changeset', ' ', lambda x: short(x[0].node())),
244 ('date', ' ', getdate),
244 ('date', ' ', getdate),
245 ('file', ' ', lambda x: x[0].path()),
245 ('file', ' ', lambda x: x[0].path()),
246 ('line_number', ':', lambda x: str(x[1])),
246 ('line_number', ':', lambda x: str(x[1])),
247 ]
247 ]
248
248
249 if (not opts.get('user') and not opts.get('changeset')
249 if (not opts.get('user') and not opts.get('changeset')
250 and not opts.get('date') and not opts.get('file')):
250 and not opts.get('date') and not opts.get('file')):
251 opts['number'] = True
251 opts['number'] = True
252
252
253 linenumber = opts.get('line_number') is not None
253 linenumber = opts.get('line_number') is not None
254 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
254 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
255 raise util.Abort(_('at least one of -n/-c is required for -l'))
255 raise util.Abort(_('at least one of -n/-c is required for -l'))
256
256
257 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
257 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
258 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
258 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
259
259
260 def bad(x, y):
260 def bad(x, y):
261 raise util.Abort("%s: %s" % (x, y))
261 raise util.Abort("%s: %s" % (x, y))
262
262
263 ctx = scmutil.revsingle(repo, opts.get('rev'))
263 ctx = scmutil.revsingle(repo, opts.get('rev'))
264 m = scmutil.match(repo, pats, opts)
264 m = scmutil.match(repo, pats, opts)
265 m.bad = bad
265 m.bad = bad
266 follow = not opts.get('no_follow')
266 follow = not opts.get('no_follow')
267 for abs in ctx.walk(m):
267 for abs in ctx.walk(m):
268 fctx = ctx[abs]
268 fctx = ctx[abs]
269 if not opts.get('text') and util.binary(fctx.data()):
269 if not opts.get('text') and util.binary(fctx.data()):
270 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
270 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
271 continue
271 continue
272
272
273 lines = fctx.annotate(follow=follow, linenumber=linenumber)
273 lines = fctx.annotate(follow=follow, linenumber=linenumber)
274 pieces = []
274 pieces = []
275
275
276 for f, sep in funcmap:
276 for f, sep in funcmap:
277 l = [f(n) for n, dummy in lines]
277 l = [f(n) for n, dummy in lines]
278 if l:
278 if l:
279 sized = [(x, encoding.colwidth(x)) for x in l]
279 sized = [(x, encoding.colwidth(x)) for x in l]
280 ml = max([w for x, w in sized])
280 ml = max([w for x, w in sized])
281 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
281 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
282 for x, w in sized])
282 for x, w in sized])
283
283
284 if pieces:
284 if pieces:
285 for p, l in zip(zip(*pieces), lines):
285 for p, l in zip(zip(*pieces), lines):
286 ui.write("%s: %s" % ("".join(p), l[1]))
286 ui.write("%s: %s" % ("".join(p), l[1]))
287
287
288 @command('archive',
288 @command('archive',
289 [('', 'no-decode', None, _('do not pass files through decoders')),
289 [('', 'no-decode', None, _('do not pass files through decoders')),
290 ('p', 'prefix', '', _('directory prefix for files in archive'),
290 ('p', 'prefix', '', _('directory prefix for files in archive'),
291 _('PREFIX')),
291 _('PREFIX')),
292 ('r', 'rev', '', _('revision to distribute'), _('REV')),
292 ('r', 'rev', '', _('revision to distribute'), _('REV')),
293 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
293 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
294 ] + subrepoopts + walkopts,
294 ] + subrepoopts + walkopts,
295 _('[OPTION]... DEST'))
295 _('[OPTION]... DEST'))
296 def archive(ui, repo, dest, **opts):
296 def archive(ui, repo, dest, **opts):
297 '''create an unversioned archive of a repository revision
297 '''create an unversioned archive of a repository revision
298
298
299 By default, the revision used is the parent of the working
299 By default, the revision used is the parent of the working
300 directory; use -r/--rev to specify a different revision.
300 directory; use -r/--rev to specify a different revision.
301
301
302 The archive type is automatically detected based on file
302 The archive type is automatically detected based on file
303 extension (or override using -t/--type).
303 extension (or override using -t/--type).
304
304
305 Valid types are:
305 Valid types are:
306
306
307 :``files``: a directory full of files (default)
307 :``files``: a directory full of files (default)
308 :``tar``: tar archive, uncompressed
308 :``tar``: tar archive, uncompressed
309 :``tbz2``: tar archive, compressed using bzip2
309 :``tbz2``: tar archive, compressed using bzip2
310 :``tgz``: tar archive, compressed using gzip
310 :``tgz``: tar archive, compressed using gzip
311 :``uzip``: zip archive, uncompressed
311 :``uzip``: zip archive, uncompressed
312 :``zip``: zip archive, compressed using deflate
312 :``zip``: zip archive, compressed using deflate
313
313
314 The exact name of the destination archive or directory is given
314 The exact name of the destination archive or directory is given
315 using a format string; see :hg:`help export` for details.
315 using a format string; see :hg:`help export` for details.
316
316
317 Each member added to an archive file has a directory prefix
317 Each member added to an archive file has a directory prefix
318 prepended. Use -p/--prefix to specify a format string for the
318 prepended. Use -p/--prefix to specify a format string for the
319 prefix. The default is the basename of the archive, with suffixes
319 prefix. The default is the basename of the archive, with suffixes
320 removed.
320 removed.
321
321
322 Returns 0 on success.
322 Returns 0 on success.
323 '''
323 '''
324
324
325 ctx = scmutil.revsingle(repo, opts.get('rev'))
325 ctx = scmutil.revsingle(repo, opts.get('rev'))
326 if not ctx:
326 if not ctx:
327 raise util.Abort(_('no working directory: please specify a revision'))
327 raise util.Abort(_('no working directory: please specify a revision'))
328 node = ctx.node()
328 node = ctx.node()
329 dest = cmdutil.makefilename(repo, dest, node)
329 dest = cmdutil.makefilename(repo, dest, node)
330 if os.path.realpath(dest) == repo.root:
330 if os.path.realpath(dest) == repo.root:
331 raise util.Abort(_('repository root cannot be destination'))
331 raise util.Abort(_('repository root cannot be destination'))
332
332
333 kind = opts.get('type') or archival.guesskind(dest) or 'files'
333 kind = opts.get('type') or archival.guesskind(dest) or 'files'
334 prefix = opts.get('prefix')
334 prefix = opts.get('prefix')
335
335
336 if dest == '-':
336 if dest == '-':
337 if kind == 'files':
337 if kind == 'files':
338 raise util.Abort(_('cannot archive plain files to stdout'))
338 raise util.Abort(_('cannot archive plain files to stdout'))
339 dest = sys.stdout
339 dest = sys.stdout
340 if not prefix:
340 if not prefix:
341 prefix = os.path.basename(repo.root) + '-%h'
341 prefix = os.path.basename(repo.root) + '-%h'
342
342
343 prefix = cmdutil.makefilename(repo, prefix, node)
343 prefix = cmdutil.makefilename(repo, prefix, node)
344 matchfn = scmutil.match(repo, [], opts)
344 matchfn = scmutil.match(repo, [], opts)
345 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
345 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
346 matchfn, prefix, subrepos=opts.get('subrepos'))
346 matchfn, prefix, subrepos=opts.get('subrepos'))
347
347
348 @command('backout',
348 @command('backout',
349 [('', 'merge', None, _('merge with old dirstate parent after backout')),
349 [('', 'merge', None, _('merge with old dirstate parent after backout')),
350 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
350 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
351 ('t', 'tool', '', _('specify merge tool')),
351 ('t', 'tool', '', _('specify merge tool')),
352 ('r', 'rev', '', _('revision to backout'), _('REV')),
352 ('r', 'rev', '', _('revision to backout'), _('REV')),
353 ] + walkopts + commitopts + commitopts2,
353 ] + walkopts + commitopts + commitopts2,
354 _('[OPTION]... [-r] REV'))
354 _('[OPTION]... [-r] REV'))
355 def backout(ui, repo, node=None, rev=None, **opts):
355 def backout(ui, repo, node=None, rev=None, **opts):
356 '''reverse effect of earlier changeset
356 '''reverse effect of earlier changeset
357
357
358 Prepare a new changeset with the effect of REV undone in the
358 Prepare a new changeset with the effect of REV undone in the
359 current working directory.
359 current working directory.
360
360
361 If REV is the parent of the working directory, then this new changeset
361 If REV is the parent of the working directory, then this new changeset
362 is committed automatically. Otherwise, hg needs to merge the
362 is committed automatically. Otherwise, hg needs to merge the
363 changes and the merged result is left uncommitted.
363 changes and the merged result is left uncommitted.
364
364
365 By default, the pending changeset will have one parent,
365 By default, the pending changeset will have one parent,
366 maintaining a linear history. With --merge, the pending changeset
366 maintaining a linear history. With --merge, the pending changeset
367 will instead have two parents: the old parent of the working
367 will instead have two parents: the old parent of the working
368 directory and a new child of REV that simply undoes REV.
368 directory and a new child of REV that simply undoes REV.
369
369
370 Before version 1.7, the behavior without --merge was equivalent to
370 Before version 1.7, the behavior without --merge was equivalent to
371 specifying --merge followed by :hg:`update --clean .` to cancel
371 specifying --merge followed by :hg:`update --clean .` to cancel
372 the merge and leave the child of REV as a head to be merged
372 the merge and leave the child of REV as a head to be merged
373 separately.
373 separately.
374
374
375 See :hg:`help dates` for a list of formats valid for -d/--date.
375 See :hg:`help dates` for a list of formats valid for -d/--date.
376
376
377 Returns 0 on success.
377 Returns 0 on success.
378 '''
378 '''
379 if rev and node:
379 if rev and node:
380 raise util.Abort(_("please specify just one revision"))
380 raise util.Abort(_("please specify just one revision"))
381
381
382 if not rev:
382 if not rev:
383 rev = node
383 rev = node
384
384
385 if not rev:
385 if not rev:
386 raise util.Abort(_("please specify a revision to backout"))
386 raise util.Abort(_("please specify a revision to backout"))
387
387
388 date = opts.get('date')
388 date = opts.get('date')
389 if date:
389 if date:
390 opts['date'] = util.parsedate(date)
390 opts['date'] = util.parsedate(date)
391
391
392 cmdutil.bailifchanged(repo)
392 cmdutil.bailifchanged(repo)
393 node = scmutil.revsingle(repo, rev).node()
393 node = scmutil.revsingle(repo, rev).node()
394
394
395 op1, op2 = repo.dirstate.parents()
395 op1, op2 = repo.dirstate.parents()
396 a = repo.changelog.ancestor(op1, node)
396 a = repo.changelog.ancestor(op1, node)
397 if a != node:
397 if a != node:
398 raise util.Abort(_('cannot backout change on a different branch'))
398 raise util.Abort(_('cannot backout change on a different branch'))
399
399
400 p1, p2 = repo.changelog.parents(node)
400 p1, p2 = repo.changelog.parents(node)
401 if p1 == nullid:
401 if p1 == nullid:
402 raise util.Abort(_('cannot backout a change with no parents'))
402 raise util.Abort(_('cannot backout a change with no parents'))
403 if p2 != nullid:
403 if p2 != nullid:
404 if not opts.get('parent'):
404 if not opts.get('parent'):
405 raise util.Abort(_('cannot backout a merge changeset without '
405 raise util.Abort(_('cannot backout a merge changeset without '
406 '--parent'))
406 '--parent'))
407 p = repo.lookup(opts['parent'])
407 p = repo.lookup(opts['parent'])
408 if p not in (p1, p2):
408 if p not in (p1, p2):
409 raise util.Abort(_('%s is not a parent of %s') %
409 raise util.Abort(_('%s is not a parent of %s') %
410 (short(p), short(node)))
410 (short(p), short(node)))
411 parent = p
411 parent = p
412 else:
412 else:
413 if opts.get('parent'):
413 if opts.get('parent'):
414 raise util.Abort(_('cannot use --parent on non-merge changeset'))
414 raise util.Abort(_('cannot use --parent on non-merge changeset'))
415 parent = p1
415 parent = p1
416
416
417 # the backout should appear on the same branch
417 # the backout should appear on the same branch
418 branch = repo.dirstate.branch()
418 branch = repo.dirstate.branch()
419 hg.clean(repo, node, show_stats=False)
419 hg.clean(repo, node, show_stats=False)
420 repo.dirstate.setbranch(branch)
420 repo.dirstate.setbranch(branch)
421 revert_opts = opts.copy()
421 revert_opts = opts.copy()
422 revert_opts['date'] = None
422 revert_opts['date'] = None
423 revert_opts['all'] = True
423 revert_opts['all'] = True
424 revert_opts['rev'] = hex(parent)
424 revert_opts['rev'] = hex(parent)
425 revert_opts['no_backup'] = None
425 revert_opts['no_backup'] = None
426 revert(ui, repo, **revert_opts)
426 revert(ui, repo, **revert_opts)
427 if not opts.get('merge') and op1 != node:
427 if not opts.get('merge') and op1 != node:
428 try:
428 try:
429 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
429 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
430 return hg.update(repo, op1)
430 return hg.update(repo, op1)
431 finally:
431 finally:
432 ui.setconfig('ui', 'forcemerge', '')
432 ui.setconfig('ui', 'forcemerge', '')
433
433
434 commit_opts = opts.copy()
434 commit_opts = opts.copy()
435 commit_opts['addremove'] = False
435 commit_opts['addremove'] = False
436 if not commit_opts['message'] and not commit_opts['logfile']:
436 if not commit_opts['message'] and not commit_opts['logfile']:
437 # we don't translate commit messages
437 # we don't translate commit messages
438 commit_opts['message'] = "Backed out changeset %s" % short(node)
438 commit_opts['message'] = "Backed out changeset %s" % short(node)
439 commit_opts['force_editor'] = True
439 commit_opts['force_editor'] = True
440 commit(ui, repo, **commit_opts)
440 commit(ui, repo, **commit_opts)
441 def nice(node):
441 def nice(node):
442 return '%d:%s' % (repo.changelog.rev(node), short(node))
442 return '%d:%s' % (repo.changelog.rev(node), short(node))
443 ui.status(_('changeset %s backs out changeset %s\n') %
443 ui.status(_('changeset %s backs out changeset %s\n') %
444 (nice(repo.changelog.tip()), nice(node)))
444 (nice(repo.changelog.tip()), nice(node)))
445 if opts.get('merge') and op1 != node:
445 if opts.get('merge') and op1 != node:
446 hg.clean(repo, op1, show_stats=False)
446 hg.clean(repo, op1, show_stats=False)
447 ui.status(_('merging with changeset %s\n')
447 ui.status(_('merging with changeset %s\n')
448 % nice(repo.changelog.tip()))
448 % nice(repo.changelog.tip()))
449 try:
449 try:
450 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
450 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
451 return hg.merge(repo, hex(repo.changelog.tip()))
451 return hg.merge(repo, hex(repo.changelog.tip()))
452 finally:
452 finally:
453 ui.setconfig('ui', 'forcemerge', '')
453 ui.setconfig('ui', 'forcemerge', '')
454 return 0
454 return 0
455
455
456 @command('bisect',
456 @command('bisect',
457 [('r', 'reset', False, _('reset bisect state')),
457 [('r', 'reset', False, _('reset bisect state')),
458 ('g', 'good', False, _('mark changeset good')),
458 ('g', 'good', False, _('mark changeset good')),
459 ('b', 'bad', False, _('mark changeset bad')),
459 ('b', 'bad', False, _('mark changeset bad')),
460 ('s', 'skip', False, _('skip testing changeset')),
460 ('s', 'skip', False, _('skip testing changeset')),
461 ('e', 'extend', False, _('extend the bisect range')),
461 ('e', 'extend', False, _('extend the bisect range')),
462 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
462 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
463 ('U', 'noupdate', False, _('do not update to target'))],
463 ('U', 'noupdate', False, _('do not update to target'))],
464 _("[-gbsr] [-U] [-c CMD] [REV]"))
464 _("[-gbsr] [-U] [-c CMD] [REV]"))
465 def bisect(ui, repo, rev=None, extra=None, command=None,
465 def bisect(ui, repo, rev=None, extra=None, command=None,
466 reset=None, good=None, bad=None, skip=None, extend=None,
466 reset=None, good=None, bad=None, skip=None, extend=None,
467 noupdate=None):
467 noupdate=None):
468 """subdivision search of changesets
468 """subdivision search of changesets
469
469
470 This command helps to find changesets which introduce problems. To
470 This command helps to find changesets which introduce problems. To
471 use, mark the earliest changeset you know exhibits the problem as
471 use, mark the earliest changeset you know exhibits the problem as
472 bad, then mark the latest changeset which is free from the problem
472 bad, then mark the latest changeset which is free from the problem
473 as good. Bisect will update your working directory to a revision
473 as good. Bisect will update your working directory to a revision
474 for testing (unless the -U/--noupdate option is specified). Once
474 for testing (unless the -U/--noupdate option is specified). Once
475 you have performed tests, mark the working directory as good or
475 you have performed tests, mark the working directory as good or
476 bad, and bisect will either update to another candidate changeset
476 bad, and bisect will either update to another candidate changeset
477 or announce that it has found the bad revision.
477 or announce that it has found the bad revision.
478
478
479 As a shortcut, you can also use the revision argument to mark a
479 As a shortcut, you can also use the revision argument to mark a
480 revision as good or bad without checking it out first.
480 revision as good or bad without checking it out first.
481
481
482 If you supply a command, it will be used for automatic bisection.
482 If you supply a command, it will be used for automatic bisection.
483 Its exit status will be used to mark revisions as good or bad:
483 Its exit status will be used to mark revisions as good or bad:
484 status 0 means good, 125 means to skip the revision, 127
484 status 0 means good, 125 means to skip the revision, 127
485 (command not found) will abort the bisection, and any other
485 (command not found) will abort the bisection, and any other
486 non-zero exit status means the revision is bad.
486 non-zero exit status means the revision is bad.
487
487
488 Returns 0 on success.
488 Returns 0 on success.
489 """
489 """
490 def extendbisectrange(nodes, good):
490 def extendbisectrange(nodes, good):
491 # bisect is incomplete when it ends on a merge node and
491 # bisect is incomplete when it ends on a merge node and
492 # one of the parent was not checked.
492 # one of the parent was not checked.
493 parents = repo[nodes[0]].parents()
493 parents = repo[nodes[0]].parents()
494 if len(parents) > 1:
494 if len(parents) > 1:
495 side = good and state['bad'] or state['good']
495 side = good and state['bad'] or state['good']
496 num = len(set(i.node() for i in parents) & set(side))
496 num = len(set(i.node() for i in parents) & set(side))
497 if num == 1:
497 if num == 1:
498 return parents[0].ancestor(parents[1])
498 return parents[0].ancestor(parents[1])
499 return None
499 return None
500
500
501 def print_result(nodes, good):
501 def print_result(nodes, good):
502 displayer = cmdutil.show_changeset(ui, repo, {})
502 displayer = cmdutil.show_changeset(ui, repo, {})
503 if len(nodes) == 1:
503 if len(nodes) == 1:
504 # narrowed it down to a single revision
504 # narrowed it down to a single revision
505 if good:
505 if good:
506 ui.write(_("The first good revision is:\n"))
506 ui.write(_("The first good revision is:\n"))
507 else:
507 else:
508 ui.write(_("The first bad revision is:\n"))
508 ui.write(_("The first bad revision is:\n"))
509 displayer.show(repo[nodes[0]])
509 displayer.show(repo[nodes[0]])
510 extendnode = extendbisectrange(nodes, good)
510 extendnode = extendbisectrange(nodes, good)
511 if extendnode is not None:
511 if extendnode is not None:
512 ui.write(_('Not all ancestors of this changeset have been'
512 ui.write(_('Not all ancestors of this changeset have been'
513 ' checked.\nUse bisect --extend to continue the '
513 ' checked.\nUse bisect --extend to continue the '
514 'bisection from\nthe common ancestor, %s.\n')
514 'bisection from\nthe common ancestor, %s.\n')
515 % extendnode)
515 % extendnode)
516 else:
516 else:
517 # multiple possible revisions
517 # multiple possible revisions
518 if good:
518 if good:
519 ui.write(_("Due to skipped revisions, the first "
519 ui.write(_("Due to skipped revisions, the first "
520 "good revision could be any of:\n"))
520 "good revision could be any of:\n"))
521 else:
521 else:
522 ui.write(_("Due to skipped revisions, the first "
522 ui.write(_("Due to skipped revisions, the first "
523 "bad revision could be any of:\n"))
523 "bad revision could be any of:\n"))
524 for n in nodes:
524 for n in nodes:
525 displayer.show(repo[n])
525 displayer.show(repo[n])
526 displayer.close()
526 displayer.close()
527
527
528 def check_state(state, interactive=True):
528 def check_state(state, interactive=True):
529 if not state['good'] or not state['bad']:
529 if not state['good'] or not state['bad']:
530 if (good or bad or skip or reset) and interactive:
530 if (good or bad or skip or reset) and interactive:
531 return
531 return
532 if not state['good']:
532 if not state['good']:
533 raise util.Abort(_('cannot bisect (no known good revisions)'))
533 raise util.Abort(_('cannot bisect (no known good revisions)'))
534 else:
534 else:
535 raise util.Abort(_('cannot bisect (no known bad revisions)'))
535 raise util.Abort(_('cannot bisect (no known bad revisions)'))
536 return True
536 return True
537
537
538 # backward compatibility
538 # backward compatibility
539 if rev in "good bad reset init".split():
539 if rev in "good bad reset init".split():
540 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
540 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
541 cmd, rev, extra = rev, extra, None
541 cmd, rev, extra = rev, extra, None
542 if cmd == "good":
542 if cmd == "good":
543 good = True
543 good = True
544 elif cmd == "bad":
544 elif cmd == "bad":
545 bad = True
545 bad = True
546 else:
546 else:
547 reset = True
547 reset = True
548 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
548 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
549 raise util.Abort(_('incompatible arguments'))
549 raise util.Abort(_('incompatible arguments'))
550
550
551 if reset:
551 if reset:
552 p = repo.join("bisect.state")
552 p = repo.join("bisect.state")
553 if os.path.exists(p):
553 if os.path.exists(p):
554 os.unlink(p)
554 os.unlink(p)
555 return
555 return
556
556
557 state = hbisect.load_state(repo)
557 state = hbisect.load_state(repo)
558
558
559 if command:
559 if command:
560 changesets = 1
560 changesets = 1
561 try:
561 try:
562 while changesets:
562 while changesets:
563 # update state
563 # update state
564 status = util.system(command)
564 status = util.system(command)
565 if status == 125:
565 if status == 125:
566 transition = "skip"
566 transition = "skip"
567 elif status == 0:
567 elif status == 0:
568 transition = "good"
568 transition = "good"
569 # status < 0 means process was killed
569 # status < 0 means process was killed
570 elif status == 127:
570 elif status == 127:
571 raise util.Abort(_("failed to execute %s") % command)
571 raise util.Abort(_("failed to execute %s") % command)
572 elif status < 0:
572 elif status < 0:
573 raise util.Abort(_("%s killed") % command)
573 raise util.Abort(_("%s killed") % command)
574 else:
574 else:
575 transition = "bad"
575 transition = "bad"
576 ctx = scmutil.revsingle(repo, rev)
576 ctx = scmutil.revsingle(repo, rev)
577 rev = None # clear for future iterations
577 rev = None # clear for future iterations
578 state[transition].append(ctx.node())
578 state[transition].append(ctx.node())
579 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
579 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
580 check_state(state, interactive=False)
580 check_state(state, interactive=False)
581 # bisect
581 # bisect
582 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
582 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
583 # update to next check
583 # update to next check
584 cmdutil.bailifchanged(repo)
584 cmdutil.bailifchanged(repo)
585 hg.clean(repo, nodes[0], show_stats=False)
585 hg.clean(repo, nodes[0], show_stats=False)
586 finally:
586 finally:
587 hbisect.save_state(repo, state)
587 hbisect.save_state(repo, state)
588 print_result(nodes, good)
588 print_result(nodes, good)
589 return
589 return
590
590
591 # update state
591 # update state
592
592
593 if rev:
593 if rev:
594 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
594 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
595 else:
595 else:
596 nodes = [repo.lookup('.')]
596 nodes = [repo.lookup('.')]
597
597
598 if good or bad or skip:
598 if good or bad or skip:
599 if good:
599 if good:
600 state['good'] += nodes
600 state['good'] += nodes
601 elif bad:
601 elif bad:
602 state['bad'] += nodes
602 state['bad'] += nodes
603 elif skip:
603 elif skip:
604 state['skip'] += nodes
604 state['skip'] += nodes
605 hbisect.save_state(repo, state)
605 hbisect.save_state(repo, state)
606
606
607 if not check_state(state):
607 if not check_state(state):
608 return
608 return
609
609
610 # actually bisect
610 # actually bisect
611 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
611 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
612 if extend:
612 if extend:
613 if not changesets:
613 if not changesets:
614 extendnode = extendbisectrange(nodes, good)
614 extendnode = extendbisectrange(nodes, good)
615 if extendnode is not None:
615 if extendnode is not None:
616 ui.write(_("Extending search to changeset %d:%s\n"
616 ui.write(_("Extending search to changeset %d:%s\n"
617 % (extendnode.rev(), extendnode)))
617 % (extendnode.rev(), extendnode)))
618 if noupdate:
618 if noupdate:
619 return
619 return
620 cmdutil.bailifchanged(repo)
620 cmdutil.bailifchanged(repo)
621 return hg.clean(repo, extendnode.node())
621 return hg.clean(repo, extendnode.node())
622 raise util.Abort(_("nothing to extend"))
622 raise util.Abort(_("nothing to extend"))
623
623
624 if changesets == 0:
624 if changesets == 0:
625 print_result(nodes, good)
625 print_result(nodes, good)
626 else:
626 else:
627 assert len(nodes) == 1 # only a single node can be tested next
627 assert len(nodes) == 1 # only a single node can be tested next
628 node = nodes[0]
628 node = nodes[0]
629 # compute the approximate number of remaining tests
629 # compute the approximate number of remaining tests
630 tests, size = 0, 2
630 tests, size = 0, 2
631 while size <= changesets:
631 while size <= changesets:
632 tests, size = tests + 1, size * 2
632 tests, size = tests + 1, size * 2
633 rev = repo.changelog.rev(node)
633 rev = repo.changelog.rev(node)
634 ui.write(_("Testing changeset %d:%s "
634 ui.write(_("Testing changeset %d:%s "
635 "(%d changesets remaining, ~%d tests)\n")
635 "(%d changesets remaining, ~%d tests)\n")
636 % (rev, short(node), changesets, tests))
636 % (rev, short(node), changesets, tests))
637 if not noupdate:
637 if not noupdate:
638 cmdutil.bailifchanged(repo)
638 cmdutil.bailifchanged(repo)
639 return hg.clean(repo, node)
639 return hg.clean(repo, node)
640
640
641 @command('bookmarks',
641 @command('bookmarks',
642 [('f', 'force', False, _('force')),
642 [('f', 'force', False, _('force')),
643 ('r', 'rev', '', _('revision'), _('REV')),
643 ('r', 'rev', '', _('revision'), _('REV')),
644 ('d', 'delete', False, _('delete a given bookmark')),
644 ('d', 'delete', False, _('delete a given bookmark')),
645 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
645 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
646 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
646 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
647 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
647 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
648 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
648 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
649 rename=None, inactive=False):
649 rename=None, inactive=False):
650 '''track a line of development with movable markers
650 '''track a line of development with movable markers
651
651
652 Bookmarks are pointers to certain commits that move when
652 Bookmarks are pointers to certain commits that move when
653 committing. Bookmarks are local. They can be renamed, copied and
653 committing. Bookmarks are local. They can be renamed, copied and
654 deleted. It is possible to use bookmark names in :hg:`merge` and
654 deleted. It is possible to use bookmark names in :hg:`merge` and
655 :hg:`update` to merge and update respectively to a given bookmark.
655 :hg:`update` to merge and update respectively to a given bookmark.
656
656
657 You can use :hg:`bookmark NAME` to set a bookmark on the working
657 You can use :hg:`bookmark NAME` to set a bookmark on the working
658 directory's parent revision with the given name. If you specify
658 directory's parent revision with the given name. If you specify
659 a revision using -r REV (where REV may be an existing bookmark),
659 a revision using -r REV (where REV may be an existing bookmark),
660 the bookmark is assigned to that revision.
660 the bookmark is assigned to that revision.
661
661
662 Bookmarks can be pushed and pulled between repositories (see :hg:`help
662 Bookmarks can be pushed and pulled between repositories (see :hg:`help
663 push` and :hg:`help pull`). This requires both the local and remote
663 push` and :hg:`help pull`). This requires both the local and remote
664 repositories to support bookmarks. For versions prior to 1.8, this means
664 repositories to support bookmarks. For versions prior to 1.8, this means
665 the bookmarks extension must be enabled.
665 the bookmarks extension must be enabled.
666 '''
666 '''
667 hexfn = ui.debugflag and hex or short
667 hexfn = ui.debugflag and hex or short
668 marks = repo._bookmarks
668 marks = repo._bookmarks
669 cur = repo.changectx('.').node()
669 cur = repo.changectx('.').node()
670
670
671 if rename:
671 if rename:
672 if rename not in marks:
672 if rename not in marks:
673 raise util.Abort(_("bookmark '%s' does not exist") % rename)
673 raise util.Abort(_("bookmark '%s' does not exist") % rename)
674 if mark in marks and not force:
674 if mark in marks and not force:
675 raise util.Abort(_("bookmark '%s' already exists "
675 raise util.Abort(_("bookmark '%s' already exists "
676 "(use -f to force)") % mark)
676 "(use -f to force)") % mark)
677 if mark is None:
677 if mark is None:
678 raise util.Abort(_("new bookmark name required"))
678 raise util.Abort(_("new bookmark name required"))
679 marks[mark] = marks[rename]
679 marks[mark] = marks[rename]
680 if repo._bookmarkcurrent == rename and not inactive:
680 if repo._bookmarkcurrent == rename and not inactive:
681 bookmarks.setcurrent(repo, mark)
681 bookmarks.setcurrent(repo, mark)
682 del marks[rename]
682 del marks[rename]
683 bookmarks.write(repo)
683 bookmarks.write(repo)
684 return
684 return
685
685
686 if delete:
686 if delete:
687 if mark is None:
687 if mark is None:
688 raise util.Abort(_("bookmark name required"))
688 raise util.Abort(_("bookmark name required"))
689 if mark not in marks:
689 if mark not in marks:
690 raise util.Abort(_("bookmark '%s' does not exist") % mark)
690 raise util.Abort(_("bookmark '%s' does not exist") % mark)
691 if mark == repo._bookmarkcurrent:
691 if mark == repo._bookmarkcurrent:
692 bookmarks.setcurrent(repo, None)
692 bookmarks.setcurrent(repo, None)
693 del marks[mark]
693 del marks[mark]
694 bookmarks.write(repo)
694 bookmarks.write(repo)
695 return
695 return
696
696
697 if mark is not None:
697 if mark is not None:
698 if "\n" in mark:
698 if "\n" in mark:
699 raise util.Abort(_("bookmark name cannot contain newlines"))
699 raise util.Abort(_("bookmark name cannot contain newlines"))
700 mark = mark.strip()
700 mark = mark.strip()
701 if not mark:
701 if not mark:
702 raise util.Abort(_("bookmark names cannot consist entirely of "
702 raise util.Abort(_("bookmark names cannot consist entirely of "
703 "whitespace"))
703 "whitespace"))
704 if inactive and mark == repo._bookmarkcurrent:
704 if inactive and mark == repo._bookmarkcurrent:
705 bookmarks.setcurrent(repo, None)
705 bookmarks.setcurrent(repo, None)
706 return
706 return
707 if mark in marks and not force:
707 if mark in marks and not force:
708 raise util.Abort(_("bookmark '%s' already exists "
708 raise util.Abort(_("bookmark '%s' already exists "
709 "(use -f to force)") % mark)
709 "(use -f to force)") % mark)
710 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
710 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
711 and not force):
711 and not force):
712 raise util.Abort(
712 raise util.Abort(
713 _("a bookmark cannot have the name of an existing branch"))
713 _("a bookmark cannot have the name of an existing branch"))
714 if rev:
714 if rev:
715 marks[mark] = repo.lookup(rev)
715 marks[mark] = repo.lookup(rev)
716 else:
716 else:
717 marks[mark] = repo.changectx('.').node()
717 marks[mark] = repo.changectx('.').node()
718 if not inactive and repo.changectx('.').node() == marks[mark]:
718 if not inactive and repo.changectx('.').node() == marks[mark]:
719 bookmarks.setcurrent(repo, mark)
719 bookmarks.setcurrent(repo, mark)
720 bookmarks.write(repo)
720 bookmarks.write(repo)
721 return
721 return
722
722
723 if mark is None:
723 if mark is None:
724 if rev:
724 if rev:
725 raise util.Abort(_("bookmark name required"))
725 raise util.Abort(_("bookmark name required"))
726 if len(marks) == 0:
726 if len(marks) == 0:
727 ui.status(_("no bookmarks set\n"))
727 ui.status(_("no bookmarks set\n"))
728 else:
728 else:
729 for bmark, n in sorted(marks.iteritems()):
729 for bmark, n in sorted(marks.iteritems()):
730 current = repo._bookmarkcurrent
730 current = repo._bookmarkcurrent
731 if bmark == current and n == cur:
731 if bmark == current and n == cur:
732 prefix, label = '*', 'bookmarks.current'
732 prefix, label = '*', 'bookmarks.current'
733 else:
733 else:
734 prefix, label = ' ', ''
734 prefix, label = ' ', ''
735
735
736 if ui.quiet:
736 if ui.quiet:
737 ui.write("%s\n" % bmark, label=label)
737 ui.write("%s\n" % bmark, label=label)
738 else:
738 else:
739 ui.write(" %s %-25s %d:%s\n" % (
739 ui.write(" %s %-25s %d:%s\n" % (
740 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
740 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
741 label=label)
741 label=label)
742 return
742 return
743
743
744 @command('branch',
744 @command('branch',
745 [('f', 'force', None,
745 [('f', 'force', None,
746 _('set branch name even if it shadows an existing branch')),
746 _('set branch name even if it shadows an existing branch')),
747 ('C', 'clean', None, _('reset branch name to parent branch name'))],
747 ('C', 'clean', None, _('reset branch name to parent branch name'))],
748 _('[-fC] [NAME]'))
748 _('[-fC] [NAME]'))
749 def branch(ui, repo, label=None, **opts):
749 def branch(ui, repo, label=None, **opts):
750 """set or show the current branch name
750 """set or show the current branch name
751
751
752 With no argument, show the current branch name. With one argument,
752 With no argument, show the current branch name. With one argument,
753 set the working directory branch name (the branch will not exist
753 set the working directory branch name (the branch will not exist
754 in the repository until the next commit). Standard practice
754 in the repository until the next commit). Standard practice
755 recommends that primary development take place on the 'default'
755 recommends that primary development take place on the 'default'
756 branch.
756 branch.
757
757
758 Unless -f/--force is specified, branch will not let you set a
758 Unless -f/--force is specified, branch will not let you set a
759 branch name that already exists, even if it's inactive.
759 branch name that already exists, even if it's inactive.
760
760
761 Use -C/--clean to reset the working directory branch to that of
761 Use -C/--clean to reset the working directory branch to that of
762 the parent of the working directory, negating a previous branch
762 the parent of the working directory, negating a previous branch
763 change.
763 change.
764
764
765 Use the command :hg:`update` to switch to an existing branch. Use
765 Use the command :hg:`update` to switch to an existing branch. Use
766 :hg:`commit --close-branch` to mark this branch as closed.
766 :hg:`commit --close-branch` to mark this branch as closed.
767
767
768 Returns 0 on success.
768 Returns 0 on success.
769 """
769 """
770
770
771 if opts.get('clean'):
771 if opts.get('clean'):
772 label = repo[None].p1().branch()
772 label = repo[None].p1().branch()
773 repo.dirstate.setbranch(label)
773 repo.dirstate.setbranch(label)
774 ui.status(_('reset working directory to branch %s\n') % label)
774 ui.status(_('reset working directory to branch %s\n') % label)
775 elif label:
775 elif label:
776 if not opts.get('force') and label in repo.branchtags():
776 if not opts.get('force') and label in repo.branchtags():
777 if label not in [p.branch() for p in repo.parents()]:
777 if label not in [p.branch() for p in repo.parents()]:
778 raise util.Abort(_('a branch of the same name already exists'),
778 raise util.Abort(_('a branch of the same name already exists'),
779 # i18n: "it" refers to an existing branch
779 # i18n: "it" refers to an existing branch
780 hint=_("use 'hg update' to switch to it"))
780 hint=_("use 'hg update' to switch to it"))
781 repo.dirstate.setbranch(label)
781 repo.dirstate.setbranch(label)
782 ui.status(_('marked working directory as branch %s\n') % label)
782 ui.status(_('marked working directory as branch %s\n') % label)
783 else:
783 else:
784 ui.write("%s\n" % repo.dirstate.branch())
784 ui.write("%s\n" % repo.dirstate.branch())
785
785
786 @command('branches',
786 @command('branches',
787 [('a', 'active', False, _('show only branches that have unmerged heads')),
787 [('a', 'active', False, _('show only branches that have unmerged heads')),
788 ('c', 'closed', False, _('show normal and closed branches'))],
788 ('c', 'closed', False, _('show normal and closed branches'))],
789 _('[-ac]'))
789 _('[-ac]'))
790 def branches(ui, repo, active=False, closed=False):
790 def branches(ui, repo, active=False, closed=False):
791 """list repository named branches
791 """list repository named branches
792
792
793 List the repository's named branches, indicating which ones are
793 List the repository's named branches, indicating which ones are
794 inactive. If -c/--closed is specified, also list branches which have
794 inactive. If -c/--closed is specified, also list branches which have
795 been marked closed (see :hg:`commit --close-branch`).
795 been marked closed (see :hg:`commit --close-branch`).
796
796
797 If -a/--active is specified, only show active branches. A branch
797 If -a/--active is specified, only show active branches. A branch
798 is considered active if it contains repository heads.
798 is considered active if it contains repository heads.
799
799
800 Use the command :hg:`update` to switch to an existing branch.
800 Use the command :hg:`update` to switch to an existing branch.
801
801
802 Returns 0.
802 Returns 0.
803 """
803 """
804
804
805 hexfunc = ui.debugflag and hex or short
805 hexfunc = ui.debugflag and hex or short
806 activebranches = [repo[n].branch() for n in repo.heads()]
806 activebranches = [repo[n].branch() for n in repo.heads()]
807 def testactive(tag, node):
807 def testactive(tag, node):
808 realhead = tag in activebranches
808 realhead = tag in activebranches
809 open = node in repo.branchheads(tag, closed=False)
809 open = node in repo.branchheads(tag, closed=False)
810 return realhead and open
810 return realhead and open
811 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
811 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
812 for tag, node in repo.branchtags().items()],
812 for tag, node in repo.branchtags().items()],
813 reverse=True)
813 reverse=True)
814
814
815 for isactive, node, tag in branches:
815 for isactive, node, tag in branches:
816 if (not active) or isactive:
816 if (not active) or isactive:
817 if ui.quiet:
817 if ui.quiet:
818 ui.write("%s\n" % tag)
818 ui.write("%s\n" % tag)
819 else:
819 else:
820 hn = repo.lookup(node)
820 hn = repo.lookup(node)
821 if isactive:
821 if isactive:
822 label = 'branches.active'
822 label = 'branches.active'
823 notice = ''
823 notice = ''
824 elif hn not in repo.branchheads(tag, closed=False):
824 elif hn not in repo.branchheads(tag, closed=False):
825 if not closed:
825 if not closed:
826 continue
826 continue
827 label = 'branches.closed'
827 label = 'branches.closed'
828 notice = _(' (closed)')
828 notice = _(' (closed)')
829 else:
829 else:
830 label = 'branches.inactive'
830 label = 'branches.inactive'
831 notice = _(' (inactive)')
831 notice = _(' (inactive)')
832 if tag == repo.dirstate.branch():
832 if tag == repo.dirstate.branch():
833 label = 'branches.current'
833 label = 'branches.current'
834 rev = str(node).rjust(31 - encoding.colwidth(tag))
834 rev = str(node).rjust(31 - encoding.colwidth(tag))
835 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
835 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
836 tag = ui.label(tag, label)
836 tag = ui.label(tag, label)
837 ui.write("%s %s%s\n" % (tag, rev, notice))
837 ui.write("%s %s%s\n" % (tag, rev, notice))
838
838
839 @command('bundle',
839 @command('bundle',
840 [('f', 'force', None, _('run even when the destination is unrelated')),
840 [('f', 'force', None, _('run even when the destination is unrelated')),
841 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
841 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
842 _('REV')),
842 _('REV')),
843 ('b', 'branch', [], _('a specific branch you would like to bundle'),
843 ('b', 'branch', [], _('a specific branch you would like to bundle'),
844 _('BRANCH')),
844 _('BRANCH')),
845 ('', 'base', [],
845 ('', 'base', [],
846 _('a base changeset assumed to be available at the destination'),
846 _('a base changeset assumed to be available at the destination'),
847 _('REV')),
847 _('REV')),
848 ('a', 'all', None, _('bundle all changesets in the repository')),
848 ('a', 'all', None, _('bundle all changesets in the repository')),
849 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
849 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
850 ] + remoteopts,
850 ] + remoteopts,
851 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
851 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
852 def bundle(ui, repo, fname, dest=None, **opts):
852 def bundle(ui, repo, fname, dest=None, **opts):
853 """create a changegroup file
853 """create a changegroup file
854
854
855 Generate a compressed changegroup file collecting changesets not
855 Generate a compressed changegroup file collecting changesets not
856 known to be in another repository.
856 known to be in another repository.
857
857
858 If you omit the destination repository, then hg assumes the
858 If you omit the destination repository, then hg assumes the
859 destination will have all the nodes you specify with --base
859 destination will have all the nodes you specify with --base
860 parameters. To create a bundle containing all changesets, use
860 parameters. To create a bundle containing all changesets, use
861 -a/--all (or --base null).
861 -a/--all (or --base null).
862
862
863 You can change compression method with the -t/--type option.
863 You can change compression method with the -t/--type option.
864 The available compression methods are: none, bzip2, and
864 The available compression methods are: none, bzip2, and
865 gzip (by default, bundles are compressed using bzip2).
865 gzip (by default, bundles are compressed using bzip2).
866
866
867 The bundle file can then be transferred using conventional means
867 The bundle file can then be transferred using conventional means
868 and applied to another repository with the unbundle or pull
868 and applied to another repository with the unbundle or pull
869 command. This is useful when direct push and pull are not
869 command. This is useful when direct push and pull are not
870 available or when exporting an entire repository is undesirable.
870 available or when exporting an entire repository is undesirable.
871
871
872 Applying bundles preserves all changeset contents including
872 Applying bundles preserves all changeset contents including
873 permissions, copy/rename information, and revision history.
873 permissions, copy/rename information, and revision history.
874
874
875 Returns 0 on success, 1 if no changes found.
875 Returns 0 on success, 1 if no changes found.
876 """
876 """
877 revs = None
877 revs = None
878 if 'rev' in opts:
878 if 'rev' in opts:
879 revs = scmutil.revrange(repo, opts['rev'])
879 revs = scmutil.revrange(repo, opts['rev'])
880
880
881 if opts.get('all'):
881 if opts.get('all'):
882 base = ['null']
882 base = ['null']
883 else:
883 else:
884 base = scmutil.revrange(repo, opts.get('base'))
884 base = scmutil.revrange(repo, opts.get('base'))
885 if base:
885 if base:
886 if dest:
886 if dest:
887 raise util.Abort(_("--base is incompatible with specifying "
887 raise util.Abort(_("--base is incompatible with specifying "
888 "a destination"))
888 "a destination"))
889 common = [repo.lookup(rev) for rev in base]
889 common = [repo.lookup(rev) for rev in base]
890 heads = revs and map(repo.lookup, revs) or revs
890 heads = revs and map(repo.lookup, revs) or revs
891 else:
891 else:
892 dest = ui.expandpath(dest or 'default-push', dest or 'default')
892 dest = ui.expandpath(dest or 'default-push', dest or 'default')
893 dest, branches = hg.parseurl(dest, opts.get('branch'))
893 dest, branches = hg.parseurl(dest, opts.get('branch'))
894 other = hg.repository(hg.remoteui(repo, opts), dest)
894 other = hg.repository(hg.remoteui(repo, opts), dest)
895 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
895 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
896 heads = revs and map(repo.lookup, revs) or revs
896 heads = revs and map(repo.lookup, revs) or revs
897 common, outheads = discovery.findcommonoutgoing(repo, other,
897 common, outheads = discovery.findcommonoutgoing(repo, other,
898 onlyheads=heads,
898 onlyheads=heads,
899 force=opts.get('force'))
899 force=opts.get('force'))
900
900
901 cg = repo.getbundle('bundle', common=common, heads=heads)
901 cg = repo.getbundle('bundle', common=common, heads=heads)
902 if not cg:
902 if not cg:
903 ui.status(_("no changes found\n"))
903 ui.status(_("no changes found\n"))
904 return 1
904 return 1
905
905
906 bundletype = opts.get('type', 'bzip2').lower()
906 bundletype = opts.get('type', 'bzip2').lower()
907 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
907 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
908 bundletype = btypes.get(bundletype)
908 bundletype = btypes.get(bundletype)
909 if bundletype not in changegroup.bundletypes:
909 if bundletype not in changegroup.bundletypes:
910 raise util.Abort(_('unknown bundle type specified with --type'))
910 raise util.Abort(_('unknown bundle type specified with --type'))
911
911
912 changegroup.writebundle(cg, fname, bundletype)
912 changegroup.writebundle(cg, fname, bundletype)
913
913
914 @command('cat',
914 @command('cat',
915 [('o', 'output', '',
915 [('o', 'output', '',
916 _('print output to file with formatted name'), _('FORMAT')),
916 _('print output to file with formatted name'), _('FORMAT')),
917 ('r', 'rev', '', _('print the given revision'), _('REV')),
917 ('r', 'rev', '', _('print the given revision'), _('REV')),
918 ('', 'decode', None, _('apply any matching decode filter')),
918 ('', 'decode', None, _('apply any matching decode filter')),
919 ] + walkopts,
919 ] + walkopts,
920 _('[OPTION]... FILE...'))
920 _('[OPTION]... FILE...'))
921 def cat(ui, repo, file1, *pats, **opts):
921 def cat(ui, repo, file1, *pats, **opts):
922 """output the current or given revision of files
922 """output the current or given revision of files
923
923
924 Print the specified files as they were at the given revision. If
924 Print the specified files as they were at the given revision. If
925 no revision is given, the parent of the working directory is used,
925 no revision is given, the parent of the working directory is used,
926 or tip if no revision is checked out.
926 or tip if no revision is checked out.
927
927
928 Output may be to a file, in which case the name of the file is
928 Output may be to a file, in which case the name of the file is
929 given using a format string. The formatting rules are the same as
929 given using a format string. The formatting rules are the same as
930 for the export command, with the following additions:
930 for the export command, with the following additions:
931
931
932 :``%s``: basename of file being printed
932 :``%s``: basename of file being printed
933 :``%d``: dirname of file being printed, or '.' if in repository root
933 :``%d``: dirname of file being printed, or '.' if in repository root
934 :``%p``: root-relative path name of file being printed
934 :``%p``: root-relative path name of file being printed
935
935
936 Returns 0 on success.
936 Returns 0 on success.
937 """
937 """
938 ctx = scmutil.revsingle(repo, opts.get('rev'))
938 ctx = scmutil.revsingle(repo, opts.get('rev'))
939 err = 1
939 err = 1
940 m = scmutil.match(repo, (file1,) + pats, opts)
940 m = scmutil.match(repo, (file1,) + pats, opts)
941 for abs in ctx.walk(m):
941 for abs in ctx.walk(m):
942 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
942 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
943 pathname=abs)
943 pathname=abs)
944 data = ctx[abs].data()
944 data = ctx[abs].data()
945 if opts.get('decode'):
945 if opts.get('decode'):
946 data = repo.wwritedata(abs, data)
946 data = repo.wwritedata(abs, data)
947 fp.write(data)
947 fp.write(data)
948 fp.close()
948 fp.close()
949 err = 0
949 err = 0
950 return err
950 return err
951
951
952 @command('^clone',
952 @command('^clone',
953 [('U', 'noupdate', None,
953 [('U', 'noupdate', None,
954 _('the clone will include an empty working copy (only a repository)')),
954 _('the clone will include an empty working copy (only a repository)')),
955 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
955 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
956 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
956 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
957 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
957 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
958 ('', 'pull', None, _('use pull protocol to copy metadata')),
958 ('', 'pull', None, _('use pull protocol to copy metadata')),
959 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
959 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
960 ] + remoteopts,
960 ] + remoteopts,
961 _('[OPTION]... SOURCE [DEST]'))
961 _('[OPTION]... SOURCE [DEST]'))
962 def clone(ui, source, dest=None, **opts):
962 def clone(ui, source, dest=None, **opts):
963 """make a copy of an existing repository
963 """make a copy of an existing repository
964
964
965 Create a copy of an existing repository in a new directory.
965 Create a copy of an existing repository in a new directory.
966
966
967 If no destination directory name is specified, it defaults to the
967 If no destination directory name is specified, it defaults to the
968 basename of the source.
968 basename of the source.
969
969
970 The location of the source is added to the new repository's
970 The location of the source is added to the new repository's
971 ``.hg/hgrc`` file, as the default to be used for future pulls.
971 ``.hg/hgrc`` file, as the default to be used for future pulls.
972
972
973 See :hg:`help urls` for valid source format details.
973 See :hg:`help urls` for valid source format details.
974
974
975 It is possible to specify an ``ssh://`` URL as the destination, but no
975 It is possible to specify an ``ssh://`` URL as the destination, but no
976 ``.hg/hgrc`` and working directory will be created on the remote side.
976 ``.hg/hgrc`` and working directory will be created on the remote side.
977 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
977 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
978
978
979 A set of changesets (tags, or branch names) to pull may be specified
979 A set of changesets (tags, or branch names) to pull may be specified
980 by listing each changeset (tag, or branch name) with -r/--rev.
980 by listing each changeset (tag, or branch name) with -r/--rev.
981 If -r/--rev is used, the cloned repository will contain only a subset
981 If -r/--rev is used, the cloned repository will contain only a subset
982 of the changesets of the source repository. Only the set of changesets
982 of the changesets of the source repository. Only the set of changesets
983 defined by all -r/--rev options (including all their ancestors)
983 defined by all -r/--rev options (including all their ancestors)
984 will be pulled into the destination repository.
984 will be pulled into the destination repository.
985 No subsequent changesets (including subsequent tags) will be present
985 No subsequent changesets (including subsequent tags) will be present
986 in the destination.
986 in the destination.
987
987
988 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
988 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
989 local source repositories.
989 local source repositories.
990
990
991 For efficiency, hardlinks are used for cloning whenever the source
991 For efficiency, hardlinks are used for cloning whenever the source
992 and destination are on the same filesystem (note this applies only
992 and destination are on the same filesystem (note this applies only
993 to the repository data, not to the working directory). Some
993 to the repository data, not to the working directory). Some
994 filesystems, such as AFS, implement hardlinking incorrectly, but
994 filesystems, such as AFS, implement hardlinking incorrectly, but
995 do not report errors. In these cases, use the --pull option to
995 do not report errors. In these cases, use the --pull option to
996 avoid hardlinking.
996 avoid hardlinking.
997
997
998 In some cases, you can clone repositories and the working directory
998 In some cases, you can clone repositories and the working directory
999 using full hardlinks with ::
999 using full hardlinks with ::
1000
1000
1001 $ cp -al REPO REPOCLONE
1001 $ cp -al REPO REPOCLONE
1002
1002
1003 This is the fastest way to clone, but it is not always safe. The
1003 This is the fastest way to clone, but it is not always safe. The
1004 operation is not atomic (making sure REPO is not modified during
1004 operation is not atomic (making sure REPO is not modified during
1005 the operation is up to you) and you have to make sure your editor
1005 the operation is up to you) and you have to make sure your editor
1006 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1006 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1007 this is not compatible with certain extensions that place their
1007 this is not compatible with certain extensions that place their
1008 metadata under the .hg directory, such as mq.
1008 metadata under the .hg directory, such as mq.
1009
1009
1010 Mercurial will update the working directory to the first applicable
1010 Mercurial will update the working directory to the first applicable
1011 revision from this list:
1011 revision from this list:
1012
1012
1013 a) null if -U or the source repository has no changesets
1013 a) null if -U or the source repository has no changesets
1014 b) if -u . and the source repository is local, the first parent of
1014 b) if -u . and the source repository is local, the first parent of
1015 the source repository's working directory
1015 the source repository's working directory
1016 c) the changeset specified with -u (if a branch name, this means the
1016 c) the changeset specified with -u (if a branch name, this means the
1017 latest head of that branch)
1017 latest head of that branch)
1018 d) the changeset specified with -r
1018 d) the changeset specified with -r
1019 e) the tipmost head specified with -b
1019 e) the tipmost head specified with -b
1020 f) the tipmost head specified with the url#branch source syntax
1020 f) the tipmost head specified with the url#branch source syntax
1021 g) the tipmost head of the default branch
1021 g) the tipmost head of the default branch
1022 h) tip
1022 h) tip
1023
1023
1024 Returns 0 on success.
1024 Returns 0 on success.
1025 """
1025 """
1026 if opts.get('noupdate') and opts.get('updaterev'):
1026 if opts.get('noupdate') and opts.get('updaterev'):
1027 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1027 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1028
1028
1029 r = hg.clone(hg.remoteui(ui, opts), source, dest,
1029 r = hg.clone(hg.remoteui(ui, opts), source, dest,
1030 pull=opts.get('pull'),
1030 pull=opts.get('pull'),
1031 stream=opts.get('uncompressed'),
1031 stream=opts.get('uncompressed'),
1032 rev=opts.get('rev'),
1032 rev=opts.get('rev'),
1033 update=opts.get('updaterev') or not opts.get('noupdate'),
1033 update=opts.get('updaterev') or not opts.get('noupdate'),
1034 branch=opts.get('branch'))
1034 branch=opts.get('branch'))
1035
1035
1036 return r is None
1036 return r is None
1037
1037
1038 @command('^commit|ci',
1038 @command('^commit|ci',
1039 [('A', 'addremove', None,
1039 [('A', 'addremove', None,
1040 _('mark new/missing files as added/removed before committing')),
1040 _('mark new/missing files as added/removed before committing')),
1041 ('', 'close-branch', None,
1041 ('', 'close-branch', None,
1042 _('mark a branch as closed, hiding it from the branch list')),
1042 _('mark a branch as closed, hiding it from the branch list')),
1043 ] + walkopts + commitopts + commitopts2,
1043 ] + walkopts + commitopts + commitopts2,
1044 _('[OPTION]... [FILE]...'))
1044 _('[OPTION]... [FILE]...'))
1045 def commit(ui, repo, *pats, **opts):
1045 def commit(ui, repo, *pats, **opts):
1046 """commit the specified files or all outstanding changes
1046 """commit the specified files or all outstanding changes
1047
1047
1048 Commit changes to the given files into the repository. Unlike a
1048 Commit changes to the given files into the repository. Unlike a
1049 centralized SCM, this operation is a local operation. See
1049 centralized SCM, this operation is a local operation. See
1050 :hg:`push` for a way to actively distribute your changes.
1050 :hg:`push` for a way to actively distribute your changes.
1051
1051
1052 If a list of files is omitted, all changes reported by :hg:`status`
1052 If a list of files is omitted, all changes reported by :hg:`status`
1053 will be committed.
1053 will be committed.
1054
1054
1055 If you are committing the result of a merge, do not provide any
1055 If you are committing the result of a merge, do not provide any
1056 filenames or -I/-X filters.
1056 filenames or -I/-X filters.
1057
1057
1058 If no commit message is specified, Mercurial starts your
1058 If no commit message is specified, Mercurial starts your
1059 configured editor where you can enter a message. In case your
1059 configured editor where you can enter a message. In case your
1060 commit fails, you will find a backup of your message in
1060 commit fails, you will find a backup of your message in
1061 ``.hg/last-message.txt``.
1061 ``.hg/last-message.txt``.
1062
1062
1063 See :hg:`help dates` for a list of formats valid for -d/--date.
1063 See :hg:`help dates` for a list of formats valid for -d/--date.
1064
1064
1065 Returns 0 on success, 1 if nothing changed.
1065 Returns 0 on success, 1 if nothing changed.
1066 """
1066 """
1067 extra = {}
1067 extra = {}
1068 if opts.get('close_branch'):
1068 if opts.get('close_branch'):
1069 if repo['.'].node() not in repo.branchheads():
1069 if repo['.'].node() not in repo.branchheads():
1070 # The topo heads set is included in the branch heads set of the
1070 # The topo heads set is included in the branch heads set of the
1071 # current branch, so it's sufficient to test branchheads
1071 # current branch, so it's sufficient to test branchheads
1072 raise util.Abort(_('can only close branch heads'))
1072 raise util.Abort(_('can only close branch heads'))
1073 extra['close'] = 1
1073 extra['close'] = 1
1074 e = cmdutil.commiteditor
1074 e = cmdutil.commiteditor
1075 if opts.get('force_editor'):
1075 if opts.get('force_editor'):
1076 e = cmdutil.commitforceeditor
1076 e = cmdutil.commitforceeditor
1077
1077
1078 def commitfunc(ui, repo, message, match, opts):
1078 def commitfunc(ui, repo, message, match, opts):
1079 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1079 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1080 editor=e, extra=extra)
1080 editor=e, extra=extra)
1081
1081
1082 branch = repo[None].branch()
1082 branch = repo[None].branch()
1083 bheads = repo.branchheads(branch)
1083 bheads = repo.branchheads(branch)
1084
1084
1085 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1085 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1086 if not node:
1086 if not node:
1087 stat = repo.status(match=scmutil.match(repo, pats, opts))
1087 stat = repo.status(match=scmutil.match(repo, pats, opts))
1088 if stat[3]:
1088 if stat[3]:
1089 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1089 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1090 % len(stat[3]))
1090 % len(stat[3]))
1091 else:
1091 else:
1092 ui.status(_("nothing changed\n"))
1092 ui.status(_("nothing changed\n"))
1093 return 1
1093 return 1
1094
1094
1095 ctx = repo[node]
1095 ctx = repo[node]
1096 parents = ctx.parents()
1096 parents = ctx.parents()
1097
1097
1098 if bheads and not [x for x in parents
1098 if bheads and not [x for x in parents
1099 if x.node() in bheads and x.branch() == branch]:
1099 if x.node() in bheads and x.branch() == branch]:
1100 ui.status(_('created new head\n'))
1100 ui.status(_('created new head\n'))
1101 # The message is not printed for initial roots. For the other
1101 # The message is not printed for initial roots. For the other
1102 # changesets, it is printed in the following situations:
1102 # changesets, it is printed in the following situations:
1103 #
1103 #
1104 # Par column: for the 2 parents with ...
1104 # Par column: for the 2 parents with ...
1105 # N: null or no parent
1105 # N: null or no parent
1106 # B: parent is on another named branch
1106 # B: parent is on another named branch
1107 # C: parent is a regular non head changeset
1107 # C: parent is a regular non head changeset
1108 # H: parent was a branch head of the current branch
1108 # H: parent was a branch head of the current branch
1109 # Msg column: whether we print "created new head" message
1109 # Msg column: whether we print "created new head" message
1110 # In the following, it is assumed that there already exists some
1110 # In the following, it is assumed that there already exists some
1111 # initial branch heads of the current branch, otherwise nothing is
1111 # initial branch heads of the current branch, otherwise nothing is
1112 # printed anyway.
1112 # printed anyway.
1113 #
1113 #
1114 # Par Msg Comment
1114 # Par Msg Comment
1115 # NN y additional topo root
1115 # NN y additional topo root
1116 #
1116 #
1117 # BN y additional branch root
1117 # BN y additional branch root
1118 # CN y additional topo head
1118 # CN y additional topo head
1119 # HN n usual case
1119 # HN n usual case
1120 #
1120 #
1121 # BB y weird additional branch root
1121 # BB y weird additional branch root
1122 # CB y branch merge
1122 # CB y branch merge
1123 # HB n merge with named branch
1123 # HB n merge with named branch
1124 #
1124 #
1125 # CC y additional head from merge
1125 # CC y additional head from merge
1126 # CH n merge with a head
1126 # CH n merge with a head
1127 #
1127 #
1128 # HH n head merge: head count decreases
1128 # HH n head merge: head count decreases
1129
1129
1130 if not opts.get('close_branch'):
1130 if not opts.get('close_branch'):
1131 for r in parents:
1131 for r in parents:
1132 if r.extra().get('close') and r.branch() == branch:
1132 if r.extra().get('close') and r.branch() == branch:
1133 ui.status(_('reopening closed branch head %d\n') % r)
1133 ui.status(_('reopening closed branch head %d\n') % r)
1134
1134
1135 if ui.debugflag:
1135 if ui.debugflag:
1136 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1136 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1137 elif ui.verbose:
1137 elif ui.verbose:
1138 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1138 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1139
1139
1140 @command('copy|cp',
1140 @command('copy|cp',
1141 [('A', 'after', None, _('record a copy that has already occurred')),
1141 [('A', 'after', None, _('record a copy that has already occurred')),
1142 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1142 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1143 ] + walkopts + dryrunopts,
1143 ] + walkopts + dryrunopts,
1144 _('[OPTION]... [SOURCE]... DEST'))
1144 _('[OPTION]... [SOURCE]... DEST'))
1145 def copy(ui, repo, *pats, **opts):
1145 def copy(ui, repo, *pats, **opts):
1146 """mark files as copied for the next commit
1146 """mark files as copied for the next commit
1147
1147
1148 Mark dest as having copies of source files. If dest is a
1148 Mark dest as having copies of source files. If dest is a
1149 directory, copies are put in that directory. If dest is a file,
1149 directory, copies are put in that directory. If dest is a file,
1150 the source must be a single file.
1150 the source must be a single file.
1151
1151
1152 By default, this command copies the contents of files as they
1152 By default, this command copies the contents of files as they
1153 exist in the working directory. If invoked with -A/--after, the
1153 exist in the working directory. If invoked with -A/--after, the
1154 operation is recorded, but no copying is performed.
1154 operation is recorded, but no copying is performed.
1155
1155
1156 This command takes effect with the next commit. To undo a copy
1156 This command takes effect with the next commit. To undo a copy
1157 before that, see :hg:`revert`.
1157 before that, see :hg:`revert`.
1158
1158
1159 Returns 0 on success, 1 if errors are encountered.
1159 Returns 0 on success, 1 if errors are encountered.
1160 """
1160 """
1161 wlock = repo.wlock(False)
1161 wlock = repo.wlock(False)
1162 try:
1162 try:
1163 return cmdutil.copy(ui, repo, pats, opts)
1163 return cmdutil.copy(ui, repo, pats, opts)
1164 finally:
1164 finally:
1165 wlock.release()
1165 wlock.release()
1166
1166
1167 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1167 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1168 def debugancestor(ui, repo, *args):
1168 def debugancestor(ui, repo, *args):
1169 """find the ancestor revision of two revisions in a given index"""
1169 """find the ancestor revision of two revisions in a given index"""
1170 if len(args) == 3:
1170 if len(args) == 3:
1171 index, rev1, rev2 = args
1171 index, rev1, rev2 = args
1172 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1172 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1173 lookup = r.lookup
1173 lookup = r.lookup
1174 elif len(args) == 2:
1174 elif len(args) == 2:
1175 if not repo:
1175 if not repo:
1176 raise util.Abort(_("there is no Mercurial repository here "
1176 raise util.Abort(_("there is no Mercurial repository here "
1177 "(.hg not found)"))
1177 "(.hg not found)"))
1178 rev1, rev2 = args
1178 rev1, rev2 = args
1179 r = repo.changelog
1179 r = repo.changelog
1180 lookup = repo.lookup
1180 lookup = repo.lookup
1181 else:
1181 else:
1182 raise util.Abort(_('either two or three arguments required'))
1182 raise util.Abort(_('either two or three arguments required'))
1183 a = r.ancestor(lookup(rev1), lookup(rev2))
1183 a = r.ancestor(lookup(rev1), lookup(rev2))
1184 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1184 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1185
1185
1186 @command('debugbuilddag',
1186 @command('debugbuilddag',
1187 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1187 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1188 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1188 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1189 ('n', 'new-file', None, _('add new file at each rev'))],
1189 ('n', 'new-file', None, _('add new file at each rev'))],
1190 _('[OPTION]... [TEXT]'))
1190 _('[OPTION]... [TEXT]'))
1191 def debugbuilddag(ui, repo, text=None,
1191 def debugbuilddag(ui, repo, text=None,
1192 mergeable_file=False,
1192 mergeable_file=False,
1193 overwritten_file=False,
1193 overwritten_file=False,
1194 new_file=False):
1194 new_file=False):
1195 """builds a repo with a given DAG from scratch in the current empty repo
1195 """builds a repo with a given DAG from scratch in the current empty repo
1196
1196
1197 The description of the DAG is read from stdin if not given on the
1197 The description of the DAG is read from stdin if not given on the
1198 command line.
1198 command line.
1199
1199
1200 Elements:
1200 Elements:
1201
1201
1202 - "+n" is a linear run of n nodes based on the current default parent
1202 - "+n" is a linear run of n nodes based on the current default parent
1203 - "." is a single node based on the current default parent
1203 - "." is a single node based on the current default parent
1204 - "$" resets the default parent to null (implied at the start);
1204 - "$" resets the default parent to null (implied at the start);
1205 otherwise the default parent is always the last node created
1205 otherwise the default parent is always the last node created
1206 - "<p" sets the default parent to the backref p
1206 - "<p" sets the default parent to the backref p
1207 - "*p" is a fork at parent p, which is a backref
1207 - "*p" is a fork at parent p, which is a backref
1208 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1208 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1209 - "/p2" is a merge of the preceding node and p2
1209 - "/p2" is a merge of the preceding node and p2
1210 - ":tag" defines a local tag for the preceding node
1210 - ":tag" defines a local tag for the preceding node
1211 - "@branch" sets the named branch for subsequent nodes
1211 - "@branch" sets the named branch for subsequent nodes
1212 - "#...\\n" is a comment up to the end of the line
1212 - "#...\\n" is a comment up to the end of the line
1213
1213
1214 Whitespace between the above elements is ignored.
1214 Whitespace between the above elements is ignored.
1215
1215
1216 A backref is either
1216 A backref is either
1217
1217
1218 - a number n, which references the node curr-n, where curr is the current
1218 - a number n, which references the node curr-n, where curr is the current
1219 node, or
1219 node, or
1220 - the name of a local tag you placed earlier using ":tag", or
1220 - the name of a local tag you placed earlier using ":tag", or
1221 - empty to denote the default parent.
1221 - empty to denote the default parent.
1222
1222
1223 All string valued-elements are either strictly alphanumeric, or must
1223 All string valued-elements are either strictly alphanumeric, or must
1224 be enclosed in double quotes ("..."), with "\\" as escape character.
1224 be enclosed in double quotes ("..."), with "\\" as escape character.
1225 """
1225 """
1226
1226
1227 if text is None:
1227 if text is None:
1228 ui.status(_("reading DAG from stdin\n"))
1228 ui.status(_("reading DAG from stdin\n"))
1229 text = sys.stdin.read()
1229 text = sys.stdin.read()
1230
1230
1231 cl = repo.changelog
1231 cl = repo.changelog
1232 if len(cl) > 0:
1232 if len(cl) > 0:
1233 raise util.Abort(_('repository is not empty'))
1233 raise util.Abort(_('repository is not empty'))
1234
1234
1235 # determine number of revs in DAG
1235 # determine number of revs in DAG
1236 total = 0
1236 total = 0
1237 for type, data in dagparser.parsedag(text):
1237 for type, data in dagparser.parsedag(text):
1238 if type == 'n':
1238 if type == 'n':
1239 total += 1
1239 total += 1
1240
1240
1241 if mergeable_file:
1241 if mergeable_file:
1242 linesperrev = 2
1242 linesperrev = 2
1243 # make a file with k lines per rev
1243 # make a file with k lines per rev
1244 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1244 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1245 initialmergedlines.append("")
1245 initialmergedlines.append("")
1246
1246
1247 tags = []
1247 tags = []
1248
1248
1249 tr = repo.transaction("builddag")
1249 tr = repo.transaction("builddag")
1250 try:
1250 try:
1251
1251
1252 at = -1
1252 at = -1
1253 atbranch = 'default'
1253 atbranch = 'default'
1254 nodeids = []
1254 nodeids = []
1255 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1255 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1256 for type, data in dagparser.parsedag(text):
1256 for type, data in dagparser.parsedag(text):
1257 if type == 'n':
1257 if type == 'n':
1258 ui.note('node %s\n' % str(data))
1258 ui.note('node %s\n' % str(data))
1259 id, ps = data
1259 id, ps = data
1260
1260
1261 files = []
1261 files = []
1262 fctxs = {}
1262 fctxs = {}
1263
1263
1264 p2 = None
1264 p2 = None
1265 if mergeable_file:
1265 if mergeable_file:
1266 fn = "mf"
1266 fn = "mf"
1267 p1 = repo[ps[0]]
1267 p1 = repo[ps[0]]
1268 if len(ps) > 1:
1268 if len(ps) > 1:
1269 p2 = repo[ps[1]]
1269 p2 = repo[ps[1]]
1270 pa = p1.ancestor(p2)
1270 pa = p1.ancestor(p2)
1271 base, local, other = [x[fn].data() for x in pa, p1, p2]
1271 base, local, other = [x[fn].data() for x in pa, p1, p2]
1272 m3 = simplemerge.Merge3Text(base, local, other)
1272 m3 = simplemerge.Merge3Text(base, local, other)
1273 ml = [l.strip() for l in m3.merge_lines()]
1273 ml = [l.strip() for l in m3.merge_lines()]
1274 ml.append("")
1274 ml.append("")
1275 elif at > 0:
1275 elif at > 0:
1276 ml = p1[fn].data().split("\n")
1276 ml = p1[fn].data().split("\n")
1277 else:
1277 else:
1278 ml = initialmergedlines
1278 ml = initialmergedlines
1279 ml[id * linesperrev] += " r%i" % id
1279 ml[id * linesperrev] += " r%i" % id
1280 mergedtext = "\n".join(ml)
1280 mergedtext = "\n".join(ml)
1281 files.append(fn)
1281 files.append(fn)
1282 fctxs[fn] = context.memfilectx(fn, mergedtext)
1282 fctxs[fn] = context.memfilectx(fn, mergedtext)
1283
1283
1284 if overwritten_file:
1284 if overwritten_file:
1285 fn = "of"
1285 fn = "of"
1286 files.append(fn)
1286 files.append(fn)
1287 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1287 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1288
1288
1289 if new_file:
1289 if new_file:
1290 fn = "nf%i" % id
1290 fn = "nf%i" % id
1291 files.append(fn)
1291 files.append(fn)
1292 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1292 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1293 if len(ps) > 1:
1293 if len(ps) > 1:
1294 if not p2:
1294 if not p2:
1295 p2 = repo[ps[1]]
1295 p2 = repo[ps[1]]
1296 for fn in p2:
1296 for fn in p2:
1297 if fn.startswith("nf"):
1297 if fn.startswith("nf"):
1298 files.append(fn)
1298 files.append(fn)
1299 fctxs[fn] = p2[fn]
1299 fctxs[fn] = p2[fn]
1300
1300
1301 def fctxfn(repo, cx, path):
1301 def fctxfn(repo, cx, path):
1302 return fctxs.get(path)
1302 return fctxs.get(path)
1303
1303
1304 if len(ps) == 0 or ps[0] < 0:
1304 if len(ps) == 0 or ps[0] < 0:
1305 pars = [None, None]
1305 pars = [None, None]
1306 elif len(ps) == 1:
1306 elif len(ps) == 1:
1307 pars = [nodeids[ps[0]], None]
1307 pars = [nodeids[ps[0]], None]
1308 else:
1308 else:
1309 pars = [nodeids[p] for p in ps]
1309 pars = [nodeids[p] for p in ps]
1310 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1310 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1311 date=(id, 0),
1311 date=(id, 0),
1312 user="debugbuilddag",
1312 user="debugbuilddag",
1313 extra={'branch': atbranch})
1313 extra={'branch': atbranch})
1314 nodeid = repo.commitctx(cx)
1314 nodeid = repo.commitctx(cx)
1315 nodeids.append(nodeid)
1315 nodeids.append(nodeid)
1316 at = id
1316 at = id
1317 elif type == 'l':
1317 elif type == 'l':
1318 id, name = data
1318 id, name = data
1319 ui.note('tag %s\n' % name)
1319 ui.note('tag %s\n' % name)
1320 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1320 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1321 elif type == 'a':
1321 elif type == 'a':
1322 ui.note('branch %s\n' % data)
1322 ui.note('branch %s\n' % data)
1323 atbranch = data
1323 atbranch = data
1324 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1324 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1325 tr.close()
1325 tr.close()
1326 finally:
1326 finally:
1327 ui.progress(_('building'), None)
1327 ui.progress(_('building'), None)
1328 tr.release()
1328 tr.release()
1329
1329
1330 if tags:
1330 if tags:
1331 repo.opener.write("localtags", "".join(tags))
1331 repo.opener.write("localtags", "".join(tags))
1332
1332
1333 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1333 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1334 def debugbundle(ui, bundlepath, all=None, **opts):
1334 def debugbundle(ui, bundlepath, all=None, **opts):
1335 """lists the contents of a bundle"""
1335 """lists the contents of a bundle"""
1336 f = url.open(ui, bundlepath)
1336 f = url.open(ui, bundlepath)
1337 try:
1337 try:
1338 gen = changegroup.readbundle(f, bundlepath)
1338 gen = changegroup.readbundle(f, bundlepath)
1339 if all:
1339 if all:
1340 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1340 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1341
1341
1342 def showchunks(named):
1342 def showchunks(named):
1343 ui.write("\n%s\n" % named)
1343 ui.write("\n%s\n" % named)
1344 chain = None
1344 chain = None
1345 while 1:
1345 while 1:
1346 chunkdata = gen.deltachunk(chain)
1346 chunkdata = gen.deltachunk(chain)
1347 if not chunkdata:
1347 if not chunkdata:
1348 break
1348 break
1349 node = chunkdata['node']
1349 node = chunkdata['node']
1350 p1 = chunkdata['p1']
1350 p1 = chunkdata['p1']
1351 p2 = chunkdata['p2']
1351 p2 = chunkdata['p2']
1352 cs = chunkdata['cs']
1352 cs = chunkdata['cs']
1353 deltabase = chunkdata['deltabase']
1353 deltabase = chunkdata['deltabase']
1354 delta = chunkdata['delta']
1354 delta = chunkdata['delta']
1355 ui.write("%s %s %s %s %s %s\n" %
1355 ui.write("%s %s %s %s %s %s\n" %
1356 (hex(node), hex(p1), hex(p2),
1356 (hex(node), hex(p1), hex(p2),
1357 hex(cs), hex(deltabase), len(delta)))
1357 hex(cs), hex(deltabase), len(delta)))
1358 chain = node
1358 chain = node
1359
1359
1360 chunkdata = gen.changelogheader()
1360 chunkdata = gen.changelogheader()
1361 showchunks("changelog")
1361 showchunks("changelog")
1362 chunkdata = gen.manifestheader()
1362 chunkdata = gen.manifestheader()
1363 showchunks("manifest")
1363 showchunks("manifest")
1364 while 1:
1364 while 1:
1365 chunkdata = gen.filelogheader()
1365 chunkdata = gen.filelogheader()
1366 if not chunkdata:
1366 if not chunkdata:
1367 break
1367 break
1368 fname = chunkdata['filename']
1368 fname = chunkdata['filename']
1369 showchunks(fname)
1369 showchunks(fname)
1370 else:
1370 else:
1371 chunkdata = gen.changelogheader()
1371 chunkdata = gen.changelogheader()
1372 chain = None
1372 chain = None
1373 while 1:
1373 while 1:
1374 chunkdata = gen.deltachunk(chain)
1374 chunkdata = gen.deltachunk(chain)
1375 if not chunkdata:
1375 if not chunkdata:
1376 break
1376 break
1377 node = chunkdata['node']
1377 node = chunkdata['node']
1378 ui.write("%s\n" % hex(node))
1378 ui.write("%s\n" % hex(node))
1379 chain = node
1379 chain = node
1380 finally:
1380 finally:
1381 f.close()
1381 f.close()
1382
1382
1383 @command('debugcheckstate', [], '')
1383 @command('debugcheckstate', [], '')
1384 def debugcheckstate(ui, repo):
1384 def debugcheckstate(ui, repo):
1385 """validate the correctness of the current dirstate"""
1385 """validate the correctness of the current dirstate"""
1386 parent1, parent2 = repo.dirstate.parents()
1386 parent1, parent2 = repo.dirstate.parents()
1387 m1 = repo[parent1].manifest()
1387 m1 = repo[parent1].manifest()
1388 m2 = repo[parent2].manifest()
1388 m2 = repo[parent2].manifest()
1389 errors = 0
1389 errors = 0
1390 for f in repo.dirstate:
1390 for f in repo.dirstate:
1391 state = repo.dirstate[f]
1391 state = repo.dirstate[f]
1392 if state in "nr" and f not in m1:
1392 if state in "nr" and f not in m1:
1393 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1393 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1394 errors += 1
1394 errors += 1
1395 if state in "a" and f in m1:
1395 if state in "a" and f in m1:
1396 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1396 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1397 errors += 1
1397 errors += 1
1398 if state in "m" and f not in m1 and f not in m2:
1398 if state in "m" and f not in m1 and f not in m2:
1399 ui.warn(_("%s in state %s, but not in either manifest\n") %
1399 ui.warn(_("%s in state %s, but not in either manifest\n") %
1400 (f, state))
1400 (f, state))
1401 errors += 1
1401 errors += 1
1402 for f in m1:
1402 for f in m1:
1403 state = repo.dirstate[f]
1403 state = repo.dirstate[f]
1404 if state not in "nrm":
1404 if state not in "nrm":
1405 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1405 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1406 errors += 1
1406 errors += 1
1407 if errors:
1407 if errors:
1408 error = _(".hg/dirstate inconsistent with current parent's manifest")
1408 error = _(".hg/dirstate inconsistent with current parent's manifest")
1409 raise util.Abort(error)
1409 raise util.Abort(error)
1410
1410
1411 @command('debugcommands', [], _('[COMMAND]'))
1411 @command('debugcommands', [], _('[COMMAND]'))
1412 def debugcommands(ui, cmd='', *args):
1412 def debugcommands(ui, cmd='', *args):
1413 """list all available commands and options"""
1413 """list all available commands and options"""
1414 for cmd, vals in sorted(table.iteritems()):
1414 for cmd, vals in sorted(table.iteritems()):
1415 cmd = cmd.split('|')[0].strip('^')
1415 cmd = cmd.split('|')[0].strip('^')
1416 opts = ', '.join([i[1] for i in vals[1]])
1416 opts = ', '.join([i[1] for i in vals[1]])
1417 ui.write('%s: %s\n' % (cmd, opts))
1417 ui.write('%s: %s\n' % (cmd, opts))
1418
1418
1419 @command('debugcomplete',
1419 @command('debugcomplete',
1420 [('o', 'options', None, _('show the command options'))],
1420 [('o', 'options', None, _('show the command options'))],
1421 _('[-o] CMD'))
1421 _('[-o] CMD'))
1422 def debugcomplete(ui, cmd='', **opts):
1422 def debugcomplete(ui, cmd='', **opts):
1423 """returns the completion list associated with the given command"""
1423 """returns the completion list associated with the given command"""
1424
1424
1425 if opts.get('options'):
1425 if opts.get('options'):
1426 options = []
1426 options = []
1427 otables = [globalopts]
1427 otables = [globalopts]
1428 if cmd:
1428 if cmd:
1429 aliases, entry = cmdutil.findcmd(cmd, table, False)
1429 aliases, entry = cmdutil.findcmd(cmd, table, False)
1430 otables.append(entry[1])
1430 otables.append(entry[1])
1431 for t in otables:
1431 for t in otables:
1432 for o in t:
1432 for o in t:
1433 if "(DEPRECATED)" in o[3]:
1433 if "(DEPRECATED)" in o[3]:
1434 continue
1434 continue
1435 if o[0]:
1435 if o[0]:
1436 options.append('-%s' % o[0])
1436 options.append('-%s' % o[0])
1437 options.append('--%s' % o[1])
1437 options.append('--%s' % o[1])
1438 ui.write("%s\n" % "\n".join(options))
1438 ui.write("%s\n" % "\n".join(options))
1439 return
1439 return
1440
1440
1441 cmdlist = cmdutil.findpossible(cmd, table)
1441 cmdlist = cmdutil.findpossible(cmd, table)
1442 if ui.verbose:
1442 if ui.verbose:
1443 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1443 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1444 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1444 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1445
1445
1446 @command('debugdag',
1446 @command('debugdag',
1447 [('t', 'tags', None, _('use tags as labels')),
1447 [('t', 'tags', None, _('use tags as labels')),
1448 ('b', 'branches', None, _('annotate with branch names')),
1448 ('b', 'branches', None, _('annotate with branch names')),
1449 ('', 'dots', None, _('use dots for runs')),
1449 ('', 'dots', None, _('use dots for runs')),
1450 ('s', 'spaces', None, _('separate elements by spaces'))],
1450 ('s', 'spaces', None, _('separate elements by spaces'))],
1451 _('[OPTION]... [FILE [REV]...]'))
1451 _('[OPTION]... [FILE [REV]...]'))
1452 def debugdag(ui, repo, file_=None, *revs, **opts):
1452 def debugdag(ui, repo, file_=None, *revs, **opts):
1453 """format the changelog or an index DAG as a concise textual description
1453 """format the changelog or an index DAG as a concise textual description
1454
1454
1455 If you pass a revlog index, the revlog's DAG is emitted. If you list
1455 If you pass a revlog index, the revlog's DAG is emitted. If you list
1456 revision numbers, they get labelled in the output as rN.
1456 revision numbers, they get labelled in the output as rN.
1457
1457
1458 Otherwise, the changelog DAG of the current repo is emitted.
1458 Otherwise, the changelog DAG of the current repo is emitted.
1459 """
1459 """
1460 spaces = opts.get('spaces')
1460 spaces = opts.get('spaces')
1461 dots = opts.get('dots')
1461 dots = opts.get('dots')
1462 if file_:
1462 if file_:
1463 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1463 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1464 revs = set((int(r) for r in revs))
1464 revs = set((int(r) for r in revs))
1465 def events():
1465 def events():
1466 for r in rlog:
1466 for r in rlog:
1467 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1467 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1468 if r in revs:
1468 if r in revs:
1469 yield 'l', (r, "r%i" % r)
1469 yield 'l', (r, "r%i" % r)
1470 elif repo:
1470 elif repo:
1471 cl = repo.changelog
1471 cl = repo.changelog
1472 tags = opts.get('tags')
1472 tags = opts.get('tags')
1473 branches = opts.get('branches')
1473 branches = opts.get('branches')
1474 if tags:
1474 if tags:
1475 labels = {}
1475 labels = {}
1476 for l, n in repo.tags().items():
1476 for l, n in repo.tags().items():
1477 labels.setdefault(cl.rev(n), []).append(l)
1477 labels.setdefault(cl.rev(n), []).append(l)
1478 def events():
1478 def events():
1479 b = "default"
1479 b = "default"
1480 for r in cl:
1480 for r in cl:
1481 if branches:
1481 if branches:
1482 newb = cl.read(cl.node(r))[5]['branch']
1482 newb = cl.read(cl.node(r))[5]['branch']
1483 if newb != b:
1483 if newb != b:
1484 yield 'a', newb
1484 yield 'a', newb
1485 b = newb
1485 b = newb
1486 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1486 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1487 if tags:
1487 if tags:
1488 ls = labels.get(r)
1488 ls = labels.get(r)
1489 if ls:
1489 if ls:
1490 for l in ls:
1490 for l in ls:
1491 yield 'l', (r, l)
1491 yield 'l', (r, l)
1492 else:
1492 else:
1493 raise util.Abort(_('need repo for changelog dag'))
1493 raise util.Abort(_('need repo for changelog dag'))
1494
1494
1495 for line in dagparser.dagtextlines(events(),
1495 for line in dagparser.dagtextlines(events(),
1496 addspaces=spaces,
1496 addspaces=spaces,
1497 wraplabels=True,
1497 wraplabels=True,
1498 wrapannotations=True,
1498 wrapannotations=True,
1499 wrapnonlinear=dots,
1499 wrapnonlinear=dots,
1500 usedots=dots,
1500 usedots=dots,
1501 maxlinewidth=70):
1501 maxlinewidth=70):
1502 ui.write(line)
1502 ui.write(line)
1503 ui.write("\n")
1503 ui.write("\n")
1504
1504
1505 @command('debugdata',
1505 @command('debugdata',
1506 [('c', 'changelog', False, _('open changelog')),
1506 [('c', 'changelog', False, _('open changelog')),
1507 ('m', 'manifest', False, _('open manifest'))],
1507 ('m', 'manifest', False, _('open manifest'))],
1508 _('-c|-m|FILE REV'))
1508 _('-c|-m|FILE REV'))
1509 def debugdata(ui, repo, file_, rev = None, **opts):
1509 def debugdata(ui, repo, file_, rev = None, **opts):
1510 """dump the contents of a data file revision"""
1510 """dump the contents of a data file revision"""
1511 if opts.get('changelog') or opts.get('manifest'):
1511 if opts.get('changelog') or opts.get('manifest'):
1512 file_, rev = None, file_
1512 file_, rev = None, file_
1513 elif rev is None:
1513 elif rev is None:
1514 raise error.CommandError('debugdata', _('invalid arguments'))
1514 raise error.CommandError('debugdata', _('invalid arguments'))
1515 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1515 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1516 try:
1516 try:
1517 ui.write(r.revision(r.lookup(rev)))
1517 ui.write(r.revision(r.lookup(rev)))
1518 except KeyError:
1518 except KeyError:
1519 raise util.Abort(_('invalid revision identifier %s') % rev)
1519 raise util.Abort(_('invalid revision identifier %s') % rev)
1520
1520
1521 @command('debugdate',
1521 @command('debugdate',
1522 [('e', 'extended', None, _('try extended date formats'))],
1522 [('e', 'extended', None, _('try extended date formats'))],
1523 _('[-e] DATE [RANGE]'))
1523 _('[-e] DATE [RANGE]'))
1524 def debugdate(ui, date, range=None, **opts):
1524 def debugdate(ui, date, range=None, **opts):
1525 """parse and display a date"""
1525 """parse and display a date"""
1526 if opts["extended"]:
1526 if opts["extended"]:
1527 d = util.parsedate(date, util.extendeddateformats)
1527 d = util.parsedate(date, util.extendeddateformats)
1528 else:
1528 else:
1529 d = util.parsedate(date)
1529 d = util.parsedate(date)
1530 ui.write("internal: %s %s\n" % d)
1530 ui.write("internal: %s %s\n" % d)
1531 ui.write("standard: %s\n" % util.datestr(d))
1531 ui.write("standard: %s\n" % util.datestr(d))
1532 if range:
1532 if range:
1533 m = util.matchdate(range)
1533 m = util.matchdate(range)
1534 ui.write("match: %s\n" % m(d[0]))
1534 ui.write("match: %s\n" % m(d[0]))
1535
1535
1536 @command('debugdiscovery',
1536 @command('debugdiscovery',
1537 [('', 'old', None, _('use old-style discovery')),
1537 [('', 'old', None, _('use old-style discovery')),
1538 ('', 'nonheads', None,
1538 ('', 'nonheads', None,
1539 _('use old-style discovery with non-heads included')),
1539 _('use old-style discovery with non-heads included')),
1540 ] + remoteopts,
1540 ] + remoteopts,
1541 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1541 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1542 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1542 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1543 """runs the changeset discovery protocol in isolation"""
1543 """runs the changeset discovery protocol in isolation"""
1544 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1544 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1545 remote = hg.repository(hg.remoteui(repo, opts), remoteurl)
1545 remote = hg.repository(hg.remoteui(repo, opts), remoteurl)
1546 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1546 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1547
1547
1548 # make sure tests are repeatable
1548 # make sure tests are repeatable
1549 random.seed(12323)
1549 random.seed(12323)
1550
1550
1551 def doit(localheads, remoteheads):
1551 def doit(localheads, remoteheads):
1552 if opts.get('old'):
1552 if opts.get('old'):
1553 if localheads:
1553 if localheads:
1554 raise util.Abort('cannot use localheads with old style discovery')
1554 raise util.Abort('cannot use localheads with old style discovery')
1555 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1555 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1556 force=True)
1556 force=True)
1557 common = set(common)
1557 common = set(common)
1558 if not opts.get('nonheads'):
1558 if not opts.get('nonheads'):
1559 ui.write("unpruned common: %s\n" % " ".join([short(n)
1559 ui.write("unpruned common: %s\n" % " ".join([short(n)
1560 for n in common]))
1560 for n in common]))
1561 dag = dagutil.revlogdag(repo.changelog)
1561 dag = dagutil.revlogdag(repo.changelog)
1562 all = dag.ancestorset(dag.internalizeall(common))
1562 all = dag.ancestorset(dag.internalizeall(common))
1563 common = dag.externalizeall(dag.headsetofconnecteds(all))
1563 common = dag.externalizeall(dag.headsetofconnecteds(all))
1564 else:
1564 else:
1565 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1565 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1566 common = set(common)
1566 common = set(common)
1567 rheads = set(hds)
1567 rheads = set(hds)
1568 lheads = set(repo.heads())
1568 lheads = set(repo.heads())
1569 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1569 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1570 if lheads <= common:
1570 if lheads <= common:
1571 ui.write("local is subset\n")
1571 ui.write("local is subset\n")
1572 elif rheads <= common:
1572 elif rheads <= common:
1573 ui.write("remote is subset\n")
1573 ui.write("remote is subset\n")
1574
1574
1575 serverlogs = opts.get('serverlog')
1575 serverlogs = opts.get('serverlog')
1576 if serverlogs:
1576 if serverlogs:
1577 for filename in serverlogs:
1577 for filename in serverlogs:
1578 logfile = open(filename, 'r')
1578 logfile = open(filename, 'r')
1579 try:
1579 try:
1580 line = logfile.readline()
1580 line = logfile.readline()
1581 while line:
1581 while line:
1582 parts = line.strip().split(';')
1582 parts = line.strip().split(';')
1583 op = parts[1]
1583 op = parts[1]
1584 if op == 'cg':
1584 if op == 'cg':
1585 pass
1585 pass
1586 elif op == 'cgss':
1586 elif op == 'cgss':
1587 doit(parts[2].split(' '), parts[3].split(' '))
1587 doit(parts[2].split(' '), parts[3].split(' '))
1588 elif op == 'unb':
1588 elif op == 'unb':
1589 doit(parts[3].split(' '), parts[2].split(' '))
1589 doit(parts[3].split(' '), parts[2].split(' '))
1590 line = logfile.readline()
1590 line = logfile.readline()
1591 finally:
1591 finally:
1592 logfile.close()
1592 logfile.close()
1593
1593
1594 else:
1594 else:
1595 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1595 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1596 opts.get('remote_head'))
1596 opts.get('remote_head'))
1597 localrevs = opts.get('local_head')
1597 localrevs = opts.get('local_head')
1598 doit(localrevs, remoterevs)
1598 doit(localrevs, remoterevs)
1599
1599
1600 @command('debugfsinfo', [], _('[PATH]'))
1600 @command('debugfsinfo', [], _('[PATH]'))
1601 def debugfsinfo(ui, path = "."):
1601 def debugfsinfo(ui, path = "."):
1602 """show information detected about current filesystem"""
1602 """show information detected about current filesystem"""
1603 util.writefile('.debugfsinfo', '')
1603 util.writefile('.debugfsinfo', '')
1604 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1604 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1605 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1605 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1606 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1606 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1607 and 'yes' or 'no'))
1607 and 'yes' or 'no'))
1608 os.unlink('.debugfsinfo')
1608 os.unlink('.debugfsinfo')
1609
1609
1610 @command('debuggetbundle',
1610 @command('debuggetbundle',
1611 [('H', 'head', [], _('id of head node'), _('ID')),
1611 [('H', 'head', [], _('id of head node'), _('ID')),
1612 ('C', 'common', [], _('id of common node'), _('ID')),
1612 ('C', 'common', [], _('id of common node'), _('ID')),
1613 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1613 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1614 _('REPO FILE [-H|-C ID]...'))
1614 _('REPO FILE [-H|-C ID]...'))
1615 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1615 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1616 """retrieves a bundle from a repo
1616 """retrieves a bundle from a repo
1617
1617
1618 Every ID must be a full-length hex node id string. Saves the bundle to the
1618 Every ID must be a full-length hex node id string. Saves the bundle to the
1619 given file.
1619 given file.
1620 """
1620 """
1621 repo = hg.repository(ui, repopath)
1621 repo = hg.repository(ui, repopath)
1622 if not repo.capable('getbundle'):
1622 if not repo.capable('getbundle'):
1623 raise util.Abort("getbundle() not supported by target repository")
1623 raise util.Abort("getbundle() not supported by target repository")
1624 args = {}
1624 args = {}
1625 if common:
1625 if common:
1626 args['common'] = [bin(s) for s in common]
1626 args['common'] = [bin(s) for s in common]
1627 if head:
1627 if head:
1628 args['heads'] = [bin(s) for s in head]
1628 args['heads'] = [bin(s) for s in head]
1629 bundle = repo.getbundle('debug', **args)
1629 bundle = repo.getbundle('debug', **args)
1630
1630
1631 bundletype = opts.get('type', 'bzip2').lower()
1631 bundletype = opts.get('type', 'bzip2').lower()
1632 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1632 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1633 bundletype = btypes.get(bundletype)
1633 bundletype = btypes.get(bundletype)
1634 if bundletype not in changegroup.bundletypes:
1634 if bundletype not in changegroup.bundletypes:
1635 raise util.Abort(_('unknown bundle type specified with --type'))
1635 raise util.Abort(_('unknown bundle type specified with --type'))
1636 changegroup.writebundle(bundle, bundlepath, bundletype)
1636 changegroup.writebundle(bundle, bundlepath, bundletype)
1637
1637
1638 @command('debugignore', [], '')
1638 @command('debugignore', [], '')
1639 def debugignore(ui, repo, *values, **opts):
1639 def debugignore(ui, repo, *values, **opts):
1640 """display the combined ignore pattern"""
1640 """display the combined ignore pattern"""
1641 ignore = repo.dirstate._ignore
1641 ignore = repo.dirstate._ignore
1642 if hasattr(ignore, 'includepat'):
1642 if hasattr(ignore, 'includepat'):
1643 ui.write("%s\n" % ignore.includepat)
1643 ui.write("%s\n" % ignore.includepat)
1644 else:
1644 else:
1645 raise util.Abort(_("no ignore patterns found"))
1645 raise util.Abort(_("no ignore patterns found"))
1646
1646
1647 @command('debugindex',
1647 @command('debugindex',
1648 [('c', 'changelog', False, _('open changelog')),
1648 [('c', 'changelog', False, _('open changelog')),
1649 ('m', 'manifest', False, _('open manifest')),
1649 ('m', 'manifest', False, _('open manifest')),
1650 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1650 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1651 _('[-f FORMAT] -c|-m|FILE'))
1651 _('[-f FORMAT] -c|-m|FILE'))
1652 def debugindex(ui, repo, file_ = None, **opts):
1652 def debugindex(ui, repo, file_ = None, **opts):
1653 """dump the contents of an index file"""
1653 """dump the contents of an index file"""
1654 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1654 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1655 format = opts.get('format', 0)
1655 format = opts.get('format', 0)
1656 if format not in (0, 1):
1656 if format not in (0, 1):
1657 raise util.Abort(_("unknown format %d") % format)
1657 raise util.Abort(_("unknown format %d") % format)
1658
1658
1659 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1659 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1660 if generaldelta:
1660 if generaldelta:
1661 basehdr = ' delta'
1661 basehdr = ' delta'
1662 else:
1662 else:
1663 basehdr = ' base'
1663 basehdr = ' base'
1664
1664
1665 if format == 0:
1665 if format == 0:
1666 ui.write(" rev offset length " + basehdr + " linkrev"
1666 ui.write(" rev offset length " + basehdr + " linkrev"
1667 " nodeid p1 p2\n")
1667 " nodeid p1 p2\n")
1668 elif format == 1:
1668 elif format == 1:
1669 ui.write(" rev flag offset length"
1669 ui.write(" rev flag offset length"
1670 " size " + basehdr + " link p1 p2 nodeid\n")
1670 " size " + basehdr + " link p1 p2 nodeid\n")
1671
1671
1672 for i in r:
1672 for i in r:
1673 node = r.node(i)
1673 node = r.node(i)
1674 if generaldelta:
1674 if generaldelta:
1675 base = r.deltaparent(i)
1675 base = r.deltaparent(i)
1676 else:
1676 else:
1677 base = r.chainbase(i)
1677 base = r.chainbase(i)
1678 if format == 0:
1678 if format == 0:
1679 try:
1679 try:
1680 pp = r.parents(node)
1680 pp = r.parents(node)
1681 except:
1681 except:
1682 pp = [nullid, nullid]
1682 pp = [nullid, nullid]
1683 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1683 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1684 i, r.start(i), r.length(i), base, r.linkrev(i),
1684 i, r.start(i), r.length(i), base, r.linkrev(i),
1685 short(node), short(pp[0]), short(pp[1])))
1685 short(node), short(pp[0]), short(pp[1])))
1686 elif format == 1:
1686 elif format == 1:
1687 pr = r.parentrevs(i)
1687 pr = r.parentrevs(i)
1688 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1688 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1689 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1689 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1690 base, r.linkrev(i), pr[0], pr[1], short(node)))
1690 base, r.linkrev(i), pr[0], pr[1], short(node)))
1691
1691
1692 @command('debugindexdot', [], _('FILE'))
1692 @command('debugindexdot', [], _('FILE'))
1693 def debugindexdot(ui, repo, file_):
1693 def debugindexdot(ui, repo, file_):
1694 """dump an index DAG as a graphviz dot file"""
1694 """dump an index DAG as a graphviz dot file"""
1695 r = None
1695 r = None
1696 if repo:
1696 if repo:
1697 filelog = repo.file(file_)
1697 filelog = repo.file(file_)
1698 if len(filelog):
1698 if len(filelog):
1699 r = filelog
1699 r = filelog
1700 if not r:
1700 if not r:
1701 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1701 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1702 ui.write("digraph G {\n")
1702 ui.write("digraph G {\n")
1703 for i in r:
1703 for i in r:
1704 node = r.node(i)
1704 node = r.node(i)
1705 pp = r.parents(node)
1705 pp = r.parents(node)
1706 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1706 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1707 if pp[1] != nullid:
1707 if pp[1] != nullid:
1708 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1708 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1709 ui.write("}\n")
1709 ui.write("}\n")
1710
1710
1711 @command('debuginstall', [], '')
1711 @command('debuginstall', [], '')
1712 def debuginstall(ui):
1712 def debuginstall(ui):
1713 '''test Mercurial installation
1713 '''test Mercurial installation
1714
1714
1715 Returns 0 on success.
1715 Returns 0 on success.
1716 '''
1716 '''
1717
1717
1718 def writetemp(contents):
1718 def writetemp(contents):
1719 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1719 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1720 f = os.fdopen(fd, "wb")
1720 f = os.fdopen(fd, "wb")
1721 f.write(contents)
1721 f.write(contents)
1722 f.close()
1722 f.close()
1723 return name
1723 return name
1724
1724
1725 problems = 0
1725 problems = 0
1726
1726
1727 # encoding
1727 # encoding
1728 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1728 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1729 try:
1729 try:
1730 encoding.fromlocal("test")
1730 encoding.fromlocal("test")
1731 except util.Abort, inst:
1731 except util.Abort, inst:
1732 ui.write(" %s\n" % inst)
1732 ui.write(" %s\n" % inst)
1733 ui.write(_(" (check that your locale is properly set)\n"))
1733 ui.write(_(" (check that your locale is properly set)\n"))
1734 problems += 1
1734 problems += 1
1735
1735
1736 # compiled modules
1736 # compiled modules
1737 ui.status(_("Checking installed modules (%s)...\n")
1737 ui.status(_("Checking installed modules (%s)...\n")
1738 % os.path.dirname(__file__))
1738 % os.path.dirname(__file__))
1739 try:
1739 try:
1740 import bdiff, mpatch, base85, osutil
1740 import bdiff, mpatch, base85, osutil
1741 except Exception, inst:
1741 except Exception, inst:
1742 ui.write(" %s\n" % inst)
1742 ui.write(" %s\n" % inst)
1743 ui.write(_(" One or more extensions could not be found"))
1743 ui.write(_(" One or more extensions could not be found"))
1744 ui.write(_(" (check that you compiled the extensions)\n"))
1744 ui.write(_(" (check that you compiled the extensions)\n"))
1745 problems += 1
1745 problems += 1
1746
1746
1747 # templates
1747 # templates
1748 ui.status(_("Checking templates...\n"))
1748 ui.status(_("Checking templates...\n"))
1749 try:
1749 try:
1750 import templater
1750 import templater
1751 templater.templater(templater.templatepath("map-cmdline.default"))
1751 templater.templater(templater.templatepath("map-cmdline.default"))
1752 except Exception, inst:
1752 except Exception, inst:
1753 ui.write(" %s\n" % inst)
1753 ui.write(" %s\n" % inst)
1754 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1754 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1755 problems += 1
1755 problems += 1
1756
1756
1757 # editor
1757 # editor
1758 ui.status(_("Checking commit editor...\n"))
1758 ui.status(_("Checking commit editor...\n"))
1759 editor = ui.geteditor()
1759 editor = ui.geteditor()
1760 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1760 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1761 if not cmdpath:
1761 if not cmdpath:
1762 if editor == 'vi':
1762 if editor == 'vi':
1763 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1763 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1764 ui.write(_(" (specify a commit editor in your configuration"
1764 ui.write(_(" (specify a commit editor in your configuration"
1765 " file)\n"))
1765 " file)\n"))
1766 else:
1766 else:
1767 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1767 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1768 ui.write(_(" (specify a commit editor in your configuration"
1768 ui.write(_(" (specify a commit editor in your configuration"
1769 " file)\n"))
1769 " file)\n"))
1770 problems += 1
1770 problems += 1
1771
1771
1772 # check username
1772 # check username
1773 ui.status(_("Checking username...\n"))
1773 ui.status(_("Checking username...\n"))
1774 try:
1774 try:
1775 ui.username()
1775 ui.username()
1776 except util.Abort, e:
1776 except util.Abort, e:
1777 ui.write(" %s\n" % e)
1777 ui.write(" %s\n" % e)
1778 ui.write(_(" (specify a username in your configuration file)\n"))
1778 ui.write(_(" (specify a username in your configuration file)\n"))
1779 problems += 1
1779 problems += 1
1780
1780
1781 if not problems:
1781 if not problems:
1782 ui.status(_("No problems detected\n"))
1782 ui.status(_("No problems detected\n"))
1783 else:
1783 else:
1784 ui.write(_("%s problems detected,"
1784 ui.write(_("%s problems detected,"
1785 " please check your install!\n") % problems)
1785 " please check your install!\n") % problems)
1786
1786
1787 return problems
1787 return problems
1788
1788
1789 @command('debugknown', [], _('REPO ID...'))
1789 @command('debugknown', [], _('REPO ID...'))
1790 def debugknown(ui, repopath, *ids, **opts):
1790 def debugknown(ui, repopath, *ids, **opts):
1791 """test whether node ids are known to a repo
1791 """test whether node ids are known to a repo
1792
1792
1793 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1793 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1794 indicating unknown/known.
1794 indicating unknown/known.
1795 """
1795 """
1796 repo = hg.repository(ui, repopath)
1796 repo = hg.repository(ui, repopath)
1797 if not repo.capable('known'):
1797 if not repo.capable('known'):
1798 raise util.Abort("known() not supported by target repository")
1798 raise util.Abort("known() not supported by target repository")
1799 flags = repo.known([bin(s) for s in ids])
1799 flags = repo.known([bin(s) for s in ids])
1800 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1800 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1801
1801
1802 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1802 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1803 def debugpushkey(ui, repopath, namespace, *keyinfo):
1803 def debugpushkey(ui, repopath, namespace, *keyinfo):
1804 '''access the pushkey key/value protocol
1804 '''access the pushkey key/value protocol
1805
1805
1806 With two args, list the keys in the given namespace.
1806 With two args, list the keys in the given namespace.
1807
1807
1808 With five args, set a key to new if it currently is set to old.
1808 With five args, set a key to new if it currently is set to old.
1809 Reports success or failure.
1809 Reports success or failure.
1810 '''
1810 '''
1811
1811
1812 target = hg.repository(ui, repopath)
1812 target = hg.repository(ui, repopath)
1813 if keyinfo:
1813 if keyinfo:
1814 key, old, new = keyinfo
1814 key, old, new = keyinfo
1815 r = target.pushkey(namespace, key, old, new)
1815 r = target.pushkey(namespace, key, old, new)
1816 ui.status(str(r) + '\n')
1816 ui.status(str(r) + '\n')
1817 return not r
1817 return not r
1818 else:
1818 else:
1819 for k, v in target.listkeys(namespace).iteritems():
1819 for k, v in target.listkeys(namespace).iteritems():
1820 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1820 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1821 v.encode('string-escape')))
1821 v.encode('string-escape')))
1822
1822
1823 @command('debugrebuildstate',
1823 @command('debugrebuildstate',
1824 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1824 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1825 _('[-r REV] [REV]'))
1825 _('[-r REV] [REV]'))
1826 def debugrebuildstate(ui, repo, rev="tip"):
1826 def debugrebuildstate(ui, repo, rev="tip"):
1827 """rebuild the dirstate as it would look like for the given revision"""
1827 """rebuild the dirstate as it would look like for the given revision"""
1828 ctx = scmutil.revsingle(repo, rev)
1828 ctx = scmutil.revsingle(repo, rev)
1829 wlock = repo.wlock()
1829 wlock = repo.wlock()
1830 try:
1830 try:
1831 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1831 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1832 finally:
1832 finally:
1833 wlock.release()
1833 wlock.release()
1834
1834
1835 @command('debugrename',
1835 @command('debugrename',
1836 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1836 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1837 _('[-r REV] FILE'))
1837 _('[-r REV] FILE'))
1838 def debugrename(ui, repo, file1, *pats, **opts):
1838 def debugrename(ui, repo, file1, *pats, **opts):
1839 """dump rename information"""
1839 """dump rename information"""
1840
1840
1841 ctx = scmutil.revsingle(repo, opts.get('rev'))
1841 ctx = scmutil.revsingle(repo, opts.get('rev'))
1842 m = scmutil.match(repo, (file1,) + pats, opts)
1842 m = scmutil.match(repo, (file1,) + pats, opts)
1843 for abs in ctx.walk(m):
1843 for abs in ctx.walk(m):
1844 fctx = ctx[abs]
1844 fctx = ctx[abs]
1845 o = fctx.filelog().renamed(fctx.filenode())
1845 o = fctx.filelog().renamed(fctx.filenode())
1846 rel = m.rel(abs)
1846 rel = m.rel(abs)
1847 if o:
1847 if o:
1848 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1848 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1849 else:
1849 else:
1850 ui.write(_("%s not renamed\n") % rel)
1850 ui.write(_("%s not renamed\n") % rel)
1851
1851
1852 @command('debugrevlog',
1852 @command('debugrevlog',
1853 [('c', 'changelog', False, _('open changelog')),
1853 [('c', 'changelog', False, _('open changelog')),
1854 ('m', 'manifest', False, _('open manifest')),
1854 ('m', 'manifest', False, _('open manifest')),
1855 ('d', 'dump', False, _('dump index data'))],
1855 ('d', 'dump', False, _('dump index data'))],
1856 _('-c|-m|FILE'))
1856 _('-c|-m|FILE'))
1857 def debugrevlog(ui, repo, file_ = None, **opts):
1857 def debugrevlog(ui, repo, file_ = None, **opts):
1858 """show data and statistics about a revlog"""
1858 """show data and statistics about a revlog"""
1859 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1859 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1860
1860
1861 if opts.get("dump"):
1861 if opts.get("dump"):
1862 numrevs = len(r)
1862 numrevs = len(r)
1863 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1863 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1864 " rawsize totalsize compression heads\n")
1864 " rawsize totalsize compression heads\n")
1865 ts = 0
1865 ts = 0
1866 heads = set()
1866 heads = set()
1867 for rev in xrange(numrevs):
1867 for rev in xrange(numrevs):
1868 dbase = r.deltaparent(rev)
1868 dbase = r.deltaparent(rev)
1869 if dbase == -1:
1869 if dbase == -1:
1870 dbase = rev
1870 dbase = rev
1871 cbase = r.chainbase(rev)
1871 cbase = r.chainbase(rev)
1872 p1, p2 = r.parentrevs(rev)
1872 p1, p2 = r.parentrevs(rev)
1873 rs = r.rawsize(rev)
1873 rs = r.rawsize(rev)
1874 ts = ts + rs
1874 ts = ts + rs
1875 heads -= set(r.parentrevs(rev))
1875 heads -= set(r.parentrevs(rev))
1876 heads.add(rev)
1876 heads.add(rev)
1877 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1877 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1878 (rev, p1, p2, r.start(rev), r.end(rev),
1878 (rev, p1, p2, r.start(rev), r.end(rev),
1879 r.start(dbase), r.start(cbase),
1879 r.start(dbase), r.start(cbase),
1880 r.start(p1), r.start(p2),
1880 r.start(p1), r.start(p2),
1881 rs, ts, ts / r.end(rev), len(heads)))
1881 rs, ts, ts / r.end(rev), len(heads)))
1882 return 0
1882 return 0
1883
1883
1884 v = r.version
1884 v = r.version
1885 format = v & 0xFFFF
1885 format = v & 0xFFFF
1886 flags = []
1886 flags = []
1887 gdelta = False
1887 gdelta = False
1888 if v & revlog.REVLOGNGINLINEDATA:
1888 if v & revlog.REVLOGNGINLINEDATA:
1889 flags.append('inline')
1889 flags.append('inline')
1890 if v & revlog.REVLOGGENERALDELTA:
1890 if v & revlog.REVLOGGENERALDELTA:
1891 gdelta = True
1891 gdelta = True
1892 flags.append('generaldelta')
1892 flags.append('generaldelta')
1893 if not flags:
1893 if not flags:
1894 flags = ['(none)']
1894 flags = ['(none)']
1895
1895
1896 nummerges = 0
1896 nummerges = 0
1897 numfull = 0
1897 numfull = 0
1898 numprev = 0
1898 numprev = 0
1899 nump1 = 0
1899 nump1 = 0
1900 nump2 = 0
1900 nump2 = 0
1901 numother = 0
1901 numother = 0
1902 nump1prev = 0
1902 nump1prev = 0
1903 nump2prev = 0
1903 nump2prev = 0
1904 chainlengths = []
1904 chainlengths = []
1905
1905
1906 datasize = [None, 0, 0L]
1906 datasize = [None, 0, 0L]
1907 fullsize = [None, 0, 0L]
1907 fullsize = [None, 0, 0L]
1908 deltasize = [None, 0, 0L]
1908 deltasize = [None, 0, 0L]
1909
1909
1910 def addsize(size, l):
1910 def addsize(size, l):
1911 if l[0] is None or size < l[0]:
1911 if l[0] is None or size < l[0]:
1912 l[0] = size
1912 l[0] = size
1913 if size > l[1]:
1913 if size > l[1]:
1914 l[1] = size
1914 l[1] = size
1915 l[2] += size
1915 l[2] += size
1916
1916
1917 numrevs = len(r)
1917 numrevs = len(r)
1918 for rev in xrange(numrevs):
1918 for rev in xrange(numrevs):
1919 p1, p2 = r.parentrevs(rev)
1919 p1, p2 = r.parentrevs(rev)
1920 delta = r.deltaparent(rev)
1920 delta = r.deltaparent(rev)
1921 if format > 0:
1921 if format > 0:
1922 addsize(r.rawsize(rev), datasize)
1922 addsize(r.rawsize(rev), datasize)
1923 if p2 != nullrev:
1923 if p2 != nullrev:
1924 nummerges += 1
1924 nummerges += 1
1925 size = r.length(rev)
1925 size = r.length(rev)
1926 if delta == nullrev:
1926 if delta == nullrev:
1927 chainlengths.append(0)
1927 chainlengths.append(0)
1928 numfull += 1
1928 numfull += 1
1929 addsize(size, fullsize)
1929 addsize(size, fullsize)
1930 else:
1930 else:
1931 chainlengths.append(chainlengths[delta] + 1)
1931 chainlengths.append(chainlengths[delta] + 1)
1932 addsize(size, deltasize)
1932 addsize(size, deltasize)
1933 if delta == rev - 1:
1933 if delta == rev - 1:
1934 numprev += 1
1934 numprev += 1
1935 if delta == p1:
1935 if delta == p1:
1936 nump1prev += 1
1936 nump1prev += 1
1937 elif delta == p2:
1937 elif delta == p2:
1938 nump2prev += 1
1938 nump2prev += 1
1939 elif delta == p1:
1939 elif delta == p1:
1940 nump1 += 1
1940 nump1 += 1
1941 elif delta == p2:
1941 elif delta == p2:
1942 nump2 += 1
1942 nump2 += 1
1943 elif delta != nullrev:
1943 elif delta != nullrev:
1944 numother += 1
1944 numother += 1
1945
1945
1946 numdeltas = numrevs - numfull
1946 numdeltas = numrevs - numfull
1947 numoprev = numprev - nump1prev - nump2prev
1947 numoprev = numprev - nump1prev - nump2prev
1948 totalrawsize = datasize[2]
1948 totalrawsize = datasize[2]
1949 datasize[2] /= numrevs
1949 datasize[2] /= numrevs
1950 fulltotal = fullsize[2]
1950 fulltotal = fullsize[2]
1951 fullsize[2] /= numfull
1951 fullsize[2] /= numfull
1952 deltatotal = deltasize[2]
1952 deltatotal = deltasize[2]
1953 deltasize[2] /= numrevs - numfull
1953 deltasize[2] /= numrevs - numfull
1954 totalsize = fulltotal + deltatotal
1954 totalsize = fulltotal + deltatotal
1955 avgchainlen = sum(chainlengths) / numrevs
1955 avgchainlen = sum(chainlengths) / numrevs
1956 compratio = totalrawsize / totalsize
1956 compratio = totalrawsize / totalsize
1957
1957
1958 basedfmtstr = '%%%dd\n'
1958 basedfmtstr = '%%%dd\n'
1959 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1959 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1960
1960
1961 def dfmtstr(max):
1961 def dfmtstr(max):
1962 return basedfmtstr % len(str(max))
1962 return basedfmtstr % len(str(max))
1963 def pcfmtstr(max, padding=0):
1963 def pcfmtstr(max, padding=0):
1964 return basepcfmtstr % (len(str(max)), ' ' * padding)
1964 return basepcfmtstr % (len(str(max)), ' ' * padding)
1965
1965
1966 def pcfmt(value, total):
1966 def pcfmt(value, total):
1967 return (value, 100 * float(value) / total)
1967 return (value, 100 * float(value) / total)
1968
1968
1969 ui.write('format : %d\n' % format)
1969 ui.write('format : %d\n' % format)
1970 ui.write('flags : %s\n' % ', '.join(flags))
1970 ui.write('flags : %s\n' % ', '.join(flags))
1971
1971
1972 ui.write('\n')
1972 ui.write('\n')
1973 fmt = pcfmtstr(totalsize)
1973 fmt = pcfmtstr(totalsize)
1974 fmt2 = dfmtstr(totalsize)
1974 fmt2 = dfmtstr(totalsize)
1975 ui.write('revisions : ' + fmt2 % numrevs)
1975 ui.write('revisions : ' + fmt2 % numrevs)
1976 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
1976 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
1977 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
1977 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
1978 ui.write('revisions : ' + fmt2 % numrevs)
1978 ui.write('revisions : ' + fmt2 % numrevs)
1979 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
1979 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
1980 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
1980 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
1981 ui.write('revision size : ' + fmt2 % totalsize)
1981 ui.write('revision size : ' + fmt2 % totalsize)
1982 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
1982 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
1983 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
1983 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
1984
1984
1985 ui.write('\n')
1985 ui.write('\n')
1986 fmt = dfmtstr(max(avgchainlen, compratio))
1986 fmt = dfmtstr(max(avgchainlen, compratio))
1987 ui.write('avg chain length : ' + fmt % avgchainlen)
1987 ui.write('avg chain length : ' + fmt % avgchainlen)
1988 ui.write('compression ratio : ' + fmt % compratio)
1988 ui.write('compression ratio : ' + fmt % compratio)
1989
1989
1990 if format > 0:
1990 if format > 0:
1991 ui.write('\n')
1991 ui.write('\n')
1992 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
1992 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
1993 % tuple(datasize))
1993 % tuple(datasize))
1994 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
1994 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
1995 % tuple(fullsize))
1995 % tuple(fullsize))
1996 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
1996 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
1997 % tuple(deltasize))
1997 % tuple(deltasize))
1998
1998
1999 if numdeltas > 0:
1999 if numdeltas > 0:
2000 ui.write('\n')
2000 ui.write('\n')
2001 fmt = pcfmtstr(numdeltas)
2001 fmt = pcfmtstr(numdeltas)
2002 fmt2 = pcfmtstr(numdeltas, 4)
2002 fmt2 = pcfmtstr(numdeltas, 4)
2003 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2003 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2004 if numprev > 0:
2004 if numprev > 0:
2005 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2005 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2006 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2006 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2007 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2007 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2008 if gdelta:
2008 if gdelta:
2009 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2009 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2010 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2010 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2011 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2011 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2012
2012
2013 @command('debugrevspec', [], ('REVSPEC'))
2013 @command('debugrevspec', [], ('REVSPEC'))
2014 def debugrevspec(ui, repo, expr):
2014 def debugrevspec(ui, repo, expr):
2015 '''parse and apply a revision specification'''
2015 '''parse and apply a revision specification'''
2016 if ui.verbose:
2016 if ui.verbose:
2017 tree = revset.parse(expr)[0]
2017 tree = revset.parse(expr)[0]
2018 ui.note(tree, "\n")
2018 ui.note(tree, "\n")
2019 newtree = revset.findaliases(ui, tree)
2019 newtree = revset.findaliases(ui, tree)
2020 if newtree != tree:
2020 if newtree != tree:
2021 ui.note(newtree, "\n")
2021 ui.note(newtree, "\n")
2022 func = revset.match(ui, expr)
2022 func = revset.match(ui, expr)
2023 for c in func(repo, range(len(repo))):
2023 for c in func(repo, range(len(repo))):
2024 ui.write("%s\n" % c)
2024 ui.write("%s\n" % c)
2025
2025
2026 @command('debugsetparents', [], _('REV1 [REV2]'))
2026 @command('debugsetparents', [], _('REV1 [REV2]'))
2027 def debugsetparents(ui, repo, rev1, rev2=None):
2027 def debugsetparents(ui, repo, rev1, rev2=None):
2028 """manually set the parents of the current working directory
2028 """manually set the parents of the current working directory
2029
2029
2030 This is useful for writing repository conversion tools, but should
2030 This is useful for writing repository conversion tools, but should
2031 be used with care.
2031 be used with care.
2032
2032
2033 Returns 0 on success.
2033 Returns 0 on success.
2034 """
2034 """
2035
2035
2036 r1 = scmutil.revsingle(repo, rev1).node()
2036 r1 = scmutil.revsingle(repo, rev1).node()
2037 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2037 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2038
2038
2039 wlock = repo.wlock()
2039 wlock = repo.wlock()
2040 try:
2040 try:
2041 repo.dirstate.setparents(r1, r2)
2041 repo.dirstate.setparents(r1, r2)
2042 finally:
2042 finally:
2043 wlock.release()
2043 wlock.release()
2044
2044
2045 @command('debugstate',
2045 @command('debugstate',
2046 [('', 'nodates', None, _('do not display the saved mtime')),
2046 [('', 'nodates', None, _('do not display the saved mtime')),
2047 ('', 'datesort', None, _('sort by saved mtime'))],
2047 ('', 'datesort', None, _('sort by saved mtime'))],
2048 _('[OPTION]...'))
2048 _('[OPTION]...'))
2049 def debugstate(ui, repo, nodates=None, datesort=None):
2049 def debugstate(ui, repo, nodates=None, datesort=None):
2050 """show the contents of the current dirstate"""
2050 """show the contents of the current dirstate"""
2051 timestr = ""
2051 timestr = ""
2052 showdate = not nodates
2052 showdate = not nodates
2053 if datesort:
2053 if datesort:
2054 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2054 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2055 else:
2055 else:
2056 keyfunc = None # sort by filename
2056 keyfunc = None # sort by filename
2057 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2057 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2058 if showdate:
2058 if showdate:
2059 if ent[3] == -1:
2059 if ent[3] == -1:
2060 # Pad or slice to locale representation
2060 # Pad or slice to locale representation
2061 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2061 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2062 time.localtime(0)))
2062 time.localtime(0)))
2063 timestr = 'unset'
2063 timestr = 'unset'
2064 timestr = (timestr[:locale_len] +
2064 timestr = (timestr[:locale_len] +
2065 ' ' * (locale_len - len(timestr)))
2065 ' ' * (locale_len - len(timestr)))
2066 else:
2066 else:
2067 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2067 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2068 time.localtime(ent[3]))
2068 time.localtime(ent[3]))
2069 if ent[1] & 020000:
2069 if ent[1] & 020000:
2070 mode = 'lnk'
2070 mode = 'lnk'
2071 else:
2071 else:
2072 mode = '%3o' % (ent[1] & 0777)
2072 mode = '%3o' % (ent[1] & 0777)
2073 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2073 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2074 for f in repo.dirstate.copies():
2074 for f in repo.dirstate.copies():
2075 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2075 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2076
2076
2077 @command('debugsub',
2077 @command('debugsub',
2078 [('r', 'rev', '',
2078 [('r', 'rev', '',
2079 _('revision to check'), _('REV'))],
2079 _('revision to check'), _('REV'))],
2080 _('[-r REV] [REV]'))
2080 _('[-r REV] [REV]'))
2081 def debugsub(ui, repo, rev=None):
2081 def debugsub(ui, repo, rev=None):
2082 ctx = scmutil.revsingle(repo, rev, None)
2082 ctx = scmutil.revsingle(repo, rev, None)
2083 for k, v in sorted(ctx.substate.items()):
2083 for k, v in sorted(ctx.substate.items()):
2084 ui.write('path %s\n' % k)
2084 ui.write('path %s\n' % k)
2085 ui.write(' source %s\n' % v[0])
2085 ui.write(' source %s\n' % v[0])
2086 ui.write(' revision %s\n' % v[1])
2086 ui.write(' revision %s\n' % v[1])
2087
2087
2088 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2088 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2089 def debugwalk(ui, repo, *pats, **opts):
2089 def debugwalk(ui, repo, *pats, **opts):
2090 """show how files match on given patterns"""
2090 """show how files match on given patterns"""
2091 m = scmutil.match(repo, pats, opts)
2091 m = scmutil.match(repo, pats, opts)
2092 items = list(repo.walk(m))
2092 items = list(repo.walk(m))
2093 if not items:
2093 if not items:
2094 return
2094 return
2095 fmt = 'f %%-%ds %%-%ds %%s' % (
2095 fmt = 'f %%-%ds %%-%ds %%s' % (
2096 max([len(abs) for abs in items]),
2096 max([len(abs) for abs in items]),
2097 max([len(m.rel(abs)) for abs in items]))
2097 max([len(m.rel(abs)) for abs in items]))
2098 for abs in items:
2098 for abs in items:
2099 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2099 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2100 ui.write("%s\n" % line.rstrip())
2100 ui.write("%s\n" % line.rstrip())
2101
2101
2102 @command('debugwireargs',
2102 @command('debugwireargs',
2103 [('', 'three', '', 'three'),
2103 [('', 'three', '', 'three'),
2104 ('', 'four', '', 'four'),
2104 ('', 'four', '', 'four'),
2105 ('', 'five', '', 'five'),
2105 ('', 'five', '', 'five'),
2106 ] + remoteopts,
2106 ] + remoteopts,
2107 _('REPO [OPTIONS]... [ONE [TWO]]'))
2107 _('REPO [OPTIONS]... [ONE [TWO]]'))
2108 def debugwireargs(ui, repopath, *vals, **opts):
2108 def debugwireargs(ui, repopath, *vals, **opts):
2109 repo = hg.repository(hg.remoteui(ui, opts), repopath)
2109 repo = hg.repository(hg.remoteui(ui, opts), repopath)
2110 for opt in remoteopts:
2110 for opt in remoteopts:
2111 del opts[opt[1]]
2111 del opts[opt[1]]
2112 args = {}
2112 args = {}
2113 for k, v in opts.iteritems():
2113 for k, v in opts.iteritems():
2114 if v:
2114 if v:
2115 args[k] = v
2115 args[k] = v
2116 # run twice to check that we don't mess up the stream for the next command
2116 # run twice to check that we don't mess up the stream for the next command
2117 res1 = repo.debugwireargs(*vals, **args)
2117 res1 = repo.debugwireargs(*vals, **args)
2118 res2 = repo.debugwireargs(*vals, **args)
2118 res2 = repo.debugwireargs(*vals, **args)
2119 ui.write("%s\n" % res1)
2119 ui.write("%s\n" % res1)
2120 if res1 != res2:
2120 if res1 != res2:
2121 ui.warn("%s\n" % res2)
2121 ui.warn("%s\n" % res2)
2122
2122
2123 @command('^diff',
2123 @command('^diff',
2124 [('r', 'rev', [], _('revision'), _('REV')),
2124 [('r', 'rev', [], _('revision'), _('REV')),
2125 ('c', 'change', '', _('change made by revision'), _('REV'))
2125 ('c', 'change', '', _('change made by revision'), _('REV'))
2126 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2126 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2127 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2127 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2128 def diff(ui, repo, *pats, **opts):
2128 def diff(ui, repo, *pats, **opts):
2129 """diff repository (or selected files)
2129 """diff repository (or selected files)
2130
2130
2131 Show differences between revisions for the specified files.
2131 Show differences between revisions for the specified files.
2132
2132
2133 Differences between files are shown using the unified diff format.
2133 Differences between files are shown using the unified diff format.
2134
2134
2135 .. note::
2135 .. note::
2136 diff may generate unexpected results for merges, as it will
2136 diff may generate unexpected results for merges, as it will
2137 default to comparing against the working directory's first
2137 default to comparing against the working directory's first
2138 parent changeset if no revisions are specified.
2138 parent changeset if no revisions are specified.
2139
2139
2140 When two revision arguments are given, then changes are shown
2140 When two revision arguments are given, then changes are shown
2141 between those revisions. If only one revision is specified then
2141 between those revisions. If only one revision is specified then
2142 that revision is compared to the working directory, and, when no
2142 that revision is compared to the working directory, and, when no
2143 revisions are specified, the working directory files are compared
2143 revisions are specified, the working directory files are compared
2144 to its parent.
2144 to its parent.
2145
2145
2146 Alternatively you can specify -c/--change with a revision to see
2146 Alternatively you can specify -c/--change with a revision to see
2147 the changes in that changeset relative to its first parent.
2147 the changes in that changeset relative to its first parent.
2148
2148
2149 Without the -a/--text option, diff will avoid generating diffs of
2149 Without the -a/--text option, diff will avoid generating diffs of
2150 files it detects as binary. With -a, diff will generate a diff
2150 files it detects as binary. With -a, diff will generate a diff
2151 anyway, probably with undesirable results.
2151 anyway, probably with undesirable results.
2152
2152
2153 Use the -g/--git option to generate diffs in the git extended diff
2153 Use the -g/--git option to generate diffs in the git extended diff
2154 format. For more information, read :hg:`help diffs`.
2154 format. For more information, read :hg:`help diffs`.
2155
2155
2156 Returns 0 on success.
2156 Returns 0 on success.
2157 """
2157 """
2158
2158
2159 revs = opts.get('rev')
2159 revs = opts.get('rev')
2160 change = opts.get('change')
2160 change = opts.get('change')
2161 stat = opts.get('stat')
2161 stat = opts.get('stat')
2162 reverse = opts.get('reverse')
2162 reverse = opts.get('reverse')
2163
2163
2164 if revs and change:
2164 if revs and change:
2165 msg = _('cannot specify --rev and --change at the same time')
2165 msg = _('cannot specify --rev and --change at the same time')
2166 raise util.Abort(msg)
2166 raise util.Abort(msg)
2167 elif change:
2167 elif change:
2168 node2 = scmutil.revsingle(repo, change, None).node()
2168 node2 = scmutil.revsingle(repo, change, None).node()
2169 node1 = repo[node2].p1().node()
2169 node1 = repo[node2].p1().node()
2170 else:
2170 else:
2171 node1, node2 = scmutil.revpair(repo, revs)
2171 node1, node2 = scmutil.revpair(repo, revs)
2172
2172
2173 if reverse:
2173 if reverse:
2174 node1, node2 = node2, node1
2174 node1, node2 = node2, node1
2175
2175
2176 diffopts = patch.diffopts(ui, opts)
2176 diffopts = patch.diffopts(ui, opts)
2177 m = scmutil.match(repo, pats, opts)
2177 m = scmutil.match(repo, pats, opts)
2178 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2178 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2179 listsubrepos=opts.get('subrepos'))
2179 listsubrepos=opts.get('subrepos'))
2180
2180
2181 @command('^export',
2181 @command('^export',
2182 [('o', 'output', '',
2182 [('o', 'output', '',
2183 _('print output to file with formatted name'), _('FORMAT')),
2183 _('print output to file with formatted name'), _('FORMAT')),
2184 ('', 'switch-parent', None, _('diff against the second parent')),
2184 ('', 'switch-parent', None, _('diff against the second parent')),
2185 ('r', 'rev', [], _('revisions to export'), _('REV')),
2185 ('r', 'rev', [], _('revisions to export'), _('REV')),
2186 ] + diffopts,
2186 ] + diffopts,
2187 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2187 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2188 def export(ui, repo, *changesets, **opts):
2188 def export(ui, repo, *changesets, **opts):
2189 """dump the header and diffs for one or more changesets
2189 """dump the header and diffs for one or more changesets
2190
2190
2191 Print the changeset header and diffs for one or more revisions.
2191 Print the changeset header and diffs for one or more revisions.
2192
2192
2193 The information shown in the changeset header is: author, date,
2193 The information shown in the changeset header is: author, date,
2194 branch name (if non-default), changeset hash, parent(s) and commit
2194 branch name (if non-default), changeset hash, parent(s) and commit
2195 comment.
2195 comment.
2196
2196
2197 .. note::
2197 .. note::
2198 export may generate unexpected diff output for merge
2198 export may generate unexpected diff output for merge
2199 changesets, as it will compare the merge changeset against its
2199 changesets, as it will compare the merge changeset against its
2200 first parent only.
2200 first parent only.
2201
2201
2202 Output may be to a file, in which case the name of the file is
2202 Output may be to a file, in which case the name of the file is
2203 given using a format string. The formatting rules are as follows:
2203 given using a format string. The formatting rules are as follows:
2204
2204
2205 :``%%``: literal "%" character
2205 :``%%``: literal "%" character
2206 :``%H``: changeset hash (40 hexadecimal digits)
2206 :``%H``: changeset hash (40 hexadecimal digits)
2207 :``%N``: number of patches being generated
2207 :``%N``: number of patches being generated
2208 :``%R``: changeset revision number
2208 :``%R``: changeset revision number
2209 :``%b``: basename of the exporting repository
2209 :``%b``: basename of the exporting repository
2210 :``%h``: short-form changeset hash (12 hexadecimal digits)
2210 :``%h``: short-form changeset hash (12 hexadecimal digits)
2211 :``%n``: zero-padded sequence number, starting at 1
2211 :``%n``: zero-padded sequence number, starting at 1
2212 :``%r``: zero-padded changeset revision number
2212 :``%r``: zero-padded changeset revision number
2213
2213
2214 Without the -a/--text option, export will avoid generating diffs
2214 Without the -a/--text option, export will avoid generating diffs
2215 of files it detects as binary. With -a, export will generate a
2215 of files it detects as binary. With -a, export will generate a
2216 diff anyway, probably with undesirable results.
2216 diff anyway, probably with undesirable results.
2217
2217
2218 Use the -g/--git option to generate diffs in the git extended diff
2218 Use the -g/--git option to generate diffs in the git extended diff
2219 format. See :hg:`help diffs` for more information.
2219 format. See :hg:`help diffs` for more information.
2220
2220
2221 With the --switch-parent option, the diff will be against the
2221 With the --switch-parent option, the diff will be against the
2222 second parent. It can be useful to review a merge.
2222 second parent. It can be useful to review a merge.
2223
2223
2224 Returns 0 on success.
2224 Returns 0 on success.
2225 """
2225 """
2226 changesets += tuple(opts.get('rev', []))
2226 changesets += tuple(opts.get('rev', []))
2227 if not changesets:
2227 if not changesets:
2228 raise util.Abort(_("export requires at least one changeset"))
2228 raise util.Abort(_("export requires at least one changeset"))
2229 revs = scmutil.revrange(repo, changesets)
2229 revs = scmutil.revrange(repo, changesets)
2230 if len(revs) > 1:
2230 if len(revs) > 1:
2231 ui.note(_('exporting patches:\n'))
2231 ui.note(_('exporting patches:\n'))
2232 else:
2232 else:
2233 ui.note(_('exporting patch:\n'))
2233 ui.note(_('exporting patch:\n'))
2234 cmdutil.export(repo, revs, template=opts.get('output'),
2234 cmdutil.export(repo, revs, template=opts.get('output'),
2235 switch_parent=opts.get('switch_parent'),
2235 switch_parent=opts.get('switch_parent'),
2236 opts=patch.diffopts(ui, opts))
2236 opts=patch.diffopts(ui, opts))
2237
2237
2238 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2238 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2239 def forget(ui, repo, *pats, **opts):
2239 def forget(ui, repo, *pats, **opts):
2240 """forget the specified files on the next commit
2240 """forget the specified files on the next commit
2241
2241
2242 Mark the specified files so they will no longer be tracked
2242 Mark the specified files so they will no longer be tracked
2243 after the next commit.
2243 after the next commit.
2244
2244
2245 This only removes files from the current branch, not from the
2245 This only removes files from the current branch, not from the
2246 entire project history, and it does not delete them from the
2246 entire project history, and it does not delete them from the
2247 working directory.
2247 working directory.
2248
2248
2249 To undo a forget before the next commit, see :hg:`add`.
2249 To undo a forget before the next commit, see :hg:`add`.
2250
2250
2251 Returns 0 on success.
2251 Returns 0 on success.
2252 """
2252 """
2253
2253
2254 if not pats:
2254 if not pats:
2255 raise util.Abort(_('no files specified'))
2255 raise util.Abort(_('no files specified'))
2256
2256
2257 m = scmutil.match(repo, pats, opts)
2257 m = scmutil.match(repo, pats, opts)
2258 s = repo.status(match=m, clean=True)
2258 s = repo.status(match=m, clean=True)
2259 forget = sorted(s[0] + s[1] + s[3] + s[6])
2259 forget = sorted(s[0] + s[1] + s[3] + s[6])
2260 errs = 0
2260 errs = 0
2261
2261
2262 for f in m.files():
2262 for f in m.files():
2263 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2263 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2264 ui.warn(_('not removing %s: file is already untracked\n')
2264 ui.warn(_('not removing %s: file is already untracked\n')
2265 % m.rel(f))
2265 % m.rel(f))
2266 errs = 1
2266 errs = 1
2267
2267
2268 for f in forget:
2268 for f in forget:
2269 if ui.verbose or not m.exact(f):
2269 if ui.verbose or not m.exact(f):
2270 ui.status(_('removing %s\n') % m.rel(f))
2270 ui.status(_('removing %s\n') % m.rel(f))
2271
2271
2272 repo[None].remove(forget, unlink=False)
2272 repo[None].remove(forget, unlink=False)
2273 return errs
2273 return errs
2274
2274
2275 @command('grep',
2275 @command('grep',
2276 [('0', 'print0', None, _('end fields with NUL')),
2276 [('0', 'print0', None, _('end fields with NUL')),
2277 ('', 'all', None, _('print all revisions that match')),
2277 ('', 'all', None, _('print all revisions that match')),
2278 ('a', 'text', None, _('treat all files as text')),
2278 ('a', 'text', None, _('treat all files as text')),
2279 ('f', 'follow', None,
2279 ('f', 'follow', None,
2280 _('follow changeset history,'
2280 _('follow changeset history,'
2281 ' or file history across copies and renames')),
2281 ' or file history across copies and renames')),
2282 ('i', 'ignore-case', None, _('ignore case when matching')),
2282 ('i', 'ignore-case', None, _('ignore case when matching')),
2283 ('l', 'files-with-matches', None,
2283 ('l', 'files-with-matches', None,
2284 _('print only filenames and revisions that match')),
2284 _('print only filenames and revisions that match')),
2285 ('n', 'line-number', None, _('print matching line numbers')),
2285 ('n', 'line-number', None, _('print matching line numbers')),
2286 ('r', 'rev', [],
2286 ('r', 'rev', [],
2287 _('only search files changed within revision range'), _('REV')),
2287 _('only search files changed within revision range'), _('REV')),
2288 ('u', 'user', None, _('list the author (long with -v)')),
2288 ('u', 'user', None, _('list the author (long with -v)')),
2289 ('d', 'date', None, _('list the date (short with -q)')),
2289 ('d', 'date', None, _('list the date (short with -q)')),
2290 ] + walkopts,
2290 ] + walkopts,
2291 _('[OPTION]... PATTERN [FILE]...'))
2291 _('[OPTION]... PATTERN [FILE]...'))
2292 def grep(ui, repo, pattern, *pats, **opts):
2292 def grep(ui, repo, pattern, *pats, **opts):
2293 """search for a pattern in specified files and revisions
2293 """search for a pattern in specified files and revisions
2294
2294
2295 Search revisions of files for a regular expression.
2295 Search revisions of files for a regular expression.
2296
2296
2297 This command behaves differently than Unix grep. It only accepts
2297 This command behaves differently than Unix grep. It only accepts
2298 Python/Perl regexps. It searches repository history, not the
2298 Python/Perl regexps. It searches repository history, not the
2299 working directory. It always prints the revision number in which a
2299 working directory. It always prints the revision number in which a
2300 match appears.
2300 match appears.
2301
2301
2302 By default, grep only prints output for the first revision of a
2302 By default, grep only prints output for the first revision of a
2303 file in which it finds a match. To get it to print every revision
2303 file in which it finds a match. To get it to print every revision
2304 that contains a change in match status ("-" for a match that
2304 that contains a change in match status ("-" for a match that
2305 becomes a non-match, or "+" for a non-match that becomes a match),
2305 becomes a non-match, or "+" for a non-match that becomes a match),
2306 use the --all flag.
2306 use the --all flag.
2307
2307
2308 Returns 0 if a match is found, 1 otherwise.
2308 Returns 0 if a match is found, 1 otherwise.
2309 """
2309 """
2310 reflags = 0
2310 reflags = 0
2311 if opts.get('ignore_case'):
2311 if opts.get('ignore_case'):
2312 reflags |= re.I
2312 reflags |= re.I
2313 try:
2313 try:
2314 regexp = re.compile(pattern, reflags)
2314 regexp = re.compile(pattern, reflags)
2315 except re.error, inst:
2315 except re.error, inst:
2316 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2316 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2317 return 1
2317 return 1
2318 sep, eol = ':', '\n'
2318 sep, eol = ':', '\n'
2319 if opts.get('print0'):
2319 if opts.get('print0'):
2320 sep = eol = '\0'
2320 sep = eol = '\0'
2321
2321
2322 getfile = util.lrucachefunc(repo.file)
2322 getfile = util.lrucachefunc(repo.file)
2323
2323
2324 def matchlines(body):
2324 def matchlines(body):
2325 begin = 0
2325 begin = 0
2326 linenum = 0
2326 linenum = 0
2327 while True:
2327 while True:
2328 match = regexp.search(body, begin)
2328 match = regexp.search(body, begin)
2329 if not match:
2329 if not match:
2330 break
2330 break
2331 mstart, mend = match.span()
2331 mstart, mend = match.span()
2332 linenum += body.count('\n', begin, mstart) + 1
2332 linenum += body.count('\n', begin, mstart) + 1
2333 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2333 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2334 begin = body.find('\n', mend) + 1 or len(body)
2334 begin = body.find('\n', mend) + 1 or len(body)
2335 lend = begin - 1
2335 lend = begin - 1
2336 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2336 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2337
2337
2338 class linestate(object):
2338 class linestate(object):
2339 def __init__(self, line, linenum, colstart, colend):
2339 def __init__(self, line, linenum, colstart, colend):
2340 self.line = line
2340 self.line = line
2341 self.linenum = linenum
2341 self.linenum = linenum
2342 self.colstart = colstart
2342 self.colstart = colstart
2343 self.colend = colend
2343 self.colend = colend
2344
2344
2345 def __hash__(self):
2345 def __hash__(self):
2346 return hash((self.linenum, self.line))
2346 return hash((self.linenum, self.line))
2347
2347
2348 def __eq__(self, other):
2348 def __eq__(self, other):
2349 return self.line == other.line
2349 return self.line == other.line
2350
2350
2351 matches = {}
2351 matches = {}
2352 copies = {}
2352 copies = {}
2353 def grepbody(fn, rev, body):
2353 def grepbody(fn, rev, body):
2354 matches[rev].setdefault(fn, [])
2354 matches[rev].setdefault(fn, [])
2355 m = matches[rev][fn]
2355 m = matches[rev][fn]
2356 for lnum, cstart, cend, line in matchlines(body):
2356 for lnum, cstart, cend, line in matchlines(body):
2357 s = linestate(line, lnum, cstart, cend)
2357 s = linestate(line, lnum, cstart, cend)
2358 m.append(s)
2358 m.append(s)
2359
2359
2360 def difflinestates(a, b):
2360 def difflinestates(a, b):
2361 sm = difflib.SequenceMatcher(None, a, b)
2361 sm = difflib.SequenceMatcher(None, a, b)
2362 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2362 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2363 if tag == 'insert':
2363 if tag == 'insert':
2364 for i in xrange(blo, bhi):
2364 for i in xrange(blo, bhi):
2365 yield ('+', b[i])
2365 yield ('+', b[i])
2366 elif tag == 'delete':
2366 elif tag == 'delete':
2367 for i in xrange(alo, ahi):
2367 for i in xrange(alo, ahi):
2368 yield ('-', a[i])
2368 yield ('-', a[i])
2369 elif tag == 'replace':
2369 elif tag == 'replace':
2370 for i in xrange(alo, ahi):
2370 for i in xrange(alo, ahi):
2371 yield ('-', a[i])
2371 yield ('-', a[i])
2372 for i in xrange(blo, bhi):
2372 for i in xrange(blo, bhi):
2373 yield ('+', b[i])
2373 yield ('+', b[i])
2374
2374
2375 def display(fn, ctx, pstates, states):
2375 def display(fn, ctx, pstates, states):
2376 rev = ctx.rev()
2376 rev = ctx.rev()
2377 datefunc = ui.quiet and util.shortdate or util.datestr
2377 datefunc = ui.quiet and util.shortdate or util.datestr
2378 found = False
2378 found = False
2379 filerevmatches = {}
2379 filerevmatches = {}
2380 def binary():
2380 def binary():
2381 flog = getfile(fn)
2381 flog = getfile(fn)
2382 return util.binary(flog.read(ctx.filenode(fn)))
2382 return util.binary(flog.read(ctx.filenode(fn)))
2383
2383
2384 if opts.get('all'):
2384 if opts.get('all'):
2385 iter = difflinestates(pstates, states)
2385 iter = difflinestates(pstates, states)
2386 else:
2386 else:
2387 iter = [('', l) for l in states]
2387 iter = [('', l) for l in states]
2388 for change, l in iter:
2388 for change, l in iter:
2389 cols = [fn, str(rev)]
2389 cols = [fn, str(rev)]
2390 before, match, after = None, None, None
2390 before, match, after = None, None, None
2391 if opts.get('line_number'):
2391 if opts.get('line_number'):
2392 cols.append(str(l.linenum))
2392 cols.append(str(l.linenum))
2393 if opts.get('all'):
2393 if opts.get('all'):
2394 cols.append(change)
2394 cols.append(change)
2395 if opts.get('user'):
2395 if opts.get('user'):
2396 cols.append(ui.shortuser(ctx.user()))
2396 cols.append(ui.shortuser(ctx.user()))
2397 if opts.get('date'):
2397 if opts.get('date'):
2398 cols.append(datefunc(ctx.date()))
2398 cols.append(datefunc(ctx.date()))
2399 if opts.get('files_with_matches'):
2399 if opts.get('files_with_matches'):
2400 c = (fn, rev)
2400 c = (fn, rev)
2401 if c in filerevmatches:
2401 if c in filerevmatches:
2402 continue
2402 continue
2403 filerevmatches[c] = 1
2403 filerevmatches[c] = 1
2404 else:
2404 else:
2405 before = l.line[:l.colstart]
2405 before = l.line[:l.colstart]
2406 match = l.line[l.colstart:l.colend]
2406 match = l.line[l.colstart:l.colend]
2407 after = l.line[l.colend:]
2407 after = l.line[l.colend:]
2408 ui.write(sep.join(cols))
2408 ui.write(sep.join(cols))
2409 if before is not None:
2409 if before is not None:
2410 if not opts.get('text') and binary():
2410 if not opts.get('text') and binary():
2411 ui.write(sep + " Binary file matches")
2411 ui.write(sep + " Binary file matches")
2412 else:
2412 else:
2413 ui.write(sep + before)
2413 ui.write(sep + before)
2414 ui.write(match, label='grep.match')
2414 ui.write(match, label='grep.match')
2415 ui.write(after)
2415 ui.write(after)
2416 ui.write(eol)
2416 ui.write(eol)
2417 found = True
2417 found = True
2418 return found
2418 return found
2419
2419
2420 skip = {}
2420 skip = {}
2421 revfiles = {}
2421 revfiles = {}
2422 matchfn = scmutil.match(repo, pats, opts)
2422 matchfn = scmutil.match(repo, pats, opts)
2423 found = False
2423 found = False
2424 follow = opts.get('follow')
2424 follow = opts.get('follow')
2425
2425
2426 def prep(ctx, fns):
2426 def prep(ctx, fns):
2427 rev = ctx.rev()
2427 rev = ctx.rev()
2428 pctx = ctx.p1()
2428 pctx = ctx.p1()
2429 parent = pctx.rev()
2429 parent = pctx.rev()
2430 matches.setdefault(rev, {})
2430 matches.setdefault(rev, {})
2431 matches.setdefault(parent, {})
2431 matches.setdefault(parent, {})
2432 files = revfiles.setdefault(rev, [])
2432 files = revfiles.setdefault(rev, [])
2433 for fn in fns:
2433 for fn in fns:
2434 flog = getfile(fn)
2434 flog = getfile(fn)
2435 try:
2435 try:
2436 fnode = ctx.filenode(fn)
2436 fnode = ctx.filenode(fn)
2437 except error.LookupError:
2437 except error.LookupError:
2438 continue
2438 continue
2439
2439
2440 copied = flog.renamed(fnode)
2440 copied = flog.renamed(fnode)
2441 copy = follow and copied and copied[0]
2441 copy = follow and copied and copied[0]
2442 if copy:
2442 if copy:
2443 copies.setdefault(rev, {})[fn] = copy
2443 copies.setdefault(rev, {})[fn] = copy
2444 if fn in skip:
2444 if fn in skip:
2445 if copy:
2445 if copy:
2446 skip[copy] = True
2446 skip[copy] = True
2447 continue
2447 continue
2448 files.append(fn)
2448 files.append(fn)
2449
2449
2450 if fn not in matches[rev]:
2450 if fn not in matches[rev]:
2451 grepbody(fn, rev, flog.read(fnode))
2451 grepbody(fn, rev, flog.read(fnode))
2452
2452
2453 pfn = copy or fn
2453 pfn = copy or fn
2454 if pfn not in matches[parent]:
2454 if pfn not in matches[parent]:
2455 try:
2455 try:
2456 fnode = pctx.filenode(pfn)
2456 fnode = pctx.filenode(pfn)
2457 grepbody(pfn, parent, flog.read(fnode))
2457 grepbody(pfn, parent, flog.read(fnode))
2458 except error.LookupError:
2458 except error.LookupError:
2459 pass
2459 pass
2460
2460
2461 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2461 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2462 rev = ctx.rev()
2462 rev = ctx.rev()
2463 parent = ctx.p1().rev()
2463 parent = ctx.p1().rev()
2464 for fn in sorted(revfiles.get(rev, [])):
2464 for fn in sorted(revfiles.get(rev, [])):
2465 states = matches[rev][fn]
2465 states = matches[rev][fn]
2466 copy = copies.get(rev, {}).get(fn)
2466 copy = copies.get(rev, {}).get(fn)
2467 if fn in skip:
2467 if fn in skip:
2468 if copy:
2468 if copy:
2469 skip[copy] = True
2469 skip[copy] = True
2470 continue
2470 continue
2471 pstates = matches.get(parent, {}).get(copy or fn, [])
2471 pstates = matches.get(parent, {}).get(copy or fn, [])
2472 if pstates or states:
2472 if pstates or states:
2473 r = display(fn, ctx, pstates, states)
2473 r = display(fn, ctx, pstates, states)
2474 found = found or r
2474 found = found or r
2475 if r and not opts.get('all'):
2475 if r and not opts.get('all'):
2476 skip[fn] = True
2476 skip[fn] = True
2477 if copy:
2477 if copy:
2478 skip[copy] = True
2478 skip[copy] = True
2479 del matches[rev]
2479 del matches[rev]
2480 del revfiles[rev]
2480 del revfiles[rev]
2481
2481
2482 return not found
2482 return not found
2483
2483
2484 @command('heads',
2484 @command('heads',
2485 [('r', 'rev', '',
2485 [('r', 'rev', '',
2486 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2486 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2487 ('t', 'topo', False, _('show topological heads only')),
2487 ('t', 'topo', False, _('show topological heads only')),
2488 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2488 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2489 ('c', 'closed', False, _('show normal and closed branch heads')),
2489 ('c', 'closed', False, _('show normal and closed branch heads')),
2490 ] + templateopts,
2490 ] + templateopts,
2491 _('[-ac] [-r STARTREV] [REV]...'))
2491 _('[-ac] [-r STARTREV] [REV]...'))
2492 def heads(ui, repo, *branchrevs, **opts):
2492 def heads(ui, repo, *branchrevs, **opts):
2493 """show current repository heads or show branch heads
2493 """show current repository heads or show branch heads
2494
2494
2495 With no arguments, show all repository branch heads.
2495 With no arguments, show all repository branch heads.
2496
2496
2497 Repository "heads" are changesets with no child changesets. They are
2497 Repository "heads" are changesets with no child changesets. They are
2498 where development generally takes place and are the usual targets
2498 where development generally takes place and are the usual targets
2499 for update and merge operations. Branch heads are changesets that have
2499 for update and merge operations. Branch heads are changesets that have
2500 no child changeset on the same branch.
2500 no child changeset on the same branch.
2501
2501
2502 If one or more REVs are given, only branch heads on the branches
2502 If one or more REVs are given, only branch heads on the branches
2503 associated with the specified changesets are shown.
2503 associated with the specified changesets are shown.
2504
2504
2505 If -c/--closed is specified, also show branch heads marked closed
2505 If -c/--closed is specified, also show branch heads marked closed
2506 (see :hg:`commit --close-branch`).
2506 (see :hg:`commit --close-branch`).
2507
2507
2508 If STARTREV is specified, only those heads that are descendants of
2508 If STARTREV is specified, only those heads that are descendants of
2509 STARTREV will be displayed.
2509 STARTREV will be displayed.
2510
2510
2511 If -t/--topo is specified, named branch mechanics will be ignored and only
2511 If -t/--topo is specified, named branch mechanics will be ignored and only
2512 changesets without children will be shown.
2512 changesets without children will be shown.
2513
2513
2514 Returns 0 if matching heads are found, 1 if not.
2514 Returns 0 if matching heads are found, 1 if not.
2515 """
2515 """
2516
2516
2517 start = None
2517 start = None
2518 if 'rev' in opts:
2518 if 'rev' in opts:
2519 start = scmutil.revsingle(repo, opts['rev'], None).node()
2519 start = scmutil.revsingle(repo, opts['rev'], None).node()
2520
2520
2521 if opts.get('topo'):
2521 if opts.get('topo'):
2522 heads = [repo[h] for h in repo.heads(start)]
2522 heads = [repo[h] for h in repo.heads(start)]
2523 else:
2523 else:
2524 heads = []
2524 heads = []
2525 for b, ls in repo.branchmap().iteritems():
2525 for b, ls in repo.branchmap().iteritems():
2526 if start is None:
2526 if start is None:
2527 heads += [repo[h] for h in ls]
2527 heads += [repo[h] for h in ls]
2528 continue
2528 continue
2529 startrev = repo.changelog.rev(start)
2529 startrev = repo.changelog.rev(start)
2530 descendants = set(repo.changelog.descendants(startrev))
2530 descendants = set(repo.changelog.descendants(startrev))
2531 descendants.add(startrev)
2531 descendants.add(startrev)
2532 rev = repo.changelog.rev
2532 rev = repo.changelog.rev
2533 heads += [repo[h] for h in ls if rev(h) in descendants]
2533 heads += [repo[h] for h in ls if rev(h) in descendants]
2534
2534
2535 if branchrevs:
2535 if branchrevs:
2536 branches = set(repo[br].branch() for br in branchrevs)
2536 branches = set(repo[br].branch() for br in branchrevs)
2537 heads = [h for h in heads if h.branch() in branches]
2537 heads = [h for h in heads if h.branch() in branches]
2538
2538
2539 if not opts.get('closed'):
2539 if not opts.get('closed'):
2540 heads = [h for h in heads if not h.extra().get('close')]
2540 heads = [h for h in heads if not h.extra().get('close')]
2541
2541
2542 if opts.get('active') and branchrevs:
2542 if opts.get('active') and branchrevs:
2543 dagheads = repo.heads(start)
2543 dagheads = repo.heads(start)
2544 heads = [h for h in heads if h.node() in dagheads]
2544 heads = [h for h in heads if h.node() in dagheads]
2545
2545
2546 if branchrevs:
2546 if branchrevs:
2547 haveheads = set(h.branch() for h in heads)
2547 haveheads = set(h.branch() for h in heads)
2548 if branches - haveheads:
2548 if branches - haveheads:
2549 headless = ', '.join(b for b in branches - haveheads)
2549 headless = ', '.join(b for b in branches - haveheads)
2550 msg = _('no open branch heads found on branches %s')
2550 msg = _('no open branch heads found on branches %s')
2551 if opts.get('rev'):
2551 if opts.get('rev'):
2552 msg += _(' (started at %s)' % opts['rev'])
2552 msg += _(' (started at %s)' % opts['rev'])
2553 ui.warn((msg + '\n') % headless)
2553 ui.warn((msg + '\n') % headless)
2554
2554
2555 if not heads:
2555 if not heads:
2556 return 1
2556 return 1
2557
2557
2558 heads = sorted(heads, key=lambda x: -x.rev())
2558 heads = sorted(heads, key=lambda x: -x.rev())
2559 displayer = cmdutil.show_changeset(ui, repo, opts)
2559 displayer = cmdutil.show_changeset(ui, repo, opts)
2560 for ctx in heads:
2560 for ctx in heads:
2561 displayer.show(ctx)
2561 displayer.show(ctx)
2562 displayer.close()
2562 displayer.close()
2563
2563
2564 @command('help',
2564 @command('help',
2565 [('e', 'extension', None, _('show only help for extensions')),
2565 [('e', 'extension', None, _('show only help for extensions')),
2566 ('c', 'command', None, _('show only help for commands'))],
2566 ('c', 'command', None, _('show only help for commands'))],
2567 _('[-ec] [TOPIC]'))
2567 _('[-ec] [TOPIC]'))
2568 def help_(ui, name=None, with_version=False, unknowncmd=False, full=True, **opts):
2568 def help_(ui, name=None, with_version=False, unknowncmd=False, full=True, **opts):
2569 """show help for a given topic or a help overview
2569 """show help for a given topic or a help overview
2570
2570
2571 With no arguments, print a list of commands with short help messages.
2571 With no arguments, print a list of commands with short help messages.
2572
2572
2573 Given a topic, extension, or command name, print help for that
2573 Given a topic, extension, or command name, print help for that
2574 topic.
2574 topic.
2575
2575
2576 Returns 0 if successful.
2576 Returns 0 if successful.
2577 """
2577 """
2578 option_lists = []
2578 option_lists = []
2579 textwidth = min(ui.termwidth(), 80) - 2
2579 textwidth = min(ui.termwidth(), 80) - 2
2580
2580
2581 def addglobalopts(aliases):
2581 def addglobalopts(aliases):
2582 if ui.verbose:
2582 if ui.verbose:
2583 option_lists.append((_("global options:"), globalopts))
2583 option_lists.append((_("global options:"), globalopts))
2584 if name == 'shortlist':
2584 if name == 'shortlist':
2585 option_lists.append((_('use "hg help" for the full list '
2585 option_lists.append((_('use "hg help" for the full list '
2586 'of commands'), ()))
2586 'of commands'), ()))
2587 else:
2587 else:
2588 if name == 'shortlist':
2588 if name == 'shortlist':
2589 msg = _('use "hg help" for the full list of commands '
2589 msg = _('use "hg help" for the full list of commands '
2590 'or "hg -v" for details')
2590 'or "hg -v" for details')
2591 elif name and not full:
2591 elif name and not full:
2592 msg = _('use "hg help %s" to show the full help text' % name)
2592 msg = _('use "hg help %s" to show the full help text' % name)
2593 elif aliases:
2593 elif aliases:
2594 msg = _('use "hg -v help%s" to show builtin aliases and '
2594 msg = _('use "hg -v help%s" to show builtin aliases and '
2595 'global options') % (name and " " + name or "")
2595 'global options') % (name and " " + name or "")
2596 else:
2596 else:
2597 msg = _('use "hg -v help %s" to show global options') % name
2597 msg = _('use "hg -v help %s" to show global options') % name
2598 option_lists.append((msg, ()))
2598 option_lists.append((msg, ()))
2599
2599
2600 def helpcmd(name):
2600 def helpcmd(name):
2601 if with_version:
2601 if with_version:
2602 version_(ui)
2602 version_(ui)
2603 ui.write('\n')
2603 ui.write('\n')
2604
2604
2605 try:
2605 try:
2606 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2606 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2607 except error.AmbiguousCommand, inst:
2607 except error.AmbiguousCommand, inst:
2608 # py3k fix: except vars can't be used outside the scope of the
2608 # py3k fix: except vars can't be used outside the scope of the
2609 # except block, nor can be used inside a lambda. python issue4617
2609 # except block, nor can be used inside a lambda. python issue4617
2610 prefix = inst.args[0]
2610 prefix = inst.args[0]
2611 select = lambda c: c.lstrip('^').startswith(prefix)
2611 select = lambda c: c.lstrip('^').startswith(prefix)
2612 helplist(_('list of commands:\n\n'), select)
2612 helplist(_('list of commands:\n\n'), select)
2613 return
2613 return
2614
2614
2615 # check if it's an invalid alias and display its error if it is
2615 # check if it's an invalid alias and display its error if it is
2616 if getattr(entry[0], 'badalias', False):
2616 if getattr(entry[0], 'badalias', False):
2617 if not unknowncmd:
2617 if not unknowncmd:
2618 entry[0](ui)
2618 entry[0](ui)
2619 return
2619 return
2620
2620
2621 # synopsis
2621 # synopsis
2622 if len(entry) > 2:
2622 if len(entry) > 2:
2623 if entry[2].startswith('hg'):
2623 if entry[2].startswith('hg'):
2624 ui.write("%s\n" % entry[2])
2624 ui.write("%s\n" % entry[2])
2625 else:
2625 else:
2626 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2626 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2627 else:
2627 else:
2628 ui.write('hg %s\n' % aliases[0])
2628 ui.write('hg %s\n' % aliases[0])
2629
2629
2630 # aliases
2630 # aliases
2631 if full and not ui.quiet and len(aliases) > 1:
2631 if full and not ui.quiet and len(aliases) > 1:
2632 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2632 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2633
2633
2634 # description
2634 # description
2635 doc = gettext(entry[0].__doc__)
2635 doc = gettext(entry[0].__doc__)
2636 if not doc:
2636 if not doc:
2637 doc = _("(no help text available)")
2637 doc = _("(no help text available)")
2638 if hasattr(entry[0], 'definition'): # aliased command
2638 if hasattr(entry[0], 'definition'): # aliased command
2639 if entry[0].definition.startswith('!'): # shell alias
2639 if entry[0].definition.startswith('!'): # shell alias
2640 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2640 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2641 else:
2641 else:
2642 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2642 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2643 if ui.quiet or not full:
2643 if ui.quiet or not full:
2644 doc = doc.splitlines()[0]
2644 doc = doc.splitlines()[0]
2645 keep = ui.verbose and ['verbose'] or []
2645 keep = ui.verbose and ['verbose'] or []
2646 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2646 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2647 ui.write("\n%s\n" % formatted)
2647 ui.write("\n%s\n" % formatted)
2648 if pruned:
2648 if pruned:
2649 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2649 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2650
2650
2651 if not ui.quiet:
2651 if not ui.quiet:
2652 # options
2652 # options
2653 if entry[1]:
2653 if entry[1]:
2654 option_lists.append((_("options:\n"), entry[1]))
2654 option_lists.append((_("options:\n"), entry[1]))
2655
2655
2656 addglobalopts(False)
2656 addglobalopts(False)
2657
2657
2658 # check if this command shadows a non-trivial (multi-line)
2658 # check if this command shadows a non-trivial (multi-line)
2659 # extension help text
2659 # extension help text
2660 try:
2660 try:
2661 mod = extensions.find(name)
2661 mod = extensions.find(name)
2662 doc = gettext(mod.__doc__) or ''
2662 doc = gettext(mod.__doc__) or ''
2663 if '\n' in doc.strip():
2663 if '\n' in doc.strip():
2664 msg = _('use "hg help -e %s" to show help for '
2664 msg = _('use "hg help -e %s" to show help for '
2665 'the %s extension') % (name, name)
2665 'the %s extension') % (name, name)
2666 ui.write('\n%s\n' % msg)
2666 ui.write('\n%s\n' % msg)
2667 except KeyError:
2667 except KeyError:
2668 pass
2668 pass
2669
2669
2670 def helplist(header, select=None):
2670 def helplist(header, select=None):
2671 h = {}
2671 h = {}
2672 cmds = {}
2672 cmds = {}
2673 for c, e in table.iteritems():
2673 for c, e in table.iteritems():
2674 f = c.split("|", 1)[0]
2674 f = c.split("|", 1)[0]
2675 if select and not select(f):
2675 if select and not select(f):
2676 continue
2676 continue
2677 if (not select and name != 'shortlist' and
2677 if (not select and name != 'shortlist' and
2678 e[0].__module__ != __name__):
2678 e[0].__module__ != __name__):
2679 continue
2679 continue
2680 if name == "shortlist" and not f.startswith("^"):
2680 if name == "shortlist" and not f.startswith("^"):
2681 continue
2681 continue
2682 f = f.lstrip("^")
2682 f = f.lstrip("^")
2683 if not ui.debugflag and f.startswith("debug"):
2683 if not ui.debugflag and f.startswith("debug"):
2684 continue
2684 continue
2685 doc = e[0].__doc__
2685 doc = e[0].__doc__
2686 if doc and 'DEPRECATED' in doc and not ui.verbose:
2686 if doc and 'DEPRECATED' in doc and not ui.verbose:
2687 continue
2687 continue
2688 doc = gettext(doc)
2688 doc = gettext(doc)
2689 if not doc:
2689 if not doc:
2690 doc = _("(no help text available)")
2690 doc = _("(no help text available)")
2691 h[f] = doc.splitlines()[0].rstrip()
2691 h[f] = doc.splitlines()[0].rstrip()
2692 cmds[f] = c.lstrip("^")
2692 cmds[f] = c.lstrip("^")
2693
2693
2694 if not h:
2694 if not h:
2695 ui.status(_('no commands defined\n'))
2695 ui.status(_('no commands defined\n'))
2696 return
2696 return
2697
2697
2698 ui.status(header)
2698 ui.status(header)
2699 fns = sorted(h)
2699 fns = sorted(h)
2700 m = max(map(len, fns))
2700 m = max(map(len, fns))
2701 for f in fns:
2701 for f in fns:
2702 if ui.verbose:
2702 if ui.verbose:
2703 commands = cmds[f].replace("|",", ")
2703 commands = cmds[f].replace("|",", ")
2704 ui.write(" %s:\n %s\n"%(commands, h[f]))
2704 ui.write(" %s:\n %s\n"%(commands, h[f]))
2705 else:
2705 else:
2706 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2706 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2707 initindent=' %-*s ' % (m, f),
2707 initindent=' %-*s ' % (m, f),
2708 hangindent=' ' * (m + 4))))
2708 hangindent=' ' * (m + 4))))
2709
2709
2710 if not ui.quiet:
2710 if not ui.quiet:
2711 addglobalopts(True)
2711 addglobalopts(True)
2712
2712
2713 def helptopic(name):
2713 def helptopic(name):
2714 for names, header, doc in help.helptable:
2714 for names, header, doc in help.helptable:
2715 if name in names:
2715 if name in names:
2716 break
2716 break
2717 else:
2717 else:
2718 raise error.UnknownCommand(name)
2718 raise error.UnknownCommand(name)
2719
2719
2720 # description
2720 # description
2721 if not doc:
2721 if not doc:
2722 doc = _("(no help text available)")
2722 doc = _("(no help text available)")
2723 if hasattr(doc, '__call__'):
2723 if hasattr(doc, '__call__'):
2724 doc = doc()
2724 doc = doc()
2725
2725
2726 ui.write("%s\n\n" % header)
2726 ui.write("%s\n\n" % header)
2727 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2727 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2728 try:
2728 try:
2729 cmdutil.findcmd(name, table)
2729 cmdutil.findcmd(name, table)
2730 ui.write(_('\nuse "hg help -c %s" to see help for '
2730 ui.write(_('\nuse "hg help -c %s" to see help for '
2731 'the %s command\n') % (name, name))
2731 'the %s command\n') % (name, name))
2732 except error.UnknownCommand:
2732 except error.UnknownCommand:
2733 pass
2733 pass
2734
2734
2735 def helpext(name):
2735 def helpext(name):
2736 try:
2736 try:
2737 mod = extensions.find(name)
2737 mod = extensions.find(name)
2738 doc = gettext(mod.__doc__) or _('no help text available')
2738 doc = gettext(mod.__doc__) or _('no help text available')
2739 except KeyError:
2739 except KeyError:
2740 mod = None
2740 mod = None
2741 doc = extensions.disabledext(name)
2741 doc = extensions.disabledext(name)
2742 if not doc:
2742 if not doc:
2743 raise error.UnknownCommand(name)
2743 raise error.UnknownCommand(name)
2744
2744
2745 if '\n' not in doc:
2745 if '\n' not in doc:
2746 head, tail = doc, ""
2746 head, tail = doc, ""
2747 else:
2747 else:
2748 head, tail = doc.split('\n', 1)
2748 head, tail = doc.split('\n', 1)
2749 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2749 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2750 if tail:
2750 if tail:
2751 ui.write(minirst.format(tail, textwidth))
2751 ui.write(minirst.format(tail, textwidth))
2752 ui.status('\n\n')
2752 ui.status('\n\n')
2753
2753
2754 if mod:
2754 if mod:
2755 try:
2755 try:
2756 ct = mod.cmdtable
2756 ct = mod.cmdtable
2757 except AttributeError:
2757 except AttributeError:
2758 ct = {}
2758 ct = {}
2759 modcmds = set([c.split('|', 1)[0] for c in ct])
2759 modcmds = set([c.split('|', 1)[0] for c in ct])
2760 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2760 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2761 else:
2761 else:
2762 ui.write(_('use "hg help extensions" for information on enabling '
2762 ui.write(_('use "hg help extensions" for information on enabling '
2763 'extensions\n'))
2763 'extensions\n'))
2764
2764
2765 def helpextcmd(name):
2765 def helpextcmd(name):
2766 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2766 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2767 doc = gettext(mod.__doc__).splitlines()[0]
2767 doc = gettext(mod.__doc__).splitlines()[0]
2768
2768
2769 msg = help.listexts(_("'%s' is provided by the following "
2769 msg = help.listexts(_("'%s' is provided by the following "
2770 "extension:") % cmd, {ext: doc}, indent=4)
2770 "extension:") % cmd, {ext: doc}, indent=4)
2771 ui.write(minirst.format(msg, textwidth))
2771 ui.write(minirst.format(msg, textwidth))
2772 ui.write('\n\n')
2772 ui.write('\n\n')
2773 ui.write(_('use "hg help extensions" for information on enabling '
2773 ui.write(_('use "hg help extensions" for information on enabling '
2774 'extensions\n'))
2774 'extensions\n'))
2775
2775
2776 if name and name != 'shortlist':
2776 if name and name != 'shortlist':
2777 i = None
2777 i = None
2778 if unknowncmd:
2778 if unknowncmd:
2779 queries = (helpextcmd,)
2779 queries = (helpextcmd,)
2780 elif opts.get('extension'):
2780 elif opts.get('extension'):
2781 queries = (helpext,)
2781 queries = (helpext,)
2782 elif opts.get('command'):
2782 elif opts.get('command'):
2783 queries = (helpcmd,)
2783 queries = (helpcmd,)
2784 else:
2784 else:
2785 queries = (helptopic, helpcmd, helpext, helpextcmd)
2785 queries = (helptopic, helpcmd, helpext, helpextcmd)
2786 for f in queries:
2786 for f in queries:
2787 try:
2787 try:
2788 f(name)
2788 f(name)
2789 i = None
2789 i = None
2790 break
2790 break
2791 except error.UnknownCommand, inst:
2791 except error.UnknownCommand, inst:
2792 i = inst
2792 i = inst
2793 if i:
2793 if i:
2794 raise i
2794 raise i
2795
2795
2796 else:
2796 else:
2797 # program name
2797 # program name
2798 if ui.verbose or with_version:
2798 if ui.verbose or with_version:
2799 version_(ui)
2799 version_(ui)
2800 else:
2800 else:
2801 ui.status(_("Mercurial Distributed SCM\n"))
2801 ui.status(_("Mercurial Distributed SCM\n"))
2802 ui.status('\n')
2802 ui.status('\n')
2803
2803
2804 # list of commands
2804 # list of commands
2805 if name == "shortlist":
2805 if name == "shortlist":
2806 header = _('basic commands:\n\n')
2806 header = _('basic commands:\n\n')
2807 else:
2807 else:
2808 header = _('list of commands:\n\n')
2808 header = _('list of commands:\n\n')
2809
2809
2810 helplist(header)
2810 helplist(header)
2811 if name != 'shortlist':
2811 if name != 'shortlist':
2812 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2812 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2813 if text:
2813 if text:
2814 ui.write("\n%s\n" % minirst.format(text, textwidth))
2814 ui.write("\n%s\n" % minirst.format(text, textwidth))
2815
2815
2816 # list all option lists
2816 # list all option lists
2817 opt_output = []
2817 opt_output = []
2818 multioccur = False
2818 multioccur = False
2819 for title, options in option_lists:
2819 for title, options in option_lists:
2820 opt_output.append(("\n%s" % title, None))
2820 opt_output.append(("\n%s" % title, None))
2821 for option in options:
2821 for option in options:
2822 if len(option) == 5:
2822 if len(option) == 5:
2823 shortopt, longopt, default, desc, optlabel = option
2823 shortopt, longopt, default, desc, optlabel = option
2824 else:
2824 else:
2825 shortopt, longopt, default, desc = option
2825 shortopt, longopt, default, desc = option
2826 optlabel = _("VALUE") # default label
2826 optlabel = _("VALUE") # default label
2827
2827
2828 if _("DEPRECATED") in desc and not ui.verbose:
2828 if _("DEPRECATED") in desc and not ui.verbose:
2829 continue
2829 continue
2830 if isinstance(default, list):
2830 if isinstance(default, list):
2831 numqualifier = " %s [+]" % optlabel
2831 numqualifier = " %s [+]" % optlabel
2832 multioccur = True
2832 multioccur = True
2833 elif (default is not None) and not isinstance(default, bool):
2833 elif (default is not None) and not isinstance(default, bool):
2834 numqualifier = " %s" % optlabel
2834 numqualifier = " %s" % optlabel
2835 else:
2835 else:
2836 numqualifier = ""
2836 numqualifier = ""
2837 opt_output.append(("%2s%s" %
2837 opt_output.append(("%2s%s" %
2838 (shortopt and "-%s" % shortopt,
2838 (shortopt and "-%s" % shortopt,
2839 longopt and " --%s%s" %
2839 longopt and " --%s%s" %
2840 (longopt, numqualifier)),
2840 (longopt, numqualifier)),
2841 "%s%s" % (desc,
2841 "%s%s" % (desc,
2842 default
2842 default
2843 and _(" (default: %s)") % default
2843 and _(" (default: %s)") % default
2844 or "")))
2844 or "")))
2845 if multioccur:
2845 if multioccur:
2846 msg = _("\n[+] marked option can be specified multiple times")
2846 msg = _("\n[+] marked option can be specified multiple times")
2847 if ui.verbose and name != 'shortlist':
2847 if ui.verbose and name != 'shortlist':
2848 opt_output.append((msg, None))
2848 opt_output.append((msg, None))
2849 else:
2849 else:
2850 opt_output.insert(-1, (msg, None))
2850 opt_output.insert(-1, (msg, None))
2851
2851
2852 if not name:
2852 if not name:
2853 ui.write(_("\nadditional help topics:\n\n"))
2853 ui.write(_("\nadditional help topics:\n\n"))
2854 topics = []
2854 topics = []
2855 for names, header, doc in help.helptable:
2855 for names, header, doc in help.helptable:
2856 topics.append((sorted(names, key=len, reverse=True)[0], header))
2856 topics.append((sorted(names, key=len, reverse=True)[0], header))
2857 topics_len = max([len(s[0]) for s in topics])
2857 topics_len = max([len(s[0]) for s in topics])
2858 for t, desc in topics:
2858 for t, desc in topics:
2859 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2859 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2860
2860
2861 if opt_output:
2861 if opt_output:
2862 colwidth = encoding.colwidth
2862 colwidth = encoding.colwidth
2863 # normalize: (opt or message, desc or None, width of opt)
2863 # normalize: (opt or message, desc or None, width of opt)
2864 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2864 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2865 for opt, desc in opt_output]
2865 for opt, desc in opt_output]
2866 hanging = max([e[2] for e in entries])
2866 hanging = max([e[2] for e in entries])
2867 for opt, desc, width in entries:
2867 for opt, desc, width in entries:
2868 if desc:
2868 if desc:
2869 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2869 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2870 hangindent = ' ' * (hanging + 3)
2870 hangindent = ' ' * (hanging + 3)
2871 ui.write('%s\n' % (util.wrap(desc, textwidth,
2871 ui.write('%s\n' % (util.wrap(desc, textwidth,
2872 initindent=initindent,
2872 initindent=initindent,
2873 hangindent=hangindent)))
2873 hangindent=hangindent)))
2874 else:
2874 else:
2875 ui.write("%s\n" % opt)
2875 ui.write("%s\n" % opt)
2876
2876
2877 @command('identify|id',
2877 @command('identify|id',
2878 [('r', 'rev', '',
2878 [('r', 'rev', '',
2879 _('identify the specified revision'), _('REV')),
2879 _('identify the specified revision'), _('REV')),
2880 ('n', 'num', None, _('show local revision number')),
2880 ('n', 'num', None, _('show local revision number')),
2881 ('i', 'id', None, _('show global revision id')),
2881 ('i', 'id', None, _('show global revision id')),
2882 ('b', 'branch', None, _('show branch')),
2882 ('b', 'branch', None, _('show branch')),
2883 ('t', 'tags', None, _('show tags')),
2883 ('t', 'tags', None, _('show tags')),
2884 ('B', 'bookmarks', None, _('show bookmarks'))],
2884 ('B', 'bookmarks', None, _('show bookmarks'))],
2885 _('[-nibtB] [-r REV] [SOURCE]'))
2885 _('[-nibtB] [-r REV] [SOURCE]'))
2886 def identify(ui, repo, source=None, rev=None,
2886 def identify(ui, repo, source=None, rev=None,
2887 num=None, id=None, branch=None, tags=None, bookmarks=None):
2887 num=None, id=None, branch=None, tags=None, bookmarks=None):
2888 """identify the working copy or specified revision
2888 """identify the working copy or specified revision
2889
2889
2890 Print a summary identifying the repository state at REV using one or
2890 Print a summary identifying the repository state at REV using one or
2891 two parent hash identifiers, followed by a "+" if the working
2891 two parent hash identifiers, followed by a "+" if the working
2892 directory has uncommitted changes, the branch name (if not default),
2892 directory has uncommitted changes, the branch name (if not default),
2893 a list of tags, and a list of bookmarks.
2893 a list of tags, and a list of bookmarks.
2894
2894
2895 When REV is not given, print a summary of the current state of the
2895 When REV is not given, print a summary of the current state of the
2896 repository.
2896 repository.
2897
2897
2898 Specifying a path to a repository root or Mercurial bundle will
2898 Specifying a path to a repository root or Mercurial bundle will
2899 cause lookup to operate on that repository/bundle.
2899 cause lookup to operate on that repository/bundle.
2900
2900
2901 Returns 0 if successful.
2901 Returns 0 if successful.
2902 """
2902 """
2903
2903
2904 if not repo and not source:
2904 if not repo and not source:
2905 raise util.Abort(_("there is no Mercurial repository here "
2905 raise util.Abort(_("there is no Mercurial repository here "
2906 "(.hg not found)"))
2906 "(.hg not found)"))
2907
2907
2908 hexfunc = ui.debugflag and hex or short
2908 hexfunc = ui.debugflag and hex or short
2909 default = not (num or id or branch or tags or bookmarks)
2909 default = not (num or id or branch or tags or bookmarks)
2910 output = []
2910 output = []
2911 revs = []
2911 revs = []
2912
2912
2913 if source:
2913 if source:
2914 source, branches = hg.parseurl(ui.expandpath(source))
2914 source, branches = hg.parseurl(ui.expandpath(source))
2915 repo = hg.repository(ui, source)
2915 repo = hg.repository(ui, source)
2916 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2916 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2917
2917
2918 if not repo.local():
2918 if not repo.local():
2919 if num or branch or tags:
2919 if num or branch or tags:
2920 raise util.Abort(
2920 raise util.Abort(
2921 _("can't query remote revision number, branch, or tags"))
2921 _("can't query remote revision number, branch, or tags"))
2922 if not rev and revs:
2922 if not rev and revs:
2923 rev = revs[0]
2923 rev = revs[0]
2924 if not rev:
2924 if not rev:
2925 rev = "tip"
2925 rev = "tip"
2926
2926
2927 remoterev = repo.lookup(rev)
2927 remoterev = repo.lookup(rev)
2928 if default or id:
2928 if default or id:
2929 output = [hexfunc(remoterev)]
2929 output = [hexfunc(remoterev)]
2930
2930
2931 def getbms():
2931 def getbms():
2932 bms = []
2932 bms = []
2933
2933
2934 if 'bookmarks' in repo.listkeys('namespaces'):
2934 if 'bookmarks' in repo.listkeys('namespaces'):
2935 hexremoterev = hex(remoterev)
2935 hexremoterev = hex(remoterev)
2936 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
2936 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
2937 if bmr == hexremoterev]
2937 if bmr == hexremoterev]
2938
2938
2939 return bms
2939 return bms
2940
2940
2941 if bookmarks:
2941 if bookmarks:
2942 output.extend(getbms())
2942 output.extend(getbms())
2943 elif default and not ui.quiet:
2943 elif default and not ui.quiet:
2944 # multiple bookmarks for a single parent separated by '/'
2944 # multiple bookmarks for a single parent separated by '/'
2945 bm = '/'.join(getbms())
2945 bm = '/'.join(getbms())
2946 if bm:
2946 if bm:
2947 output.append(bm)
2947 output.append(bm)
2948 else:
2948 else:
2949 if not rev:
2949 if not rev:
2950 ctx = repo[None]
2950 ctx = repo[None]
2951 parents = ctx.parents()
2951 parents = ctx.parents()
2952 changed = ""
2952 changed = ""
2953 if default or id or num:
2953 if default or id or num:
2954 changed = util.any(repo.status()) and "+" or ""
2954 changed = util.any(repo.status()) and "+" or ""
2955 if default or id:
2955 if default or id:
2956 output = ["%s%s" %
2956 output = ["%s%s" %
2957 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2957 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2958 if num:
2958 if num:
2959 output.append("%s%s" %
2959 output.append("%s%s" %
2960 ('+'.join([str(p.rev()) for p in parents]), changed))
2960 ('+'.join([str(p.rev()) for p in parents]), changed))
2961 else:
2961 else:
2962 ctx = scmutil.revsingle(repo, rev)
2962 ctx = scmutil.revsingle(repo, rev)
2963 if default or id:
2963 if default or id:
2964 output = [hexfunc(ctx.node())]
2964 output = [hexfunc(ctx.node())]
2965 if num:
2965 if num:
2966 output.append(str(ctx.rev()))
2966 output.append(str(ctx.rev()))
2967
2967
2968 if default and not ui.quiet:
2968 if default and not ui.quiet:
2969 b = ctx.branch()
2969 b = ctx.branch()
2970 if b != 'default':
2970 if b != 'default':
2971 output.append("(%s)" % b)
2971 output.append("(%s)" % b)
2972
2972
2973 # multiple tags for a single parent separated by '/'
2973 # multiple tags for a single parent separated by '/'
2974 t = '/'.join(ctx.tags())
2974 t = '/'.join(ctx.tags())
2975 if t:
2975 if t:
2976 output.append(t)
2976 output.append(t)
2977
2977
2978 # multiple bookmarks for a single parent separated by '/'
2978 # multiple bookmarks for a single parent separated by '/'
2979 bm = '/'.join(ctx.bookmarks())
2979 bm = '/'.join(ctx.bookmarks())
2980 if bm:
2980 if bm:
2981 output.append(bm)
2981 output.append(bm)
2982 else:
2982 else:
2983 if branch:
2983 if branch:
2984 output.append(ctx.branch())
2984 output.append(ctx.branch())
2985
2985
2986 if tags:
2986 if tags:
2987 output.extend(ctx.tags())
2987 output.extend(ctx.tags())
2988
2988
2989 if bookmarks:
2989 if bookmarks:
2990 output.extend(ctx.bookmarks())
2990 output.extend(ctx.bookmarks())
2991
2991
2992 ui.write("%s\n" % ' '.join(output))
2992 ui.write("%s\n" % ' '.join(output))
2993
2993
2994 @command('import|patch',
2994 @command('import|patch',
2995 [('p', 'strip', 1,
2995 [('p', 'strip', 1,
2996 _('directory strip option for patch. This has the same '
2996 _('directory strip option for patch. This has the same '
2997 'meaning as the corresponding patch option'), _('NUM')),
2997 'meaning as the corresponding patch option'), _('NUM')),
2998 ('b', 'base', '', _('base path'), _('PATH')),
2998 ('b', 'base', '', _('base path'), _('PATH')),
2999 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
2999 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3000 ('', 'no-commit', None,
3000 ('', 'no-commit', None,
3001 _("don't commit, just update the working directory")),
3001 _("don't commit, just update the working directory")),
3002 ('', 'exact', None,
3002 ('', 'exact', None,
3003 _('apply patch to the nodes from which it was generated')),
3003 _('apply patch to the nodes from which it was generated')),
3004 ('', 'import-branch', None,
3004 ('', 'import-branch', None,
3005 _('use any branch information in patch (implied by --exact)'))] +
3005 _('use any branch information in patch (implied by --exact)'))] +
3006 commitopts + commitopts2 + similarityopts,
3006 commitopts + commitopts2 + similarityopts,
3007 _('[OPTION]... PATCH...'))
3007 _('[OPTION]... PATCH...'))
3008 def import_(ui, repo, patch1, *patches, **opts):
3008 def import_(ui, repo, patch1, *patches, **opts):
3009 """import an ordered set of patches
3009 """import an ordered set of patches
3010
3010
3011 Import a list of patches and commit them individually (unless
3011 Import a list of patches and commit them individually (unless
3012 --no-commit is specified).
3012 --no-commit is specified).
3013
3013
3014 If there are outstanding changes in the working directory, import
3014 If there are outstanding changes in the working directory, import
3015 will abort unless given the -f/--force flag.
3015 will abort unless given the -f/--force flag.
3016
3016
3017 You can import a patch straight from a mail message. Even patches
3017 You can import a patch straight from a mail message. Even patches
3018 as attachments work (to use the body part, it must have type
3018 as attachments work (to use the body part, it must have type
3019 text/plain or text/x-patch). From and Subject headers of email
3019 text/plain or text/x-patch). From and Subject headers of email
3020 message are used as default committer and commit message. All
3020 message are used as default committer and commit message. All
3021 text/plain body parts before first diff are added to commit
3021 text/plain body parts before first diff are added to commit
3022 message.
3022 message.
3023
3023
3024 If the imported patch was generated by :hg:`export`, user and
3024 If the imported patch was generated by :hg:`export`, user and
3025 description from patch override values from message headers and
3025 description from patch override values from message headers and
3026 body. Values given on command line with -m/--message and -u/--user
3026 body. Values given on command line with -m/--message and -u/--user
3027 override these.
3027 override these.
3028
3028
3029 If --exact is specified, import will set the working directory to
3029 If --exact is specified, import will set the working directory to
3030 the parent of each patch before applying it, and will abort if the
3030 the parent of each patch before applying it, and will abort if the
3031 resulting changeset has a different ID than the one recorded in
3031 resulting changeset has a different ID than the one recorded in
3032 the patch. This may happen due to character set problems or other
3032 the patch. This may happen due to character set problems or other
3033 deficiencies in the text patch format.
3033 deficiencies in the text patch format.
3034
3034
3035 With -s/--similarity, hg will attempt to discover renames and
3035 With -s/--similarity, hg will attempt to discover renames and
3036 copies in the patch in the same way as 'addremove'.
3036 copies in the patch in the same way as 'addremove'.
3037
3037
3038 To read a patch from standard input, use "-" as the patch name. If
3038 To read a patch from standard input, use "-" as the patch name. If
3039 a URL is specified, the patch will be downloaded from it.
3039 a URL is specified, the patch will be downloaded from it.
3040 See :hg:`help dates` for a list of formats valid for -d/--date.
3040 See :hg:`help dates` for a list of formats valid for -d/--date.
3041
3041
3042 Returns 0 on success.
3042 Returns 0 on success.
3043 """
3043 """
3044 patches = (patch1,) + patches
3044 patches = (patch1,) + patches
3045
3045
3046 date = opts.get('date')
3046 date = opts.get('date')
3047 if date:
3047 if date:
3048 opts['date'] = util.parsedate(date)
3048 opts['date'] = util.parsedate(date)
3049
3049
3050 try:
3050 try:
3051 sim = float(opts.get('similarity') or 0)
3051 sim = float(opts.get('similarity') or 0)
3052 except ValueError:
3052 except ValueError:
3053 raise util.Abort(_('similarity must be a number'))
3053 raise util.Abort(_('similarity must be a number'))
3054 if sim < 0 or sim > 100:
3054 if sim < 0 or sim > 100:
3055 raise util.Abort(_('similarity must be between 0 and 100'))
3055 raise util.Abort(_('similarity must be between 0 and 100'))
3056
3056
3057 if opts.get('exact') or not opts.get('force'):
3057 if opts.get('exact') or not opts.get('force'):
3058 cmdutil.bailifchanged(repo)
3058 cmdutil.bailifchanged(repo)
3059
3059
3060 d = opts["base"]
3060 d = opts["base"]
3061 strip = opts["strip"]
3061 strip = opts["strip"]
3062 wlock = lock = None
3062 wlock = lock = None
3063 msgs = []
3063 msgs = []
3064
3064
3065 def tryone(ui, hunk):
3065 def tryone(ui, hunk):
3066 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3066 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3067 patch.extract(ui, hunk)
3067 patch.extract(ui, hunk)
3068
3068
3069 if not tmpname:
3069 if not tmpname:
3070 return None
3070 return None
3071 commitid = _('to working directory')
3071 commitid = _('to working directory')
3072
3072
3073 try:
3073 try:
3074 cmdline_message = cmdutil.logmessage(opts)
3074 cmdline_message = cmdutil.logmessage(opts)
3075 if cmdline_message:
3075 if cmdline_message:
3076 # pickup the cmdline msg
3076 # pickup the cmdline msg
3077 message = cmdline_message
3077 message = cmdline_message
3078 elif message:
3078 elif message:
3079 # pickup the patch msg
3079 # pickup the patch msg
3080 message = message.strip()
3080 message = message.strip()
3081 else:
3081 else:
3082 # launch the editor
3082 # launch the editor
3083 message = None
3083 message = None
3084 ui.debug('message:\n%s\n' % message)
3084 ui.debug('message:\n%s\n' % message)
3085
3085
3086 wp = repo.parents()
3086 wp = repo.parents()
3087 if opts.get('exact'):
3087 if opts.get('exact'):
3088 if not nodeid or not p1:
3088 if not nodeid or not p1:
3089 raise util.Abort(_('not a Mercurial patch'))
3089 raise util.Abort(_('not a Mercurial patch'))
3090 p1 = repo.lookup(p1)
3090 p1 = repo.lookup(p1)
3091 p2 = repo.lookup(p2 or hex(nullid))
3091 p2 = repo.lookup(p2 or hex(nullid))
3092
3092
3093 if p1 != wp[0].node():
3093 if p1 != wp[0].node():
3094 hg.clean(repo, p1)
3094 hg.clean(repo, p1)
3095 repo.dirstate.setparents(p1, p2)
3095 repo.dirstate.setparents(p1, p2)
3096 elif p2:
3096 elif p2:
3097 try:
3097 try:
3098 p1 = repo.lookup(p1)
3098 p1 = repo.lookup(p1)
3099 p2 = repo.lookup(p2)
3099 p2 = repo.lookup(p2)
3100 if p1 == wp[0].node():
3100 if p1 == wp[0].node():
3101 repo.dirstate.setparents(p1, p2)
3101 repo.dirstate.setparents(p1, p2)
3102 except error.RepoError:
3102 except error.RepoError:
3103 pass
3103 pass
3104 if opts.get('exact') or opts.get('import_branch'):
3104 if opts.get('exact') or opts.get('import_branch'):
3105 repo.dirstate.setbranch(branch or 'default')
3105 repo.dirstate.setbranch(branch or 'default')
3106
3106
3107 files = {}
3107 files = {}
3108 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3108 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3109 eolmode=None, similarity=sim / 100.0)
3109 eolmode=None, similarity=sim / 100.0)
3110 files = list(files)
3110 files = list(files)
3111 if opts.get('no_commit'):
3111 if opts.get('no_commit'):
3112 if message:
3112 if message:
3113 msgs.append(message)
3113 msgs.append(message)
3114 else:
3114 else:
3115 if opts.get('exact'):
3115 if opts.get('exact'):
3116 m = None
3116 m = None
3117 else:
3117 else:
3118 m = scmutil.matchfiles(repo, files or [])
3118 m = scmutil.matchfiles(repo, files or [])
3119 n = repo.commit(message, opts.get('user') or user,
3119 n = repo.commit(message, opts.get('user') or user,
3120 opts.get('date') or date, match=m,
3120 opts.get('date') or date, match=m,
3121 editor=cmdutil.commiteditor)
3121 editor=cmdutil.commiteditor)
3122 if opts.get('exact'):
3122 if opts.get('exact'):
3123 if hex(n) != nodeid:
3123 if hex(n) != nodeid:
3124 repo.rollback()
3124 repo.rollback()
3125 raise util.Abort(_('patch is damaged'
3125 raise util.Abort(_('patch is damaged'
3126 ' or loses information'))
3126 ' or loses information'))
3127 # Force a dirstate write so that the next transaction
3127 # Force a dirstate write so that the next transaction
3128 # backups an up-do-date file.
3128 # backups an up-do-date file.
3129 repo.dirstate.write()
3129 repo.dirstate.write()
3130 if n:
3130 if n:
3131 commitid = short(n)
3131 commitid = short(n)
3132
3132
3133 return commitid
3133 return commitid
3134 finally:
3134 finally:
3135 os.unlink(tmpname)
3135 os.unlink(tmpname)
3136
3136
3137 try:
3137 try:
3138 wlock = repo.wlock()
3138 wlock = repo.wlock()
3139 lock = repo.lock()
3139 lock = repo.lock()
3140 lastcommit = None
3140 lastcommit = None
3141 for p in patches:
3141 for p in patches:
3142 pf = os.path.join(d, p)
3142 pf = os.path.join(d, p)
3143
3143
3144 if pf == '-':
3144 if pf == '-':
3145 ui.status(_("applying patch from stdin\n"))
3145 ui.status(_("applying patch from stdin\n"))
3146 pf = sys.stdin
3146 pf = sys.stdin
3147 else:
3147 else:
3148 ui.status(_("applying %s\n") % p)
3148 ui.status(_("applying %s\n") % p)
3149 pf = url.open(ui, pf)
3149 pf = url.open(ui, pf)
3150
3150
3151 haspatch = False
3151 haspatch = False
3152 for hunk in patch.split(pf):
3152 for hunk in patch.split(pf):
3153 commitid = tryone(ui, hunk)
3153 commitid = tryone(ui, hunk)
3154 if commitid:
3154 if commitid:
3155 haspatch = True
3155 haspatch = True
3156 if lastcommit:
3156 if lastcommit:
3157 ui.status(_('applied %s\n') % lastcommit)
3157 ui.status(_('applied %s\n') % lastcommit)
3158 lastcommit = commitid
3158 lastcommit = commitid
3159
3159
3160 if not haspatch:
3160 if not haspatch:
3161 raise util.Abort(_('no diffs found'))
3161 raise util.Abort(_('no diffs found'))
3162
3162
3163 if msgs:
3163 if msgs:
3164 repo.opener.write('last-message.txt', '\n* * *\n'.join(msgs))
3164 repo.opener.write('last-message.txt', '\n* * *\n'.join(msgs))
3165 finally:
3165 finally:
3166 release(lock, wlock)
3166 release(lock, wlock)
3167
3167
3168 @command('incoming|in',
3168 @command('incoming|in',
3169 [('f', 'force', None,
3169 [('f', 'force', None,
3170 _('run even if remote repository is unrelated')),
3170 _('run even if remote repository is unrelated')),
3171 ('n', 'newest-first', None, _('show newest record first')),
3171 ('n', 'newest-first', None, _('show newest record first')),
3172 ('', 'bundle', '',
3172 ('', 'bundle', '',
3173 _('file to store the bundles into'), _('FILE')),
3173 _('file to store the bundles into'), _('FILE')),
3174 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3174 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3175 ('B', 'bookmarks', False, _("compare bookmarks")),
3175 ('B', 'bookmarks', False, _("compare bookmarks")),
3176 ('b', 'branch', [],
3176 ('b', 'branch', [],
3177 _('a specific branch you would like to pull'), _('BRANCH')),
3177 _('a specific branch you would like to pull'), _('BRANCH')),
3178 ] + logopts + remoteopts + subrepoopts,
3178 ] + logopts + remoteopts + subrepoopts,
3179 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3179 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3180 def incoming(ui, repo, source="default", **opts):
3180 def incoming(ui, repo, source="default", **opts):
3181 """show new changesets found in source
3181 """show new changesets found in source
3182
3182
3183 Show new changesets found in the specified path/URL or the default
3183 Show new changesets found in the specified path/URL or the default
3184 pull location. These are the changesets that would have been pulled
3184 pull location. These are the changesets that would have been pulled
3185 if a pull at the time you issued this command.
3185 if a pull at the time you issued this command.
3186
3186
3187 For remote repository, using --bundle avoids downloading the
3187 For remote repository, using --bundle avoids downloading the
3188 changesets twice if the incoming is followed by a pull.
3188 changesets twice if the incoming is followed by a pull.
3189
3189
3190 See pull for valid source format details.
3190 See pull for valid source format details.
3191
3191
3192 Returns 0 if there are incoming changes, 1 otherwise.
3192 Returns 0 if there are incoming changes, 1 otherwise.
3193 """
3193 """
3194 if opts.get('bundle') and opts.get('subrepos'):
3194 if opts.get('bundle') and opts.get('subrepos'):
3195 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3195 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3196
3196
3197 if opts.get('bookmarks'):
3197 if opts.get('bookmarks'):
3198 source, branches = hg.parseurl(ui.expandpath(source),
3198 source, branches = hg.parseurl(ui.expandpath(source),
3199 opts.get('branch'))
3199 opts.get('branch'))
3200 other = hg.repository(hg.remoteui(repo, opts), source)
3200 other = hg.repository(hg.remoteui(repo, opts), source)
3201 if 'bookmarks' not in other.listkeys('namespaces'):
3201 if 'bookmarks' not in other.listkeys('namespaces'):
3202 ui.warn(_("remote doesn't support bookmarks\n"))
3202 ui.warn(_("remote doesn't support bookmarks\n"))
3203 return 0
3203 return 0
3204 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3204 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3205 return bookmarks.diff(ui, repo, other)
3205 return bookmarks.diff(ui, repo, other)
3206
3206
3207 repo._subtoppath = ui.expandpath(source)
3207 repo._subtoppath = ui.expandpath(source)
3208 try:
3208 try:
3209 return hg.incoming(ui, repo, source, opts)
3209 return hg.incoming(ui, repo, source, opts)
3210 finally:
3210 finally:
3211 del repo._subtoppath
3211 del repo._subtoppath
3212
3212
3213
3213
3214 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3214 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3215 def init(ui, dest=".", **opts):
3215 def init(ui, dest=".", **opts):
3216 """create a new repository in the given directory
3216 """create a new repository in the given directory
3217
3217
3218 Initialize a new repository in the given directory. If the given
3218 Initialize a new repository in the given directory. If the given
3219 directory does not exist, it will be created.
3219 directory does not exist, it will be created.
3220
3220
3221 If no directory is given, the current directory is used.
3221 If no directory is given, the current directory is used.
3222
3222
3223 It is possible to specify an ``ssh://`` URL as the destination.
3223 It is possible to specify an ``ssh://`` URL as the destination.
3224 See :hg:`help urls` for more information.
3224 See :hg:`help urls` for more information.
3225
3225
3226 Returns 0 on success.
3226 Returns 0 on success.
3227 """
3227 """
3228 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=True)
3228 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=True)
3229
3229
3230 @command('locate',
3230 @command('locate',
3231 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3231 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3232 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3232 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3233 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3233 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3234 ] + walkopts,
3234 ] + walkopts,
3235 _('[OPTION]... [PATTERN]...'))
3235 _('[OPTION]... [PATTERN]...'))
3236 def locate(ui, repo, *pats, **opts):
3236 def locate(ui, repo, *pats, **opts):
3237 """locate files matching specific patterns
3237 """locate files matching specific patterns
3238
3238
3239 Print files under Mercurial control in the working directory whose
3239 Print files under Mercurial control in the working directory whose
3240 names match the given patterns.
3240 names match the given patterns.
3241
3241
3242 By default, this command searches all directories in the working
3242 By default, this command searches all directories in the working
3243 directory. To search just the current directory and its
3243 directory. To search just the current directory and its
3244 subdirectories, use "--include .".
3244 subdirectories, use "--include .".
3245
3245
3246 If no patterns are given to match, this command prints the names
3246 If no patterns are given to match, this command prints the names
3247 of all files under Mercurial control in the working directory.
3247 of all files under Mercurial control in the working directory.
3248
3248
3249 If you want to feed the output of this command into the "xargs"
3249 If you want to feed the output of this command into the "xargs"
3250 command, use the -0 option to both this command and "xargs". This
3250 command, use the -0 option to both this command and "xargs". This
3251 will avoid the problem of "xargs" treating single filenames that
3251 will avoid the problem of "xargs" treating single filenames that
3252 contain whitespace as multiple filenames.
3252 contain whitespace as multiple filenames.
3253
3253
3254 Returns 0 if a match is found, 1 otherwise.
3254 Returns 0 if a match is found, 1 otherwise.
3255 """
3255 """
3256 end = opts.get('print0') and '\0' or '\n'
3256 end = opts.get('print0') and '\0' or '\n'
3257 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3257 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3258
3258
3259 ret = 1
3259 ret = 1
3260 m = scmutil.match(repo, pats, opts, default='relglob')
3260 m = scmutil.match(repo, pats, opts, default='relglob')
3261 m.bad = lambda x, y: False
3261 m.bad = lambda x, y: False
3262 for abs in repo[rev].walk(m):
3262 for abs in repo[rev].walk(m):
3263 if not rev and abs not in repo.dirstate:
3263 if not rev and abs not in repo.dirstate:
3264 continue
3264 continue
3265 if opts.get('fullpath'):
3265 if opts.get('fullpath'):
3266 ui.write(repo.wjoin(abs), end)
3266 ui.write(repo.wjoin(abs), end)
3267 else:
3267 else:
3268 ui.write(((pats and m.rel(abs)) or abs), end)
3268 ui.write(((pats and m.rel(abs)) or abs), end)
3269 ret = 0
3269 ret = 0
3270
3270
3271 return ret
3271 return ret
3272
3272
3273 @command('^log|history',
3273 @command('^log|history',
3274 [('f', 'follow', None,
3274 [('f', 'follow', None,
3275 _('follow changeset history, or file history across copies and renames')),
3275 _('follow changeset history, or file history across copies and renames')),
3276 ('', 'follow-first', None,
3276 ('', 'follow-first', None,
3277 _('only follow the first parent of merge changesets')),
3277 _('only follow the first parent of merge changesets')),
3278 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3278 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3279 ('C', 'copies', None, _('show copied files')),
3279 ('C', 'copies', None, _('show copied files')),
3280 ('k', 'keyword', [],
3280 ('k', 'keyword', [],
3281 _('do case-insensitive search for a given text'), _('TEXT')),
3281 _('do case-insensitive search for a given text'), _('TEXT')),
3282 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3282 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3283 ('', 'removed', None, _('include revisions where files were removed')),
3283 ('', 'removed', None, _('include revisions where files were removed')),
3284 ('m', 'only-merges', None, _('show only merges')),
3284 ('m', 'only-merges', None, _('show only merges')),
3285 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3285 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3286 ('', 'only-branch', [],
3286 ('', 'only-branch', [],
3287 _('show only changesets within the given named branch (DEPRECATED)'),
3287 _('show only changesets within the given named branch (DEPRECATED)'),
3288 _('BRANCH')),
3288 _('BRANCH')),
3289 ('b', 'branch', [],
3289 ('b', 'branch', [],
3290 _('show changesets within the given named branch'), _('BRANCH')),
3290 _('show changesets within the given named branch'), _('BRANCH')),
3291 ('P', 'prune', [],
3291 ('P', 'prune', [],
3292 _('do not display revision or any of its ancestors'), _('REV')),
3292 _('do not display revision or any of its ancestors'), _('REV')),
3293 ] + logopts + walkopts,
3293 ] + logopts + walkopts,
3294 _('[OPTION]... [FILE]'))
3294 _('[OPTION]... [FILE]'))
3295 def log(ui, repo, *pats, **opts):
3295 def log(ui, repo, *pats, **opts):
3296 """show revision history of entire repository or files
3296 """show revision history of entire repository or files
3297
3297
3298 Print the revision history of the specified files or the entire
3298 Print the revision history of the specified files or the entire
3299 project.
3299 project.
3300
3300
3301 File history is shown without following rename or copy history of
3301 File history is shown without following rename or copy history of
3302 files. Use -f/--follow with a filename to follow history across
3302 files. Use -f/--follow with a filename to follow history across
3303 renames and copies. --follow without a filename will only show
3303 renames and copies. --follow without a filename will only show
3304 ancestors or descendants of the starting revision. --follow-first
3304 ancestors or descendants of the starting revision. --follow-first
3305 only follows the first parent of merge revisions.
3305 only follows the first parent of merge revisions.
3306
3306
3307 If no revision range is specified, the default is ``tip:0`` unless
3307 If no revision range is specified, the default is ``tip:0`` unless
3308 --follow is set, in which case the working directory parent is
3308 --follow is set, in which case the working directory parent is
3309 used as the starting revision. You can specify a revision set for
3309 used as the starting revision. You can specify a revision set for
3310 log, see :hg:`help revsets` for more information.
3310 log, see :hg:`help revsets` for more information.
3311
3311
3312 See :hg:`help dates` for a list of formats valid for -d/--date.
3312 See :hg:`help dates` for a list of formats valid for -d/--date.
3313
3313
3314 By default this command prints revision number and changeset id,
3314 By default this command prints revision number and changeset id,
3315 tags, non-trivial parents, user, date and time, and a summary for
3315 tags, non-trivial parents, user, date and time, and a summary for
3316 each commit. When the -v/--verbose switch is used, the list of
3316 each commit. When the -v/--verbose switch is used, the list of
3317 changed files and full commit message are shown.
3317 changed files and full commit message are shown.
3318
3318
3319 .. note::
3319 .. note::
3320 log -p/--patch may generate unexpected diff output for merge
3320 log -p/--patch may generate unexpected diff output for merge
3321 changesets, as it will only compare the merge changeset against
3321 changesets, as it will only compare the merge changeset against
3322 its first parent. Also, only files different from BOTH parents
3322 its first parent. Also, only files different from BOTH parents
3323 will appear in files:.
3323 will appear in files:.
3324
3324
3325 Returns 0 on success.
3325 Returns 0 on success.
3326 """
3326 """
3327
3327
3328 matchfn = scmutil.match(repo, pats, opts)
3328 matchfn = scmutil.match(repo, pats, opts)
3329 limit = cmdutil.loglimit(opts)
3329 limit = cmdutil.loglimit(opts)
3330 count = 0
3330 count = 0
3331
3331
3332 endrev = None
3332 endrev = None
3333 if opts.get('copies') and opts.get('rev'):
3333 if opts.get('copies') and opts.get('rev'):
3334 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3334 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3335
3335
3336 df = False
3336 df = False
3337 if opts["date"]:
3337 if opts["date"]:
3338 df = util.matchdate(opts["date"])
3338 df = util.matchdate(opts["date"])
3339
3339
3340 branches = opts.get('branch', []) + opts.get('only_branch', [])
3340 branches = opts.get('branch', []) + opts.get('only_branch', [])
3341 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3341 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3342
3342
3343 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3343 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3344 def prep(ctx, fns):
3344 def prep(ctx, fns):
3345 rev = ctx.rev()
3345 rev = ctx.rev()
3346 parents = [p for p in repo.changelog.parentrevs(rev)
3346 parents = [p for p in repo.changelog.parentrevs(rev)
3347 if p != nullrev]
3347 if p != nullrev]
3348 if opts.get('no_merges') and len(parents) == 2:
3348 if opts.get('no_merges') and len(parents) == 2:
3349 return
3349 return
3350 if opts.get('only_merges') and len(parents) != 2:
3350 if opts.get('only_merges') and len(parents) != 2:
3351 return
3351 return
3352 if opts.get('branch') and ctx.branch() not in opts['branch']:
3352 if opts.get('branch') and ctx.branch() not in opts['branch']:
3353 return
3353 return
3354 if df and not df(ctx.date()[0]):
3354 if df and not df(ctx.date()[0]):
3355 return
3355 return
3356 if opts['user'] and not [k for k in opts['user']
3356 if opts['user'] and not [k for k in opts['user']
3357 if k.lower() in ctx.user().lower()]:
3357 if k.lower() in ctx.user().lower()]:
3358 return
3358 return
3359 if opts.get('keyword'):
3359 if opts.get('keyword'):
3360 for k in [kw.lower() for kw in opts['keyword']]:
3360 for k in [kw.lower() for kw in opts['keyword']]:
3361 if (k in ctx.user().lower() or
3361 if (k in ctx.user().lower() or
3362 k in ctx.description().lower() or
3362 k in ctx.description().lower() or
3363 k in " ".join(ctx.files()).lower()):
3363 k in " ".join(ctx.files()).lower()):
3364 break
3364 break
3365 else:
3365 else:
3366 return
3366 return
3367
3367
3368 copies = None
3368 copies = None
3369 if opts.get('copies') and rev:
3369 if opts.get('copies') and rev:
3370 copies = []
3370 copies = []
3371 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3371 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3372 for fn in ctx.files():
3372 for fn in ctx.files():
3373 rename = getrenamed(fn, rev)
3373 rename = getrenamed(fn, rev)
3374 if rename:
3374 if rename:
3375 copies.append((fn, rename[0]))
3375 copies.append((fn, rename[0]))
3376
3376
3377 revmatchfn = None
3377 revmatchfn = None
3378 if opts.get('patch') or opts.get('stat'):
3378 if opts.get('patch') or opts.get('stat'):
3379 if opts.get('follow') or opts.get('follow_first'):
3379 if opts.get('follow') or opts.get('follow_first'):
3380 # note: this might be wrong when following through merges
3380 # note: this might be wrong when following through merges
3381 revmatchfn = scmutil.match(repo, fns, default='path')
3381 revmatchfn = scmutil.match(repo, fns, default='path')
3382 else:
3382 else:
3383 revmatchfn = matchfn
3383 revmatchfn = matchfn
3384
3384
3385 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3385 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3386
3386
3387 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3387 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3388 if count == limit:
3388 if count == limit:
3389 break
3389 break
3390 if displayer.flush(ctx.rev()):
3390 if displayer.flush(ctx.rev()):
3391 count += 1
3391 count += 1
3392 displayer.close()
3392 displayer.close()
3393
3393
3394 @command('manifest',
3394 @command('manifest',
3395 [('r', 'rev', '', _('revision to display'), _('REV'))],
3395 [('r', 'rev', '', _('revision to display'), _('REV')),
3396 ('', 'all', False, _("list files from all revisions"))],
3396 _('[-r REV]'))
3397 _('[-r REV]'))
3397 def manifest(ui, repo, node=None, rev=None):
3398 def manifest(ui, repo, node=None, rev=None, **opts):
3398 """output the current or given revision of the project manifest
3399 """output the current or given revision of the project manifest
3399
3400
3400 Print a list of version controlled files for the given revision.
3401 Print a list of version controlled files for the given revision.
3401 If no revision is given, the first parent of the working directory
3402 If no revision is given, the first parent of the working directory
3402 is used, or the null revision if no revision is checked out.
3403 is used, or the null revision if no revision is checked out.
3403
3404
3404 With -v, print file permissions, symlink and executable bits.
3405 With -v, print file permissions, symlink and executable bits.
3405 With --debug, print file revision hashes.
3406 With --debug, print file revision hashes.
3406
3407
3408 If option --all is specified, the list of all files from all revisions
3409 is printed. This includes deleted and renamed files.
3410
3407 Returns 0 on success.
3411 Returns 0 on success.
3408 """
3412 """
3413 if opts.get('all'):
3414 if rev or node:
3415 raise util.Abort(_("can't specify a revision with --all"))
3416
3417 res = []
3418 prefix = "data/"
3419 suffix = ".i"
3420 plen = len(prefix)
3421 slen = len(suffix)
3422 lock = repo.lock()
3423 try:
3424 for fn, b, size in repo.store.datafiles():
3425 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3426 res.append(fn[plen:-slen])
3427 finally:
3428 lock.release()
3429 for f in sorted(res):
3430 ui.write("%s\n" % f)
3431 return
3409
3432
3410 if rev and node:
3433 if rev and node:
3411 raise util.Abort(_("please specify just one revision"))
3434 raise util.Abort(_("please specify just one revision"))
3412
3435
3413 if not node:
3436 if not node:
3414 node = rev
3437 node = rev
3415
3438
3416 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3439 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3417 ctx = scmutil.revsingle(repo, node)
3440 ctx = scmutil.revsingle(repo, node)
3418 for f in ctx:
3441 for f in ctx:
3419 if ui.debugflag:
3442 if ui.debugflag:
3420 ui.write("%40s " % hex(ctx.manifest()[f]))
3443 ui.write("%40s " % hex(ctx.manifest()[f]))
3421 if ui.verbose:
3444 if ui.verbose:
3422 ui.write(decor[ctx.flags(f)])
3445 ui.write(decor[ctx.flags(f)])
3423 ui.write("%s\n" % f)
3446 ui.write("%s\n" % f)
3424
3447
3425 @command('^merge',
3448 @command('^merge',
3426 [('f', 'force', None, _('force a merge with outstanding changes')),
3449 [('f', 'force', None, _('force a merge with outstanding changes')),
3427 ('t', 'tool', '', _('specify merge tool')),
3450 ('t', 'tool', '', _('specify merge tool')),
3428 ('r', 'rev', '', _('revision to merge'), _('REV')),
3451 ('r', 'rev', '', _('revision to merge'), _('REV')),
3429 ('P', 'preview', None,
3452 ('P', 'preview', None,
3430 _('review revisions to merge (no merge is performed)'))],
3453 _('review revisions to merge (no merge is performed)'))],
3431 _('[-P] [-f] [[-r] REV]'))
3454 _('[-P] [-f] [[-r] REV]'))
3432 def merge(ui, repo, node=None, **opts):
3455 def merge(ui, repo, node=None, **opts):
3433 """merge working directory with another revision
3456 """merge working directory with another revision
3434
3457
3435 The current working directory is updated with all changes made in
3458 The current working directory is updated with all changes made in
3436 the requested revision since the last common predecessor revision.
3459 the requested revision since the last common predecessor revision.
3437
3460
3438 Files that changed between either parent are marked as changed for
3461 Files that changed between either parent are marked as changed for
3439 the next commit and a commit must be performed before any further
3462 the next commit and a commit must be performed before any further
3440 updates to the repository are allowed. The next commit will have
3463 updates to the repository are allowed. The next commit will have
3441 two parents.
3464 two parents.
3442
3465
3443 ``--tool`` can be used to specify the merge tool used for file
3466 ``--tool`` can be used to specify the merge tool used for file
3444 merges. It overrides the HGMERGE environment variable and your
3467 merges. It overrides the HGMERGE environment variable and your
3445 configuration files. See :hg:`help merge-tools` for options.
3468 configuration files. See :hg:`help merge-tools` for options.
3446
3469
3447 If no revision is specified, the working directory's parent is a
3470 If no revision is specified, the working directory's parent is a
3448 head revision, and the current branch contains exactly one other
3471 head revision, and the current branch contains exactly one other
3449 head, the other head is merged with by default. Otherwise, an
3472 head, the other head is merged with by default. Otherwise, an
3450 explicit revision with which to merge with must be provided.
3473 explicit revision with which to merge with must be provided.
3451
3474
3452 :hg:`resolve` must be used to resolve unresolved files.
3475 :hg:`resolve` must be used to resolve unresolved files.
3453
3476
3454 To undo an uncommitted merge, use :hg:`update --clean .` which
3477 To undo an uncommitted merge, use :hg:`update --clean .` which
3455 will check out a clean copy of the original merge parent, losing
3478 will check out a clean copy of the original merge parent, losing
3456 all changes.
3479 all changes.
3457
3480
3458 Returns 0 on success, 1 if there are unresolved files.
3481 Returns 0 on success, 1 if there are unresolved files.
3459 """
3482 """
3460
3483
3461 if opts.get('rev') and node:
3484 if opts.get('rev') and node:
3462 raise util.Abort(_("please specify just one revision"))
3485 raise util.Abort(_("please specify just one revision"))
3463 if not node:
3486 if not node:
3464 node = opts.get('rev')
3487 node = opts.get('rev')
3465
3488
3466 if not node:
3489 if not node:
3467 branch = repo[None].branch()
3490 branch = repo[None].branch()
3468 bheads = repo.branchheads(branch)
3491 bheads = repo.branchheads(branch)
3469 if len(bheads) > 2:
3492 if len(bheads) > 2:
3470 raise util.Abort(_("branch '%s' has %d heads - "
3493 raise util.Abort(_("branch '%s' has %d heads - "
3471 "please merge with an explicit rev")
3494 "please merge with an explicit rev")
3472 % (branch, len(bheads)),
3495 % (branch, len(bheads)),
3473 hint=_("run 'hg heads .' to see heads"))
3496 hint=_("run 'hg heads .' to see heads"))
3474
3497
3475 parent = repo.dirstate.p1()
3498 parent = repo.dirstate.p1()
3476 if len(bheads) == 1:
3499 if len(bheads) == 1:
3477 if len(repo.heads()) > 1:
3500 if len(repo.heads()) > 1:
3478 raise util.Abort(_("branch '%s' has one head - "
3501 raise util.Abort(_("branch '%s' has one head - "
3479 "please merge with an explicit rev")
3502 "please merge with an explicit rev")
3480 % branch,
3503 % branch,
3481 hint=_("run 'hg heads' to see all heads"))
3504 hint=_("run 'hg heads' to see all heads"))
3482 msg = _('there is nothing to merge')
3505 msg = _('there is nothing to merge')
3483 if parent != repo.lookup(repo[None].branch()):
3506 if parent != repo.lookup(repo[None].branch()):
3484 msg = _('%s - use "hg update" instead') % msg
3507 msg = _('%s - use "hg update" instead') % msg
3485 raise util.Abort(msg)
3508 raise util.Abort(msg)
3486
3509
3487 if parent not in bheads:
3510 if parent not in bheads:
3488 raise util.Abort(_('working directory not at a head revision'),
3511 raise util.Abort(_('working directory not at a head revision'),
3489 hint=_("use 'hg update' or merge with an "
3512 hint=_("use 'hg update' or merge with an "
3490 "explicit revision"))
3513 "explicit revision"))
3491 node = parent == bheads[0] and bheads[-1] or bheads[0]
3514 node = parent == bheads[0] and bheads[-1] or bheads[0]
3492 else:
3515 else:
3493 node = scmutil.revsingle(repo, node).node()
3516 node = scmutil.revsingle(repo, node).node()
3494
3517
3495 if opts.get('preview'):
3518 if opts.get('preview'):
3496 # find nodes that are ancestors of p2 but not of p1
3519 # find nodes that are ancestors of p2 but not of p1
3497 p1 = repo.lookup('.')
3520 p1 = repo.lookup('.')
3498 p2 = repo.lookup(node)
3521 p2 = repo.lookup(node)
3499 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3522 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3500
3523
3501 displayer = cmdutil.show_changeset(ui, repo, opts)
3524 displayer = cmdutil.show_changeset(ui, repo, opts)
3502 for node in nodes:
3525 for node in nodes:
3503 displayer.show(repo[node])
3526 displayer.show(repo[node])
3504 displayer.close()
3527 displayer.close()
3505 return 0
3528 return 0
3506
3529
3507 try:
3530 try:
3508 # ui.forcemerge is an internal variable, do not document
3531 # ui.forcemerge is an internal variable, do not document
3509 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3532 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3510 return hg.merge(repo, node, force=opts.get('force'))
3533 return hg.merge(repo, node, force=opts.get('force'))
3511 finally:
3534 finally:
3512 ui.setconfig('ui', 'forcemerge', '')
3535 ui.setconfig('ui', 'forcemerge', '')
3513
3536
3514 @command('outgoing|out',
3537 @command('outgoing|out',
3515 [('f', 'force', None, _('run even when the destination is unrelated')),
3538 [('f', 'force', None, _('run even when the destination is unrelated')),
3516 ('r', 'rev', [],
3539 ('r', 'rev', [],
3517 _('a changeset intended to be included in the destination'), _('REV')),
3540 _('a changeset intended to be included in the destination'), _('REV')),
3518 ('n', 'newest-first', None, _('show newest record first')),
3541 ('n', 'newest-first', None, _('show newest record first')),
3519 ('B', 'bookmarks', False, _('compare bookmarks')),
3542 ('B', 'bookmarks', False, _('compare bookmarks')),
3520 ('b', 'branch', [], _('a specific branch you would like to push'),
3543 ('b', 'branch', [], _('a specific branch you would like to push'),
3521 _('BRANCH')),
3544 _('BRANCH')),
3522 ] + logopts + remoteopts + subrepoopts,
3545 ] + logopts + remoteopts + subrepoopts,
3523 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3546 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3524 def outgoing(ui, repo, dest=None, **opts):
3547 def outgoing(ui, repo, dest=None, **opts):
3525 """show changesets not found in the destination
3548 """show changesets not found in the destination
3526
3549
3527 Show changesets not found in the specified destination repository
3550 Show changesets not found in the specified destination repository
3528 or the default push location. These are the changesets that would
3551 or the default push location. These are the changesets that would
3529 be pushed if a push was requested.
3552 be pushed if a push was requested.
3530
3553
3531 See pull for details of valid destination formats.
3554 See pull for details of valid destination formats.
3532
3555
3533 Returns 0 if there are outgoing changes, 1 otherwise.
3556 Returns 0 if there are outgoing changes, 1 otherwise.
3534 """
3557 """
3535
3558
3536 if opts.get('bookmarks'):
3559 if opts.get('bookmarks'):
3537 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3560 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3538 dest, branches = hg.parseurl(dest, opts.get('branch'))
3561 dest, branches = hg.parseurl(dest, opts.get('branch'))
3539 other = hg.repository(hg.remoteui(repo, opts), dest)
3562 other = hg.repository(hg.remoteui(repo, opts), dest)
3540 if 'bookmarks' not in other.listkeys('namespaces'):
3563 if 'bookmarks' not in other.listkeys('namespaces'):
3541 ui.warn(_("remote doesn't support bookmarks\n"))
3564 ui.warn(_("remote doesn't support bookmarks\n"))
3542 return 0
3565 return 0
3543 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3566 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3544 return bookmarks.diff(ui, other, repo)
3567 return bookmarks.diff(ui, other, repo)
3545
3568
3546 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3569 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3547 try:
3570 try:
3548 return hg.outgoing(ui, repo, dest, opts)
3571 return hg.outgoing(ui, repo, dest, opts)
3549 finally:
3572 finally:
3550 del repo._subtoppath
3573 del repo._subtoppath
3551
3574
3552 @command('parents',
3575 @command('parents',
3553 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3576 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3554 ] + templateopts,
3577 ] + templateopts,
3555 _('[-r REV] [FILE]'))
3578 _('[-r REV] [FILE]'))
3556 def parents(ui, repo, file_=None, **opts):
3579 def parents(ui, repo, file_=None, **opts):
3557 """show the parents of the working directory or revision
3580 """show the parents of the working directory or revision
3558
3581
3559 Print the working directory's parent revisions. If a revision is
3582 Print the working directory's parent revisions. If a revision is
3560 given via -r/--rev, the parent of that revision will be printed.
3583 given via -r/--rev, the parent of that revision will be printed.
3561 If a file argument is given, the revision in which the file was
3584 If a file argument is given, the revision in which the file was
3562 last changed (before the working directory revision or the
3585 last changed (before the working directory revision or the
3563 argument to --rev if given) is printed.
3586 argument to --rev if given) is printed.
3564
3587
3565 Returns 0 on success.
3588 Returns 0 on success.
3566 """
3589 """
3567
3590
3568 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3591 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3569
3592
3570 if file_:
3593 if file_:
3571 m = scmutil.match(repo, (file_,), opts)
3594 m = scmutil.match(repo, (file_,), opts)
3572 if m.anypats() or len(m.files()) != 1:
3595 if m.anypats() or len(m.files()) != 1:
3573 raise util.Abort(_('can only specify an explicit filename'))
3596 raise util.Abort(_('can only specify an explicit filename'))
3574 file_ = m.files()[0]
3597 file_ = m.files()[0]
3575 filenodes = []
3598 filenodes = []
3576 for cp in ctx.parents():
3599 for cp in ctx.parents():
3577 if not cp:
3600 if not cp:
3578 continue
3601 continue
3579 try:
3602 try:
3580 filenodes.append(cp.filenode(file_))
3603 filenodes.append(cp.filenode(file_))
3581 except error.LookupError:
3604 except error.LookupError:
3582 pass
3605 pass
3583 if not filenodes:
3606 if not filenodes:
3584 raise util.Abort(_("'%s' not found in manifest!") % file_)
3607 raise util.Abort(_("'%s' not found in manifest!") % file_)
3585 fl = repo.file(file_)
3608 fl = repo.file(file_)
3586 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3609 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3587 else:
3610 else:
3588 p = [cp.node() for cp in ctx.parents()]
3611 p = [cp.node() for cp in ctx.parents()]
3589
3612
3590 displayer = cmdutil.show_changeset(ui, repo, opts)
3613 displayer = cmdutil.show_changeset(ui, repo, opts)
3591 for n in p:
3614 for n in p:
3592 if n != nullid:
3615 if n != nullid:
3593 displayer.show(repo[n])
3616 displayer.show(repo[n])
3594 displayer.close()
3617 displayer.close()
3595
3618
3596 @command('paths', [], _('[NAME]'))
3619 @command('paths', [], _('[NAME]'))
3597 def paths(ui, repo, search=None):
3620 def paths(ui, repo, search=None):
3598 """show aliases for remote repositories
3621 """show aliases for remote repositories
3599
3622
3600 Show definition of symbolic path name NAME. If no name is given,
3623 Show definition of symbolic path name NAME. If no name is given,
3601 show definition of all available names.
3624 show definition of all available names.
3602
3625
3603 Option -q/--quiet suppresses all output when searching for NAME
3626 Option -q/--quiet suppresses all output when searching for NAME
3604 and shows only the path names when listing all definitions.
3627 and shows only the path names when listing all definitions.
3605
3628
3606 Path names are defined in the [paths] section of your
3629 Path names are defined in the [paths] section of your
3607 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3630 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3608 repository, ``.hg/hgrc`` is used, too.
3631 repository, ``.hg/hgrc`` is used, too.
3609
3632
3610 The path names ``default`` and ``default-push`` have a special
3633 The path names ``default`` and ``default-push`` have a special
3611 meaning. When performing a push or pull operation, they are used
3634 meaning. When performing a push or pull operation, they are used
3612 as fallbacks if no location is specified on the command-line.
3635 as fallbacks if no location is specified on the command-line.
3613 When ``default-push`` is set, it will be used for push and
3636 When ``default-push`` is set, it will be used for push and
3614 ``default`` will be used for pull; otherwise ``default`` is used
3637 ``default`` will be used for pull; otherwise ``default`` is used
3615 as the fallback for both. When cloning a repository, the clone
3638 as the fallback for both. When cloning a repository, the clone
3616 source is written as ``default`` in ``.hg/hgrc``. Note that
3639 source is written as ``default`` in ``.hg/hgrc``. Note that
3617 ``default`` and ``default-push`` apply to all inbound (e.g.
3640 ``default`` and ``default-push`` apply to all inbound (e.g.
3618 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3641 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3619 :hg:`bundle`) operations.
3642 :hg:`bundle`) operations.
3620
3643
3621 See :hg:`help urls` for more information.
3644 See :hg:`help urls` for more information.
3622
3645
3623 Returns 0 on success.
3646 Returns 0 on success.
3624 """
3647 """
3625 if search:
3648 if search:
3626 for name, path in ui.configitems("paths"):
3649 for name, path in ui.configitems("paths"):
3627 if name == search:
3650 if name == search:
3628 ui.status("%s\n" % util.hidepassword(path))
3651 ui.status("%s\n" % util.hidepassword(path))
3629 return
3652 return
3630 if not ui.quiet:
3653 if not ui.quiet:
3631 ui.warn(_("not found!\n"))
3654 ui.warn(_("not found!\n"))
3632 return 1
3655 return 1
3633 else:
3656 else:
3634 for name, path in ui.configitems("paths"):
3657 for name, path in ui.configitems("paths"):
3635 if ui.quiet:
3658 if ui.quiet:
3636 ui.write("%s\n" % name)
3659 ui.write("%s\n" % name)
3637 else:
3660 else:
3638 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3661 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3639
3662
3640 def postincoming(ui, repo, modheads, optupdate, checkout):
3663 def postincoming(ui, repo, modheads, optupdate, checkout):
3641 if modheads == 0:
3664 if modheads == 0:
3642 return
3665 return
3643 if optupdate:
3666 if optupdate:
3644 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
3667 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
3645 return hg.update(repo, checkout)
3668 return hg.update(repo, checkout)
3646 else:
3669 else:
3647 ui.status(_("not updating, since new heads added\n"))
3670 ui.status(_("not updating, since new heads added\n"))
3648 if modheads > 1:
3671 if modheads > 1:
3649 currentbranchheads = len(repo.branchheads())
3672 currentbranchheads = len(repo.branchheads())
3650 if currentbranchheads == modheads:
3673 if currentbranchheads == modheads:
3651 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3674 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3652 elif currentbranchheads > 1:
3675 elif currentbranchheads > 1:
3653 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3676 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3654 else:
3677 else:
3655 ui.status(_("(run 'hg heads' to see heads)\n"))
3678 ui.status(_("(run 'hg heads' to see heads)\n"))
3656 else:
3679 else:
3657 ui.status(_("(run 'hg update' to get a working copy)\n"))
3680 ui.status(_("(run 'hg update' to get a working copy)\n"))
3658
3681
3659 @command('^pull',
3682 @command('^pull',
3660 [('u', 'update', None,
3683 [('u', 'update', None,
3661 _('update to new branch head if changesets were pulled')),
3684 _('update to new branch head if changesets were pulled')),
3662 ('f', 'force', None, _('run even when remote repository is unrelated')),
3685 ('f', 'force', None, _('run even when remote repository is unrelated')),
3663 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3686 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3664 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3687 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3665 ('b', 'branch', [], _('a specific branch you would like to pull'),
3688 ('b', 'branch', [], _('a specific branch you would like to pull'),
3666 _('BRANCH')),
3689 _('BRANCH')),
3667 ] + remoteopts,
3690 ] + remoteopts,
3668 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3691 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3669 def pull(ui, repo, source="default", **opts):
3692 def pull(ui, repo, source="default", **opts):
3670 """pull changes from the specified source
3693 """pull changes from the specified source
3671
3694
3672 Pull changes from a remote repository to a local one.
3695 Pull changes from a remote repository to a local one.
3673
3696
3674 This finds all changes from the repository at the specified path
3697 This finds all changes from the repository at the specified path
3675 or URL and adds them to a local repository (the current one unless
3698 or URL and adds them to a local repository (the current one unless
3676 -R is specified). By default, this does not update the copy of the
3699 -R is specified). By default, this does not update the copy of the
3677 project in the working directory.
3700 project in the working directory.
3678
3701
3679 Use :hg:`incoming` if you want to see what would have been added
3702 Use :hg:`incoming` if you want to see what would have been added
3680 by a pull at the time you issued this command. If you then decide
3703 by a pull at the time you issued this command. If you then decide
3681 to add those changes to the repository, you should use :hg:`pull
3704 to add those changes to the repository, you should use :hg:`pull
3682 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3705 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3683
3706
3684 If SOURCE is omitted, the 'default' path will be used.
3707 If SOURCE is omitted, the 'default' path will be used.
3685 See :hg:`help urls` for more information.
3708 See :hg:`help urls` for more information.
3686
3709
3687 Returns 0 on success, 1 if an update had unresolved files.
3710 Returns 0 on success, 1 if an update had unresolved files.
3688 """
3711 """
3689 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3712 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3690 other = hg.repository(hg.remoteui(repo, opts), source)
3713 other = hg.repository(hg.remoteui(repo, opts), source)
3691 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3714 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3692 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3715 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3693
3716
3694 if opts.get('bookmark'):
3717 if opts.get('bookmark'):
3695 if not revs:
3718 if not revs:
3696 revs = []
3719 revs = []
3697 rb = other.listkeys('bookmarks')
3720 rb = other.listkeys('bookmarks')
3698 for b in opts['bookmark']:
3721 for b in opts['bookmark']:
3699 if b not in rb:
3722 if b not in rb:
3700 raise util.Abort(_('remote bookmark %s not found!') % b)
3723 raise util.Abort(_('remote bookmark %s not found!') % b)
3701 revs.append(rb[b])
3724 revs.append(rb[b])
3702
3725
3703 if revs:
3726 if revs:
3704 try:
3727 try:
3705 revs = [other.lookup(rev) for rev in revs]
3728 revs = [other.lookup(rev) for rev in revs]
3706 except error.CapabilityError:
3729 except error.CapabilityError:
3707 err = _("other repository doesn't support revision lookup, "
3730 err = _("other repository doesn't support revision lookup, "
3708 "so a rev cannot be specified.")
3731 "so a rev cannot be specified.")
3709 raise util.Abort(err)
3732 raise util.Abort(err)
3710
3733
3711 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3734 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3712 bookmarks.updatefromremote(ui, repo, other)
3735 bookmarks.updatefromremote(ui, repo, other)
3713 if checkout:
3736 if checkout:
3714 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3737 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3715 repo._subtoppath = source
3738 repo._subtoppath = source
3716 try:
3739 try:
3717 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3740 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3718
3741
3719 finally:
3742 finally:
3720 del repo._subtoppath
3743 del repo._subtoppath
3721
3744
3722 # update specified bookmarks
3745 # update specified bookmarks
3723 if opts.get('bookmark'):
3746 if opts.get('bookmark'):
3724 for b in opts['bookmark']:
3747 for b in opts['bookmark']:
3725 # explicit pull overrides local bookmark if any
3748 # explicit pull overrides local bookmark if any
3726 ui.status(_("importing bookmark %s\n") % b)
3749 ui.status(_("importing bookmark %s\n") % b)
3727 repo._bookmarks[b] = repo[rb[b]].node()
3750 repo._bookmarks[b] = repo[rb[b]].node()
3728 bookmarks.write(repo)
3751 bookmarks.write(repo)
3729
3752
3730 return ret
3753 return ret
3731
3754
3732 @command('^push',
3755 @command('^push',
3733 [('f', 'force', None, _('force push')),
3756 [('f', 'force', None, _('force push')),
3734 ('r', 'rev', [],
3757 ('r', 'rev', [],
3735 _('a changeset intended to be included in the destination'),
3758 _('a changeset intended to be included in the destination'),
3736 _('REV')),
3759 _('REV')),
3737 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3760 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3738 ('b', 'branch', [],
3761 ('b', 'branch', [],
3739 _('a specific branch you would like to push'), _('BRANCH')),
3762 _('a specific branch you would like to push'), _('BRANCH')),
3740 ('', 'new-branch', False, _('allow pushing a new branch')),
3763 ('', 'new-branch', False, _('allow pushing a new branch')),
3741 ] + remoteopts,
3764 ] + remoteopts,
3742 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3765 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3743 def push(ui, repo, dest=None, **opts):
3766 def push(ui, repo, dest=None, **opts):
3744 """push changes to the specified destination
3767 """push changes to the specified destination
3745
3768
3746 Push changesets from the local repository to the specified
3769 Push changesets from the local repository to the specified
3747 destination.
3770 destination.
3748
3771
3749 This operation is symmetrical to pull: it is identical to a pull
3772 This operation is symmetrical to pull: it is identical to a pull
3750 in the destination repository from the current one.
3773 in the destination repository from the current one.
3751
3774
3752 By default, push will not allow creation of new heads at the
3775 By default, push will not allow creation of new heads at the
3753 destination, since multiple heads would make it unclear which head
3776 destination, since multiple heads would make it unclear which head
3754 to use. In this situation, it is recommended to pull and merge
3777 to use. In this situation, it is recommended to pull and merge
3755 before pushing.
3778 before pushing.
3756
3779
3757 Use --new-branch if you want to allow push to create a new named
3780 Use --new-branch if you want to allow push to create a new named
3758 branch that is not present at the destination. This allows you to
3781 branch that is not present at the destination. This allows you to
3759 only create a new branch without forcing other changes.
3782 only create a new branch without forcing other changes.
3760
3783
3761 Use -f/--force to override the default behavior and push all
3784 Use -f/--force to override the default behavior and push all
3762 changesets on all branches.
3785 changesets on all branches.
3763
3786
3764 If -r/--rev is used, the specified revision and all its ancestors
3787 If -r/--rev is used, the specified revision and all its ancestors
3765 will be pushed to the remote repository.
3788 will be pushed to the remote repository.
3766
3789
3767 Please see :hg:`help urls` for important details about ``ssh://``
3790 Please see :hg:`help urls` for important details about ``ssh://``
3768 URLs. If DESTINATION is omitted, a default path will be used.
3791 URLs. If DESTINATION is omitted, a default path will be used.
3769
3792
3770 Returns 0 if push was successful, 1 if nothing to push.
3793 Returns 0 if push was successful, 1 if nothing to push.
3771 """
3794 """
3772
3795
3773 if opts.get('bookmark'):
3796 if opts.get('bookmark'):
3774 for b in opts['bookmark']:
3797 for b in opts['bookmark']:
3775 # translate -B options to -r so changesets get pushed
3798 # translate -B options to -r so changesets get pushed
3776 if b in repo._bookmarks:
3799 if b in repo._bookmarks:
3777 opts.setdefault('rev', []).append(b)
3800 opts.setdefault('rev', []).append(b)
3778 else:
3801 else:
3779 # if we try to push a deleted bookmark, translate it to null
3802 # if we try to push a deleted bookmark, translate it to null
3780 # this lets simultaneous -r, -b options continue working
3803 # this lets simultaneous -r, -b options continue working
3781 opts.setdefault('rev', []).append("null")
3804 opts.setdefault('rev', []).append("null")
3782
3805
3783 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3806 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3784 dest, branches = hg.parseurl(dest, opts.get('branch'))
3807 dest, branches = hg.parseurl(dest, opts.get('branch'))
3785 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3808 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3786 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3809 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3787 other = hg.repository(hg.remoteui(repo, opts), dest)
3810 other = hg.repository(hg.remoteui(repo, opts), dest)
3788 if revs:
3811 if revs:
3789 revs = [repo.lookup(rev) for rev in revs]
3812 revs = [repo.lookup(rev) for rev in revs]
3790
3813
3791 repo._subtoppath = dest
3814 repo._subtoppath = dest
3792 try:
3815 try:
3793 # push subrepos depth-first for coherent ordering
3816 # push subrepos depth-first for coherent ordering
3794 c = repo['']
3817 c = repo['']
3795 subs = c.substate # only repos that are committed
3818 subs = c.substate # only repos that are committed
3796 for s in sorted(subs):
3819 for s in sorted(subs):
3797 if not c.sub(s).push(opts.get('force')):
3820 if not c.sub(s).push(opts.get('force')):
3798 return False
3821 return False
3799 finally:
3822 finally:
3800 del repo._subtoppath
3823 del repo._subtoppath
3801 result = repo.push(other, opts.get('force'), revs=revs,
3824 result = repo.push(other, opts.get('force'), revs=revs,
3802 newbranch=opts.get('new_branch'))
3825 newbranch=opts.get('new_branch'))
3803
3826
3804 result = (result == 0)
3827 result = (result == 0)
3805
3828
3806 if opts.get('bookmark'):
3829 if opts.get('bookmark'):
3807 rb = other.listkeys('bookmarks')
3830 rb = other.listkeys('bookmarks')
3808 for b in opts['bookmark']:
3831 for b in opts['bookmark']:
3809 # explicit push overrides remote bookmark if any
3832 # explicit push overrides remote bookmark if any
3810 if b in repo._bookmarks:
3833 if b in repo._bookmarks:
3811 ui.status(_("exporting bookmark %s\n") % b)
3834 ui.status(_("exporting bookmark %s\n") % b)
3812 new = repo[b].hex()
3835 new = repo[b].hex()
3813 elif b in rb:
3836 elif b in rb:
3814 ui.status(_("deleting remote bookmark %s\n") % b)
3837 ui.status(_("deleting remote bookmark %s\n") % b)
3815 new = '' # delete
3838 new = '' # delete
3816 else:
3839 else:
3817 ui.warn(_('bookmark %s does not exist on the local '
3840 ui.warn(_('bookmark %s does not exist on the local '
3818 'or remote repository!\n') % b)
3841 'or remote repository!\n') % b)
3819 return 2
3842 return 2
3820 old = rb.get(b, '')
3843 old = rb.get(b, '')
3821 r = other.pushkey('bookmarks', b, old, new)
3844 r = other.pushkey('bookmarks', b, old, new)
3822 if not r:
3845 if not r:
3823 ui.warn(_('updating bookmark %s failed!\n') % b)
3846 ui.warn(_('updating bookmark %s failed!\n') % b)
3824 if not result:
3847 if not result:
3825 result = 2
3848 result = 2
3826
3849
3827 return result
3850 return result
3828
3851
3829 @command('recover', [])
3852 @command('recover', [])
3830 def recover(ui, repo):
3853 def recover(ui, repo):
3831 """roll back an interrupted transaction
3854 """roll back an interrupted transaction
3832
3855
3833 Recover from an interrupted commit or pull.
3856 Recover from an interrupted commit or pull.
3834
3857
3835 This command tries to fix the repository status after an
3858 This command tries to fix the repository status after an
3836 interrupted operation. It should only be necessary when Mercurial
3859 interrupted operation. It should only be necessary when Mercurial
3837 suggests it.
3860 suggests it.
3838
3861
3839 Returns 0 if successful, 1 if nothing to recover or verify fails.
3862 Returns 0 if successful, 1 if nothing to recover or verify fails.
3840 """
3863 """
3841 if repo.recover():
3864 if repo.recover():
3842 return hg.verify(repo)
3865 return hg.verify(repo)
3843 return 1
3866 return 1
3844
3867
3845 @command('^remove|rm',
3868 @command('^remove|rm',
3846 [('A', 'after', None, _('record delete for missing files')),
3869 [('A', 'after', None, _('record delete for missing files')),
3847 ('f', 'force', None,
3870 ('f', 'force', None,
3848 _('remove (and delete) file even if added or modified')),
3871 _('remove (and delete) file even if added or modified')),
3849 ] + walkopts,
3872 ] + walkopts,
3850 _('[OPTION]... FILE...'))
3873 _('[OPTION]... FILE...'))
3851 def remove(ui, repo, *pats, **opts):
3874 def remove(ui, repo, *pats, **opts):
3852 """remove the specified files on the next commit
3875 """remove the specified files on the next commit
3853
3876
3854 Schedule the indicated files for removal from the repository.
3877 Schedule the indicated files for removal from the repository.
3855
3878
3856 This only removes files from the current branch, not from the
3879 This only removes files from the current branch, not from the
3857 entire project history. -A/--after can be used to remove only
3880 entire project history. -A/--after can be used to remove only
3858 files that have already been deleted, -f/--force can be used to
3881 files that have already been deleted, -f/--force can be used to
3859 force deletion, and -Af can be used to remove files from the next
3882 force deletion, and -Af can be used to remove files from the next
3860 revision without deleting them from the working directory.
3883 revision without deleting them from the working directory.
3861
3884
3862 The following table details the behavior of remove for different
3885 The following table details the behavior of remove for different
3863 file states (columns) and option combinations (rows). The file
3886 file states (columns) and option combinations (rows). The file
3864 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3887 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3865 reported by :hg:`status`). The actions are Warn, Remove (from
3888 reported by :hg:`status`). The actions are Warn, Remove (from
3866 branch) and Delete (from disk)::
3889 branch) and Delete (from disk)::
3867
3890
3868 A C M !
3891 A C M !
3869 none W RD W R
3892 none W RD W R
3870 -f R RD RD R
3893 -f R RD RD R
3871 -A W W W R
3894 -A W W W R
3872 -Af R R R R
3895 -Af R R R R
3873
3896
3874 This command schedules the files to be removed at the next commit.
3897 This command schedules the files to be removed at the next commit.
3875 To undo a remove before that, see :hg:`revert`.
3898 To undo a remove before that, see :hg:`revert`.
3876
3899
3877 Returns 0 on success, 1 if any warnings encountered.
3900 Returns 0 on success, 1 if any warnings encountered.
3878 """
3901 """
3879
3902
3880 ret = 0
3903 ret = 0
3881 after, force = opts.get('after'), opts.get('force')
3904 after, force = opts.get('after'), opts.get('force')
3882 if not pats and not after:
3905 if not pats and not after:
3883 raise util.Abort(_('no files specified'))
3906 raise util.Abort(_('no files specified'))
3884
3907
3885 m = scmutil.match(repo, pats, opts)
3908 m = scmutil.match(repo, pats, opts)
3886 s = repo.status(match=m, clean=True)
3909 s = repo.status(match=m, clean=True)
3887 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3910 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3888
3911
3889 for f in m.files():
3912 for f in m.files():
3890 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3913 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3891 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3914 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3892 ret = 1
3915 ret = 1
3893
3916
3894 if force:
3917 if force:
3895 remove, forget = modified + deleted + clean, added
3918 remove, forget = modified + deleted + clean, added
3896 elif after:
3919 elif after:
3897 remove, forget = deleted, []
3920 remove, forget = deleted, []
3898 for f in modified + added + clean:
3921 for f in modified + added + clean:
3899 ui.warn(_('not removing %s: file still exists (use -f'
3922 ui.warn(_('not removing %s: file still exists (use -f'
3900 ' to force removal)\n') % m.rel(f))
3923 ' to force removal)\n') % m.rel(f))
3901 ret = 1
3924 ret = 1
3902 else:
3925 else:
3903 remove, forget = deleted + clean, []
3926 remove, forget = deleted + clean, []
3904 for f in modified:
3927 for f in modified:
3905 ui.warn(_('not removing %s: file is modified (use -f'
3928 ui.warn(_('not removing %s: file is modified (use -f'
3906 ' to force removal)\n') % m.rel(f))
3929 ' to force removal)\n') % m.rel(f))
3907 ret = 1
3930 ret = 1
3908 for f in added:
3931 for f in added:
3909 ui.warn(_('not removing %s: file has been marked for add (use -f'
3932 ui.warn(_('not removing %s: file has been marked for add (use -f'
3910 ' to force removal)\n') % m.rel(f))
3933 ' to force removal)\n') % m.rel(f))
3911 ret = 1
3934 ret = 1
3912
3935
3913 for f in sorted(remove + forget):
3936 for f in sorted(remove + forget):
3914 if ui.verbose or not m.exact(f):
3937 if ui.verbose or not m.exact(f):
3915 ui.status(_('removing %s\n') % m.rel(f))
3938 ui.status(_('removing %s\n') % m.rel(f))
3916
3939
3917 repo[None].forget(forget)
3940 repo[None].forget(forget)
3918 repo[None].remove(remove, unlink=not after)
3941 repo[None].remove(remove, unlink=not after)
3919 return ret
3942 return ret
3920
3943
3921 @command('rename|move|mv',
3944 @command('rename|move|mv',
3922 [('A', 'after', None, _('record a rename that has already occurred')),
3945 [('A', 'after', None, _('record a rename that has already occurred')),
3923 ('f', 'force', None, _('forcibly copy over an existing managed file')),
3946 ('f', 'force', None, _('forcibly copy over an existing managed file')),
3924 ] + walkopts + dryrunopts,
3947 ] + walkopts + dryrunopts,
3925 _('[OPTION]... SOURCE... DEST'))
3948 _('[OPTION]... SOURCE... DEST'))
3926 def rename(ui, repo, *pats, **opts):
3949 def rename(ui, repo, *pats, **opts):
3927 """rename files; equivalent of copy + remove
3950 """rename files; equivalent of copy + remove
3928
3951
3929 Mark dest as copies of sources; mark sources for deletion. If dest
3952 Mark dest as copies of sources; mark sources for deletion. If dest
3930 is a directory, copies are put in that directory. If dest is a
3953 is a directory, copies are put in that directory. If dest is a
3931 file, there can only be one source.
3954 file, there can only be one source.
3932
3955
3933 By default, this command copies the contents of files as they
3956 By default, this command copies the contents of files as they
3934 exist in the working directory. If invoked with -A/--after, the
3957 exist in the working directory. If invoked with -A/--after, the
3935 operation is recorded, but no copying is performed.
3958 operation is recorded, but no copying is performed.
3936
3959
3937 This command takes effect at the next commit. To undo a rename
3960 This command takes effect at the next commit. To undo a rename
3938 before that, see :hg:`revert`.
3961 before that, see :hg:`revert`.
3939
3962
3940 Returns 0 on success, 1 if errors are encountered.
3963 Returns 0 on success, 1 if errors are encountered.
3941 """
3964 """
3942 wlock = repo.wlock(False)
3965 wlock = repo.wlock(False)
3943 try:
3966 try:
3944 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3967 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3945 finally:
3968 finally:
3946 wlock.release()
3969 wlock.release()
3947
3970
3948 @command('resolve',
3971 @command('resolve',
3949 [('a', 'all', None, _('select all unresolved files')),
3972 [('a', 'all', None, _('select all unresolved files')),
3950 ('l', 'list', None, _('list state of files needing merge')),
3973 ('l', 'list', None, _('list state of files needing merge')),
3951 ('m', 'mark', None, _('mark files as resolved')),
3974 ('m', 'mark', None, _('mark files as resolved')),
3952 ('u', 'unmark', None, _('mark files as unresolved')),
3975 ('u', 'unmark', None, _('mark files as unresolved')),
3953 ('t', 'tool', '', _('specify merge tool')),
3976 ('t', 'tool', '', _('specify merge tool')),
3954 ('n', 'no-status', None, _('hide status prefix'))]
3977 ('n', 'no-status', None, _('hide status prefix'))]
3955 + walkopts,
3978 + walkopts,
3956 _('[OPTION]... [FILE]...'))
3979 _('[OPTION]... [FILE]...'))
3957 def resolve(ui, repo, *pats, **opts):
3980 def resolve(ui, repo, *pats, **opts):
3958 """redo merges or set/view the merge status of files
3981 """redo merges or set/view the merge status of files
3959
3982
3960 Merges with unresolved conflicts are often the result of
3983 Merges with unresolved conflicts are often the result of
3961 non-interactive merging using the ``internal:merge`` configuration
3984 non-interactive merging using the ``internal:merge`` configuration
3962 setting, or a command-line merge tool like ``diff3``. The resolve
3985 setting, or a command-line merge tool like ``diff3``. The resolve
3963 command is used to manage the files involved in a merge, after
3986 command is used to manage the files involved in a merge, after
3964 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3987 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3965 working directory must have two parents).
3988 working directory must have two parents).
3966
3989
3967 The resolve command can be used in the following ways:
3990 The resolve command can be used in the following ways:
3968
3991
3969 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3992 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3970 files, discarding any previous merge attempts. Re-merging is not
3993 files, discarding any previous merge attempts. Re-merging is not
3971 performed for files already marked as resolved. Use ``--all/-a``
3994 performed for files already marked as resolved. Use ``--all/-a``
3972 to selects all unresolved files. ``--tool`` can be used to specify
3995 to selects all unresolved files. ``--tool`` can be used to specify
3973 the merge tool used for the given files. It overrides the HGMERGE
3996 the merge tool used for the given files. It overrides the HGMERGE
3974 environment variable and your configuration files.
3997 environment variable and your configuration files.
3975
3998
3976 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3999 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3977 (e.g. after having manually fixed-up the files). The default is
4000 (e.g. after having manually fixed-up the files). The default is
3978 to mark all unresolved files.
4001 to mark all unresolved files.
3979
4002
3980 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4003 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3981 default is to mark all resolved files.
4004 default is to mark all resolved files.
3982
4005
3983 - :hg:`resolve -l`: list files which had or still have conflicts.
4006 - :hg:`resolve -l`: list files which had or still have conflicts.
3984 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4007 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3985
4008
3986 Note that Mercurial will not let you commit files with unresolved
4009 Note that Mercurial will not let you commit files with unresolved
3987 merge conflicts. You must use :hg:`resolve -m ...` before you can
4010 merge conflicts. You must use :hg:`resolve -m ...` before you can
3988 commit after a conflicting merge.
4011 commit after a conflicting merge.
3989
4012
3990 Returns 0 on success, 1 if any files fail a resolve attempt.
4013 Returns 0 on success, 1 if any files fail a resolve attempt.
3991 """
4014 """
3992
4015
3993 all, mark, unmark, show, nostatus = \
4016 all, mark, unmark, show, nostatus = \
3994 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4017 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3995
4018
3996 if (show and (mark or unmark)) or (mark and unmark):
4019 if (show and (mark or unmark)) or (mark and unmark):
3997 raise util.Abort(_("too many options specified"))
4020 raise util.Abort(_("too many options specified"))
3998 if pats and all:
4021 if pats and all:
3999 raise util.Abort(_("can't specify --all and patterns"))
4022 raise util.Abort(_("can't specify --all and patterns"))
4000 if not (all or pats or show or mark or unmark):
4023 if not (all or pats or show or mark or unmark):
4001 raise util.Abort(_('no files or directories specified; '
4024 raise util.Abort(_('no files or directories specified; '
4002 'use --all to remerge all files'))
4025 'use --all to remerge all files'))
4003
4026
4004 ms = mergemod.mergestate(repo)
4027 ms = mergemod.mergestate(repo)
4005 m = scmutil.match(repo, pats, opts)
4028 m = scmutil.match(repo, pats, opts)
4006 ret = 0
4029 ret = 0
4007
4030
4008 for f in ms:
4031 for f in ms:
4009 if m(f):
4032 if m(f):
4010 if show:
4033 if show:
4011 if nostatus:
4034 if nostatus:
4012 ui.write("%s\n" % f)
4035 ui.write("%s\n" % f)
4013 else:
4036 else:
4014 ui.write("%s %s\n" % (ms[f].upper(), f),
4037 ui.write("%s %s\n" % (ms[f].upper(), f),
4015 label='resolve.' +
4038 label='resolve.' +
4016 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4039 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4017 elif mark:
4040 elif mark:
4018 ms.mark(f, "r")
4041 ms.mark(f, "r")
4019 elif unmark:
4042 elif unmark:
4020 ms.mark(f, "u")
4043 ms.mark(f, "u")
4021 else:
4044 else:
4022 wctx = repo[None]
4045 wctx = repo[None]
4023 mctx = wctx.parents()[-1]
4046 mctx = wctx.parents()[-1]
4024
4047
4025 # backup pre-resolve (merge uses .orig for its own purposes)
4048 # backup pre-resolve (merge uses .orig for its own purposes)
4026 a = repo.wjoin(f)
4049 a = repo.wjoin(f)
4027 util.copyfile(a, a + ".resolve")
4050 util.copyfile(a, a + ".resolve")
4028
4051
4029 try:
4052 try:
4030 # resolve file
4053 # resolve file
4031 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4054 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4032 if ms.resolve(f, wctx, mctx):
4055 if ms.resolve(f, wctx, mctx):
4033 ret = 1
4056 ret = 1
4034 finally:
4057 finally:
4035 ui.setconfig('ui', 'forcemerge', '')
4058 ui.setconfig('ui', 'forcemerge', '')
4036
4059
4037 # replace filemerge's .orig file with our resolve file
4060 # replace filemerge's .orig file with our resolve file
4038 util.rename(a + ".resolve", a + ".orig")
4061 util.rename(a + ".resolve", a + ".orig")
4039
4062
4040 ms.commit()
4063 ms.commit()
4041 return ret
4064 return ret
4042
4065
4043 @command('revert',
4066 @command('revert',
4044 [('a', 'all', None, _('revert all changes when no arguments given')),
4067 [('a', 'all', None, _('revert all changes when no arguments given')),
4045 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4068 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4046 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4069 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4047 ('', 'no-backup', None, _('do not save backup copies of files')),
4070 ('', 'no-backup', None, _('do not save backup copies of files')),
4048 ] + walkopts + dryrunopts,
4071 ] + walkopts + dryrunopts,
4049 _('[OPTION]... [-r REV] [NAME]...'))
4072 _('[OPTION]... [-r REV] [NAME]...'))
4050 def revert(ui, repo, *pats, **opts):
4073 def revert(ui, repo, *pats, **opts):
4051 """restore individual files or directories to an earlier state
4074 """restore individual files or directories to an earlier state
4052
4075
4053 .. note::
4076 .. note::
4054 This command is most likely not what you are looking for.
4077 This command is most likely not what you are looking for.
4055 Revert will partially overwrite content in the working
4078 Revert will partially overwrite content in the working
4056 directory without changing the working directory parents. Use
4079 directory without changing the working directory parents. Use
4057 :hg:`update -r rev` to check out earlier revisions, or
4080 :hg:`update -r rev` to check out earlier revisions, or
4058 :hg:`update --clean .` to undo a merge which has added another
4081 :hg:`update --clean .` to undo a merge which has added another
4059 parent.
4082 parent.
4060
4083
4061 With no revision specified, revert the named files or directories
4084 With no revision specified, revert the named files or directories
4062 to the contents they had in the parent of the working directory.
4085 to the contents they had in the parent of the working directory.
4063 This restores the contents of the affected files to an unmodified
4086 This restores the contents of the affected files to an unmodified
4064 state and unschedules adds, removes, copies, and renames. If the
4087 state and unschedules adds, removes, copies, and renames. If the
4065 working directory has two parents, you must explicitly specify a
4088 working directory has two parents, you must explicitly specify a
4066 revision.
4089 revision.
4067
4090
4068 Using the -r/--rev option, revert the given files or directories
4091 Using the -r/--rev option, revert the given files or directories
4069 to their contents as of a specific revision. This can be helpful
4092 to their contents as of a specific revision. This can be helpful
4070 to "roll back" some or all of an earlier change. See :hg:`help
4093 to "roll back" some or all of an earlier change. See :hg:`help
4071 dates` for a list of formats valid for -d/--date.
4094 dates` for a list of formats valid for -d/--date.
4072
4095
4073 Revert modifies the working directory. It does not commit any
4096 Revert modifies the working directory. It does not commit any
4074 changes, or change the parent of the working directory. If you
4097 changes, or change the parent of the working directory. If you
4075 revert to a revision other than the parent of the working
4098 revert to a revision other than the parent of the working
4076 directory, the reverted files will thus appear modified
4099 directory, the reverted files will thus appear modified
4077 afterwards.
4100 afterwards.
4078
4101
4079 If a file has been deleted, it is restored. Files scheduled for
4102 If a file has been deleted, it is restored. Files scheduled for
4080 addition are just unscheduled and left as they are. If the
4103 addition are just unscheduled and left as they are. If the
4081 executable mode of a file was changed, it is reset.
4104 executable mode of a file was changed, it is reset.
4082
4105
4083 If names are given, all files matching the names are reverted.
4106 If names are given, all files matching the names are reverted.
4084 If no arguments are given, no files are reverted.
4107 If no arguments are given, no files are reverted.
4085
4108
4086 Modified files are saved with a .orig suffix before reverting.
4109 Modified files are saved with a .orig suffix before reverting.
4087 To disable these backups, use --no-backup.
4110 To disable these backups, use --no-backup.
4088
4111
4089 Returns 0 on success.
4112 Returns 0 on success.
4090 """
4113 """
4091
4114
4092 if opts.get("date"):
4115 if opts.get("date"):
4093 if opts.get("rev"):
4116 if opts.get("rev"):
4094 raise util.Abort(_("you can't specify a revision and a date"))
4117 raise util.Abort(_("you can't specify a revision and a date"))
4095 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4118 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4096
4119
4097 parent, p2 = repo.dirstate.parents()
4120 parent, p2 = repo.dirstate.parents()
4098 if not opts.get('rev') and p2 != nullid:
4121 if not opts.get('rev') and p2 != nullid:
4099 raise util.Abort(_('uncommitted merge - '
4122 raise util.Abort(_('uncommitted merge - '
4100 'use "hg update", see "hg help revert"'))
4123 'use "hg update", see "hg help revert"'))
4101
4124
4102 if not pats and not opts.get('all'):
4125 if not pats and not opts.get('all'):
4103 raise util.Abort(_('no files or directories specified; '
4126 raise util.Abort(_('no files or directories specified; '
4104 'use --all to revert the whole repo'))
4127 'use --all to revert the whole repo'))
4105
4128
4106 ctx = scmutil.revsingle(repo, opts.get('rev'))
4129 ctx = scmutil.revsingle(repo, opts.get('rev'))
4107 node = ctx.node()
4130 node = ctx.node()
4108 mf = ctx.manifest()
4131 mf = ctx.manifest()
4109 if node == parent:
4132 if node == parent:
4110 pmf = mf
4133 pmf = mf
4111 else:
4134 else:
4112 pmf = None
4135 pmf = None
4113
4136
4114 # need all matching names in dirstate and manifest of target rev,
4137 # need all matching names in dirstate and manifest of target rev,
4115 # so have to walk both. do not print errors if files exist in one
4138 # so have to walk both. do not print errors if files exist in one
4116 # but not other.
4139 # but not other.
4117
4140
4118 names = {}
4141 names = {}
4119
4142
4120 wlock = repo.wlock()
4143 wlock = repo.wlock()
4121 try:
4144 try:
4122 # walk dirstate.
4145 # walk dirstate.
4123
4146
4124 m = scmutil.match(repo, pats, opts)
4147 m = scmutil.match(repo, pats, opts)
4125 m.bad = lambda x, y: False
4148 m.bad = lambda x, y: False
4126 for abs in repo.walk(m):
4149 for abs in repo.walk(m):
4127 names[abs] = m.rel(abs), m.exact(abs)
4150 names[abs] = m.rel(abs), m.exact(abs)
4128
4151
4129 # walk target manifest.
4152 # walk target manifest.
4130
4153
4131 def badfn(path, msg):
4154 def badfn(path, msg):
4132 if path in names:
4155 if path in names:
4133 return
4156 return
4134 path_ = path + '/'
4157 path_ = path + '/'
4135 for f in names:
4158 for f in names:
4136 if f.startswith(path_):
4159 if f.startswith(path_):
4137 return
4160 return
4138 ui.warn("%s: %s\n" % (m.rel(path), msg))
4161 ui.warn("%s: %s\n" % (m.rel(path), msg))
4139
4162
4140 m = scmutil.match(repo, pats, opts)
4163 m = scmutil.match(repo, pats, opts)
4141 m.bad = badfn
4164 m.bad = badfn
4142 for abs in repo[node].walk(m):
4165 for abs in repo[node].walk(m):
4143 if abs not in names:
4166 if abs not in names:
4144 names[abs] = m.rel(abs), m.exact(abs)
4167 names[abs] = m.rel(abs), m.exact(abs)
4145
4168
4146 m = scmutil.matchfiles(repo, names)
4169 m = scmutil.matchfiles(repo, names)
4147 changes = repo.status(match=m)[:4]
4170 changes = repo.status(match=m)[:4]
4148 modified, added, removed, deleted = map(set, changes)
4171 modified, added, removed, deleted = map(set, changes)
4149
4172
4150 # if f is a rename, also revert the source
4173 # if f is a rename, also revert the source
4151 cwd = repo.getcwd()
4174 cwd = repo.getcwd()
4152 for f in added:
4175 for f in added:
4153 src = repo.dirstate.copied(f)
4176 src = repo.dirstate.copied(f)
4154 if src and src not in names and repo.dirstate[src] == 'r':
4177 if src and src not in names and repo.dirstate[src] == 'r':
4155 removed.add(src)
4178 removed.add(src)
4156 names[src] = (repo.pathto(src, cwd), True)
4179 names[src] = (repo.pathto(src, cwd), True)
4157
4180
4158 def removeforget(abs):
4181 def removeforget(abs):
4159 if repo.dirstate[abs] == 'a':
4182 if repo.dirstate[abs] == 'a':
4160 return _('forgetting %s\n')
4183 return _('forgetting %s\n')
4161 return _('removing %s\n')
4184 return _('removing %s\n')
4162
4185
4163 revert = ([], _('reverting %s\n'))
4186 revert = ([], _('reverting %s\n'))
4164 add = ([], _('adding %s\n'))
4187 add = ([], _('adding %s\n'))
4165 remove = ([], removeforget)
4188 remove = ([], removeforget)
4166 undelete = ([], _('undeleting %s\n'))
4189 undelete = ([], _('undeleting %s\n'))
4167
4190
4168 disptable = (
4191 disptable = (
4169 # dispatch table:
4192 # dispatch table:
4170 # file state
4193 # file state
4171 # action if in target manifest
4194 # action if in target manifest
4172 # action if not in target manifest
4195 # action if not in target manifest
4173 # make backup if in target manifest
4196 # make backup if in target manifest
4174 # make backup if not in target manifest
4197 # make backup if not in target manifest
4175 (modified, revert, remove, True, True),
4198 (modified, revert, remove, True, True),
4176 (added, revert, remove, True, False),
4199 (added, revert, remove, True, False),
4177 (removed, undelete, None, False, False),
4200 (removed, undelete, None, False, False),
4178 (deleted, revert, remove, False, False),
4201 (deleted, revert, remove, False, False),
4179 )
4202 )
4180
4203
4181 for abs, (rel, exact) in sorted(names.items()):
4204 for abs, (rel, exact) in sorted(names.items()):
4182 mfentry = mf.get(abs)
4205 mfentry = mf.get(abs)
4183 target = repo.wjoin(abs)
4206 target = repo.wjoin(abs)
4184 def handle(xlist, dobackup):
4207 def handle(xlist, dobackup):
4185 xlist[0].append(abs)
4208 xlist[0].append(abs)
4186 if (dobackup and not opts.get('no_backup') and
4209 if (dobackup and not opts.get('no_backup') and
4187 os.path.lexists(target)):
4210 os.path.lexists(target)):
4188 bakname = "%s.orig" % rel
4211 bakname = "%s.orig" % rel
4189 ui.note(_('saving current version of %s as %s\n') %
4212 ui.note(_('saving current version of %s as %s\n') %
4190 (rel, bakname))
4213 (rel, bakname))
4191 if not opts.get('dry_run'):
4214 if not opts.get('dry_run'):
4192 util.rename(target, bakname)
4215 util.rename(target, bakname)
4193 if ui.verbose or not exact:
4216 if ui.verbose or not exact:
4194 msg = xlist[1]
4217 msg = xlist[1]
4195 if not isinstance(msg, basestring):
4218 if not isinstance(msg, basestring):
4196 msg = msg(abs)
4219 msg = msg(abs)
4197 ui.status(msg % rel)
4220 ui.status(msg % rel)
4198 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4221 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4199 if abs not in table:
4222 if abs not in table:
4200 continue
4223 continue
4201 # file has changed in dirstate
4224 # file has changed in dirstate
4202 if mfentry:
4225 if mfentry:
4203 handle(hitlist, backuphit)
4226 handle(hitlist, backuphit)
4204 elif misslist is not None:
4227 elif misslist is not None:
4205 handle(misslist, backupmiss)
4228 handle(misslist, backupmiss)
4206 break
4229 break
4207 else:
4230 else:
4208 if abs not in repo.dirstate:
4231 if abs not in repo.dirstate:
4209 if mfentry:
4232 if mfentry:
4210 handle(add, True)
4233 handle(add, True)
4211 elif exact:
4234 elif exact:
4212 ui.warn(_('file not managed: %s\n') % rel)
4235 ui.warn(_('file not managed: %s\n') % rel)
4213 continue
4236 continue
4214 # file has not changed in dirstate
4237 # file has not changed in dirstate
4215 if node == parent:
4238 if node == parent:
4216 if exact:
4239 if exact:
4217 ui.warn(_('no changes needed to %s\n') % rel)
4240 ui.warn(_('no changes needed to %s\n') % rel)
4218 continue
4241 continue
4219 if pmf is None:
4242 if pmf is None:
4220 # only need parent manifest in this unlikely case,
4243 # only need parent manifest in this unlikely case,
4221 # so do not read by default
4244 # so do not read by default
4222 pmf = repo[parent].manifest()
4245 pmf = repo[parent].manifest()
4223 if abs in pmf:
4246 if abs in pmf:
4224 if mfentry:
4247 if mfentry:
4225 # if version of file is same in parent and target
4248 # if version of file is same in parent and target
4226 # manifests, do nothing
4249 # manifests, do nothing
4227 if (pmf[abs] != mfentry or
4250 if (pmf[abs] != mfentry or
4228 pmf.flags(abs) != mf.flags(abs)):
4251 pmf.flags(abs) != mf.flags(abs)):
4229 handle(revert, False)
4252 handle(revert, False)
4230 else:
4253 else:
4231 handle(remove, False)
4254 handle(remove, False)
4232
4255
4233 if not opts.get('dry_run'):
4256 if not opts.get('dry_run'):
4234 def checkout(f):
4257 def checkout(f):
4235 fc = ctx[f]
4258 fc = ctx[f]
4236 repo.wwrite(f, fc.data(), fc.flags())
4259 repo.wwrite(f, fc.data(), fc.flags())
4237
4260
4238 audit_path = scmutil.pathauditor(repo.root)
4261 audit_path = scmutil.pathauditor(repo.root)
4239 for f in remove[0]:
4262 for f in remove[0]:
4240 if repo.dirstate[f] == 'a':
4263 if repo.dirstate[f] == 'a':
4241 repo.dirstate.forget(f)
4264 repo.dirstate.forget(f)
4242 continue
4265 continue
4243 audit_path(f)
4266 audit_path(f)
4244 try:
4267 try:
4245 util.unlinkpath(repo.wjoin(f))
4268 util.unlinkpath(repo.wjoin(f))
4246 except OSError:
4269 except OSError:
4247 pass
4270 pass
4248 repo.dirstate.remove(f)
4271 repo.dirstate.remove(f)
4249
4272
4250 normal = None
4273 normal = None
4251 if node == parent:
4274 if node == parent:
4252 # We're reverting to our parent. If possible, we'd like status
4275 # We're reverting to our parent. If possible, we'd like status
4253 # to report the file as clean. We have to use normallookup for
4276 # to report the file as clean. We have to use normallookup for
4254 # merges to avoid losing information about merged/dirty files.
4277 # merges to avoid losing information about merged/dirty files.
4255 if p2 != nullid:
4278 if p2 != nullid:
4256 normal = repo.dirstate.normallookup
4279 normal = repo.dirstate.normallookup
4257 else:
4280 else:
4258 normal = repo.dirstate.normal
4281 normal = repo.dirstate.normal
4259 for f in revert[0]:
4282 for f in revert[0]:
4260 checkout(f)
4283 checkout(f)
4261 if normal:
4284 if normal:
4262 normal(f)
4285 normal(f)
4263
4286
4264 for f in add[0]:
4287 for f in add[0]:
4265 checkout(f)
4288 checkout(f)
4266 repo.dirstate.add(f)
4289 repo.dirstate.add(f)
4267
4290
4268 normal = repo.dirstate.normallookup
4291 normal = repo.dirstate.normallookup
4269 if node == parent and p2 == nullid:
4292 if node == parent and p2 == nullid:
4270 normal = repo.dirstate.normal
4293 normal = repo.dirstate.normal
4271 for f in undelete[0]:
4294 for f in undelete[0]:
4272 checkout(f)
4295 checkout(f)
4273 normal(f)
4296 normal(f)
4274
4297
4275 finally:
4298 finally:
4276 wlock.release()
4299 wlock.release()
4277
4300
4278 @command('rollback', dryrunopts)
4301 @command('rollback', dryrunopts)
4279 def rollback(ui, repo, **opts):
4302 def rollback(ui, repo, **opts):
4280 """roll back the last transaction (dangerous)
4303 """roll back the last transaction (dangerous)
4281
4304
4282 This command should be used with care. There is only one level of
4305 This command should be used with care. There is only one level of
4283 rollback, and there is no way to undo a rollback. It will also
4306 rollback, and there is no way to undo a rollback. It will also
4284 restore the dirstate at the time of the last transaction, losing
4307 restore the dirstate at the time of the last transaction, losing
4285 any dirstate changes since that time. This command does not alter
4308 any dirstate changes since that time. This command does not alter
4286 the working directory.
4309 the working directory.
4287
4310
4288 Transactions are used to encapsulate the effects of all commands
4311 Transactions are used to encapsulate the effects of all commands
4289 that create new changesets or propagate existing changesets into a
4312 that create new changesets or propagate existing changesets into a
4290 repository. For example, the following commands are transactional,
4313 repository. For example, the following commands are transactional,
4291 and their effects can be rolled back:
4314 and their effects can be rolled back:
4292
4315
4293 - commit
4316 - commit
4294 - import
4317 - import
4295 - pull
4318 - pull
4296 - push (with this repository as the destination)
4319 - push (with this repository as the destination)
4297 - unbundle
4320 - unbundle
4298
4321
4299 This command is not intended for use on public repositories. Once
4322 This command is not intended for use on public repositories. Once
4300 changes are visible for pull by other users, rolling a transaction
4323 changes are visible for pull by other users, rolling a transaction
4301 back locally is ineffective (someone else may already have pulled
4324 back locally is ineffective (someone else may already have pulled
4302 the changes). Furthermore, a race is possible with readers of the
4325 the changes). Furthermore, a race is possible with readers of the
4303 repository; for example an in-progress pull from the repository
4326 repository; for example an in-progress pull from the repository
4304 may fail if a rollback is performed.
4327 may fail if a rollback is performed.
4305
4328
4306 Returns 0 on success, 1 if no rollback data is available.
4329 Returns 0 on success, 1 if no rollback data is available.
4307 """
4330 """
4308 return repo.rollback(opts.get('dry_run'))
4331 return repo.rollback(opts.get('dry_run'))
4309
4332
4310 @command('root', [])
4333 @command('root', [])
4311 def root(ui, repo):
4334 def root(ui, repo):
4312 """print the root (top) of the current working directory
4335 """print the root (top) of the current working directory
4313
4336
4314 Print the root directory of the current repository.
4337 Print the root directory of the current repository.
4315
4338
4316 Returns 0 on success.
4339 Returns 0 on success.
4317 """
4340 """
4318 ui.write(repo.root + "\n")
4341 ui.write(repo.root + "\n")
4319
4342
4320 @command('^serve',
4343 @command('^serve',
4321 [('A', 'accesslog', '', _('name of access log file to write to'),
4344 [('A', 'accesslog', '', _('name of access log file to write to'),
4322 _('FILE')),
4345 _('FILE')),
4323 ('d', 'daemon', None, _('run server in background')),
4346 ('d', 'daemon', None, _('run server in background')),
4324 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4347 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4325 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4348 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4326 # use string type, then we can check if something was passed
4349 # use string type, then we can check if something was passed
4327 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4350 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4328 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4351 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4329 _('ADDR')),
4352 _('ADDR')),
4330 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4353 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4331 _('PREFIX')),
4354 _('PREFIX')),
4332 ('n', 'name', '',
4355 ('n', 'name', '',
4333 _('name to show in web pages (default: working directory)'), _('NAME')),
4356 _('name to show in web pages (default: working directory)'), _('NAME')),
4334 ('', 'web-conf', '',
4357 ('', 'web-conf', '',
4335 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4358 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4336 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4359 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4337 _('FILE')),
4360 _('FILE')),
4338 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4361 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4339 ('', 'stdio', None, _('for remote clients')),
4362 ('', 'stdio', None, _('for remote clients')),
4340 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4363 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4341 ('', 'style', '', _('template style to use'), _('STYLE')),
4364 ('', 'style', '', _('template style to use'), _('STYLE')),
4342 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4365 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4343 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4366 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4344 _('[OPTION]...'))
4367 _('[OPTION]...'))
4345 def serve(ui, repo, **opts):
4368 def serve(ui, repo, **opts):
4346 """start stand-alone webserver
4369 """start stand-alone webserver
4347
4370
4348 Start a local HTTP repository browser and pull server. You can use
4371 Start a local HTTP repository browser and pull server. You can use
4349 this for ad-hoc sharing and browsing of repositories. It is
4372 this for ad-hoc sharing and browsing of repositories. It is
4350 recommended to use a real web server to serve a repository for
4373 recommended to use a real web server to serve a repository for
4351 longer periods of time.
4374 longer periods of time.
4352
4375
4353 Please note that the server does not implement access control.
4376 Please note that the server does not implement access control.
4354 This means that, by default, anybody can read from the server and
4377 This means that, by default, anybody can read from the server and
4355 nobody can write to it by default. Set the ``web.allow_push``
4378 nobody can write to it by default. Set the ``web.allow_push``
4356 option to ``*`` to allow everybody to push to the server. You
4379 option to ``*`` to allow everybody to push to the server. You
4357 should use a real web server if you need to authenticate users.
4380 should use a real web server if you need to authenticate users.
4358
4381
4359 By default, the server logs accesses to stdout and errors to
4382 By default, the server logs accesses to stdout and errors to
4360 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4383 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4361 files.
4384 files.
4362
4385
4363 To have the server choose a free port number to listen on, specify
4386 To have the server choose a free port number to listen on, specify
4364 a port number of 0; in this case, the server will print the port
4387 a port number of 0; in this case, the server will print the port
4365 number it uses.
4388 number it uses.
4366
4389
4367 Returns 0 on success.
4390 Returns 0 on success.
4368 """
4391 """
4369
4392
4370 if opts["stdio"]:
4393 if opts["stdio"]:
4371 if repo is None:
4394 if repo is None:
4372 raise error.RepoError(_("There is no Mercurial repository here"
4395 raise error.RepoError(_("There is no Mercurial repository here"
4373 " (.hg not found)"))
4396 " (.hg not found)"))
4374 s = sshserver.sshserver(ui, repo)
4397 s = sshserver.sshserver(ui, repo)
4375 s.serve_forever()
4398 s.serve_forever()
4376
4399
4377 # this way we can check if something was given in the command-line
4400 # this way we can check if something was given in the command-line
4378 if opts.get('port'):
4401 if opts.get('port'):
4379 opts['port'] = util.getport(opts.get('port'))
4402 opts['port'] = util.getport(opts.get('port'))
4380
4403
4381 baseui = repo and repo.baseui or ui
4404 baseui = repo and repo.baseui or ui
4382 optlist = ("name templates style address port prefix ipv6"
4405 optlist = ("name templates style address port prefix ipv6"
4383 " accesslog errorlog certificate encoding")
4406 " accesslog errorlog certificate encoding")
4384 for o in optlist.split():
4407 for o in optlist.split():
4385 val = opts.get(o, '')
4408 val = opts.get(o, '')
4386 if val in (None, ''): # should check against default options instead
4409 if val in (None, ''): # should check against default options instead
4387 continue
4410 continue
4388 baseui.setconfig("web", o, val)
4411 baseui.setconfig("web", o, val)
4389 if repo and repo.ui != baseui:
4412 if repo and repo.ui != baseui:
4390 repo.ui.setconfig("web", o, val)
4413 repo.ui.setconfig("web", o, val)
4391
4414
4392 o = opts.get('web_conf') or opts.get('webdir_conf')
4415 o = opts.get('web_conf') or opts.get('webdir_conf')
4393 if not o:
4416 if not o:
4394 if not repo:
4417 if not repo:
4395 raise error.RepoError(_("There is no Mercurial repository"
4418 raise error.RepoError(_("There is no Mercurial repository"
4396 " here (.hg not found)"))
4419 " here (.hg not found)"))
4397 o = repo.root
4420 o = repo.root
4398
4421
4399 app = hgweb.hgweb(o, baseui=ui)
4422 app = hgweb.hgweb(o, baseui=ui)
4400
4423
4401 class service(object):
4424 class service(object):
4402 def init(self):
4425 def init(self):
4403 util.setsignalhandler()
4426 util.setsignalhandler()
4404 self.httpd = hgweb.server.create_server(ui, app)
4427 self.httpd = hgweb.server.create_server(ui, app)
4405
4428
4406 if opts['port'] and not ui.verbose:
4429 if opts['port'] and not ui.verbose:
4407 return
4430 return
4408
4431
4409 if self.httpd.prefix:
4432 if self.httpd.prefix:
4410 prefix = self.httpd.prefix.strip('/') + '/'
4433 prefix = self.httpd.prefix.strip('/') + '/'
4411 else:
4434 else:
4412 prefix = ''
4435 prefix = ''
4413
4436
4414 port = ':%d' % self.httpd.port
4437 port = ':%d' % self.httpd.port
4415 if port == ':80':
4438 if port == ':80':
4416 port = ''
4439 port = ''
4417
4440
4418 bindaddr = self.httpd.addr
4441 bindaddr = self.httpd.addr
4419 if bindaddr == '0.0.0.0':
4442 if bindaddr == '0.0.0.0':
4420 bindaddr = '*'
4443 bindaddr = '*'
4421 elif ':' in bindaddr: # IPv6
4444 elif ':' in bindaddr: # IPv6
4422 bindaddr = '[%s]' % bindaddr
4445 bindaddr = '[%s]' % bindaddr
4423
4446
4424 fqaddr = self.httpd.fqaddr
4447 fqaddr = self.httpd.fqaddr
4425 if ':' in fqaddr:
4448 if ':' in fqaddr:
4426 fqaddr = '[%s]' % fqaddr
4449 fqaddr = '[%s]' % fqaddr
4427 if opts['port']:
4450 if opts['port']:
4428 write = ui.status
4451 write = ui.status
4429 else:
4452 else:
4430 write = ui.write
4453 write = ui.write
4431 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4454 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4432 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4455 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4433
4456
4434 def run(self):
4457 def run(self):
4435 self.httpd.serve_forever()
4458 self.httpd.serve_forever()
4436
4459
4437 service = service()
4460 service = service()
4438
4461
4439 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4462 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4440
4463
4441 @command('showconfig|debugconfig',
4464 @command('showconfig|debugconfig',
4442 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4465 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4443 _('[-u] [NAME]...'))
4466 _('[-u] [NAME]...'))
4444 def showconfig(ui, repo, *values, **opts):
4467 def showconfig(ui, repo, *values, **opts):
4445 """show combined config settings from all hgrc files
4468 """show combined config settings from all hgrc files
4446
4469
4447 With no arguments, print names and values of all config items.
4470 With no arguments, print names and values of all config items.
4448
4471
4449 With one argument of the form section.name, print just the value
4472 With one argument of the form section.name, print just the value
4450 of that config item.
4473 of that config item.
4451
4474
4452 With multiple arguments, print names and values of all config
4475 With multiple arguments, print names and values of all config
4453 items with matching section names.
4476 items with matching section names.
4454
4477
4455 With --debug, the source (filename and line number) is printed
4478 With --debug, the source (filename and line number) is printed
4456 for each config item.
4479 for each config item.
4457
4480
4458 Returns 0 on success.
4481 Returns 0 on success.
4459 """
4482 """
4460
4483
4461 for f in scmutil.rcpath():
4484 for f in scmutil.rcpath():
4462 ui.debug(_('read config from: %s\n') % f)
4485 ui.debug(_('read config from: %s\n') % f)
4463 untrusted = bool(opts.get('untrusted'))
4486 untrusted = bool(opts.get('untrusted'))
4464 if values:
4487 if values:
4465 sections = [v for v in values if '.' not in v]
4488 sections = [v for v in values if '.' not in v]
4466 items = [v for v in values if '.' in v]
4489 items = [v for v in values if '.' in v]
4467 if len(items) > 1 or items and sections:
4490 if len(items) > 1 or items and sections:
4468 raise util.Abort(_('only one config item permitted'))
4491 raise util.Abort(_('only one config item permitted'))
4469 for section, name, value in ui.walkconfig(untrusted=untrusted):
4492 for section, name, value in ui.walkconfig(untrusted=untrusted):
4470 value = str(value).replace('\n', '\\n')
4493 value = str(value).replace('\n', '\\n')
4471 sectname = section + '.' + name
4494 sectname = section + '.' + name
4472 if values:
4495 if values:
4473 for v in values:
4496 for v in values:
4474 if v == section:
4497 if v == section:
4475 ui.debug('%s: ' %
4498 ui.debug('%s: ' %
4476 ui.configsource(section, name, untrusted))
4499 ui.configsource(section, name, untrusted))
4477 ui.write('%s=%s\n' % (sectname, value))
4500 ui.write('%s=%s\n' % (sectname, value))
4478 elif v == sectname:
4501 elif v == sectname:
4479 ui.debug('%s: ' %
4502 ui.debug('%s: ' %
4480 ui.configsource(section, name, untrusted))
4503 ui.configsource(section, name, untrusted))
4481 ui.write(value, '\n')
4504 ui.write(value, '\n')
4482 else:
4505 else:
4483 ui.debug('%s: ' %
4506 ui.debug('%s: ' %
4484 ui.configsource(section, name, untrusted))
4507 ui.configsource(section, name, untrusted))
4485 ui.write('%s=%s\n' % (sectname, value))
4508 ui.write('%s=%s\n' % (sectname, value))
4486
4509
4487 @command('^status|st',
4510 @command('^status|st',
4488 [('A', 'all', None, _('show status of all files')),
4511 [('A', 'all', None, _('show status of all files')),
4489 ('m', 'modified', None, _('show only modified files')),
4512 ('m', 'modified', None, _('show only modified files')),
4490 ('a', 'added', None, _('show only added files')),
4513 ('a', 'added', None, _('show only added files')),
4491 ('r', 'removed', None, _('show only removed files')),
4514 ('r', 'removed', None, _('show only removed files')),
4492 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4515 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4493 ('c', 'clean', None, _('show only files without changes')),
4516 ('c', 'clean', None, _('show only files without changes')),
4494 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4517 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4495 ('i', 'ignored', None, _('show only ignored files')),
4518 ('i', 'ignored', None, _('show only ignored files')),
4496 ('n', 'no-status', None, _('hide status prefix')),
4519 ('n', 'no-status', None, _('hide status prefix')),
4497 ('C', 'copies', None, _('show source of copied files')),
4520 ('C', 'copies', None, _('show source of copied files')),
4498 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4521 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4499 ('', 'rev', [], _('show difference from revision'), _('REV')),
4522 ('', 'rev', [], _('show difference from revision'), _('REV')),
4500 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4523 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4501 ] + walkopts + subrepoopts,
4524 ] + walkopts + subrepoopts,
4502 _('[OPTION]... [FILE]...'))
4525 _('[OPTION]... [FILE]...'))
4503 def status(ui, repo, *pats, **opts):
4526 def status(ui, repo, *pats, **opts):
4504 """show changed files in the working directory
4527 """show changed files in the working directory
4505
4528
4506 Show status of files in the repository. If names are given, only
4529 Show status of files in the repository. If names are given, only
4507 files that match are shown. Files that are clean or ignored or
4530 files that match are shown. Files that are clean or ignored or
4508 the source of a copy/move operation, are not listed unless
4531 the source of a copy/move operation, are not listed unless
4509 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4532 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4510 Unless options described with "show only ..." are given, the
4533 Unless options described with "show only ..." are given, the
4511 options -mardu are used.
4534 options -mardu are used.
4512
4535
4513 Option -q/--quiet hides untracked (unknown and ignored) files
4536 Option -q/--quiet hides untracked (unknown and ignored) files
4514 unless explicitly requested with -u/--unknown or -i/--ignored.
4537 unless explicitly requested with -u/--unknown or -i/--ignored.
4515
4538
4516 .. note::
4539 .. note::
4517 status may appear to disagree with diff if permissions have
4540 status may appear to disagree with diff if permissions have
4518 changed or a merge has occurred. The standard diff format does
4541 changed or a merge has occurred. The standard diff format does
4519 not report permission changes and diff only reports changes
4542 not report permission changes and diff only reports changes
4520 relative to one merge parent.
4543 relative to one merge parent.
4521
4544
4522 If one revision is given, it is used as the base revision.
4545 If one revision is given, it is used as the base revision.
4523 If two revisions are given, the differences between them are
4546 If two revisions are given, the differences between them are
4524 shown. The --change option can also be used as a shortcut to list
4547 shown. The --change option can also be used as a shortcut to list
4525 the changed files of a revision from its first parent.
4548 the changed files of a revision from its first parent.
4526
4549
4527 The codes used to show the status of files are::
4550 The codes used to show the status of files are::
4528
4551
4529 M = modified
4552 M = modified
4530 A = added
4553 A = added
4531 R = removed
4554 R = removed
4532 C = clean
4555 C = clean
4533 ! = missing (deleted by non-hg command, but still tracked)
4556 ! = missing (deleted by non-hg command, but still tracked)
4534 ? = not tracked
4557 ? = not tracked
4535 I = ignored
4558 I = ignored
4536 = origin of the previous file listed as A (added)
4559 = origin of the previous file listed as A (added)
4537
4560
4538 Returns 0 on success.
4561 Returns 0 on success.
4539 """
4562 """
4540
4563
4541 revs = opts.get('rev')
4564 revs = opts.get('rev')
4542 change = opts.get('change')
4565 change = opts.get('change')
4543
4566
4544 if revs and change:
4567 if revs and change:
4545 msg = _('cannot specify --rev and --change at the same time')
4568 msg = _('cannot specify --rev and --change at the same time')
4546 raise util.Abort(msg)
4569 raise util.Abort(msg)
4547 elif change:
4570 elif change:
4548 node2 = repo.lookup(change)
4571 node2 = repo.lookup(change)
4549 node1 = repo[node2].p1().node()
4572 node1 = repo[node2].p1().node()
4550 else:
4573 else:
4551 node1, node2 = scmutil.revpair(repo, revs)
4574 node1, node2 = scmutil.revpair(repo, revs)
4552
4575
4553 cwd = (pats and repo.getcwd()) or ''
4576 cwd = (pats and repo.getcwd()) or ''
4554 end = opts.get('print0') and '\0' or '\n'
4577 end = opts.get('print0') and '\0' or '\n'
4555 copy = {}
4578 copy = {}
4556 states = 'modified added removed deleted unknown ignored clean'.split()
4579 states = 'modified added removed deleted unknown ignored clean'.split()
4557 show = [k for k in states if opts.get(k)]
4580 show = [k for k in states if opts.get(k)]
4558 if opts.get('all'):
4581 if opts.get('all'):
4559 show += ui.quiet and (states[:4] + ['clean']) or states
4582 show += ui.quiet and (states[:4] + ['clean']) or states
4560 if not show:
4583 if not show:
4561 show = ui.quiet and states[:4] or states[:5]
4584 show = ui.quiet and states[:4] or states[:5]
4562
4585
4563 stat = repo.status(node1, node2, scmutil.match(repo, pats, opts),
4586 stat = repo.status(node1, node2, scmutil.match(repo, pats, opts),
4564 'ignored' in show, 'clean' in show, 'unknown' in show,
4587 'ignored' in show, 'clean' in show, 'unknown' in show,
4565 opts.get('subrepos'))
4588 opts.get('subrepos'))
4566 changestates = zip(states, 'MAR!?IC', stat)
4589 changestates = zip(states, 'MAR!?IC', stat)
4567
4590
4568 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4591 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4569 ctxn = repo[nullid]
4592 ctxn = repo[nullid]
4570 ctx1 = repo[node1]
4593 ctx1 = repo[node1]
4571 ctx2 = repo[node2]
4594 ctx2 = repo[node2]
4572 added = stat[1]
4595 added = stat[1]
4573 if node2 is None:
4596 if node2 is None:
4574 added = stat[0] + stat[1] # merged?
4597 added = stat[0] + stat[1] # merged?
4575
4598
4576 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4599 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4577 if k in added:
4600 if k in added:
4578 copy[k] = v
4601 copy[k] = v
4579 elif v in added:
4602 elif v in added:
4580 copy[v] = k
4603 copy[v] = k
4581
4604
4582 for state, char, files in changestates:
4605 for state, char, files in changestates:
4583 if state in show:
4606 if state in show:
4584 format = "%s %%s%s" % (char, end)
4607 format = "%s %%s%s" % (char, end)
4585 if opts.get('no_status'):
4608 if opts.get('no_status'):
4586 format = "%%s%s" % end
4609 format = "%%s%s" % end
4587
4610
4588 for f in files:
4611 for f in files:
4589 ui.write(format % repo.pathto(f, cwd),
4612 ui.write(format % repo.pathto(f, cwd),
4590 label='status.' + state)
4613 label='status.' + state)
4591 if f in copy:
4614 if f in copy:
4592 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4615 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4593 label='status.copied')
4616 label='status.copied')
4594
4617
4595 @command('^summary|sum',
4618 @command('^summary|sum',
4596 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4619 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4597 def summary(ui, repo, **opts):
4620 def summary(ui, repo, **opts):
4598 """summarize working directory state
4621 """summarize working directory state
4599
4622
4600 This generates a brief summary of the working directory state,
4623 This generates a brief summary of the working directory state,
4601 including parents, branch, commit status, and available updates.
4624 including parents, branch, commit status, and available updates.
4602
4625
4603 With the --remote option, this will check the default paths for
4626 With the --remote option, this will check the default paths for
4604 incoming and outgoing changes. This can be time-consuming.
4627 incoming and outgoing changes. This can be time-consuming.
4605
4628
4606 Returns 0 on success.
4629 Returns 0 on success.
4607 """
4630 """
4608
4631
4609 ctx = repo[None]
4632 ctx = repo[None]
4610 parents = ctx.parents()
4633 parents = ctx.parents()
4611 pnode = parents[0].node()
4634 pnode = parents[0].node()
4612
4635
4613 for p in parents:
4636 for p in parents:
4614 # label with log.changeset (instead of log.parent) since this
4637 # label with log.changeset (instead of log.parent) since this
4615 # shows a working directory parent *changeset*:
4638 # shows a working directory parent *changeset*:
4616 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4639 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4617 label='log.changeset')
4640 label='log.changeset')
4618 ui.write(' '.join(p.tags()), label='log.tag')
4641 ui.write(' '.join(p.tags()), label='log.tag')
4619 if p.bookmarks():
4642 if p.bookmarks():
4620 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
4643 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
4621 if p.rev() == -1:
4644 if p.rev() == -1:
4622 if not len(repo):
4645 if not len(repo):
4623 ui.write(_(' (empty repository)'))
4646 ui.write(_(' (empty repository)'))
4624 else:
4647 else:
4625 ui.write(_(' (no revision checked out)'))
4648 ui.write(_(' (no revision checked out)'))
4626 ui.write('\n')
4649 ui.write('\n')
4627 if p.description():
4650 if p.description():
4628 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4651 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4629 label='log.summary')
4652 label='log.summary')
4630
4653
4631 branch = ctx.branch()
4654 branch = ctx.branch()
4632 bheads = repo.branchheads(branch)
4655 bheads = repo.branchheads(branch)
4633 m = _('branch: %s\n') % branch
4656 m = _('branch: %s\n') % branch
4634 if branch != 'default':
4657 if branch != 'default':
4635 ui.write(m, label='log.branch')
4658 ui.write(m, label='log.branch')
4636 else:
4659 else:
4637 ui.status(m, label='log.branch')
4660 ui.status(m, label='log.branch')
4638
4661
4639 st = list(repo.status(unknown=True))[:6]
4662 st = list(repo.status(unknown=True))[:6]
4640
4663
4641 c = repo.dirstate.copies()
4664 c = repo.dirstate.copies()
4642 copied, renamed = [], []
4665 copied, renamed = [], []
4643 for d, s in c.iteritems():
4666 for d, s in c.iteritems():
4644 if s in st[2]:
4667 if s in st[2]:
4645 st[2].remove(s)
4668 st[2].remove(s)
4646 renamed.append(d)
4669 renamed.append(d)
4647 else:
4670 else:
4648 copied.append(d)
4671 copied.append(d)
4649 if d in st[1]:
4672 if d in st[1]:
4650 st[1].remove(d)
4673 st[1].remove(d)
4651 st.insert(3, renamed)
4674 st.insert(3, renamed)
4652 st.insert(4, copied)
4675 st.insert(4, copied)
4653
4676
4654 ms = mergemod.mergestate(repo)
4677 ms = mergemod.mergestate(repo)
4655 st.append([f for f in ms if ms[f] == 'u'])
4678 st.append([f for f in ms if ms[f] == 'u'])
4656
4679
4657 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4680 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4658 st.append(subs)
4681 st.append(subs)
4659
4682
4660 labels = [ui.label(_('%d modified'), 'status.modified'),
4683 labels = [ui.label(_('%d modified'), 'status.modified'),
4661 ui.label(_('%d added'), 'status.added'),
4684 ui.label(_('%d added'), 'status.added'),
4662 ui.label(_('%d removed'), 'status.removed'),
4685 ui.label(_('%d removed'), 'status.removed'),
4663 ui.label(_('%d renamed'), 'status.copied'),
4686 ui.label(_('%d renamed'), 'status.copied'),
4664 ui.label(_('%d copied'), 'status.copied'),
4687 ui.label(_('%d copied'), 'status.copied'),
4665 ui.label(_('%d deleted'), 'status.deleted'),
4688 ui.label(_('%d deleted'), 'status.deleted'),
4666 ui.label(_('%d unknown'), 'status.unknown'),
4689 ui.label(_('%d unknown'), 'status.unknown'),
4667 ui.label(_('%d ignored'), 'status.ignored'),
4690 ui.label(_('%d ignored'), 'status.ignored'),
4668 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4691 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4669 ui.label(_('%d subrepos'), 'status.modified')]
4692 ui.label(_('%d subrepos'), 'status.modified')]
4670 t = []
4693 t = []
4671 for s, l in zip(st, labels):
4694 for s, l in zip(st, labels):
4672 if s:
4695 if s:
4673 t.append(l % len(s))
4696 t.append(l % len(s))
4674
4697
4675 t = ', '.join(t)
4698 t = ', '.join(t)
4676 cleanworkdir = False
4699 cleanworkdir = False
4677
4700
4678 if len(parents) > 1:
4701 if len(parents) > 1:
4679 t += _(' (merge)')
4702 t += _(' (merge)')
4680 elif branch != parents[0].branch():
4703 elif branch != parents[0].branch():
4681 t += _(' (new branch)')
4704 t += _(' (new branch)')
4682 elif (parents[0].extra().get('close') and
4705 elif (parents[0].extra().get('close') and
4683 pnode in repo.branchheads(branch, closed=True)):
4706 pnode in repo.branchheads(branch, closed=True)):
4684 t += _(' (head closed)')
4707 t += _(' (head closed)')
4685 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4708 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4686 t += _(' (clean)')
4709 t += _(' (clean)')
4687 cleanworkdir = True
4710 cleanworkdir = True
4688 elif pnode not in bheads:
4711 elif pnode not in bheads:
4689 t += _(' (new branch head)')
4712 t += _(' (new branch head)')
4690
4713
4691 if cleanworkdir:
4714 if cleanworkdir:
4692 ui.status(_('commit: %s\n') % t.strip())
4715 ui.status(_('commit: %s\n') % t.strip())
4693 else:
4716 else:
4694 ui.write(_('commit: %s\n') % t.strip())
4717 ui.write(_('commit: %s\n') % t.strip())
4695
4718
4696 # all ancestors of branch heads - all ancestors of parent = new csets
4719 # all ancestors of branch heads - all ancestors of parent = new csets
4697 new = [0] * len(repo)
4720 new = [0] * len(repo)
4698 cl = repo.changelog
4721 cl = repo.changelog
4699 for a in [cl.rev(n) for n in bheads]:
4722 for a in [cl.rev(n) for n in bheads]:
4700 new[a] = 1
4723 new[a] = 1
4701 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
4724 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
4702 new[a] = 1
4725 new[a] = 1
4703 for a in [p.rev() for p in parents]:
4726 for a in [p.rev() for p in parents]:
4704 if a >= 0:
4727 if a >= 0:
4705 new[a] = 0
4728 new[a] = 0
4706 for a in cl.ancestors(*[p.rev() for p in parents]):
4729 for a in cl.ancestors(*[p.rev() for p in parents]):
4707 new[a] = 0
4730 new[a] = 0
4708 new = sum(new)
4731 new = sum(new)
4709
4732
4710 if new == 0:
4733 if new == 0:
4711 ui.status(_('update: (current)\n'))
4734 ui.status(_('update: (current)\n'))
4712 elif pnode not in bheads:
4735 elif pnode not in bheads:
4713 ui.write(_('update: %d new changesets (update)\n') % new)
4736 ui.write(_('update: %d new changesets (update)\n') % new)
4714 else:
4737 else:
4715 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4738 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4716 (new, len(bheads)))
4739 (new, len(bheads)))
4717
4740
4718 if opts.get('remote'):
4741 if opts.get('remote'):
4719 t = []
4742 t = []
4720 source, branches = hg.parseurl(ui.expandpath('default'))
4743 source, branches = hg.parseurl(ui.expandpath('default'))
4721 other = hg.repository(hg.remoteui(repo, {}), source)
4744 other = hg.repository(hg.remoteui(repo, {}), source)
4722 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4745 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4723 ui.debug('comparing with %s\n' % util.hidepassword(source))
4746 ui.debug('comparing with %s\n' % util.hidepassword(source))
4724 repo.ui.pushbuffer()
4747 repo.ui.pushbuffer()
4725 commoninc = discovery.findcommonincoming(repo, other)
4748 commoninc = discovery.findcommonincoming(repo, other)
4726 _common, incoming, _rheads = commoninc
4749 _common, incoming, _rheads = commoninc
4727 repo.ui.popbuffer()
4750 repo.ui.popbuffer()
4728 if incoming:
4751 if incoming:
4729 t.append(_('1 or more incoming'))
4752 t.append(_('1 or more incoming'))
4730
4753
4731 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
4754 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
4732 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
4755 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
4733 if source != dest:
4756 if source != dest:
4734 other = hg.repository(hg.remoteui(repo, {}), dest)
4757 other = hg.repository(hg.remoteui(repo, {}), dest)
4735 commoninc = None
4758 commoninc = None
4736 ui.debug('comparing with %s\n' % util.hidepassword(dest))
4759 ui.debug('comparing with %s\n' % util.hidepassword(dest))
4737 repo.ui.pushbuffer()
4760 repo.ui.pushbuffer()
4738 common, outheads = discovery.findcommonoutgoing(repo, other,
4761 common, outheads = discovery.findcommonoutgoing(repo, other,
4739 commoninc=commoninc)
4762 commoninc=commoninc)
4740 repo.ui.popbuffer()
4763 repo.ui.popbuffer()
4741 o = repo.changelog.findmissing(common=common, heads=outheads)
4764 o = repo.changelog.findmissing(common=common, heads=outheads)
4742 if o:
4765 if o:
4743 t.append(_('%d outgoing') % len(o))
4766 t.append(_('%d outgoing') % len(o))
4744 if 'bookmarks' in other.listkeys('namespaces'):
4767 if 'bookmarks' in other.listkeys('namespaces'):
4745 lmarks = repo.listkeys('bookmarks')
4768 lmarks = repo.listkeys('bookmarks')
4746 rmarks = other.listkeys('bookmarks')
4769 rmarks = other.listkeys('bookmarks')
4747 diff = set(rmarks) - set(lmarks)
4770 diff = set(rmarks) - set(lmarks)
4748 if len(diff) > 0:
4771 if len(diff) > 0:
4749 t.append(_('%d incoming bookmarks') % len(diff))
4772 t.append(_('%d incoming bookmarks') % len(diff))
4750 diff = set(lmarks) - set(rmarks)
4773 diff = set(lmarks) - set(rmarks)
4751 if len(diff) > 0:
4774 if len(diff) > 0:
4752 t.append(_('%d outgoing bookmarks') % len(diff))
4775 t.append(_('%d outgoing bookmarks') % len(diff))
4753
4776
4754 if t:
4777 if t:
4755 ui.write(_('remote: %s\n') % (', '.join(t)))
4778 ui.write(_('remote: %s\n') % (', '.join(t)))
4756 else:
4779 else:
4757 ui.status(_('remote: (synced)\n'))
4780 ui.status(_('remote: (synced)\n'))
4758
4781
4759 @command('tag',
4782 @command('tag',
4760 [('f', 'force', None, _('force tag')),
4783 [('f', 'force', None, _('force tag')),
4761 ('l', 'local', None, _('make the tag local')),
4784 ('l', 'local', None, _('make the tag local')),
4762 ('r', 'rev', '', _('revision to tag'), _('REV')),
4785 ('r', 'rev', '', _('revision to tag'), _('REV')),
4763 ('', 'remove', None, _('remove a tag')),
4786 ('', 'remove', None, _('remove a tag')),
4764 # -l/--local is already there, commitopts cannot be used
4787 # -l/--local is already there, commitopts cannot be used
4765 ('e', 'edit', None, _('edit commit message')),
4788 ('e', 'edit', None, _('edit commit message')),
4766 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
4789 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
4767 ] + commitopts2,
4790 ] + commitopts2,
4768 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
4791 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
4769 def tag(ui, repo, name1, *names, **opts):
4792 def tag(ui, repo, name1, *names, **opts):
4770 """add one or more tags for the current or given revision
4793 """add one or more tags for the current or given revision
4771
4794
4772 Name a particular revision using <name>.
4795 Name a particular revision using <name>.
4773
4796
4774 Tags are used to name particular revisions of the repository and are
4797 Tags are used to name particular revisions of the repository and are
4775 very useful to compare different revisions, to go back to significant
4798 very useful to compare different revisions, to go back to significant
4776 earlier versions or to mark branch points as releases, etc. Changing
4799 earlier versions or to mark branch points as releases, etc. Changing
4777 an existing tag is normally disallowed; use -f/--force to override.
4800 an existing tag is normally disallowed; use -f/--force to override.
4778
4801
4779 If no revision is given, the parent of the working directory is
4802 If no revision is given, the parent of the working directory is
4780 used, or tip if no revision is checked out.
4803 used, or tip if no revision is checked out.
4781
4804
4782 To facilitate version control, distribution, and merging of tags,
4805 To facilitate version control, distribution, and merging of tags,
4783 they are stored as a file named ".hgtags" which is managed similarly
4806 they are stored as a file named ".hgtags" which is managed similarly
4784 to other project files and can be hand-edited if necessary. This
4807 to other project files and can be hand-edited if necessary. This
4785 also means that tagging creates a new commit. The file
4808 also means that tagging creates a new commit. The file
4786 ".hg/localtags" is used for local tags (not shared among
4809 ".hg/localtags" is used for local tags (not shared among
4787 repositories).
4810 repositories).
4788
4811
4789 Tag commits are usually made at the head of a branch. If the parent
4812 Tag commits are usually made at the head of a branch. If the parent
4790 of the working directory is not a branch head, :hg:`tag` aborts; use
4813 of the working directory is not a branch head, :hg:`tag` aborts; use
4791 -f/--force to force the tag commit to be based on a non-head
4814 -f/--force to force the tag commit to be based on a non-head
4792 changeset.
4815 changeset.
4793
4816
4794 See :hg:`help dates` for a list of formats valid for -d/--date.
4817 See :hg:`help dates` for a list of formats valid for -d/--date.
4795
4818
4796 Since tag names have priority over branch names during revision
4819 Since tag names have priority over branch names during revision
4797 lookup, using an existing branch name as a tag name is discouraged.
4820 lookup, using an existing branch name as a tag name is discouraged.
4798
4821
4799 Returns 0 on success.
4822 Returns 0 on success.
4800 """
4823 """
4801
4824
4802 rev_ = "."
4825 rev_ = "."
4803 names = [t.strip() for t in (name1,) + names]
4826 names = [t.strip() for t in (name1,) + names]
4804 if len(names) != len(set(names)):
4827 if len(names) != len(set(names)):
4805 raise util.Abort(_('tag names must be unique'))
4828 raise util.Abort(_('tag names must be unique'))
4806 for n in names:
4829 for n in names:
4807 if n in ['tip', '.', 'null']:
4830 if n in ['tip', '.', 'null']:
4808 raise util.Abort(_("the name '%s' is reserved") % n)
4831 raise util.Abort(_("the name '%s' is reserved") % n)
4809 if not n:
4832 if not n:
4810 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
4833 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
4811 if opts.get('rev') and opts.get('remove'):
4834 if opts.get('rev') and opts.get('remove'):
4812 raise util.Abort(_("--rev and --remove are incompatible"))
4835 raise util.Abort(_("--rev and --remove are incompatible"))
4813 if opts.get('rev'):
4836 if opts.get('rev'):
4814 rev_ = opts['rev']
4837 rev_ = opts['rev']
4815 message = opts.get('message')
4838 message = opts.get('message')
4816 if opts.get('remove'):
4839 if opts.get('remove'):
4817 expectedtype = opts.get('local') and 'local' or 'global'
4840 expectedtype = opts.get('local') and 'local' or 'global'
4818 for n in names:
4841 for n in names:
4819 if not repo.tagtype(n):
4842 if not repo.tagtype(n):
4820 raise util.Abort(_("tag '%s' does not exist") % n)
4843 raise util.Abort(_("tag '%s' does not exist") % n)
4821 if repo.tagtype(n) != expectedtype:
4844 if repo.tagtype(n) != expectedtype:
4822 if expectedtype == 'global':
4845 if expectedtype == 'global':
4823 raise util.Abort(_("tag '%s' is not a global tag") % n)
4846 raise util.Abort(_("tag '%s' is not a global tag") % n)
4824 else:
4847 else:
4825 raise util.Abort(_("tag '%s' is not a local tag") % n)
4848 raise util.Abort(_("tag '%s' is not a local tag") % n)
4826 rev_ = nullid
4849 rev_ = nullid
4827 if not message:
4850 if not message:
4828 # we don't translate commit messages
4851 # we don't translate commit messages
4829 message = 'Removed tag %s' % ', '.join(names)
4852 message = 'Removed tag %s' % ', '.join(names)
4830 elif not opts.get('force'):
4853 elif not opts.get('force'):
4831 for n in names:
4854 for n in names:
4832 if n in repo.tags():
4855 if n in repo.tags():
4833 raise util.Abort(_("tag '%s' already exists "
4856 raise util.Abort(_("tag '%s' already exists "
4834 "(use -f to force)") % n)
4857 "(use -f to force)") % n)
4835 if not opts.get('local'):
4858 if not opts.get('local'):
4836 p1, p2 = repo.dirstate.parents()
4859 p1, p2 = repo.dirstate.parents()
4837 if p2 != nullid:
4860 if p2 != nullid:
4838 raise util.Abort(_('uncommitted merge'))
4861 raise util.Abort(_('uncommitted merge'))
4839 bheads = repo.branchheads()
4862 bheads = repo.branchheads()
4840 if not opts.get('force') and bheads and p1 not in bheads:
4863 if not opts.get('force') and bheads and p1 not in bheads:
4841 raise util.Abort(_('not at a branch head (use -f to force)'))
4864 raise util.Abort(_('not at a branch head (use -f to force)'))
4842 r = scmutil.revsingle(repo, rev_).node()
4865 r = scmutil.revsingle(repo, rev_).node()
4843
4866
4844 if not message:
4867 if not message:
4845 # we don't translate commit messages
4868 # we don't translate commit messages
4846 message = ('Added tag %s for changeset %s' %
4869 message = ('Added tag %s for changeset %s' %
4847 (', '.join(names), short(r)))
4870 (', '.join(names), short(r)))
4848
4871
4849 date = opts.get('date')
4872 date = opts.get('date')
4850 if date:
4873 if date:
4851 date = util.parsedate(date)
4874 date = util.parsedate(date)
4852
4875
4853 if opts.get('edit'):
4876 if opts.get('edit'):
4854 message = ui.edit(message, ui.username())
4877 message = ui.edit(message, ui.username())
4855
4878
4856 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
4879 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
4857
4880
4858 @command('tags', [], '')
4881 @command('tags', [], '')
4859 def tags(ui, repo):
4882 def tags(ui, repo):
4860 """list repository tags
4883 """list repository tags
4861
4884
4862 This lists both regular and local tags. When the -v/--verbose
4885 This lists both regular and local tags. When the -v/--verbose
4863 switch is used, a third column "local" is printed for local tags.
4886 switch is used, a third column "local" is printed for local tags.
4864
4887
4865 Returns 0 on success.
4888 Returns 0 on success.
4866 """
4889 """
4867
4890
4868 hexfunc = ui.debugflag and hex or short
4891 hexfunc = ui.debugflag and hex or short
4869 tagtype = ""
4892 tagtype = ""
4870
4893
4871 for t, n in reversed(repo.tagslist()):
4894 for t, n in reversed(repo.tagslist()):
4872 if ui.quiet:
4895 if ui.quiet:
4873 ui.write("%s\n" % t)
4896 ui.write("%s\n" % t)
4874 continue
4897 continue
4875
4898
4876 hn = hexfunc(n)
4899 hn = hexfunc(n)
4877 r = "%5d:%s" % (repo.changelog.rev(n), hn)
4900 r = "%5d:%s" % (repo.changelog.rev(n), hn)
4878 spaces = " " * (30 - encoding.colwidth(t))
4901 spaces = " " * (30 - encoding.colwidth(t))
4879
4902
4880 if ui.verbose:
4903 if ui.verbose:
4881 if repo.tagtype(t) == 'local':
4904 if repo.tagtype(t) == 'local':
4882 tagtype = " local"
4905 tagtype = " local"
4883 else:
4906 else:
4884 tagtype = ""
4907 tagtype = ""
4885 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
4908 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
4886
4909
4887 @command('tip',
4910 @command('tip',
4888 [('p', 'patch', None, _('show patch')),
4911 [('p', 'patch', None, _('show patch')),
4889 ('g', 'git', None, _('use git extended diff format')),
4912 ('g', 'git', None, _('use git extended diff format')),
4890 ] + templateopts,
4913 ] + templateopts,
4891 _('[-p] [-g]'))
4914 _('[-p] [-g]'))
4892 def tip(ui, repo, **opts):
4915 def tip(ui, repo, **opts):
4893 """show the tip revision
4916 """show the tip revision
4894
4917
4895 The tip revision (usually just called the tip) is the changeset
4918 The tip revision (usually just called the tip) is the changeset
4896 most recently added to the repository (and therefore the most
4919 most recently added to the repository (and therefore the most
4897 recently changed head).
4920 recently changed head).
4898
4921
4899 If you have just made a commit, that commit will be the tip. If
4922 If you have just made a commit, that commit will be the tip. If
4900 you have just pulled changes from another repository, the tip of
4923 you have just pulled changes from another repository, the tip of
4901 that repository becomes the current tip. The "tip" tag is special
4924 that repository becomes the current tip. The "tip" tag is special
4902 and cannot be renamed or assigned to a different changeset.
4925 and cannot be renamed or assigned to a different changeset.
4903
4926
4904 Returns 0 on success.
4927 Returns 0 on success.
4905 """
4928 """
4906 displayer = cmdutil.show_changeset(ui, repo, opts)
4929 displayer = cmdutil.show_changeset(ui, repo, opts)
4907 displayer.show(repo[len(repo) - 1])
4930 displayer.show(repo[len(repo) - 1])
4908 displayer.close()
4931 displayer.close()
4909
4932
4910 @command('unbundle',
4933 @command('unbundle',
4911 [('u', 'update', None,
4934 [('u', 'update', None,
4912 _('update to new branch head if changesets were unbundled'))],
4935 _('update to new branch head if changesets were unbundled'))],
4913 _('[-u] FILE...'))
4936 _('[-u] FILE...'))
4914 def unbundle(ui, repo, fname1, *fnames, **opts):
4937 def unbundle(ui, repo, fname1, *fnames, **opts):
4915 """apply one or more changegroup files
4938 """apply one or more changegroup files
4916
4939
4917 Apply one or more compressed changegroup files generated by the
4940 Apply one or more compressed changegroup files generated by the
4918 bundle command.
4941 bundle command.
4919
4942
4920 Returns 0 on success, 1 if an update has unresolved files.
4943 Returns 0 on success, 1 if an update has unresolved files.
4921 """
4944 """
4922 fnames = (fname1,) + fnames
4945 fnames = (fname1,) + fnames
4923
4946
4924 lock = repo.lock()
4947 lock = repo.lock()
4925 wc = repo['.']
4948 wc = repo['.']
4926 try:
4949 try:
4927 for fname in fnames:
4950 for fname in fnames:
4928 f = url.open(ui, fname)
4951 f = url.open(ui, fname)
4929 gen = changegroup.readbundle(f, fname)
4952 gen = changegroup.readbundle(f, fname)
4930 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
4953 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
4931 lock=lock)
4954 lock=lock)
4932 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
4955 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
4933 finally:
4956 finally:
4934 lock.release()
4957 lock.release()
4935 return postincoming(ui, repo, modheads, opts.get('update'), None)
4958 return postincoming(ui, repo, modheads, opts.get('update'), None)
4936
4959
4937 @command('^update|up|checkout|co',
4960 @command('^update|up|checkout|co',
4938 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4961 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4939 ('c', 'check', None,
4962 ('c', 'check', None,
4940 _('update across branches if no uncommitted changes')),
4963 _('update across branches if no uncommitted changes')),
4941 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4964 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4942 ('r', 'rev', '', _('revision'), _('REV'))],
4965 ('r', 'rev', '', _('revision'), _('REV'))],
4943 _('[-c] [-C] [-d DATE] [[-r] REV]'))
4966 _('[-c] [-C] [-d DATE] [[-r] REV]'))
4944 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
4967 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
4945 """update working directory (or switch revisions)
4968 """update working directory (or switch revisions)
4946
4969
4947 Update the repository's working directory to the specified
4970 Update the repository's working directory to the specified
4948 changeset. If no changeset is specified, update to the tip of the
4971 changeset. If no changeset is specified, update to the tip of the
4949 current named branch.
4972 current named branch.
4950
4973
4951 If the changeset is not a descendant of the working directory's
4974 If the changeset is not a descendant of the working directory's
4952 parent, the update is aborted. With the -c/--check option, the
4975 parent, the update is aborted. With the -c/--check option, the
4953 working directory is checked for uncommitted changes; if none are
4976 working directory is checked for uncommitted changes; if none are
4954 found, the working directory is updated to the specified
4977 found, the working directory is updated to the specified
4955 changeset.
4978 changeset.
4956
4979
4957 The following rules apply when the working directory contains
4980 The following rules apply when the working directory contains
4958 uncommitted changes:
4981 uncommitted changes:
4959
4982
4960 1. If neither -c/--check nor -C/--clean is specified, and if
4983 1. If neither -c/--check nor -C/--clean is specified, and if
4961 the requested changeset is an ancestor or descendant of
4984 the requested changeset is an ancestor or descendant of
4962 the working directory's parent, the uncommitted changes
4985 the working directory's parent, the uncommitted changes
4963 are merged into the requested changeset and the merged
4986 are merged into the requested changeset and the merged
4964 result is left uncommitted. If the requested changeset is
4987 result is left uncommitted. If the requested changeset is
4965 not an ancestor or descendant (that is, it is on another
4988 not an ancestor or descendant (that is, it is on another
4966 branch), the update is aborted and the uncommitted changes
4989 branch), the update is aborted and the uncommitted changes
4967 are preserved.
4990 are preserved.
4968
4991
4969 2. With the -c/--check option, the update is aborted and the
4992 2. With the -c/--check option, the update is aborted and the
4970 uncommitted changes are preserved.
4993 uncommitted changes are preserved.
4971
4994
4972 3. With the -C/--clean option, uncommitted changes are discarded and
4995 3. With the -C/--clean option, uncommitted changes are discarded and
4973 the working directory is updated to the requested changeset.
4996 the working directory is updated to the requested changeset.
4974
4997
4975 Use null as the changeset to remove the working directory (like
4998 Use null as the changeset to remove the working directory (like
4976 :hg:`clone -U`).
4999 :hg:`clone -U`).
4977
5000
4978 If you want to update just one file to an older changeset, use
5001 If you want to update just one file to an older changeset, use
4979 :hg:`revert`.
5002 :hg:`revert`.
4980
5003
4981 See :hg:`help dates` for a list of formats valid for -d/--date.
5004 See :hg:`help dates` for a list of formats valid for -d/--date.
4982
5005
4983 Returns 0 on success, 1 if there are unresolved files.
5006 Returns 0 on success, 1 if there are unresolved files.
4984 """
5007 """
4985 if rev and node:
5008 if rev and node:
4986 raise util.Abort(_("please specify just one revision"))
5009 raise util.Abort(_("please specify just one revision"))
4987
5010
4988 if rev is None or rev == '':
5011 if rev is None or rev == '':
4989 rev = node
5012 rev = node
4990
5013
4991 # if we defined a bookmark, we have to remember the original bookmark name
5014 # if we defined a bookmark, we have to remember the original bookmark name
4992 brev = rev
5015 brev = rev
4993 rev = scmutil.revsingle(repo, rev, rev).rev()
5016 rev = scmutil.revsingle(repo, rev, rev).rev()
4994
5017
4995 if check and clean:
5018 if check and clean:
4996 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5019 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4997
5020
4998 if check:
5021 if check:
4999 # we could use dirty() but we can ignore merge and branch trivia
5022 # we could use dirty() but we can ignore merge and branch trivia
5000 c = repo[None]
5023 c = repo[None]
5001 if c.modified() or c.added() or c.removed():
5024 if c.modified() or c.added() or c.removed():
5002 raise util.Abort(_("uncommitted local changes"))
5025 raise util.Abort(_("uncommitted local changes"))
5003
5026
5004 if date:
5027 if date:
5005 if rev is not None:
5028 if rev is not None:
5006 raise util.Abort(_("you can't specify a revision and a date"))
5029 raise util.Abort(_("you can't specify a revision and a date"))
5007 rev = cmdutil.finddate(ui, repo, date)
5030 rev = cmdutil.finddate(ui, repo, date)
5008
5031
5009 if clean or check:
5032 if clean or check:
5010 ret = hg.clean(repo, rev)
5033 ret = hg.clean(repo, rev)
5011 else:
5034 else:
5012 ret = hg.update(repo, rev)
5035 ret = hg.update(repo, rev)
5013
5036
5014 if brev in repo._bookmarks:
5037 if brev in repo._bookmarks:
5015 bookmarks.setcurrent(repo, brev)
5038 bookmarks.setcurrent(repo, brev)
5016
5039
5017 return ret
5040 return ret
5018
5041
5019 @command('verify', [])
5042 @command('verify', [])
5020 def verify(ui, repo):
5043 def verify(ui, repo):
5021 """verify the integrity of the repository
5044 """verify the integrity of the repository
5022
5045
5023 Verify the integrity of the current repository.
5046 Verify the integrity of the current repository.
5024
5047
5025 This will perform an extensive check of the repository's
5048 This will perform an extensive check of the repository's
5026 integrity, validating the hashes and checksums of each entry in
5049 integrity, validating the hashes and checksums of each entry in
5027 the changelog, manifest, and tracked files, as well as the
5050 the changelog, manifest, and tracked files, as well as the
5028 integrity of their crosslinks and indices.
5051 integrity of their crosslinks and indices.
5029
5052
5030 Returns 0 on success, 1 if errors are encountered.
5053 Returns 0 on success, 1 if errors are encountered.
5031 """
5054 """
5032 return hg.verify(repo)
5055 return hg.verify(repo)
5033
5056
5034 @command('version', [])
5057 @command('version', [])
5035 def version_(ui):
5058 def version_(ui):
5036 """output version and copyright information"""
5059 """output version and copyright information"""
5037 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5060 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5038 % util.version())
5061 % util.version())
5039 ui.status(_(
5062 ui.status(_(
5040 "(see http://mercurial.selenic.com for more information)\n"
5063 "(see http://mercurial.selenic.com for more information)\n"
5041 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5064 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5042 "This is free software; see the source for copying conditions. "
5065 "This is free software; see the source for copying conditions. "
5043 "There is NO\nwarranty; "
5066 "There is NO\nwarranty; "
5044 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5067 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5045 ))
5068 ))
5046
5069
5047 norepo = ("clone init version help debugcommands debugcomplete"
5070 norepo = ("clone init version help debugcommands debugcomplete"
5048 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5071 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5049 " debugknown debuggetbundle debugbundle")
5072 " debugknown debuggetbundle debugbundle")
5050 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5073 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5051 " debugdata debugindex debugindexdot debugrevlog")
5074 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,265 +1,265 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 copy
16 copy
17 diff
17 diff
18 export
18 export
19 forget
19 forget
20 grep
20 grep
21 heads
21 heads
22 help
22 help
23 identify
23 identify
24 import
24 import
25 incoming
25 incoming
26 init
26 init
27 locate
27 locate
28 log
28 log
29 manifest
29 manifest
30 merge
30 merge
31 outgoing
31 outgoing
32 parents
32 parents
33 paths
33 paths
34 pull
34 pull
35 push
35 push
36 recover
36 recover
37 remove
37 remove
38 rename
38 rename
39 resolve
39 resolve
40 revert
40 revert
41 rollback
41 rollback
42 root
42 root
43 serve
43 serve
44 showconfig
44 showconfig
45 status
45 status
46 summary
46 summary
47 tag
47 tag
48 tags
48 tags
49 tip
49 tip
50 unbundle
50 unbundle
51 update
51 update
52 verify
52 verify
53 version
53 version
54
54
55 Show all commands that start with "a"
55 Show all commands that start with "a"
56 $ hg debugcomplete a
56 $ hg debugcomplete a
57 add
57 add
58 addremove
58 addremove
59 annotate
59 annotate
60 archive
60 archive
61
61
62 Do not show debug commands if there are other candidates
62 Do not show debug commands if there are other candidates
63 $ hg debugcomplete d
63 $ hg debugcomplete d
64 diff
64 diff
65
65
66 Show debug commands if there are no other candidates
66 Show debug commands if there are no other candidates
67 $ hg debugcomplete debug
67 $ hg debugcomplete debug
68 debugancestor
68 debugancestor
69 debugbuilddag
69 debugbuilddag
70 debugbundle
70 debugbundle
71 debugcheckstate
71 debugcheckstate
72 debugcommands
72 debugcommands
73 debugcomplete
73 debugcomplete
74 debugconfig
74 debugconfig
75 debugdag
75 debugdag
76 debugdata
76 debugdata
77 debugdate
77 debugdate
78 debugdiscovery
78 debugdiscovery
79 debugfsinfo
79 debugfsinfo
80 debuggetbundle
80 debuggetbundle
81 debugignore
81 debugignore
82 debugindex
82 debugindex
83 debugindexdot
83 debugindexdot
84 debuginstall
84 debuginstall
85 debugknown
85 debugknown
86 debugpushkey
86 debugpushkey
87 debugrebuildstate
87 debugrebuildstate
88 debugrename
88 debugrename
89 debugrevlog
89 debugrevlog
90 debugrevspec
90 debugrevspec
91 debugsetparents
91 debugsetparents
92 debugstate
92 debugstate
93 debugsub
93 debugsub
94 debugwalk
94 debugwalk
95 debugwireargs
95 debugwireargs
96
96
97 Do not show the alias of a debug command if there are other candidates
97 Do not show the alias of a debug command if there are other candidates
98 (this should hide rawcommit)
98 (this should hide rawcommit)
99 $ hg debugcomplete r
99 $ hg debugcomplete r
100 recover
100 recover
101 remove
101 remove
102 rename
102 rename
103 resolve
103 resolve
104 revert
104 revert
105 rollback
105 rollback
106 root
106 root
107 Show the alias of a debug command if there are no other candidates
107 Show the alias of a debug command if there are no other candidates
108 $ hg debugcomplete rawc
108 $ hg debugcomplete rawc
109
109
110
110
111 Show the global options
111 Show the global options
112 $ hg debugcomplete --options | sort
112 $ hg debugcomplete --options | sort
113 --config
113 --config
114 --cwd
114 --cwd
115 --debug
115 --debug
116 --debugger
116 --debugger
117 --encoding
117 --encoding
118 --encodingmode
118 --encodingmode
119 --help
119 --help
120 --noninteractive
120 --noninteractive
121 --profile
121 --profile
122 --quiet
122 --quiet
123 --repository
123 --repository
124 --time
124 --time
125 --traceback
125 --traceback
126 --verbose
126 --verbose
127 --version
127 --version
128 -R
128 -R
129 -h
129 -h
130 -q
130 -q
131 -v
131 -v
132 -y
132 -y
133
133
134 Show the options for the "serve" command
134 Show the options for the "serve" command
135 $ hg debugcomplete --options serve | sort
135 $ hg debugcomplete --options serve | sort
136 --accesslog
136 --accesslog
137 --address
137 --address
138 --certificate
138 --certificate
139 --config
139 --config
140 --cwd
140 --cwd
141 --daemon
141 --daemon
142 --daemon-pipefds
142 --daemon-pipefds
143 --debug
143 --debug
144 --debugger
144 --debugger
145 --encoding
145 --encoding
146 --encodingmode
146 --encodingmode
147 --errorlog
147 --errorlog
148 --help
148 --help
149 --ipv6
149 --ipv6
150 --name
150 --name
151 --noninteractive
151 --noninteractive
152 --pid-file
152 --pid-file
153 --port
153 --port
154 --prefix
154 --prefix
155 --profile
155 --profile
156 --quiet
156 --quiet
157 --repository
157 --repository
158 --stdio
158 --stdio
159 --style
159 --style
160 --templates
160 --templates
161 --time
161 --time
162 --traceback
162 --traceback
163 --verbose
163 --verbose
164 --version
164 --version
165 --web-conf
165 --web-conf
166 -6
166 -6
167 -A
167 -A
168 -E
168 -E
169 -R
169 -R
170 -a
170 -a
171 -d
171 -d
172 -h
172 -h
173 -n
173 -n
174 -p
174 -p
175 -q
175 -q
176 -t
176 -t
177 -v
177 -v
178 -y
178 -y
179
179
180 Show an error if we use --options with an ambiguous abbreviation
180 Show an error if we use --options with an ambiguous abbreviation
181 $ hg debugcomplete --options s
181 $ hg debugcomplete --options s
182 hg: command 's' is ambiguous:
182 hg: command 's' is ambiguous:
183 serve showconfig status summary
183 serve showconfig status summary
184 [255]
184 [255]
185
185
186 Show all commands + options
186 Show all commands + options
187 $ hg debugcommands
187 $ hg debugcommands
188 add: include, exclude, subrepos, dry-run
188 add: include, exclude, subrepos, dry-run
189 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
189 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
190 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
190 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
191 commit: addremove, close-branch, include, exclude, message, logfile, date, user
191 commit: addremove, close-branch, include, exclude, message, logfile, date, user
192 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
192 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
193 export: output, switch-parent, rev, text, git, nodates
193 export: output, switch-parent, rev, text, git, nodates
194 forget: include, exclude
194 forget: include, exclude
195 init: ssh, remotecmd, insecure
195 init: ssh, remotecmd, insecure
196 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
196 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
197 merge: force, tool, rev, preview
197 merge: force, tool, rev, preview
198 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
198 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
199 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
199 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
200 remove: after, force, include, exclude
200 remove: after, force, include, exclude
201 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
201 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
202 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
202 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
203 summary: remote
203 summary: remote
204 update: clean, check, date, rev
204 update: clean, check, date, rev
205 addremove: similarity, include, exclude, dry-run
205 addremove: similarity, include, exclude, dry-run
206 archive: no-decode, prefix, rev, type, subrepos, include, exclude
206 archive: no-decode, prefix, rev, type, subrepos, include, exclude
207 backout: merge, parent, tool, rev, include, exclude, message, logfile, date, user
207 backout: merge, parent, tool, rev, include, exclude, message, logfile, date, user
208 bisect: reset, good, bad, skip, extend, command, noupdate
208 bisect: reset, good, bad, skip, extend, command, noupdate
209 bookmarks: force, rev, delete, rename, inactive
209 bookmarks: force, rev, delete, rename, inactive
210 branch: force, clean
210 branch: force, clean
211 branches: active, closed
211 branches: active, closed
212 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
212 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
213 cat: output, rev, decode, include, exclude
213 cat: output, rev, decode, include, exclude
214 copy: after, force, include, exclude, dry-run
214 copy: after, force, include, exclude, dry-run
215 debugancestor:
215 debugancestor:
216 debugbuilddag: mergeable-file, overwritten-file, new-file
216 debugbuilddag: mergeable-file, overwritten-file, new-file
217 debugbundle: all
217 debugbundle: all
218 debugcheckstate:
218 debugcheckstate:
219 debugcommands:
219 debugcommands:
220 debugcomplete: options
220 debugcomplete: options
221 debugdag: tags, branches, dots, spaces
221 debugdag: tags, branches, dots, spaces
222 debugdata: changelog, manifest
222 debugdata: changelog, manifest
223 debugdate: extended
223 debugdate: extended
224 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
224 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
225 debugfsinfo:
225 debugfsinfo:
226 debuggetbundle: head, common, type
226 debuggetbundle: head, common, type
227 debugignore:
227 debugignore:
228 debugindex: changelog, manifest, format
228 debugindex: changelog, manifest, format
229 debugindexdot:
229 debugindexdot:
230 debuginstall:
230 debuginstall:
231 debugknown:
231 debugknown:
232 debugpushkey:
232 debugpushkey:
233 debugrebuildstate: rev
233 debugrebuildstate: rev
234 debugrename: rev
234 debugrename: rev
235 debugrevlog: changelog, manifest, dump
235 debugrevlog: changelog, manifest, dump
236 debugrevspec:
236 debugrevspec:
237 debugsetparents:
237 debugsetparents:
238 debugstate: nodates, datesort
238 debugstate: nodates, datesort
239 debugsub: rev
239 debugsub: rev
240 debugwalk: include, exclude
240 debugwalk: include, exclude
241 debugwireargs: three, four, five, ssh, remotecmd, insecure
241 debugwireargs: three, four, five, ssh, remotecmd, insecure
242 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
242 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
243 heads: rev, topo, active, closed, style, template
243 heads: rev, topo, active, closed, style, template
244 help: extension, command
244 help: extension, command
245 identify: rev, num, id, branch, tags, bookmarks
245 identify: rev, num, id, branch, tags, bookmarks
246 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
246 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
247 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
247 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
248 locate: rev, print0, fullpath, include, exclude
248 locate: rev, print0, fullpath, include, exclude
249 manifest: rev
249 manifest: rev, all
250 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
250 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
251 parents: rev, style, template
251 parents: rev, style, template
252 paths:
252 paths:
253 recover:
253 recover:
254 rename: after, force, include, exclude, dry-run
254 rename: after, force, include, exclude, dry-run
255 resolve: all, list, mark, unmark, tool, no-status, include, exclude
255 resolve: all, list, mark, unmark, tool, no-status, include, exclude
256 revert: all, date, rev, no-backup, include, exclude, dry-run
256 revert: all, date, rev, no-backup, include, exclude, dry-run
257 rollback: dry-run
257 rollback: dry-run
258 root:
258 root:
259 showconfig: untrusted
259 showconfig: untrusted
260 tag: force, local, rev, remove, edit, message, date, user
260 tag: force, local, rev, remove, edit, message, date, user
261 tags:
261 tags:
262 tip: patch, git, style, template
262 tip: patch, git, style, template
263 unbundle: update
263 unbundle: update
264 verify:
264 verify:
265 version:
265 version:
@@ -1,65 +1,69 b''
1 Source bundle was generated with the following script:
1 Source bundle was generated with the following script:
2
2
3 # hg init
3 # hg init
4 # echo a > a
4 # echo a > a
5 # ln -s a l
5 # ln -s a l
6 # hg ci -Ama -d'0 0'
6 # hg ci -Ama -d'0 0'
7 # mkdir b
7 # mkdir b
8 # echo a > b/a
8 # echo a > b/a
9 # chmod +x b/a
9 # chmod +x b/a
10 # hg ci -Amb -d'1 0'
10 # hg ci -Amb -d'1 0'
11
11
12 $ hg init
12 $ hg init
13 $ hg -q pull "$TESTDIR/bundles/test-manifest.hg"
13 $ hg -q pull "$TESTDIR/bundles/test-manifest.hg"
14
14
15 The next call is expected to return nothing:
15 The next call is expected to return nothing:
16
16
17 $ hg manifest
17 $ hg manifest
18
18
19 $ hg co
19 $ hg co
20 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
21
21
22 $ hg manifest
22 $ hg manifest
23 a
23 a
24 b/a
24 b/a
25 l
25 l
26
26
27 $ hg manifest -v
27 $ hg manifest -v
28 644 a
28 644 a
29 755 * b/a
29 755 * b/a
30 644 @ l
30 644 @ l
31
31
32 $ hg manifest --debug
32 $ hg manifest --debug
33 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 644 a
33 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 644 a
34 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 755 * b/a
34 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 755 * b/a
35 047b75c6d7a3ef6a2243bd0e99f94f6ea6683597 644 @ l
35 047b75c6d7a3ef6a2243bd0e99f94f6ea6683597 644 @ l
36
36
37 $ hg manifest -r 0
37 $ hg manifest -r 0
38 a
38 a
39 l
39 l
40
40
41 $ hg manifest -r 1
41 $ hg manifest -r 1
42 a
42 a
43 b/a
43 b/a
44 l
44 l
45
45
46 $ hg manifest -r tip
46 $ hg manifest -r tip
47 a
47 a
48 b/a
48 b/a
49 l
49 l
50
50
51 $ hg manifest tip
51 $ hg manifest tip
52 a
52 a
53 b/a
53 b/a
54 l
54 l
55
55
56 $ hg manifest --all
57 a
58 b/a
59 l
56
60
57 The next two calls are expected to abort:
61 The next two calls are expected to abort:
58
62
59 $ hg manifest -r 2
63 $ hg manifest -r 2
60 abort: unknown revision '2'!
64 abort: unknown revision '2'!
61 [255]
65 [255]
62
66
63 $ hg manifest -r tip tip
67 $ hg manifest -r tip tip
64 abort: please specify just one revision
68 abort: please specify just one revision
65 [255]
69 [255]
General Comments 0
You need to be logged in to leave comments. Login now