##// END OF EJS Templates
clone: improve help on -r/-b and tags
Matt Mackall -
r15174:9f1a08c0 default
parent child Browse files
Show More
@@ -1,5409 +1,5405 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge
18 import dagparser, context, simplemerge
19 import random, setdiscovery, treediscovery, dagutil
19 import random, setdiscovery, treediscovery, dagutil
20
20
21 table = {}
21 table = {}
22
22
23 command = cmdutil.command(table)
23 command = cmdutil.command(table)
24
24
25 # common command options
25 # common command options
26
26
27 globalopts = [
27 globalopts = [
28 ('R', 'repository', '',
28 ('R', 'repository', '',
29 _('repository root directory or name of overlay bundle file'),
29 _('repository root directory or name of overlay bundle file'),
30 _('REPO')),
30 _('REPO')),
31 ('', 'cwd', '',
31 ('', 'cwd', '',
32 _('change working directory'), _('DIR')),
32 _('change working directory'), _('DIR')),
33 ('y', 'noninteractive', None,
33 ('y', 'noninteractive', None,
34 _('do not prompt, automatically pick the first choice for all prompts')),
34 _('do not prompt, automatically pick the first choice for all prompts')),
35 ('q', 'quiet', None, _('suppress output')),
35 ('q', 'quiet', None, _('suppress output')),
36 ('v', 'verbose', None, _('enable additional output')),
36 ('v', 'verbose', None, _('enable additional output')),
37 ('', 'config', [],
37 ('', 'config', [],
38 _('set/override config option (use \'section.name=value\')'),
38 _('set/override config option (use \'section.name=value\')'),
39 _('CONFIG')),
39 _('CONFIG')),
40 ('', 'debug', None, _('enable debugging output')),
40 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debugger', None, _('start debugger')),
41 ('', 'debugger', None, _('start debugger')),
42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 _('ENCODE')),
43 _('ENCODE')),
44 ('', 'encodingmode', encoding.encodingmode,
44 ('', 'encodingmode', encoding.encodingmode,
45 _('set the charset encoding mode'), _('MODE')),
45 _('set the charset encoding mode'), _('MODE')),
46 ('', 'traceback', None, _('always print a traceback on exception')),
46 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'time', None, _('time how long the command takes')),
47 ('', 'time', None, _('time how long the command takes')),
48 ('', 'profile', None, _('print command execution profile')),
48 ('', 'profile', None, _('print command execution profile')),
49 ('', 'version', None, _('output version information and exit')),
49 ('', 'version', None, _('output version information and exit')),
50 ('h', 'help', None, _('display help and exit')),
50 ('h', 'help', None, _('display help and exit')),
51 ]
51 ]
52
52
53 dryrunopts = [('n', 'dry-run', None,
53 dryrunopts = [('n', 'dry-run', None,
54 _('do not perform actions, just print output'))]
54 _('do not perform actions, just print output'))]
55
55
56 remoteopts = [
56 remoteopts = [
57 ('e', 'ssh', '',
57 ('e', 'ssh', '',
58 _('specify ssh command to use'), _('CMD')),
58 _('specify ssh command to use'), _('CMD')),
59 ('', 'remotecmd', '',
59 ('', 'remotecmd', '',
60 _('specify hg command to run on the remote side'), _('CMD')),
60 _('specify hg command to run on the remote side'), _('CMD')),
61 ('', 'insecure', None,
61 ('', 'insecure', None,
62 _('do not verify server certificate (ignoring web.cacerts config)')),
62 _('do not verify server certificate (ignoring web.cacerts config)')),
63 ]
63 ]
64
64
65 walkopts = [
65 walkopts = [
66 ('I', 'include', [],
66 ('I', 'include', [],
67 _('include names matching the given patterns'), _('PATTERN')),
67 _('include names matching the given patterns'), _('PATTERN')),
68 ('X', 'exclude', [],
68 ('X', 'exclude', [],
69 _('exclude names matching the given patterns'), _('PATTERN')),
69 _('exclude names matching the given patterns'), _('PATTERN')),
70 ]
70 ]
71
71
72 commitopts = [
72 commitopts = [
73 ('m', 'message', '',
73 ('m', 'message', '',
74 _('use text as commit message'), _('TEXT')),
74 _('use text as commit message'), _('TEXT')),
75 ('l', 'logfile', '',
75 ('l', 'logfile', '',
76 _('read commit message from file'), _('FILE')),
76 _('read commit message from file'), _('FILE')),
77 ]
77 ]
78
78
79 commitopts2 = [
79 commitopts2 = [
80 ('d', 'date', '',
80 ('d', 'date', '',
81 _('record the specified date as commit date'), _('DATE')),
81 _('record the specified date as commit date'), _('DATE')),
82 ('u', 'user', '',
82 ('u', 'user', '',
83 _('record the specified user as committer'), _('USER')),
83 _('record the specified user as committer'), _('USER')),
84 ]
84 ]
85
85
86 templateopts = [
86 templateopts = [
87 ('', 'style', '',
87 ('', 'style', '',
88 _('display using template map file'), _('STYLE')),
88 _('display using template map file'), _('STYLE')),
89 ('', 'template', '',
89 ('', 'template', '',
90 _('display with template'), _('TEMPLATE')),
90 _('display with template'), _('TEMPLATE')),
91 ]
91 ]
92
92
93 logopts = [
93 logopts = [
94 ('p', 'patch', None, _('show patch')),
94 ('p', 'patch', None, _('show patch')),
95 ('g', 'git', None, _('use git extended diff format')),
95 ('g', 'git', None, _('use git extended diff format')),
96 ('l', 'limit', '',
96 ('l', 'limit', '',
97 _('limit number of changes displayed'), _('NUM')),
97 _('limit number of changes displayed'), _('NUM')),
98 ('M', 'no-merges', None, _('do not show merges')),
98 ('M', 'no-merges', None, _('do not show merges')),
99 ('', 'stat', None, _('output diffstat-style summary of changes')),
99 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ] + templateopts
100 ] + templateopts
101
101
102 diffopts = [
102 diffopts = [
103 ('a', 'text', None, _('treat all files as text')),
103 ('a', 'text', None, _('treat all files as text')),
104 ('g', 'git', None, _('use git extended diff format')),
104 ('g', 'git', None, _('use git extended diff format')),
105 ('', 'nodates', None, _('omit dates from diff headers'))
105 ('', 'nodates', None, _('omit dates from diff headers'))
106 ]
106 ]
107
107
108 diffopts2 = [
108 diffopts2 = [
109 ('p', 'show-function', None, _('show which function each change is in')),
109 ('p', 'show-function', None, _('show which function each change is in')),
110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
111 ('w', 'ignore-all-space', None,
111 ('w', 'ignore-all-space', None,
112 _('ignore white space when comparing lines')),
112 _('ignore white space when comparing lines')),
113 ('b', 'ignore-space-change', None,
113 ('b', 'ignore-space-change', None,
114 _('ignore changes in the amount of white space')),
114 _('ignore changes in the amount of white space')),
115 ('B', 'ignore-blank-lines', None,
115 ('B', 'ignore-blank-lines', None,
116 _('ignore changes whose lines are all blank')),
116 _('ignore changes whose lines are all blank')),
117 ('U', 'unified', '',
117 ('U', 'unified', '',
118 _('number of lines of context to show'), _('NUM')),
118 _('number of lines of context to show'), _('NUM')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
120 ]
120 ]
121
121
122 mergetoolopts = [
122 mergetoolopts = [
123 ('t', 'tool', '', _('specify merge tool')),
123 ('t', 'tool', '', _('specify merge tool')),
124 ]
124 ]
125
125
126 similarityopts = [
126 similarityopts = [
127 ('s', 'similarity', '',
127 ('s', 'similarity', '',
128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
129 ]
129 ]
130
130
131 subrepoopts = [
131 subrepoopts = [
132 ('S', 'subrepos', None,
132 ('S', 'subrepos', None,
133 _('recurse into subrepositories'))
133 _('recurse into subrepositories'))
134 ]
134 ]
135
135
136 # Commands start here, listed alphabetically
136 # Commands start here, listed alphabetically
137
137
138 @command('^add',
138 @command('^add',
139 walkopts + subrepoopts + dryrunopts,
139 walkopts + subrepoopts + dryrunopts,
140 _('[OPTION]... [FILE]...'))
140 _('[OPTION]... [FILE]...'))
141 def add(ui, repo, *pats, **opts):
141 def add(ui, repo, *pats, **opts):
142 """add the specified files on the next commit
142 """add the specified files on the next commit
143
143
144 Schedule files to be version controlled and added to the
144 Schedule files to be version controlled and added to the
145 repository.
145 repository.
146
146
147 The files will be added to the repository at the next commit. To
147 The files will be added to the repository at the next commit. To
148 undo an add before that, see :hg:`forget`.
148 undo an add before that, see :hg:`forget`.
149
149
150 If no names are given, add all files to the repository.
150 If no names are given, add all files to the repository.
151
151
152 .. container:: verbose
152 .. container:: verbose
153
153
154 An example showing how new (unknown) files are added
154 An example showing how new (unknown) files are added
155 automatically by :hg:`add`::
155 automatically by :hg:`add`::
156
156
157 $ ls
157 $ ls
158 foo.c
158 foo.c
159 $ hg status
159 $ hg status
160 ? foo.c
160 ? foo.c
161 $ hg add
161 $ hg add
162 adding foo.c
162 adding foo.c
163 $ hg status
163 $ hg status
164 A foo.c
164 A foo.c
165
165
166 Returns 0 if all files are successfully added.
166 Returns 0 if all files are successfully added.
167 """
167 """
168
168
169 m = scmutil.match(repo[None], pats, opts)
169 m = scmutil.match(repo[None], pats, opts)
170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
171 opts.get('subrepos'), prefix="")
171 opts.get('subrepos'), prefix="")
172 return rejected and 1 or 0
172 return rejected and 1 or 0
173
173
174 @command('addremove',
174 @command('addremove',
175 similarityopts + walkopts + dryrunopts,
175 similarityopts + walkopts + dryrunopts,
176 _('[OPTION]... [FILE]...'))
176 _('[OPTION]... [FILE]...'))
177 def addremove(ui, repo, *pats, **opts):
177 def addremove(ui, repo, *pats, **opts):
178 """add all new files, delete all missing files
178 """add all new files, delete all missing files
179
179
180 Add all new files and remove all missing files from the
180 Add all new files and remove all missing files from the
181 repository.
181 repository.
182
182
183 New files are ignored if they match any of the patterns in
183 New files are ignored if they match any of the patterns in
184 ``.hgignore``. As with add, these changes take effect at the next
184 ``.hgignore``. As with add, these changes take effect at the next
185 commit.
185 commit.
186
186
187 Use the -s/--similarity option to detect renamed files. With a
187 Use the -s/--similarity option to detect renamed files. With a
188 parameter greater than 0, this compares every removed file with
188 parameter greater than 0, this compares every removed file with
189 every added file and records those similar enough as renames. This
189 every added file and records those similar enough as renames. This
190 option takes a percentage between 0 (disabled) and 100 (files must
190 option takes a percentage between 0 (disabled) and 100 (files must
191 be identical) as its parameter. Detecting renamed files this way
191 be identical) as its parameter. Detecting renamed files this way
192 can be expensive. After using this option, :hg:`status -C` can be
192 can be expensive. After using this option, :hg:`status -C` can be
193 used to check which files were identified as moved or renamed.
193 used to check which files were identified as moved or renamed.
194
194
195 Returns 0 if all files are successfully added.
195 Returns 0 if all files are successfully added.
196 """
196 """
197 try:
197 try:
198 sim = float(opts.get('similarity') or 100)
198 sim = float(opts.get('similarity') or 100)
199 except ValueError:
199 except ValueError:
200 raise util.Abort(_('similarity must be a number'))
200 raise util.Abort(_('similarity must be a number'))
201 if sim < 0 or sim > 100:
201 if sim < 0 or sim > 100:
202 raise util.Abort(_('similarity must be between 0 and 100'))
202 raise util.Abort(_('similarity must be between 0 and 100'))
203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
204
204
205 @command('^annotate|blame',
205 @command('^annotate|blame',
206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
207 ('', 'follow', None,
207 ('', 'follow', None,
208 _('follow copies/renames and list the filename (DEPRECATED)')),
208 _('follow copies/renames and list the filename (DEPRECATED)')),
209 ('', 'no-follow', None, _("don't follow copies and renames")),
209 ('', 'no-follow', None, _("don't follow copies and renames")),
210 ('a', 'text', None, _('treat all files as text')),
210 ('a', 'text', None, _('treat all files as text')),
211 ('u', 'user', None, _('list the author (long with -v)')),
211 ('u', 'user', None, _('list the author (long with -v)')),
212 ('f', 'file', None, _('list the filename')),
212 ('f', 'file', None, _('list the filename')),
213 ('d', 'date', None, _('list the date (short with -q)')),
213 ('d', 'date', None, _('list the date (short with -q)')),
214 ('n', 'number', None, _('list the revision number (default)')),
214 ('n', 'number', None, _('list the revision number (default)')),
215 ('c', 'changeset', None, _('list the changeset')),
215 ('c', 'changeset', None, _('list the changeset')),
216 ('l', 'line-number', None, _('show line number at the first appearance'))
216 ('l', 'line-number', None, _('show line number at the first appearance'))
217 ] + walkopts,
217 ] + walkopts,
218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
219 def annotate(ui, repo, *pats, **opts):
219 def annotate(ui, repo, *pats, **opts):
220 """show changeset information by line for each file
220 """show changeset information by line for each file
221
221
222 List changes in files, showing the revision id responsible for
222 List changes in files, showing the revision id responsible for
223 each line
223 each line
224
224
225 This command is useful for discovering when a change was made and
225 This command is useful for discovering when a change was made and
226 by whom.
226 by whom.
227
227
228 Without the -a/--text option, annotate will avoid processing files
228 Without the -a/--text option, annotate will avoid processing files
229 it detects as binary. With -a, annotate will annotate the file
229 it detects as binary. With -a, annotate will annotate the file
230 anyway, although the results will probably be neither useful
230 anyway, although the results will probably be neither useful
231 nor desirable.
231 nor desirable.
232
232
233 Returns 0 on success.
233 Returns 0 on success.
234 """
234 """
235 if opts.get('follow'):
235 if opts.get('follow'):
236 # --follow is deprecated and now just an alias for -f/--file
236 # --follow is deprecated and now just an alias for -f/--file
237 # to mimic the behavior of Mercurial before version 1.5
237 # to mimic the behavior of Mercurial before version 1.5
238 opts['file'] = True
238 opts['file'] = True
239
239
240 datefunc = ui.quiet and util.shortdate or util.datestr
240 datefunc = ui.quiet and util.shortdate or util.datestr
241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
242
242
243 if not pats:
243 if not pats:
244 raise util.Abort(_('at least one filename or pattern is required'))
244 raise util.Abort(_('at least one filename or pattern is required'))
245
245
246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
247 ('number', ' ', lambda x: str(x[0].rev())),
247 ('number', ' ', lambda x: str(x[0].rev())),
248 ('changeset', ' ', lambda x: short(x[0].node())),
248 ('changeset', ' ', lambda x: short(x[0].node())),
249 ('date', ' ', getdate),
249 ('date', ' ', getdate),
250 ('file', ' ', lambda x: x[0].path()),
250 ('file', ' ', lambda x: x[0].path()),
251 ('line_number', ':', lambda x: str(x[1])),
251 ('line_number', ':', lambda x: str(x[1])),
252 ]
252 ]
253
253
254 if (not opts.get('user') and not opts.get('changeset')
254 if (not opts.get('user') and not opts.get('changeset')
255 and not opts.get('date') and not opts.get('file')):
255 and not opts.get('date') and not opts.get('file')):
256 opts['number'] = True
256 opts['number'] = True
257
257
258 linenumber = opts.get('line_number') is not None
258 linenumber = opts.get('line_number') is not None
259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
260 raise util.Abort(_('at least one of -n/-c is required for -l'))
260 raise util.Abort(_('at least one of -n/-c is required for -l'))
261
261
262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
264
264
265 def bad(x, y):
265 def bad(x, y):
266 raise util.Abort("%s: %s" % (x, y))
266 raise util.Abort("%s: %s" % (x, y))
267
267
268 ctx = scmutil.revsingle(repo, opts.get('rev'))
268 ctx = scmutil.revsingle(repo, opts.get('rev'))
269 m = scmutil.match(ctx, pats, opts)
269 m = scmutil.match(ctx, pats, opts)
270 m.bad = bad
270 m.bad = bad
271 follow = not opts.get('no_follow')
271 follow = not opts.get('no_follow')
272 for abs in ctx.walk(m):
272 for abs in ctx.walk(m):
273 fctx = ctx[abs]
273 fctx = ctx[abs]
274 if not opts.get('text') and util.binary(fctx.data()):
274 if not opts.get('text') and util.binary(fctx.data()):
275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
276 continue
276 continue
277
277
278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
279 pieces = []
279 pieces = []
280
280
281 for f, sep in funcmap:
281 for f, sep in funcmap:
282 l = [f(n) for n, dummy in lines]
282 l = [f(n) for n, dummy in lines]
283 if l:
283 if l:
284 sized = [(x, encoding.colwidth(x)) for x in l]
284 sized = [(x, encoding.colwidth(x)) for x in l]
285 ml = max([w for x, w in sized])
285 ml = max([w for x, w in sized])
286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
287 for x, w in sized])
287 for x, w in sized])
288
288
289 if pieces:
289 if pieces:
290 for p, l in zip(zip(*pieces), lines):
290 for p, l in zip(zip(*pieces), lines):
291 ui.write("%s: %s" % ("".join(p), l[1]))
291 ui.write("%s: %s" % ("".join(p), l[1]))
292
292
293 @command('archive',
293 @command('archive',
294 [('', 'no-decode', None, _('do not pass files through decoders')),
294 [('', 'no-decode', None, _('do not pass files through decoders')),
295 ('p', 'prefix', '', _('directory prefix for files in archive'),
295 ('p', 'prefix', '', _('directory prefix for files in archive'),
296 _('PREFIX')),
296 _('PREFIX')),
297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
299 ] + subrepoopts + walkopts,
299 ] + subrepoopts + walkopts,
300 _('[OPTION]... DEST'))
300 _('[OPTION]... DEST'))
301 def archive(ui, repo, dest, **opts):
301 def archive(ui, repo, dest, **opts):
302 '''create an unversioned archive of a repository revision
302 '''create an unversioned archive of a repository revision
303
303
304 By default, the revision used is the parent of the working
304 By default, the revision used is the parent of the working
305 directory; use -r/--rev to specify a different revision.
305 directory; use -r/--rev to specify a different revision.
306
306
307 The archive type is automatically detected based on file
307 The archive type is automatically detected based on file
308 extension (or override using -t/--type).
308 extension (or override using -t/--type).
309
309
310 .. container:: verbose
310 .. container:: verbose
311
311
312 Examples:
312 Examples:
313
313
314 - create a zip file containing the 1.0 release::
314 - create a zip file containing the 1.0 release::
315
315
316 hg archive -r 1.0 project-1.0.zip
316 hg archive -r 1.0 project-1.0.zip
317
317
318 - create a tarball excluding .hg files::
318 - create a tarball excluding .hg files::
319
319
320 hg archive project.tar.gz -X ".hg*"
320 hg archive project.tar.gz -X ".hg*"
321
321
322 Valid types are:
322 Valid types are:
323
323
324 :``files``: a directory full of files (default)
324 :``files``: a directory full of files (default)
325 :``tar``: tar archive, uncompressed
325 :``tar``: tar archive, uncompressed
326 :``tbz2``: tar archive, compressed using bzip2
326 :``tbz2``: tar archive, compressed using bzip2
327 :``tgz``: tar archive, compressed using gzip
327 :``tgz``: tar archive, compressed using gzip
328 :``uzip``: zip archive, uncompressed
328 :``uzip``: zip archive, uncompressed
329 :``zip``: zip archive, compressed using deflate
329 :``zip``: zip archive, compressed using deflate
330
330
331 The exact name of the destination archive or directory is given
331 The exact name of the destination archive or directory is given
332 using a format string; see :hg:`help export` for details.
332 using a format string; see :hg:`help export` for details.
333
333
334 Each member added to an archive file has a directory prefix
334 Each member added to an archive file has a directory prefix
335 prepended. Use -p/--prefix to specify a format string for the
335 prepended. Use -p/--prefix to specify a format string for the
336 prefix. The default is the basename of the archive, with suffixes
336 prefix. The default is the basename of the archive, with suffixes
337 removed.
337 removed.
338
338
339 Returns 0 on success.
339 Returns 0 on success.
340 '''
340 '''
341
341
342 ctx = scmutil.revsingle(repo, opts.get('rev'))
342 ctx = scmutil.revsingle(repo, opts.get('rev'))
343 if not ctx:
343 if not ctx:
344 raise util.Abort(_('no working directory: please specify a revision'))
344 raise util.Abort(_('no working directory: please specify a revision'))
345 node = ctx.node()
345 node = ctx.node()
346 dest = cmdutil.makefilename(repo, dest, node)
346 dest = cmdutil.makefilename(repo, dest, node)
347 if os.path.realpath(dest) == repo.root:
347 if os.path.realpath(dest) == repo.root:
348 raise util.Abort(_('repository root cannot be destination'))
348 raise util.Abort(_('repository root cannot be destination'))
349
349
350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
351 prefix = opts.get('prefix')
351 prefix = opts.get('prefix')
352
352
353 if dest == '-':
353 if dest == '-':
354 if kind == 'files':
354 if kind == 'files':
355 raise util.Abort(_('cannot archive plain files to stdout'))
355 raise util.Abort(_('cannot archive plain files to stdout'))
356 dest = cmdutil.makefileobj(repo, dest)
356 dest = cmdutil.makefileobj(repo, dest)
357 if not prefix:
357 if not prefix:
358 prefix = os.path.basename(repo.root) + '-%h'
358 prefix = os.path.basename(repo.root) + '-%h'
359
359
360 prefix = cmdutil.makefilename(repo, prefix, node)
360 prefix = cmdutil.makefilename(repo, prefix, node)
361 matchfn = scmutil.match(ctx, [], opts)
361 matchfn = scmutil.match(ctx, [], opts)
362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
363 matchfn, prefix, subrepos=opts.get('subrepos'))
363 matchfn, prefix, subrepos=opts.get('subrepos'))
364
364
365 @command('backout',
365 @command('backout',
366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
367 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
367 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
368 ('r', 'rev', '', _('revision to backout'), _('REV')),
368 ('r', 'rev', '', _('revision to backout'), _('REV')),
369 ] + mergetoolopts + walkopts + commitopts + commitopts2,
369 ] + mergetoolopts + walkopts + commitopts + commitopts2,
370 _('[OPTION]... [-r] REV'))
370 _('[OPTION]... [-r] REV'))
371 def backout(ui, repo, node=None, rev=None, **opts):
371 def backout(ui, repo, node=None, rev=None, **opts):
372 '''reverse effect of earlier changeset
372 '''reverse effect of earlier changeset
373
373
374 Prepare a new changeset with the effect of REV undone in the
374 Prepare a new changeset with the effect of REV undone in the
375 current working directory.
375 current working directory.
376
376
377 If REV is the parent of the working directory, then this new changeset
377 If REV is the parent of the working directory, then this new changeset
378 is committed automatically. Otherwise, hg needs to merge the
378 is committed automatically. Otherwise, hg needs to merge the
379 changes and the merged result is left uncommitted.
379 changes and the merged result is left uncommitted.
380
380
381 By default, the pending changeset will have one parent,
381 By default, the pending changeset will have one parent,
382 maintaining a linear history. With --merge, the pending changeset
382 maintaining a linear history. With --merge, the pending changeset
383 will instead have two parents: the old parent of the working
383 will instead have two parents: the old parent of the working
384 directory and a new child of REV that simply undoes REV.
384 directory and a new child of REV that simply undoes REV.
385
385
386 Before version 1.7, the behavior without --merge was equivalent to
386 Before version 1.7, the behavior without --merge was equivalent to
387 specifying --merge followed by :hg:`update --clean .` to cancel
387 specifying --merge followed by :hg:`update --clean .` to cancel
388 the merge and leave the child of REV as a head to be merged
388 the merge and leave the child of REV as a head to be merged
389 separately.
389 separately.
390
390
391 See :hg:`help dates` for a list of formats valid for -d/--date.
391 See :hg:`help dates` for a list of formats valid for -d/--date.
392
392
393 Returns 0 on success.
393 Returns 0 on success.
394 '''
394 '''
395 if rev and node:
395 if rev and node:
396 raise util.Abort(_("please specify just one revision"))
396 raise util.Abort(_("please specify just one revision"))
397
397
398 if not rev:
398 if not rev:
399 rev = node
399 rev = node
400
400
401 if not rev:
401 if not rev:
402 raise util.Abort(_("please specify a revision to backout"))
402 raise util.Abort(_("please specify a revision to backout"))
403
403
404 date = opts.get('date')
404 date = opts.get('date')
405 if date:
405 if date:
406 opts['date'] = util.parsedate(date)
406 opts['date'] = util.parsedate(date)
407
407
408 cmdutil.bailifchanged(repo)
408 cmdutil.bailifchanged(repo)
409 node = scmutil.revsingle(repo, rev).node()
409 node = scmutil.revsingle(repo, rev).node()
410
410
411 op1, op2 = repo.dirstate.parents()
411 op1, op2 = repo.dirstate.parents()
412 a = repo.changelog.ancestor(op1, node)
412 a = repo.changelog.ancestor(op1, node)
413 if a != node:
413 if a != node:
414 raise util.Abort(_('cannot backout change on a different branch'))
414 raise util.Abort(_('cannot backout change on a different branch'))
415
415
416 p1, p2 = repo.changelog.parents(node)
416 p1, p2 = repo.changelog.parents(node)
417 if p1 == nullid:
417 if p1 == nullid:
418 raise util.Abort(_('cannot backout a change with no parents'))
418 raise util.Abort(_('cannot backout a change with no parents'))
419 if p2 != nullid:
419 if p2 != nullid:
420 if not opts.get('parent'):
420 if not opts.get('parent'):
421 raise util.Abort(_('cannot backout a merge changeset without '
421 raise util.Abort(_('cannot backout a merge changeset without '
422 '--parent'))
422 '--parent'))
423 p = repo.lookup(opts['parent'])
423 p = repo.lookup(opts['parent'])
424 if p not in (p1, p2):
424 if p not in (p1, p2):
425 raise util.Abort(_('%s is not a parent of %s') %
425 raise util.Abort(_('%s is not a parent of %s') %
426 (short(p), short(node)))
426 (short(p), short(node)))
427 parent = p
427 parent = p
428 else:
428 else:
429 if opts.get('parent'):
429 if opts.get('parent'):
430 raise util.Abort(_('cannot use --parent on non-merge changeset'))
430 raise util.Abort(_('cannot use --parent on non-merge changeset'))
431 parent = p1
431 parent = p1
432
432
433 # the backout should appear on the same branch
433 # the backout should appear on the same branch
434 branch = repo.dirstate.branch()
434 branch = repo.dirstate.branch()
435 hg.clean(repo, node, show_stats=False)
435 hg.clean(repo, node, show_stats=False)
436 repo.dirstate.setbranch(branch)
436 repo.dirstate.setbranch(branch)
437 revert_opts = opts.copy()
437 revert_opts = opts.copy()
438 revert_opts['date'] = None
438 revert_opts['date'] = None
439 revert_opts['all'] = True
439 revert_opts['all'] = True
440 revert_opts['rev'] = hex(parent)
440 revert_opts['rev'] = hex(parent)
441 revert_opts['no_backup'] = None
441 revert_opts['no_backup'] = None
442 revert(ui, repo, **revert_opts)
442 revert(ui, repo, **revert_opts)
443 if not opts.get('merge') and op1 != node:
443 if not opts.get('merge') and op1 != node:
444 try:
444 try:
445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
446 return hg.update(repo, op1)
446 return hg.update(repo, op1)
447 finally:
447 finally:
448 ui.setconfig('ui', 'forcemerge', '')
448 ui.setconfig('ui', 'forcemerge', '')
449
449
450 commit_opts = opts.copy()
450 commit_opts = opts.copy()
451 commit_opts['addremove'] = False
451 commit_opts['addremove'] = False
452 if not commit_opts['message'] and not commit_opts['logfile']:
452 if not commit_opts['message'] and not commit_opts['logfile']:
453 # we don't translate commit messages
453 # we don't translate commit messages
454 commit_opts['message'] = "Backed out changeset %s" % short(node)
454 commit_opts['message'] = "Backed out changeset %s" % short(node)
455 commit_opts['force_editor'] = True
455 commit_opts['force_editor'] = True
456 commit(ui, repo, **commit_opts)
456 commit(ui, repo, **commit_opts)
457 def nice(node):
457 def nice(node):
458 return '%d:%s' % (repo.changelog.rev(node), short(node))
458 return '%d:%s' % (repo.changelog.rev(node), short(node))
459 ui.status(_('changeset %s backs out changeset %s\n') %
459 ui.status(_('changeset %s backs out changeset %s\n') %
460 (nice(repo.changelog.tip()), nice(node)))
460 (nice(repo.changelog.tip()), nice(node)))
461 if opts.get('merge') and op1 != node:
461 if opts.get('merge') and op1 != node:
462 hg.clean(repo, op1, show_stats=False)
462 hg.clean(repo, op1, show_stats=False)
463 ui.status(_('merging with changeset %s\n')
463 ui.status(_('merging with changeset %s\n')
464 % nice(repo.changelog.tip()))
464 % nice(repo.changelog.tip()))
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.merge(repo, hex(repo.changelog.tip()))
467 return hg.merge(repo, hex(repo.changelog.tip()))
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470 return 0
470 return 0
471
471
472 @command('bisect',
472 @command('bisect',
473 [('r', 'reset', False, _('reset bisect state')),
473 [('r', 'reset', False, _('reset bisect state')),
474 ('g', 'good', False, _('mark changeset good')),
474 ('g', 'good', False, _('mark changeset good')),
475 ('b', 'bad', False, _('mark changeset bad')),
475 ('b', 'bad', False, _('mark changeset bad')),
476 ('s', 'skip', False, _('skip testing changeset')),
476 ('s', 'skip', False, _('skip testing changeset')),
477 ('e', 'extend', False, _('extend the bisect range')),
477 ('e', 'extend', False, _('extend the bisect range')),
478 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
478 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
479 ('U', 'noupdate', False, _('do not update to target'))],
479 ('U', 'noupdate', False, _('do not update to target'))],
480 _("[-gbsr] [-U] [-c CMD] [REV]"))
480 _("[-gbsr] [-U] [-c CMD] [REV]"))
481 def bisect(ui, repo, rev=None, extra=None, command=None,
481 def bisect(ui, repo, rev=None, extra=None, command=None,
482 reset=None, good=None, bad=None, skip=None, extend=None,
482 reset=None, good=None, bad=None, skip=None, extend=None,
483 noupdate=None):
483 noupdate=None):
484 """subdivision search of changesets
484 """subdivision search of changesets
485
485
486 This command helps to find changesets which introduce problems. To
486 This command helps to find changesets which introduce problems. To
487 use, mark the earliest changeset you know exhibits the problem as
487 use, mark the earliest changeset you know exhibits the problem as
488 bad, then mark the latest changeset which is free from the problem
488 bad, then mark the latest changeset which is free from the problem
489 as good. Bisect will update your working directory to a revision
489 as good. Bisect will update your working directory to a revision
490 for testing (unless the -U/--noupdate option is specified). Once
490 for testing (unless the -U/--noupdate option is specified). Once
491 you have performed tests, mark the working directory as good or
491 you have performed tests, mark the working directory as good or
492 bad, and bisect will either update to another candidate changeset
492 bad, and bisect will either update to another candidate changeset
493 or announce that it has found the bad revision.
493 or announce that it has found the bad revision.
494
494
495 As a shortcut, you can also use the revision argument to mark a
495 As a shortcut, you can also use the revision argument to mark a
496 revision as good or bad without checking it out first.
496 revision as good or bad without checking it out first.
497
497
498 If you supply a command, it will be used for automatic bisection.
498 If you supply a command, it will be used for automatic bisection.
499 Its exit status will be used to mark revisions as good or bad:
499 Its exit status will be used to mark revisions as good or bad:
500 status 0 means good, 125 means to skip the revision, 127
500 status 0 means good, 125 means to skip the revision, 127
501 (command not found) will abort the bisection, and any other
501 (command not found) will abort the bisection, and any other
502 non-zero exit status means the revision is bad.
502 non-zero exit status means the revision is bad.
503
503
504 .. container:: verbose
504 .. container:: verbose
505
505
506 Some examples:
506 Some examples:
507
507
508 - start a bisection with known bad revision 12, and good revision 34::
508 - start a bisection with known bad revision 12, and good revision 34::
509
509
510 hg bisect --bad 34
510 hg bisect --bad 34
511 hg bisect --good 12
511 hg bisect --good 12
512
512
513 - advance the current bisection by marking current revision as good or
513 - advance the current bisection by marking current revision as good or
514 bad::
514 bad::
515
515
516 hg bisect --good
516 hg bisect --good
517 hg bisect --bad
517 hg bisect --bad
518
518
519 - mark the current revision, or a known revision, to be skipped (eg. if
519 - mark the current revision, or a known revision, to be skipped (eg. if
520 that revision is not usable because of another issue)::
520 that revision is not usable because of another issue)::
521
521
522 hg bisect --skip
522 hg bisect --skip
523 hg bisect --skip 23
523 hg bisect --skip 23
524
524
525 - forget the current bisection::
525 - forget the current bisection::
526
526
527 hg bisect --reset
527 hg bisect --reset
528
528
529 - use 'make && make tests' to automatically find the first broken
529 - use 'make && make tests' to automatically find the first broken
530 revision::
530 revision::
531
531
532 hg bisect --reset
532 hg bisect --reset
533 hg bisect --bad 34
533 hg bisect --bad 34
534 hg bisect --good 12
534 hg bisect --good 12
535 hg bisect --command 'make && make tests'
535 hg bisect --command 'make && make tests'
536
536
537 - see all changesets whose states are already known in the current
537 - see all changesets whose states are already known in the current
538 bisection::
538 bisection::
539
539
540 hg log -r "bisect(pruned)"
540 hg log -r "bisect(pruned)"
541
541
542 - see all changesets that took part in the current bisection::
542 - see all changesets that took part in the current bisection::
543
543
544 hg log -r "bisect(range)"
544 hg log -r "bisect(range)"
545
545
546 - with the graphlog extension, you can even get a nice graph::
546 - with the graphlog extension, you can even get a nice graph::
547
547
548 hg log --graph -r "bisect(range)"
548 hg log --graph -r "bisect(range)"
549
549
550 See :hg:`help revsets` for more about the `bisect()` keyword.
550 See :hg:`help revsets` for more about the `bisect()` keyword.
551
551
552 Returns 0 on success.
552 Returns 0 on success.
553 """
553 """
554 def extendbisectrange(nodes, good):
554 def extendbisectrange(nodes, good):
555 # bisect is incomplete when it ends on a merge node and
555 # bisect is incomplete when it ends on a merge node and
556 # one of the parent was not checked.
556 # one of the parent was not checked.
557 parents = repo[nodes[0]].parents()
557 parents = repo[nodes[0]].parents()
558 if len(parents) > 1:
558 if len(parents) > 1:
559 side = good and state['bad'] or state['good']
559 side = good and state['bad'] or state['good']
560 num = len(set(i.node() for i in parents) & set(side))
560 num = len(set(i.node() for i in parents) & set(side))
561 if num == 1:
561 if num == 1:
562 return parents[0].ancestor(parents[1])
562 return parents[0].ancestor(parents[1])
563 return None
563 return None
564
564
565 def print_result(nodes, good):
565 def print_result(nodes, good):
566 displayer = cmdutil.show_changeset(ui, repo, {})
566 displayer = cmdutil.show_changeset(ui, repo, {})
567 if len(nodes) == 1:
567 if len(nodes) == 1:
568 # narrowed it down to a single revision
568 # narrowed it down to a single revision
569 if good:
569 if good:
570 ui.write(_("The first good revision is:\n"))
570 ui.write(_("The first good revision is:\n"))
571 else:
571 else:
572 ui.write(_("The first bad revision is:\n"))
572 ui.write(_("The first bad revision is:\n"))
573 displayer.show(repo[nodes[0]])
573 displayer.show(repo[nodes[0]])
574 extendnode = extendbisectrange(nodes, good)
574 extendnode = extendbisectrange(nodes, good)
575 if extendnode is not None:
575 if extendnode is not None:
576 ui.write(_('Not all ancestors of this changeset have been'
576 ui.write(_('Not all ancestors of this changeset have been'
577 ' checked.\nUse bisect --extend to continue the '
577 ' checked.\nUse bisect --extend to continue the '
578 'bisection from\nthe common ancestor, %s.\n')
578 'bisection from\nthe common ancestor, %s.\n')
579 % extendnode)
579 % extendnode)
580 else:
580 else:
581 # multiple possible revisions
581 # multiple possible revisions
582 if good:
582 if good:
583 ui.write(_("Due to skipped revisions, the first "
583 ui.write(_("Due to skipped revisions, the first "
584 "good revision could be any of:\n"))
584 "good revision could be any of:\n"))
585 else:
585 else:
586 ui.write(_("Due to skipped revisions, the first "
586 ui.write(_("Due to skipped revisions, the first "
587 "bad revision could be any of:\n"))
587 "bad revision could be any of:\n"))
588 for n in nodes:
588 for n in nodes:
589 displayer.show(repo[n])
589 displayer.show(repo[n])
590 displayer.close()
590 displayer.close()
591
591
592 def check_state(state, interactive=True):
592 def check_state(state, interactive=True):
593 if not state['good'] or not state['bad']:
593 if not state['good'] or not state['bad']:
594 if (good or bad or skip or reset) and interactive:
594 if (good or bad or skip or reset) and interactive:
595 return
595 return
596 if not state['good']:
596 if not state['good']:
597 raise util.Abort(_('cannot bisect (no known good revisions)'))
597 raise util.Abort(_('cannot bisect (no known good revisions)'))
598 else:
598 else:
599 raise util.Abort(_('cannot bisect (no known bad revisions)'))
599 raise util.Abort(_('cannot bisect (no known bad revisions)'))
600 return True
600 return True
601
601
602 # backward compatibility
602 # backward compatibility
603 if rev in "good bad reset init".split():
603 if rev in "good bad reset init".split():
604 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
604 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
605 cmd, rev, extra = rev, extra, None
605 cmd, rev, extra = rev, extra, None
606 if cmd == "good":
606 if cmd == "good":
607 good = True
607 good = True
608 elif cmd == "bad":
608 elif cmd == "bad":
609 bad = True
609 bad = True
610 else:
610 else:
611 reset = True
611 reset = True
612 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
612 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
613 raise util.Abort(_('incompatible arguments'))
613 raise util.Abort(_('incompatible arguments'))
614
614
615 if reset:
615 if reset:
616 p = repo.join("bisect.state")
616 p = repo.join("bisect.state")
617 if os.path.exists(p):
617 if os.path.exists(p):
618 os.unlink(p)
618 os.unlink(p)
619 return
619 return
620
620
621 state = hbisect.load_state(repo)
621 state = hbisect.load_state(repo)
622
622
623 if command:
623 if command:
624 changesets = 1
624 changesets = 1
625 try:
625 try:
626 while changesets:
626 while changesets:
627 # update state
627 # update state
628 status = util.system(command, out=ui.fout)
628 status = util.system(command, out=ui.fout)
629 if status == 125:
629 if status == 125:
630 transition = "skip"
630 transition = "skip"
631 elif status == 0:
631 elif status == 0:
632 transition = "good"
632 transition = "good"
633 # status < 0 means process was killed
633 # status < 0 means process was killed
634 elif status == 127:
634 elif status == 127:
635 raise util.Abort(_("failed to execute %s") % command)
635 raise util.Abort(_("failed to execute %s") % command)
636 elif status < 0:
636 elif status < 0:
637 raise util.Abort(_("%s killed") % command)
637 raise util.Abort(_("%s killed") % command)
638 else:
638 else:
639 transition = "bad"
639 transition = "bad"
640 ctx = scmutil.revsingle(repo, rev)
640 ctx = scmutil.revsingle(repo, rev)
641 rev = None # clear for future iterations
641 rev = None # clear for future iterations
642 state[transition].append(ctx.node())
642 state[transition].append(ctx.node())
643 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
643 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
644 check_state(state, interactive=False)
644 check_state(state, interactive=False)
645 # bisect
645 # bisect
646 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
646 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
647 # update to next check
647 # update to next check
648 cmdutil.bailifchanged(repo)
648 cmdutil.bailifchanged(repo)
649 hg.clean(repo, nodes[0], show_stats=False)
649 hg.clean(repo, nodes[0], show_stats=False)
650 finally:
650 finally:
651 hbisect.save_state(repo, state)
651 hbisect.save_state(repo, state)
652 print_result(nodes, good)
652 print_result(nodes, good)
653 return
653 return
654
654
655 # update state
655 # update state
656
656
657 if rev:
657 if rev:
658 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
658 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
659 else:
659 else:
660 nodes = [repo.lookup('.')]
660 nodes = [repo.lookup('.')]
661
661
662 if good or bad or skip:
662 if good or bad or skip:
663 if good:
663 if good:
664 state['good'] += nodes
664 state['good'] += nodes
665 elif bad:
665 elif bad:
666 state['bad'] += nodes
666 state['bad'] += nodes
667 elif skip:
667 elif skip:
668 state['skip'] += nodes
668 state['skip'] += nodes
669 hbisect.save_state(repo, state)
669 hbisect.save_state(repo, state)
670
670
671 if not check_state(state):
671 if not check_state(state):
672 return
672 return
673
673
674 # actually bisect
674 # actually bisect
675 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
675 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
676 if extend:
676 if extend:
677 if not changesets:
677 if not changesets:
678 extendnode = extendbisectrange(nodes, good)
678 extendnode = extendbisectrange(nodes, good)
679 if extendnode is not None:
679 if extendnode is not None:
680 ui.write(_("Extending search to changeset %d:%s\n"
680 ui.write(_("Extending search to changeset %d:%s\n"
681 % (extendnode.rev(), extendnode)))
681 % (extendnode.rev(), extendnode)))
682 if noupdate:
682 if noupdate:
683 return
683 return
684 cmdutil.bailifchanged(repo)
684 cmdutil.bailifchanged(repo)
685 return hg.clean(repo, extendnode.node())
685 return hg.clean(repo, extendnode.node())
686 raise util.Abort(_("nothing to extend"))
686 raise util.Abort(_("nothing to extend"))
687
687
688 if changesets == 0:
688 if changesets == 0:
689 print_result(nodes, good)
689 print_result(nodes, good)
690 else:
690 else:
691 assert len(nodes) == 1 # only a single node can be tested next
691 assert len(nodes) == 1 # only a single node can be tested next
692 node = nodes[0]
692 node = nodes[0]
693 # compute the approximate number of remaining tests
693 # compute the approximate number of remaining tests
694 tests, size = 0, 2
694 tests, size = 0, 2
695 while size <= changesets:
695 while size <= changesets:
696 tests, size = tests + 1, size * 2
696 tests, size = tests + 1, size * 2
697 rev = repo.changelog.rev(node)
697 rev = repo.changelog.rev(node)
698 ui.write(_("Testing changeset %d:%s "
698 ui.write(_("Testing changeset %d:%s "
699 "(%d changesets remaining, ~%d tests)\n")
699 "(%d changesets remaining, ~%d tests)\n")
700 % (rev, short(node), changesets, tests))
700 % (rev, short(node), changesets, tests))
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 return hg.clean(repo, node)
703 return hg.clean(repo, node)
704
704
705 @command('bookmarks',
705 @command('bookmarks',
706 [('f', 'force', False, _('force')),
706 [('f', 'force', False, _('force')),
707 ('r', 'rev', '', _('revision'), _('REV')),
707 ('r', 'rev', '', _('revision'), _('REV')),
708 ('d', 'delete', False, _('delete a given bookmark')),
708 ('d', 'delete', False, _('delete a given bookmark')),
709 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
709 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
710 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
710 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
711 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
711 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
712 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
712 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
713 rename=None, inactive=False):
713 rename=None, inactive=False):
714 '''track a line of development with movable markers
714 '''track a line of development with movable markers
715
715
716 Bookmarks are pointers to certain commits that move when
716 Bookmarks are pointers to certain commits that move when
717 committing. Bookmarks are local. They can be renamed, copied and
717 committing. Bookmarks are local. They can be renamed, copied and
718 deleted. It is possible to use bookmark names in :hg:`merge` and
718 deleted. It is possible to use bookmark names in :hg:`merge` and
719 :hg:`update` to merge and update respectively to a given bookmark.
719 :hg:`update` to merge and update respectively to a given bookmark.
720
720
721 You can use :hg:`bookmark NAME` to set a bookmark on the working
721 You can use :hg:`bookmark NAME` to set a bookmark on the working
722 directory's parent revision with the given name. If you specify
722 directory's parent revision with the given name. If you specify
723 a revision using -r REV (where REV may be an existing bookmark),
723 a revision using -r REV (where REV may be an existing bookmark),
724 the bookmark is assigned to that revision.
724 the bookmark is assigned to that revision.
725
725
726 Bookmarks can be pushed and pulled between repositories (see :hg:`help
726 Bookmarks can be pushed and pulled between repositories (see :hg:`help
727 push` and :hg:`help pull`). This requires both the local and remote
727 push` and :hg:`help pull`). This requires both the local and remote
728 repositories to support bookmarks. For versions prior to 1.8, this means
728 repositories to support bookmarks. For versions prior to 1.8, this means
729 the bookmarks extension must be enabled.
729 the bookmarks extension must be enabled.
730 '''
730 '''
731 hexfn = ui.debugflag and hex or short
731 hexfn = ui.debugflag and hex or short
732 marks = repo._bookmarks
732 marks = repo._bookmarks
733 cur = repo.changectx('.').node()
733 cur = repo.changectx('.').node()
734
734
735 if rename:
735 if rename:
736 if rename not in marks:
736 if rename not in marks:
737 raise util.Abort(_("bookmark '%s' does not exist") % rename)
737 raise util.Abort(_("bookmark '%s' does not exist") % rename)
738 if mark in marks and not force:
738 if mark in marks and not force:
739 raise util.Abort(_("bookmark '%s' already exists "
739 raise util.Abort(_("bookmark '%s' already exists "
740 "(use -f to force)") % mark)
740 "(use -f to force)") % mark)
741 if mark is None:
741 if mark is None:
742 raise util.Abort(_("new bookmark name required"))
742 raise util.Abort(_("new bookmark name required"))
743 marks[mark] = marks[rename]
743 marks[mark] = marks[rename]
744 if repo._bookmarkcurrent == rename and not inactive:
744 if repo._bookmarkcurrent == rename and not inactive:
745 bookmarks.setcurrent(repo, mark)
745 bookmarks.setcurrent(repo, mark)
746 del marks[rename]
746 del marks[rename]
747 bookmarks.write(repo)
747 bookmarks.write(repo)
748 return
748 return
749
749
750 if delete:
750 if delete:
751 if mark is None:
751 if mark is None:
752 raise util.Abort(_("bookmark name required"))
752 raise util.Abort(_("bookmark name required"))
753 if mark not in marks:
753 if mark not in marks:
754 raise util.Abort(_("bookmark '%s' does not exist") % mark)
754 raise util.Abort(_("bookmark '%s' does not exist") % mark)
755 if mark == repo._bookmarkcurrent:
755 if mark == repo._bookmarkcurrent:
756 bookmarks.setcurrent(repo, None)
756 bookmarks.setcurrent(repo, None)
757 del marks[mark]
757 del marks[mark]
758 bookmarks.write(repo)
758 bookmarks.write(repo)
759 return
759 return
760
760
761 if mark is not None:
761 if mark is not None:
762 if "\n" in mark:
762 if "\n" in mark:
763 raise util.Abort(_("bookmark name cannot contain newlines"))
763 raise util.Abort(_("bookmark name cannot contain newlines"))
764 mark = mark.strip()
764 mark = mark.strip()
765 if not mark:
765 if not mark:
766 raise util.Abort(_("bookmark names cannot consist entirely of "
766 raise util.Abort(_("bookmark names cannot consist entirely of "
767 "whitespace"))
767 "whitespace"))
768 if inactive and mark == repo._bookmarkcurrent:
768 if inactive and mark == repo._bookmarkcurrent:
769 bookmarks.setcurrent(repo, None)
769 bookmarks.setcurrent(repo, None)
770 return
770 return
771 if mark in marks and not force:
771 if mark in marks and not force:
772 raise util.Abort(_("bookmark '%s' already exists "
772 raise util.Abort(_("bookmark '%s' already exists "
773 "(use -f to force)") % mark)
773 "(use -f to force)") % mark)
774 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
774 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
775 and not force):
775 and not force):
776 raise util.Abort(
776 raise util.Abort(
777 _("a bookmark cannot have the name of an existing branch"))
777 _("a bookmark cannot have the name of an existing branch"))
778 if rev:
778 if rev:
779 marks[mark] = repo.lookup(rev)
779 marks[mark] = repo.lookup(rev)
780 else:
780 else:
781 marks[mark] = repo.changectx('.').node()
781 marks[mark] = repo.changectx('.').node()
782 if not inactive and repo.changectx('.').node() == marks[mark]:
782 if not inactive and repo.changectx('.').node() == marks[mark]:
783 bookmarks.setcurrent(repo, mark)
783 bookmarks.setcurrent(repo, mark)
784 bookmarks.write(repo)
784 bookmarks.write(repo)
785 return
785 return
786
786
787 if mark is None:
787 if mark is None:
788 if rev:
788 if rev:
789 raise util.Abort(_("bookmark name required"))
789 raise util.Abort(_("bookmark name required"))
790 if len(marks) == 0:
790 if len(marks) == 0:
791 ui.status(_("no bookmarks set\n"))
791 ui.status(_("no bookmarks set\n"))
792 else:
792 else:
793 for bmark, n in sorted(marks.iteritems()):
793 for bmark, n in sorted(marks.iteritems()):
794 current = repo._bookmarkcurrent
794 current = repo._bookmarkcurrent
795 if bmark == current and n == cur:
795 if bmark == current and n == cur:
796 prefix, label = '*', 'bookmarks.current'
796 prefix, label = '*', 'bookmarks.current'
797 else:
797 else:
798 prefix, label = ' ', ''
798 prefix, label = ' ', ''
799
799
800 if ui.quiet:
800 if ui.quiet:
801 ui.write("%s\n" % bmark, label=label)
801 ui.write("%s\n" % bmark, label=label)
802 else:
802 else:
803 ui.write(" %s %-25s %d:%s\n" % (
803 ui.write(" %s %-25s %d:%s\n" % (
804 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
804 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
805 label=label)
805 label=label)
806 return
806 return
807
807
808 @command('branch',
808 @command('branch',
809 [('f', 'force', None,
809 [('f', 'force', None,
810 _('set branch name even if it shadows an existing branch')),
810 _('set branch name even if it shadows an existing branch')),
811 ('C', 'clean', None, _('reset branch name to parent branch name'))],
811 ('C', 'clean', None, _('reset branch name to parent branch name'))],
812 _('[-fC] [NAME]'))
812 _('[-fC] [NAME]'))
813 def branch(ui, repo, label=None, **opts):
813 def branch(ui, repo, label=None, **opts):
814 """set or show the current branch name
814 """set or show the current branch name
815
815
816 With no argument, show the current branch name. With one argument,
816 With no argument, show the current branch name. With one argument,
817 set the working directory branch name (the branch will not exist
817 set the working directory branch name (the branch will not exist
818 in the repository until the next commit). Standard practice
818 in the repository until the next commit). Standard practice
819 recommends that primary development take place on the 'default'
819 recommends that primary development take place on the 'default'
820 branch.
820 branch.
821
821
822 Unless -f/--force is specified, branch will not let you set a
822 Unless -f/--force is specified, branch will not let you set a
823 branch name that already exists, even if it's inactive.
823 branch name that already exists, even if it's inactive.
824
824
825 Use -C/--clean to reset the working directory branch to that of
825 Use -C/--clean to reset the working directory branch to that of
826 the parent of the working directory, negating a previous branch
826 the parent of the working directory, negating a previous branch
827 change.
827 change.
828
828
829 Use the command :hg:`update` to switch to an existing branch. Use
829 Use the command :hg:`update` to switch to an existing branch. Use
830 :hg:`commit --close-branch` to mark this branch as closed.
830 :hg:`commit --close-branch` to mark this branch as closed.
831
831
832 .. note::
832 .. note::
833
833
834 Branch names are permanent. Use :hg:`bookmark` to create a
834 Branch names are permanent. Use :hg:`bookmark` to create a
835 light-weight bookmark instead. See :hg:`help glossary` for more
835 light-weight bookmark instead. See :hg:`help glossary` for more
836 information about named branches and bookmarks.
836 information about named branches and bookmarks.
837
837
838 Returns 0 on success.
838 Returns 0 on success.
839 """
839 """
840
840
841 if opts.get('clean'):
841 if opts.get('clean'):
842 label = repo[None].p1().branch()
842 label = repo[None].p1().branch()
843 repo.dirstate.setbranch(label)
843 repo.dirstate.setbranch(label)
844 ui.status(_('reset working directory to branch %s\n') % label)
844 ui.status(_('reset working directory to branch %s\n') % label)
845 elif label:
845 elif label:
846 if not opts.get('force') and label in repo.branchtags():
846 if not opts.get('force') and label in repo.branchtags():
847 if label not in [p.branch() for p in repo.parents()]:
847 if label not in [p.branch() for p in repo.parents()]:
848 raise util.Abort(_('a branch of the same name already exists'),
848 raise util.Abort(_('a branch of the same name already exists'),
849 # i18n: "it" refers to an existing branch
849 # i18n: "it" refers to an existing branch
850 hint=_("use 'hg update' to switch to it"))
850 hint=_("use 'hg update' to switch to it"))
851 repo.dirstate.setbranch(label)
851 repo.dirstate.setbranch(label)
852 ui.status(_('marked working directory as branch %s\n') % label)
852 ui.status(_('marked working directory as branch %s\n') % label)
853 else:
853 else:
854 ui.write("%s\n" % repo.dirstate.branch())
854 ui.write("%s\n" % repo.dirstate.branch())
855
855
856 @command('branches',
856 @command('branches',
857 [('a', 'active', False, _('show only branches that have unmerged heads')),
857 [('a', 'active', False, _('show only branches that have unmerged heads')),
858 ('c', 'closed', False, _('show normal and closed branches'))],
858 ('c', 'closed', False, _('show normal and closed branches'))],
859 _('[-ac]'))
859 _('[-ac]'))
860 def branches(ui, repo, active=False, closed=False):
860 def branches(ui, repo, active=False, closed=False):
861 """list repository named branches
861 """list repository named branches
862
862
863 List the repository's named branches, indicating which ones are
863 List the repository's named branches, indicating which ones are
864 inactive. If -c/--closed is specified, also list branches which have
864 inactive. If -c/--closed is specified, also list branches which have
865 been marked closed (see :hg:`commit --close-branch`).
865 been marked closed (see :hg:`commit --close-branch`).
866
866
867 If -a/--active is specified, only show active branches. A branch
867 If -a/--active is specified, only show active branches. A branch
868 is considered active if it contains repository heads.
868 is considered active if it contains repository heads.
869
869
870 Use the command :hg:`update` to switch to an existing branch.
870 Use the command :hg:`update` to switch to an existing branch.
871
871
872 Returns 0.
872 Returns 0.
873 """
873 """
874
874
875 hexfunc = ui.debugflag and hex or short
875 hexfunc = ui.debugflag and hex or short
876 activebranches = [repo[n].branch() for n in repo.heads()]
876 activebranches = [repo[n].branch() for n in repo.heads()]
877 def testactive(tag, node):
877 def testactive(tag, node):
878 realhead = tag in activebranches
878 realhead = tag in activebranches
879 open = node in repo.branchheads(tag, closed=False)
879 open = node in repo.branchheads(tag, closed=False)
880 return realhead and open
880 return realhead and open
881 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
881 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
882 for tag, node in repo.branchtags().items()],
882 for tag, node in repo.branchtags().items()],
883 reverse=True)
883 reverse=True)
884
884
885 for isactive, node, tag in branches:
885 for isactive, node, tag in branches:
886 if (not active) or isactive:
886 if (not active) or isactive:
887 if ui.quiet:
887 if ui.quiet:
888 ui.write("%s\n" % tag)
888 ui.write("%s\n" % tag)
889 else:
889 else:
890 hn = repo.lookup(node)
890 hn = repo.lookup(node)
891 if isactive:
891 if isactive:
892 label = 'branches.active'
892 label = 'branches.active'
893 notice = ''
893 notice = ''
894 elif hn not in repo.branchheads(tag, closed=False):
894 elif hn not in repo.branchheads(tag, closed=False):
895 if not closed:
895 if not closed:
896 continue
896 continue
897 label = 'branches.closed'
897 label = 'branches.closed'
898 notice = _(' (closed)')
898 notice = _(' (closed)')
899 else:
899 else:
900 label = 'branches.inactive'
900 label = 'branches.inactive'
901 notice = _(' (inactive)')
901 notice = _(' (inactive)')
902 if tag == repo.dirstate.branch():
902 if tag == repo.dirstate.branch():
903 label = 'branches.current'
903 label = 'branches.current'
904 rev = str(node).rjust(31 - encoding.colwidth(tag))
904 rev = str(node).rjust(31 - encoding.colwidth(tag))
905 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
905 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
906 tag = ui.label(tag, label)
906 tag = ui.label(tag, label)
907 ui.write("%s %s%s\n" % (tag, rev, notice))
907 ui.write("%s %s%s\n" % (tag, rev, notice))
908
908
909 @command('bundle',
909 @command('bundle',
910 [('f', 'force', None, _('run even when the destination is unrelated')),
910 [('f', 'force', None, _('run even when the destination is unrelated')),
911 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
911 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
912 _('REV')),
912 _('REV')),
913 ('b', 'branch', [], _('a specific branch you would like to bundle'),
913 ('b', 'branch', [], _('a specific branch you would like to bundle'),
914 _('BRANCH')),
914 _('BRANCH')),
915 ('', 'base', [],
915 ('', 'base', [],
916 _('a base changeset assumed to be available at the destination'),
916 _('a base changeset assumed to be available at the destination'),
917 _('REV')),
917 _('REV')),
918 ('a', 'all', None, _('bundle all changesets in the repository')),
918 ('a', 'all', None, _('bundle all changesets in the repository')),
919 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
919 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
920 ] + remoteopts,
920 ] + remoteopts,
921 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
921 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
922 def bundle(ui, repo, fname, dest=None, **opts):
922 def bundle(ui, repo, fname, dest=None, **opts):
923 """create a changegroup file
923 """create a changegroup file
924
924
925 Generate a compressed changegroup file collecting changesets not
925 Generate a compressed changegroup file collecting changesets not
926 known to be in another repository.
926 known to be in another repository.
927
927
928 If you omit the destination repository, then hg assumes the
928 If you omit the destination repository, then hg assumes the
929 destination will have all the nodes you specify with --base
929 destination will have all the nodes you specify with --base
930 parameters. To create a bundle containing all changesets, use
930 parameters. To create a bundle containing all changesets, use
931 -a/--all (or --base null).
931 -a/--all (or --base null).
932
932
933 You can change compression method with the -t/--type option.
933 You can change compression method with the -t/--type option.
934 The available compression methods are: none, bzip2, and
934 The available compression methods are: none, bzip2, and
935 gzip (by default, bundles are compressed using bzip2).
935 gzip (by default, bundles are compressed using bzip2).
936
936
937 The bundle file can then be transferred using conventional means
937 The bundle file can then be transferred using conventional means
938 and applied to another repository with the unbundle or pull
938 and applied to another repository with the unbundle or pull
939 command. This is useful when direct push and pull are not
939 command. This is useful when direct push and pull are not
940 available or when exporting an entire repository is undesirable.
940 available or when exporting an entire repository is undesirable.
941
941
942 Applying bundles preserves all changeset contents including
942 Applying bundles preserves all changeset contents including
943 permissions, copy/rename information, and revision history.
943 permissions, copy/rename information, and revision history.
944
944
945 Returns 0 on success, 1 if no changes found.
945 Returns 0 on success, 1 if no changes found.
946 """
946 """
947 revs = None
947 revs = None
948 if 'rev' in opts:
948 if 'rev' in opts:
949 revs = scmutil.revrange(repo, opts['rev'])
949 revs = scmutil.revrange(repo, opts['rev'])
950
950
951 if opts.get('all'):
951 if opts.get('all'):
952 base = ['null']
952 base = ['null']
953 else:
953 else:
954 base = scmutil.revrange(repo, opts.get('base'))
954 base = scmutil.revrange(repo, opts.get('base'))
955 if base:
955 if base:
956 if dest:
956 if dest:
957 raise util.Abort(_("--base is incompatible with specifying "
957 raise util.Abort(_("--base is incompatible with specifying "
958 "a destination"))
958 "a destination"))
959 common = [repo.lookup(rev) for rev in base]
959 common = [repo.lookup(rev) for rev in base]
960 heads = revs and map(repo.lookup, revs) or revs
960 heads = revs and map(repo.lookup, revs) or revs
961 else:
961 else:
962 dest = ui.expandpath(dest or 'default-push', dest or 'default')
962 dest = ui.expandpath(dest or 'default-push', dest or 'default')
963 dest, branches = hg.parseurl(dest, opts.get('branch'))
963 dest, branches = hg.parseurl(dest, opts.get('branch'))
964 other = hg.peer(repo, opts, dest)
964 other = hg.peer(repo, opts, dest)
965 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
965 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
966 heads = revs and map(repo.lookup, revs) or revs
966 heads = revs and map(repo.lookup, revs) or revs
967 common, outheads = discovery.findcommonoutgoing(repo, other,
967 common, outheads = discovery.findcommonoutgoing(repo, other,
968 onlyheads=heads,
968 onlyheads=heads,
969 force=opts.get('force'))
969 force=opts.get('force'))
970
970
971 cg = repo.getbundle('bundle', common=common, heads=heads)
971 cg = repo.getbundle('bundle', common=common, heads=heads)
972 if not cg:
972 if not cg:
973 ui.status(_("no changes found\n"))
973 ui.status(_("no changes found\n"))
974 return 1
974 return 1
975
975
976 bundletype = opts.get('type', 'bzip2').lower()
976 bundletype = opts.get('type', 'bzip2').lower()
977 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
977 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
978 bundletype = btypes.get(bundletype)
978 bundletype = btypes.get(bundletype)
979 if bundletype not in changegroup.bundletypes:
979 if bundletype not in changegroup.bundletypes:
980 raise util.Abort(_('unknown bundle type specified with --type'))
980 raise util.Abort(_('unknown bundle type specified with --type'))
981
981
982 changegroup.writebundle(cg, fname, bundletype)
982 changegroup.writebundle(cg, fname, bundletype)
983
983
984 @command('cat',
984 @command('cat',
985 [('o', 'output', '',
985 [('o', 'output', '',
986 _('print output to file with formatted name'), _('FORMAT')),
986 _('print output to file with formatted name'), _('FORMAT')),
987 ('r', 'rev', '', _('print the given revision'), _('REV')),
987 ('r', 'rev', '', _('print the given revision'), _('REV')),
988 ('', 'decode', None, _('apply any matching decode filter')),
988 ('', 'decode', None, _('apply any matching decode filter')),
989 ] + walkopts,
989 ] + walkopts,
990 _('[OPTION]... FILE...'))
990 _('[OPTION]... FILE...'))
991 def cat(ui, repo, file1, *pats, **opts):
991 def cat(ui, repo, file1, *pats, **opts):
992 """output the current or given revision of files
992 """output the current or given revision of files
993
993
994 Print the specified files as they were at the given revision. If
994 Print the specified files as they were at the given revision. If
995 no revision is given, the parent of the working directory is used,
995 no revision is given, the parent of the working directory is used,
996 or tip if no revision is checked out.
996 or tip if no revision is checked out.
997
997
998 Output may be to a file, in which case the name of the file is
998 Output may be to a file, in which case the name of the file is
999 given using a format string. The formatting rules are the same as
999 given using a format string. The formatting rules are the same as
1000 for the export command, with the following additions:
1000 for the export command, with the following additions:
1001
1001
1002 :``%s``: basename of file being printed
1002 :``%s``: basename of file being printed
1003 :``%d``: dirname of file being printed, or '.' if in repository root
1003 :``%d``: dirname of file being printed, or '.' if in repository root
1004 :``%p``: root-relative path name of file being printed
1004 :``%p``: root-relative path name of file being printed
1005
1005
1006 Returns 0 on success.
1006 Returns 0 on success.
1007 """
1007 """
1008 ctx = scmutil.revsingle(repo, opts.get('rev'))
1008 ctx = scmutil.revsingle(repo, opts.get('rev'))
1009 err = 1
1009 err = 1
1010 m = scmutil.match(ctx, (file1,) + pats, opts)
1010 m = scmutil.match(ctx, (file1,) + pats, opts)
1011 for abs in ctx.walk(m):
1011 for abs in ctx.walk(m):
1012 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1012 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1013 pathname=abs)
1013 pathname=abs)
1014 data = ctx[abs].data()
1014 data = ctx[abs].data()
1015 if opts.get('decode'):
1015 if opts.get('decode'):
1016 data = repo.wwritedata(abs, data)
1016 data = repo.wwritedata(abs, data)
1017 fp.write(data)
1017 fp.write(data)
1018 fp.close()
1018 fp.close()
1019 err = 0
1019 err = 0
1020 return err
1020 return err
1021
1021
1022 @command('^clone',
1022 @command('^clone',
1023 [('U', 'noupdate', None,
1023 [('U', 'noupdate', None,
1024 _('the clone will include an empty working copy (only a repository)')),
1024 _('the clone will include an empty working copy (only a repository)')),
1025 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1025 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1026 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1026 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1027 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1027 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1028 ('', 'pull', None, _('use pull protocol to copy metadata')),
1028 ('', 'pull', None, _('use pull protocol to copy metadata')),
1029 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1029 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1030 ] + remoteopts,
1030 ] + remoteopts,
1031 _('[OPTION]... SOURCE [DEST]'))
1031 _('[OPTION]... SOURCE [DEST]'))
1032 def clone(ui, source, dest=None, **opts):
1032 def clone(ui, source, dest=None, **opts):
1033 """make a copy of an existing repository
1033 """make a copy of an existing repository
1034
1034
1035 Create a copy of an existing repository in a new directory.
1035 Create a copy of an existing repository in a new directory.
1036
1036
1037 If no destination directory name is specified, it defaults to the
1037 If no destination directory name is specified, it defaults to the
1038 basename of the source.
1038 basename of the source.
1039
1039
1040 The location of the source is added to the new repository's
1040 The location of the source is added to the new repository's
1041 ``.hg/hgrc`` file, as the default to be used for future pulls.
1041 ``.hg/hgrc`` file, as the default to be used for future pulls.
1042
1042
1043 See :hg:`help urls` for valid source format details.
1043 See :hg:`help urls` for valid source format details.
1044
1044
1045 It is possible to specify an ``ssh://`` URL as the destination, but no
1045 It is possible to specify an ``ssh://`` URL as the destination, but no
1046 ``.hg/hgrc`` and working directory will be created on the remote side.
1046 ``.hg/hgrc`` and working directory will be created on the remote side.
1047 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
1047 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
1048
1048
1049 A set of changesets (tags, or branch names) to pull may be specified
1049 To pull only a subset of changesets, specify one or more revisions
1050 by listing each changeset (tag, or branch name) with -r/--rev.
1050 identifiers with -r/--rev or branches with -b/--branch. The
1051 If -r/--rev is used, the cloned repository will contain only a subset
1051 resulting clone will contain only the specified changesets and
1052 of the changesets of the source repository. Only the set of changesets
1052 their ancestors. These options (or 'clone src#rev dest') imply
1053 defined by all -r/--rev options (including all their ancestors)
1053 --pull, even for local source repositories. Note that specifying a
1054 will be pulled into the destination repository.
1054 tag will include the tagged changeset but not the changeset
1055 No subsequent changesets (including subsequent tags) will be present
1055 containing the tag.
1056 in the destination.
1057
1058 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
1059 local source repositories.
1060
1056
1061 For efficiency, hardlinks are used for cloning whenever the source
1057 For efficiency, hardlinks are used for cloning whenever the source
1062 and destination are on the same filesystem (note this applies only
1058 and destination are on the same filesystem (note this applies only
1063 to the repository data, not to the working directory). Some
1059 to the repository data, not to the working directory). Some
1064 filesystems, such as AFS, implement hardlinking incorrectly, but
1060 filesystems, such as AFS, implement hardlinking incorrectly, but
1065 do not report errors. In these cases, use the --pull option to
1061 do not report errors. In these cases, use the --pull option to
1066 avoid hardlinking.
1062 avoid hardlinking.
1067
1063
1068 In some cases, you can clone repositories and the working directory
1064 In some cases, you can clone repositories and the working directory
1069 using full hardlinks with ::
1065 using full hardlinks with ::
1070
1066
1071 $ cp -al REPO REPOCLONE
1067 $ cp -al REPO REPOCLONE
1072
1068
1073 This is the fastest way to clone, but it is not always safe. The
1069 This is the fastest way to clone, but it is not always safe. The
1074 operation is not atomic (making sure REPO is not modified during
1070 operation is not atomic (making sure REPO is not modified during
1075 the operation is up to you) and you have to make sure your editor
1071 the operation is up to you) and you have to make sure your editor
1076 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1072 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1077 this is not compatible with certain extensions that place their
1073 this is not compatible with certain extensions that place their
1078 metadata under the .hg directory, such as mq.
1074 metadata under the .hg directory, such as mq.
1079
1075
1080 Mercurial will update the working directory to the first applicable
1076 Mercurial will update the working directory to the first applicable
1081 revision from this list:
1077 revision from this list:
1082
1078
1083 a) null if -U or the source repository has no changesets
1079 a) null if -U or the source repository has no changesets
1084 b) if -u . and the source repository is local, the first parent of
1080 b) if -u . and the source repository is local, the first parent of
1085 the source repository's working directory
1081 the source repository's working directory
1086 c) the changeset specified with -u (if a branch name, this means the
1082 c) the changeset specified with -u (if a branch name, this means the
1087 latest head of that branch)
1083 latest head of that branch)
1088 d) the changeset specified with -r
1084 d) the changeset specified with -r
1089 e) the tipmost head specified with -b
1085 e) the tipmost head specified with -b
1090 f) the tipmost head specified with the url#branch source syntax
1086 f) the tipmost head specified with the url#branch source syntax
1091 g) the tipmost head of the default branch
1087 g) the tipmost head of the default branch
1092 h) tip
1088 h) tip
1093
1089
1094 Returns 0 on success.
1090 Returns 0 on success.
1095 """
1091 """
1096 if opts.get('noupdate') and opts.get('updaterev'):
1092 if opts.get('noupdate') and opts.get('updaterev'):
1097 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1093 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1098
1094
1099 r = hg.clone(ui, opts, source, dest,
1095 r = hg.clone(ui, opts, source, dest,
1100 pull=opts.get('pull'),
1096 pull=opts.get('pull'),
1101 stream=opts.get('uncompressed'),
1097 stream=opts.get('uncompressed'),
1102 rev=opts.get('rev'),
1098 rev=opts.get('rev'),
1103 update=opts.get('updaterev') or not opts.get('noupdate'),
1099 update=opts.get('updaterev') or not opts.get('noupdate'),
1104 branch=opts.get('branch'))
1100 branch=opts.get('branch'))
1105
1101
1106 return r is None
1102 return r is None
1107
1103
1108 @command('^commit|ci',
1104 @command('^commit|ci',
1109 [('A', 'addremove', None,
1105 [('A', 'addremove', None,
1110 _('mark new/missing files as added/removed before committing')),
1106 _('mark new/missing files as added/removed before committing')),
1111 ('', 'close-branch', None,
1107 ('', 'close-branch', None,
1112 _('mark a branch as closed, hiding it from the branch list')),
1108 _('mark a branch as closed, hiding it from the branch list')),
1113 ] + walkopts + commitopts + commitopts2,
1109 ] + walkopts + commitopts + commitopts2,
1114 _('[OPTION]... [FILE]...'))
1110 _('[OPTION]... [FILE]...'))
1115 def commit(ui, repo, *pats, **opts):
1111 def commit(ui, repo, *pats, **opts):
1116 """commit the specified files or all outstanding changes
1112 """commit the specified files or all outstanding changes
1117
1113
1118 Commit changes to the given files into the repository. Unlike a
1114 Commit changes to the given files into the repository. Unlike a
1119 centralized SCM, this operation is a local operation. See
1115 centralized SCM, this operation is a local operation. See
1120 :hg:`push` for a way to actively distribute your changes.
1116 :hg:`push` for a way to actively distribute your changes.
1121
1117
1122 If a list of files is omitted, all changes reported by :hg:`status`
1118 If a list of files is omitted, all changes reported by :hg:`status`
1123 will be committed.
1119 will be committed.
1124
1120
1125 If you are committing the result of a merge, do not provide any
1121 If you are committing the result of a merge, do not provide any
1126 filenames or -I/-X filters.
1122 filenames or -I/-X filters.
1127
1123
1128 If no commit message is specified, Mercurial starts your
1124 If no commit message is specified, Mercurial starts your
1129 configured editor where you can enter a message. In case your
1125 configured editor where you can enter a message. In case your
1130 commit fails, you will find a backup of your message in
1126 commit fails, you will find a backup of your message in
1131 ``.hg/last-message.txt``.
1127 ``.hg/last-message.txt``.
1132
1128
1133 See :hg:`help dates` for a list of formats valid for -d/--date.
1129 See :hg:`help dates` for a list of formats valid for -d/--date.
1134
1130
1135 Returns 0 on success, 1 if nothing changed.
1131 Returns 0 on success, 1 if nothing changed.
1136 """
1132 """
1137 extra = {}
1133 extra = {}
1138 if opts.get('close_branch'):
1134 if opts.get('close_branch'):
1139 if repo['.'].node() not in repo.branchheads():
1135 if repo['.'].node() not in repo.branchheads():
1140 # The topo heads set is included in the branch heads set of the
1136 # The topo heads set is included in the branch heads set of the
1141 # current branch, so it's sufficient to test branchheads
1137 # current branch, so it's sufficient to test branchheads
1142 raise util.Abort(_('can only close branch heads'))
1138 raise util.Abort(_('can only close branch heads'))
1143 extra['close'] = 1
1139 extra['close'] = 1
1144 e = cmdutil.commiteditor
1140 e = cmdutil.commiteditor
1145 if opts.get('force_editor'):
1141 if opts.get('force_editor'):
1146 e = cmdutil.commitforceeditor
1142 e = cmdutil.commitforceeditor
1147
1143
1148 def commitfunc(ui, repo, message, match, opts):
1144 def commitfunc(ui, repo, message, match, opts):
1149 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1145 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1150 editor=e, extra=extra)
1146 editor=e, extra=extra)
1151
1147
1152 branch = repo[None].branch()
1148 branch = repo[None].branch()
1153 bheads = repo.branchheads(branch)
1149 bheads = repo.branchheads(branch)
1154
1150
1155 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1151 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1156 if not node:
1152 if not node:
1157 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1153 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1158 if stat[3]:
1154 if stat[3]:
1159 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1155 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1160 % len(stat[3]))
1156 % len(stat[3]))
1161 else:
1157 else:
1162 ui.status(_("nothing changed\n"))
1158 ui.status(_("nothing changed\n"))
1163 return 1
1159 return 1
1164
1160
1165 ctx = repo[node]
1161 ctx = repo[node]
1166 parents = ctx.parents()
1162 parents = ctx.parents()
1167
1163
1168 if (bheads and node not in bheads and not
1164 if (bheads and node not in bheads and not
1169 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1165 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1170 ui.status(_('created new head\n'))
1166 ui.status(_('created new head\n'))
1171 # The message is not printed for initial roots. For the other
1167 # The message is not printed for initial roots. For the other
1172 # changesets, it is printed in the following situations:
1168 # changesets, it is printed in the following situations:
1173 #
1169 #
1174 # Par column: for the 2 parents with ...
1170 # Par column: for the 2 parents with ...
1175 # N: null or no parent
1171 # N: null or no parent
1176 # B: parent is on another named branch
1172 # B: parent is on another named branch
1177 # C: parent is a regular non head changeset
1173 # C: parent is a regular non head changeset
1178 # H: parent was a branch head of the current branch
1174 # H: parent was a branch head of the current branch
1179 # Msg column: whether we print "created new head" message
1175 # Msg column: whether we print "created new head" message
1180 # In the following, it is assumed that there already exists some
1176 # In the following, it is assumed that there already exists some
1181 # initial branch heads of the current branch, otherwise nothing is
1177 # initial branch heads of the current branch, otherwise nothing is
1182 # printed anyway.
1178 # printed anyway.
1183 #
1179 #
1184 # Par Msg Comment
1180 # Par Msg Comment
1185 # NN y additional topo root
1181 # NN y additional topo root
1186 #
1182 #
1187 # BN y additional branch root
1183 # BN y additional branch root
1188 # CN y additional topo head
1184 # CN y additional topo head
1189 # HN n usual case
1185 # HN n usual case
1190 #
1186 #
1191 # BB y weird additional branch root
1187 # BB y weird additional branch root
1192 # CB y branch merge
1188 # CB y branch merge
1193 # HB n merge with named branch
1189 # HB n merge with named branch
1194 #
1190 #
1195 # CC y additional head from merge
1191 # CC y additional head from merge
1196 # CH n merge with a head
1192 # CH n merge with a head
1197 #
1193 #
1198 # HH n head merge: head count decreases
1194 # HH n head merge: head count decreases
1199
1195
1200 if not opts.get('close_branch'):
1196 if not opts.get('close_branch'):
1201 for r in parents:
1197 for r in parents:
1202 if r.extra().get('close') and r.branch() == branch:
1198 if r.extra().get('close') and r.branch() == branch:
1203 ui.status(_('reopening closed branch head %d\n') % r)
1199 ui.status(_('reopening closed branch head %d\n') % r)
1204
1200
1205 if ui.debugflag:
1201 if ui.debugflag:
1206 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1202 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1207 elif ui.verbose:
1203 elif ui.verbose:
1208 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1204 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1209
1205
1210 @command('copy|cp',
1206 @command('copy|cp',
1211 [('A', 'after', None, _('record a copy that has already occurred')),
1207 [('A', 'after', None, _('record a copy that has already occurred')),
1212 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1208 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1213 ] + walkopts + dryrunopts,
1209 ] + walkopts + dryrunopts,
1214 _('[OPTION]... [SOURCE]... DEST'))
1210 _('[OPTION]... [SOURCE]... DEST'))
1215 def copy(ui, repo, *pats, **opts):
1211 def copy(ui, repo, *pats, **opts):
1216 """mark files as copied for the next commit
1212 """mark files as copied for the next commit
1217
1213
1218 Mark dest as having copies of source files. If dest is a
1214 Mark dest as having copies of source files. If dest is a
1219 directory, copies are put in that directory. If dest is a file,
1215 directory, copies are put in that directory. If dest is a file,
1220 the source must be a single file.
1216 the source must be a single file.
1221
1217
1222 By default, this command copies the contents of files as they
1218 By default, this command copies the contents of files as they
1223 exist in the working directory. If invoked with -A/--after, the
1219 exist in the working directory. If invoked with -A/--after, the
1224 operation is recorded, but no copying is performed.
1220 operation is recorded, but no copying is performed.
1225
1221
1226 This command takes effect with the next commit. To undo a copy
1222 This command takes effect with the next commit. To undo a copy
1227 before that, see :hg:`revert`.
1223 before that, see :hg:`revert`.
1228
1224
1229 Returns 0 on success, 1 if errors are encountered.
1225 Returns 0 on success, 1 if errors are encountered.
1230 """
1226 """
1231 wlock = repo.wlock(False)
1227 wlock = repo.wlock(False)
1232 try:
1228 try:
1233 return cmdutil.copy(ui, repo, pats, opts)
1229 return cmdutil.copy(ui, repo, pats, opts)
1234 finally:
1230 finally:
1235 wlock.release()
1231 wlock.release()
1236
1232
1237 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1233 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1238 def debugancestor(ui, repo, *args):
1234 def debugancestor(ui, repo, *args):
1239 """find the ancestor revision of two revisions in a given index"""
1235 """find the ancestor revision of two revisions in a given index"""
1240 if len(args) == 3:
1236 if len(args) == 3:
1241 index, rev1, rev2 = args
1237 index, rev1, rev2 = args
1242 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1238 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1243 lookup = r.lookup
1239 lookup = r.lookup
1244 elif len(args) == 2:
1240 elif len(args) == 2:
1245 if not repo:
1241 if not repo:
1246 raise util.Abort(_("there is no Mercurial repository here "
1242 raise util.Abort(_("there is no Mercurial repository here "
1247 "(.hg not found)"))
1243 "(.hg not found)"))
1248 rev1, rev2 = args
1244 rev1, rev2 = args
1249 r = repo.changelog
1245 r = repo.changelog
1250 lookup = repo.lookup
1246 lookup = repo.lookup
1251 else:
1247 else:
1252 raise util.Abort(_('either two or three arguments required'))
1248 raise util.Abort(_('either two or three arguments required'))
1253 a = r.ancestor(lookup(rev1), lookup(rev2))
1249 a = r.ancestor(lookup(rev1), lookup(rev2))
1254 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1250 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1255
1251
1256 @command('debugbuilddag',
1252 @command('debugbuilddag',
1257 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1253 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1258 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1254 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1259 ('n', 'new-file', None, _('add new file at each rev'))],
1255 ('n', 'new-file', None, _('add new file at each rev'))],
1260 _('[OPTION]... [TEXT]'))
1256 _('[OPTION]... [TEXT]'))
1261 def debugbuilddag(ui, repo, text=None,
1257 def debugbuilddag(ui, repo, text=None,
1262 mergeable_file=False,
1258 mergeable_file=False,
1263 overwritten_file=False,
1259 overwritten_file=False,
1264 new_file=False):
1260 new_file=False):
1265 """builds a repo with a given DAG from scratch in the current empty repo
1261 """builds a repo with a given DAG from scratch in the current empty repo
1266
1262
1267 The description of the DAG is read from stdin if not given on the
1263 The description of the DAG is read from stdin if not given on the
1268 command line.
1264 command line.
1269
1265
1270 Elements:
1266 Elements:
1271
1267
1272 - "+n" is a linear run of n nodes based on the current default parent
1268 - "+n" is a linear run of n nodes based on the current default parent
1273 - "." is a single node based on the current default parent
1269 - "." is a single node based on the current default parent
1274 - "$" resets the default parent to null (implied at the start);
1270 - "$" resets the default parent to null (implied at the start);
1275 otherwise the default parent is always the last node created
1271 otherwise the default parent is always the last node created
1276 - "<p" sets the default parent to the backref p
1272 - "<p" sets the default parent to the backref p
1277 - "*p" is a fork at parent p, which is a backref
1273 - "*p" is a fork at parent p, which is a backref
1278 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1274 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1279 - "/p2" is a merge of the preceding node and p2
1275 - "/p2" is a merge of the preceding node and p2
1280 - ":tag" defines a local tag for the preceding node
1276 - ":tag" defines a local tag for the preceding node
1281 - "@branch" sets the named branch for subsequent nodes
1277 - "@branch" sets the named branch for subsequent nodes
1282 - "#...\\n" is a comment up to the end of the line
1278 - "#...\\n" is a comment up to the end of the line
1283
1279
1284 Whitespace between the above elements is ignored.
1280 Whitespace between the above elements is ignored.
1285
1281
1286 A backref is either
1282 A backref is either
1287
1283
1288 - a number n, which references the node curr-n, where curr is the current
1284 - a number n, which references the node curr-n, where curr is the current
1289 node, or
1285 node, or
1290 - the name of a local tag you placed earlier using ":tag", or
1286 - the name of a local tag you placed earlier using ":tag", or
1291 - empty to denote the default parent.
1287 - empty to denote the default parent.
1292
1288
1293 All string valued-elements are either strictly alphanumeric, or must
1289 All string valued-elements are either strictly alphanumeric, or must
1294 be enclosed in double quotes ("..."), with "\\" as escape character.
1290 be enclosed in double quotes ("..."), with "\\" as escape character.
1295 """
1291 """
1296
1292
1297 if text is None:
1293 if text is None:
1298 ui.status(_("reading DAG from stdin\n"))
1294 ui.status(_("reading DAG from stdin\n"))
1299 text = ui.fin.read()
1295 text = ui.fin.read()
1300
1296
1301 cl = repo.changelog
1297 cl = repo.changelog
1302 if len(cl) > 0:
1298 if len(cl) > 0:
1303 raise util.Abort(_('repository is not empty'))
1299 raise util.Abort(_('repository is not empty'))
1304
1300
1305 # determine number of revs in DAG
1301 # determine number of revs in DAG
1306 total = 0
1302 total = 0
1307 for type, data in dagparser.parsedag(text):
1303 for type, data in dagparser.parsedag(text):
1308 if type == 'n':
1304 if type == 'n':
1309 total += 1
1305 total += 1
1310
1306
1311 if mergeable_file:
1307 if mergeable_file:
1312 linesperrev = 2
1308 linesperrev = 2
1313 # make a file with k lines per rev
1309 # make a file with k lines per rev
1314 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1310 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1315 initialmergedlines.append("")
1311 initialmergedlines.append("")
1316
1312
1317 tags = []
1313 tags = []
1318
1314
1319 tr = repo.transaction("builddag")
1315 tr = repo.transaction("builddag")
1320 try:
1316 try:
1321
1317
1322 at = -1
1318 at = -1
1323 atbranch = 'default'
1319 atbranch = 'default'
1324 nodeids = []
1320 nodeids = []
1325 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1321 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1326 for type, data in dagparser.parsedag(text):
1322 for type, data in dagparser.parsedag(text):
1327 if type == 'n':
1323 if type == 'n':
1328 ui.note('node %s\n' % str(data))
1324 ui.note('node %s\n' % str(data))
1329 id, ps = data
1325 id, ps = data
1330
1326
1331 files = []
1327 files = []
1332 fctxs = {}
1328 fctxs = {}
1333
1329
1334 p2 = None
1330 p2 = None
1335 if mergeable_file:
1331 if mergeable_file:
1336 fn = "mf"
1332 fn = "mf"
1337 p1 = repo[ps[0]]
1333 p1 = repo[ps[0]]
1338 if len(ps) > 1:
1334 if len(ps) > 1:
1339 p2 = repo[ps[1]]
1335 p2 = repo[ps[1]]
1340 pa = p1.ancestor(p2)
1336 pa = p1.ancestor(p2)
1341 base, local, other = [x[fn].data() for x in pa, p1, p2]
1337 base, local, other = [x[fn].data() for x in pa, p1, p2]
1342 m3 = simplemerge.Merge3Text(base, local, other)
1338 m3 = simplemerge.Merge3Text(base, local, other)
1343 ml = [l.strip() for l in m3.merge_lines()]
1339 ml = [l.strip() for l in m3.merge_lines()]
1344 ml.append("")
1340 ml.append("")
1345 elif at > 0:
1341 elif at > 0:
1346 ml = p1[fn].data().split("\n")
1342 ml = p1[fn].data().split("\n")
1347 else:
1343 else:
1348 ml = initialmergedlines
1344 ml = initialmergedlines
1349 ml[id * linesperrev] += " r%i" % id
1345 ml[id * linesperrev] += " r%i" % id
1350 mergedtext = "\n".join(ml)
1346 mergedtext = "\n".join(ml)
1351 files.append(fn)
1347 files.append(fn)
1352 fctxs[fn] = context.memfilectx(fn, mergedtext)
1348 fctxs[fn] = context.memfilectx(fn, mergedtext)
1353
1349
1354 if overwritten_file:
1350 if overwritten_file:
1355 fn = "of"
1351 fn = "of"
1356 files.append(fn)
1352 files.append(fn)
1357 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1353 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1358
1354
1359 if new_file:
1355 if new_file:
1360 fn = "nf%i" % id
1356 fn = "nf%i" % id
1361 files.append(fn)
1357 files.append(fn)
1362 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1358 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1363 if len(ps) > 1:
1359 if len(ps) > 1:
1364 if not p2:
1360 if not p2:
1365 p2 = repo[ps[1]]
1361 p2 = repo[ps[1]]
1366 for fn in p2:
1362 for fn in p2:
1367 if fn.startswith("nf"):
1363 if fn.startswith("nf"):
1368 files.append(fn)
1364 files.append(fn)
1369 fctxs[fn] = p2[fn]
1365 fctxs[fn] = p2[fn]
1370
1366
1371 def fctxfn(repo, cx, path):
1367 def fctxfn(repo, cx, path):
1372 return fctxs.get(path)
1368 return fctxs.get(path)
1373
1369
1374 if len(ps) == 0 or ps[0] < 0:
1370 if len(ps) == 0 or ps[0] < 0:
1375 pars = [None, None]
1371 pars = [None, None]
1376 elif len(ps) == 1:
1372 elif len(ps) == 1:
1377 pars = [nodeids[ps[0]], None]
1373 pars = [nodeids[ps[0]], None]
1378 else:
1374 else:
1379 pars = [nodeids[p] for p in ps]
1375 pars = [nodeids[p] for p in ps]
1380 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1376 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1381 date=(id, 0),
1377 date=(id, 0),
1382 user="debugbuilddag",
1378 user="debugbuilddag",
1383 extra={'branch': atbranch})
1379 extra={'branch': atbranch})
1384 nodeid = repo.commitctx(cx)
1380 nodeid = repo.commitctx(cx)
1385 nodeids.append(nodeid)
1381 nodeids.append(nodeid)
1386 at = id
1382 at = id
1387 elif type == 'l':
1383 elif type == 'l':
1388 id, name = data
1384 id, name = data
1389 ui.note('tag %s\n' % name)
1385 ui.note('tag %s\n' % name)
1390 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1386 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1391 elif type == 'a':
1387 elif type == 'a':
1392 ui.note('branch %s\n' % data)
1388 ui.note('branch %s\n' % data)
1393 atbranch = data
1389 atbranch = data
1394 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1390 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1395 tr.close()
1391 tr.close()
1396 finally:
1392 finally:
1397 ui.progress(_('building'), None)
1393 ui.progress(_('building'), None)
1398 tr.release()
1394 tr.release()
1399
1395
1400 if tags:
1396 if tags:
1401 repo.opener.write("localtags", "".join(tags))
1397 repo.opener.write("localtags", "".join(tags))
1402
1398
1403 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1399 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1404 def debugbundle(ui, bundlepath, all=None, **opts):
1400 def debugbundle(ui, bundlepath, all=None, **opts):
1405 """lists the contents of a bundle"""
1401 """lists the contents of a bundle"""
1406 f = url.open(ui, bundlepath)
1402 f = url.open(ui, bundlepath)
1407 try:
1403 try:
1408 gen = changegroup.readbundle(f, bundlepath)
1404 gen = changegroup.readbundle(f, bundlepath)
1409 if all:
1405 if all:
1410 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1406 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1411
1407
1412 def showchunks(named):
1408 def showchunks(named):
1413 ui.write("\n%s\n" % named)
1409 ui.write("\n%s\n" % named)
1414 chain = None
1410 chain = None
1415 while True:
1411 while True:
1416 chunkdata = gen.deltachunk(chain)
1412 chunkdata = gen.deltachunk(chain)
1417 if not chunkdata:
1413 if not chunkdata:
1418 break
1414 break
1419 node = chunkdata['node']
1415 node = chunkdata['node']
1420 p1 = chunkdata['p1']
1416 p1 = chunkdata['p1']
1421 p2 = chunkdata['p2']
1417 p2 = chunkdata['p2']
1422 cs = chunkdata['cs']
1418 cs = chunkdata['cs']
1423 deltabase = chunkdata['deltabase']
1419 deltabase = chunkdata['deltabase']
1424 delta = chunkdata['delta']
1420 delta = chunkdata['delta']
1425 ui.write("%s %s %s %s %s %s\n" %
1421 ui.write("%s %s %s %s %s %s\n" %
1426 (hex(node), hex(p1), hex(p2),
1422 (hex(node), hex(p1), hex(p2),
1427 hex(cs), hex(deltabase), len(delta)))
1423 hex(cs), hex(deltabase), len(delta)))
1428 chain = node
1424 chain = node
1429
1425
1430 chunkdata = gen.changelogheader()
1426 chunkdata = gen.changelogheader()
1431 showchunks("changelog")
1427 showchunks("changelog")
1432 chunkdata = gen.manifestheader()
1428 chunkdata = gen.manifestheader()
1433 showchunks("manifest")
1429 showchunks("manifest")
1434 while True:
1430 while True:
1435 chunkdata = gen.filelogheader()
1431 chunkdata = gen.filelogheader()
1436 if not chunkdata:
1432 if not chunkdata:
1437 break
1433 break
1438 fname = chunkdata['filename']
1434 fname = chunkdata['filename']
1439 showchunks(fname)
1435 showchunks(fname)
1440 else:
1436 else:
1441 chunkdata = gen.changelogheader()
1437 chunkdata = gen.changelogheader()
1442 chain = None
1438 chain = None
1443 while True:
1439 while True:
1444 chunkdata = gen.deltachunk(chain)
1440 chunkdata = gen.deltachunk(chain)
1445 if not chunkdata:
1441 if not chunkdata:
1446 break
1442 break
1447 node = chunkdata['node']
1443 node = chunkdata['node']
1448 ui.write("%s\n" % hex(node))
1444 ui.write("%s\n" % hex(node))
1449 chain = node
1445 chain = node
1450 finally:
1446 finally:
1451 f.close()
1447 f.close()
1452
1448
1453 @command('debugcheckstate', [], '')
1449 @command('debugcheckstate', [], '')
1454 def debugcheckstate(ui, repo):
1450 def debugcheckstate(ui, repo):
1455 """validate the correctness of the current dirstate"""
1451 """validate the correctness of the current dirstate"""
1456 parent1, parent2 = repo.dirstate.parents()
1452 parent1, parent2 = repo.dirstate.parents()
1457 m1 = repo[parent1].manifest()
1453 m1 = repo[parent1].manifest()
1458 m2 = repo[parent2].manifest()
1454 m2 = repo[parent2].manifest()
1459 errors = 0
1455 errors = 0
1460 for f in repo.dirstate:
1456 for f in repo.dirstate:
1461 state = repo.dirstate[f]
1457 state = repo.dirstate[f]
1462 if state in "nr" and f not in m1:
1458 if state in "nr" and f not in m1:
1463 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1459 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1464 errors += 1
1460 errors += 1
1465 if state in "a" and f in m1:
1461 if state in "a" and f in m1:
1466 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1462 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1467 errors += 1
1463 errors += 1
1468 if state in "m" and f not in m1 and f not in m2:
1464 if state in "m" and f not in m1 and f not in m2:
1469 ui.warn(_("%s in state %s, but not in either manifest\n") %
1465 ui.warn(_("%s in state %s, but not in either manifest\n") %
1470 (f, state))
1466 (f, state))
1471 errors += 1
1467 errors += 1
1472 for f in m1:
1468 for f in m1:
1473 state = repo.dirstate[f]
1469 state = repo.dirstate[f]
1474 if state not in "nrm":
1470 if state not in "nrm":
1475 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1471 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1476 errors += 1
1472 errors += 1
1477 if errors:
1473 if errors:
1478 error = _(".hg/dirstate inconsistent with current parent's manifest")
1474 error = _(".hg/dirstate inconsistent with current parent's manifest")
1479 raise util.Abort(error)
1475 raise util.Abort(error)
1480
1476
1481 @command('debugcommands', [], _('[COMMAND]'))
1477 @command('debugcommands', [], _('[COMMAND]'))
1482 def debugcommands(ui, cmd='', *args):
1478 def debugcommands(ui, cmd='', *args):
1483 """list all available commands and options"""
1479 """list all available commands and options"""
1484 for cmd, vals in sorted(table.iteritems()):
1480 for cmd, vals in sorted(table.iteritems()):
1485 cmd = cmd.split('|')[0].strip('^')
1481 cmd = cmd.split('|')[0].strip('^')
1486 opts = ', '.join([i[1] for i in vals[1]])
1482 opts = ', '.join([i[1] for i in vals[1]])
1487 ui.write('%s: %s\n' % (cmd, opts))
1483 ui.write('%s: %s\n' % (cmd, opts))
1488
1484
1489 @command('debugcomplete',
1485 @command('debugcomplete',
1490 [('o', 'options', None, _('show the command options'))],
1486 [('o', 'options', None, _('show the command options'))],
1491 _('[-o] CMD'))
1487 _('[-o] CMD'))
1492 def debugcomplete(ui, cmd='', **opts):
1488 def debugcomplete(ui, cmd='', **opts):
1493 """returns the completion list associated with the given command"""
1489 """returns the completion list associated with the given command"""
1494
1490
1495 if opts.get('options'):
1491 if opts.get('options'):
1496 options = []
1492 options = []
1497 otables = [globalopts]
1493 otables = [globalopts]
1498 if cmd:
1494 if cmd:
1499 aliases, entry = cmdutil.findcmd(cmd, table, False)
1495 aliases, entry = cmdutil.findcmd(cmd, table, False)
1500 otables.append(entry[1])
1496 otables.append(entry[1])
1501 for t in otables:
1497 for t in otables:
1502 for o in t:
1498 for o in t:
1503 if "(DEPRECATED)" in o[3]:
1499 if "(DEPRECATED)" in o[3]:
1504 continue
1500 continue
1505 if o[0]:
1501 if o[0]:
1506 options.append('-%s' % o[0])
1502 options.append('-%s' % o[0])
1507 options.append('--%s' % o[1])
1503 options.append('--%s' % o[1])
1508 ui.write("%s\n" % "\n".join(options))
1504 ui.write("%s\n" % "\n".join(options))
1509 return
1505 return
1510
1506
1511 cmdlist = cmdutil.findpossible(cmd, table)
1507 cmdlist = cmdutil.findpossible(cmd, table)
1512 if ui.verbose:
1508 if ui.verbose:
1513 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1509 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1514 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1510 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1515
1511
1516 @command('debugdag',
1512 @command('debugdag',
1517 [('t', 'tags', None, _('use tags as labels')),
1513 [('t', 'tags', None, _('use tags as labels')),
1518 ('b', 'branches', None, _('annotate with branch names')),
1514 ('b', 'branches', None, _('annotate with branch names')),
1519 ('', 'dots', None, _('use dots for runs')),
1515 ('', 'dots', None, _('use dots for runs')),
1520 ('s', 'spaces', None, _('separate elements by spaces'))],
1516 ('s', 'spaces', None, _('separate elements by spaces'))],
1521 _('[OPTION]... [FILE [REV]...]'))
1517 _('[OPTION]... [FILE [REV]...]'))
1522 def debugdag(ui, repo, file_=None, *revs, **opts):
1518 def debugdag(ui, repo, file_=None, *revs, **opts):
1523 """format the changelog or an index DAG as a concise textual description
1519 """format the changelog or an index DAG as a concise textual description
1524
1520
1525 If you pass a revlog index, the revlog's DAG is emitted. If you list
1521 If you pass a revlog index, the revlog's DAG is emitted. If you list
1526 revision numbers, they get labelled in the output as rN.
1522 revision numbers, they get labelled in the output as rN.
1527
1523
1528 Otherwise, the changelog DAG of the current repo is emitted.
1524 Otherwise, the changelog DAG of the current repo is emitted.
1529 """
1525 """
1530 spaces = opts.get('spaces')
1526 spaces = opts.get('spaces')
1531 dots = opts.get('dots')
1527 dots = opts.get('dots')
1532 if file_:
1528 if file_:
1533 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1529 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1534 revs = set((int(r) for r in revs))
1530 revs = set((int(r) for r in revs))
1535 def events():
1531 def events():
1536 for r in rlog:
1532 for r in rlog:
1537 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1533 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1538 if r in revs:
1534 if r in revs:
1539 yield 'l', (r, "r%i" % r)
1535 yield 'l', (r, "r%i" % r)
1540 elif repo:
1536 elif repo:
1541 cl = repo.changelog
1537 cl = repo.changelog
1542 tags = opts.get('tags')
1538 tags = opts.get('tags')
1543 branches = opts.get('branches')
1539 branches = opts.get('branches')
1544 if tags:
1540 if tags:
1545 labels = {}
1541 labels = {}
1546 for l, n in repo.tags().items():
1542 for l, n in repo.tags().items():
1547 labels.setdefault(cl.rev(n), []).append(l)
1543 labels.setdefault(cl.rev(n), []).append(l)
1548 def events():
1544 def events():
1549 b = "default"
1545 b = "default"
1550 for r in cl:
1546 for r in cl:
1551 if branches:
1547 if branches:
1552 newb = cl.read(cl.node(r))[5]['branch']
1548 newb = cl.read(cl.node(r))[5]['branch']
1553 if newb != b:
1549 if newb != b:
1554 yield 'a', newb
1550 yield 'a', newb
1555 b = newb
1551 b = newb
1556 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1552 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1557 if tags:
1553 if tags:
1558 ls = labels.get(r)
1554 ls = labels.get(r)
1559 if ls:
1555 if ls:
1560 for l in ls:
1556 for l in ls:
1561 yield 'l', (r, l)
1557 yield 'l', (r, l)
1562 else:
1558 else:
1563 raise util.Abort(_('need repo for changelog dag'))
1559 raise util.Abort(_('need repo for changelog dag'))
1564
1560
1565 for line in dagparser.dagtextlines(events(),
1561 for line in dagparser.dagtextlines(events(),
1566 addspaces=spaces,
1562 addspaces=spaces,
1567 wraplabels=True,
1563 wraplabels=True,
1568 wrapannotations=True,
1564 wrapannotations=True,
1569 wrapnonlinear=dots,
1565 wrapnonlinear=dots,
1570 usedots=dots,
1566 usedots=dots,
1571 maxlinewidth=70):
1567 maxlinewidth=70):
1572 ui.write(line)
1568 ui.write(line)
1573 ui.write("\n")
1569 ui.write("\n")
1574
1570
1575 @command('debugdata',
1571 @command('debugdata',
1576 [('c', 'changelog', False, _('open changelog')),
1572 [('c', 'changelog', False, _('open changelog')),
1577 ('m', 'manifest', False, _('open manifest'))],
1573 ('m', 'manifest', False, _('open manifest'))],
1578 _('-c|-m|FILE REV'))
1574 _('-c|-m|FILE REV'))
1579 def debugdata(ui, repo, file_, rev = None, **opts):
1575 def debugdata(ui, repo, file_, rev = None, **opts):
1580 """dump the contents of a data file revision"""
1576 """dump the contents of a data file revision"""
1581 if opts.get('changelog') or opts.get('manifest'):
1577 if opts.get('changelog') or opts.get('manifest'):
1582 file_, rev = None, file_
1578 file_, rev = None, file_
1583 elif rev is None:
1579 elif rev is None:
1584 raise error.CommandError('debugdata', _('invalid arguments'))
1580 raise error.CommandError('debugdata', _('invalid arguments'))
1585 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1581 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1586 try:
1582 try:
1587 ui.write(r.revision(r.lookup(rev)))
1583 ui.write(r.revision(r.lookup(rev)))
1588 except KeyError:
1584 except KeyError:
1589 raise util.Abort(_('invalid revision identifier %s') % rev)
1585 raise util.Abort(_('invalid revision identifier %s') % rev)
1590
1586
1591 @command('debugdate',
1587 @command('debugdate',
1592 [('e', 'extended', None, _('try extended date formats'))],
1588 [('e', 'extended', None, _('try extended date formats'))],
1593 _('[-e] DATE [RANGE]'))
1589 _('[-e] DATE [RANGE]'))
1594 def debugdate(ui, date, range=None, **opts):
1590 def debugdate(ui, date, range=None, **opts):
1595 """parse and display a date"""
1591 """parse and display a date"""
1596 if opts["extended"]:
1592 if opts["extended"]:
1597 d = util.parsedate(date, util.extendeddateformats)
1593 d = util.parsedate(date, util.extendeddateformats)
1598 else:
1594 else:
1599 d = util.parsedate(date)
1595 d = util.parsedate(date)
1600 ui.write("internal: %s %s\n" % d)
1596 ui.write("internal: %s %s\n" % d)
1601 ui.write("standard: %s\n" % util.datestr(d))
1597 ui.write("standard: %s\n" % util.datestr(d))
1602 if range:
1598 if range:
1603 m = util.matchdate(range)
1599 m = util.matchdate(range)
1604 ui.write("match: %s\n" % m(d[0]))
1600 ui.write("match: %s\n" % m(d[0]))
1605
1601
1606 @command('debugdiscovery',
1602 @command('debugdiscovery',
1607 [('', 'old', None, _('use old-style discovery')),
1603 [('', 'old', None, _('use old-style discovery')),
1608 ('', 'nonheads', None,
1604 ('', 'nonheads', None,
1609 _('use old-style discovery with non-heads included')),
1605 _('use old-style discovery with non-heads included')),
1610 ] + remoteopts,
1606 ] + remoteopts,
1611 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1607 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1612 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1608 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1613 """runs the changeset discovery protocol in isolation"""
1609 """runs the changeset discovery protocol in isolation"""
1614 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1610 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1615 remote = hg.peer(repo, opts, remoteurl)
1611 remote = hg.peer(repo, opts, remoteurl)
1616 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1612 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1617
1613
1618 # make sure tests are repeatable
1614 # make sure tests are repeatable
1619 random.seed(12323)
1615 random.seed(12323)
1620
1616
1621 def doit(localheads, remoteheads):
1617 def doit(localheads, remoteheads):
1622 if opts.get('old'):
1618 if opts.get('old'):
1623 if localheads:
1619 if localheads:
1624 raise util.Abort('cannot use localheads with old style discovery')
1620 raise util.Abort('cannot use localheads with old style discovery')
1625 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1621 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1626 force=True)
1622 force=True)
1627 common = set(common)
1623 common = set(common)
1628 if not opts.get('nonheads'):
1624 if not opts.get('nonheads'):
1629 ui.write("unpruned common: %s\n" % " ".join([short(n)
1625 ui.write("unpruned common: %s\n" % " ".join([short(n)
1630 for n in common]))
1626 for n in common]))
1631 dag = dagutil.revlogdag(repo.changelog)
1627 dag = dagutil.revlogdag(repo.changelog)
1632 all = dag.ancestorset(dag.internalizeall(common))
1628 all = dag.ancestorset(dag.internalizeall(common))
1633 common = dag.externalizeall(dag.headsetofconnecteds(all))
1629 common = dag.externalizeall(dag.headsetofconnecteds(all))
1634 else:
1630 else:
1635 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1631 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1636 common = set(common)
1632 common = set(common)
1637 rheads = set(hds)
1633 rheads = set(hds)
1638 lheads = set(repo.heads())
1634 lheads = set(repo.heads())
1639 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1635 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1640 if lheads <= common:
1636 if lheads <= common:
1641 ui.write("local is subset\n")
1637 ui.write("local is subset\n")
1642 elif rheads <= common:
1638 elif rheads <= common:
1643 ui.write("remote is subset\n")
1639 ui.write("remote is subset\n")
1644
1640
1645 serverlogs = opts.get('serverlog')
1641 serverlogs = opts.get('serverlog')
1646 if serverlogs:
1642 if serverlogs:
1647 for filename in serverlogs:
1643 for filename in serverlogs:
1648 logfile = open(filename, 'r')
1644 logfile = open(filename, 'r')
1649 try:
1645 try:
1650 line = logfile.readline()
1646 line = logfile.readline()
1651 while line:
1647 while line:
1652 parts = line.strip().split(';')
1648 parts = line.strip().split(';')
1653 op = parts[1]
1649 op = parts[1]
1654 if op == 'cg':
1650 if op == 'cg':
1655 pass
1651 pass
1656 elif op == 'cgss':
1652 elif op == 'cgss':
1657 doit(parts[2].split(' '), parts[3].split(' '))
1653 doit(parts[2].split(' '), parts[3].split(' '))
1658 elif op == 'unb':
1654 elif op == 'unb':
1659 doit(parts[3].split(' '), parts[2].split(' '))
1655 doit(parts[3].split(' '), parts[2].split(' '))
1660 line = logfile.readline()
1656 line = logfile.readline()
1661 finally:
1657 finally:
1662 logfile.close()
1658 logfile.close()
1663
1659
1664 else:
1660 else:
1665 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1661 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1666 opts.get('remote_head'))
1662 opts.get('remote_head'))
1667 localrevs = opts.get('local_head')
1663 localrevs = opts.get('local_head')
1668 doit(localrevs, remoterevs)
1664 doit(localrevs, remoterevs)
1669
1665
1670 @command('debugfileset', [], ('REVSPEC'))
1666 @command('debugfileset', [], ('REVSPEC'))
1671 def debugfileset(ui, repo, expr):
1667 def debugfileset(ui, repo, expr):
1672 '''parse and apply a fileset specification'''
1668 '''parse and apply a fileset specification'''
1673 if ui.verbose:
1669 if ui.verbose:
1674 tree = fileset.parse(expr)[0]
1670 tree = fileset.parse(expr)[0]
1675 ui.note(tree, "\n")
1671 ui.note(tree, "\n")
1676
1672
1677 for f in fileset.getfileset(repo[None], expr):
1673 for f in fileset.getfileset(repo[None], expr):
1678 ui.write("%s\n" % f)
1674 ui.write("%s\n" % f)
1679
1675
1680 @command('debugfsinfo', [], _('[PATH]'))
1676 @command('debugfsinfo', [], _('[PATH]'))
1681 def debugfsinfo(ui, path = "."):
1677 def debugfsinfo(ui, path = "."):
1682 """show information detected about current filesystem"""
1678 """show information detected about current filesystem"""
1683 util.writefile('.debugfsinfo', '')
1679 util.writefile('.debugfsinfo', '')
1684 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1680 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1685 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1681 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1686 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1682 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1687 and 'yes' or 'no'))
1683 and 'yes' or 'no'))
1688 os.unlink('.debugfsinfo')
1684 os.unlink('.debugfsinfo')
1689
1685
1690 @command('debuggetbundle',
1686 @command('debuggetbundle',
1691 [('H', 'head', [], _('id of head node'), _('ID')),
1687 [('H', 'head', [], _('id of head node'), _('ID')),
1692 ('C', 'common', [], _('id of common node'), _('ID')),
1688 ('C', 'common', [], _('id of common node'), _('ID')),
1693 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1689 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1694 _('REPO FILE [-H|-C ID]...'))
1690 _('REPO FILE [-H|-C ID]...'))
1695 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1691 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1696 """retrieves a bundle from a repo
1692 """retrieves a bundle from a repo
1697
1693
1698 Every ID must be a full-length hex node id string. Saves the bundle to the
1694 Every ID must be a full-length hex node id string. Saves the bundle to the
1699 given file.
1695 given file.
1700 """
1696 """
1701 repo = hg.peer(ui, opts, repopath)
1697 repo = hg.peer(ui, opts, repopath)
1702 if not repo.capable('getbundle'):
1698 if not repo.capable('getbundle'):
1703 raise util.Abort("getbundle() not supported by target repository")
1699 raise util.Abort("getbundle() not supported by target repository")
1704 args = {}
1700 args = {}
1705 if common:
1701 if common:
1706 args['common'] = [bin(s) for s in common]
1702 args['common'] = [bin(s) for s in common]
1707 if head:
1703 if head:
1708 args['heads'] = [bin(s) for s in head]
1704 args['heads'] = [bin(s) for s in head]
1709 bundle = repo.getbundle('debug', **args)
1705 bundle = repo.getbundle('debug', **args)
1710
1706
1711 bundletype = opts.get('type', 'bzip2').lower()
1707 bundletype = opts.get('type', 'bzip2').lower()
1712 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1708 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1713 bundletype = btypes.get(bundletype)
1709 bundletype = btypes.get(bundletype)
1714 if bundletype not in changegroup.bundletypes:
1710 if bundletype not in changegroup.bundletypes:
1715 raise util.Abort(_('unknown bundle type specified with --type'))
1711 raise util.Abort(_('unknown bundle type specified with --type'))
1716 changegroup.writebundle(bundle, bundlepath, bundletype)
1712 changegroup.writebundle(bundle, bundlepath, bundletype)
1717
1713
1718 @command('debugignore', [], '')
1714 @command('debugignore', [], '')
1719 def debugignore(ui, repo, *values, **opts):
1715 def debugignore(ui, repo, *values, **opts):
1720 """display the combined ignore pattern"""
1716 """display the combined ignore pattern"""
1721 ignore = repo.dirstate._ignore
1717 ignore = repo.dirstate._ignore
1722 includepat = getattr(ignore, 'includepat', None)
1718 includepat = getattr(ignore, 'includepat', None)
1723 if includepat is not None:
1719 if includepat is not None:
1724 ui.write("%s\n" % includepat)
1720 ui.write("%s\n" % includepat)
1725 else:
1721 else:
1726 raise util.Abort(_("no ignore patterns found"))
1722 raise util.Abort(_("no ignore patterns found"))
1727
1723
1728 @command('debugindex',
1724 @command('debugindex',
1729 [('c', 'changelog', False, _('open changelog')),
1725 [('c', 'changelog', False, _('open changelog')),
1730 ('m', 'manifest', False, _('open manifest')),
1726 ('m', 'manifest', False, _('open manifest')),
1731 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1727 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1732 _('[-f FORMAT] -c|-m|FILE'))
1728 _('[-f FORMAT] -c|-m|FILE'))
1733 def debugindex(ui, repo, file_ = None, **opts):
1729 def debugindex(ui, repo, file_ = None, **opts):
1734 """dump the contents of an index file"""
1730 """dump the contents of an index file"""
1735 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1731 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1736 format = opts.get('format', 0)
1732 format = opts.get('format', 0)
1737 if format not in (0, 1):
1733 if format not in (0, 1):
1738 raise util.Abort(_("unknown format %d") % format)
1734 raise util.Abort(_("unknown format %d") % format)
1739
1735
1740 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1736 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1741 if generaldelta:
1737 if generaldelta:
1742 basehdr = ' delta'
1738 basehdr = ' delta'
1743 else:
1739 else:
1744 basehdr = ' base'
1740 basehdr = ' base'
1745
1741
1746 if format == 0:
1742 if format == 0:
1747 ui.write(" rev offset length " + basehdr + " linkrev"
1743 ui.write(" rev offset length " + basehdr + " linkrev"
1748 " nodeid p1 p2\n")
1744 " nodeid p1 p2\n")
1749 elif format == 1:
1745 elif format == 1:
1750 ui.write(" rev flag offset length"
1746 ui.write(" rev flag offset length"
1751 " size " + basehdr + " link p1 p2 nodeid\n")
1747 " size " + basehdr + " link p1 p2 nodeid\n")
1752
1748
1753 for i in r:
1749 for i in r:
1754 node = r.node(i)
1750 node = r.node(i)
1755 if generaldelta:
1751 if generaldelta:
1756 base = r.deltaparent(i)
1752 base = r.deltaparent(i)
1757 else:
1753 else:
1758 base = r.chainbase(i)
1754 base = r.chainbase(i)
1759 if format == 0:
1755 if format == 0:
1760 try:
1756 try:
1761 pp = r.parents(node)
1757 pp = r.parents(node)
1762 except:
1758 except:
1763 pp = [nullid, nullid]
1759 pp = [nullid, nullid]
1764 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1760 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1765 i, r.start(i), r.length(i), base, r.linkrev(i),
1761 i, r.start(i), r.length(i), base, r.linkrev(i),
1766 short(node), short(pp[0]), short(pp[1])))
1762 short(node), short(pp[0]), short(pp[1])))
1767 elif format == 1:
1763 elif format == 1:
1768 pr = r.parentrevs(i)
1764 pr = r.parentrevs(i)
1769 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1765 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1770 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1766 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1771 base, r.linkrev(i), pr[0], pr[1], short(node)))
1767 base, r.linkrev(i), pr[0], pr[1], short(node)))
1772
1768
1773 @command('debugindexdot', [], _('FILE'))
1769 @command('debugindexdot', [], _('FILE'))
1774 def debugindexdot(ui, repo, file_):
1770 def debugindexdot(ui, repo, file_):
1775 """dump an index DAG as a graphviz dot file"""
1771 """dump an index DAG as a graphviz dot file"""
1776 r = None
1772 r = None
1777 if repo:
1773 if repo:
1778 filelog = repo.file(file_)
1774 filelog = repo.file(file_)
1779 if len(filelog):
1775 if len(filelog):
1780 r = filelog
1776 r = filelog
1781 if not r:
1777 if not r:
1782 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1778 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1783 ui.write("digraph G {\n")
1779 ui.write("digraph G {\n")
1784 for i in r:
1780 for i in r:
1785 node = r.node(i)
1781 node = r.node(i)
1786 pp = r.parents(node)
1782 pp = r.parents(node)
1787 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1783 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1788 if pp[1] != nullid:
1784 if pp[1] != nullid:
1789 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1785 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1790 ui.write("}\n")
1786 ui.write("}\n")
1791
1787
1792 @command('debuginstall', [], '')
1788 @command('debuginstall', [], '')
1793 def debuginstall(ui):
1789 def debuginstall(ui):
1794 '''test Mercurial installation
1790 '''test Mercurial installation
1795
1791
1796 Returns 0 on success.
1792 Returns 0 on success.
1797 '''
1793 '''
1798
1794
1799 def writetemp(contents):
1795 def writetemp(contents):
1800 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1796 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1801 f = os.fdopen(fd, "wb")
1797 f = os.fdopen(fd, "wb")
1802 f.write(contents)
1798 f.write(contents)
1803 f.close()
1799 f.close()
1804 return name
1800 return name
1805
1801
1806 problems = 0
1802 problems = 0
1807
1803
1808 # encoding
1804 # encoding
1809 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1805 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1810 try:
1806 try:
1811 encoding.fromlocal("test")
1807 encoding.fromlocal("test")
1812 except util.Abort, inst:
1808 except util.Abort, inst:
1813 ui.write(" %s\n" % inst)
1809 ui.write(" %s\n" % inst)
1814 ui.write(_(" (check that your locale is properly set)\n"))
1810 ui.write(_(" (check that your locale is properly set)\n"))
1815 problems += 1
1811 problems += 1
1816
1812
1817 # compiled modules
1813 # compiled modules
1818 ui.status(_("Checking installed modules (%s)...\n")
1814 ui.status(_("Checking installed modules (%s)...\n")
1819 % os.path.dirname(__file__))
1815 % os.path.dirname(__file__))
1820 try:
1816 try:
1821 import bdiff, mpatch, base85, osutil
1817 import bdiff, mpatch, base85, osutil
1822 except Exception, inst:
1818 except Exception, inst:
1823 ui.write(" %s\n" % inst)
1819 ui.write(" %s\n" % inst)
1824 ui.write(_(" One or more extensions could not be found"))
1820 ui.write(_(" One or more extensions could not be found"))
1825 ui.write(_(" (check that you compiled the extensions)\n"))
1821 ui.write(_(" (check that you compiled the extensions)\n"))
1826 problems += 1
1822 problems += 1
1827
1823
1828 # templates
1824 # templates
1829 ui.status(_("Checking templates...\n"))
1825 ui.status(_("Checking templates...\n"))
1830 try:
1826 try:
1831 import templater
1827 import templater
1832 templater.templater(templater.templatepath("map-cmdline.default"))
1828 templater.templater(templater.templatepath("map-cmdline.default"))
1833 except Exception, inst:
1829 except Exception, inst:
1834 ui.write(" %s\n" % inst)
1830 ui.write(" %s\n" % inst)
1835 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1831 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1836 problems += 1
1832 problems += 1
1837
1833
1838 # editor
1834 # editor
1839 ui.status(_("Checking commit editor...\n"))
1835 ui.status(_("Checking commit editor...\n"))
1840 editor = ui.geteditor()
1836 editor = ui.geteditor()
1841 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1837 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1842 if not cmdpath:
1838 if not cmdpath:
1843 if editor == 'vi':
1839 if editor == 'vi':
1844 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1840 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1845 ui.write(_(" (specify a commit editor in your configuration"
1841 ui.write(_(" (specify a commit editor in your configuration"
1846 " file)\n"))
1842 " file)\n"))
1847 else:
1843 else:
1848 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1844 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1849 ui.write(_(" (specify a commit editor in your configuration"
1845 ui.write(_(" (specify a commit editor in your configuration"
1850 " file)\n"))
1846 " file)\n"))
1851 problems += 1
1847 problems += 1
1852
1848
1853 # check username
1849 # check username
1854 ui.status(_("Checking username...\n"))
1850 ui.status(_("Checking username...\n"))
1855 try:
1851 try:
1856 ui.username()
1852 ui.username()
1857 except util.Abort, e:
1853 except util.Abort, e:
1858 ui.write(" %s\n" % e)
1854 ui.write(" %s\n" % e)
1859 ui.write(_(" (specify a username in your configuration file)\n"))
1855 ui.write(_(" (specify a username in your configuration file)\n"))
1860 problems += 1
1856 problems += 1
1861
1857
1862 if not problems:
1858 if not problems:
1863 ui.status(_("No problems detected\n"))
1859 ui.status(_("No problems detected\n"))
1864 else:
1860 else:
1865 ui.write(_("%s problems detected,"
1861 ui.write(_("%s problems detected,"
1866 " please check your install!\n") % problems)
1862 " please check your install!\n") % problems)
1867
1863
1868 return problems
1864 return problems
1869
1865
1870 @command('debugknown', [], _('REPO ID...'))
1866 @command('debugknown', [], _('REPO ID...'))
1871 def debugknown(ui, repopath, *ids, **opts):
1867 def debugknown(ui, repopath, *ids, **opts):
1872 """test whether node ids are known to a repo
1868 """test whether node ids are known to a repo
1873
1869
1874 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1870 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1875 indicating unknown/known.
1871 indicating unknown/known.
1876 """
1872 """
1877 repo = hg.peer(ui, opts, repopath)
1873 repo = hg.peer(ui, opts, repopath)
1878 if not repo.capable('known'):
1874 if not repo.capable('known'):
1879 raise util.Abort("known() not supported by target repository")
1875 raise util.Abort("known() not supported by target repository")
1880 flags = repo.known([bin(s) for s in ids])
1876 flags = repo.known([bin(s) for s in ids])
1881 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1877 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1882
1878
1883 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1879 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1884 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1880 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1885 '''access the pushkey key/value protocol
1881 '''access the pushkey key/value protocol
1886
1882
1887 With two args, list the keys in the given namespace.
1883 With two args, list the keys in the given namespace.
1888
1884
1889 With five args, set a key to new if it currently is set to old.
1885 With five args, set a key to new if it currently is set to old.
1890 Reports success or failure.
1886 Reports success or failure.
1891 '''
1887 '''
1892
1888
1893 target = hg.peer(ui, {}, repopath)
1889 target = hg.peer(ui, {}, repopath)
1894 if keyinfo:
1890 if keyinfo:
1895 key, old, new = keyinfo
1891 key, old, new = keyinfo
1896 r = target.pushkey(namespace, key, old, new)
1892 r = target.pushkey(namespace, key, old, new)
1897 ui.status(str(r) + '\n')
1893 ui.status(str(r) + '\n')
1898 return not r
1894 return not r
1899 else:
1895 else:
1900 for k, v in target.listkeys(namespace).iteritems():
1896 for k, v in target.listkeys(namespace).iteritems():
1901 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1897 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1902 v.encode('string-escape')))
1898 v.encode('string-escape')))
1903
1899
1904 @command('debugrebuildstate',
1900 @command('debugrebuildstate',
1905 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1901 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1906 _('[-r REV] [REV]'))
1902 _('[-r REV] [REV]'))
1907 def debugrebuildstate(ui, repo, rev="tip"):
1903 def debugrebuildstate(ui, repo, rev="tip"):
1908 """rebuild the dirstate as it would look like for the given revision"""
1904 """rebuild the dirstate as it would look like for the given revision"""
1909 ctx = scmutil.revsingle(repo, rev)
1905 ctx = scmutil.revsingle(repo, rev)
1910 wlock = repo.wlock()
1906 wlock = repo.wlock()
1911 try:
1907 try:
1912 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1908 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1913 finally:
1909 finally:
1914 wlock.release()
1910 wlock.release()
1915
1911
1916 @command('debugrename',
1912 @command('debugrename',
1917 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1913 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1918 _('[-r REV] FILE'))
1914 _('[-r REV] FILE'))
1919 def debugrename(ui, repo, file1, *pats, **opts):
1915 def debugrename(ui, repo, file1, *pats, **opts):
1920 """dump rename information"""
1916 """dump rename information"""
1921
1917
1922 ctx = scmutil.revsingle(repo, opts.get('rev'))
1918 ctx = scmutil.revsingle(repo, opts.get('rev'))
1923 m = scmutil.match(ctx, (file1,) + pats, opts)
1919 m = scmutil.match(ctx, (file1,) + pats, opts)
1924 for abs in ctx.walk(m):
1920 for abs in ctx.walk(m):
1925 fctx = ctx[abs]
1921 fctx = ctx[abs]
1926 o = fctx.filelog().renamed(fctx.filenode())
1922 o = fctx.filelog().renamed(fctx.filenode())
1927 rel = m.rel(abs)
1923 rel = m.rel(abs)
1928 if o:
1924 if o:
1929 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1925 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1930 else:
1926 else:
1931 ui.write(_("%s not renamed\n") % rel)
1927 ui.write(_("%s not renamed\n") % rel)
1932
1928
1933 @command('debugrevlog',
1929 @command('debugrevlog',
1934 [('c', 'changelog', False, _('open changelog')),
1930 [('c', 'changelog', False, _('open changelog')),
1935 ('m', 'manifest', False, _('open manifest')),
1931 ('m', 'manifest', False, _('open manifest')),
1936 ('d', 'dump', False, _('dump index data'))],
1932 ('d', 'dump', False, _('dump index data'))],
1937 _('-c|-m|FILE'))
1933 _('-c|-m|FILE'))
1938 def debugrevlog(ui, repo, file_ = None, **opts):
1934 def debugrevlog(ui, repo, file_ = None, **opts):
1939 """show data and statistics about a revlog"""
1935 """show data and statistics about a revlog"""
1940 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1936 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1941
1937
1942 if opts.get("dump"):
1938 if opts.get("dump"):
1943 numrevs = len(r)
1939 numrevs = len(r)
1944 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1940 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1945 " rawsize totalsize compression heads\n")
1941 " rawsize totalsize compression heads\n")
1946 ts = 0
1942 ts = 0
1947 heads = set()
1943 heads = set()
1948 for rev in xrange(numrevs):
1944 for rev in xrange(numrevs):
1949 dbase = r.deltaparent(rev)
1945 dbase = r.deltaparent(rev)
1950 if dbase == -1:
1946 if dbase == -1:
1951 dbase = rev
1947 dbase = rev
1952 cbase = r.chainbase(rev)
1948 cbase = r.chainbase(rev)
1953 p1, p2 = r.parentrevs(rev)
1949 p1, p2 = r.parentrevs(rev)
1954 rs = r.rawsize(rev)
1950 rs = r.rawsize(rev)
1955 ts = ts + rs
1951 ts = ts + rs
1956 heads -= set(r.parentrevs(rev))
1952 heads -= set(r.parentrevs(rev))
1957 heads.add(rev)
1953 heads.add(rev)
1958 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1954 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1959 (rev, p1, p2, r.start(rev), r.end(rev),
1955 (rev, p1, p2, r.start(rev), r.end(rev),
1960 r.start(dbase), r.start(cbase),
1956 r.start(dbase), r.start(cbase),
1961 r.start(p1), r.start(p2),
1957 r.start(p1), r.start(p2),
1962 rs, ts, ts / r.end(rev), len(heads)))
1958 rs, ts, ts / r.end(rev), len(heads)))
1963 return 0
1959 return 0
1964
1960
1965 v = r.version
1961 v = r.version
1966 format = v & 0xFFFF
1962 format = v & 0xFFFF
1967 flags = []
1963 flags = []
1968 gdelta = False
1964 gdelta = False
1969 if v & revlog.REVLOGNGINLINEDATA:
1965 if v & revlog.REVLOGNGINLINEDATA:
1970 flags.append('inline')
1966 flags.append('inline')
1971 if v & revlog.REVLOGGENERALDELTA:
1967 if v & revlog.REVLOGGENERALDELTA:
1972 gdelta = True
1968 gdelta = True
1973 flags.append('generaldelta')
1969 flags.append('generaldelta')
1974 if not flags:
1970 if not flags:
1975 flags = ['(none)']
1971 flags = ['(none)']
1976
1972
1977 nummerges = 0
1973 nummerges = 0
1978 numfull = 0
1974 numfull = 0
1979 numprev = 0
1975 numprev = 0
1980 nump1 = 0
1976 nump1 = 0
1981 nump2 = 0
1977 nump2 = 0
1982 numother = 0
1978 numother = 0
1983 nump1prev = 0
1979 nump1prev = 0
1984 nump2prev = 0
1980 nump2prev = 0
1985 chainlengths = []
1981 chainlengths = []
1986
1982
1987 datasize = [None, 0, 0L]
1983 datasize = [None, 0, 0L]
1988 fullsize = [None, 0, 0L]
1984 fullsize = [None, 0, 0L]
1989 deltasize = [None, 0, 0L]
1985 deltasize = [None, 0, 0L]
1990
1986
1991 def addsize(size, l):
1987 def addsize(size, l):
1992 if l[0] is None or size < l[0]:
1988 if l[0] is None or size < l[0]:
1993 l[0] = size
1989 l[0] = size
1994 if size > l[1]:
1990 if size > l[1]:
1995 l[1] = size
1991 l[1] = size
1996 l[2] += size
1992 l[2] += size
1997
1993
1998 numrevs = len(r)
1994 numrevs = len(r)
1999 for rev in xrange(numrevs):
1995 for rev in xrange(numrevs):
2000 p1, p2 = r.parentrevs(rev)
1996 p1, p2 = r.parentrevs(rev)
2001 delta = r.deltaparent(rev)
1997 delta = r.deltaparent(rev)
2002 if format > 0:
1998 if format > 0:
2003 addsize(r.rawsize(rev), datasize)
1999 addsize(r.rawsize(rev), datasize)
2004 if p2 != nullrev:
2000 if p2 != nullrev:
2005 nummerges += 1
2001 nummerges += 1
2006 size = r.length(rev)
2002 size = r.length(rev)
2007 if delta == nullrev:
2003 if delta == nullrev:
2008 chainlengths.append(0)
2004 chainlengths.append(0)
2009 numfull += 1
2005 numfull += 1
2010 addsize(size, fullsize)
2006 addsize(size, fullsize)
2011 else:
2007 else:
2012 chainlengths.append(chainlengths[delta] + 1)
2008 chainlengths.append(chainlengths[delta] + 1)
2013 addsize(size, deltasize)
2009 addsize(size, deltasize)
2014 if delta == rev - 1:
2010 if delta == rev - 1:
2015 numprev += 1
2011 numprev += 1
2016 if delta == p1:
2012 if delta == p1:
2017 nump1prev += 1
2013 nump1prev += 1
2018 elif delta == p2:
2014 elif delta == p2:
2019 nump2prev += 1
2015 nump2prev += 1
2020 elif delta == p1:
2016 elif delta == p1:
2021 nump1 += 1
2017 nump1 += 1
2022 elif delta == p2:
2018 elif delta == p2:
2023 nump2 += 1
2019 nump2 += 1
2024 elif delta != nullrev:
2020 elif delta != nullrev:
2025 numother += 1
2021 numother += 1
2026
2022
2027 numdeltas = numrevs - numfull
2023 numdeltas = numrevs - numfull
2028 numoprev = numprev - nump1prev - nump2prev
2024 numoprev = numprev - nump1prev - nump2prev
2029 totalrawsize = datasize[2]
2025 totalrawsize = datasize[2]
2030 datasize[2] /= numrevs
2026 datasize[2] /= numrevs
2031 fulltotal = fullsize[2]
2027 fulltotal = fullsize[2]
2032 fullsize[2] /= numfull
2028 fullsize[2] /= numfull
2033 deltatotal = deltasize[2]
2029 deltatotal = deltasize[2]
2034 deltasize[2] /= numrevs - numfull
2030 deltasize[2] /= numrevs - numfull
2035 totalsize = fulltotal + deltatotal
2031 totalsize = fulltotal + deltatotal
2036 avgchainlen = sum(chainlengths) / numrevs
2032 avgchainlen = sum(chainlengths) / numrevs
2037 compratio = totalrawsize / totalsize
2033 compratio = totalrawsize / totalsize
2038
2034
2039 basedfmtstr = '%%%dd\n'
2035 basedfmtstr = '%%%dd\n'
2040 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2036 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2041
2037
2042 def dfmtstr(max):
2038 def dfmtstr(max):
2043 return basedfmtstr % len(str(max))
2039 return basedfmtstr % len(str(max))
2044 def pcfmtstr(max, padding=0):
2040 def pcfmtstr(max, padding=0):
2045 return basepcfmtstr % (len(str(max)), ' ' * padding)
2041 return basepcfmtstr % (len(str(max)), ' ' * padding)
2046
2042
2047 def pcfmt(value, total):
2043 def pcfmt(value, total):
2048 return (value, 100 * float(value) / total)
2044 return (value, 100 * float(value) / total)
2049
2045
2050 ui.write('format : %d\n' % format)
2046 ui.write('format : %d\n' % format)
2051 ui.write('flags : %s\n' % ', '.join(flags))
2047 ui.write('flags : %s\n' % ', '.join(flags))
2052
2048
2053 ui.write('\n')
2049 ui.write('\n')
2054 fmt = pcfmtstr(totalsize)
2050 fmt = pcfmtstr(totalsize)
2055 fmt2 = dfmtstr(totalsize)
2051 fmt2 = dfmtstr(totalsize)
2056 ui.write('revisions : ' + fmt2 % numrevs)
2052 ui.write('revisions : ' + fmt2 % numrevs)
2057 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2053 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2058 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2054 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2059 ui.write('revisions : ' + fmt2 % numrevs)
2055 ui.write('revisions : ' + fmt2 % numrevs)
2060 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2056 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2061 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2057 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2062 ui.write('revision size : ' + fmt2 % totalsize)
2058 ui.write('revision size : ' + fmt2 % totalsize)
2063 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2059 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2064 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2060 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2065
2061
2066 ui.write('\n')
2062 ui.write('\n')
2067 fmt = dfmtstr(max(avgchainlen, compratio))
2063 fmt = dfmtstr(max(avgchainlen, compratio))
2068 ui.write('avg chain length : ' + fmt % avgchainlen)
2064 ui.write('avg chain length : ' + fmt % avgchainlen)
2069 ui.write('compression ratio : ' + fmt % compratio)
2065 ui.write('compression ratio : ' + fmt % compratio)
2070
2066
2071 if format > 0:
2067 if format > 0:
2072 ui.write('\n')
2068 ui.write('\n')
2073 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2069 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2074 % tuple(datasize))
2070 % tuple(datasize))
2075 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2071 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2076 % tuple(fullsize))
2072 % tuple(fullsize))
2077 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2073 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2078 % tuple(deltasize))
2074 % tuple(deltasize))
2079
2075
2080 if numdeltas > 0:
2076 if numdeltas > 0:
2081 ui.write('\n')
2077 ui.write('\n')
2082 fmt = pcfmtstr(numdeltas)
2078 fmt = pcfmtstr(numdeltas)
2083 fmt2 = pcfmtstr(numdeltas, 4)
2079 fmt2 = pcfmtstr(numdeltas, 4)
2084 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2080 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2085 if numprev > 0:
2081 if numprev > 0:
2086 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2082 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2087 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2083 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2088 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2084 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2089 if gdelta:
2085 if gdelta:
2090 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2086 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2091 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2087 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2092 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2088 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2093
2089
2094 @command('debugrevspec', [], ('REVSPEC'))
2090 @command('debugrevspec', [], ('REVSPEC'))
2095 def debugrevspec(ui, repo, expr):
2091 def debugrevspec(ui, repo, expr):
2096 '''parse and apply a revision specification'''
2092 '''parse and apply a revision specification'''
2097 if ui.verbose:
2093 if ui.verbose:
2098 tree = revset.parse(expr)[0]
2094 tree = revset.parse(expr)[0]
2099 ui.note(tree, "\n")
2095 ui.note(tree, "\n")
2100 newtree = revset.findaliases(ui, tree)
2096 newtree = revset.findaliases(ui, tree)
2101 if newtree != tree:
2097 if newtree != tree:
2102 ui.note(newtree, "\n")
2098 ui.note(newtree, "\n")
2103 func = revset.match(ui, expr)
2099 func = revset.match(ui, expr)
2104 for c in func(repo, range(len(repo))):
2100 for c in func(repo, range(len(repo))):
2105 ui.write("%s\n" % c)
2101 ui.write("%s\n" % c)
2106
2102
2107 @command('debugsetparents', [], _('REV1 [REV2]'))
2103 @command('debugsetparents', [], _('REV1 [REV2]'))
2108 def debugsetparents(ui, repo, rev1, rev2=None):
2104 def debugsetparents(ui, repo, rev1, rev2=None):
2109 """manually set the parents of the current working directory
2105 """manually set the parents of the current working directory
2110
2106
2111 This is useful for writing repository conversion tools, but should
2107 This is useful for writing repository conversion tools, but should
2112 be used with care.
2108 be used with care.
2113
2109
2114 Returns 0 on success.
2110 Returns 0 on success.
2115 """
2111 """
2116
2112
2117 r1 = scmutil.revsingle(repo, rev1).node()
2113 r1 = scmutil.revsingle(repo, rev1).node()
2118 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2114 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2119
2115
2120 wlock = repo.wlock()
2116 wlock = repo.wlock()
2121 try:
2117 try:
2122 repo.dirstate.setparents(r1, r2)
2118 repo.dirstate.setparents(r1, r2)
2123 finally:
2119 finally:
2124 wlock.release()
2120 wlock.release()
2125
2121
2126 @command('debugstate',
2122 @command('debugstate',
2127 [('', 'nodates', None, _('do not display the saved mtime')),
2123 [('', 'nodates', None, _('do not display the saved mtime')),
2128 ('', 'datesort', None, _('sort by saved mtime'))],
2124 ('', 'datesort', None, _('sort by saved mtime'))],
2129 _('[OPTION]...'))
2125 _('[OPTION]...'))
2130 def debugstate(ui, repo, nodates=None, datesort=None):
2126 def debugstate(ui, repo, nodates=None, datesort=None):
2131 """show the contents of the current dirstate"""
2127 """show the contents of the current dirstate"""
2132 timestr = ""
2128 timestr = ""
2133 showdate = not nodates
2129 showdate = not nodates
2134 if datesort:
2130 if datesort:
2135 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2131 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2136 else:
2132 else:
2137 keyfunc = None # sort by filename
2133 keyfunc = None # sort by filename
2138 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2134 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2139 if showdate:
2135 if showdate:
2140 if ent[3] == -1:
2136 if ent[3] == -1:
2141 # Pad or slice to locale representation
2137 # Pad or slice to locale representation
2142 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2138 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2143 time.localtime(0)))
2139 time.localtime(0)))
2144 timestr = 'unset'
2140 timestr = 'unset'
2145 timestr = (timestr[:locale_len] +
2141 timestr = (timestr[:locale_len] +
2146 ' ' * (locale_len - len(timestr)))
2142 ' ' * (locale_len - len(timestr)))
2147 else:
2143 else:
2148 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2144 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2149 time.localtime(ent[3]))
2145 time.localtime(ent[3]))
2150 if ent[1] & 020000:
2146 if ent[1] & 020000:
2151 mode = 'lnk'
2147 mode = 'lnk'
2152 else:
2148 else:
2153 mode = '%3o' % (ent[1] & 0777)
2149 mode = '%3o' % (ent[1] & 0777)
2154 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2150 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2155 for f in repo.dirstate.copies():
2151 for f in repo.dirstate.copies():
2156 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2152 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2157
2153
2158 @command('debugsub',
2154 @command('debugsub',
2159 [('r', 'rev', '',
2155 [('r', 'rev', '',
2160 _('revision to check'), _('REV'))],
2156 _('revision to check'), _('REV'))],
2161 _('[-r REV] [REV]'))
2157 _('[-r REV] [REV]'))
2162 def debugsub(ui, repo, rev=None):
2158 def debugsub(ui, repo, rev=None):
2163 ctx = scmutil.revsingle(repo, rev, None)
2159 ctx = scmutil.revsingle(repo, rev, None)
2164 for k, v in sorted(ctx.substate.items()):
2160 for k, v in sorted(ctx.substate.items()):
2165 ui.write('path %s\n' % k)
2161 ui.write('path %s\n' % k)
2166 ui.write(' source %s\n' % v[0])
2162 ui.write(' source %s\n' % v[0])
2167 ui.write(' revision %s\n' % v[1])
2163 ui.write(' revision %s\n' % v[1])
2168
2164
2169 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2165 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2170 def debugwalk(ui, repo, *pats, **opts):
2166 def debugwalk(ui, repo, *pats, **opts):
2171 """show how files match on given patterns"""
2167 """show how files match on given patterns"""
2172 m = scmutil.match(repo[None], pats, opts)
2168 m = scmutil.match(repo[None], pats, opts)
2173 items = list(repo.walk(m))
2169 items = list(repo.walk(m))
2174 if not items:
2170 if not items:
2175 return
2171 return
2176 fmt = 'f %%-%ds %%-%ds %%s' % (
2172 fmt = 'f %%-%ds %%-%ds %%s' % (
2177 max([len(abs) for abs in items]),
2173 max([len(abs) for abs in items]),
2178 max([len(m.rel(abs)) for abs in items]))
2174 max([len(m.rel(abs)) for abs in items]))
2179 for abs in items:
2175 for abs in items:
2180 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2176 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2181 ui.write("%s\n" % line.rstrip())
2177 ui.write("%s\n" % line.rstrip())
2182
2178
2183 @command('debugwireargs',
2179 @command('debugwireargs',
2184 [('', 'three', '', 'three'),
2180 [('', 'three', '', 'three'),
2185 ('', 'four', '', 'four'),
2181 ('', 'four', '', 'four'),
2186 ('', 'five', '', 'five'),
2182 ('', 'five', '', 'five'),
2187 ] + remoteopts,
2183 ] + remoteopts,
2188 _('REPO [OPTIONS]... [ONE [TWO]]'))
2184 _('REPO [OPTIONS]... [ONE [TWO]]'))
2189 def debugwireargs(ui, repopath, *vals, **opts):
2185 def debugwireargs(ui, repopath, *vals, **opts):
2190 repo = hg.peer(ui, opts, repopath)
2186 repo = hg.peer(ui, opts, repopath)
2191 for opt in remoteopts:
2187 for opt in remoteopts:
2192 del opts[opt[1]]
2188 del opts[opt[1]]
2193 args = {}
2189 args = {}
2194 for k, v in opts.iteritems():
2190 for k, v in opts.iteritems():
2195 if v:
2191 if v:
2196 args[k] = v
2192 args[k] = v
2197 # run twice to check that we don't mess up the stream for the next command
2193 # run twice to check that we don't mess up the stream for the next command
2198 res1 = repo.debugwireargs(*vals, **args)
2194 res1 = repo.debugwireargs(*vals, **args)
2199 res2 = repo.debugwireargs(*vals, **args)
2195 res2 = repo.debugwireargs(*vals, **args)
2200 ui.write("%s\n" % res1)
2196 ui.write("%s\n" % res1)
2201 if res1 != res2:
2197 if res1 != res2:
2202 ui.warn("%s\n" % res2)
2198 ui.warn("%s\n" % res2)
2203
2199
2204 @command('^diff',
2200 @command('^diff',
2205 [('r', 'rev', [], _('revision'), _('REV')),
2201 [('r', 'rev', [], _('revision'), _('REV')),
2206 ('c', 'change', '', _('change made by revision'), _('REV'))
2202 ('c', 'change', '', _('change made by revision'), _('REV'))
2207 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2203 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2208 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2204 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2209 def diff(ui, repo, *pats, **opts):
2205 def diff(ui, repo, *pats, **opts):
2210 """diff repository (or selected files)
2206 """diff repository (or selected files)
2211
2207
2212 Show differences between revisions for the specified files.
2208 Show differences between revisions for the specified files.
2213
2209
2214 Differences between files are shown using the unified diff format.
2210 Differences between files are shown using the unified diff format.
2215
2211
2216 .. note::
2212 .. note::
2217 diff may generate unexpected results for merges, as it will
2213 diff may generate unexpected results for merges, as it will
2218 default to comparing against the working directory's first
2214 default to comparing against the working directory's first
2219 parent changeset if no revisions are specified.
2215 parent changeset if no revisions are specified.
2220
2216
2221 When two revision arguments are given, then changes are shown
2217 When two revision arguments are given, then changes are shown
2222 between those revisions. If only one revision is specified then
2218 between those revisions. If only one revision is specified then
2223 that revision is compared to the working directory, and, when no
2219 that revision is compared to the working directory, and, when no
2224 revisions are specified, the working directory files are compared
2220 revisions are specified, the working directory files are compared
2225 to its parent.
2221 to its parent.
2226
2222
2227 Alternatively you can specify -c/--change with a revision to see
2223 Alternatively you can specify -c/--change with a revision to see
2228 the changes in that changeset relative to its first parent.
2224 the changes in that changeset relative to its first parent.
2229
2225
2230 Without the -a/--text option, diff will avoid generating diffs of
2226 Without the -a/--text option, diff will avoid generating diffs of
2231 files it detects as binary. With -a, diff will generate a diff
2227 files it detects as binary. With -a, diff will generate a diff
2232 anyway, probably with undesirable results.
2228 anyway, probably with undesirable results.
2233
2229
2234 Use the -g/--git option to generate diffs in the git extended diff
2230 Use the -g/--git option to generate diffs in the git extended diff
2235 format. For more information, read :hg:`help diffs`.
2231 format. For more information, read :hg:`help diffs`.
2236
2232
2237 .. container:: verbose
2233 .. container:: verbose
2238
2234
2239 Examples:
2235 Examples:
2240
2236
2241 - compare a file in the current working directory to its parent::
2237 - compare a file in the current working directory to its parent::
2242
2238
2243 hg diff foo.c
2239 hg diff foo.c
2244
2240
2245 - compare two historical versions of a directory, with rename info::
2241 - compare two historical versions of a directory, with rename info::
2246
2242
2247 hg diff --git -r 1.0:1.2 lib/
2243 hg diff --git -r 1.0:1.2 lib/
2248
2244
2249 - get change stats relative to the last change on some date::
2245 - get change stats relative to the last change on some date::
2250
2246
2251 hg diff --stat -r "date('may 2')"
2247 hg diff --stat -r "date('may 2')"
2252
2248
2253 - diff all newly-added files that contain a keyword::
2249 - diff all newly-added files that contain a keyword::
2254
2250
2255 hg diff "set:added() and grep(GNU)"
2251 hg diff "set:added() and grep(GNU)"
2256
2252
2257 - compare a revision and its parents::
2253 - compare a revision and its parents::
2258
2254
2259 hg diff -c 9353 # compare against first parent
2255 hg diff -c 9353 # compare against first parent
2260 hg diff -r 9353^:9353 # same using revset syntax
2256 hg diff -r 9353^:9353 # same using revset syntax
2261 hg diff -r 9353^2:9353 # compare against the second parent
2257 hg diff -r 9353^2:9353 # compare against the second parent
2262
2258
2263 Returns 0 on success.
2259 Returns 0 on success.
2264 """
2260 """
2265
2261
2266 revs = opts.get('rev')
2262 revs = opts.get('rev')
2267 change = opts.get('change')
2263 change = opts.get('change')
2268 stat = opts.get('stat')
2264 stat = opts.get('stat')
2269 reverse = opts.get('reverse')
2265 reverse = opts.get('reverse')
2270
2266
2271 if revs and change:
2267 if revs and change:
2272 msg = _('cannot specify --rev and --change at the same time')
2268 msg = _('cannot specify --rev and --change at the same time')
2273 raise util.Abort(msg)
2269 raise util.Abort(msg)
2274 elif change:
2270 elif change:
2275 node2 = scmutil.revsingle(repo, change, None).node()
2271 node2 = scmutil.revsingle(repo, change, None).node()
2276 node1 = repo[node2].p1().node()
2272 node1 = repo[node2].p1().node()
2277 else:
2273 else:
2278 node1, node2 = scmutil.revpair(repo, revs)
2274 node1, node2 = scmutil.revpair(repo, revs)
2279
2275
2280 if reverse:
2276 if reverse:
2281 node1, node2 = node2, node1
2277 node1, node2 = node2, node1
2282
2278
2283 diffopts = patch.diffopts(ui, opts)
2279 diffopts = patch.diffopts(ui, opts)
2284 m = scmutil.match(repo[node2], pats, opts)
2280 m = scmutil.match(repo[node2], pats, opts)
2285 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2281 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2286 listsubrepos=opts.get('subrepos'))
2282 listsubrepos=opts.get('subrepos'))
2287
2283
2288 @command('^export',
2284 @command('^export',
2289 [('o', 'output', '',
2285 [('o', 'output', '',
2290 _('print output to file with formatted name'), _('FORMAT')),
2286 _('print output to file with formatted name'), _('FORMAT')),
2291 ('', 'switch-parent', None, _('diff against the second parent')),
2287 ('', 'switch-parent', None, _('diff against the second parent')),
2292 ('r', 'rev', [], _('revisions to export'), _('REV')),
2288 ('r', 'rev', [], _('revisions to export'), _('REV')),
2293 ] + diffopts,
2289 ] + diffopts,
2294 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2290 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2295 def export(ui, repo, *changesets, **opts):
2291 def export(ui, repo, *changesets, **opts):
2296 """dump the header and diffs for one or more changesets
2292 """dump the header and diffs for one or more changesets
2297
2293
2298 Print the changeset header and diffs for one or more revisions.
2294 Print the changeset header and diffs for one or more revisions.
2299
2295
2300 The information shown in the changeset header is: author, date,
2296 The information shown in the changeset header is: author, date,
2301 branch name (if non-default), changeset hash, parent(s) and commit
2297 branch name (if non-default), changeset hash, parent(s) and commit
2302 comment.
2298 comment.
2303
2299
2304 .. note::
2300 .. note::
2305 export may generate unexpected diff output for merge
2301 export may generate unexpected diff output for merge
2306 changesets, as it will compare the merge changeset against its
2302 changesets, as it will compare the merge changeset against its
2307 first parent only.
2303 first parent only.
2308
2304
2309 Output may be to a file, in which case the name of the file is
2305 Output may be to a file, in which case the name of the file is
2310 given using a format string. The formatting rules are as follows:
2306 given using a format string. The formatting rules are as follows:
2311
2307
2312 :``%%``: literal "%" character
2308 :``%%``: literal "%" character
2313 :``%H``: changeset hash (40 hexadecimal digits)
2309 :``%H``: changeset hash (40 hexadecimal digits)
2314 :``%N``: number of patches being generated
2310 :``%N``: number of patches being generated
2315 :``%R``: changeset revision number
2311 :``%R``: changeset revision number
2316 :``%b``: basename of the exporting repository
2312 :``%b``: basename of the exporting repository
2317 :``%h``: short-form changeset hash (12 hexadecimal digits)
2313 :``%h``: short-form changeset hash (12 hexadecimal digits)
2318 :``%m``: first line of the commit message (only alphanumeric characters)
2314 :``%m``: first line of the commit message (only alphanumeric characters)
2319 :``%n``: zero-padded sequence number, starting at 1
2315 :``%n``: zero-padded sequence number, starting at 1
2320 :``%r``: zero-padded changeset revision number
2316 :``%r``: zero-padded changeset revision number
2321
2317
2322 Without the -a/--text option, export will avoid generating diffs
2318 Without the -a/--text option, export will avoid generating diffs
2323 of files it detects as binary. With -a, export will generate a
2319 of files it detects as binary. With -a, export will generate a
2324 diff anyway, probably with undesirable results.
2320 diff anyway, probably with undesirable results.
2325
2321
2326 Use the -g/--git option to generate diffs in the git extended diff
2322 Use the -g/--git option to generate diffs in the git extended diff
2327 format. See :hg:`help diffs` for more information.
2323 format. See :hg:`help diffs` for more information.
2328
2324
2329 With the --switch-parent option, the diff will be against the
2325 With the --switch-parent option, the diff will be against the
2330 second parent. It can be useful to review a merge.
2326 second parent. It can be useful to review a merge.
2331
2327
2332 .. container:: verbose
2328 .. container:: verbose
2333
2329
2334 Examples:
2330 Examples:
2335
2331
2336 - use export and import to transplant a bugfix to the current
2332 - use export and import to transplant a bugfix to the current
2337 branch::
2333 branch::
2338
2334
2339 hg export -r 9353 | hg import -
2335 hg export -r 9353 | hg import -
2340
2336
2341 - export all the changesets between two revisions to a file with
2337 - export all the changesets between two revisions to a file with
2342 rename information::
2338 rename information::
2343
2339
2344 hg export --git -r 123:150 > changes.txt
2340 hg export --git -r 123:150 > changes.txt
2345
2341
2346 - split outgoing changes into a series of patches with
2342 - split outgoing changes into a series of patches with
2347 descriptive names::
2343 descriptive names::
2348
2344
2349 hg export -r "outgoing()" -o "%n-%m.patch"
2345 hg export -r "outgoing()" -o "%n-%m.patch"
2350
2346
2351 Returns 0 on success.
2347 Returns 0 on success.
2352 """
2348 """
2353 changesets += tuple(opts.get('rev', []))
2349 changesets += tuple(opts.get('rev', []))
2354 if not changesets:
2350 if not changesets:
2355 raise util.Abort(_("export requires at least one changeset"))
2351 raise util.Abort(_("export requires at least one changeset"))
2356 revs = scmutil.revrange(repo, changesets)
2352 revs = scmutil.revrange(repo, changesets)
2357 if len(revs) > 1:
2353 if len(revs) > 1:
2358 ui.note(_('exporting patches:\n'))
2354 ui.note(_('exporting patches:\n'))
2359 else:
2355 else:
2360 ui.note(_('exporting patch:\n'))
2356 ui.note(_('exporting patch:\n'))
2361 cmdutil.export(repo, revs, template=opts.get('output'),
2357 cmdutil.export(repo, revs, template=opts.get('output'),
2362 switch_parent=opts.get('switch_parent'),
2358 switch_parent=opts.get('switch_parent'),
2363 opts=patch.diffopts(ui, opts))
2359 opts=patch.diffopts(ui, opts))
2364
2360
2365 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2361 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2366 def forget(ui, repo, *pats, **opts):
2362 def forget(ui, repo, *pats, **opts):
2367 """forget the specified files on the next commit
2363 """forget the specified files on the next commit
2368
2364
2369 Mark the specified files so they will no longer be tracked
2365 Mark the specified files so they will no longer be tracked
2370 after the next commit.
2366 after the next commit.
2371
2367
2372 This only removes files from the current branch, not from the
2368 This only removes files from the current branch, not from the
2373 entire project history, and it does not delete them from the
2369 entire project history, and it does not delete them from the
2374 working directory.
2370 working directory.
2375
2371
2376 To undo a forget before the next commit, see :hg:`add`.
2372 To undo a forget before the next commit, see :hg:`add`.
2377
2373
2378 .. container:: verbose
2374 .. container:: verbose
2379
2375
2380 Examples:
2376 Examples:
2381
2377
2382 - forget newly-added binary files::
2378 - forget newly-added binary files::
2383
2379
2384 hg forget "set:added() and binary()"
2380 hg forget "set:added() and binary()"
2385
2381
2386 - forget files that would be excluded by .hgignore::
2382 - forget files that would be excluded by .hgignore::
2387
2383
2388 hg forget "set:hgignore()"
2384 hg forget "set:hgignore()"
2389
2385
2390 Returns 0 on success.
2386 Returns 0 on success.
2391 """
2387 """
2392
2388
2393 if not pats:
2389 if not pats:
2394 raise util.Abort(_('no files specified'))
2390 raise util.Abort(_('no files specified'))
2395
2391
2396 m = scmutil.match(repo[None], pats, opts)
2392 m = scmutil.match(repo[None], pats, opts)
2397 s = repo.status(match=m, clean=True)
2393 s = repo.status(match=m, clean=True)
2398 forget = sorted(s[0] + s[1] + s[3] + s[6])
2394 forget = sorted(s[0] + s[1] + s[3] + s[6])
2399 errs = 0
2395 errs = 0
2400
2396
2401 for f in m.files():
2397 for f in m.files():
2402 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2398 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2403 if os.path.exists(m.rel(f)):
2399 if os.path.exists(m.rel(f)):
2404 ui.warn(_('not removing %s: file is already untracked\n')
2400 ui.warn(_('not removing %s: file is already untracked\n')
2405 % m.rel(f))
2401 % m.rel(f))
2406 errs = 1
2402 errs = 1
2407
2403
2408 for f in forget:
2404 for f in forget:
2409 if ui.verbose or not m.exact(f):
2405 if ui.verbose or not m.exact(f):
2410 ui.status(_('removing %s\n') % m.rel(f))
2406 ui.status(_('removing %s\n') % m.rel(f))
2411
2407
2412 repo[None].forget(forget)
2408 repo[None].forget(forget)
2413 return errs
2409 return errs
2414
2410
2415 @command('grep',
2411 @command('grep',
2416 [('0', 'print0', None, _('end fields with NUL')),
2412 [('0', 'print0', None, _('end fields with NUL')),
2417 ('', 'all', None, _('print all revisions that match')),
2413 ('', 'all', None, _('print all revisions that match')),
2418 ('a', 'text', None, _('treat all files as text')),
2414 ('a', 'text', None, _('treat all files as text')),
2419 ('f', 'follow', None,
2415 ('f', 'follow', None,
2420 _('follow changeset history,'
2416 _('follow changeset history,'
2421 ' or file history across copies and renames')),
2417 ' or file history across copies and renames')),
2422 ('i', 'ignore-case', None, _('ignore case when matching')),
2418 ('i', 'ignore-case', None, _('ignore case when matching')),
2423 ('l', 'files-with-matches', None,
2419 ('l', 'files-with-matches', None,
2424 _('print only filenames and revisions that match')),
2420 _('print only filenames and revisions that match')),
2425 ('n', 'line-number', None, _('print matching line numbers')),
2421 ('n', 'line-number', None, _('print matching line numbers')),
2426 ('r', 'rev', [],
2422 ('r', 'rev', [],
2427 _('only search files changed within revision range'), _('REV')),
2423 _('only search files changed within revision range'), _('REV')),
2428 ('u', 'user', None, _('list the author (long with -v)')),
2424 ('u', 'user', None, _('list the author (long with -v)')),
2429 ('d', 'date', None, _('list the date (short with -q)')),
2425 ('d', 'date', None, _('list the date (short with -q)')),
2430 ] + walkopts,
2426 ] + walkopts,
2431 _('[OPTION]... PATTERN [FILE]...'))
2427 _('[OPTION]... PATTERN [FILE]...'))
2432 def grep(ui, repo, pattern, *pats, **opts):
2428 def grep(ui, repo, pattern, *pats, **opts):
2433 """search for a pattern in specified files and revisions
2429 """search for a pattern in specified files and revisions
2434
2430
2435 Search revisions of files for a regular expression.
2431 Search revisions of files for a regular expression.
2436
2432
2437 This command behaves differently than Unix grep. It only accepts
2433 This command behaves differently than Unix grep. It only accepts
2438 Python/Perl regexps. It searches repository history, not the
2434 Python/Perl regexps. It searches repository history, not the
2439 working directory. It always prints the revision number in which a
2435 working directory. It always prints the revision number in which a
2440 match appears.
2436 match appears.
2441
2437
2442 By default, grep only prints output for the first revision of a
2438 By default, grep only prints output for the first revision of a
2443 file in which it finds a match. To get it to print every revision
2439 file in which it finds a match. To get it to print every revision
2444 that contains a change in match status ("-" for a match that
2440 that contains a change in match status ("-" for a match that
2445 becomes a non-match, or "+" for a non-match that becomes a match),
2441 becomes a non-match, or "+" for a non-match that becomes a match),
2446 use the --all flag.
2442 use the --all flag.
2447
2443
2448 Returns 0 if a match is found, 1 otherwise.
2444 Returns 0 if a match is found, 1 otherwise.
2449 """
2445 """
2450 reflags = 0
2446 reflags = 0
2451 if opts.get('ignore_case'):
2447 if opts.get('ignore_case'):
2452 reflags |= re.I
2448 reflags |= re.I
2453 try:
2449 try:
2454 regexp = re.compile(pattern, reflags)
2450 regexp = re.compile(pattern, reflags)
2455 except re.error, inst:
2451 except re.error, inst:
2456 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2452 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2457 return 1
2453 return 1
2458 sep, eol = ':', '\n'
2454 sep, eol = ':', '\n'
2459 if opts.get('print0'):
2455 if opts.get('print0'):
2460 sep = eol = '\0'
2456 sep = eol = '\0'
2461
2457
2462 getfile = util.lrucachefunc(repo.file)
2458 getfile = util.lrucachefunc(repo.file)
2463
2459
2464 def matchlines(body):
2460 def matchlines(body):
2465 begin = 0
2461 begin = 0
2466 linenum = 0
2462 linenum = 0
2467 while True:
2463 while True:
2468 match = regexp.search(body, begin)
2464 match = regexp.search(body, begin)
2469 if not match:
2465 if not match:
2470 break
2466 break
2471 mstart, mend = match.span()
2467 mstart, mend = match.span()
2472 linenum += body.count('\n', begin, mstart) + 1
2468 linenum += body.count('\n', begin, mstart) + 1
2473 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2469 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2474 begin = body.find('\n', mend) + 1 or len(body)
2470 begin = body.find('\n', mend) + 1 or len(body)
2475 lend = begin - 1
2471 lend = begin - 1
2476 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2472 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2477
2473
2478 class linestate(object):
2474 class linestate(object):
2479 def __init__(self, line, linenum, colstart, colend):
2475 def __init__(self, line, linenum, colstart, colend):
2480 self.line = line
2476 self.line = line
2481 self.linenum = linenum
2477 self.linenum = linenum
2482 self.colstart = colstart
2478 self.colstart = colstart
2483 self.colend = colend
2479 self.colend = colend
2484
2480
2485 def __hash__(self):
2481 def __hash__(self):
2486 return hash((self.linenum, self.line))
2482 return hash((self.linenum, self.line))
2487
2483
2488 def __eq__(self, other):
2484 def __eq__(self, other):
2489 return self.line == other.line
2485 return self.line == other.line
2490
2486
2491 matches = {}
2487 matches = {}
2492 copies = {}
2488 copies = {}
2493 def grepbody(fn, rev, body):
2489 def grepbody(fn, rev, body):
2494 matches[rev].setdefault(fn, [])
2490 matches[rev].setdefault(fn, [])
2495 m = matches[rev][fn]
2491 m = matches[rev][fn]
2496 for lnum, cstart, cend, line in matchlines(body):
2492 for lnum, cstart, cend, line in matchlines(body):
2497 s = linestate(line, lnum, cstart, cend)
2493 s = linestate(line, lnum, cstart, cend)
2498 m.append(s)
2494 m.append(s)
2499
2495
2500 def difflinestates(a, b):
2496 def difflinestates(a, b):
2501 sm = difflib.SequenceMatcher(None, a, b)
2497 sm = difflib.SequenceMatcher(None, a, b)
2502 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2498 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2503 if tag == 'insert':
2499 if tag == 'insert':
2504 for i in xrange(blo, bhi):
2500 for i in xrange(blo, bhi):
2505 yield ('+', b[i])
2501 yield ('+', b[i])
2506 elif tag == 'delete':
2502 elif tag == 'delete':
2507 for i in xrange(alo, ahi):
2503 for i in xrange(alo, ahi):
2508 yield ('-', a[i])
2504 yield ('-', a[i])
2509 elif tag == 'replace':
2505 elif tag == 'replace':
2510 for i in xrange(alo, ahi):
2506 for i in xrange(alo, ahi):
2511 yield ('-', a[i])
2507 yield ('-', a[i])
2512 for i in xrange(blo, bhi):
2508 for i in xrange(blo, bhi):
2513 yield ('+', b[i])
2509 yield ('+', b[i])
2514
2510
2515 def display(fn, ctx, pstates, states):
2511 def display(fn, ctx, pstates, states):
2516 rev = ctx.rev()
2512 rev = ctx.rev()
2517 datefunc = ui.quiet and util.shortdate or util.datestr
2513 datefunc = ui.quiet and util.shortdate or util.datestr
2518 found = False
2514 found = False
2519 filerevmatches = {}
2515 filerevmatches = {}
2520 def binary():
2516 def binary():
2521 flog = getfile(fn)
2517 flog = getfile(fn)
2522 return util.binary(flog.read(ctx.filenode(fn)))
2518 return util.binary(flog.read(ctx.filenode(fn)))
2523
2519
2524 if opts.get('all'):
2520 if opts.get('all'):
2525 iter = difflinestates(pstates, states)
2521 iter = difflinestates(pstates, states)
2526 else:
2522 else:
2527 iter = [('', l) for l in states]
2523 iter = [('', l) for l in states]
2528 for change, l in iter:
2524 for change, l in iter:
2529 cols = [fn, str(rev)]
2525 cols = [fn, str(rev)]
2530 before, match, after = None, None, None
2526 before, match, after = None, None, None
2531 if opts.get('line_number'):
2527 if opts.get('line_number'):
2532 cols.append(str(l.linenum))
2528 cols.append(str(l.linenum))
2533 if opts.get('all'):
2529 if opts.get('all'):
2534 cols.append(change)
2530 cols.append(change)
2535 if opts.get('user'):
2531 if opts.get('user'):
2536 cols.append(ui.shortuser(ctx.user()))
2532 cols.append(ui.shortuser(ctx.user()))
2537 if opts.get('date'):
2533 if opts.get('date'):
2538 cols.append(datefunc(ctx.date()))
2534 cols.append(datefunc(ctx.date()))
2539 if opts.get('files_with_matches'):
2535 if opts.get('files_with_matches'):
2540 c = (fn, rev)
2536 c = (fn, rev)
2541 if c in filerevmatches:
2537 if c in filerevmatches:
2542 continue
2538 continue
2543 filerevmatches[c] = 1
2539 filerevmatches[c] = 1
2544 else:
2540 else:
2545 before = l.line[:l.colstart]
2541 before = l.line[:l.colstart]
2546 match = l.line[l.colstart:l.colend]
2542 match = l.line[l.colstart:l.colend]
2547 after = l.line[l.colend:]
2543 after = l.line[l.colend:]
2548 ui.write(sep.join(cols))
2544 ui.write(sep.join(cols))
2549 if before is not None:
2545 if before is not None:
2550 if not opts.get('text') and binary():
2546 if not opts.get('text') and binary():
2551 ui.write(sep + " Binary file matches")
2547 ui.write(sep + " Binary file matches")
2552 else:
2548 else:
2553 ui.write(sep + before)
2549 ui.write(sep + before)
2554 ui.write(match, label='grep.match')
2550 ui.write(match, label='grep.match')
2555 ui.write(after)
2551 ui.write(after)
2556 ui.write(eol)
2552 ui.write(eol)
2557 found = True
2553 found = True
2558 return found
2554 return found
2559
2555
2560 skip = {}
2556 skip = {}
2561 revfiles = {}
2557 revfiles = {}
2562 matchfn = scmutil.match(repo[None], pats, opts)
2558 matchfn = scmutil.match(repo[None], pats, opts)
2563 found = False
2559 found = False
2564 follow = opts.get('follow')
2560 follow = opts.get('follow')
2565
2561
2566 def prep(ctx, fns):
2562 def prep(ctx, fns):
2567 rev = ctx.rev()
2563 rev = ctx.rev()
2568 pctx = ctx.p1()
2564 pctx = ctx.p1()
2569 parent = pctx.rev()
2565 parent = pctx.rev()
2570 matches.setdefault(rev, {})
2566 matches.setdefault(rev, {})
2571 matches.setdefault(parent, {})
2567 matches.setdefault(parent, {})
2572 files = revfiles.setdefault(rev, [])
2568 files = revfiles.setdefault(rev, [])
2573 for fn in fns:
2569 for fn in fns:
2574 flog = getfile(fn)
2570 flog = getfile(fn)
2575 try:
2571 try:
2576 fnode = ctx.filenode(fn)
2572 fnode = ctx.filenode(fn)
2577 except error.LookupError:
2573 except error.LookupError:
2578 continue
2574 continue
2579
2575
2580 copied = flog.renamed(fnode)
2576 copied = flog.renamed(fnode)
2581 copy = follow and copied and copied[0]
2577 copy = follow and copied and copied[0]
2582 if copy:
2578 if copy:
2583 copies.setdefault(rev, {})[fn] = copy
2579 copies.setdefault(rev, {})[fn] = copy
2584 if fn in skip:
2580 if fn in skip:
2585 if copy:
2581 if copy:
2586 skip[copy] = True
2582 skip[copy] = True
2587 continue
2583 continue
2588 files.append(fn)
2584 files.append(fn)
2589
2585
2590 if fn not in matches[rev]:
2586 if fn not in matches[rev]:
2591 grepbody(fn, rev, flog.read(fnode))
2587 grepbody(fn, rev, flog.read(fnode))
2592
2588
2593 pfn = copy or fn
2589 pfn = copy or fn
2594 if pfn not in matches[parent]:
2590 if pfn not in matches[parent]:
2595 try:
2591 try:
2596 fnode = pctx.filenode(pfn)
2592 fnode = pctx.filenode(pfn)
2597 grepbody(pfn, parent, flog.read(fnode))
2593 grepbody(pfn, parent, flog.read(fnode))
2598 except error.LookupError:
2594 except error.LookupError:
2599 pass
2595 pass
2600
2596
2601 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2597 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2602 rev = ctx.rev()
2598 rev = ctx.rev()
2603 parent = ctx.p1().rev()
2599 parent = ctx.p1().rev()
2604 for fn in sorted(revfiles.get(rev, [])):
2600 for fn in sorted(revfiles.get(rev, [])):
2605 states = matches[rev][fn]
2601 states = matches[rev][fn]
2606 copy = copies.get(rev, {}).get(fn)
2602 copy = copies.get(rev, {}).get(fn)
2607 if fn in skip:
2603 if fn in skip:
2608 if copy:
2604 if copy:
2609 skip[copy] = True
2605 skip[copy] = True
2610 continue
2606 continue
2611 pstates = matches.get(parent, {}).get(copy or fn, [])
2607 pstates = matches.get(parent, {}).get(copy or fn, [])
2612 if pstates or states:
2608 if pstates or states:
2613 r = display(fn, ctx, pstates, states)
2609 r = display(fn, ctx, pstates, states)
2614 found = found or r
2610 found = found or r
2615 if r and not opts.get('all'):
2611 if r and not opts.get('all'):
2616 skip[fn] = True
2612 skip[fn] = True
2617 if copy:
2613 if copy:
2618 skip[copy] = True
2614 skip[copy] = True
2619 del matches[rev]
2615 del matches[rev]
2620 del revfiles[rev]
2616 del revfiles[rev]
2621
2617
2622 return not found
2618 return not found
2623
2619
2624 @command('heads',
2620 @command('heads',
2625 [('r', 'rev', '',
2621 [('r', 'rev', '',
2626 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2622 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2627 ('t', 'topo', False, _('show topological heads only')),
2623 ('t', 'topo', False, _('show topological heads only')),
2628 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2624 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2629 ('c', 'closed', False, _('show normal and closed branch heads')),
2625 ('c', 'closed', False, _('show normal and closed branch heads')),
2630 ] + templateopts,
2626 ] + templateopts,
2631 _('[-ac] [-r STARTREV] [REV]...'))
2627 _('[-ac] [-r STARTREV] [REV]...'))
2632 def heads(ui, repo, *branchrevs, **opts):
2628 def heads(ui, repo, *branchrevs, **opts):
2633 """show current repository heads or show branch heads
2629 """show current repository heads or show branch heads
2634
2630
2635 With no arguments, show all repository branch heads.
2631 With no arguments, show all repository branch heads.
2636
2632
2637 Repository "heads" are changesets with no child changesets. They are
2633 Repository "heads" are changesets with no child changesets. They are
2638 where development generally takes place and are the usual targets
2634 where development generally takes place and are the usual targets
2639 for update and merge operations. Branch heads are changesets that have
2635 for update and merge operations. Branch heads are changesets that have
2640 no child changeset on the same branch.
2636 no child changeset on the same branch.
2641
2637
2642 If one or more REVs are given, only branch heads on the branches
2638 If one or more REVs are given, only branch heads on the branches
2643 associated with the specified changesets are shown. This means
2639 associated with the specified changesets are shown. This means
2644 that you can use :hg:`heads foo` to see the heads on a branch
2640 that you can use :hg:`heads foo` to see the heads on a branch
2645 named ``foo``.
2641 named ``foo``.
2646
2642
2647 If -c/--closed is specified, also show branch heads marked closed
2643 If -c/--closed is specified, also show branch heads marked closed
2648 (see :hg:`commit --close-branch`).
2644 (see :hg:`commit --close-branch`).
2649
2645
2650 If STARTREV is specified, only those heads that are descendants of
2646 If STARTREV is specified, only those heads that are descendants of
2651 STARTREV will be displayed.
2647 STARTREV will be displayed.
2652
2648
2653 If -t/--topo is specified, named branch mechanics will be ignored and only
2649 If -t/--topo is specified, named branch mechanics will be ignored and only
2654 changesets without children will be shown.
2650 changesets without children will be shown.
2655
2651
2656 Returns 0 if matching heads are found, 1 if not.
2652 Returns 0 if matching heads are found, 1 if not.
2657 """
2653 """
2658
2654
2659 start = None
2655 start = None
2660 if 'rev' in opts:
2656 if 'rev' in opts:
2661 start = scmutil.revsingle(repo, opts['rev'], None).node()
2657 start = scmutil.revsingle(repo, opts['rev'], None).node()
2662
2658
2663 if opts.get('topo'):
2659 if opts.get('topo'):
2664 heads = [repo[h] for h in repo.heads(start)]
2660 heads = [repo[h] for h in repo.heads(start)]
2665 else:
2661 else:
2666 heads = []
2662 heads = []
2667 for branch in repo.branchmap():
2663 for branch in repo.branchmap():
2668 heads += repo.branchheads(branch, start, opts.get('closed'))
2664 heads += repo.branchheads(branch, start, opts.get('closed'))
2669 heads = [repo[h] for h in heads]
2665 heads = [repo[h] for h in heads]
2670
2666
2671 if branchrevs:
2667 if branchrevs:
2672 branches = set(repo[br].branch() for br in branchrevs)
2668 branches = set(repo[br].branch() for br in branchrevs)
2673 heads = [h for h in heads if h.branch() in branches]
2669 heads = [h for h in heads if h.branch() in branches]
2674
2670
2675 if opts.get('active') and branchrevs:
2671 if opts.get('active') and branchrevs:
2676 dagheads = repo.heads(start)
2672 dagheads = repo.heads(start)
2677 heads = [h for h in heads if h.node() in dagheads]
2673 heads = [h for h in heads if h.node() in dagheads]
2678
2674
2679 if branchrevs:
2675 if branchrevs:
2680 haveheads = set(h.branch() for h in heads)
2676 haveheads = set(h.branch() for h in heads)
2681 if branches - haveheads:
2677 if branches - haveheads:
2682 headless = ', '.join(b for b in branches - haveheads)
2678 headless = ', '.join(b for b in branches - haveheads)
2683 msg = _('no open branch heads found on branches %s')
2679 msg = _('no open branch heads found on branches %s')
2684 if opts.get('rev'):
2680 if opts.get('rev'):
2685 msg += _(' (started at %s)' % opts['rev'])
2681 msg += _(' (started at %s)' % opts['rev'])
2686 ui.warn((msg + '\n') % headless)
2682 ui.warn((msg + '\n') % headless)
2687
2683
2688 if not heads:
2684 if not heads:
2689 return 1
2685 return 1
2690
2686
2691 heads = sorted(heads, key=lambda x: -x.rev())
2687 heads = sorted(heads, key=lambda x: -x.rev())
2692 displayer = cmdutil.show_changeset(ui, repo, opts)
2688 displayer = cmdutil.show_changeset(ui, repo, opts)
2693 for ctx in heads:
2689 for ctx in heads:
2694 displayer.show(ctx)
2690 displayer.show(ctx)
2695 displayer.close()
2691 displayer.close()
2696
2692
2697 @command('help',
2693 @command('help',
2698 [('e', 'extension', None, _('show only help for extensions')),
2694 [('e', 'extension', None, _('show only help for extensions')),
2699 ('c', 'command', None, _('show only help for commands'))],
2695 ('c', 'command', None, _('show only help for commands'))],
2700 _('[-ec] [TOPIC]'))
2696 _('[-ec] [TOPIC]'))
2701 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2697 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2702 """show help for a given topic or a help overview
2698 """show help for a given topic or a help overview
2703
2699
2704 With no arguments, print a list of commands with short help messages.
2700 With no arguments, print a list of commands with short help messages.
2705
2701
2706 Given a topic, extension, or command name, print help for that
2702 Given a topic, extension, or command name, print help for that
2707 topic.
2703 topic.
2708
2704
2709 Returns 0 if successful.
2705 Returns 0 if successful.
2710 """
2706 """
2711
2707
2712 textwidth = min(ui.termwidth(), 80) - 2
2708 textwidth = min(ui.termwidth(), 80) - 2
2713
2709
2714 def optrst(options):
2710 def optrst(options):
2715 data = []
2711 data = []
2716 multioccur = False
2712 multioccur = False
2717 for option in options:
2713 for option in options:
2718 if len(option) == 5:
2714 if len(option) == 5:
2719 shortopt, longopt, default, desc, optlabel = option
2715 shortopt, longopt, default, desc, optlabel = option
2720 else:
2716 else:
2721 shortopt, longopt, default, desc = option
2717 shortopt, longopt, default, desc = option
2722 optlabel = _("VALUE") # default label
2718 optlabel = _("VALUE") # default label
2723
2719
2724 if _("DEPRECATED") in desc and not ui.verbose:
2720 if _("DEPRECATED") in desc and not ui.verbose:
2725 continue
2721 continue
2726
2722
2727 so = ''
2723 so = ''
2728 if shortopt:
2724 if shortopt:
2729 so = '-' + shortopt
2725 so = '-' + shortopt
2730 lo = '--' + longopt
2726 lo = '--' + longopt
2731 if default:
2727 if default:
2732 desc += _(" (default: %s)") % default
2728 desc += _(" (default: %s)") % default
2733
2729
2734 if isinstance(default, list):
2730 if isinstance(default, list):
2735 lo += " %s [+]" % optlabel
2731 lo += " %s [+]" % optlabel
2736 multioccur = True
2732 multioccur = True
2737 elif (default is not None) and not isinstance(default, bool):
2733 elif (default is not None) and not isinstance(default, bool):
2738 lo += " %s" % optlabel
2734 lo += " %s" % optlabel
2739
2735
2740 data.append((so, lo, desc))
2736 data.append((so, lo, desc))
2741
2737
2742 rst = minirst.maketable(data, 1)
2738 rst = minirst.maketable(data, 1)
2743 if multioccur:
2739 if multioccur:
2744 rst += _("\n[+] marked option can be specified multiple times")
2740 rst += _("\n[+] marked option can be specified multiple times")
2745
2741
2746 return rst
2742 return rst
2747
2743
2748 # list all option lists
2744 # list all option lists
2749 def opttext(optlist, width):
2745 def opttext(optlist, width):
2750 rst = ''
2746 rst = ''
2751 if not optlist:
2747 if not optlist:
2752 return ''
2748 return ''
2753
2749
2754 for title, options in optlist:
2750 for title, options in optlist:
2755 rst += '\n%s\n\n' % title
2751 rst += '\n%s\n\n' % title
2756 rst += optrst(options)
2752 rst += optrst(options)
2757 rst += '\n'
2753 rst += '\n'
2758
2754
2759 return '\n' + minirst.format(rst, width)
2755 return '\n' + minirst.format(rst, width)
2760
2756
2761 def addglobalopts(optlist, aliases):
2757 def addglobalopts(optlist, aliases):
2762 if ui.quiet:
2758 if ui.quiet:
2763 return []
2759 return []
2764
2760
2765 if ui.verbose:
2761 if ui.verbose:
2766 optlist.append((_("global options:"), globalopts))
2762 optlist.append((_("global options:"), globalopts))
2767 if name == 'shortlist':
2763 if name == 'shortlist':
2768 optlist.append((_('use "hg help" for the full list '
2764 optlist.append((_('use "hg help" for the full list '
2769 'of commands'), ()))
2765 'of commands'), ()))
2770 else:
2766 else:
2771 if name == 'shortlist':
2767 if name == 'shortlist':
2772 msg = _('use "hg help" for the full list of commands '
2768 msg = _('use "hg help" for the full list of commands '
2773 'or "hg -v" for details')
2769 'or "hg -v" for details')
2774 elif name and not full:
2770 elif name and not full:
2775 msg = _('use "hg help %s" to show the full help text' % name)
2771 msg = _('use "hg help %s" to show the full help text' % name)
2776 elif aliases:
2772 elif aliases:
2777 msg = _('use "hg -v help%s" to show builtin aliases and '
2773 msg = _('use "hg -v help%s" to show builtin aliases and '
2778 'global options') % (name and " " + name or "")
2774 'global options') % (name and " " + name or "")
2779 else:
2775 else:
2780 msg = _('use "hg -v help %s" to show global options') % name
2776 msg = _('use "hg -v help %s" to show global options') % name
2781 optlist.append((msg, ()))
2777 optlist.append((msg, ()))
2782
2778
2783 def helpcmd(name):
2779 def helpcmd(name):
2784 optlist = []
2780 optlist = []
2785 try:
2781 try:
2786 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2782 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2787 except error.AmbiguousCommand, inst:
2783 except error.AmbiguousCommand, inst:
2788 # py3k fix: except vars can't be used outside the scope of the
2784 # py3k fix: except vars can't be used outside the scope of the
2789 # except block, nor can be used inside a lambda. python issue4617
2785 # except block, nor can be used inside a lambda. python issue4617
2790 prefix = inst.args[0]
2786 prefix = inst.args[0]
2791 select = lambda c: c.lstrip('^').startswith(prefix)
2787 select = lambda c: c.lstrip('^').startswith(prefix)
2792 helplist(select)
2788 helplist(select)
2793 return
2789 return
2794
2790
2795 # check if it's an invalid alias and display its error if it is
2791 # check if it's an invalid alias and display its error if it is
2796 if getattr(entry[0], 'badalias', False):
2792 if getattr(entry[0], 'badalias', False):
2797 if not unknowncmd:
2793 if not unknowncmd:
2798 entry[0](ui)
2794 entry[0](ui)
2799 return
2795 return
2800
2796
2801 # synopsis
2797 # synopsis
2802 if len(entry) > 2:
2798 if len(entry) > 2:
2803 if entry[2].startswith('hg'):
2799 if entry[2].startswith('hg'):
2804 ui.write("%s\n" % entry[2])
2800 ui.write("%s\n" % entry[2])
2805 else:
2801 else:
2806 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2802 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2807 else:
2803 else:
2808 ui.write('hg %s\n' % aliases[0])
2804 ui.write('hg %s\n' % aliases[0])
2809
2805
2810 # aliases
2806 # aliases
2811 if full and not ui.quiet and len(aliases) > 1:
2807 if full and not ui.quiet and len(aliases) > 1:
2812 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2808 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2813
2809
2814 # description
2810 # description
2815 doc = gettext(entry[0].__doc__)
2811 doc = gettext(entry[0].__doc__)
2816 if not doc:
2812 if not doc:
2817 doc = _("(no help text available)")
2813 doc = _("(no help text available)")
2818 if util.safehasattr(entry[0], 'definition'): # aliased command
2814 if util.safehasattr(entry[0], 'definition'): # aliased command
2819 if entry[0].definition.startswith('!'): # shell alias
2815 if entry[0].definition.startswith('!'): # shell alias
2820 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2816 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2821 else:
2817 else:
2822 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2818 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2823 if ui.quiet or not full:
2819 if ui.quiet or not full:
2824 doc = doc.splitlines()[0]
2820 doc = doc.splitlines()[0]
2825 keep = ui.verbose and ['verbose'] or []
2821 keep = ui.verbose and ['verbose'] or []
2826 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2822 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2827 ui.write("\n%s" % formatted)
2823 ui.write("\n%s" % formatted)
2828 if pruned:
2824 if pruned:
2829 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2825 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2830
2826
2831 if not ui.quiet:
2827 if not ui.quiet:
2832 # options
2828 # options
2833 if entry[1]:
2829 if entry[1]:
2834 optlist.append((_("options:\n"), entry[1]))
2830 optlist.append((_("options:\n"), entry[1]))
2835
2831
2836 # check if this command shadows a non-trivial (multi-line)
2832 # check if this command shadows a non-trivial (multi-line)
2837 # extension help text
2833 # extension help text
2838 try:
2834 try:
2839 mod = extensions.find(name)
2835 mod = extensions.find(name)
2840 doc = gettext(mod.__doc__) or ''
2836 doc = gettext(mod.__doc__) or ''
2841 if '\n' in doc.strip():
2837 if '\n' in doc.strip():
2842 msg = _('use "hg help -e %s" to show help for '
2838 msg = _('use "hg help -e %s" to show help for '
2843 'the %s extension') % (name, name)
2839 'the %s extension') % (name, name)
2844 ui.write('\n%s\n' % msg)
2840 ui.write('\n%s\n' % msg)
2845 except KeyError:
2841 except KeyError:
2846 pass
2842 pass
2847
2843
2848 addglobalopts(optlist, False)
2844 addglobalopts(optlist, False)
2849 ui.write(opttext(optlist, textwidth))
2845 ui.write(opttext(optlist, textwidth))
2850
2846
2851 def helplist(select=None):
2847 def helplist(select=None):
2852 # list of commands
2848 # list of commands
2853 if name == "shortlist":
2849 if name == "shortlist":
2854 header = _('basic commands:\n\n')
2850 header = _('basic commands:\n\n')
2855 else:
2851 else:
2856 header = _('list of commands:\n\n')
2852 header = _('list of commands:\n\n')
2857
2853
2858 h = {}
2854 h = {}
2859 cmds = {}
2855 cmds = {}
2860 for c, e in table.iteritems():
2856 for c, e in table.iteritems():
2861 f = c.split("|", 1)[0]
2857 f = c.split("|", 1)[0]
2862 if select and not select(f):
2858 if select and not select(f):
2863 continue
2859 continue
2864 if (not select and name != 'shortlist' and
2860 if (not select and name != 'shortlist' and
2865 e[0].__module__ != __name__):
2861 e[0].__module__ != __name__):
2866 continue
2862 continue
2867 if name == "shortlist" and not f.startswith("^"):
2863 if name == "shortlist" and not f.startswith("^"):
2868 continue
2864 continue
2869 f = f.lstrip("^")
2865 f = f.lstrip("^")
2870 if not ui.debugflag and f.startswith("debug"):
2866 if not ui.debugflag and f.startswith("debug"):
2871 continue
2867 continue
2872 doc = e[0].__doc__
2868 doc = e[0].__doc__
2873 if doc and 'DEPRECATED' in doc and not ui.verbose:
2869 if doc and 'DEPRECATED' in doc and not ui.verbose:
2874 continue
2870 continue
2875 doc = gettext(doc)
2871 doc = gettext(doc)
2876 if not doc:
2872 if not doc:
2877 doc = _("(no help text available)")
2873 doc = _("(no help text available)")
2878 h[f] = doc.splitlines()[0].rstrip()
2874 h[f] = doc.splitlines()[0].rstrip()
2879 cmds[f] = c.lstrip("^")
2875 cmds[f] = c.lstrip("^")
2880
2876
2881 if not h:
2877 if not h:
2882 ui.status(_('no commands defined\n'))
2878 ui.status(_('no commands defined\n'))
2883 return
2879 return
2884
2880
2885 ui.status(header)
2881 ui.status(header)
2886 fns = sorted(h)
2882 fns = sorted(h)
2887 m = max(map(len, fns))
2883 m = max(map(len, fns))
2888 for f in fns:
2884 for f in fns:
2889 if ui.verbose:
2885 if ui.verbose:
2890 commands = cmds[f].replace("|",", ")
2886 commands = cmds[f].replace("|",", ")
2891 ui.write(" %s:\n %s\n"%(commands, h[f]))
2887 ui.write(" %s:\n %s\n"%(commands, h[f]))
2892 else:
2888 else:
2893 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2889 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2894 initindent=' %-*s ' % (m, f),
2890 initindent=' %-*s ' % (m, f),
2895 hangindent=' ' * (m + 4))))
2891 hangindent=' ' * (m + 4))))
2896
2892
2897 if not name:
2893 if not name:
2898 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2894 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2899 if text:
2895 if text:
2900 ui.write("\n%s" % minirst.format(text, textwidth))
2896 ui.write("\n%s" % minirst.format(text, textwidth))
2901
2897
2902 ui.write(_("\nadditional help topics:\n\n"))
2898 ui.write(_("\nadditional help topics:\n\n"))
2903 topics = []
2899 topics = []
2904 for names, header, doc in help.helptable:
2900 for names, header, doc in help.helptable:
2905 topics.append((sorted(names, key=len, reverse=True)[0], header))
2901 topics.append((sorted(names, key=len, reverse=True)[0], header))
2906 topics_len = max([len(s[0]) for s in topics])
2902 topics_len = max([len(s[0]) for s in topics])
2907 for t, desc in topics:
2903 for t, desc in topics:
2908 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2904 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2909
2905
2910 optlist = []
2906 optlist = []
2911 addglobalopts(optlist, True)
2907 addglobalopts(optlist, True)
2912 ui.write(opttext(optlist, textwidth))
2908 ui.write(opttext(optlist, textwidth))
2913
2909
2914 def helptopic(name):
2910 def helptopic(name):
2915 for names, header, doc in help.helptable:
2911 for names, header, doc in help.helptable:
2916 if name in names:
2912 if name in names:
2917 break
2913 break
2918 else:
2914 else:
2919 raise error.UnknownCommand(name)
2915 raise error.UnknownCommand(name)
2920
2916
2921 # description
2917 # description
2922 if not doc:
2918 if not doc:
2923 doc = _("(no help text available)")
2919 doc = _("(no help text available)")
2924 if util.safehasattr(doc, '__call__'):
2920 if util.safehasattr(doc, '__call__'):
2925 doc = doc()
2921 doc = doc()
2926
2922
2927 ui.write("%s\n\n" % header)
2923 ui.write("%s\n\n" % header)
2928 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2924 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2929 try:
2925 try:
2930 cmdutil.findcmd(name, table)
2926 cmdutil.findcmd(name, table)
2931 ui.write(_('\nuse "hg help -c %s" to see help for '
2927 ui.write(_('\nuse "hg help -c %s" to see help for '
2932 'the %s command\n') % (name, name))
2928 'the %s command\n') % (name, name))
2933 except error.UnknownCommand:
2929 except error.UnknownCommand:
2934 pass
2930 pass
2935
2931
2936 def helpext(name):
2932 def helpext(name):
2937 try:
2933 try:
2938 mod = extensions.find(name)
2934 mod = extensions.find(name)
2939 doc = gettext(mod.__doc__) or _('no help text available')
2935 doc = gettext(mod.__doc__) or _('no help text available')
2940 except KeyError:
2936 except KeyError:
2941 mod = None
2937 mod = None
2942 doc = extensions.disabledext(name)
2938 doc = extensions.disabledext(name)
2943 if not doc:
2939 if not doc:
2944 raise error.UnknownCommand(name)
2940 raise error.UnknownCommand(name)
2945
2941
2946 if '\n' not in doc:
2942 if '\n' not in doc:
2947 head, tail = doc, ""
2943 head, tail = doc, ""
2948 else:
2944 else:
2949 head, tail = doc.split('\n', 1)
2945 head, tail = doc.split('\n', 1)
2950 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2946 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2951 if tail:
2947 if tail:
2952 ui.write(minirst.format(tail, textwidth))
2948 ui.write(minirst.format(tail, textwidth))
2953 ui.status('\n')
2949 ui.status('\n')
2954
2950
2955 if mod:
2951 if mod:
2956 try:
2952 try:
2957 ct = mod.cmdtable
2953 ct = mod.cmdtable
2958 except AttributeError:
2954 except AttributeError:
2959 ct = {}
2955 ct = {}
2960 modcmds = set([c.split('|', 1)[0] for c in ct])
2956 modcmds = set([c.split('|', 1)[0] for c in ct])
2961 helplist(modcmds.__contains__)
2957 helplist(modcmds.__contains__)
2962 else:
2958 else:
2963 ui.write(_('use "hg help extensions" for information on enabling '
2959 ui.write(_('use "hg help extensions" for information on enabling '
2964 'extensions\n'))
2960 'extensions\n'))
2965
2961
2966 def helpextcmd(name):
2962 def helpextcmd(name):
2967 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2963 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2968 doc = gettext(mod.__doc__).splitlines()[0]
2964 doc = gettext(mod.__doc__).splitlines()[0]
2969
2965
2970 msg = help.listexts(_("'%s' is provided by the following "
2966 msg = help.listexts(_("'%s' is provided by the following "
2971 "extension:") % cmd, {ext: doc}, indent=4)
2967 "extension:") % cmd, {ext: doc}, indent=4)
2972 ui.write(minirst.format(msg, textwidth))
2968 ui.write(minirst.format(msg, textwidth))
2973 ui.write('\n')
2969 ui.write('\n')
2974 ui.write(_('use "hg help extensions" for information on enabling '
2970 ui.write(_('use "hg help extensions" for information on enabling '
2975 'extensions\n'))
2971 'extensions\n'))
2976
2972
2977 if name and name != 'shortlist':
2973 if name and name != 'shortlist':
2978 i = None
2974 i = None
2979 if unknowncmd:
2975 if unknowncmd:
2980 queries = (helpextcmd,)
2976 queries = (helpextcmd,)
2981 elif opts.get('extension'):
2977 elif opts.get('extension'):
2982 queries = (helpext,)
2978 queries = (helpext,)
2983 elif opts.get('command'):
2979 elif opts.get('command'):
2984 queries = (helpcmd,)
2980 queries = (helpcmd,)
2985 else:
2981 else:
2986 queries = (helptopic, helpcmd, helpext, helpextcmd)
2982 queries = (helptopic, helpcmd, helpext, helpextcmd)
2987 for f in queries:
2983 for f in queries:
2988 try:
2984 try:
2989 f(name)
2985 f(name)
2990 i = None
2986 i = None
2991 break
2987 break
2992 except error.UnknownCommand, inst:
2988 except error.UnknownCommand, inst:
2993 i = inst
2989 i = inst
2994 if i:
2990 if i:
2995 raise i
2991 raise i
2996 else:
2992 else:
2997 # program name
2993 # program name
2998 ui.status(_("Mercurial Distributed SCM\n"))
2994 ui.status(_("Mercurial Distributed SCM\n"))
2999 ui.status('\n')
2995 ui.status('\n')
3000 helplist()
2996 helplist()
3001
2997
3002
2998
3003 @command('identify|id',
2999 @command('identify|id',
3004 [('r', 'rev', '',
3000 [('r', 'rev', '',
3005 _('identify the specified revision'), _('REV')),
3001 _('identify the specified revision'), _('REV')),
3006 ('n', 'num', None, _('show local revision number')),
3002 ('n', 'num', None, _('show local revision number')),
3007 ('i', 'id', None, _('show global revision id')),
3003 ('i', 'id', None, _('show global revision id')),
3008 ('b', 'branch', None, _('show branch')),
3004 ('b', 'branch', None, _('show branch')),
3009 ('t', 'tags', None, _('show tags')),
3005 ('t', 'tags', None, _('show tags')),
3010 ('B', 'bookmarks', None, _('show bookmarks'))],
3006 ('B', 'bookmarks', None, _('show bookmarks'))],
3011 _('[-nibtB] [-r REV] [SOURCE]'))
3007 _('[-nibtB] [-r REV] [SOURCE]'))
3012 def identify(ui, repo, source=None, rev=None,
3008 def identify(ui, repo, source=None, rev=None,
3013 num=None, id=None, branch=None, tags=None, bookmarks=None):
3009 num=None, id=None, branch=None, tags=None, bookmarks=None):
3014 """identify the working copy or specified revision
3010 """identify the working copy or specified revision
3015
3011
3016 Print a summary identifying the repository state at REV using one or
3012 Print a summary identifying the repository state at REV using one or
3017 two parent hash identifiers, followed by a "+" if the working
3013 two parent hash identifiers, followed by a "+" if the working
3018 directory has uncommitted changes, the branch name (if not default),
3014 directory has uncommitted changes, the branch name (if not default),
3019 a list of tags, and a list of bookmarks.
3015 a list of tags, and a list of bookmarks.
3020
3016
3021 When REV is not given, print a summary of the current state of the
3017 When REV is not given, print a summary of the current state of the
3022 repository.
3018 repository.
3023
3019
3024 Specifying a path to a repository root or Mercurial bundle will
3020 Specifying a path to a repository root or Mercurial bundle will
3025 cause lookup to operate on that repository/bundle.
3021 cause lookup to operate on that repository/bundle.
3026
3022
3027 .. container:: verbose
3023 .. container:: verbose
3028
3024
3029 Examples:
3025 Examples:
3030
3026
3031 - generate a build identifier for the working directory::
3027 - generate a build identifier for the working directory::
3032
3028
3033 hg id --id > build-id.dat
3029 hg id --id > build-id.dat
3034
3030
3035 - find the revision corresponding to a tag::
3031 - find the revision corresponding to a tag::
3036
3032
3037 hg id -n -r 1.3
3033 hg id -n -r 1.3
3038
3034
3039 - check the most recent revision of a remote repository::
3035 - check the most recent revision of a remote repository::
3040
3036
3041 hg id -r tip http://selenic.com/hg/
3037 hg id -r tip http://selenic.com/hg/
3042
3038
3043 Returns 0 if successful.
3039 Returns 0 if successful.
3044 """
3040 """
3045
3041
3046 if not repo and not source:
3042 if not repo and not source:
3047 raise util.Abort(_("there is no Mercurial repository here "
3043 raise util.Abort(_("there is no Mercurial repository here "
3048 "(.hg not found)"))
3044 "(.hg not found)"))
3049
3045
3050 hexfunc = ui.debugflag and hex or short
3046 hexfunc = ui.debugflag and hex or short
3051 default = not (num or id or branch or tags or bookmarks)
3047 default = not (num or id or branch or tags or bookmarks)
3052 output = []
3048 output = []
3053 revs = []
3049 revs = []
3054
3050
3055 if source:
3051 if source:
3056 source, branches = hg.parseurl(ui.expandpath(source))
3052 source, branches = hg.parseurl(ui.expandpath(source))
3057 repo = hg.peer(ui, {}, source)
3053 repo = hg.peer(ui, {}, source)
3058 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3054 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3059
3055
3060 if not repo.local():
3056 if not repo.local():
3061 if num or branch or tags:
3057 if num or branch or tags:
3062 raise util.Abort(
3058 raise util.Abort(
3063 _("can't query remote revision number, branch, or tags"))
3059 _("can't query remote revision number, branch, or tags"))
3064 if not rev and revs:
3060 if not rev and revs:
3065 rev = revs[0]
3061 rev = revs[0]
3066 if not rev:
3062 if not rev:
3067 rev = "tip"
3063 rev = "tip"
3068
3064
3069 remoterev = repo.lookup(rev)
3065 remoterev = repo.lookup(rev)
3070 if default or id:
3066 if default or id:
3071 output = [hexfunc(remoterev)]
3067 output = [hexfunc(remoterev)]
3072
3068
3073 def getbms():
3069 def getbms():
3074 bms = []
3070 bms = []
3075
3071
3076 if 'bookmarks' in repo.listkeys('namespaces'):
3072 if 'bookmarks' in repo.listkeys('namespaces'):
3077 hexremoterev = hex(remoterev)
3073 hexremoterev = hex(remoterev)
3078 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3074 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3079 if bmr == hexremoterev]
3075 if bmr == hexremoterev]
3080
3076
3081 return bms
3077 return bms
3082
3078
3083 if bookmarks:
3079 if bookmarks:
3084 output.extend(getbms())
3080 output.extend(getbms())
3085 elif default and not ui.quiet:
3081 elif default and not ui.quiet:
3086 # multiple bookmarks for a single parent separated by '/'
3082 # multiple bookmarks for a single parent separated by '/'
3087 bm = '/'.join(getbms())
3083 bm = '/'.join(getbms())
3088 if bm:
3084 if bm:
3089 output.append(bm)
3085 output.append(bm)
3090 else:
3086 else:
3091 if not rev:
3087 if not rev:
3092 ctx = repo[None]
3088 ctx = repo[None]
3093 parents = ctx.parents()
3089 parents = ctx.parents()
3094 changed = ""
3090 changed = ""
3095 if default or id or num:
3091 if default or id or num:
3096 changed = util.any(repo.status()) and "+" or ""
3092 changed = util.any(repo.status()) and "+" or ""
3097 if default or id:
3093 if default or id:
3098 output = ["%s%s" %
3094 output = ["%s%s" %
3099 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3095 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3100 if num:
3096 if num:
3101 output.append("%s%s" %
3097 output.append("%s%s" %
3102 ('+'.join([str(p.rev()) for p in parents]), changed))
3098 ('+'.join([str(p.rev()) for p in parents]), changed))
3103 else:
3099 else:
3104 ctx = scmutil.revsingle(repo, rev)
3100 ctx = scmutil.revsingle(repo, rev)
3105 if default or id:
3101 if default or id:
3106 output = [hexfunc(ctx.node())]
3102 output = [hexfunc(ctx.node())]
3107 if num:
3103 if num:
3108 output.append(str(ctx.rev()))
3104 output.append(str(ctx.rev()))
3109
3105
3110 if default and not ui.quiet:
3106 if default and not ui.quiet:
3111 b = ctx.branch()
3107 b = ctx.branch()
3112 if b != 'default':
3108 if b != 'default':
3113 output.append("(%s)" % b)
3109 output.append("(%s)" % b)
3114
3110
3115 # multiple tags for a single parent separated by '/'
3111 # multiple tags for a single parent separated by '/'
3116 t = '/'.join(ctx.tags())
3112 t = '/'.join(ctx.tags())
3117 if t:
3113 if t:
3118 output.append(t)
3114 output.append(t)
3119
3115
3120 # multiple bookmarks for a single parent separated by '/'
3116 # multiple bookmarks for a single parent separated by '/'
3121 bm = '/'.join(ctx.bookmarks())
3117 bm = '/'.join(ctx.bookmarks())
3122 if bm:
3118 if bm:
3123 output.append(bm)
3119 output.append(bm)
3124 else:
3120 else:
3125 if branch:
3121 if branch:
3126 output.append(ctx.branch())
3122 output.append(ctx.branch())
3127
3123
3128 if tags:
3124 if tags:
3129 output.extend(ctx.tags())
3125 output.extend(ctx.tags())
3130
3126
3131 if bookmarks:
3127 if bookmarks:
3132 output.extend(ctx.bookmarks())
3128 output.extend(ctx.bookmarks())
3133
3129
3134 ui.write("%s\n" % ' '.join(output))
3130 ui.write("%s\n" % ' '.join(output))
3135
3131
3136 @command('import|patch',
3132 @command('import|patch',
3137 [('p', 'strip', 1,
3133 [('p', 'strip', 1,
3138 _('directory strip option for patch. This has the same '
3134 _('directory strip option for patch. This has the same '
3139 'meaning as the corresponding patch option'), _('NUM')),
3135 'meaning as the corresponding patch option'), _('NUM')),
3140 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3136 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3141 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3137 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3142 ('', 'no-commit', None,
3138 ('', 'no-commit', None,
3143 _("don't commit, just update the working directory")),
3139 _("don't commit, just update the working directory")),
3144 ('', 'bypass', None,
3140 ('', 'bypass', None,
3145 _("apply patch without touching the working directory")),
3141 _("apply patch without touching the working directory")),
3146 ('', 'exact', None,
3142 ('', 'exact', None,
3147 _('apply patch to the nodes from which it was generated')),
3143 _('apply patch to the nodes from which it was generated')),
3148 ('', 'import-branch', None,
3144 ('', 'import-branch', None,
3149 _('use any branch information in patch (implied by --exact)'))] +
3145 _('use any branch information in patch (implied by --exact)'))] +
3150 commitopts + commitopts2 + similarityopts,
3146 commitopts + commitopts2 + similarityopts,
3151 _('[OPTION]... PATCH...'))
3147 _('[OPTION]... PATCH...'))
3152 def import_(ui, repo, patch1, *patches, **opts):
3148 def import_(ui, repo, patch1, *patches, **opts):
3153 """import an ordered set of patches
3149 """import an ordered set of patches
3154
3150
3155 Import a list of patches and commit them individually (unless
3151 Import a list of patches and commit them individually (unless
3156 --no-commit is specified).
3152 --no-commit is specified).
3157
3153
3158 If there are outstanding changes in the working directory, import
3154 If there are outstanding changes in the working directory, import
3159 will abort unless given the -f/--force flag.
3155 will abort unless given the -f/--force flag.
3160
3156
3161 You can import a patch straight from a mail message. Even patches
3157 You can import a patch straight from a mail message. Even patches
3162 as attachments work (to use the body part, it must have type
3158 as attachments work (to use the body part, it must have type
3163 text/plain or text/x-patch). From and Subject headers of email
3159 text/plain or text/x-patch). From and Subject headers of email
3164 message are used as default committer and commit message. All
3160 message are used as default committer and commit message. All
3165 text/plain body parts before first diff are added to commit
3161 text/plain body parts before first diff are added to commit
3166 message.
3162 message.
3167
3163
3168 If the imported patch was generated by :hg:`export`, user and
3164 If the imported patch was generated by :hg:`export`, user and
3169 description from patch override values from message headers and
3165 description from patch override values from message headers and
3170 body. Values given on command line with -m/--message and -u/--user
3166 body. Values given on command line with -m/--message and -u/--user
3171 override these.
3167 override these.
3172
3168
3173 If --exact is specified, import will set the working directory to
3169 If --exact is specified, import will set the working directory to
3174 the parent of each patch before applying it, and will abort if the
3170 the parent of each patch before applying it, and will abort if the
3175 resulting changeset has a different ID than the one recorded in
3171 resulting changeset has a different ID than the one recorded in
3176 the patch. This may happen due to character set problems or other
3172 the patch. This may happen due to character set problems or other
3177 deficiencies in the text patch format.
3173 deficiencies in the text patch format.
3178
3174
3179 Use --bypass to apply and commit patches directly to the
3175 Use --bypass to apply and commit patches directly to the
3180 repository, not touching the working directory. Without --exact,
3176 repository, not touching the working directory. Without --exact,
3181 patches will be applied on top of the working directory parent
3177 patches will be applied on top of the working directory parent
3182 revision.
3178 revision.
3183
3179
3184 With -s/--similarity, hg will attempt to discover renames and
3180 With -s/--similarity, hg will attempt to discover renames and
3185 copies in the patch in the same way as 'addremove'.
3181 copies in the patch in the same way as 'addremove'.
3186
3182
3187 To read a patch from standard input, use "-" as the patch name. If
3183 To read a patch from standard input, use "-" as the patch name. If
3188 a URL is specified, the patch will be downloaded from it.
3184 a URL is specified, the patch will be downloaded from it.
3189 See :hg:`help dates` for a list of formats valid for -d/--date.
3185 See :hg:`help dates` for a list of formats valid for -d/--date.
3190
3186
3191 .. container:: verbose
3187 .. container:: verbose
3192
3188
3193 Examples:
3189 Examples:
3194
3190
3195 - import a traditional patch from a website and detect renames::
3191 - import a traditional patch from a website and detect renames::
3196
3192
3197 hg import -s 80 http://example.com/bugfix.patch
3193 hg import -s 80 http://example.com/bugfix.patch
3198
3194
3199 - import a changeset from an hgweb server::
3195 - import a changeset from an hgweb server::
3200
3196
3201 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3197 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3202
3198
3203 - import all the patches in an Unix-style mbox::
3199 - import all the patches in an Unix-style mbox::
3204
3200
3205 hg import incoming-patches.mbox
3201 hg import incoming-patches.mbox
3206
3202
3207 - attempt to exactly restore an exported changeset (not always
3203 - attempt to exactly restore an exported changeset (not always
3208 possible)::
3204 possible)::
3209
3205
3210 hg import --exact proposed-fix.patch
3206 hg import --exact proposed-fix.patch
3211
3207
3212 Returns 0 on success.
3208 Returns 0 on success.
3213 """
3209 """
3214 patches = (patch1,) + patches
3210 patches = (patch1,) + patches
3215
3211
3216 date = opts.get('date')
3212 date = opts.get('date')
3217 if date:
3213 if date:
3218 opts['date'] = util.parsedate(date)
3214 opts['date'] = util.parsedate(date)
3219
3215
3220 update = not opts.get('bypass')
3216 update = not opts.get('bypass')
3221 if not update and opts.get('no_commit'):
3217 if not update and opts.get('no_commit'):
3222 raise util.Abort(_('cannot use --no-commit with --bypass'))
3218 raise util.Abort(_('cannot use --no-commit with --bypass'))
3223 try:
3219 try:
3224 sim = float(opts.get('similarity') or 0)
3220 sim = float(opts.get('similarity') or 0)
3225 except ValueError:
3221 except ValueError:
3226 raise util.Abort(_('similarity must be a number'))
3222 raise util.Abort(_('similarity must be a number'))
3227 if sim < 0 or sim > 100:
3223 if sim < 0 or sim > 100:
3228 raise util.Abort(_('similarity must be between 0 and 100'))
3224 raise util.Abort(_('similarity must be between 0 and 100'))
3229 if sim and not update:
3225 if sim and not update:
3230 raise util.Abort(_('cannot use --similarity with --bypass'))
3226 raise util.Abort(_('cannot use --similarity with --bypass'))
3231
3227
3232 if (opts.get('exact') or not opts.get('force')) and update:
3228 if (opts.get('exact') or not opts.get('force')) and update:
3233 cmdutil.bailifchanged(repo)
3229 cmdutil.bailifchanged(repo)
3234
3230
3235 d = opts["base"]
3231 d = opts["base"]
3236 strip = opts["strip"]
3232 strip = opts["strip"]
3237 wlock = lock = None
3233 wlock = lock = None
3238 msgs = []
3234 msgs = []
3239
3235
3240 def checkexact(repo, n, nodeid):
3236 def checkexact(repo, n, nodeid):
3241 if opts.get('exact') and hex(n) != nodeid:
3237 if opts.get('exact') and hex(n) != nodeid:
3242 repo.rollback()
3238 repo.rollback()
3243 raise util.Abort(_('patch is damaged or loses information'))
3239 raise util.Abort(_('patch is damaged or loses information'))
3244
3240
3245 def tryone(ui, hunk, parents):
3241 def tryone(ui, hunk, parents):
3246 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3242 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3247 patch.extract(ui, hunk)
3243 patch.extract(ui, hunk)
3248
3244
3249 if not tmpname:
3245 if not tmpname:
3250 return None
3246 return None
3251 commitid = _('to working directory')
3247 commitid = _('to working directory')
3252
3248
3253 try:
3249 try:
3254 cmdline_message = cmdutil.logmessage(ui, opts)
3250 cmdline_message = cmdutil.logmessage(ui, opts)
3255 if cmdline_message:
3251 if cmdline_message:
3256 # pickup the cmdline msg
3252 # pickup the cmdline msg
3257 message = cmdline_message
3253 message = cmdline_message
3258 elif message:
3254 elif message:
3259 # pickup the patch msg
3255 # pickup the patch msg
3260 message = message.strip()
3256 message = message.strip()
3261 else:
3257 else:
3262 # launch the editor
3258 # launch the editor
3263 message = None
3259 message = None
3264 ui.debug('message:\n%s\n' % message)
3260 ui.debug('message:\n%s\n' % message)
3265
3261
3266 if len(parents) == 1:
3262 if len(parents) == 1:
3267 parents.append(repo[nullid])
3263 parents.append(repo[nullid])
3268 if opts.get('exact'):
3264 if opts.get('exact'):
3269 if not nodeid or not p1:
3265 if not nodeid or not p1:
3270 raise util.Abort(_('not a Mercurial patch'))
3266 raise util.Abort(_('not a Mercurial patch'))
3271 p1 = repo[p1]
3267 p1 = repo[p1]
3272 p2 = repo[p2 or nullid]
3268 p2 = repo[p2 or nullid]
3273 elif p2:
3269 elif p2:
3274 try:
3270 try:
3275 p1 = repo[p1]
3271 p1 = repo[p1]
3276 p2 = repo[p2]
3272 p2 = repo[p2]
3277 except error.RepoError:
3273 except error.RepoError:
3278 p1, p2 = parents
3274 p1, p2 = parents
3279 else:
3275 else:
3280 p1, p2 = parents
3276 p1, p2 = parents
3281
3277
3282 n = None
3278 n = None
3283 if update:
3279 if update:
3284 if opts.get('exact') and p1 != parents[0]:
3280 if opts.get('exact') and p1 != parents[0]:
3285 hg.clean(repo, p1.node())
3281 hg.clean(repo, p1.node())
3286 if p1 != parents[0] and p2 != parents[1]:
3282 if p1 != parents[0] and p2 != parents[1]:
3287 repo.dirstate.setparents(p1.node(), p2.node())
3283 repo.dirstate.setparents(p1.node(), p2.node())
3288
3284
3289 if opts.get('exact') or opts.get('import_branch'):
3285 if opts.get('exact') or opts.get('import_branch'):
3290 repo.dirstate.setbranch(branch or 'default')
3286 repo.dirstate.setbranch(branch or 'default')
3291
3287
3292 files = set()
3288 files = set()
3293 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3289 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3294 eolmode=None, similarity=sim / 100.0)
3290 eolmode=None, similarity=sim / 100.0)
3295 files = list(files)
3291 files = list(files)
3296 if opts.get('no_commit'):
3292 if opts.get('no_commit'):
3297 if message:
3293 if message:
3298 msgs.append(message)
3294 msgs.append(message)
3299 else:
3295 else:
3300 if opts.get('exact'):
3296 if opts.get('exact'):
3301 m = None
3297 m = None
3302 else:
3298 else:
3303 m = scmutil.matchfiles(repo, files or [])
3299 m = scmutil.matchfiles(repo, files or [])
3304 n = repo.commit(message, opts.get('user') or user,
3300 n = repo.commit(message, opts.get('user') or user,
3305 opts.get('date') or date, match=m,
3301 opts.get('date') or date, match=m,
3306 editor=cmdutil.commiteditor)
3302 editor=cmdutil.commiteditor)
3307 checkexact(repo, n, nodeid)
3303 checkexact(repo, n, nodeid)
3308 # Force a dirstate write so that the next transaction
3304 # Force a dirstate write so that the next transaction
3309 # backups an up-to-date file.
3305 # backups an up-to-date file.
3310 repo.dirstate.write()
3306 repo.dirstate.write()
3311 else:
3307 else:
3312 if opts.get('exact') or opts.get('import_branch'):
3308 if opts.get('exact') or opts.get('import_branch'):
3313 branch = branch or 'default'
3309 branch = branch or 'default'
3314 else:
3310 else:
3315 branch = p1.branch()
3311 branch = p1.branch()
3316 store = patch.filestore()
3312 store = patch.filestore()
3317 try:
3313 try:
3318 files = set()
3314 files = set()
3319 try:
3315 try:
3320 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3316 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3321 files, eolmode=None)
3317 files, eolmode=None)
3322 except patch.PatchError, e:
3318 except patch.PatchError, e:
3323 raise util.Abort(str(e))
3319 raise util.Abort(str(e))
3324 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3320 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3325 message,
3321 message,
3326 opts.get('user') or user,
3322 opts.get('user') or user,
3327 opts.get('date') or date,
3323 opts.get('date') or date,
3328 branch, files, store,
3324 branch, files, store,
3329 editor=cmdutil.commiteditor)
3325 editor=cmdutil.commiteditor)
3330 repo.savecommitmessage(memctx.description())
3326 repo.savecommitmessage(memctx.description())
3331 n = memctx.commit()
3327 n = memctx.commit()
3332 checkexact(repo, n, nodeid)
3328 checkexact(repo, n, nodeid)
3333 finally:
3329 finally:
3334 store.close()
3330 store.close()
3335 if n:
3331 if n:
3336 commitid = short(n)
3332 commitid = short(n)
3337 return commitid
3333 return commitid
3338 finally:
3334 finally:
3339 os.unlink(tmpname)
3335 os.unlink(tmpname)
3340
3336
3341 try:
3337 try:
3342 wlock = repo.wlock()
3338 wlock = repo.wlock()
3343 lock = repo.lock()
3339 lock = repo.lock()
3344 parents = repo.parents()
3340 parents = repo.parents()
3345 lastcommit = None
3341 lastcommit = None
3346 for p in patches:
3342 for p in patches:
3347 pf = os.path.join(d, p)
3343 pf = os.path.join(d, p)
3348
3344
3349 if pf == '-':
3345 if pf == '-':
3350 ui.status(_("applying patch from stdin\n"))
3346 ui.status(_("applying patch from stdin\n"))
3351 pf = ui.fin
3347 pf = ui.fin
3352 else:
3348 else:
3353 ui.status(_("applying %s\n") % p)
3349 ui.status(_("applying %s\n") % p)
3354 pf = url.open(ui, pf)
3350 pf = url.open(ui, pf)
3355
3351
3356 haspatch = False
3352 haspatch = False
3357 for hunk in patch.split(pf):
3353 for hunk in patch.split(pf):
3358 commitid = tryone(ui, hunk, parents)
3354 commitid = tryone(ui, hunk, parents)
3359 if commitid:
3355 if commitid:
3360 haspatch = True
3356 haspatch = True
3361 if lastcommit:
3357 if lastcommit:
3362 ui.status(_('applied %s\n') % lastcommit)
3358 ui.status(_('applied %s\n') % lastcommit)
3363 lastcommit = commitid
3359 lastcommit = commitid
3364 if update or opts.get('exact'):
3360 if update or opts.get('exact'):
3365 parents = repo.parents()
3361 parents = repo.parents()
3366 else:
3362 else:
3367 parents = [repo[commitid]]
3363 parents = [repo[commitid]]
3368
3364
3369 if not haspatch:
3365 if not haspatch:
3370 raise util.Abort(_('no diffs found'))
3366 raise util.Abort(_('no diffs found'))
3371
3367
3372 if msgs:
3368 if msgs:
3373 repo.savecommitmessage('\n* * *\n'.join(msgs))
3369 repo.savecommitmessage('\n* * *\n'.join(msgs))
3374 finally:
3370 finally:
3375 release(lock, wlock)
3371 release(lock, wlock)
3376
3372
3377 @command('incoming|in',
3373 @command('incoming|in',
3378 [('f', 'force', None,
3374 [('f', 'force', None,
3379 _('run even if remote repository is unrelated')),
3375 _('run even if remote repository is unrelated')),
3380 ('n', 'newest-first', None, _('show newest record first')),
3376 ('n', 'newest-first', None, _('show newest record first')),
3381 ('', 'bundle', '',
3377 ('', 'bundle', '',
3382 _('file to store the bundles into'), _('FILE')),
3378 _('file to store the bundles into'), _('FILE')),
3383 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3379 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3384 ('B', 'bookmarks', False, _("compare bookmarks")),
3380 ('B', 'bookmarks', False, _("compare bookmarks")),
3385 ('b', 'branch', [],
3381 ('b', 'branch', [],
3386 _('a specific branch you would like to pull'), _('BRANCH')),
3382 _('a specific branch you would like to pull'), _('BRANCH')),
3387 ] + logopts + remoteopts + subrepoopts,
3383 ] + logopts + remoteopts + subrepoopts,
3388 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3384 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3389 def incoming(ui, repo, source="default", **opts):
3385 def incoming(ui, repo, source="default", **opts):
3390 """show new changesets found in source
3386 """show new changesets found in source
3391
3387
3392 Show new changesets found in the specified path/URL or the default
3388 Show new changesets found in the specified path/URL or the default
3393 pull location. These are the changesets that would have been pulled
3389 pull location. These are the changesets that would have been pulled
3394 if a pull at the time you issued this command.
3390 if a pull at the time you issued this command.
3395
3391
3396 For remote repository, using --bundle avoids downloading the
3392 For remote repository, using --bundle avoids downloading the
3397 changesets twice if the incoming is followed by a pull.
3393 changesets twice if the incoming is followed by a pull.
3398
3394
3399 See pull for valid source format details.
3395 See pull for valid source format details.
3400
3396
3401 Returns 0 if there are incoming changes, 1 otherwise.
3397 Returns 0 if there are incoming changes, 1 otherwise.
3402 """
3398 """
3403 if opts.get('bundle') and opts.get('subrepos'):
3399 if opts.get('bundle') and opts.get('subrepos'):
3404 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3400 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3405
3401
3406 if opts.get('bookmarks'):
3402 if opts.get('bookmarks'):
3407 source, branches = hg.parseurl(ui.expandpath(source),
3403 source, branches = hg.parseurl(ui.expandpath(source),
3408 opts.get('branch'))
3404 opts.get('branch'))
3409 other = hg.peer(repo, opts, source)
3405 other = hg.peer(repo, opts, source)
3410 if 'bookmarks' not in other.listkeys('namespaces'):
3406 if 'bookmarks' not in other.listkeys('namespaces'):
3411 ui.warn(_("remote doesn't support bookmarks\n"))
3407 ui.warn(_("remote doesn't support bookmarks\n"))
3412 return 0
3408 return 0
3413 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3409 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3414 return bookmarks.diff(ui, repo, other)
3410 return bookmarks.diff(ui, repo, other)
3415
3411
3416 repo._subtoppath = ui.expandpath(source)
3412 repo._subtoppath = ui.expandpath(source)
3417 try:
3413 try:
3418 return hg.incoming(ui, repo, source, opts)
3414 return hg.incoming(ui, repo, source, opts)
3419 finally:
3415 finally:
3420 del repo._subtoppath
3416 del repo._subtoppath
3421
3417
3422
3418
3423 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3419 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3424 def init(ui, dest=".", **opts):
3420 def init(ui, dest=".", **opts):
3425 """create a new repository in the given directory
3421 """create a new repository in the given directory
3426
3422
3427 Initialize a new repository in the given directory. If the given
3423 Initialize a new repository in the given directory. If the given
3428 directory does not exist, it will be created.
3424 directory does not exist, it will be created.
3429
3425
3430 If no directory is given, the current directory is used.
3426 If no directory is given, the current directory is used.
3431
3427
3432 It is possible to specify an ``ssh://`` URL as the destination.
3428 It is possible to specify an ``ssh://`` URL as the destination.
3433 See :hg:`help urls` for more information.
3429 See :hg:`help urls` for more information.
3434
3430
3435 Returns 0 on success.
3431 Returns 0 on success.
3436 """
3432 """
3437 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3433 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3438
3434
3439 @command('locate',
3435 @command('locate',
3440 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3436 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3441 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3437 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3442 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3438 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3443 ] + walkopts,
3439 ] + walkopts,
3444 _('[OPTION]... [PATTERN]...'))
3440 _('[OPTION]... [PATTERN]...'))
3445 def locate(ui, repo, *pats, **opts):
3441 def locate(ui, repo, *pats, **opts):
3446 """locate files matching specific patterns
3442 """locate files matching specific patterns
3447
3443
3448 Print files under Mercurial control in the working directory whose
3444 Print files under Mercurial control in the working directory whose
3449 names match the given patterns.
3445 names match the given patterns.
3450
3446
3451 By default, this command searches all directories in the working
3447 By default, this command searches all directories in the working
3452 directory. To search just the current directory and its
3448 directory. To search just the current directory and its
3453 subdirectories, use "--include .".
3449 subdirectories, use "--include .".
3454
3450
3455 If no patterns are given to match, this command prints the names
3451 If no patterns are given to match, this command prints the names
3456 of all files under Mercurial control in the working directory.
3452 of all files under Mercurial control in the working directory.
3457
3453
3458 If you want to feed the output of this command into the "xargs"
3454 If you want to feed the output of this command into the "xargs"
3459 command, use the -0 option to both this command and "xargs". This
3455 command, use the -0 option to both this command and "xargs". This
3460 will avoid the problem of "xargs" treating single filenames that
3456 will avoid the problem of "xargs" treating single filenames that
3461 contain whitespace as multiple filenames.
3457 contain whitespace as multiple filenames.
3462
3458
3463 Returns 0 if a match is found, 1 otherwise.
3459 Returns 0 if a match is found, 1 otherwise.
3464 """
3460 """
3465 end = opts.get('print0') and '\0' or '\n'
3461 end = opts.get('print0') and '\0' or '\n'
3466 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3462 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3467
3463
3468 ret = 1
3464 ret = 1
3469 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3465 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3470 m.bad = lambda x, y: False
3466 m.bad = lambda x, y: False
3471 for abs in repo[rev].walk(m):
3467 for abs in repo[rev].walk(m):
3472 if not rev and abs not in repo.dirstate:
3468 if not rev and abs not in repo.dirstate:
3473 continue
3469 continue
3474 if opts.get('fullpath'):
3470 if opts.get('fullpath'):
3475 ui.write(repo.wjoin(abs), end)
3471 ui.write(repo.wjoin(abs), end)
3476 else:
3472 else:
3477 ui.write(((pats and m.rel(abs)) or abs), end)
3473 ui.write(((pats and m.rel(abs)) or abs), end)
3478 ret = 0
3474 ret = 0
3479
3475
3480 return ret
3476 return ret
3481
3477
3482 @command('^log|history',
3478 @command('^log|history',
3483 [('f', 'follow', None,
3479 [('f', 'follow', None,
3484 _('follow changeset history, or file history across copies and renames')),
3480 _('follow changeset history, or file history across copies and renames')),
3485 ('', 'follow-first', None,
3481 ('', 'follow-first', None,
3486 _('only follow the first parent of merge changesets')),
3482 _('only follow the first parent of merge changesets')),
3487 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3483 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3488 ('C', 'copies', None, _('show copied files')),
3484 ('C', 'copies', None, _('show copied files')),
3489 ('k', 'keyword', [],
3485 ('k', 'keyword', [],
3490 _('do case-insensitive search for a given text'), _('TEXT')),
3486 _('do case-insensitive search for a given text'), _('TEXT')),
3491 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3487 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3492 ('', 'removed', None, _('include revisions where files were removed')),
3488 ('', 'removed', None, _('include revisions where files were removed')),
3493 ('m', 'only-merges', None, _('show only merges')),
3489 ('m', 'only-merges', None, _('show only merges')),
3494 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3490 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3495 ('', 'only-branch', [],
3491 ('', 'only-branch', [],
3496 _('show only changesets within the given named branch (DEPRECATED)'),
3492 _('show only changesets within the given named branch (DEPRECATED)'),
3497 _('BRANCH')),
3493 _('BRANCH')),
3498 ('b', 'branch', [],
3494 ('b', 'branch', [],
3499 _('show changesets within the given named branch'), _('BRANCH')),
3495 _('show changesets within the given named branch'), _('BRANCH')),
3500 ('P', 'prune', [],
3496 ('P', 'prune', [],
3501 _('do not display revision or any of its ancestors'), _('REV')),
3497 _('do not display revision or any of its ancestors'), _('REV')),
3502 ('', 'hidden', False, _('show hidden changesets')),
3498 ('', 'hidden', False, _('show hidden changesets')),
3503 ] + logopts + walkopts,
3499 ] + logopts + walkopts,
3504 _('[OPTION]... [FILE]'))
3500 _('[OPTION]... [FILE]'))
3505 def log(ui, repo, *pats, **opts):
3501 def log(ui, repo, *pats, **opts):
3506 """show revision history of entire repository or files
3502 """show revision history of entire repository or files
3507
3503
3508 Print the revision history of the specified files or the entire
3504 Print the revision history of the specified files or the entire
3509 project.
3505 project.
3510
3506
3511 If no revision range is specified, the default is ``tip:0`` unless
3507 If no revision range is specified, the default is ``tip:0`` unless
3512 --follow is set, in which case the working directory parent is
3508 --follow is set, in which case the working directory parent is
3513 used as the starting revision.
3509 used as the starting revision.
3514
3510
3515 File history is shown without following rename or copy history of
3511 File history is shown without following rename or copy history of
3516 files. Use -f/--follow with a filename to follow history across
3512 files. Use -f/--follow with a filename to follow history across
3517 renames and copies. --follow without a filename will only show
3513 renames and copies. --follow without a filename will only show
3518 ancestors or descendants of the starting revision.
3514 ancestors or descendants of the starting revision.
3519
3515
3520 By default this command prints revision number and changeset id,
3516 By default this command prints revision number and changeset id,
3521 tags, non-trivial parents, user, date and time, and a summary for
3517 tags, non-trivial parents, user, date and time, and a summary for
3522 each commit. When the -v/--verbose switch is used, the list of
3518 each commit. When the -v/--verbose switch is used, the list of
3523 changed files and full commit message are shown.
3519 changed files and full commit message are shown.
3524
3520
3525 .. note::
3521 .. note::
3526 log -p/--patch may generate unexpected diff output for merge
3522 log -p/--patch may generate unexpected diff output for merge
3527 changesets, as it will only compare the merge changeset against
3523 changesets, as it will only compare the merge changeset against
3528 its first parent. Also, only files different from BOTH parents
3524 its first parent. Also, only files different from BOTH parents
3529 will appear in files:.
3525 will appear in files:.
3530
3526
3531 .. note::
3527 .. note::
3532 for performance reasons, log FILE may omit duplicate changes
3528 for performance reasons, log FILE may omit duplicate changes
3533 made on branches and will not show deletions. To see all
3529 made on branches and will not show deletions. To see all
3534 changes including duplicates and deletions, use the --removed
3530 changes including duplicates and deletions, use the --removed
3535 switch.
3531 switch.
3536
3532
3537 .. container:: verbose
3533 .. container:: verbose
3538
3534
3539 Some examples:
3535 Some examples:
3540
3536
3541 - changesets with full descriptions and file lists::
3537 - changesets with full descriptions and file lists::
3542
3538
3543 hg log -v
3539 hg log -v
3544
3540
3545 - changesets ancestral to the working directory::
3541 - changesets ancestral to the working directory::
3546
3542
3547 hg log -f
3543 hg log -f
3548
3544
3549 - last 10 commits on the current branch::
3545 - last 10 commits on the current branch::
3550
3546
3551 hg log -l 10 -b .
3547 hg log -l 10 -b .
3552
3548
3553 - changesets showing all modifications of a file, including removals::
3549 - changesets showing all modifications of a file, including removals::
3554
3550
3555 hg log --removed file.c
3551 hg log --removed file.c
3556
3552
3557 - all changesets that touch a directory, with diffs, excluding merges::
3553 - all changesets that touch a directory, with diffs, excluding merges::
3558
3554
3559 hg log -Mp lib/
3555 hg log -Mp lib/
3560
3556
3561 - all revision numbers that match a keyword::
3557 - all revision numbers that match a keyword::
3562
3558
3563 hg log -k bug --template "{rev}\\n"
3559 hg log -k bug --template "{rev}\\n"
3564
3560
3565 - check if a given changeset is included is a tagged release::
3561 - check if a given changeset is included is a tagged release::
3566
3562
3567 hg log -r "a21ccf and ancestor(1.9)"
3563 hg log -r "a21ccf and ancestor(1.9)"
3568
3564
3569 - find all changesets by some user in a date range::
3565 - find all changesets by some user in a date range::
3570
3566
3571 hg log -k alice -d "may 2008 to jul 2008"
3567 hg log -k alice -d "may 2008 to jul 2008"
3572
3568
3573 - summary of all changesets after the last tag::
3569 - summary of all changesets after the last tag::
3574
3570
3575 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3571 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3576
3572
3577 See :hg:`help dates` for a list of formats valid for -d/--date.
3573 See :hg:`help dates` for a list of formats valid for -d/--date.
3578
3574
3579 See :hg:`help revisions` and :hg:`help revsets` for more about
3575 See :hg:`help revisions` and :hg:`help revsets` for more about
3580 specifying revisions.
3576 specifying revisions.
3581
3577
3582 Returns 0 on success.
3578 Returns 0 on success.
3583 """
3579 """
3584
3580
3585 matchfn = scmutil.match(repo[None], pats, opts)
3581 matchfn = scmutil.match(repo[None], pats, opts)
3586 limit = cmdutil.loglimit(opts)
3582 limit = cmdutil.loglimit(opts)
3587 count = 0
3583 count = 0
3588
3584
3589 endrev = None
3585 endrev = None
3590 if opts.get('copies') and opts.get('rev'):
3586 if opts.get('copies') and opts.get('rev'):
3591 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3587 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3592
3588
3593 df = False
3589 df = False
3594 if opts["date"]:
3590 if opts["date"]:
3595 df = util.matchdate(opts["date"])
3591 df = util.matchdate(opts["date"])
3596
3592
3597 branches = opts.get('branch', []) + opts.get('only_branch', [])
3593 branches = opts.get('branch', []) + opts.get('only_branch', [])
3598 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3594 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3599
3595
3600 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3596 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3601 def prep(ctx, fns):
3597 def prep(ctx, fns):
3602 rev = ctx.rev()
3598 rev = ctx.rev()
3603 parents = [p for p in repo.changelog.parentrevs(rev)
3599 parents = [p for p in repo.changelog.parentrevs(rev)
3604 if p != nullrev]
3600 if p != nullrev]
3605 if opts.get('no_merges') and len(parents) == 2:
3601 if opts.get('no_merges') and len(parents) == 2:
3606 return
3602 return
3607 if opts.get('only_merges') and len(parents) != 2:
3603 if opts.get('only_merges') and len(parents) != 2:
3608 return
3604 return
3609 if opts.get('branch') and ctx.branch() not in opts['branch']:
3605 if opts.get('branch') and ctx.branch() not in opts['branch']:
3610 return
3606 return
3611 if not opts.get('hidden') and ctx.hidden():
3607 if not opts.get('hidden') and ctx.hidden():
3612 return
3608 return
3613 if df and not df(ctx.date()[0]):
3609 if df and not df(ctx.date()[0]):
3614 return
3610 return
3615 if opts['user'] and not [k for k in opts['user']
3611 if opts['user'] and not [k for k in opts['user']
3616 if k.lower() in ctx.user().lower()]:
3612 if k.lower() in ctx.user().lower()]:
3617 return
3613 return
3618 if opts.get('keyword'):
3614 if opts.get('keyword'):
3619 for k in [kw.lower() for kw in opts['keyword']]:
3615 for k in [kw.lower() for kw in opts['keyword']]:
3620 if (k in ctx.user().lower() or
3616 if (k in ctx.user().lower() or
3621 k in ctx.description().lower() or
3617 k in ctx.description().lower() or
3622 k in " ".join(ctx.files()).lower()):
3618 k in " ".join(ctx.files()).lower()):
3623 break
3619 break
3624 else:
3620 else:
3625 return
3621 return
3626
3622
3627 copies = None
3623 copies = None
3628 if opts.get('copies') and rev:
3624 if opts.get('copies') and rev:
3629 copies = []
3625 copies = []
3630 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3626 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3631 for fn in ctx.files():
3627 for fn in ctx.files():
3632 rename = getrenamed(fn, rev)
3628 rename = getrenamed(fn, rev)
3633 if rename:
3629 if rename:
3634 copies.append((fn, rename[0]))
3630 copies.append((fn, rename[0]))
3635
3631
3636 revmatchfn = None
3632 revmatchfn = None
3637 if opts.get('patch') or opts.get('stat'):
3633 if opts.get('patch') or opts.get('stat'):
3638 if opts.get('follow') or opts.get('follow_first'):
3634 if opts.get('follow') or opts.get('follow_first'):
3639 # note: this might be wrong when following through merges
3635 # note: this might be wrong when following through merges
3640 revmatchfn = scmutil.match(repo[None], fns, default='path')
3636 revmatchfn = scmutil.match(repo[None], fns, default='path')
3641 else:
3637 else:
3642 revmatchfn = matchfn
3638 revmatchfn = matchfn
3643
3639
3644 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3640 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3645
3641
3646 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3642 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3647 if count == limit:
3643 if count == limit:
3648 break
3644 break
3649 if displayer.flush(ctx.rev()):
3645 if displayer.flush(ctx.rev()):
3650 count += 1
3646 count += 1
3651 displayer.close()
3647 displayer.close()
3652
3648
3653 @command('manifest',
3649 @command('manifest',
3654 [('r', 'rev', '', _('revision to display'), _('REV')),
3650 [('r', 'rev', '', _('revision to display'), _('REV')),
3655 ('', 'all', False, _("list files from all revisions"))],
3651 ('', 'all', False, _("list files from all revisions"))],
3656 _('[-r REV]'))
3652 _('[-r REV]'))
3657 def manifest(ui, repo, node=None, rev=None, **opts):
3653 def manifest(ui, repo, node=None, rev=None, **opts):
3658 """output the current or given revision of the project manifest
3654 """output the current or given revision of the project manifest
3659
3655
3660 Print a list of version controlled files for the given revision.
3656 Print a list of version controlled files for the given revision.
3661 If no revision is given, the first parent of the working directory
3657 If no revision is given, the first parent of the working directory
3662 is used, or the null revision if no revision is checked out.
3658 is used, or the null revision if no revision is checked out.
3663
3659
3664 With -v, print file permissions, symlink and executable bits.
3660 With -v, print file permissions, symlink and executable bits.
3665 With --debug, print file revision hashes.
3661 With --debug, print file revision hashes.
3666
3662
3667 If option --all is specified, the list of all files from all revisions
3663 If option --all is specified, the list of all files from all revisions
3668 is printed. This includes deleted and renamed files.
3664 is printed. This includes deleted and renamed files.
3669
3665
3670 Returns 0 on success.
3666 Returns 0 on success.
3671 """
3667 """
3672 if opts.get('all'):
3668 if opts.get('all'):
3673 if rev or node:
3669 if rev or node:
3674 raise util.Abort(_("can't specify a revision with --all"))
3670 raise util.Abort(_("can't specify a revision with --all"))
3675
3671
3676 res = []
3672 res = []
3677 prefix = "data/"
3673 prefix = "data/"
3678 suffix = ".i"
3674 suffix = ".i"
3679 plen = len(prefix)
3675 plen = len(prefix)
3680 slen = len(suffix)
3676 slen = len(suffix)
3681 lock = repo.lock()
3677 lock = repo.lock()
3682 try:
3678 try:
3683 for fn, b, size in repo.store.datafiles():
3679 for fn, b, size in repo.store.datafiles():
3684 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3680 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3685 res.append(fn[plen:-slen])
3681 res.append(fn[plen:-slen])
3686 finally:
3682 finally:
3687 lock.release()
3683 lock.release()
3688 for f in sorted(res):
3684 for f in sorted(res):
3689 ui.write("%s\n" % f)
3685 ui.write("%s\n" % f)
3690 return
3686 return
3691
3687
3692 if rev and node:
3688 if rev and node:
3693 raise util.Abort(_("please specify just one revision"))
3689 raise util.Abort(_("please specify just one revision"))
3694
3690
3695 if not node:
3691 if not node:
3696 node = rev
3692 node = rev
3697
3693
3698 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3694 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3699 ctx = scmutil.revsingle(repo, node)
3695 ctx = scmutil.revsingle(repo, node)
3700 for f in ctx:
3696 for f in ctx:
3701 if ui.debugflag:
3697 if ui.debugflag:
3702 ui.write("%40s " % hex(ctx.manifest()[f]))
3698 ui.write("%40s " % hex(ctx.manifest()[f]))
3703 if ui.verbose:
3699 if ui.verbose:
3704 ui.write(decor[ctx.flags(f)])
3700 ui.write(decor[ctx.flags(f)])
3705 ui.write("%s\n" % f)
3701 ui.write("%s\n" % f)
3706
3702
3707 @command('^merge',
3703 @command('^merge',
3708 [('f', 'force', None, _('force a merge with outstanding changes')),
3704 [('f', 'force', None, _('force a merge with outstanding changes')),
3709 ('r', 'rev', '', _('revision to merge'), _('REV')),
3705 ('r', 'rev', '', _('revision to merge'), _('REV')),
3710 ('P', 'preview', None,
3706 ('P', 'preview', None,
3711 _('review revisions to merge (no merge is performed)'))
3707 _('review revisions to merge (no merge is performed)'))
3712 ] + mergetoolopts,
3708 ] + mergetoolopts,
3713 _('[-P] [-f] [[-r] REV]'))
3709 _('[-P] [-f] [[-r] REV]'))
3714 def merge(ui, repo, node=None, **opts):
3710 def merge(ui, repo, node=None, **opts):
3715 """merge working directory with another revision
3711 """merge working directory with another revision
3716
3712
3717 The current working directory is updated with all changes made in
3713 The current working directory is updated with all changes made in
3718 the requested revision since the last common predecessor revision.
3714 the requested revision since the last common predecessor revision.
3719
3715
3720 Files that changed between either parent are marked as changed for
3716 Files that changed between either parent are marked as changed for
3721 the next commit and a commit must be performed before any further
3717 the next commit and a commit must be performed before any further
3722 updates to the repository are allowed. The next commit will have
3718 updates to the repository are allowed. The next commit will have
3723 two parents.
3719 two parents.
3724
3720
3725 ``--tool`` can be used to specify the merge tool used for file
3721 ``--tool`` can be used to specify the merge tool used for file
3726 merges. It overrides the HGMERGE environment variable and your
3722 merges. It overrides the HGMERGE environment variable and your
3727 configuration files. See :hg:`help merge-tools` for options.
3723 configuration files. See :hg:`help merge-tools` for options.
3728
3724
3729 If no revision is specified, the working directory's parent is a
3725 If no revision is specified, the working directory's parent is a
3730 head revision, and the current branch contains exactly one other
3726 head revision, and the current branch contains exactly one other
3731 head, the other head is merged with by default. Otherwise, an
3727 head, the other head is merged with by default. Otherwise, an
3732 explicit revision with which to merge with must be provided.
3728 explicit revision with which to merge with must be provided.
3733
3729
3734 :hg:`resolve` must be used to resolve unresolved files.
3730 :hg:`resolve` must be used to resolve unresolved files.
3735
3731
3736 To undo an uncommitted merge, use :hg:`update --clean .` which
3732 To undo an uncommitted merge, use :hg:`update --clean .` which
3737 will check out a clean copy of the original merge parent, losing
3733 will check out a clean copy of the original merge parent, losing
3738 all changes.
3734 all changes.
3739
3735
3740 Returns 0 on success, 1 if there are unresolved files.
3736 Returns 0 on success, 1 if there are unresolved files.
3741 """
3737 """
3742
3738
3743 if opts.get('rev') and node:
3739 if opts.get('rev') and node:
3744 raise util.Abort(_("please specify just one revision"))
3740 raise util.Abort(_("please specify just one revision"))
3745 if not node:
3741 if not node:
3746 node = opts.get('rev')
3742 node = opts.get('rev')
3747
3743
3748 if not node:
3744 if not node:
3749 branch = repo[None].branch()
3745 branch = repo[None].branch()
3750 bheads = repo.branchheads(branch)
3746 bheads = repo.branchheads(branch)
3751 if len(bheads) > 2:
3747 if len(bheads) > 2:
3752 raise util.Abort(_("branch '%s' has %d heads - "
3748 raise util.Abort(_("branch '%s' has %d heads - "
3753 "please merge with an explicit rev")
3749 "please merge with an explicit rev")
3754 % (branch, len(bheads)),
3750 % (branch, len(bheads)),
3755 hint=_("run 'hg heads .' to see heads"))
3751 hint=_("run 'hg heads .' to see heads"))
3756
3752
3757 parent = repo.dirstate.p1()
3753 parent = repo.dirstate.p1()
3758 if len(bheads) == 1:
3754 if len(bheads) == 1:
3759 if len(repo.heads()) > 1:
3755 if len(repo.heads()) > 1:
3760 raise util.Abort(_("branch '%s' has one head - "
3756 raise util.Abort(_("branch '%s' has one head - "
3761 "please merge with an explicit rev")
3757 "please merge with an explicit rev")
3762 % branch,
3758 % branch,
3763 hint=_("run 'hg heads' to see all heads"))
3759 hint=_("run 'hg heads' to see all heads"))
3764 msg = _('there is nothing to merge')
3760 msg = _('there is nothing to merge')
3765 if parent != repo.lookup(repo[None].branch()):
3761 if parent != repo.lookup(repo[None].branch()):
3766 msg = _('%s - use "hg update" instead') % msg
3762 msg = _('%s - use "hg update" instead') % msg
3767 raise util.Abort(msg)
3763 raise util.Abort(msg)
3768
3764
3769 if parent not in bheads:
3765 if parent not in bheads:
3770 raise util.Abort(_('working directory not at a head revision'),
3766 raise util.Abort(_('working directory not at a head revision'),
3771 hint=_("use 'hg update' or merge with an "
3767 hint=_("use 'hg update' or merge with an "
3772 "explicit revision"))
3768 "explicit revision"))
3773 node = parent == bheads[0] and bheads[-1] or bheads[0]
3769 node = parent == bheads[0] and bheads[-1] or bheads[0]
3774 else:
3770 else:
3775 node = scmutil.revsingle(repo, node).node()
3771 node = scmutil.revsingle(repo, node).node()
3776
3772
3777 if opts.get('preview'):
3773 if opts.get('preview'):
3778 # find nodes that are ancestors of p2 but not of p1
3774 # find nodes that are ancestors of p2 but not of p1
3779 p1 = repo.lookup('.')
3775 p1 = repo.lookup('.')
3780 p2 = repo.lookup(node)
3776 p2 = repo.lookup(node)
3781 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3777 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3782
3778
3783 displayer = cmdutil.show_changeset(ui, repo, opts)
3779 displayer = cmdutil.show_changeset(ui, repo, opts)
3784 for node in nodes:
3780 for node in nodes:
3785 displayer.show(repo[node])
3781 displayer.show(repo[node])
3786 displayer.close()
3782 displayer.close()
3787 return 0
3783 return 0
3788
3784
3789 try:
3785 try:
3790 # ui.forcemerge is an internal variable, do not document
3786 # ui.forcemerge is an internal variable, do not document
3791 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3787 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3792 return hg.merge(repo, node, force=opts.get('force'))
3788 return hg.merge(repo, node, force=opts.get('force'))
3793 finally:
3789 finally:
3794 ui.setconfig('ui', 'forcemerge', '')
3790 ui.setconfig('ui', 'forcemerge', '')
3795
3791
3796 @command('outgoing|out',
3792 @command('outgoing|out',
3797 [('f', 'force', None, _('run even when the destination is unrelated')),
3793 [('f', 'force', None, _('run even when the destination is unrelated')),
3798 ('r', 'rev', [],
3794 ('r', 'rev', [],
3799 _('a changeset intended to be included in the destination'), _('REV')),
3795 _('a changeset intended to be included in the destination'), _('REV')),
3800 ('n', 'newest-first', None, _('show newest record first')),
3796 ('n', 'newest-first', None, _('show newest record first')),
3801 ('B', 'bookmarks', False, _('compare bookmarks')),
3797 ('B', 'bookmarks', False, _('compare bookmarks')),
3802 ('b', 'branch', [], _('a specific branch you would like to push'),
3798 ('b', 'branch', [], _('a specific branch you would like to push'),
3803 _('BRANCH')),
3799 _('BRANCH')),
3804 ] + logopts + remoteopts + subrepoopts,
3800 ] + logopts + remoteopts + subrepoopts,
3805 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3801 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3806 def outgoing(ui, repo, dest=None, **opts):
3802 def outgoing(ui, repo, dest=None, **opts):
3807 """show changesets not found in the destination
3803 """show changesets not found in the destination
3808
3804
3809 Show changesets not found in the specified destination repository
3805 Show changesets not found in the specified destination repository
3810 or the default push location. These are the changesets that would
3806 or the default push location. These are the changesets that would
3811 be pushed if a push was requested.
3807 be pushed if a push was requested.
3812
3808
3813 See pull for details of valid destination formats.
3809 See pull for details of valid destination formats.
3814
3810
3815 Returns 0 if there are outgoing changes, 1 otherwise.
3811 Returns 0 if there are outgoing changes, 1 otherwise.
3816 """
3812 """
3817
3813
3818 if opts.get('bookmarks'):
3814 if opts.get('bookmarks'):
3819 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3815 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3820 dest, branches = hg.parseurl(dest, opts.get('branch'))
3816 dest, branches = hg.parseurl(dest, opts.get('branch'))
3821 other = hg.peer(repo, opts, dest)
3817 other = hg.peer(repo, opts, dest)
3822 if 'bookmarks' not in other.listkeys('namespaces'):
3818 if 'bookmarks' not in other.listkeys('namespaces'):
3823 ui.warn(_("remote doesn't support bookmarks\n"))
3819 ui.warn(_("remote doesn't support bookmarks\n"))
3824 return 0
3820 return 0
3825 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3821 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3826 return bookmarks.diff(ui, other, repo)
3822 return bookmarks.diff(ui, other, repo)
3827
3823
3828 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3824 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3829 try:
3825 try:
3830 return hg.outgoing(ui, repo, dest, opts)
3826 return hg.outgoing(ui, repo, dest, opts)
3831 finally:
3827 finally:
3832 del repo._subtoppath
3828 del repo._subtoppath
3833
3829
3834 @command('parents',
3830 @command('parents',
3835 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3831 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3836 ] + templateopts,
3832 ] + templateopts,
3837 _('[-r REV] [FILE]'))
3833 _('[-r REV] [FILE]'))
3838 def parents(ui, repo, file_=None, **opts):
3834 def parents(ui, repo, file_=None, **opts):
3839 """show the parents of the working directory or revision
3835 """show the parents of the working directory or revision
3840
3836
3841 Print the working directory's parent revisions. If a revision is
3837 Print the working directory's parent revisions. If a revision is
3842 given via -r/--rev, the parent of that revision will be printed.
3838 given via -r/--rev, the parent of that revision will be printed.
3843 If a file argument is given, the revision in which the file was
3839 If a file argument is given, the revision in which the file was
3844 last changed (before the working directory revision or the
3840 last changed (before the working directory revision or the
3845 argument to --rev if given) is printed.
3841 argument to --rev if given) is printed.
3846
3842
3847 Returns 0 on success.
3843 Returns 0 on success.
3848 """
3844 """
3849
3845
3850 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3846 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3851
3847
3852 if file_:
3848 if file_:
3853 m = scmutil.match(ctx, (file_,), opts)
3849 m = scmutil.match(ctx, (file_,), opts)
3854 if m.anypats() or len(m.files()) != 1:
3850 if m.anypats() or len(m.files()) != 1:
3855 raise util.Abort(_('can only specify an explicit filename'))
3851 raise util.Abort(_('can only specify an explicit filename'))
3856 file_ = m.files()[0]
3852 file_ = m.files()[0]
3857 filenodes = []
3853 filenodes = []
3858 for cp in ctx.parents():
3854 for cp in ctx.parents():
3859 if not cp:
3855 if not cp:
3860 continue
3856 continue
3861 try:
3857 try:
3862 filenodes.append(cp.filenode(file_))
3858 filenodes.append(cp.filenode(file_))
3863 except error.LookupError:
3859 except error.LookupError:
3864 pass
3860 pass
3865 if not filenodes:
3861 if not filenodes:
3866 raise util.Abort(_("'%s' not found in manifest!") % file_)
3862 raise util.Abort(_("'%s' not found in manifest!") % file_)
3867 fl = repo.file(file_)
3863 fl = repo.file(file_)
3868 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3864 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3869 else:
3865 else:
3870 p = [cp.node() for cp in ctx.parents()]
3866 p = [cp.node() for cp in ctx.parents()]
3871
3867
3872 displayer = cmdutil.show_changeset(ui, repo, opts)
3868 displayer = cmdutil.show_changeset(ui, repo, opts)
3873 for n in p:
3869 for n in p:
3874 if n != nullid:
3870 if n != nullid:
3875 displayer.show(repo[n])
3871 displayer.show(repo[n])
3876 displayer.close()
3872 displayer.close()
3877
3873
3878 @command('paths', [], _('[NAME]'))
3874 @command('paths', [], _('[NAME]'))
3879 def paths(ui, repo, search=None):
3875 def paths(ui, repo, search=None):
3880 """show aliases for remote repositories
3876 """show aliases for remote repositories
3881
3877
3882 Show definition of symbolic path name NAME. If no name is given,
3878 Show definition of symbolic path name NAME. If no name is given,
3883 show definition of all available names.
3879 show definition of all available names.
3884
3880
3885 Option -q/--quiet suppresses all output when searching for NAME
3881 Option -q/--quiet suppresses all output when searching for NAME
3886 and shows only the path names when listing all definitions.
3882 and shows only the path names when listing all definitions.
3887
3883
3888 Path names are defined in the [paths] section of your
3884 Path names are defined in the [paths] section of your
3889 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3885 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3890 repository, ``.hg/hgrc`` is used, too.
3886 repository, ``.hg/hgrc`` is used, too.
3891
3887
3892 The path names ``default`` and ``default-push`` have a special
3888 The path names ``default`` and ``default-push`` have a special
3893 meaning. When performing a push or pull operation, they are used
3889 meaning. When performing a push or pull operation, they are used
3894 as fallbacks if no location is specified on the command-line.
3890 as fallbacks if no location is specified on the command-line.
3895 When ``default-push`` is set, it will be used for push and
3891 When ``default-push`` is set, it will be used for push and
3896 ``default`` will be used for pull; otherwise ``default`` is used
3892 ``default`` will be used for pull; otherwise ``default`` is used
3897 as the fallback for both. When cloning a repository, the clone
3893 as the fallback for both. When cloning a repository, the clone
3898 source is written as ``default`` in ``.hg/hgrc``. Note that
3894 source is written as ``default`` in ``.hg/hgrc``. Note that
3899 ``default`` and ``default-push`` apply to all inbound (e.g.
3895 ``default`` and ``default-push`` apply to all inbound (e.g.
3900 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3896 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3901 :hg:`bundle`) operations.
3897 :hg:`bundle`) operations.
3902
3898
3903 See :hg:`help urls` for more information.
3899 See :hg:`help urls` for more information.
3904
3900
3905 Returns 0 on success.
3901 Returns 0 on success.
3906 """
3902 """
3907 if search:
3903 if search:
3908 for name, path in ui.configitems("paths"):
3904 for name, path in ui.configitems("paths"):
3909 if name == search:
3905 if name == search:
3910 ui.status("%s\n" % util.hidepassword(path))
3906 ui.status("%s\n" % util.hidepassword(path))
3911 return
3907 return
3912 if not ui.quiet:
3908 if not ui.quiet:
3913 ui.warn(_("not found!\n"))
3909 ui.warn(_("not found!\n"))
3914 return 1
3910 return 1
3915 else:
3911 else:
3916 for name, path in ui.configitems("paths"):
3912 for name, path in ui.configitems("paths"):
3917 if ui.quiet:
3913 if ui.quiet:
3918 ui.write("%s\n" % name)
3914 ui.write("%s\n" % name)
3919 else:
3915 else:
3920 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3916 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3921
3917
3922 def postincoming(ui, repo, modheads, optupdate, checkout):
3918 def postincoming(ui, repo, modheads, optupdate, checkout):
3923 if modheads == 0:
3919 if modheads == 0:
3924 return
3920 return
3925 if optupdate:
3921 if optupdate:
3926 try:
3922 try:
3927 return hg.update(repo, checkout)
3923 return hg.update(repo, checkout)
3928 except util.Abort, inst:
3924 except util.Abort, inst:
3929 ui.warn(_("not updating: %s\n" % str(inst)))
3925 ui.warn(_("not updating: %s\n" % str(inst)))
3930 return 0
3926 return 0
3931 if modheads > 1:
3927 if modheads > 1:
3932 currentbranchheads = len(repo.branchheads())
3928 currentbranchheads = len(repo.branchheads())
3933 if currentbranchheads == modheads:
3929 if currentbranchheads == modheads:
3934 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3930 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3935 elif currentbranchheads > 1:
3931 elif currentbranchheads > 1:
3936 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3932 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3937 else:
3933 else:
3938 ui.status(_("(run 'hg heads' to see heads)\n"))
3934 ui.status(_("(run 'hg heads' to see heads)\n"))
3939 else:
3935 else:
3940 ui.status(_("(run 'hg update' to get a working copy)\n"))
3936 ui.status(_("(run 'hg update' to get a working copy)\n"))
3941
3937
3942 @command('^pull',
3938 @command('^pull',
3943 [('u', 'update', None,
3939 [('u', 'update', None,
3944 _('update to new branch head if changesets were pulled')),
3940 _('update to new branch head if changesets were pulled')),
3945 ('f', 'force', None, _('run even when remote repository is unrelated')),
3941 ('f', 'force', None, _('run even when remote repository is unrelated')),
3946 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3942 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3947 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3943 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3948 ('b', 'branch', [], _('a specific branch you would like to pull'),
3944 ('b', 'branch', [], _('a specific branch you would like to pull'),
3949 _('BRANCH')),
3945 _('BRANCH')),
3950 ] + remoteopts,
3946 ] + remoteopts,
3951 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3947 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3952 def pull(ui, repo, source="default", **opts):
3948 def pull(ui, repo, source="default", **opts):
3953 """pull changes from the specified source
3949 """pull changes from the specified source
3954
3950
3955 Pull changes from a remote repository to a local one.
3951 Pull changes from a remote repository to a local one.
3956
3952
3957 This finds all changes from the repository at the specified path
3953 This finds all changes from the repository at the specified path
3958 or URL and adds them to a local repository (the current one unless
3954 or URL and adds them to a local repository (the current one unless
3959 -R is specified). By default, this does not update the copy of the
3955 -R is specified). By default, this does not update the copy of the
3960 project in the working directory.
3956 project in the working directory.
3961
3957
3962 Use :hg:`incoming` if you want to see what would have been added
3958 Use :hg:`incoming` if you want to see what would have been added
3963 by a pull at the time you issued this command. If you then decide
3959 by a pull at the time you issued this command. If you then decide
3964 to add those changes to the repository, you should use :hg:`pull
3960 to add those changes to the repository, you should use :hg:`pull
3965 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3961 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3966
3962
3967 If SOURCE is omitted, the 'default' path will be used.
3963 If SOURCE is omitted, the 'default' path will be used.
3968 See :hg:`help urls` for more information.
3964 See :hg:`help urls` for more information.
3969
3965
3970 Returns 0 on success, 1 if an update had unresolved files.
3966 Returns 0 on success, 1 if an update had unresolved files.
3971 """
3967 """
3972 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3968 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3973 other = hg.peer(repo, opts, source)
3969 other = hg.peer(repo, opts, source)
3974 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3970 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3975 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3971 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3976
3972
3977 if opts.get('bookmark'):
3973 if opts.get('bookmark'):
3978 if not revs:
3974 if not revs:
3979 revs = []
3975 revs = []
3980 rb = other.listkeys('bookmarks')
3976 rb = other.listkeys('bookmarks')
3981 for b in opts['bookmark']:
3977 for b in opts['bookmark']:
3982 if b not in rb:
3978 if b not in rb:
3983 raise util.Abort(_('remote bookmark %s not found!') % b)
3979 raise util.Abort(_('remote bookmark %s not found!') % b)
3984 revs.append(rb[b])
3980 revs.append(rb[b])
3985
3981
3986 if revs:
3982 if revs:
3987 try:
3983 try:
3988 revs = [other.lookup(rev) for rev in revs]
3984 revs = [other.lookup(rev) for rev in revs]
3989 except error.CapabilityError:
3985 except error.CapabilityError:
3990 err = _("other repository doesn't support revision lookup, "
3986 err = _("other repository doesn't support revision lookup, "
3991 "so a rev cannot be specified.")
3987 "so a rev cannot be specified.")
3992 raise util.Abort(err)
3988 raise util.Abort(err)
3993
3989
3994 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3990 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3995 bookmarks.updatefromremote(ui, repo, other)
3991 bookmarks.updatefromremote(ui, repo, other)
3996 if checkout:
3992 if checkout:
3997 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3993 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3998 repo._subtoppath = source
3994 repo._subtoppath = source
3999 try:
3995 try:
4000 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3996 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4001
3997
4002 finally:
3998 finally:
4003 del repo._subtoppath
3999 del repo._subtoppath
4004
4000
4005 # update specified bookmarks
4001 # update specified bookmarks
4006 if opts.get('bookmark'):
4002 if opts.get('bookmark'):
4007 for b in opts['bookmark']:
4003 for b in opts['bookmark']:
4008 # explicit pull overrides local bookmark if any
4004 # explicit pull overrides local bookmark if any
4009 ui.status(_("importing bookmark %s\n") % b)
4005 ui.status(_("importing bookmark %s\n") % b)
4010 repo._bookmarks[b] = repo[rb[b]].node()
4006 repo._bookmarks[b] = repo[rb[b]].node()
4011 bookmarks.write(repo)
4007 bookmarks.write(repo)
4012
4008
4013 return ret
4009 return ret
4014
4010
4015 @command('^push',
4011 @command('^push',
4016 [('f', 'force', None, _('force push')),
4012 [('f', 'force', None, _('force push')),
4017 ('r', 'rev', [],
4013 ('r', 'rev', [],
4018 _('a changeset intended to be included in the destination'),
4014 _('a changeset intended to be included in the destination'),
4019 _('REV')),
4015 _('REV')),
4020 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4016 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4021 ('b', 'branch', [],
4017 ('b', 'branch', [],
4022 _('a specific branch you would like to push'), _('BRANCH')),
4018 _('a specific branch you would like to push'), _('BRANCH')),
4023 ('', 'new-branch', False, _('allow pushing a new branch')),
4019 ('', 'new-branch', False, _('allow pushing a new branch')),
4024 ] + remoteopts,
4020 ] + remoteopts,
4025 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4021 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4026 def push(ui, repo, dest=None, **opts):
4022 def push(ui, repo, dest=None, **opts):
4027 """push changes to the specified destination
4023 """push changes to the specified destination
4028
4024
4029 Push changesets from the local repository to the specified
4025 Push changesets from the local repository to the specified
4030 destination.
4026 destination.
4031
4027
4032 This operation is symmetrical to pull: it is identical to a pull
4028 This operation is symmetrical to pull: it is identical to a pull
4033 in the destination repository from the current one.
4029 in the destination repository from the current one.
4034
4030
4035 By default, push will not allow creation of new heads at the
4031 By default, push will not allow creation of new heads at the
4036 destination, since multiple heads would make it unclear which head
4032 destination, since multiple heads would make it unclear which head
4037 to use. In this situation, it is recommended to pull and merge
4033 to use. In this situation, it is recommended to pull and merge
4038 before pushing.
4034 before pushing.
4039
4035
4040 Use --new-branch if you want to allow push to create a new named
4036 Use --new-branch if you want to allow push to create a new named
4041 branch that is not present at the destination. This allows you to
4037 branch that is not present at the destination. This allows you to
4042 only create a new branch without forcing other changes.
4038 only create a new branch without forcing other changes.
4043
4039
4044 Use -f/--force to override the default behavior and push all
4040 Use -f/--force to override the default behavior and push all
4045 changesets on all branches.
4041 changesets on all branches.
4046
4042
4047 If -r/--rev is used, the specified revision and all its ancestors
4043 If -r/--rev is used, the specified revision and all its ancestors
4048 will be pushed to the remote repository.
4044 will be pushed to the remote repository.
4049
4045
4050 Please see :hg:`help urls` for important details about ``ssh://``
4046 Please see :hg:`help urls` for important details about ``ssh://``
4051 URLs. If DESTINATION is omitted, a default path will be used.
4047 URLs. If DESTINATION is omitted, a default path will be used.
4052
4048
4053 Returns 0 if push was successful, 1 if nothing to push.
4049 Returns 0 if push was successful, 1 if nothing to push.
4054 """
4050 """
4055
4051
4056 if opts.get('bookmark'):
4052 if opts.get('bookmark'):
4057 for b in opts['bookmark']:
4053 for b in opts['bookmark']:
4058 # translate -B options to -r so changesets get pushed
4054 # translate -B options to -r so changesets get pushed
4059 if b in repo._bookmarks:
4055 if b in repo._bookmarks:
4060 opts.setdefault('rev', []).append(b)
4056 opts.setdefault('rev', []).append(b)
4061 else:
4057 else:
4062 # if we try to push a deleted bookmark, translate it to null
4058 # if we try to push a deleted bookmark, translate it to null
4063 # this lets simultaneous -r, -b options continue working
4059 # this lets simultaneous -r, -b options continue working
4064 opts.setdefault('rev', []).append("null")
4060 opts.setdefault('rev', []).append("null")
4065
4061
4066 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4062 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4067 dest, branches = hg.parseurl(dest, opts.get('branch'))
4063 dest, branches = hg.parseurl(dest, opts.get('branch'))
4068 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4064 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4069 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4065 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4070 other = hg.peer(repo, opts, dest)
4066 other = hg.peer(repo, opts, dest)
4071 if revs:
4067 if revs:
4072 revs = [repo.lookup(rev) for rev in revs]
4068 revs = [repo.lookup(rev) for rev in revs]
4073
4069
4074 repo._subtoppath = dest
4070 repo._subtoppath = dest
4075 try:
4071 try:
4076 # push subrepos depth-first for coherent ordering
4072 # push subrepos depth-first for coherent ordering
4077 c = repo['']
4073 c = repo['']
4078 subs = c.substate # only repos that are committed
4074 subs = c.substate # only repos that are committed
4079 for s in sorted(subs):
4075 for s in sorted(subs):
4080 if not c.sub(s).push(opts.get('force')):
4076 if not c.sub(s).push(opts.get('force')):
4081 return False
4077 return False
4082 finally:
4078 finally:
4083 del repo._subtoppath
4079 del repo._subtoppath
4084 result = repo.push(other, opts.get('force'), revs=revs,
4080 result = repo.push(other, opts.get('force'), revs=revs,
4085 newbranch=opts.get('new_branch'))
4081 newbranch=opts.get('new_branch'))
4086
4082
4087 result = (result == 0)
4083 result = (result == 0)
4088
4084
4089 if opts.get('bookmark'):
4085 if opts.get('bookmark'):
4090 rb = other.listkeys('bookmarks')
4086 rb = other.listkeys('bookmarks')
4091 for b in opts['bookmark']:
4087 for b in opts['bookmark']:
4092 # explicit push overrides remote bookmark if any
4088 # explicit push overrides remote bookmark if any
4093 if b in repo._bookmarks:
4089 if b in repo._bookmarks:
4094 ui.status(_("exporting bookmark %s\n") % b)
4090 ui.status(_("exporting bookmark %s\n") % b)
4095 new = repo[b].hex()
4091 new = repo[b].hex()
4096 elif b in rb:
4092 elif b in rb:
4097 ui.status(_("deleting remote bookmark %s\n") % b)
4093 ui.status(_("deleting remote bookmark %s\n") % b)
4098 new = '' # delete
4094 new = '' # delete
4099 else:
4095 else:
4100 ui.warn(_('bookmark %s does not exist on the local '
4096 ui.warn(_('bookmark %s does not exist on the local '
4101 'or remote repository!\n') % b)
4097 'or remote repository!\n') % b)
4102 return 2
4098 return 2
4103 old = rb.get(b, '')
4099 old = rb.get(b, '')
4104 r = other.pushkey('bookmarks', b, old, new)
4100 r = other.pushkey('bookmarks', b, old, new)
4105 if not r:
4101 if not r:
4106 ui.warn(_('updating bookmark %s failed!\n') % b)
4102 ui.warn(_('updating bookmark %s failed!\n') % b)
4107 if not result:
4103 if not result:
4108 result = 2
4104 result = 2
4109
4105
4110 return result
4106 return result
4111
4107
4112 @command('recover', [])
4108 @command('recover', [])
4113 def recover(ui, repo):
4109 def recover(ui, repo):
4114 """roll back an interrupted transaction
4110 """roll back an interrupted transaction
4115
4111
4116 Recover from an interrupted commit or pull.
4112 Recover from an interrupted commit or pull.
4117
4113
4118 This command tries to fix the repository status after an
4114 This command tries to fix the repository status after an
4119 interrupted operation. It should only be necessary when Mercurial
4115 interrupted operation. It should only be necessary when Mercurial
4120 suggests it.
4116 suggests it.
4121
4117
4122 Returns 0 if successful, 1 if nothing to recover or verify fails.
4118 Returns 0 if successful, 1 if nothing to recover or verify fails.
4123 """
4119 """
4124 if repo.recover():
4120 if repo.recover():
4125 return hg.verify(repo)
4121 return hg.verify(repo)
4126 return 1
4122 return 1
4127
4123
4128 @command('^remove|rm',
4124 @command('^remove|rm',
4129 [('A', 'after', None, _('record delete for missing files')),
4125 [('A', 'after', None, _('record delete for missing files')),
4130 ('f', 'force', None,
4126 ('f', 'force', None,
4131 _('remove (and delete) file even if added or modified')),
4127 _('remove (and delete) file even if added or modified')),
4132 ] + walkopts,
4128 ] + walkopts,
4133 _('[OPTION]... FILE...'))
4129 _('[OPTION]... FILE...'))
4134 def remove(ui, repo, *pats, **opts):
4130 def remove(ui, repo, *pats, **opts):
4135 """remove the specified files on the next commit
4131 """remove the specified files on the next commit
4136
4132
4137 Schedule the indicated files for removal from the current branch.
4133 Schedule the indicated files for removal from the current branch.
4138
4134
4139 This command schedules the files to be removed at the next commit.
4135 This command schedules the files to be removed at the next commit.
4140 To undo a remove before that, see :hg:`revert`. To undo added
4136 To undo a remove before that, see :hg:`revert`. To undo added
4141 files, see :hg:`forget`.
4137 files, see :hg:`forget`.
4142
4138
4143 .. container:: verbose
4139 .. container:: verbose
4144
4140
4145 -A/--after can be used to remove only files that have already
4141 -A/--after can be used to remove only files that have already
4146 been deleted, -f/--force can be used to force deletion, and -Af
4142 been deleted, -f/--force can be used to force deletion, and -Af
4147 can be used to remove files from the next revision without
4143 can be used to remove files from the next revision without
4148 deleting them from the working directory.
4144 deleting them from the working directory.
4149
4145
4150 The following table details the behavior of remove for different
4146 The following table details the behavior of remove for different
4151 file states (columns) and option combinations (rows). The file
4147 file states (columns) and option combinations (rows). The file
4152 states are Added [A], Clean [C], Modified [M] and Missing [!]
4148 states are Added [A], Clean [C], Modified [M] and Missing [!]
4153 (as reported by :hg:`status`). The actions are Warn, Remove
4149 (as reported by :hg:`status`). The actions are Warn, Remove
4154 (from branch) and Delete (from disk):
4150 (from branch) and Delete (from disk):
4155
4151
4156 ======= == == == ==
4152 ======= == == == ==
4157 A C M !
4153 A C M !
4158 ======= == == == ==
4154 ======= == == == ==
4159 none W RD W R
4155 none W RD W R
4160 -f R RD RD R
4156 -f R RD RD R
4161 -A W W W R
4157 -A W W W R
4162 -Af R R R R
4158 -Af R R R R
4163 ======= == == == ==
4159 ======= == == == ==
4164
4160
4165 Note that remove never deletes files in Added [A] state from the
4161 Note that remove never deletes files in Added [A] state from the
4166 working directory, not even if option --force is specified.
4162 working directory, not even if option --force is specified.
4167
4163
4168 Returns 0 on success, 1 if any warnings encountered.
4164 Returns 0 on success, 1 if any warnings encountered.
4169 """
4165 """
4170
4166
4171 ret = 0
4167 ret = 0
4172 after, force = opts.get('after'), opts.get('force')
4168 after, force = opts.get('after'), opts.get('force')
4173 if not pats and not after:
4169 if not pats and not after:
4174 raise util.Abort(_('no files specified'))
4170 raise util.Abort(_('no files specified'))
4175
4171
4176 m = scmutil.match(repo[None], pats, opts)
4172 m = scmutil.match(repo[None], pats, opts)
4177 s = repo.status(match=m, clean=True)
4173 s = repo.status(match=m, clean=True)
4178 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4174 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4179
4175
4180 for f in m.files():
4176 for f in m.files():
4181 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4177 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4182 if os.path.exists(m.rel(f)):
4178 if os.path.exists(m.rel(f)):
4183 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4179 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4184 ret = 1
4180 ret = 1
4185
4181
4186 if force:
4182 if force:
4187 list = modified + deleted + clean + added
4183 list = modified + deleted + clean + added
4188 elif after:
4184 elif after:
4189 list = deleted
4185 list = deleted
4190 for f in modified + added + clean:
4186 for f in modified + added + clean:
4191 ui.warn(_('not removing %s: file still exists (use -f'
4187 ui.warn(_('not removing %s: file still exists (use -f'
4192 ' to force removal)\n') % m.rel(f))
4188 ' to force removal)\n') % m.rel(f))
4193 ret = 1
4189 ret = 1
4194 else:
4190 else:
4195 list = deleted + clean
4191 list = deleted + clean
4196 for f in modified:
4192 for f in modified:
4197 ui.warn(_('not removing %s: file is modified (use -f'
4193 ui.warn(_('not removing %s: file is modified (use -f'
4198 ' to force removal)\n') % m.rel(f))
4194 ' to force removal)\n') % m.rel(f))
4199 ret = 1
4195 ret = 1
4200 for f in added:
4196 for f in added:
4201 ui.warn(_('not removing %s: file has been marked for add'
4197 ui.warn(_('not removing %s: file has been marked for add'
4202 ' (use forget to undo)\n') % m.rel(f))
4198 ' (use forget to undo)\n') % m.rel(f))
4203 ret = 1
4199 ret = 1
4204
4200
4205 for f in sorted(list):
4201 for f in sorted(list):
4206 if ui.verbose or not m.exact(f):
4202 if ui.verbose or not m.exact(f):
4207 ui.status(_('removing %s\n') % m.rel(f))
4203 ui.status(_('removing %s\n') % m.rel(f))
4208
4204
4209 wlock = repo.wlock()
4205 wlock = repo.wlock()
4210 try:
4206 try:
4211 if not after:
4207 if not after:
4212 for f in list:
4208 for f in list:
4213 if f in added:
4209 if f in added:
4214 continue # we never unlink added files on remove
4210 continue # we never unlink added files on remove
4215 try:
4211 try:
4216 util.unlinkpath(repo.wjoin(f))
4212 util.unlinkpath(repo.wjoin(f))
4217 except OSError, inst:
4213 except OSError, inst:
4218 if inst.errno != errno.ENOENT:
4214 if inst.errno != errno.ENOENT:
4219 raise
4215 raise
4220 repo[None].forget(list)
4216 repo[None].forget(list)
4221 finally:
4217 finally:
4222 wlock.release()
4218 wlock.release()
4223
4219
4224 return ret
4220 return ret
4225
4221
4226 @command('rename|move|mv',
4222 @command('rename|move|mv',
4227 [('A', 'after', None, _('record a rename that has already occurred')),
4223 [('A', 'after', None, _('record a rename that has already occurred')),
4228 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4224 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4229 ] + walkopts + dryrunopts,
4225 ] + walkopts + dryrunopts,
4230 _('[OPTION]... SOURCE... DEST'))
4226 _('[OPTION]... SOURCE... DEST'))
4231 def rename(ui, repo, *pats, **opts):
4227 def rename(ui, repo, *pats, **opts):
4232 """rename files; equivalent of copy + remove
4228 """rename files; equivalent of copy + remove
4233
4229
4234 Mark dest as copies of sources; mark sources for deletion. If dest
4230 Mark dest as copies of sources; mark sources for deletion. If dest
4235 is a directory, copies are put in that directory. If dest is a
4231 is a directory, copies are put in that directory. If dest is a
4236 file, there can only be one source.
4232 file, there can only be one source.
4237
4233
4238 By default, this command copies the contents of files as they
4234 By default, this command copies the contents of files as they
4239 exist in the working directory. If invoked with -A/--after, the
4235 exist in the working directory. If invoked with -A/--after, the
4240 operation is recorded, but no copying is performed.
4236 operation is recorded, but no copying is performed.
4241
4237
4242 This command takes effect at the next commit. To undo a rename
4238 This command takes effect at the next commit. To undo a rename
4243 before that, see :hg:`revert`.
4239 before that, see :hg:`revert`.
4244
4240
4245 Returns 0 on success, 1 if errors are encountered.
4241 Returns 0 on success, 1 if errors are encountered.
4246 """
4242 """
4247 wlock = repo.wlock(False)
4243 wlock = repo.wlock(False)
4248 try:
4244 try:
4249 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4245 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4250 finally:
4246 finally:
4251 wlock.release()
4247 wlock.release()
4252
4248
4253 @command('resolve',
4249 @command('resolve',
4254 [('a', 'all', None, _('select all unresolved files')),
4250 [('a', 'all', None, _('select all unresolved files')),
4255 ('l', 'list', None, _('list state of files needing merge')),
4251 ('l', 'list', None, _('list state of files needing merge')),
4256 ('m', 'mark', None, _('mark files as resolved')),
4252 ('m', 'mark', None, _('mark files as resolved')),
4257 ('u', 'unmark', None, _('mark files as unresolved')),
4253 ('u', 'unmark', None, _('mark files as unresolved')),
4258 ('n', 'no-status', None, _('hide status prefix'))]
4254 ('n', 'no-status', None, _('hide status prefix'))]
4259 + mergetoolopts + walkopts,
4255 + mergetoolopts + walkopts,
4260 _('[OPTION]... [FILE]...'))
4256 _('[OPTION]... [FILE]...'))
4261 def resolve(ui, repo, *pats, **opts):
4257 def resolve(ui, repo, *pats, **opts):
4262 """redo merges or set/view the merge status of files
4258 """redo merges or set/view the merge status of files
4263
4259
4264 Merges with unresolved conflicts are often the result of
4260 Merges with unresolved conflicts are often the result of
4265 non-interactive merging using the ``internal:merge`` configuration
4261 non-interactive merging using the ``internal:merge`` configuration
4266 setting, or a command-line merge tool like ``diff3``. The resolve
4262 setting, or a command-line merge tool like ``diff3``. The resolve
4267 command is used to manage the files involved in a merge, after
4263 command is used to manage the files involved in a merge, after
4268 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4264 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4269 working directory must have two parents).
4265 working directory must have two parents).
4270
4266
4271 The resolve command can be used in the following ways:
4267 The resolve command can be used in the following ways:
4272
4268
4273 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4269 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4274 files, discarding any previous merge attempts. Re-merging is not
4270 files, discarding any previous merge attempts. Re-merging is not
4275 performed for files already marked as resolved. Use ``--all/-a``
4271 performed for files already marked as resolved. Use ``--all/-a``
4276 to select all unresolved files. ``--tool`` can be used to specify
4272 to select all unresolved files. ``--tool`` can be used to specify
4277 the merge tool used for the given files. It overrides the HGMERGE
4273 the merge tool used for the given files. It overrides the HGMERGE
4278 environment variable and your configuration files.
4274 environment variable and your configuration files.
4279
4275
4280 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4276 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4281 (e.g. after having manually fixed-up the files). The default is
4277 (e.g. after having manually fixed-up the files). The default is
4282 to mark all unresolved files.
4278 to mark all unresolved files.
4283
4279
4284 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4280 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4285 default is to mark all resolved files.
4281 default is to mark all resolved files.
4286
4282
4287 - :hg:`resolve -l`: list files which had or still have conflicts.
4283 - :hg:`resolve -l`: list files which had or still have conflicts.
4288 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4284 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4289
4285
4290 Note that Mercurial will not let you commit files with unresolved
4286 Note that Mercurial will not let you commit files with unresolved
4291 merge conflicts. You must use :hg:`resolve -m ...` before you can
4287 merge conflicts. You must use :hg:`resolve -m ...` before you can
4292 commit after a conflicting merge.
4288 commit after a conflicting merge.
4293
4289
4294 Returns 0 on success, 1 if any files fail a resolve attempt.
4290 Returns 0 on success, 1 if any files fail a resolve attempt.
4295 """
4291 """
4296
4292
4297 all, mark, unmark, show, nostatus = \
4293 all, mark, unmark, show, nostatus = \
4298 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4294 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4299
4295
4300 if (show and (mark or unmark)) or (mark and unmark):
4296 if (show and (mark or unmark)) or (mark and unmark):
4301 raise util.Abort(_("too many options specified"))
4297 raise util.Abort(_("too many options specified"))
4302 if pats and all:
4298 if pats and all:
4303 raise util.Abort(_("can't specify --all and patterns"))
4299 raise util.Abort(_("can't specify --all and patterns"))
4304 if not (all or pats or show or mark or unmark):
4300 if not (all or pats or show or mark or unmark):
4305 raise util.Abort(_('no files or directories specified; '
4301 raise util.Abort(_('no files or directories specified; '
4306 'use --all to remerge all files'))
4302 'use --all to remerge all files'))
4307
4303
4308 ms = mergemod.mergestate(repo)
4304 ms = mergemod.mergestate(repo)
4309 m = scmutil.match(repo[None], pats, opts)
4305 m = scmutil.match(repo[None], pats, opts)
4310 ret = 0
4306 ret = 0
4311
4307
4312 for f in ms:
4308 for f in ms:
4313 if m(f):
4309 if m(f):
4314 if show:
4310 if show:
4315 if nostatus:
4311 if nostatus:
4316 ui.write("%s\n" % f)
4312 ui.write("%s\n" % f)
4317 else:
4313 else:
4318 ui.write("%s %s\n" % (ms[f].upper(), f),
4314 ui.write("%s %s\n" % (ms[f].upper(), f),
4319 label='resolve.' +
4315 label='resolve.' +
4320 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4316 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4321 elif mark:
4317 elif mark:
4322 ms.mark(f, "r")
4318 ms.mark(f, "r")
4323 elif unmark:
4319 elif unmark:
4324 ms.mark(f, "u")
4320 ms.mark(f, "u")
4325 else:
4321 else:
4326 wctx = repo[None]
4322 wctx = repo[None]
4327 mctx = wctx.parents()[-1]
4323 mctx = wctx.parents()[-1]
4328
4324
4329 # backup pre-resolve (merge uses .orig for its own purposes)
4325 # backup pre-resolve (merge uses .orig for its own purposes)
4330 a = repo.wjoin(f)
4326 a = repo.wjoin(f)
4331 util.copyfile(a, a + ".resolve")
4327 util.copyfile(a, a + ".resolve")
4332
4328
4333 try:
4329 try:
4334 # resolve file
4330 # resolve file
4335 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4331 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4336 if ms.resolve(f, wctx, mctx):
4332 if ms.resolve(f, wctx, mctx):
4337 ret = 1
4333 ret = 1
4338 finally:
4334 finally:
4339 ui.setconfig('ui', 'forcemerge', '')
4335 ui.setconfig('ui', 'forcemerge', '')
4340
4336
4341 # replace filemerge's .orig file with our resolve file
4337 # replace filemerge's .orig file with our resolve file
4342 util.rename(a + ".resolve", a + ".orig")
4338 util.rename(a + ".resolve", a + ".orig")
4343
4339
4344 ms.commit()
4340 ms.commit()
4345 return ret
4341 return ret
4346
4342
4347 @command('revert',
4343 @command('revert',
4348 [('a', 'all', None, _('revert all changes when no arguments given')),
4344 [('a', 'all', None, _('revert all changes when no arguments given')),
4349 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4345 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4350 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4346 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4351 ('C', 'no-backup', None, _('do not save backup copies of files')),
4347 ('C', 'no-backup', None, _('do not save backup copies of files')),
4352 ] + walkopts + dryrunopts,
4348 ] + walkopts + dryrunopts,
4353 _('[OPTION]... [-r REV] [NAME]...'))
4349 _('[OPTION]... [-r REV] [NAME]...'))
4354 def revert(ui, repo, *pats, **opts):
4350 def revert(ui, repo, *pats, **opts):
4355 """restore files to their checkout state
4351 """restore files to their checkout state
4356
4352
4357 .. note::
4353 .. note::
4358 To check out earlier revisions, you should use :hg:`update REV`.
4354 To check out earlier revisions, you should use :hg:`update REV`.
4359 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4355 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4360
4356
4361 With no revision specified, revert the specified files or directories
4357 With no revision specified, revert the specified files or directories
4362 to the contents they had in the parent of the working directory.
4358 to the contents they had in the parent of the working directory.
4363 This restores the contents of files to an unmodified
4359 This restores the contents of files to an unmodified
4364 state and unschedules adds, removes, copies, and renames. If the
4360 state and unschedules adds, removes, copies, and renames. If the
4365 working directory has two parents, you must explicitly specify a
4361 working directory has two parents, you must explicitly specify a
4366 revision.
4362 revision.
4367
4363
4368 Using the -r/--rev or -d/--date options, revert the given files or
4364 Using the -r/--rev or -d/--date options, revert the given files or
4369 directories to their states as of a specific revision. Because
4365 directories to their states as of a specific revision. Because
4370 revert does not change the working directory parents, this will
4366 revert does not change the working directory parents, this will
4371 cause these files to appear modified. This can be helpful to "back
4367 cause these files to appear modified. This can be helpful to "back
4372 out" some or all of an earlier change. See :hg:`backout` for a
4368 out" some or all of an earlier change. See :hg:`backout` for a
4373 related method.
4369 related method.
4374
4370
4375 Modified files are saved with a .orig suffix before reverting.
4371 Modified files are saved with a .orig suffix before reverting.
4376 To disable these backups, use --no-backup.
4372 To disable these backups, use --no-backup.
4377
4373
4378 See :hg:`help dates` for a list of formats valid for -d/--date.
4374 See :hg:`help dates` for a list of formats valid for -d/--date.
4379
4375
4380 Returns 0 on success.
4376 Returns 0 on success.
4381 """
4377 """
4382
4378
4383 if opts.get("date"):
4379 if opts.get("date"):
4384 if opts.get("rev"):
4380 if opts.get("rev"):
4385 raise util.Abort(_("you can't specify a revision and a date"))
4381 raise util.Abort(_("you can't specify a revision and a date"))
4386 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4382 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4387
4383
4388 parent, p2 = repo.dirstate.parents()
4384 parent, p2 = repo.dirstate.parents()
4389 if not opts.get('rev') and p2 != nullid:
4385 if not opts.get('rev') and p2 != nullid:
4390 # revert after merge is a trap for new users (issue2915)
4386 # revert after merge is a trap for new users (issue2915)
4391 raise util.Abort(_('uncommitted merge with no revision specified'),
4387 raise util.Abort(_('uncommitted merge with no revision specified'),
4392 hint=_('use "hg update" or see "hg help revert"'))
4388 hint=_('use "hg update" or see "hg help revert"'))
4393
4389
4394 ctx = scmutil.revsingle(repo, opts.get('rev'))
4390 ctx = scmutil.revsingle(repo, opts.get('rev'))
4395 node = ctx.node()
4391 node = ctx.node()
4396
4392
4397 if not pats and not opts.get('all'):
4393 if not pats and not opts.get('all'):
4398 msg = _("no files or directories specified")
4394 msg = _("no files or directories specified")
4399 if p2 != nullid:
4395 if p2 != nullid:
4400 hint = _("uncommitted merge, use --all to discard all changes,"
4396 hint = _("uncommitted merge, use --all to discard all changes,"
4401 " or 'hg update -C .' to abort the merge")
4397 " or 'hg update -C .' to abort the merge")
4402 raise util.Abort(msg, hint=hint)
4398 raise util.Abort(msg, hint=hint)
4403 dirty = util.any(repo.status())
4399 dirty = util.any(repo.status())
4404 if node != parent:
4400 if node != parent:
4405 if dirty:
4401 if dirty:
4406 hint = _("uncommitted changes, use --all to discard all"
4402 hint = _("uncommitted changes, use --all to discard all"
4407 " changes, or 'hg update %s' to update") % ctx.rev()
4403 " changes, or 'hg update %s' to update") % ctx.rev()
4408 else:
4404 else:
4409 hint = _("use --all to revert all files,"
4405 hint = _("use --all to revert all files,"
4410 " or 'hg update %s' to update") % ctx.rev()
4406 " or 'hg update %s' to update") % ctx.rev()
4411 elif dirty:
4407 elif dirty:
4412 hint = _("uncommitted changes, use --all to discard all changes")
4408 hint = _("uncommitted changes, use --all to discard all changes")
4413 else:
4409 else:
4414 hint = _("use --all to revert all files")
4410 hint = _("use --all to revert all files")
4415 raise util.Abort(msg, hint=hint)
4411 raise util.Abort(msg, hint=hint)
4416
4412
4417 mf = ctx.manifest()
4413 mf = ctx.manifest()
4418 if node == parent:
4414 if node == parent:
4419 pmf = mf
4415 pmf = mf
4420 else:
4416 else:
4421 pmf = None
4417 pmf = None
4422
4418
4423 # need all matching names in dirstate and manifest of target rev,
4419 # need all matching names in dirstate and manifest of target rev,
4424 # so have to walk both. do not print errors if files exist in one
4420 # so have to walk both. do not print errors if files exist in one
4425 # but not other.
4421 # but not other.
4426
4422
4427 names = {}
4423 names = {}
4428
4424
4429 wlock = repo.wlock()
4425 wlock = repo.wlock()
4430 try:
4426 try:
4431 # walk dirstate.
4427 # walk dirstate.
4432
4428
4433 m = scmutil.match(repo[None], pats, opts)
4429 m = scmutil.match(repo[None], pats, opts)
4434 m.bad = lambda x, y: False
4430 m.bad = lambda x, y: False
4435 for abs in repo.walk(m):
4431 for abs in repo.walk(m):
4436 names[abs] = m.rel(abs), m.exact(abs)
4432 names[abs] = m.rel(abs), m.exact(abs)
4437
4433
4438 # walk target manifest.
4434 # walk target manifest.
4439
4435
4440 def badfn(path, msg):
4436 def badfn(path, msg):
4441 if path in names:
4437 if path in names:
4442 return
4438 return
4443 path_ = path + '/'
4439 path_ = path + '/'
4444 for f in names:
4440 for f in names:
4445 if f.startswith(path_):
4441 if f.startswith(path_):
4446 return
4442 return
4447 ui.warn("%s: %s\n" % (m.rel(path), msg))
4443 ui.warn("%s: %s\n" % (m.rel(path), msg))
4448
4444
4449 m = scmutil.match(repo[node], pats, opts)
4445 m = scmutil.match(repo[node], pats, opts)
4450 m.bad = badfn
4446 m.bad = badfn
4451 for abs in repo[node].walk(m):
4447 for abs in repo[node].walk(m):
4452 if abs not in names:
4448 if abs not in names:
4453 names[abs] = m.rel(abs), m.exact(abs)
4449 names[abs] = m.rel(abs), m.exact(abs)
4454
4450
4455 m = scmutil.matchfiles(repo, names)
4451 m = scmutil.matchfiles(repo, names)
4456 changes = repo.status(match=m)[:4]
4452 changes = repo.status(match=m)[:4]
4457 modified, added, removed, deleted = map(set, changes)
4453 modified, added, removed, deleted = map(set, changes)
4458
4454
4459 # if f is a rename, also revert the source
4455 # if f is a rename, also revert the source
4460 cwd = repo.getcwd()
4456 cwd = repo.getcwd()
4461 for f in added:
4457 for f in added:
4462 src = repo.dirstate.copied(f)
4458 src = repo.dirstate.copied(f)
4463 if src and src not in names and repo.dirstate[src] == 'r':
4459 if src and src not in names and repo.dirstate[src] == 'r':
4464 removed.add(src)
4460 removed.add(src)
4465 names[src] = (repo.pathto(src, cwd), True)
4461 names[src] = (repo.pathto(src, cwd), True)
4466
4462
4467 def removeforget(abs):
4463 def removeforget(abs):
4468 if repo.dirstate[abs] == 'a':
4464 if repo.dirstate[abs] == 'a':
4469 return _('forgetting %s\n')
4465 return _('forgetting %s\n')
4470 return _('removing %s\n')
4466 return _('removing %s\n')
4471
4467
4472 revert = ([], _('reverting %s\n'))
4468 revert = ([], _('reverting %s\n'))
4473 add = ([], _('adding %s\n'))
4469 add = ([], _('adding %s\n'))
4474 remove = ([], removeforget)
4470 remove = ([], removeforget)
4475 undelete = ([], _('undeleting %s\n'))
4471 undelete = ([], _('undeleting %s\n'))
4476
4472
4477 disptable = (
4473 disptable = (
4478 # dispatch table:
4474 # dispatch table:
4479 # file state
4475 # file state
4480 # action if in target manifest
4476 # action if in target manifest
4481 # action if not in target manifest
4477 # action if not in target manifest
4482 # make backup if in target manifest
4478 # make backup if in target manifest
4483 # make backup if not in target manifest
4479 # make backup if not in target manifest
4484 (modified, revert, remove, True, True),
4480 (modified, revert, remove, True, True),
4485 (added, revert, remove, True, False),
4481 (added, revert, remove, True, False),
4486 (removed, undelete, None, False, False),
4482 (removed, undelete, None, False, False),
4487 (deleted, revert, remove, False, False),
4483 (deleted, revert, remove, False, False),
4488 )
4484 )
4489
4485
4490 for abs, (rel, exact) in sorted(names.items()):
4486 for abs, (rel, exact) in sorted(names.items()):
4491 mfentry = mf.get(abs)
4487 mfentry = mf.get(abs)
4492 target = repo.wjoin(abs)
4488 target = repo.wjoin(abs)
4493 def handle(xlist, dobackup):
4489 def handle(xlist, dobackup):
4494 xlist[0].append(abs)
4490 xlist[0].append(abs)
4495 if (dobackup and not opts.get('no_backup') and
4491 if (dobackup and not opts.get('no_backup') and
4496 os.path.lexists(target)):
4492 os.path.lexists(target)):
4497 bakname = "%s.orig" % rel
4493 bakname = "%s.orig" % rel
4498 ui.note(_('saving current version of %s as %s\n') %
4494 ui.note(_('saving current version of %s as %s\n') %
4499 (rel, bakname))
4495 (rel, bakname))
4500 if not opts.get('dry_run'):
4496 if not opts.get('dry_run'):
4501 util.rename(target, bakname)
4497 util.rename(target, bakname)
4502 if ui.verbose or not exact:
4498 if ui.verbose or not exact:
4503 msg = xlist[1]
4499 msg = xlist[1]
4504 if not isinstance(msg, basestring):
4500 if not isinstance(msg, basestring):
4505 msg = msg(abs)
4501 msg = msg(abs)
4506 ui.status(msg % rel)
4502 ui.status(msg % rel)
4507 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4503 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4508 if abs not in table:
4504 if abs not in table:
4509 continue
4505 continue
4510 # file has changed in dirstate
4506 # file has changed in dirstate
4511 if mfentry:
4507 if mfentry:
4512 handle(hitlist, backuphit)
4508 handle(hitlist, backuphit)
4513 elif misslist is not None:
4509 elif misslist is not None:
4514 handle(misslist, backupmiss)
4510 handle(misslist, backupmiss)
4515 break
4511 break
4516 else:
4512 else:
4517 if abs not in repo.dirstate:
4513 if abs not in repo.dirstate:
4518 if mfentry:
4514 if mfentry:
4519 handle(add, True)
4515 handle(add, True)
4520 elif exact:
4516 elif exact:
4521 ui.warn(_('file not managed: %s\n') % rel)
4517 ui.warn(_('file not managed: %s\n') % rel)
4522 continue
4518 continue
4523 # file has not changed in dirstate
4519 # file has not changed in dirstate
4524 if node == parent:
4520 if node == parent:
4525 if exact:
4521 if exact:
4526 ui.warn(_('no changes needed to %s\n') % rel)
4522 ui.warn(_('no changes needed to %s\n') % rel)
4527 continue
4523 continue
4528 if pmf is None:
4524 if pmf is None:
4529 # only need parent manifest in this unlikely case,
4525 # only need parent manifest in this unlikely case,
4530 # so do not read by default
4526 # so do not read by default
4531 pmf = repo[parent].manifest()
4527 pmf = repo[parent].manifest()
4532 if abs in pmf:
4528 if abs in pmf:
4533 if mfentry:
4529 if mfentry:
4534 # if version of file is same in parent and target
4530 # if version of file is same in parent and target
4535 # manifests, do nothing
4531 # manifests, do nothing
4536 if (pmf[abs] != mfentry or
4532 if (pmf[abs] != mfentry or
4537 pmf.flags(abs) != mf.flags(abs)):
4533 pmf.flags(abs) != mf.flags(abs)):
4538 handle(revert, False)
4534 handle(revert, False)
4539 else:
4535 else:
4540 handle(remove, False)
4536 handle(remove, False)
4541
4537
4542 if not opts.get('dry_run'):
4538 if not opts.get('dry_run'):
4543 def checkout(f):
4539 def checkout(f):
4544 fc = ctx[f]
4540 fc = ctx[f]
4545 repo.wwrite(f, fc.data(), fc.flags())
4541 repo.wwrite(f, fc.data(), fc.flags())
4546
4542
4547 audit_path = scmutil.pathauditor(repo.root)
4543 audit_path = scmutil.pathauditor(repo.root)
4548 for f in remove[0]:
4544 for f in remove[0]:
4549 if repo.dirstate[f] == 'a':
4545 if repo.dirstate[f] == 'a':
4550 repo.dirstate.drop(f)
4546 repo.dirstate.drop(f)
4551 continue
4547 continue
4552 audit_path(f)
4548 audit_path(f)
4553 try:
4549 try:
4554 util.unlinkpath(repo.wjoin(f))
4550 util.unlinkpath(repo.wjoin(f))
4555 except OSError:
4551 except OSError:
4556 pass
4552 pass
4557 repo.dirstate.remove(f)
4553 repo.dirstate.remove(f)
4558
4554
4559 normal = None
4555 normal = None
4560 if node == parent:
4556 if node == parent:
4561 # We're reverting to our parent. If possible, we'd like status
4557 # We're reverting to our parent. If possible, we'd like status
4562 # to report the file as clean. We have to use normallookup for
4558 # to report the file as clean. We have to use normallookup for
4563 # merges to avoid losing information about merged/dirty files.
4559 # merges to avoid losing information about merged/dirty files.
4564 if p2 != nullid:
4560 if p2 != nullid:
4565 normal = repo.dirstate.normallookup
4561 normal = repo.dirstate.normallookup
4566 else:
4562 else:
4567 normal = repo.dirstate.normal
4563 normal = repo.dirstate.normal
4568 for f in revert[0]:
4564 for f in revert[0]:
4569 checkout(f)
4565 checkout(f)
4570 if normal:
4566 if normal:
4571 normal(f)
4567 normal(f)
4572
4568
4573 for f in add[0]:
4569 for f in add[0]:
4574 checkout(f)
4570 checkout(f)
4575 repo.dirstate.add(f)
4571 repo.dirstate.add(f)
4576
4572
4577 normal = repo.dirstate.normallookup
4573 normal = repo.dirstate.normallookup
4578 if node == parent and p2 == nullid:
4574 if node == parent and p2 == nullid:
4579 normal = repo.dirstate.normal
4575 normal = repo.dirstate.normal
4580 for f in undelete[0]:
4576 for f in undelete[0]:
4581 checkout(f)
4577 checkout(f)
4582 normal(f)
4578 normal(f)
4583
4579
4584 finally:
4580 finally:
4585 wlock.release()
4581 wlock.release()
4586
4582
4587 @command('rollback', dryrunopts)
4583 @command('rollback', dryrunopts)
4588 def rollback(ui, repo, **opts):
4584 def rollback(ui, repo, **opts):
4589 """roll back the last transaction (dangerous)
4585 """roll back the last transaction (dangerous)
4590
4586
4591 This command should be used with care. There is only one level of
4587 This command should be used with care. There is only one level of
4592 rollback, and there is no way to undo a rollback. It will also
4588 rollback, and there is no way to undo a rollback. It will also
4593 restore the dirstate at the time of the last transaction, losing
4589 restore the dirstate at the time of the last transaction, losing
4594 any dirstate changes since that time. This command does not alter
4590 any dirstate changes since that time. This command does not alter
4595 the working directory.
4591 the working directory.
4596
4592
4597 Transactions are used to encapsulate the effects of all commands
4593 Transactions are used to encapsulate the effects of all commands
4598 that create new changesets or propagate existing changesets into a
4594 that create new changesets or propagate existing changesets into a
4599 repository. For example, the following commands are transactional,
4595 repository. For example, the following commands are transactional,
4600 and their effects can be rolled back:
4596 and their effects can be rolled back:
4601
4597
4602 - commit
4598 - commit
4603 - import
4599 - import
4604 - pull
4600 - pull
4605 - push (with this repository as the destination)
4601 - push (with this repository as the destination)
4606 - unbundle
4602 - unbundle
4607
4603
4608 This command is not intended for use on public repositories. Once
4604 This command is not intended for use on public repositories. Once
4609 changes are visible for pull by other users, rolling a transaction
4605 changes are visible for pull by other users, rolling a transaction
4610 back locally is ineffective (someone else may already have pulled
4606 back locally is ineffective (someone else may already have pulled
4611 the changes). Furthermore, a race is possible with readers of the
4607 the changes). Furthermore, a race is possible with readers of the
4612 repository; for example an in-progress pull from the repository
4608 repository; for example an in-progress pull from the repository
4613 may fail if a rollback is performed.
4609 may fail if a rollback is performed.
4614
4610
4615 Returns 0 on success, 1 if no rollback data is available.
4611 Returns 0 on success, 1 if no rollback data is available.
4616 """
4612 """
4617 return repo.rollback(opts.get('dry_run'))
4613 return repo.rollback(opts.get('dry_run'))
4618
4614
4619 @command('root', [])
4615 @command('root', [])
4620 def root(ui, repo):
4616 def root(ui, repo):
4621 """print the root (top) of the current working directory
4617 """print the root (top) of the current working directory
4622
4618
4623 Print the root directory of the current repository.
4619 Print the root directory of the current repository.
4624
4620
4625 Returns 0 on success.
4621 Returns 0 on success.
4626 """
4622 """
4627 ui.write(repo.root + "\n")
4623 ui.write(repo.root + "\n")
4628
4624
4629 @command('^serve',
4625 @command('^serve',
4630 [('A', 'accesslog', '', _('name of access log file to write to'),
4626 [('A', 'accesslog', '', _('name of access log file to write to'),
4631 _('FILE')),
4627 _('FILE')),
4632 ('d', 'daemon', None, _('run server in background')),
4628 ('d', 'daemon', None, _('run server in background')),
4633 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4629 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4634 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4630 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4635 # use string type, then we can check if something was passed
4631 # use string type, then we can check if something was passed
4636 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4632 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4637 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4633 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4638 _('ADDR')),
4634 _('ADDR')),
4639 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4635 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4640 _('PREFIX')),
4636 _('PREFIX')),
4641 ('n', 'name', '',
4637 ('n', 'name', '',
4642 _('name to show in web pages (default: working directory)'), _('NAME')),
4638 _('name to show in web pages (default: working directory)'), _('NAME')),
4643 ('', 'web-conf', '',
4639 ('', 'web-conf', '',
4644 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4640 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4645 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4641 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4646 _('FILE')),
4642 _('FILE')),
4647 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4643 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4648 ('', 'stdio', None, _('for remote clients')),
4644 ('', 'stdio', None, _('for remote clients')),
4649 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4645 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4650 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4646 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4651 ('', 'style', '', _('template style to use'), _('STYLE')),
4647 ('', 'style', '', _('template style to use'), _('STYLE')),
4652 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4648 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4653 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4649 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4654 _('[OPTION]...'))
4650 _('[OPTION]...'))
4655 def serve(ui, repo, **opts):
4651 def serve(ui, repo, **opts):
4656 """start stand-alone webserver
4652 """start stand-alone webserver
4657
4653
4658 Start a local HTTP repository browser and pull server. You can use
4654 Start a local HTTP repository browser and pull server. You can use
4659 this for ad-hoc sharing and browsing of repositories. It is
4655 this for ad-hoc sharing and browsing of repositories. It is
4660 recommended to use a real web server to serve a repository for
4656 recommended to use a real web server to serve a repository for
4661 longer periods of time.
4657 longer periods of time.
4662
4658
4663 Please note that the server does not implement access control.
4659 Please note that the server does not implement access control.
4664 This means that, by default, anybody can read from the server and
4660 This means that, by default, anybody can read from the server and
4665 nobody can write to it by default. Set the ``web.allow_push``
4661 nobody can write to it by default. Set the ``web.allow_push``
4666 option to ``*`` to allow everybody to push to the server. You
4662 option to ``*`` to allow everybody to push to the server. You
4667 should use a real web server if you need to authenticate users.
4663 should use a real web server if you need to authenticate users.
4668
4664
4669 By default, the server logs accesses to stdout and errors to
4665 By default, the server logs accesses to stdout and errors to
4670 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4666 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4671 files.
4667 files.
4672
4668
4673 To have the server choose a free port number to listen on, specify
4669 To have the server choose a free port number to listen on, specify
4674 a port number of 0; in this case, the server will print the port
4670 a port number of 0; in this case, the server will print the port
4675 number it uses.
4671 number it uses.
4676
4672
4677 Returns 0 on success.
4673 Returns 0 on success.
4678 """
4674 """
4679
4675
4680 if opts["stdio"] and opts["cmdserver"]:
4676 if opts["stdio"] and opts["cmdserver"]:
4681 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4677 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4682
4678
4683 def checkrepo():
4679 def checkrepo():
4684 if repo is None:
4680 if repo is None:
4685 raise error.RepoError(_("There is no Mercurial repository here"
4681 raise error.RepoError(_("There is no Mercurial repository here"
4686 " (.hg not found)"))
4682 " (.hg not found)"))
4687
4683
4688 if opts["stdio"]:
4684 if opts["stdio"]:
4689 checkrepo()
4685 checkrepo()
4690 s = sshserver.sshserver(ui, repo)
4686 s = sshserver.sshserver(ui, repo)
4691 s.serve_forever()
4687 s.serve_forever()
4692
4688
4693 if opts["cmdserver"]:
4689 if opts["cmdserver"]:
4694 checkrepo()
4690 checkrepo()
4695 s = commandserver.server(ui, repo, opts["cmdserver"])
4691 s = commandserver.server(ui, repo, opts["cmdserver"])
4696 return s.serve()
4692 return s.serve()
4697
4693
4698 # this way we can check if something was given in the command-line
4694 # this way we can check if something was given in the command-line
4699 if opts.get('port'):
4695 if opts.get('port'):
4700 opts['port'] = util.getport(opts.get('port'))
4696 opts['port'] = util.getport(opts.get('port'))
4701
4697
4702 baseui = repo and repo.baseui or ui
4698 baseui = repo and repo.baseui or ui
4703 optlist = ("name templates style address port prefix ipv6"
4699 optlist = ("name templates style address port prefix ipv6"
4704 " accesslog errorlog certificate encoding")
4700 " accesslog errorlog certificate encoding")
4705 for o in optlist.split():
4701 for o in optlist.split():
4706 val = opts.get(o, '')
4702 val = opts.get(o, '')
4707 if val in (None, ''): # should check against default options instead
4703 if val in (None, ''): # should check against default options instead
4708 continue
4704 continue
4709 baseui.setconfig("web", o, val)
4705 baseui.setconfig("web", o, val)
4710 if repo and repo.ui != baseui:
4706 if repo and repo.ui != baseui:
4711 repo.ui.setconfig("web", o, val)
4707 repo.ui.setconfig("web", o, val)
4712
4708
4713 o = opts.get('web_conf') or opts.get('webdir_conf')
4709 o = opts.get('web_conf') or opts.get('webdir_conf')
4714 if not o:
4710 if not o:
4715 if not repo:
4711 if not repo:
4716 raise error.RepoError(_("There is no Mercurial repository"
4712 raise error.RepoError(_("There is no Mercurial repository"
4717 " here (.hg not found)"))
4713 " here (.hg not found)"))
4718 o = repo.root
4714 o = repo.root
4719
4715
4720 app = hgweb.hgweb(o, baseui=ui)
4716 app = hgweb.hgweb(o, baseui=ui)
4721
4717
4722 class service(object):
4718 class service(object):
4723 def init(self):
4719 def init(self):
4724 util.setsignalhandler()
4720 util.setsignalhandler()
4725 self.httpd = hgweb.server.create_server(ui, app)
4721 self.httpd = hgweb.server.create_server(ui, app)
4726
4722
4727 if opts['port'] and not ui.verbose:
4723 if opts['port'] and not ui.verbose:
4728 return
4724 return
4729
4725
4730 if self.httpd.prefix:
4726 if self.httpd.prefix:
4731 prefix = self.httpd.prefix.strip('/') + '/'
4727 prefix = self.httpd.prefix.strip('/') + '/'
4732 else:
4728 else:
4733 prefix = ''
4729 prefix = ''
4734
4730
4735 port = ':%d' % self.httpd.port
4731 port = ':%d' % self.httpd.port
4736 if port == ':80':
4732 if port == ':80':
4737 port = ''
4733 port = ''
4738
4734
4739 bindaddr = self.httpd.addr
4735 bindaddr = self.httpd.addr
4740 if bindaddr == '0.0.0.0':
4736 if bindaddr == '0.0.0.0':
4741 bindaddr = '*'
4737 bindaddr = '*'
4742 elif ':' in bindaddr: # IPv6
4738 elif ':' in bindaddr: # IPv6
4743 bindaddr = '[%s]' % bindaddr
4739 bindaddr = '[%s]' % bindaddr
4744
4740
4745 fqaddr = self.httpd.fqaddr
4741 fqaddr = self.httpd.fqaddr
4746 if ':' in fqaddr:
4742 if ':' in fqaddr:
4747 fqaddr = '[%s]' % fqaddr
4743 fqaddr = '[%s]' % fqaddr
4748 if opts['port']:
4744 if opts['port']:
4749 write = ui.status
4745 write = ui.status
4750 else:
4746 else:
4751 write = ui.write
4747 write = ui.write
4752 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4748 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4753 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4749 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4754
4750
4755 def run(self):
4751 def run(self):
4756 self.httpd.serve_forever()
4752 self.httpd.serve_forever()
4757
4753
4758 service = service()
4754 service = service()
4759
4755
4760 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4756 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4761
4757
4762 @command('showconfig|debugconfig',
4758 @command('showconfig|debugconfig',
4763 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4759 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4764 _('[-u] [NAME]...'))
4760 _('[-u] [NAME]...'))
4765 def showconfig(ui, repo, *values, **opts):
4761 def showconfig(ui, repo, *values, **opts):
4766 """show combined config settings from all hgrc files
4762 """show combined config settings from all hgrc files
4767
4763
4768 With no arguments, print names and values of all config items.
4764 With no arguments, print names and values of all config items.
4769
4765
4770 With one argument of the form section.name, print just the value
4766 With one argument of the form section.name, print just the value
4771 of that config item.
4767 of that config item.
4772
4768
4773 With multiple arguments, print names and values of all config
4769 With multiple arguments, print names and values of all config
4774 items with matching section names.
4770 items with matching section names.
4775
4771
4776 With --debug, the source (filename and line number) is printed
4772 With --debug, the source (filename and line number) is printed
4777 for each config item.
4773 for each config item.
4778
4774
4779 Returns 0 on success.
4775 Returns 0 on success.
4780 """
4776 """
4781
4777
4782 for f in scmutil.rcpath():
4778 for f in scmutil.rcpath():
4783 ui.debug('read config from: %s\n' % f)
4779 ui.debug('read config from: %s\n' % f)
4784 untrusted = bool(opts.get('untrusted'))
4780 untrusted = bool(opts.get('untrusted'))
4785 if values:
4781 if values:
4786 sections = [v for v in values if '.' not in v]
4782 sections = [v for v in values if '.' not in v]
4787 items = [v for v in values if '.' in v]
4783 items = [v for v in values if '.' in v]
4788 if len(items) > 1 or items and sections:
4784 if len(items) > 1 or items and sections:
4789 raise util.Abort(_('only one config item permitted'))
4785 raise util.Abort(_('only one config item permitted'))
4790 for section, name, value in ui.walkconfig(untrusted=untrusted):
4786 for section, name, value in ui.walkconfig(untrusted=untrusted):
4791 value = str(value).replace('\n', '\\n')
4787 value = str(value).replace('\n', '\\n')
4792 sectname = section + '.' + name
4788 sectname = section + '.' + name
4793 if values:
4789 if values:
4794 for v in values:
4790 for v in values:
4795 if v == section:
4791 if v == section:
4796 ui.debug('%s: ' %
4792 ui.debug('%s: ' %
4797 ui.configsource(section, name, untrusted))
4793 ui.configsource(section, name, untrusted))
4798 ui.write('%s=%s\n' % (sectname, value))
4794 ui.write('%s=%s\n' % (sectname, value))
4799 elif v == sectname:
4795 elif v == sectname:
4800 ui.debug('%s: ' %
4796 ui.debug('%s: ' %
4801 ui.configsource(section, name, untrusted))
4797 ui.configsource(section, name, untrusted))
4802 ui.write(value, '\n')
4798 ui.write(value, '\n')
4803 else:
4799 else:
4804 ui.debug('%s: ' %
4800 ui.debug('%s: ' %
4805 ui.configsource(section, name, untrusted))
4801 ui.configsource(section, name, untrusted))
4806 ui.write('%s=%s\n' % (sectname, value))
4802 ui.write('%s=%s\n' % (sectname, value))
4807
4803
4808 @command('^status|st',
4804 @command('^status|st',
4809 [('A', 'all', None, _('show status of all files')),
4805 [('A', 'all', None, _('show status of all files')),
4810 ('m', 'modified', None, _('show only modified files')),
4806 ('m', 'modified', None, _('show only modified files')),
4811 ('a', 'added', None, _('show only added files')),
4807 ('a', 'added', None, _('show only added files')),
4812 ('r', 'removed', None, _('show only removed files')),
4808 ('r', 'removed', None, _('show only removed files')),
4813 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4809 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4814 ('c', 'clean', None, _('show only files without changes')),
4810 ('c', 'clean', None, _('show only files without changes')),
4815 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4811 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4816 ('i', 'ignored', None, _('show only ignored files')),
4812 ('i', 'ignored', None, _('show only ignored files')),
4817 ('n', 'no-status', None, _('hide status prefix')),
4813 ('n', 'no-status', None, _('hide status prefix')),
4818 ('C', 'copies', None, _('show source of copied files')),
4814 ('C', 'copies', None, _('show source of copied files')),
4819 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4815 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4820 ('', 'rev', [], _('show difference from revision'), _('REV')),
4816 ('', 'rev', [], _('show difference from revision'), _('REV')),
4821 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4817 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4822 ] + walkopts + subrepoopts,
4818 ] + walkopts + subrepoopts,
4823 _('[OPTION]... [FILE]...'))
4819 _('[OPTION]... [FILE]...'))
4824 def status(ui, repo, *pats, **opts):
4820 def status(ui, repo, *pats, **opts):
4825 """show changed files in the working directory
4821 """show changed files in the working directory
4826
4822
4827 Show status of files in the repository. If names are given, only
4823 Show status of files in the repository. If names are given, only
4828 files that match are shown. Files that are clean or ignored or
4824 files that match are shown. Files that are clean or ignored or
4829 the source of a copy/move operation, are not listed unless
4825 the source of a copy/move operation, are not listed unless
4830 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4826 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4831 Unless options described with "show only ..." are given, the
4827 Unless options described with "show only ..." are given, the
4832 options -mardu are used.
4828 options -mardu are used.
4833
4829
4834 Option -q/--quiet hides untracked (unknown and ignored) files
4830 Option -q/--quiet hides untracked (unknown and ignored) files
4835 unless explicitly requested with -u/--unknown or -i/--ignored.
4831 unless explicitly requested with -u/--unknown or -i/--ignored.
4836
4832
4837 .. note::
4833 .. note::
4838 status may appear to disagree with diff if permissions have
4834 status may appear to disagree with diff if permissions have
4839 changed or a merge has occurred. The standard diff format does
4835 changed or a merge has occurred. The standard diff format does
4840 not report permission changes and diff only reports changes
4836 not report permission changes and diff only reports changes
4841 relative to one merge parent.
4837 relative to one merge parent.
4842
4838
4843 If one revision is given, it is used as the base revision.
4839 If one revision is given, it is used as the base revision.
4844 If two revisions are given, the differences between them are
4840 If two revisions are given, the differences between them are
4845 shown. The --change option can also be used as a shortcut to list
4841 shown. The --change option can also be used as a shortcut to list
4846 the changed files of a revision from its first parent.
4842 the changed files of a revision from its first parent.
4847
4843
4848 The codes used to show the status of files are::
4844 The codes used to show the status of files are::
4849
4845
4850 M = modified
4846 M = modified
4851 A = added
4847 A = added
4852 R = removed
4848 R = removed
4853 C = clean
4849 C = clean
4854 ! = missing (deleted by non-hg command, but still tracked)
4850 ! = missing (deleted by non-hg command, but still tracked)
4855 ? = not tracked
4851 ? = not tracked
4856 I = ignored
4852 I = ignored
4857 = origin of the previous file listed as A (added)
4853 = origin of the previous file listed as A (added)
4858
4854
4859 .. container:: verbose
4855 .. container:: verbose
4860
4856
4861 Examples:
4857 Examples:
4862
4858
4863 - show changes in the working directory relative to a changeset:
4859 - show changes in the working directory relative to a changeset:
4864
4860
4865 hg status --rev 9353
4861 hg status --rev 9353
4866
4862
4867 - show all changes including copies in an existing changeset::
4863 - show all changes including copies in an existing changeset::
4868
4864
4869 hg status --copies --change 9353
4865 hg status --copies --change 9353
4870
4866
4871 - get a NUL separated list of added files, suitable for xargs::
4867 - get a NUL separated list of added files, suitable for xargs::
4872
4868
4873 hg status -an0
4869 hg status -an0
4874
4870
4875 Returns 0 on success.
4871 Returns 0 on success.
4876 """
4872 """
4877
4873
4878 revs = opts.get('rev')
4874 revs = opts.get('rev')
4879 change = opts.get('change')
4875 change = opts.get('change')
4880
4876
4881 if revs and change:
4877 if revs and change:
4882 msg = _('cannot specify --rev and --change at the same time')
4878 msg = _('cannot specify --rev and --change at the same time')
4883 raise util.Abort(msg)
4879 raise util.Abort(msg)
4884 elif change:
4880 elif change:
4885 node2 = repo.lookup(change)
4881 node2 = repo.lookup(change)
4886 node1 = repo[node2].p1().node()
4882 node1 = repo[node2].p1().node()
4887 else:
4883 else:
4888 node1, node2 = scmutil.revpair(repo, revs)
4884 node1, node2 = scmutil.revpair(repo, revs)
4889
4885
4890 cwd = (pats and repo.getcwd()) or ''
4886 cwd = (pats and repo.getcwd()) or ''
4891 end = opts.get('print0') and '\0' or '\n'
4887 end = opts.get('print0') and '\0' or '\n'
4892 copy = {}
4888 copy = {}
4893 states = 'modified added removed deleted unknown ignored clean'.split()
4889 states = 'modified added removed deleted unknown ignored clean'.split()
4894 show = [k for k in states if opts.get(k)]
4890 show = [k for k in states if opts.get(k)]
4895 if opts.get('all'):
4891 if opts.get('all'):
4896 show += ui.quiet and (states[:4] + ['clean']) or states
4892 show += ui.quiet and (states[:4] + ['clean']) or states
4897 if not show:
4893 if not show:
4898 show = ui.quiet and states[:4] or states[:5]
4894 show = ui.quiet and states[:4] or states[:5]
4899
4895
4900 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4896 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4901 'ignored' in show, 'clean' in show, 'unknown' in show,
4897 'ignored' in show, 'clean' in show, 'unknown' in show,
4902 opts.get('subrepos'))
4898 opts.get('subrepos'))
4903 changestates = zip(states, 'MAR!?IC', stat)
4899 changestates = zip(states, 'MAR!?IC', stat)
4904
4900
4905 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4901 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4906 ctxn = repo[nullid]
4902 ctxn = repo[nullid]
4907 ctx1 = repo[node1]
4903 ctx1 = repo[node1]
4908 ctx2 = repo[node2]
4904 ctx2 = repo[node2]
4909 added = stat[1]
4905 added = stat[1]
4910 if node2 is None:
4906 if node2 is None:
4911 added = stat[0] + stat[1] # merged?
4907 added = stat[0] + stat[1] # merged?
4912
4908
4913 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4909 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4914 if k in added:
4910 if k in added:
4915 copy[k] = v
4911 copy[k] = v
4916 elif v in added:
4912 elif v in added:
4917 copy[v] = k
4913 copy[v] = k
4918
4914
4919 for state, char, files in changestates:
4915 for state, char, files in changestates:
4920 if state in show:
4916 if state in show:
4921 format = "%s %%s%s" % (char, end)
4917 format = "%s %%s%s" % (char, end)
4922 if opts.get('no_status'):
4918 if opts.get('no_status'):
4923 format = "%%s%s" % end
4919 format = "%%s%s" % end
4924
4920
4925 for f in files:
4921 for f in files:
4926 ui.write(format % repo.pathto(f, cwd),
4922 ui.write(format % repo.pathto(f, cwd),
4927 label='status.' + state)
4923 label='status.' + state)
4928 if f in copy:
4924 if f in copy:
4929 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4925 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4930 label='status.copied')
4926 label='status.copied')
4931
4927
4932 @command('^summary|sum',
4928 @command('^summary|sum',
4933 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4929 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4934 def summary(ui, repo, **opts):
4930 def summary(ui, repo, **opts):
4935 """summarize working directory state
4931 """summarize working directory state
4936
4932
4937 This generates a brief summary of the working directory state,
4933 This generates a brief summary of the working directory state,
4938 including parents, branch, commit status, and available updates.
4934 including parents, branch, commit status, and available updates.
4939
4935
4940 With the --remote option, this will check the default paths for
4936 With the --remote option, this will check the default paths for
4941 incoming and outgoing changes. This can be time-consuming.
4937 incoming and outgoing changes. This can be time-consuming.
4942
4938
4943 Returns 0 on success.
4939 Returns 0 on success.
4944 """
4940 """
4945
4941
4946 ctx = repo[None]
4942 ctx = repo[None]
4947 parents = ctx.parents()
4943 parents = ctx.parents()
4948 pnode = parents[0].node()
4944 pnode = parents[0].node()
4949 marks = []
4945 marks = []
4950
4946
4951 for p in parents:
4947 for p in parents:
4952 # label with log.changeset (instead of log.parent) since this
4948 # label with log.changeset (instead of log.parent) since this
4953 # shows a working directory parent *changeset*:
4949 # shows a working directory parent *changeset*:
4954 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4950 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4955 label='log.changeset')
4951 label='log.changeset')
4956 ui.write(' '.join(p.tags()), label='log.tag')
4952 ui.write(' '.join(p.tags()), label='log.tag')
4957 if p.bookmarks():
4953 if p.bookmarks():
4958 marks.extend(p.bookmarks())
4954 marks.extend(p.bookmarks())
4959 if p.rev() == -1:
4955 if p.rev() == -1:
4960 if not len(repo):
4956 if not len(repo):
4961 ui.write(_(' (empty repository)'))
4957 ui.write(_(' (empty repository)'))
4962 else:
4958 else:
4963 ui.write(_(' (no revision checked out)'))
4959 ui.write(_(' (no revision checked out)'))
4964 ui.write('\n')
4960 ui.write('\n')
4965 if p.description():
4961 if p.description():
4966 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4962 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4967 label='log.summary')
4963 label='log.summary')
4968
4964
4969 branch = ctx.branch()
4965 branch = ctx.branch()
4970 bheads = repo.branchheads(branch)
4966 bheads = repo.branchheads(branch)
4971 m = _('branch: %s\n') % branch
4967 m = _('branch: %s\n') % branch
4972 if branch != 'default':
4968 if branch != 'default':
4973 ui.write(m, label='log.branch')
4969 ui.write(m, label='log.branch')
4974 else:
4970 else:
4975 ui.status(m, label='log.branch')
4971 ui.status(m, label='log.branch')
4976
4972
4977 if marks:
4973 if marks:
4978 current = repo._bookmarkcurrent
4974 current = repo._bookmarkcurrent
4979 ui.write(_('bookmarks:'), label='log.bookmark')
4975 ui.write(_('bookmarks:'), label='log.bookmark')
4980 if current is not None:
4976 if current is not None:
4981 try:
4977 try:
4982 marks.remove(current)
4978 marks.remove(current)
4983 ui.write(' *' + current, label='bookmarks.current')
4979 ui.write(' *' + current, label='bookmarks.current')
4984 except ValueError:
4980 except ValueError:
4985 # current bookmark not in parent ctx marks
4981 # current bookmark not in parent ctx marks
4986 pass
4982 pass
4987 for m in marks:
4983 for m in marks:
4988 ui.write(' ' + m, label='log.bookmark')
4984 ui.write(' ' + m, label='log.bookmark')
4989 ui.write('\n', label='log.bookmark')
4985 ui.write('\n', label='log.bookmark')
4990
4986
4991 st = list(repo.status(unknown=True))[:6]
4987 st = list(repo.status(unknown=True))[:6]
4992
4988
4993 c = repo.dirstate.copies()
4989 c = repo.dirstate.copies()
4994 copied, renamed = [], []
4990 copied, renamed = [], []
4995 for d, s in c.iteritems():
4991 for d, s in c.iteritems():
4996 if s in st[2]:
4992 if s in st[2]:
4997 st[2].remove(s)
4993 st[2].remove(s)
4998 renamed.append(d)
4994 renamed.append(d)
4999 else:
4995 else:
5000 copied.append(d)
4996 copied.append(d)
5001 if d in st[1]:
4997 if d in st[1]:
5002 st[1].remove(d)
4998 st[1].remove(d)
5003 st.insert(3, renamed)
4999 st.insert(3, renamed)
5004 st.insert(4, copied)
5000 st.insert(4, copied)
5005
5001
5006 ms = mergemod.mergestate(repo)
5002 ms = mergemod.mergestate(repo)
5007 st.append([f for f in ms if ms[f] == 'u'])
5003 st.append([f for f in ms if ms[f] == 'u'])
5008
5004
5009 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5005 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5010 st.append(subs)
5006 st.append(subs)
5011
5007
5012 labels = [ui.label(_('%d modified'), 'status.modified'),
5008 labels = [ui.label(_('%d modified'), 'status.modified'),
5013 ui.label(_('%d added'), 'status.added'),
5009 ui.label(_('%d added'), 'status.added'),
5014 ui.label(_('%d removed'), 'status.removed'),
5010 ui.label(_('%d removed'), 'status.removed'),
5015 ui.label(_('%d renamed'), 'status.copied'),
5011 ui.label(_('%d renamed'), 'status.copied'),
5016 ui.label(_('%d copied'), 'status.copied'),
5012 ui.label(_('%d copied'), 'status.copied'),
5017 ui.label(_('%d deleted'), 'status.deleted'),
5013 ui.label(_('%d deleted'), 'status.deleted'),
5018 ui.label(_('%d unknown'), 'status.unknown'),
5014 ui.label(_('%d unknown'), 'status.unknown'),
5019 ui.label(_('%d ignored'), 'status.ignored'),
5015 ui.label(_('%d ignored'), 'status.ignored'),
5020 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5016 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5021 ui.label(_('%d subrepos'), 'status.modified')]
5017 ui.label(_('%d subrepos'), 'status.modified')]
5022 t = []
5018 t = []
5023 for s, l in zip(st, labels):
5019 for s, l in zip(st, labels):
5024 if s:
5020 if s:
5025 t.append(l % len(s))
5021 t.append(l % len(s))
5026
5022
5027 t = ', '.join(t)
5023 t = ', '.join(t)
5028 cleanworkdir = False
5024 cleanworkdir = False
5029
5025
5030 if len(parents) > 1:
5026 if len(parents) > 1:
5031 t += _(' (merge)')
5027 t += _(' (merge)')
5032 elif branch != parents[0].branch():
5028 elif branch != parents[0].branch():
5033 t += _(' (new branch)')
5029 t += _(' (new branch)')
5034 elif (parents[0].extra().get('close') and
5030 elif (parents[0].extra().get('close') and
5035 pnode in repo.branchheads(branch, closed=True)):
5031 pnode in repo.branchheads(branch, closed=True)):
5036 t += _(' (head closed)')
5032 t += _(' (head closed)')
5037 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5033 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5038 t += _(' (clean)')
5034 t += _(' (clean)')
5039 cleanworkdir = True
5035 cleanworkdir = True
5040 elif pnode not in bheads:
5036 elif pnode not in bheads:
5041 t += _(' (new branch head)')
5037 t += _(' (new branch head)')
5042
5038
5043 if cleanworkdir:
5039 if cleanworkdir:
5044 ui.status(_('commit: %s\n') % t.strip())
5040 ui.status(_('commit: %s\n') % t.strip())
5045 else:
5041 else:
5046 ui.write(_('commit: %s\n') % t.strip())
5042 ui.write(_('commit: %s\n') % t.strip())
5047
5043
5048 # all ancestors of branch heads - all ancestors of parent = new csets
5044 # all ancestors of branch heads - all ancestors of parent = new csets
5049 new = [0] * len(repo)
5045 new = [0] * len(repo)
5050 cl = repo.changelog
5046 cl = repo.changelog
5051 for a in [cl.rev(n) for n in bheads]:
5047 for a in [cl.rev(n) for n in bheads]:
5052 new[a] = 1
5048 new[a] = 1
5053 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5049 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5054 new[a] = 1
5050 new[a] = 1
5055 for a in [p.rev() for p in parents]:
5051 for a in [p.rev() for p in parents]:
5056 if a >= 0:
5052 if a >= 0:
5057 new[a] = 0
5053 new[a] = 0
5058 for a in cl.ancestors(*[p.rev() for p in parents]):
5054 for a in cl.ancestors(*[p.rev() for p in parents]):
5059 new[a] = 0
5055 new[a] = 0
5060 new = sum(new)
5056 new = sum(new)
5061
5057
5062 if new == 0:
5058 if new == 0:
5063 ui.status(_('update: (current)\n'))
5059 ui.status(_('update: (current)\n'))
5064 elif pnode not in bheads:
5060 elif pnode not in bheads:
5065 ui.write(_('update: %d new changesets (update)\n') % new)
5061 ui.write(_('update: %d new changesets (update)\n') % new)
5066 else:
5062 else:
5067 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5063 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5068 (new, len(bheads)))
5064 (new, len(bheads)))
5069
5065
5070 if opts.get('remote'):
5066 if opts.get('remote'):
5071 t = []
5067 t = []
5072 source, branches = hg.parseurl(ui.expandpath('default'))
5068 source, branches = hg.parseurl(ui.expandpath('default'))
5073 other = hg.peer(repo, {}, source)
5069 other = hg.peer(repo, {}, source)
5074 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5070 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5075 ui.debug('comparing with %s\n' % util.hidepassword(source))
5071 ui.debug('comparing with %s\n' % util.hidepassword(source))
5076 repo.ui.pushbuffer()
5072 repo.ui.pushbuffer()
5077 commoninc = discovery.findcommonincoming(repo, other)
5073 commoninc = discovery.findcommonincoming(repo, other)
5078 _common, incoming, _rheads = commoninc
5074 _common, incoming, _rheads = commoninc
5079 repo.ui.popbuffer()
5075 repo.ui.popbuffer()
5080 if incoming:
5076 if incoming:
5081 t.append(_('1 or more incoming'))
5077 t.append(_('1 or more incoming'))
5082
5078
5083 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5079 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5084 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5080 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5085 if source != dest:
5081 if source != dest:
5086 other = hg.peer(repo, {}, dest)
5082 other = hg.peer(repo, {}, dest)
5087 commoninc = None
5083 commoninc = None
5088 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5084 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5089 repo.ui.pushbuffer()
5085 repo.ui.pushbuffer()
5090 common, outheads = discovery.findcommonoutgoing(repo, other,
5086 common, outheads = discovery.findcommonoutgoing(repo, other,
5091 commoninc=commoninc)
5087 commoninc=commoninc)
5092 repo.ui.popbuffer()
5088 repo.ui.popbuffer()
5093 o = repo.changelog.findmissing(common=common, heads=outheads)
5089 o = repo.changelog.findmissing(common=common, heads=outheads)
5094 if o:
5090 if o:
5095 t.append(_('%d outgoing') % len(o))
5091 t.append(_('%d outgoing') % len(o))
5096 if 'bookmarks' in other.listkeys('namespaces'):
5092 if 'bookmarks' in other.listkeys('namespaces'):
5097 lmarks = repo.listkeys('bookmarks')
5093 lmarks = repo.listkeys('bookmarks')
5098 rmarks = other.listkeys('bookmarks')
5094 rmarks = other.listkeys('bookmarks')
5099 diff = set(rmarks) - set(lmarks)
5095 diff = set(rmarks) - set(lmarks)
5100 if len(diff) > 0:
5096 if len(diff) > 0:
5101 t.append(_('%d incoming bookmarks') % len(diff))
5097 t.append(_('%d incoming bookmarks') % len(diff))
5102 diff = set(lmarks) - set(rmarks)
5098 diff = set(lmarks) - set(rmarks)
5103 if len(diff) > 0:
5099 if len(diff) > 0:
5104 t.append(_('%d outgoing bookmarks') % len(diff))
5100 t.append(_('%d outgoing bookmarks') % len(diff))
5105
5101
5106 if t:
5102 if t:
5107 ui.write(_('remote: %s\n') % (', '.join(t)))
5103 ui.write(_('remote: %s\n') % (', '.join(t)))
5108 else:
5104 else:
5109 ui.status(_('remote: (synced)\n'))
5105 ui.status(_('remote: (synced)\n'))
5110
5106
5111 @command('tag',
5107 @command('tag',
5112 [('f', 'force', None, _('force tag')),
5108 [('f', 'force', None, _('force tag')),
5113 ('l', 'local', None, _('make the tag local')),
5109 ('l', 'local', None, _('make the tag local')),
5114 ('r', 'rev', '', _('revision to tag'), _('REV')),
5110 ('r', 'rev', '', _('revision to tag'), _('REV')),
5115 ('', 'remove', None, _('remove a tag')),
5111 ('', 'remove', None, _('remove a tag')),
5116 # -l/--local is already there, commitopts cannot be used
5112 # -l/--local is already there, commitopts cannot be used
5117 ('e', 'edit', None, _('edit commit message')),
5113 ('e', 'edit', None, _('edit commit message')),
5118 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5114 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5119 ] + commitopts2,
5115 ] + commitopts2,
5120 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5116 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5121 def tag(ui, repo, name1, *names, **opts):
5117 def tag(ui, repo, name1, *names, **opts):
5122 """add one or more tags for the current or given revision
5118 """add one or more tags for the current or given revision
5123
5119
5124 Name a particular revision using <name>.
5120 Name a particular revision using <name>.
5125
5121
5126 Tags are used to name particular revisions of the repository and are
5122 Tags are used to name particular revisions of the repository and are
5127 very useful to compare different revisions, to go back to significant
5123 very useful to compare different revisions, to go back to significant
5128 earlier versions or to mark branch points as releases, etc. Changing
5124 earlier versions or to mark branch points as releases, etc. Changing
5129 an existing tag is normally disallowed; use -f/--force to override.
5125 an existing tag is normally disallowed; use -f/--force to override.
5130
5126
5131 If no revision is given, the parent of the working directory is
5127 If no revision is given, the parent of the working directory is
5132 used, or tip if no revision is checked out.
5128 used, or tip if no revision is checked out.
5133
5129
5134 To facilitate version control, distribution, and merging of tags,
5130 To facilitate version control, distribution, and merging of tags,
5135 they are stored as a file named ".hgtags" which is managed similarly
5131 they are stored as a file named ".hgtags" which is managed similarly
5136 to other project files and can be hand-edited if necessary. This
5132 to other project files and can be hand-edited if necessary. This
5137 also means that tagging creates a new commit. The file
5133 also means that tagging creates a new commit. The file
5138 ".hg/localtags" is used for local tags (not shared among
5134 ".hg/localtags" is used for local tags (not shared among
5139 repositories).
5135 repositories).
5140
5136
5141 Tag commits are usually made at the head of a branch. If the parent
5137 Tag commits are usually made at the head of a branch. If the parent
5142 of the working directory is not a branch head, :hg:`tag` aborts; use
5138 of the working directory is not a branch head, :hg:`tag` aborts; use
5143 -f/--force to force the tag commit to be based on a non-head
5139 -f/--force to force the tag commit to be based on a non-head
5144 changeset.
5140 changeset.
5145
5141
5146 See :hg:`help dates` for a list of formats valid for -d/--date.
5142 See :hg:`help dates` for a list of formats valid for -d/--date.
5147
5143
5148 Since tag names have priority over branch names during revision
5144 Since tag names have priority over branch names during revision
5149 lookup, using an existing branch name as a tag name is discouraged.
5145 lookup, using an existing branch name as a tag name is discouraged.
5150
5146
5151 Returns 0 on success.
5147 Returns 0 on success.
5152 """
5148 """
5153
5149
5154 rev_ = "."
5150 rev_ = "."
5155 names = [t.strip() for t in (name1,) + names]
5151 names = [t.strip() for t in (name1,) + names]
5156 if len(names) != len(set(names)):
5152 if len(names) != len(set(names)):
5157 raise util.Abort(_('tag names must be unique'))
5153 raise util.Abort(_('tag names must be unique'))
5158 for n in names:
5154 for n in names:
5159 if n in ['tip', '.', 'null']:
5155 if n in ['tip', '.', 'null']:
5160 raise util.Abort(_("the name '%s' is reserved") % n)
5156 raise util.Abort(_("the name '%s' is reserved") % n)
5161 if not n:
5157 if not n:
5162 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5158 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5163 if opts.get('rev') and opts.get('remove'):
5159 if opts.get('rev') and opts.get('remove'):
5164 raise util.Abort(_("--rev and --remove are incompatible"))
5160 raise util.Abort(_("--rev and --remove are incompatible"))
5165 if opts.get('rev'):
5161 if opts.get('rev'):
5166 rev_ = opts['rev']
5162 rev_ = opts['rev']
5167 message = opts.get('message')
5163 message = opts.get('message')
5168 if opts.get('remove'):
5164 if opts.get('remove'):
5169 expectedtype = opts.get('local') and 'local' or 'global'
5165 expectedtype = opts.get('local') and 'local' or 'global'
5170 for n in names:
5166 for n in names:
5171 if not repo.tagtype(n):
5167 if not repo.tagtype(n):
5172 raise util.Abort(_("tag '%s' does not exist") % n)
5168 raise util.Abort(_("tag '%s' does not exist") % n)
5173 if repo.tagtype(n) != expectedtype:
5169 if repo.tagtype(n) != expectedtype:
5174 if expectedtype == 'global':
5170 if expectedtype == 'global':
5175 raise util.Abort(_("tag '%s' is not a global tag") % n)
5171 raise util.Abort(_("tag '%s' is not a global tag") % n)
5176 else:
5172 else:
5177 raise util.Abort(_("tag '%s' is not a local tag") % n)
5173 raise util.Abort(_("tag '%s' is not a local tag") % n)
5178 rev_ = nullid
5174 rev_ = nullid
5179 if not message:
5175 if not message:
5180 # we don't translate commit messages
5176 # we don't translate commit messages
5181 message = 'Removed tag %s' % ', '.join(names)
5177 message = 'Removed tag %s' % ', '.join(names)
5182 elif not opts.get('force'):
5178 elif not opts.get('force'):
5183 for n in names:
5179 for n in names:
5184 if n in repo.tags():
5180 if n in repo.tags():
5185 raise util.Abort(_("tag '%s' already exists "
5181 raise util.Abort(_("tag '%s' already exists "
5186 "(use -f to force)") % n)
5182 "(use -f to force)") % n)
5187 if not opts.get('local'):
5183 if not opts.get('local'):
5188 p1, p2 = repo.dirstate.parents()
5184 p1, p2 = repo.dirstate.parents()
5189 if p2 != nullid:
5185 if p2 != nullid:
5190 raise util.Abort(_('uncommitted merge'))
5186 raise util.Abort(_('uncommitted merge'))
5191 bheads = repo.branchheads()
5187 bheads = repo.branchheads()
5192 if not opts.get('force') and bheads and p1 not in bheads:
5188 if not opts.get('force') and bheads and p1 not in bheads:
5193 raise util.Abort(_('not at a branch head (use -f to force)'))
5189 raise util.Abort(_('not at a branch head (use -f to force)'))
5194 r = scmutil.revsingle(repo, rev_).node()
5190 r = scmutil.revsingle(repo, rev_).node()
5195
5191
5196 if not message:
5192 if not message:
5197 # we don't translate commit messages
5193 # we don't translate commit messages
5198 message = ('Added tag %s for changeset %s' %
5194 message = ('Added tag %s for changeset %s' %
5199 (', '.join(names), short(r)))
5195 (', '.join(names), short(r)))
5200
5196
5201 date = opts.get('date')
5197 date = opts.get('date')
5202 if date:
5198 if date:
5203 date = util.parsedate(date)
5199 date = util.parsedate(date)
5204
5200
5205 if opts.get('edit'):
5201 if opts.get('edit'):
5206 message = ui.edit(message, ui.username())
5202 message = ui.edit(message, ui.username())
5207
5203
5208 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5204 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5209
5205
5210 @command('tags', [], '')
5206 @command('tags', [], '')
5211 def tags(ui, repo):
5207 def tags(ui, repo):
5212 """list repository tags
5208 """list repository tags
5213
5209
5214 This lists both regular and local tags. When the -v/--verbose
5210 This lists both regular and local tags. When the -v/--verbose
5215 switch is used, a third column "local" is printed for local tags.
5211 switch is used, a third column "local" is printed for local tags.
5216
5212
5217 Returns 0 on success.
5213 Returns 0 on success.
5218 """
5214 """
5219
5215
5220 hexfunc = ui.debugflag and hex or short
5216 hexfunc = ui.debugflag and hex or short
5221 tagtype = ""
5217 tagtype = ""
5222
5218
5223 for t, n in reversed(repo.tagslist()):
5219 for t, n in reversed(repo.tagslist()):
5224 if ui.quiet:
5220 if ui.quiet:
5225 ui.write("%s\n" % t, label='tags.normal')
5221 ui.write("%s\n" % t, label='tags.normal')
5226 continue
5222 continue
5227
5223
5228 hn = hexfunc(n)
5224 hn = hexfunc(n)
5229 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5225 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5230 rev = ui.label(r, 'log.changeset')
5226 rev = ui.label(r, 'log.changeset')
5231 spaces = " " * (30 - encoding.colwidth(t))
5227 spaces = " " * (30 - encoding.colwidth(t))
5232
5228
5233 tag = ui.label(t, 'tags.normal')
5229 tag = ui.label(t, 'tags.normal')
5234 if ui.verbose:
5230 if ui.verbose:
5235 if repo.tagtype(t) == 'local':
5231 if repo.tagtype(t) == 'local':
5236 tagtype = " local"
5232 tagtype = " local"
5237 tag = ui.label(t, 'tags.local')
5233 tag = ui.label(t, 'tags.local')
5238 else:
5234 else:
5239 tagtype = ""
5235 tagtype = ""
5240 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5236 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5241
5237
5242 @command('tip',
5238 @command('tip',
5243 [('p', 'patch', None, _('show patch')),
5239 [('p', 'patch', None, _('show patch')),
5244 ('g', 'git', None, _('use git extended diff format')),
5240 ('g', 'git', None, _('use git extended diff format')),
5245 ] + templateopts,
5241 ] + templateopts,
5246 _('[-p] [-g]'))
5242 _('[-p] [-g]'))
5247 def tip(ui, repo, **opts):
5243 def tip(ui, repo, **opts):
5248 """show the tip revision
5244 """show the tip revision
5249
5245
5250 The tip revision (usually just called the tip) is the changeset
5246 The tip revision (usually just called the tip) is the changeset
5251 most recently added to the repository (and therefore the most
5247 most recently added to the repository (and therefore the most
5252 recently changed head).
5248 recently changed head).
5253
5249
5254 If you have just made a commit, that commit will be the tip. If
5250 If you have just made a commit, that commit will be the tip. If
5255 you have just pulled changes from another repository, the tip of
5251 you have just pulled changes from another repository, the tip of
5256 that repository becomes the current tip. The "tip" tag is special
5252 that repository becomes the current tip. The "tip" tag is special
5257 and cannot be renamed or assigned to a different changeset.
5253 and cannot be renamed or assigned to a different changeset.
5258
5254
5259 Returns 0 on success.
5255 Returns 0 on success.
5260 """
5256 """
5261 displayer = cmdutil.show_changeset(ui, repo, opts)
5257 displayer = cmdutil.show_changeset(ui, repo, opts)
5262 displayer.show(repo[len(repo) - 1])
5258 displayer.show(repo[len(repo) - 1])
5263 displayer.close()
5259 displayer.close()
5264
5260
5265 @command('unbundle',
5261 @command('unbundle',
5266 [('u', 'update', None,
5262 [('u', 'update', None,
5267 _('update to new branch head if changesets were unbundled'))],
5263 _('update to new branch head if changesets were unbundled'))],
5268 _('[-u] FILE...'))
5264 _('[-u] FILE...'))
5269 def unbundle(ui, repo, fname1, *fnames, **opts):
5265 def unbundle(ui, repo, fname1, *fnames, **opts):
5270 """apply one or more changegroup files
5266 """apply one or more changegroup files
5271
5267
5272 Apply one or more compressed changegroup files generated by the
5268 Apply one or more compressed changegroup files generated by the
5273 bundle command.
5269 bundle command.
5274
5270
5275 Returns 0 on success, 1 if an update has unresolved files.
5271 Returns 0 on success, 1 if an update has unresolved files.
5276 """
5272 """
5277 fnames = (fname1,) + fnames
5273 fnames = (fname1,) + fnames
5278
5274
5279 lock = repo.lock()
5275 lock = repo.lock()
5280 wc = repo['.']
5276 wc = repo['.']
5281 try:
5277 try:
5282 for fname in fnames:
5278 for fname in fnames:
5283 f = url.open(ui, fname)
5279 f = url.open(ui, fname)
5284 gen = changegroup.readbundle(f, fname)
5280 gen = changegroup.readbundle(f, fname)
5285 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5281 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5286 lock=lock)
5282 lock=lock)
5287 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5283 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5288 finally:
5284 finally:
5289 lock.release()
5285 lock.release()
5290 return postincoming(ui, repo, modheads, opts.get('update'), None)
5286 return postincoming(ui, repo, modheads, opts.get('update'), None)
5291
5287
5292 @command('^update|up|checkout|co',
5288 @command('^update|up|checkout|co',
5293 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5289 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5294 ('c', 'check', None,
5290 ('c', 'check', None,
5295 _('update across branches if no uncommitted changes')),
5291 _('update across branches if no uncommitted changes')),
5296 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5292 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5297 ('r', 'rev', '', _('revision'), _('REV'))],
5293 ('r', 'rev', '', _('revision'), _('REV'))],
5298 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5294 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5299 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5295 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5300 """update working directory (or switch revisions)
5296 """update working directory (or switch revisions)
5301
5297
5302 Update the repository's working directory to the specified
5298 Update the repository's working directory to the specified
5303 changeset. If no changeset is specified, update to the tip of the
5299 changeset. If no changeset is specified, update to the tip of the
5304 current named branch.
5300 current named branch.
5305
5301
5306 If the changeset is not a descendant of the working directory's
5302 If the changeset is not a descendant of the working directory's
5307 parent, the update is aborted. With the -c/--check option, the
5303 parent, the update is aborted. With the -c/--check option, the
5308 working directory is checked for uncommitted changes; if none are
5304 working directory is checked for uncommitted changes; if none are
5309 found, the working directory is updated to the specified
5305 found, the working directory is updated to the specified
5310 changeset.
5306 changeset.
5311
5307
5312 Update sets the working directory's parent revison to the specified
5308 Update sets the working directory's parent revison to the specified
5313 changeset (see :hg:`help parents`).
5309 changeset (see :hg:`help parents`).
5314
5310
5315 The following rules apply when the working directory contains
5311 The following rules apply when the working directory contains
5316 uncommitted changes:
5312 uncommitted changes:
5317
5313
5318 1. If neither -c/--check nor -C/--clean is specified, and if
5314 1. If neither -c/--check nor -C/--clean is specified, and if
5319 the requested changeset is an ancestor or descendant of
5315 the requested changeset is an ancestor or descendant of
5320 the working directory's parent, the uncommitted changes
5316 the working directory's parent, the uncommitted changes
5321 are merged into the requested changeset and the merged
5317 are merged into the requested changeset and the merged
5322 result is left uncommitted. If the requested changeset is
5318 result is left uncommitted. If the requested changeset is
5323 not an ancestor or descendant (that is, it is on another
5319 not an ancestor or descendant (that is, it is on another
5324 branch), the update is aborted and the uncommitted changes
5320 branch), the update is aborted and the uncommitted changes
5325 are preserved.
5321 are preserved.
5326
5322
5327 2. With the -c/--check option, the update is aborted and the
5323 2. With the -c/--check option, the update is aborted and the
5328 uncommitted changes are preserved.
5324 uncommitted changes are preserved.
5329
5325
5330 3. With the -C/--clean option, uncommitted changes are discarded and
5326 3. With the -C/--clean option, uncommitted changes are discarded and
5331 the working directory is updated to the requested changeset.
5327 the working directory is updated to the requested changeset.
5332
5328
5333 Use null as the changeset to remove the working directory (like
5329 Use null as the changeset to remove the working directory (like
5334 :hg:`clone -U`).
5330 :hg:`clone -U`).
5335
5331
5336 If you want to revert just one file to an older revision, use
5332 If you want to revert just one file to an older revision, use
5337 :hg:`revert [-r REV] NAME`.
5333 :hg:`revert [-r REV] NAME`.
5338
5334
5339 See :hg:`help dates` for a list of formats valid for -d/--date.
5335 See :hg:`help dates` for a list of formats valid for -d/--date.
5340
5336
5341 Returns 0 on success, 1 if there are unresolved files.
5337 Returns 0 on success, 1 if there are unresolved files.
5342 """
5338 """
5343 if rev and node:
5339 if rev and node:
5344 raise util.Abort(_("please specify just one revision"))
5340 raise util.Abort(_("please specify just one revision"))
5345
5341
5346 if rev is None or rev == '':
5342 if rev is None or rev == '':
5347 rev = node
5343 rev = node
5348
5344
5349 # if we defined a bookmark, we have to remember the original bookmark name
5345 # if we defined a bookmark, we have to remember the original bookmark name
5350 brev = rev
5346 brev = rev
5351 rev = scmutil.revsingle(repo, rev, rev).rev()
5347 rev = scmutil.revsingle(repo, rev, rev).rev()
5352
5348
5353 if check and clean:
5349 if check and clean:
5354 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5350 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5355
5351
5356 if check:
5352 if check:
5357 # we could use dirty() but we can ignore merge and branch trivia
5353 # we could use dirty() but we can ignore merge and branch trivia
5358 c = repo[None]
5354 c = repo[None]
5359 if c.modified() or c.added() or c.removed():
5355 if c.modified() or c.added() or c.removed():
5360 raise util.Abort(_("uncommitted local changes"))
5356 raise util.Abort(_("uncommitted local changes"))
5361
5357
5362 if date:
5358 if date:
5363 if rev is not None:
5359 if rev is not None:
5364 raise util.Abort(_("you can't specify a revision and a date"))
5360 raise util.Abort(_("you can't specify a revision and a date"))
5365 rev = cmdutil.finddate(ui, repo, date)
5361 rev = cmdutil.finddate(ui, repo, date)
5366
5362
5367 if clean or check:
5363 if clean or check:
5368 ret = hg.clean(repo, rev)
5364 ret = hg.clean(repo, rev)
5369 else:
5365 else:
5370 ret = hg.update(repo, rev)
5366 ret = hg.update(repo, rev)
5371
5367
5372 if brev in repo._bookmarks:
5368 if brev in repo._bookmarks:
5373 bookmarks.setcurrent(repo, brev)
5369 bookmarks.setcurrent(repo, brev)
5374
5370
5375 return ret
5371 return ret
5376
5372
5377 @command('verify', [])
5373 @command('verify', [])
5378 def verify(ui, repo):
5374 def verify(ui, repo):
5379 """verify the integrity of the repository
5375 """verify the integrity of the repository
5380
5376
5381 Verify the integrity of the current repository.
5377 Verify the integrity of the current repository.
5382
5378
5383 This will perform an extensive check of the repository's
5379 This will perform an extensive check of the repository's
5384 integrity, validating the hashes and checksums of each entry in
5380 integrity, validating the hashes and checksums of each entry in
5385 the changelog, manifest, and tracked files, as well as the
5381 the changelog, manifest, and tracked files, as well as the
5386 integrity of their crosslinks and indices.
5382 integrity of their crosslinks and indices.
5387
5383
5388 Returns 0 on success, 1 if errors are encountered.
5384 Returns 0 on success, 1 if errors are encountered.
5389 """
5385 """
5390 return hg.verify(repo)
5386 return hg.verify(repo)
5391
5387
5392 @command('version', [])
5388 @command('version', [])
5393 def version_(ui):
5389 def version_(ui):
5394 """output version and copyright information"""
5390 """output version and copyright information"""
5395 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5391 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5396 % util.version())
5392 % util.version())
5397 ui.status(_(
5393 ui.status(_(
5398 "(see http://mercurial.selenic.com for more information)\n"
5394 "(see http://mercurial.selenic.com for more information)\n"
5399 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5395 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5400 "This is free software; see the source for copying conditions. "
5396 "This is free software; see the source for copying conditions. "
5401 "There is NO\nwarranty; "
5397 "There is NO\nwarranty; "
5402 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5398 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5403 ))
5399 ))
5404
5400
5405 norepo = ("clone init version help debugcommands debugcomplete"
5401 norepo = ("clone init version help debugcommands debugcomplete"
5406 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5402 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5407 " debugknown debuggetbundle debugbundle")
5403 " debugknown debuggetbundle debugbundle")
5408 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5404 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5409 " debugdata debugindex debugindexdot debugrevlog")
5405 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now