##// END OF EJS Templates
addremove: mention --similarity defaults to 100 (issue3430)
Patrick Mezard -
r17266:4e35dea7 stable
parent child Browse files
Show More
@@ -1,5881 +1,5881
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, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('G', 'graph', None, _("show the revision DAG")),
101 ('G', 'graph', None, _("show the revision DAG")),
102 ] + templateopts
102 ] + templateopts
103
103
104 diffopts = [
104 diffopts = [
105 ('a', 'text', None, _('treat all files as text')),
105 ('a', 'text', None, _('treat all files as text')),
106 ('g', 'git', None, _('use git extended diff format')),
106 ('g', 'git', None, _('use git extended diff format')),
107 ('', 'nodates', None, _('omit dates from diff headers'))
107 ('', 'nodates', None, _('omit dates from diff headers'))
108 ]
108 ]
109
109
110 diffwsopts = [
110 diffwsopts = [
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 ]
117 ]
118
118
119 diffopts2 = [
119 diffopts2 = [
120 ('p', 'show-function', None, _('show which function each change is in')),
120 ('p', 'show-function', None, _('show which function each change is in')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ] + diffwsopts + [
122 ] + diffwsopts + [
123 ('U', 'unified', '',
123 ('U', 'unified', '',
124 _('number of lines of context to show'), _('NUM')),
124 _('number of lines of context to show'), _('NUM')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ]
126 ]
127
127
128 mergetoolopts = [
128 mergetoolopts = [
129 ('t', 'tool', '', _('specify merge tool')),
129 ('t', 'tool', '', _('specify merge tool')),
130 ]
130 ]
131
131
132 similarityopts = [
132 similarityopts = [
133 ('s', 'similarity', '',
133 ('s', 'similarity', '',
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 ]
135 ]
136
136
137 subrepoopts = [
137 subrepoopts = [
138 ('S', 'subrepos', None,
138 ('S', 'subrepos', None,
139 _('recurse into subrepositories'))
139 _('recurse into subrepositories'))
140 ]
140 ]
141
141
142 # Commands start here, listed alphabetically
142 # Commands start here, listed alphabetically
143
143
144 @command('^add',
144 @command('^add',
145 walkopts + subrepoopts + dryrunopts,
145 walkopts + subrepoopts + dryrunopts,
146 _('[OPTION]... [FILE]...'))
146 _('[OPTION]... [FILE]...'))
147 def add(ui, repo, *pats, **opts):
147 def add(ui, repo, *pats, **opts):
148 """add the specified files on the next commit
148 """add the specified files on the next commit
149
149
150 Schedule files to be version controlled and added to the
150 Schedule files to be version controlled and added to the
151 repository.
151 repository.
152
152
153 The files will be added to the repository at the next commit. To
153 The files will be added to the repository at the next commit. To
154 undo an add before that, see :hg:`forget`.
154 undo an add before that, see :hg:`forget`.
155
155
156 If no names are given, add all files to the repository.
156 If no names are given, add all files to the repository.
157
157
158 .. container:: verbose
158 .. container:: verbose
159
159
160 An example showing how new (unknown) files are added
160 An example showing how new (unknown) files are added
161 automatically by :hg:`add`::
161 automatically by :hg:`add`::
162
162
163 $ ls
163 $ ls
164 foo.c
164 foo.c
165 $ hg status
165 $ hg status
166 ? foo.c
166 ? foo.c
167 $ hg add
167 $ hg add
168 adding foo.c
168 adding foo.c
169 $ hg status
169 $ hg status
170 A foo.c
170 A foo.c
171
171
172 Returns 0 if all files are successfully added.
172 Returns 0 if all files are successfully added.
173 """
173 """
174
174
175 m = scmutil.match(repo[None], pats, opts)
175 m = scmutil.match(repo[None], pats, opts)
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 opts.get('subrepos'), prefix="", explicitonly=False)
177 opts.get('subrepos'), prefix="", explicitonly=False)
178 return rejected and 1 or 0
178 return rejected and 1 or 0
179
179
180 @command('addremove',
180 @command('addremove',
181 similarityopts + walkopts + dryrunopts,
181 similarityopts + walkopts + dryrunopts,
182 _('[OPTION]... [FILE]...'))
182 _('[OPTION]... [FILE]...'))
183 def addremove(ui, repo, *pats, **opts):
183 def addremove(ui, repo, *pats, **opts):
184 """add all new files, delete all missing files
184 """add all new files, delete all missing files
185
185
186 Add all new files and remove all missing files from the
186 Add all new files and remove all missing files from the
187 repository.
187 repository.
188
188
189 New files are ignored if they match any of the patterns in
189 New files are ignored if they match any of the patterns in
190 ``.hgignore``. As with add, these changes take effect at the next
190 ``.hgignore``. As with add, these changes take effect at the next
191 commit.
191 commit.
192
192
193 Use the -s/--similarity option to detect renamed files. With a
193 Use the -s/--similarity option to detect renamed files. This
194 parameter greater than 0, this compares every removed file with
195 every added file and records those similar enough as renames. This
196 option takes a percentage between 0 (disabled) and 100 (files must
194 option takes a percentage between 0 (disabled) and 100 (files must
197 be identical) as its parameter. Detecting renamed files this way
195 be identical) as its parameter. With a parameter greater than 0,
196 this compares every removed file with every added file and records
197 those similar enough as renames. Detecting renamed files this way
198 can be expensive. After using this option, :hg:`status -C` can be
198 can be expensive. After using this option, :hg:`status -C` can be
199 used to check which files were identified as moved or renamed.
199 used to check which files were identified as moved or renamed. If
200 If this option is not specified, only renames of identical files
200 not specified, -s/--similarity defaults to 100 and only renames of
201 are detected.
201 identical files are detected.
202
202
203 Returns 0 if all files are successfully added.
203 Returns 0 if all files are successfully added.
204 """
204 """
205 try:
205 try:
206 sim = float(opts.get('similarity') or 100)
206 sim = float(opts.get('similarity') or 100)
207 except ValueError:
207 except ValueError:
208 raise util.Abort(_('similarity must be a number'))
208 raise util.Abort(_('similarity must be a number'))
209 if sim < 0 or sim > 100:
209 if sim < 0 or sim > 100:
210 raise util.Abort(_('similarity must be between 0 and 100'))
210 raise util.Abort(_('similarity must be between 0 and 100'))
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212
212
213 @command('^annotate|blame',
213 @command('^annotate|blame',
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 ('', 'follow', None,
215 ('', 'follow', None,
216 _('follow copies/renames and list the filename (DEPRECATED)')),
216 _('follow copies/renames and list the filename (DEPRECATED)')),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('a', 'text', None, _('treat all files as text')),
218 ('a', 'text', None, _('treat all files as text')),
219 ('u', 'user', None, _('list the author (long with -v)')),
219 ('u', 'user', None, _('list the author (long with -v)')),
220 ('f', 'file', None, _('list the filename')),
220 ('f', 'file', None, _('list the filename')),
221 ('d', 'date', None, _('list the date (short with -q)')),
221 ('d', 'date', None, _('list the date (short with -q)')),
222 ('n', 'number', None, _('list the revision number (default)')),
222 ('n', 'number', None, _('list the revision number (default)')),
223 ('c', 'changeset', None, _('list the changeset')),
223 ('c', 'changeset', None, _('list the changeset')),
224 ('l', 'line-number', None, _('show line number at the first appearance'))
224 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ] + diffwsopts + walkopts,
225 ] + diffwsopts + walkopts,
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 def annotate(ui, repo, *pats, **opts):
227 def annotate(ui, repo, *pats, **opts):
228 """show changeset information by line for each file
228 """show changeset information by line for each file
229
229
230 List changes in files, showing the revision id responsible for
230 List changes in files, showing the revision id responsible for
231 each line
231 each line
232
232
233 This command is useful for discovering when a change was made and
233 This command is useful for discovering when a change was made and
234 by whom.
234 by whom.
235
235
236 Without the -a/--text option, annotate will avoid processing files
236 Without the -a/--text option, annotate will avoid processing files
237 it detects as binary. With -a, annotate will annotate the file
237 it detects as binary. With -a, annotate will annotate the file
238 anyway, although the results will probably be neither useful
238 anyway, although the results will probably be neither useful
239 nor desirable.
239 nor desirable.
240
240
241 Returns 0 on success.
241 Returns 0 on success.
242 """
242 """
243 if opts.get('follow'):
243 if opts.get('follow'):
244 # --follow is deprecated and now just an alias for -f/--file
244 # --follow is deprecated and now just an alias for -f/--file
245 # to mimic the behavior of Mercurial before version 1.5
245 # to mimic the behavior of Mercurial before version 1.5
246 opts['file'] = True
246 opts['file'] = True
247
247
248 datefunc = ui.quiet and util.shortdate or util.datestr
248 datefunc = ui.quiet and util.shortdate or util.datestr
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250
250
251 if not pats:
251 if not pats:
252 raise util.Abort(_('at least one filename or pattern is required'))
252 raise util.Abort(_('at least one filename or pattern is required'))
253
253
254 hexfn = ui.debugflag and hex or short
254 hexfn = ui.debugflag and hex or short
255
255
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 ('number', ' ', lambda x: str(x[0].rev())),
257 ('number', ' ', lambda x: str(x[0].rev())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('date', ' ', getdate),
259 ('date', ' ', getdate),
260 ('file', ' ', lambda x: x[0].path()),
260 ('file', ' ', lambda x: x[0].path()),
261 ('line_number', ':', lambda x: str(x[1])),
261 ('line_number', ':', lambda x: str(x[1])),
262 ]
262 ]
263
263
264 if (not opts.get('user') and not opts.get('changeset')
264 if (not opts.get('user') and not opts.get('changeset')
265 and not opts.get('date') and not opts.get('file')):
265 and not opts.get('date') and not opts.get('file')):
266 opts['number'] = True
266 opts['number'] = True
267
267
268 linenumber = opts.get('line_number') is not None
268 linenumber = opts.get('line_number') is not None
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
271
271
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274
274
275 def bad(x, y):
275 def bad(x, y):
276 raise util.Abort("%s: %s" % (x, y))
276 raise util.Abort("%s: %s" % (x, y))
277
277
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 m = scmutil.match(ctx, pats, opts)
279 m = scmutil.match(ctx, pats, opts)
280 m.bad = bad
280 m.bad = bad
281 follow = not opts.get('no_follow')
281 follow = not opts.get('no_follow')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
283 for abs in ctx.walk(m):
283 for abs in ctx.walk(m):
284 fctx = ctx[abs]
284 fctx = ctx[abs]
285 if not opts.get('text') and util.binary(fctx.data()):
285 if not opts.get('text') and util.binary(fctx.data()):
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 continue
287 continue
288
288
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 diffopts=diffopts)
290 diffopts=diffopts)
291 pieces = []
291 pieces = []
292
292
293 for f, sep in funcmap:
293 for f, sep in funcmap:
294 l = [f(n) for n, dummy in lines]
294 l = [f(n) for n, dummy in lines]
295 if l:
295 if l:
296 sized = [(x, encoding.colwidth(x)) for x in l]
296 sized = [(x, encoding.colwidth(x)) for x in l]
297 ml = max([w for x, w in sized])
297 ml = max([w for x, w in sized])
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 for x, w in sized])
299 for x, w in sized])
300
300
301 if pieces:
301 if pieces:
302 for p, l in zip(zip(*pieces), lines):
302 for p, l in zip(zip(*pieces), lines):
303 ui.write("%s: %s" % ("".join(p), l[1]))
303 ui.write("%s: %s" % ("".join(p), l[1]))
304
304
305 if lines and not lines[-1][1].endswith('\n'):
305 if lines and not lines[-1][1].endswith('\n'):
306 ui.write('\n')
306 ui.write('\n')
307
307
308 @command('archive',
308 @command('archive',
309 [('', 'no-decode', None, _('do not pass files through decoders')),
309 [('', 'no-decode', None, _('do not pass files through decoders')),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 _('PREFIX')),
311 _('PREFIX')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ] + subrepoopts + walkopts,
314 ] + subrepoopts + walkopts,
315 _('[OPTION]... DEST'))
315 _('[OPTION]... DEST'))
316 def archive(ui, repo, dest, **opts):
316 def archive(ui, repo, dest, **opts):
317 '''create an unversioned archive of a repository revision
317 '''create an unversioned archive of a repository revision
318
318
319 By default, the revision used is the parent of the working
319 By default, the revision used is the parent of the working
320 directory; use -r/--rev to specify a different revision.
320 directory; use -r/--rev to specify a different revision.
321
321
322 The archive type is automatically detected based on file
322 The archive type is automatically detected based on file
323 extension (or override using -t/--type).
323 extension (or override using -t/--type).
324
324
325 .. container:: verbose
325 .. container:: verbose
326
326
327 Examples:
327 Examples:
328
328
329 - create a zip file containing the 1.0 release::
329 - create a zip file containing the 1.0 release::
330
330
331 hg archive -r 1.0 project-1.0.zip
331 hg archive -r 1.0 project-1.0.zip
332
332
333 - create a tarball excluding .hg files::
333 - create a tarball excluding .hg files::
334
334
335 hg archive project.tar.gz -X ".hg*"
335 hg archive project.tar.gz -X ".hg*"
336
336
337 Valid types are:
337 Valid types are:
338
338
339 :``files``: a directory full of files (default)
339 :``files``: a directory full of files (default)
340 :``tar``: tar archive, uncompressed
340 :``tar``: tar archive, uncompressed
341 :``tbz2``: tar archive, compressed using bzip2
341 :``tbz2``: tar archive, compressed using bzip2
342 :``tgz``: tar archive, compressed using gzip
342 :``tgz``: tar archive, compressed using gzip
343 :``uzip``: zip archive, uncompressed
343 :``uzip``: zip archive, uncompressed
344 :``zip``: zip archive, compressed using deflate
344 :``zip``: zip archive, compressed using deflate
345
345
346 The exact name of the destination archive or directory is given
346 The exact name of the destination archive or directory is given
347 using a format string; see :hg:`help export` for details.
347 using a format string; see :hg:`help export` for details.
348
348
349 Each member added to an archive file has a directory prefix
349 Each member added to an archive file has a directory prefix
350 prepended. Use -p/--prefix to specify a format string for the
350 prepended. Use -p/--prefix to specify a format string for the
351 prefix. The default is the basename of the archive, with suffixes
351 prefix. The default is the basename of the archive, with suffixes
352 removed.
352 removed.
353
353
354 Returns 0 on success.
354 Returns 0 on success.
355 '''
355 '''
356
356
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 if not ctx:
358 if not ctx:
359 raise util.Abort(_('no working directory: please specify a revision'))
359 raise util.Abort(_('no working directory: please specify a revision'))
360 node = ctx.node()
360 node = ctx.node()
361 dest = cmdutil.makefilename(repo, dest, node)
361 dest = cmdutil.makefilename(repo, dest, node)
362 if os.path.realpath(dest) == repo.root:
362 if os.path.realpath(dest) == repo.root:
363 raise util.Abort(_('repository root cannot be destination'))
363 raise util.Abort(_('repository root cannot be destination'))
364
364
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 prefix = opts.get('prefix')
366 prefix = opts.get('prefix')
367
367
368 if dest == '-':
368 if dest == '-':
369 if kind == 'files':
369 if kind == 'files':
370 raise util.Abort(_('cannot archive plain files to stdout'))
370 raise util.Abort(_('cannot archive plain files to stdout'))
371 dest = cmdutil.makefileobj(repo, dest)
371 dest = cmdutil.makefileobj(repo, dest)
372 if not prefix:
372 if not prefix:
373 prefix = os.path.basename(repo.root) + '-%h'
373 prefix = os.path.basename(repo.root) + '-%h'
374
374
375 prefix = cmdutil.makefilename(repo, prefix, node)
375 prefix = cmdutil.makefilename(repo, prefix, node)
376 matchfn = scmutil.match(ctx, [], opts)
376 matchfn = scmutil.match(ctx, [], opts)
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 matchfn, prefix, subrepos=opts.get('subrepos'))
378 matchfn, prefix, subrepos=opts.get('subrepos'))
379
379
380 @command('backout',
380 @command('backout',
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 ('', 'parent', '',
382 ('', 'parent', '',
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 _('[OPTION]... [-r] REV'))
386 _('[OPTION]... [-r] REV'))
387 def backout(ui, repo, node=None, rev=None, **opts):
387 def backout(ui, repo, node=None, rev=None, **opts):
388 '''reverse effect of earlier changeset
388 '''reverse effect of earlier changeset
389
389
390 Prepare a new changeset with the effect of REV undone in the
390 Prepare a new changeset with the effect of REV undone in the
391 current working directory.
391 current working directory.
392
392
393 If REV is the parent of the working directory, then this new changeset
393 If REV is the parent of the working directory, then this new changeset
394 is committed automatically. Otherwise, hg needs to merge the
394 is committed automatically. Otherwise, hg needs to merge the
395 changes and the merged result is left uncommitted.
395 changes and the merged result is left uncommitted.
396
396
397 .. note::
397 .. note::
398 backout cannot be used to fix either an unwanted or
398 backout cannot be used to fix either an unwanted or
399 incorrect merge.
399 incorrect merge.
400
400
401 .. container:: verbose
401 .. container:: verbose
402
402
403 By default, the pending changeset will have one parent,
403 By default, the pending changeset will have one parent,
404 maintaining a linear history. With --merge, the pending
404 maintaining a linear history. With --merge, the pending
405 changeset will instead have two parents: the old parent of the
405 changeset will instead have two parents: the old parent of the
406 working directory and a new child of REV that simply undoes REV.
406 working directory and a new child of REV that simply undoes REV.
407
407
408 Before version 1.7, the behavior without --merge was equivalent
408 Before version 1.7, the behavior without --merge was equivalent
409 to specifying --merge followed by :hg:`update --clean .` to
409 to specifying --merge followed by :hg:`update --clean .` to
410 cancel the merge and leave the child of REV as a head to be
410 cancel the merge and leave the child of REV as a head to be
411 merged separately.
411 merged separately.
412
412
413 See :hg:`help dates` for a list of formats valid for -d/--date.
413 See :hg:`help dates` for a list of formats valid for -d/--date.
414
414
415 Returns 0 on success.
415 Returns 0 on success.
416 '''
416 '''
417 if rev and node:
417 if rev and node:
418 raise util.Abort(_("please specify just one revision"))
418 raise util.Abort(_("please specify just one revision"))
419
419
420 if not rev:
420 if not rev:
421 rev = node
421 rev = node
422
422
423 if not rev:
423 if not rev:
424 raise util.Abort(_("please specify a revision to backout"))
424 raise util.Abort(_("please specify a revision to backout"))
425
425
426 date = opts.get('date')
426 date = opts.get('date')
427 if date:
427 if date:
428 opts['date'] = util.parsedate(date)
428 opts['date'] = util.parsedate(date)
429
429
430 cmdutil.bailifchanged(repo)
430 cmdutil.bailifchanged(repo)
431 node = scmutil.revsingle(repo, rev).node()
431 node = scmutil.revsingle(repo, rev).node()
432
432
433 op1, op2 = repo.dirstate.parents()
433 op1, op2 = repo.dirstate.parents()
434 a = repo.changelog.ancestor(op1, node)
434 a = repo.changelog.ancestor(op1, node)
435 if a != node:
435 if a != node:
436 raise util.Abort(_('cannot backout change on a different branch'))
436 raise util.Abort(_('cannot backout change on a different branch'))
437
437
438 p1, p2 = repo.changelog.parents(node)
438 p1, p2 = repo.changelog.parents(node)
439 if p1 == nullid:
439 if p1 == nullid:
440 raise util.Abort(_('cannot backout a change with no parents'))
440 raise util.Abort(_('cannot backout a change with no parents'))
441 if p2 != nullid:
441 if p2 != nullid:
442 if not opts.get('parent'):
442 if not opts.get('parent'):
443 raise util.Abort(_('cannot backout a merge changeset'))
443 raise util.Abort(_('cannot backout a merge changeset'))
444 p = repo.lookup(opts['parent'])
444 p = repo.lookup(opts['parent'])
445 if p not in (p1, p2):
445 if p not in (p1, p2):
446 raise util.Abort(_('%s is not a parent of %s') %
446 raise util.Abort(_('%s is not a parent of %s') %
447 (short(p), short(node)))
447 (short(p), short(node)))
448 parent = p
448 parent = p
449 else:
449 else:
450 if opts.get('parent'):
450 if opts.get('parent'):
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 parent = p1
452 parent = p1
453
453
454 # the backout should appear on the same branch
454 # the backout should appear on the same branch
455 wlock = repo.wlock()
455 wlock = repo.wlock()
456 try:
456 try:
457 branch = repo.dirstate.branch()
457 branch = repo.dirstate.branch()
458 hg.clean(repo, node, show_stats=False)
458 hg.clean(repo, node, show_stats=False)
459 repo.dirstate.setbranch(branch)
459 repo.dirstate.setbranch(branch)
460 revert_opts = opts.copy()
460 revert_opts = opts.copy()
461 revert_opts['date'] = None
461 revert_opts['date'] = None
462 revert_opts['all'] = True
462 revert_opts['all'] = True
463 revert_opts['rev'] = hex(parent)
463 revert_opts['rev'] = hex(parent)
464 revert_opts['no_backup'] = None
464 revert_opts['no_backup'] = None
465 revert(ui, repo, **revert_opts)
465 revert(ui, repo, **revert_opts)
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 return hg.update(repo, op1)
469 return hg.update(repo, op1)
470 finally:
470 finally:
471 ui.setconfig('ui', 'forcemerge', '')
471 ui.setconfig('ui', 'forcemerge', '')
472
472
473 commit_opts = opts.copy()
473 commit_opts = opts.copy()
474 commit_opts['addremove'] = False
474 commit_opts['addremove'] = False
475 if not commit_opts['message'] and not commit_opts['logfile']:
475 if not commit_opts['message'] and not commit_opts['logfile']:
476 # we don't translate commit messages
476 # we don't translate commit messages
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
478 commit_opts['force_editor'] = True
478 commit_opts['force_editor'] = True
479 commit(ui, repo, **commit_opts)
479 commit(ui, repo, **commit_opts)
480 def nice(node):
480 def nice(node):
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
482 ui.status(_('changeset %s backs out changeset %s\n') %
482 ui.status(_('changeset %s backs out changeset %s\n') %
483 (nice(repo.changelog.tip()), nice(node)))
483 (nice(repo.changelog.tip()), nice(node)))
484 if opts.get('merge') and op1 != node:
484 if opts.get('merge') and op1 != node:
485 hg.clean(repo, op1, show_stats=False)
485 hg.clean(repo, op1, show_stats=False)
486 ui.status(_('merging with changeset %s\n')
486 ui.status(_('merging with changeset %s\n')
487 % nice(repo.changelog.tip()))
487 % nice(repo.changelog.tip()))
488 try:
488 try:
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
490 return hg.merge(repo, hex(repo.changelog.tip()))
490 return hg.merge(repo, hex(repo.changelog.tip()))
491 finally:
491 finally:
492 ui.setconfig('ui', 'forcemerge', '')
492 ui.setconfig('ui', 'forcemerge', '')
493 finally:
493 finally:
494 wlock.release()
494 wlock.release()
495 return 0
495 return 0
496
496
497 @command('bisect',
497 @command('bisect',
498 [('r', 'reset', False, _('reset bisect state')),
498 [('r', 'reset', False, _('reset bisect state')),
499 ('g', 'good', False, _('mark changeset good')),
499 ('g', 'good', False, _('mark changeset good')),
500 ('b', 'bad', False, _('mark changeset bad')),
500 ('b', 'bad', False, _('mark changeset bad')),
501 ('s', 'skip', False, _('skip testing changeset')),
501 ('s', 'skip', False, _('skip testing changeset')),
502 ('e', 'extend', False, _('extend the bisect range')),
502 ('e', 'extend', False, _('extend the bisect range')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
504 ('U', 'noupdate', False, _('do not update to target'))],
504 ('U', 'noupdate', False, _('do not update to target'))],
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
506 def bisect(ui, repo, rev=None, extra=None, command=None,
506 def bisect(ui, repo, rev=None, extra=None, command=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
508 noupdate=None):
508 noupdate=None):
509 """subdivision search of changesets
509 """subdivision search of changesets
510
510
511 This command helps to find changesets which introduce problems. To
511 This command helps to find changesets which introduce problems. To
512 use, mark the earliest changeset you know exhibits the problem as
512 use, mark the earliest changeset you know exhibits the problem as
513 bad, then mark the latest changeset which is free from the problem
513 bad, then mark the latest changeset which is free from the problem
514 as good. Bisect will update your working directory to a revision
514 as good. Bisect will update your working directory to a revision
515 for testing (unless the -U/--noupdate option is specified). Once
515 for testing (unless the -U/--noupdate option is specified). Once
516 you have performed tests, mark the working directory as good or
516 you have performed tests, mark the working directory as good or
517 bad, and bisect will either update to another candidate changeset
517 bad, and bisect will either update to another candidate changeset
518 or announce that it has found the bad revision.
518 or announce that it has found the bad revision.
519
519
520 As a shortcut, you can also use the revision argument to mark a
520 As a shortcut, you can also use the revision argument to mark a
521 revision as good or bad without checking it out first.
521 revision as good or bad without checking it out first.
522
522
523 If you supply a command, it will be used for automatic bisection.
523 If you supply a command, it will be used for automatic bisection.
524 The environment variable HG_NODE will contain the ID of the
524 The environment variable HG_NODE will contain the ID of the
525 changeset being tested. The exit status of the command will be
525 changeset being tested. The exit status of the command will be
526 used to mark revisions as good or bad: status 0 means good, 125
526 used to mark revisions as good or bad: status 0 means good, 125
527 means to skip the revision, 127 (command not found) will abort the
527 means to skip the revision, 127 (command not found) will abort the
528 bisection, and any other non-zero exit status means the revision
528 bisection, and any other non-zero exit status means the revision
529 is bad.
529 is bad.
530
530
531 .. container:: verbose
531 .. container:: verbose
532
532
533 Some examples:
533 Some examples:
534
534
535 - start a bisection with known bad revision 12, and good revision 34::
535 - start a bisection with known bad revision 12, and good revision 34::
536
536
537 hg bisect --bad 34
537 hg bisect --bad 34
538 hg bisect --good 12
538 hg bisect --good 12
539
539
540 - advance the current bisection by marking current revision as good or
540 - advance the current bisection by marking current revision as good or
541 bad::
541 bad::
542
542
543 hg bisect --good
543 hg bisect --good
544 hg bisect --bad
544 hg bisect --bad
545
545
546 - mark the current revision, or a known revision, to be skipped (eg. if
546 - mark the current revision, or a known revision, to be skipped (eg. if
547 that revision is not usable because of another issue)::
547 that revision is not usable because of another issue)::
548
548
549 hg bisect --skip
549 hg bisect --skip
550 hg bisect --skip 23
550 hg bisect --skip 23
551
551
552 - forget the current bisection::
552 - forget the current bisection::
553
553
554 hg bisect --reset
554 hg bisect --reset
555
555
556 - use 'make && make tests' to automatically find the first broken
556 - use 'make && make tests' to automatically find the first broken
557 revision::
557 revision::
558
558
559 hg bisect --reset
559 hg bisect --reset
560 hg bisect --bad 34
560 hg bisect --bad 34
561 hg bisect --good 12
561 hg bisect --good 12
562 hg bisect --command 'make && make tests'
562 hg bisect --command 'make && make tests'
563
563
564 - see all changesets whose states are already known in the current
564 - see all changesets whose states are already known in the current
565 bisection::
565 bisection::
566
566
567 hg log -r "bisect(pruned)"
567 hg log -r "bisect(pruned)"
568
568
569 - see the changeset currently being bisected (especially useful
569 - see the changeset currently being bisected (especially useful
570 if running with -U/--noupdate)::
570 if running with -U/--noupdate)::
571
571
572 hg log -r "bisect(current)"
572 hg log -r "bisect(current)"
573
573
574 - see all changesets that took part in the current bisection::
574 - see all changesets that took part in the current bisection::
575
575
576 hg log -r "bisect(range)"
576 hg log -r "bisect(range)"
577
577
578 - with the graphlog extension, you can even get a nice graph::
578 - with the graphlog extension, you can even get a nice graph::
579
579
580 hg log --graph -r "bisect(range)"
580 hg log --graph -r "bisect(range)"
581
581
582 See :hg:`help revsets` for more about the `bisect()` keyword.
582 See :hg:`help revsets` for more about the `bisect()` keyword.
583
583
584 Returns 0 on success.
584 Returns 0 on success.
585 """
585 """
586 def extendbisectrange(nodes, good):
586 def extendbisectrange(nodes, good):
587 # bisect is incomplete when it ends on a merge node and
587 # bisect is incomplete when it ends on a merge node and
588 # one of the parent was not checked.
588 # one of the parent was not checked.
589 parents = repo[nodes[0]].parents()
589 parents = repo[nodes[0]].parents()
590 if len(parents) > 1:
590 if len(parents) > 1:
591 side = good and state['bad'] or state['good']
591 side = good and state['bad'] or state['good']
592 num = len(set(i.node() for i in parents) & set(side))
592 num = len(set(i.node() for i in parents) & set(side))
593 if num == 1:
593 if num == 1:
594 return parents[0].ancestor(parents[1])
594 return parents[0].ancestor(parents[1])
595 return None
595 return None
596
596
597 def print_result(nodes, good):
597 def print_result(nodes, good):
598 displayer = cmdutil.show_changeset(ui, repo, {})
598 displayer = cmdutil.show_changeset(ui, repo, {})
599 if len(nodes) == 1:
599 if len(nodes) == 1:
600 # narrowed it down to a single revision
600 # narrowed it down to a single revision
601 if good:
601 if good:
602 ui.write(_("The first good revision is:\n"))
602 ui.write(_("The first good revision is:\n"))
603 else:
603 else:
604 ui.write(_("The first bad revision is:\n"))
604 ui.write(_("The first bad revision is:\n"))
605 displayer.show(repo[nodes[0]])
605 displayer.show(repo[nodes[0]])
606 extendnode = extendbisectrange(nodes, good)
606 extendnode = extendbisectrange(nodes, good)
607 if extendnode is not None:
607 if extendnode is not None:
608 ui.write(_('Not all ancestors of this changeset have been'
608 ui.write(_('Not all ancestors of this changeset have been'
609 ' checked.\nUse bisect --extend to continue the '
609 ' checked.\nUse bisect --extend to continue the '
610 'bisection from\nthe common ancestor, %s.\n')
610 'bisection from\nthe common ancestor, %s.\n')
611 % extendnode)
611 % extendnode)
612 else:
612 else:
613 # multiple possible revisions
613 # multiple possible revisions
614 if good:
614 if good:
615 ui.write(_("Due to skipped revisions, the first "
615 ui.write(_("Due to skipped revisions, the first "
616 "good revision could be any of:\n"))
616 "good revision could be any of:\n"))
617 else:
617 else:
618 ui.write(_("Due to skipped revisions, the first "
618 ui.write(_("Due to skipped revisions, the first "
619 "bad revision could be any of:\n"))
619 "bad revision could be any of:\n"))
620 for n in nodes:
620 for n in nodes:
621 displayer.show(repo[n])
621 displayer.show(repo[n])
622 displayer.close()
622 displayer.close()
623
623
624 def check_state(state, interactive=True):
624 def check_state(state, interactive=True):
625 if not state['good'] or not state['bad']:
625 if not state['good'] or not state['bad']:
626 if (good or bad or skip or reset) and interactive:
626 if (good or bad or skip or reset) and interactive:
627 return
627 return
628 if not state['good']:
628 if not state['good']:
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
630 else:
630 else:
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
632 return True
632 return True
633
633
634 # backward compatibility
634 # backward compatibility
635 if rev in "good bad reset init".split():
635 if rev in "good bad reset init".split():
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
637 cmd, rev, extra = rev, extra, None
637 cmd, rev, extra = rev, extra, None
638 if cmd == "good":
638 if cmd == "good":
639 good = True
639 good = True
640 elif cmd == "bad":
640 elif cmd == "bad":
641 bad = True
641 bad = True
642 else:
642 else:
643 reset = True
643 reset = True
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
645 raise util.Abort(_('incompatible arguments'))
645 raise util.Abort(_('incompatible arguments'))
646
646
647 if reset:
647 if reset:
648 p = repo.join("bisect.state")
648 p = repo.join("bisect.state")
649 if os.path.exists(p):
649 if os.path.exists(p):
650 os.unlink(p)
650 os.unlink(p)
651 return
651 return
652
652
653 state = hbisect.load_state(repo)
653 state = hbisect.load_state(repo)
654
654
655 if command:
655 if command:
656 changesets = 1
656 changesets = 1
657 try:
657 try:
658 node = state['current'][0]
658 node = state['current'][0]
659 except LookupError:
659 except LookupError:
660 if noupdate:
660 if noupdate:
661 raise util.Abort(_('current bisect revision is unknown - '
661 raise util.Abort(_('current bisect revision is unknown - '
662 'start a new bisect to fix'))
662 'start a new bisect to fix'))
663 node, p2 = repo.dirstate.parents()
663 node, p2 = repo.dirstate.parents()
664 if p2 != nullid:
664 if p2 != nullid:
665 raise util.Abort(_('current bisect revision is a merge'))
665 raise util.Abort(_('current bisect revision is a merge'))
666 try:
666 try:
667 while changesets:
667 while changesets:
668 # update state
668 # update state
669 state['current'] = [node]
669 state['current'] = [node]
670 hbisect.save_state(repo, state)
670 hbisect.save_state(repo, state)
671 status = util.system(command,
671 status = util.system(command,
672 environ={'HG_NODE': hex(node)},
672 environ={'HG_NODE': hex(node)},
673 out=ui.fout)
673 out=ui.fout)
674 if status == 125:
674 if status == 125:
675 transition = "skip"
675 transition = "skip"
676 elif status == 0:
676 elif status == 0:
677 transition = "good"
677 transition = "good"
678 # status < 0 means process was killed
678 # status < 0 means process was killed
679 elif status == 127:
679 elif status == 127:
680 raise util.Abort(_("failed to execute %s") % command)
680 raise util.Abort(_("failed to execute %s") % command)
681 elif status < 0:
681 elif status < 0:
682 raise util.Abort(_("%s killed") % command)
682 raise util.Abort(_("%s killed") % command)
683 else:
683 else:
684 transition = "bad"
684 transition = "bad"
685 ctx = scmutil.revsingle(repo, rev, node)
685 ctx = scmutil.revsingle(repo, rev, node)
686 rev = None # clear for future iterations
686 rev = None # clear for future iterations
687 state[transition].append(ctx.node())
687 state[transition].append(ctx.node())
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
689 check_state(state, interactive=False)
689 check_state(state, interactive=False)
690 # bisect
690 # bisect
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
692 # update to next check
692 # update to next check
693 node = nodes[0]
693 node = nodes[0]
694 if not noupdate:
694 if not noupdate:
695 cmdutil.bailifchanged(repo)
695 cmdutil.bailifchanged(repo)
696 hg.clean(repo, node, show_stats=False)
696 hg.clean(repo, node, show_stats=False)
697 finally:
697 finally:
698 state['current'] = [node]
698 state['current'] = [node]
699 hbisect.save_state(repo, state)
699 hbisect.save_state(repo, state)
700 print_result(nodes, good)
700 print_result(nodes, good)
701 return
701 return
702
702
703 # update state
703 # update state
704
704
705 if rev:
705 if rev:
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
707 else:
707 else:
708 nodes = [repo.lookup('.')]
708 nodes = [repo.lookup('.')]
709
709
710 if good or bad or skip:
710 if good or bad or skip:
711 if good:
711 if good:
712 state['good'] += nodes
712 state['good'] += nodes
713 elif bad:
713 elif bad:
714 state['bad'] += nodes
714 state['bad'] += nodes
715 elif skip:
715 elif skip:
716 state['skip'] += nodes
716 state['skip'] += nodes
717 hbisect.save_state(repo, state)
717 hbisect.save_state(repo, state)
718
718
719 if not check_state(state):
719 if not check_state(state):
720 return
720 return
721
721
722 # actually bisect
722 # actually bisect
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
724 if extend:
724 if extend:
725 if not changesets:
725 if not changesets:
726 extendnode = extendbisectrange(nodes, good)
726 extendnode = extendbisectrange(nodes, good)
727 if extendnode is not None:
727 if extendnode is not None:
728 ui.write(_("Extending search to changeset %d:%s\n"
728 ui.write(_("Extending search to changeset %d:%s\n"
729 % (extendnode.rev(), extendnode)))
729 % (extendnode.rev(), extendnode)))
730 state['current'] = [extendnode.node()]
730 state['current'] = [extendnode.node()]
731 hbisect.save_state(repo, state)
731 hbisect.save_state(repo, state)
732 if noupdate:
732 if noupdate:
733 return
733 return
734 cmdutil.bailifchanged(repo)
734 cmdutil.bailifchanged(repo)
735 return hg.clean(repo, extendnode.node())
735 return hg.clean(repo, extendnode.node())
736 raise util.Abort(_("nothing to extend"))
736 raise util.Abort(_("nothing to extend"))
737
737
738 if changesets == 0:
738 if changesets == 0:
739 print_result(nodes, good)
739 print_result(nodes, good)
740 else:
740 else:
741 assert len(nodes) == 1 # only a single node can be tested next
741 assert len(nodes) == 1 # only a single node can be tested next
742 node = nodes[0]
742 node = nodes[0]
743 # compute the approximate number of remaining tests
743 # compute the approximate number of remaining tests
744 tests, size = 0, 2
744 tests, size = 0, 2
745 while size <= changesets:
745 while size <= changesets:
746 tests, size = tests + 1, size * 2
746 tests, size = tests + 1, size * 2
747 rev = repo.changelog.rev(node)
747 rev = repo.changelog.rev(node)
748 ui.write(_("Testing changeset %d:%s "
748 ui.write(_("Testing changeset %d:%s "
749 "(%d changesets remaining, ~%d tests)\n")
749 "(%d changesets remaining, ~%d tests)\n")
750 % (rev, short(node), changesets, tests))
750 % (rev, short(node), changesets, tests))
751 state['current'] = [node]
751 state['current'] = [node]
752 hbisect.save_state(repo, state)
752 hbisect.save_state(repo, state)
753 if not noupdate:
753 if not noupdate:
754 cmdutil.bailifchanged(repo)
754 cmdutil.bailifchanged(repo)
755 return hg.clean(repo, node)
755 return hg.clean(repo, node)
756
756
757 @command('bookmarks',
757 @command('bookmarks',
758 [('f', 'force', False, _('force')),
758 [('f', 'force', False, _('force')),
759 ('r', 'rev', '', _('revision'), _('REV')),
759 ('r', 'rev', '', _('revision'), _('REV')),
760 ('d', 'delete', False, _('delete a given bookmark')),
760 ('d', 'delete', False, _('delete a given bookmark')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
765 rename=None, inactive=False):
765 rename=None, inactive=False):
766 '''track a line of development with movable markers
766 '''track a line of development with movable markers
767
767
768 Bookmarks are pointers to certain commits that move when committing.
768 Bookmarks are pointers to certain commits that move when committing.
769 Bookmarks are local. They can be renamed, copied and deleted. It is
769 Bookmarks are local. They can be renamed, copied and deleted. It is
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
771 :hg:`update NAME` to update to a given bookmark.
771 :hg:`update NAME` to update to a given bookmark.
772
772
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
774 directory's parent revision with the given name. If you specify
774 directory's parent revision with the given name. If you specify
775 a revision using -r REV (where REV may be an existing bookmark),
775 a revision using -r REV (where REV may be an existing bookmark),
776 the bookmark is assigned to that revision.
776 the bookmark is assigned to that revision.
777
777
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
779 push` and :hg:`help pull`). This requires both the local and remote
779 push` and :hg:`help pull`). This requires both the local and remote
780 repositories to support bookmarks. For versions prior to 1.8, this means
780 repositories to support bookmarks. For versions prior to 1.8, this means
781 the bookmarks extension must be enabled.
781 the bookmarks extension must be enabled.
782
782
783 With -i/--inactive, the new bookmark will not be made the active
783 With -i/--inactive, the new bookmark will not be made the active
784 bookmark. If -r/--rev is given, the new bookmark will not be made
784 bookmark. If -r/--rev is given, the new bookmark will not be made
785 active even if -i/--inactive is not given. If no NAME is given, the
785 active even if -i/--inactive is not given. If no NAME is given, the
786 current active bookmark will be marked inactive.
786 current active bookmark will be marked inactive.
787 '''
787 '''
788 hexfn = ui.debugflag and hex or short
788 hexfn = ui.debugflag and hex or short
789 marks = repo._bookmarks
789 marks = repo._bookmarks
790 cur = repo.changectx('.').node()
790 cur = repo.changectx('.').node()
791
791
792 if delete:
792 if delete:
793 if mark is None:
793 if mark is None:
794 raise util.Abort(_("bookmark name required"))
794 raise util.Abort(_("bookmark name required"))
795 if mark not in marks:
795 if mark not in marks:
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
797 if mark == repo._bookmarkcurrent:
797 if mark == repo._bookmarkcurrent:
798 bookmarks.setcurrent(repo, None)
798 bookmarks.setcurrent(repo, None)
799 del marks[mark]
799 del marks[mark]
800 bookmarks.write(repo)
800 bookmarks.write(repo)
801 return
801 return
802
802
803 if rename:
803 if rename:
804 if rename not in marks:
804 if rename not in marks:
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
806 if mark in marks and not force:
806 if mark in marks and not force:
807 raise util.Abort(_("bookmark '%s' already exists "
807 raise util.Abort(_("bookmark '%s' already exists "
808 "(use -f to force)") % mark)
808 "(use -f to force)") % mark)
809 if mark is None:
809 if mark is None:
810 raise util.Abort(_("new bookmark name required"))
810 raise util.Abort(_("new bookmark name required"))
811 marks[mark] = marks[rename]
811 marks[mark] = marks[rename]
812 if repo._bookmarkcurrent == rename and not inactive:
812 if repo._bookmarkcurrent == rename and not inactive:
813 bookmarks.setcurrent(repo, mark)
813 bookmarks.setcurrent(repo, mark)
814 del marks[rename]
814 del marks[rename]
815 bookmarks.write(repo)
815 bookmarks.write(repo)
816 return
816 return
817
817
818 if mark is not None:
818 if mark is not None:
819 if "\n" in mark:
819 if "\n" in mark:
820 raise util.Abort(_("bookmark name cannot contain newlines"))
820 raise util.Abort(_("bookmark name cannot contain newlines"))
821 mark = mark.strip()
821 mark = mark.strip()
822 if not mark:
822 if not mark:
823 raise util.Abort(_("bookmark names cannot consist entirely of "
823 raise util.Abort(_("bookmark names cannot consist entirely of "
824 "whitespace"))
824 "whitespace"))
825 if inactive and mark == repo._bookmarkcurrent:
825 if inactive and mark == repo._bookmarkcurrent:
826 bookmarks.setcurrent(repo, None)
826 bookmarks.setcurrent(repo, None)
827 return
827 return
828 if mark in marks and not force:
828 if mark in marks and not force:
829 raise util.Abort(_("bookmark '%s' already exists "
829 raise util.Abort(_("bookmark '%s' already exists "
830 "(use -f to force)") % mark)
830 "(use -f to force)") % mark)
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
832 and not force):
832 and not force):
833 raise util.Abort(
833 raise util.Abort(
834 _("a bookmark cannot have the name of an existing branch"))
834 _("a bookmark cannot have the name of an existing branch"))
835 if rev:
835 if rev:
836 marks[mark] = repo.lookup(rev)
836 marks[mark] = repo.lookup(rev)
837 else:
837 else:
838 marks[mark] = cur
838 marks[mark] = cur
839 if not inactive and cur == marks[mark]:
839 if not inactive and cur == marks[mark]:
840 bookmarks.setcurrent(repo, mark)
840 bookmarks.setcurrent(repo, mark)
841 bookmarks.write(repo)
841 bookmarks.write(repo)
842 return
842 return
843
843
844 if mark is None:
844 if mark is None:
845 if rev:
845 if rev:
846 raise util.Abort(_("bookmark name required"))
846 raise util.Abort(_("bookmark name required"))
847 if len(marks) == 0:
847 if len(marks) == 0:
848 ui.status(_("no bookmarks set\n"))
848 ui.status(_("no bookmarks set\n"))
849 else:
849 else:
850 for bmark, n in sorted(marks.iteritems()):
850 for bmark, n in sorted(marks.iteritems()):
851 current = repo._bookmarkcurrent
851 current = repo._bookmarkcurrent
852 if bmark == current and n == cur:
852 if bmark == current and n == cur:
853 prefix, label = '*', 'bookmarks.current'
853 prefix, label = '*', 'bookmarks.current'
854 else:
854 else:
855 prefix, label = ' ', ''
855 prefix, label = ' ', ''
856
856
857 if ui.quiet:
857 if ui.quiet:
858 ui.write("%s\n" % bmark, label=label)
858 ui.write("%s\n" % bmark, label=label)
859 else:
859 else:
860 ui.write(" %s %-25s %d:%s\n" % (
860 ui.write(" %s %-25s %d:%s\n" % (
861 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
861 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
862 label=label)
862 label=label)
863 return
863 return
864
864
865 @command('branch',
865 @command('branch',
866 [('f', 'force', None,
866 [('f', 'force', None,
867 _('set branch name even if it shadows an existing branch')),
867 _('set branch name even if it shadows an existing branch')),
868 ('C', 'clean', None, _('reset branch name to parent branch name'))],
868 ('C', 'clean', None, _('reset branch name to parent branch name'))],
869 _('[-fC] [NAME]'))
869 _('[-fC] [NAME]'))
870 def branch(ui, repo, label=None, **opts):
870 def branch(ui, repo, label=None, **opts):
871 """set or show the current branch name
871 """set or show the current branch name
872
872
873 .. note::
873 .. note::
874 Branch names are permanent and global. Use :hg:`bookmark` to create a
874 Branch names are permanent and global. Use :hg:`bookmark` to create a
875 light-weight bookmark instead. See :hg:`help glossary` for more
875 light-weight bookmark instead. See :hg:`help glossary` for more
876 information about named branches and bookmarks.
876 information about named branches and bookmarks.
877
877
878 With no argument, show the current branch name. With one argument,
878 With no argument, show the current branch name. With one argument,
879 set the working directory branch name (the branch will not exist
879 set the working directory branch name (the branch will not exist
880 in the repository until the next commit). Standard practice
880 in the repository until the next commit). Standard practice
881 recommends that primary development take place on the 'default'
881 recommends that primary development take place on the 'default'
882 branch.
882 branch.
883
883
884 Unless -f/--force is specified, branch will not let you set a
884 Unless -f/--force is specified, branch will not let you set a
885 branch name that already exists, even if it's inactive.
885 branch name that already exists, even if it's inactive.
886
886
887 Use -C/--clean to reset the working directory branch to that of
887 Use -C/--clean to reset the working directory branch to that of
888 the parent of the working directory, negating a previous branch
888 the parent of the working directory, negating a previous branch
889 change.
889 change.
890
890
891 Use the command :hg:`update` to switch to an existing branch. Use
891 Use the command :hg:`update` to switch to an existing branch. Use
892 :hg:`commit --close-branch` to mark this branch as closed.
892 :hg:`commit --close-branch` to mark this branch as closed.
893
893
894 Returns 0 on success.
894 Returns 0 on success.
895 """
895 """
896 if not opts.get('clean') and not label:
896 if not opts.get('clean') and not label:
897 ui.write("%s\n" % repo.dirstate.branch())
897 ui.write("%s\n" % repo.dirstate.branch())
898 return
898 return
899
899
900 wlock = repo.wlock()
900 wlock = repo.wlock()
901 try:
901 try:
902 if opts.get('clean'):
902 if opts.get('clean'):
903 label = repo[None].p1().branch()
903 label = repo[None].p1().branch()
904 repo.dirstate.setbranch(label)
904 repo.dirstate.setbranch(label)
905 ui.status(_('reset working directory to branch %s\n') % label)
905 ui.status(_('reset working directory to branch %s\n') % label)
906 elif label:
906 elif label:
907 if not opts.get('force') and label in repo.branchmap():
907 if not opts.get('force') and label in repo.branchmap():
908 if label not in [p.branch() for p in repo.parents()]:
908 if label not in [p.branch() for p in repo.parents()]:
909 raise util.Abort(_('a branch of the same name already'
909 raise util.Abort(_('a branch of the same name already'
910 ' exists'),
910 ' exists'),
911 # i18n: "it" refers to an existing branch
911 # i18n: "it" refers to an existing branch
912 hint=_("use 'hg update' to switch to it"))
912 hint=_("use 'hg update' to switch to it"))
913 repo.dirstate.setbranch(label)
913 repo.dirstate.setbranch(label)
914 ui.status(_('marked working directory as branch %s\n') % label)
914 ui.status(_('marked working directory as branch %s\n') % label)
915 ui.status(_('(branches are permanent and global, '
915 ui.status(_('(branches are permanent and global, '
916 'did you want a bookmark?)\n'))
916 'did you want a bookmark?)\n'))
917 finally:
917 finally:
918 wlock.release()
918 wlock.release()
919
919
920 @command('branches',
920 @command('branches',
921 [('a', 'active', False, _('show only branches that have unmerged heads')),
921 [('a', 'active', False, _('show only branches that have unmerged heads')),
922 ('c', 'closed', False, _('show normal and closed branches'))],
922 ('c', 'closed', False, _('show normal and closed branches'))],
923 _('[-ac]'))
923 _('[-ac]'))
924 def branches(ui, repo, active=False, closed=False):
924 def branches(ui, repo, active=False, closed=False):
925 """list repository named branches
925 """list repository named branches
926
926
927 List the repository's named branches, indicating which ones are
927 List the repository's named branches, indicating which ones are
928 inactive. If -c/--closed is specified, also list branches which have
928 inactive. If -c/--closed is specified, also list branches which have
929 been marked closed (see :hg:`commit --close-branch`).
929 been marked closed (see :hg:`commit --close-branch`).
930
930
931 If -a/--active is specified, only show active branches. A branch
931 If -a/--active is specified, only show active branches. A branch
932 is considered active if it contains repository heads.
932 is considered active if it contains repository heads.
933
933
934 Use the command :hg:`update` to switch to an existing branch.
934 Use the command :hg:`update` to switch to an existing branch.
935
935
936 Returns 0.
936 Returns 0.
937 """
937 """
938
938
939 hexfunc = ui.debugflag and hex or short
939 hexfunc = ui.debugflag and hex or short
940
940
941 activebranches = set([repo[n].branch() for n in repo.heads()])
941 activebranches = set([repo[n].branch() for n in repo.heads()])
942 branches = []
942 branches = []
943 for tag, heads in repo.branchmap().iteritems():
943 for tag, heads in repo.branchmap().iteritems():
944 for h in reversed(heads):
944 for h in reversed(heads):
945 ctx = repo[h]
945 ctx = repo[h]
946 isopen = not ctx.closesbranch()
946 isopen = not ctx.closesbranch()
947 if isopen:
947 if isopen:
948 tip = ctx
948 tip = ctx
949 break
949 break
950 else:
950 else:
951 tip = repo[heads[-1]]
951 tip = repo[heads[-1]]
952 isactive = tag in activebranches and isopen
952 isactive = tag in activebranches and isopen
953 branches.append((tip, isactive, isopen))
953 branches.append((tip, isactive, isopen))
954 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
954 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
955 reverse=True)
955 reverse=True)
956
956
957 for ctx, isactive, isopen in branches:
957 for ctx, isactive, isopen in branches:
958 if (not active) or isactive:
958 if (not active) or isactive:
959 if isactive:
959 if isactive:
960 label = 'branches.active'
960 label = 'branches.active'
961 notice = ''
961 notice = ''
962 elif not isopen:
962 elif not isopen:
963 if not closed:
963 if not closed:
964 continue
964 continue
965 label = 'branches.closed'
965 label = 'branches.closed'
966 notice = _(' (closed)')
966 notice = _(' (closed)')
967 else:
967 else:
968 label = 'branches.inactive'
968 label = 'branches.inactive'
969 notice = _(' (inactive)')
969 notice = _(' (inactive)')
970 if ctx.branch() == repo.dirstate.branch():
970 if ctx.branch() == repo.dirstate.branch():
971 label = 'branches.current'
971 label = 'branches.current'
972 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
972 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
973 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
973 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
974 'log.changeset')
974 'log.changeset')
975 tag = ui.label(ctx.branch(), label)
975 tag = ui.label(ctx.branch(), label)
976 if ui.quiet:
976 if ui.quiet:
977 ui.write("%s\n" % tag)
977 ui.write("%s\n" % tag)
978 else:
978 else:
979 ui.write("%s %s%s\n" % (tag, rev, notice))
979 ui.write("%s %s%s\n" % (tag, rev, notice))
980
980
981 @command('bundle',
981 @command('bundle',
982 [('f', 'force', None, _('run even when the destination is unrelated')),
982 [('f', 'force', None, _('run even when the destination is unrelated')),
983 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
983 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
984 _('REV')),
984 _('REV')),
985 ('b', 'branch', [], _('a specific branch you would like to bundle'),
985 ('b', 'branch', [], _('a specific branch you would like to bundle'),
986 _('BRANCH')),
986 _('BRANCH')),
987 ('', 'base', [],
987 ('', 'base', [],
988 _('a base changeset assumed to be available at the destination'),
988 _('a base changeset assumed to be available at the destination'),
989 _('REV')),
989 _('REV')),
990 ('a', 'all', None, _('bundle all changesets in the repository')),
990 ('a', 'all', None, _('bundle all changesets in the repository')),
991 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
991 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
992 ] + remoteopts,
992 ] + remoteopts,
993 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
993 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
994 def bundle(ui, repo, fname, dest=None, **opts):
994 def bundle(ui, repo, fname, dest=None, **opts):
995 """create a changegroup file
995 """create a changegroup file
996
996
997 Generate a compressed changegroup file collecting changesets not
997 Generate a compressed changegroup file collecting changesets not
998 known to be in another repository.
998 known to be in another repository.
999
999
1000 If you omit the destination repository, then hg assumes the
1000 If you omit the destination repository, then hg assumes the
1001 destination will have all the nodes you specify with --base
1001 destination will have all the nodes you specify with --base
1002 parameters. To create a bundle containing all changesets, use
1002 parameters. To create a bundle containing all changesets, use
1003 -a/--all (or --base null).
1003 -a/--all (or --base null).
1004
1004
1005 You can change compression method with the -t/--type option.
1005 You can change compression method with the -t/--type option.
1006 The available compression methods are: none, bzip2, and
1006 The available compression methods are: none, bzip2, and
1007 gzip (by default, bundles are compressed using bzip2).
1007 gzip (by default, bundles are compressed using bzip2).
1008
1008
1009 The bundle file can then be transferred using conventional means
1009 The bundle file can then be transferred using conventional means
1010 and applied to another repository with the unbundle or pull
1010 and applied to another repository with the unbundle or pull
1011 command. This is useful when direct push and pull are not
1011 command. This is useful when direct push and pull are not
1012 available or when exporting an entire repository is undesirable.
1012 available or when exporting an entire repository is undesirable.
1013
1013
1014 Applying bundles preserves all changeset contents including
1014 Applying bundles preserves all changeset contents including
1015 permissions, copy/rename information, and revision history.
1015 permissions, copy/rename information, and revision history.
1016
1016
1017 Returns 0 on success, 1 if no changes found.
1017 Returns 0 on success, 1 if no changes found.
1018 """
1018 """
1019 revs = None
1019 revs = None
1020 if 'rev' in opts:
1020 if 'rev' in opts:
1021 revs = scmutil.revrange(repo, opts['rev'])
1021 revs = scmutil.revrange(repo, opts['rev'])
1022
1022
1023 bundletype = opts.get('type', 'bzip2').lower()
1023 bundletype = opts.get('type', 'bzip2').lower()
1024 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1024 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1025 bundletype = btypes.get(bundletype)
1025 bundletype = btypes.get(bundletype)
1026 if bundletype not in changegroup.bundletypes:
1026 if bundletype not in changegroup.bundletypes:
1027 raise util.Abort(_('unknown bundle type specified with --type'))
1027 raise util.Abort(_('unknown bundle type specified with --type'))
1028
1028
1029 if opts.get('all'):
1029 if opts.get('all'):
1030 base = ['null']
1030 base = ['null']
1031 else:
1031 else:
1032 base = scmutil.revrange(repo, opts.get('base'))
1032 base = scmutil.revrange(repo, opts.get('base'))
1033 if base:
1033 if base:
1034 if dest:
1034 if dest:
1035 raise util.Abort(_("--base is incompatible with specifying "
1035 raise util.Abort(_("--base is incompatible with specifying "
1036 "a destination"))
1036 "a destination"))
1037 common = [repo.lookup(rev) for rev in base]
1037 common = [repo.lookup(rev) for rev in base]
1038 heads = revs and map(repo.lookup, revs) or revs
1038 heads = revs and map(repo.lookup, revs) or revs
1039 cg = repo.getbundle('bundle', heads=heads, common=common)
1039 cg = repo.getbundle('bundle', heads=heads, common=common)
1040 outgoing = None
1040 outgoing = None
1041 else:
1041 else:
1042 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1042 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1043 dest, branches = hg.parseurl(dest, opts.get('branch'))
1043 dest, branches = hg.parseurl(dest, opts.get('branch'))
1044 other = hg.peer(repo, opts, dest)
1044 other = hg.peer(repo, opts, dest)
1045 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1045 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1046 heads = revs and map(repo.lookup, revs) or revs
1046 heads = revs and map(repo.lookup, revs) or revs
1047 outgoing = discovery.findcommonoutgoing(repo, other,
1047 outgoing = discovery.findcommonoutgoing(repo, other,
1048 onlyheads=heads,
1048 onlyheads=heads,
1049 force=opts.get('force'),
1049 force=opts.get('force'),
1050 portable=True)
1050 portable=True)
1051 cg = repo.getlocalbundle('bundle', outgoing)
1051 cg = repo.getlocalbundle('bundle', outgoing)
1052 if not cg:
1052 if not cg:
1053 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1053 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1054 return 1
1054 return 1
1055
1055
1056 changegroup.writebundle(cg, fname, bundletype)
1056 changegroup.writebundle(cg, fname, bundletype)
1057
1057
1058 @command('cat',
1058 @command('cat',
1059 [('o', 'output', '',
1059 [('o', 'output', '',
1060 _('print output to file with formatted name'), _('FORMAT')),
1060 _('print output to file with formatted name'), _('FORMAT')),
1061 ('r', 'rev', '', _('print the given revision'), _('REV')),
1061 ('r', 'rev', '', _('print the given revision'), _('REV')),
1062 ('', 'decode', None, _('apply any matching decode filter')),
1062 ('', 'decode', None, _('apply any matching decode filter')),
1063 ] + walkopts,
1063 ] + walkopts,
1064 _('[OPTION]... FILE...'))
1064 _('[OPTION]... FILE...'))
1065 def cat(ui, repo, file1, *pats, **opts):
1065 def cat(ui, repo, file1, *pats, **opts):
1066 """output the current or given revision of files
1066 """output the current or given revision of files
1067
1067
1068 Print the specified files as they were at the given revision. If
1068 Print the specified files as they were at the given revision. If
1069 no revision is given, the parent of the working directory is used,
1069 no revision is given, the parent of the working directory is used,
1070 or tip if no revision is checked out.
1070 or tip if no revision is checked out.
1071
1071
1072 Output may be to a file, in which case the name of the file is
1072 Output may be to a file, in which case the name of the file is
1073 given using a format string. The formatting rules are the same as
1073 given using a format string. The formatting rules are the same as
1074 for the export command, with the following additions:
1074 for the export command, with the following additions:
1075
1075
1076 :``%s``: basename of file being printed
1076 :``%s``: basename of file being printed
1077 :``%d``: dirname of file being printed, or '.' if in repository root
1077 :``%d``: dirname of file being printed, or '.' if in repository root
1078 :``%p``: root-relative path name of file being printed
1078 :``%p``: root-relative path name of file being printed
1079
1079
1080 Returns 0 on success.
1080 Returns 0 on success.
1081 """
1081 """
1082 ctx = scmutil.revsingle(repo, opts.get('rev'))
1082 ctx = scmutil.revsingle(repo, opts.get('rev'))
1083 err = 1
1083 err = 1
1084 m = scmutil.match(ctx, (file1,) + pats, opts)
1084 m = scmutil.match(ctx, (file1,) + pats, opts)
1085 for abs in ctx.walk(m):
1085 for abs in ctx.walk(m):
1086 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1086 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1087 pathname=abs)
1087 pathname=abs)
1088 data = ctx[abs].data()
1088 data = ctx[abs].data()
1089 if opts.get('decode'):
1089 if opts.get('decode'):
1090 data = repo.wwritedata(abs, data)
1090 data = repo.wwritedata(abs, data)
1091 fp.write(data)
1091 fp.write(data)
1092 fp.close()
1092 fp.close()
1093 err = 0
1093 err = 0
1094 return err
1094 return err
1095
1095
1096 @command('^clone',
1096 @command('^clone',
1097 [('U', 'noupdate', None,
1097 [('U', 'noupdate', None,
1098 _('the clone will include an empty working copy (only a repository)')),
1098 _('the clone will include an empty working copy (only a repository)')),
1099 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1099 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1100 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1100 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1101 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1101 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1102 ('', 'pull', None, _('use pull protocol to copy metadata')),
1102 ('', 'pull', None, _('use pull protocol to copy metadata')),
1103 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1103 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1104 ] + remoteopts,
1104 ] + remoteopts,
1105 _('[OPTION]... SOURCE [DEST]'))
1105 _('[OPTION]... SOURCE [DEST]'))
1106 def clone(ui, source, dest=None, **opts):
1106 def clone(ui, source, dest=None, **opts):
1107 """make a copy of an existing repository
1107 """make a copy of an existing repository
1108
1108
1109 Create a copy of an existing repository in a new directory.
1109 Create a copy of an existing repository in a new directory.
1110
1110
1111 If no destination directory name is specified, it defaults to the
1111 If no destination directory name is specified, it defaults to the
1112 basename of the source.
1112 basename of the source.
1113
1113
1114 The location of the source is added to the new repository's
1114 The location of the source is added to the new repository's
1115 ``.hg/hgrc`` file, as the default to be used for future pulls.
1115 ``.hg/hgrc`` file, as the default to be used for future pulls.
1116
1116
1117 Only local paths and ``ssh://`` URLs are supported as
1117 Only local paths and ``ssh://`` URLs are supported as
1118 destinations. For ``ssh://`` destinations, no working directory or
1118 destinations. For ``ssh://`` destinations, no working directory or
1119 ``.hg/hgrc`` will be created on the remote side.
1119 ``.hg/hgrc`` will be created on the remote side.
1120
1120
1121 To pull only a subset of changesets, specify one or more revisions
1121 To pull only a subset of changesets, specify one or more revisions
1122 identifiers with -r/--rev or branches with -b/--branch. The
1122 identifiers with -r/--rev or branches with -b/--branch. The
1123 resulting clone will contain only the specified changesets and
1123 resulting clone will contain only the specified changesets and
1124 their ancestors. These options (or 'clone src#rev dest') imply
1124 their ancestors. These options (or 'clone src#rev dest') imply
1125 --pull, even for local source repositories. Note that specifying a
1125 --pull, even for local source repositories. Note that specifying a
1126 tag will include the tagged changeset but not the changeset
1126 tag will include the tagged changeset but not the changeset
1127 containing the tag.
1127 containing the tag.
1128
1128
1129 To check out a particular version, use -u/--update, or
1129 To check out a particular version, use -u/--update, or
1130 -U/--noupdate to create a clone with no working directory.
1130 -U/--noupdate to create a clone with no working directory.
1131
1131
1132 .. container:: verbose
1132 .. container:: verbose
1133
1133
1134 For efficiency, hardlinks are used for cloning whenever the
1134 For efficiency, hardlinks are used for cloning whenever the
1135 source and destination are on the same filesystem (note this
1135 source and destination are on the same filesystem (note this
1136 applies only to the repository data, not to the working
1136 applies only to the repository data, not to the working
1137 directory). Some filesystems, such as AFS, implement hardlinking
1137 directory). Some filesystems, such as AFS, implement hardlinking
1138 incorrectly, but do not report errors. In these cases, use the
1138 incorrectly, but do not report errors. In these cases, use the
1139 --pull option to avoid hardlinking.
1139 --pull option to avoid hardlinking.
1140
1140
1141 In some cases, you can clone repositories and the working
1141 In some cases, you can clone repositories and the working
1142 directory using full hardlinks with ::
1142 directory using full hardlinks with ::
1143
1143
1144 $ cp -al REPO REPOCLONE
1144 $ cp -al REPO REPOCLONE
1145
1145
1146 This is the fastest way to clone, but it is not always safe. The
1146 This is the fastest way to clone, but it is not always safe. The
1147 operation is not atomic (making sure REPO is not modified during
1147 operation is not atomic (making sure REPO is not modified during
1148 the operation is up to you) and you have to make sure your
1148 the operation is up to you) and you have to make sure your
1149 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1149 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1150 so). Also, this is not compatible with certain extensions that
1150 so). Also, this is not compatible with certain extensions that
1151 place their metadata under the .hg directory, such as mq.
1151 place their metadata under the .hg directory, such as mq.
1152
1152
1153 Mercurial will update the working directory to the first applicable
1153 Mercurial will update the working directory to the first applicable
1154 revision from this list:
1154 revision from this list:
1155
1155
1156 a) null if -U or the source repository has no changesets
1156 a) null if -U or the source repository has no changesets
1157 b) if -u . and the source repository is local, the first parent of
1157 b) if -u . and the source repository is local, the first parent of
1158 the source repository's working directory
1158 the source repository's working directory
1159 c) the changeset specified with -u (if a branch name, this means the
1159 c) the changeset specified with -u (if a branch name, this means the
1160 latest head of that branch)
1160 latest head of that branch)
1161 d) the changeset specified with -r
1161 d) the changeset specified with -r
1162 e) the tipmost head specified with -b
1162 e) the tipmost head specified with -b
1163 f) the tipmost head specified with the url#branch source syntax
1163 f) the tipmost head specified with the url#branch source syntax
1164 g) the tipmost head of the default branch
1164 g) the tipmost head of the default branch
1165 h) tip
1165 h) tip
1166
1166
1167 Examples:
1167 Examples:
1168
1168
1169 - clone a remote repository to a new directory named hg/::
1169 - clone a remote repository to a new directory named hg/::
1170
1170
1171 hg clone http://selenic.com/hg
1171 hg clone http://selenic.com/hg
1172
1172
1173 - create a lightweight local clone::
1173 - create a lightweight local clone::
1174
1174
1175 hg clone project/ project-feature/
1175 hg clone project/ project-feature/
1176
1176
1177 - clone from an absolute path on an ssh server (note double-slash)::
1177 - clone from an absolute path on an ssh server (note double-slash)::
1178
1178
1179 hg clone ssh://user@server//home/projects/alpha/
1179 hg clone ssh://user@server//home/projects/alpha/
1180
1180
1181 - do a high-speed clone over a LAN while checking out a
1181 - do a high-speed clone over a LAN while checking out a
1182 specified version::
1182 specified version::
1183
1183
1184 hg clone --uncompressed http://server/repo -u 1.5
1184 hg clone --uncompressed http://server/repo -u 1.5
1185
1185
1186 - create a repository without changesets after a particular revision::
1186 - create a repository without changesets after a particular revision::
1187
1187
1188 hg clone -r 04e544 experimental/ good/
1188 hg clone -r 04e544 experimental/ good/
1189
1189
1190 - clone (and track) a particular named branch::
1190 - clone (and track) a particular named branch::
1191
1191
1192 hg clone http://selenic.com/hg#stable
1192 hg clone http://selenic.com/hg#stable
1193
1193
1194 See :hg:`help urls` for details on specifying URLs.
1194 See :hg:`help urls` for details on specifying URLs.
1195
1195
1196 Returns 0 on success.
1196 Returns 0 on success.
1197 """
1197 """
1198 if opts.get('noupdate') and opts.get('updaterev'):
1198 if opts.get('noupdate') and opts.get('updaterev'):
1199 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1199 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1200
1200
1201 r = hg.clone(ui, opts, source, dest,
1201 r = hg.clone(ui, opts, source, dest,
1202 pull=opts.get('pull'),
1202 pull=opts.get('pull'),
1203 stream=opts.get('uncompressed'),
1203 stream=opts.get('uncompressed'),
1204 rev=opts.get('rev'),
1204 rev=opts.get('rev'),
1205 update=opts.get('updaterev') or not opts.get('noupdate'),
1205 update=opts.get('updaterev') or not opts.get('noupdate'),
1206 branch=opts.get('branch'))
1206 branch=opts.get('branch'))
1207
1207
1208 return r is None
1208 return r is None
1209
1209
1210 @command('^commit|ci',
1210 @command('^commit|ci',
1211 [('A', 'addremove', None,
1211 [('A', 'addremove', None,
1212 _('mark new/missing files as added/removed before committing')),
1212 _('mark new/missing files as added/removed before committing')),
1213 ('', 'close-branch', None,
1213 ('', 'close-branch', None,
1214 _('mark a branch as closed, hiding it from the branch list')),
1214 _('mark a branch as closed, hiding it from the branch list')),
1215 ('', 'amend', None, _('amend the parent of the working dir')),
1215 ('', 'amend', None, _('amend the parent of the working dir')),
1216 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1216 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1217 _('[OPTION]... [FILE]...'))
1217 _('[OPTION]... [FILE]...'))
1218 def commit(ui, repo, *pats, **opts):
1218 def commit(ui, repo, *pats, **opts):
1219 """commit the specified files or all outstanding changes
1219 """commit the specified files or all outstanding changes
1220
1220
1221 Commit changes to the given files into the repository. Unlike a
1221 Commit changes to the given files into the repository. Unlike a
1222 centralized SCM, this operation is a local operation. See
1222 centralized SCM, this operation is a local operation. See
1223 :hg:`push` for a way to actively distribute your changes.
1223 :hg:`push` for a way to actively distribute your changes.
1224
1224
1225 If a list of files is omitted, all changes reported by :hg:`status`
1225 If a list of files is omitted, all changes reported by :hg:`status`
1226 will be committed.
1226 will be committed.
1227
1227
1228 If you are committing the result of a merge, do not provide any
1228 If you are committing the result of a merge, do not provide any
1229 filenames or -I/-X filters.
1229 filenames or -I/-X filters.
1230
1230
1231 If no commit message is specified, Mercurial starts your
1231 If no commit message is specified, Mercurial starts your
1232 configured editor where you can enter a message. In case your
1232 configured editor where you can enter a message. In case your
1233 commit fails, you will find a backup of your message in
1233 commit fails, you will find a backup of your message in
1234 ``.hg/last-message.txt``.
1234 ``.hg/last-message.txt``.
1235
1235
1236 The --amend flag can be used to amend the parent of the
1236 The --amend flag can be used to amend the parent of the
1237 working directory with a new commit that contains the changes
1237 working directory with a new commit that contains the changes
1238 in the parent in addition to those currently reported by :hg:`status`,
1238 in the parent in addition to those currently reported by :hg:`status`,
1239 if there are any. The old commit is stored in a backup bundle in
1239 if there are any. The old commit is stored in a backup bundle in
1240 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1240 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1241 on how to restore it).
1241 on how to restore it).
1242
1242
1243 Message, user and date are taken from the amended commit unless
1243 Message, user and date are taken from the amended commit unless
1244 specified. When a message isn't specified on the command line,
1244 specified. When a message isn't specified on the command line,
1245 the editor will open with the message of the amended commit.
1245 the editor will open with the message of the amended commit.
1246
1246
1247 It is not possible to amend public changesets (see :hg:`help phases`)
1247 It is not possible to amend public changesets (see :hg:`help phases`)
1248 or changesets that have children.
1248 or changesets that have children.
1249
1249
1250 See :hg:`help dates` for a list of formats valid for -d/--date.
1250 See :hg:`help dates` for a list of formats valid for -d/--date.
1251
1251
1252 Returns 0 on success, 1 if nothing changed.
1252 Returns 0 on success, 1 if nothing changed.
1253 """
1253 """
1254 if opts.get('subrepos'):
1254 if opts.get('subrepos'):
1255 # Let --subrepos on the command line overide config setting.
1255 # Let --subrepos on the command line overide config setting.
1256 ui.setconfig('ui', 'commitsubrepos', True)
1256 ui.setconfig('ui', 'commitsubrepos', True)
1257
1257
1258 extra = {}
1258 extra = {}
1259 if opts.get('close_branch'):
1259 if opts.get('close_branch'):
1260 if repo['.'].node() not in repo.branchheads():
1260 if repo['.'].node() not in repo.branchheads():
1261 # The topo heads set is included in the branch heads set of the
1261 # The topo heads set is included in the branch heads set of the
1262 # current branch, so it's sufficient to test branchheads
1262 # current branch, so it's sufficient to test branchheads
1263 raise util.Abort(_('can only close branch heads'))
1263 raise util.Abort(_('can only close branch heads'))
1264 extra['close'] = 1
1264 extra['close'] = 1
1265
1265
1266 branch = repo[None].branch()
1266 branch = repo[None].branch()
1267 bheads = repo.branchheads(branch)
1267 bheads = repo.branchheads(branch)
1268
1268
1269 if opts.get('amend'):
1269 if opts.get('amend'):
1270 if ui.configbool('ui', 'commitsubrepos'):
1270 if ui.configbool('ui', 'commitsubrepos'):
1271 raise util.Abort(_('cannot amend recursively'))
1271 raise util.Abort(_('cannot amend recursively'))
1272
1272
1273 old = repo['.']
1273 old = repo['.']
1274 if old.phase() == phases.public:
1274 if old.phase() == phases.public:
1275 raise util.Abort(_('cannot amend public changesets'))
1275 raise util.Abort(_('cannot amend public changesets'))
1276 if len(old.parents()) > 1:
1276 if len(old.parents()) > 1:
1277 raise util.Abort(_('cannot amend merge changesets'))
1277 raise util.Abort(_('cannot amend merge changesets'))
1278 if len(repo[None].parents()) > 1:
1278 if len(repo[None].parents()) > 1:
1279 raise util.Abort(_('cannot amend while merging'))
1279 raise util.Abort(_('cannot amend while merging'))
1280 if old.children():
1280 if old.children():
1281 raise util.Abort(_('cannot amend changeset with children'))
1281 raise util.Abort(_('cannot amend changeset with children'))
1282
1282
1283 e = cmdutil.commiteditor
1283 e = cmdutil.commiteditor
1284 if opts.get('force_editor'):
1284 if opts.get('force_editor'):
1285 e = cmdutil.commitforceeditor
1285 e = cmdutil.commitforceeditor
1286
1286
1287 def commitfunc(ui, repo, message, match, opts):
1287 def commitfunc(ui, repo, message, match, opts):
1288 editor = e
1288 editor = e
1289 # message contains text from -m or -l, if it's empty,
1289 # message contains text from -m or -l, if it's empty,
1290 # open the editor with the old message
1290 # open the editor with the old message
1291 if not message:
1291 if not message:
1292 message = old.description()
1292 message = old.description()
1293 editor = cmdutil.commitforceeditor
1293 editor = cmdutil.commitforceeditor
1294 return repo.commit(message,
1294 return repo.commit(message,
1295 opts.get('user') or old.user(),
1295 opts.get('user') or old.user(),
1296 opts.get('date') or old.date(),
1296 opts.get('date') or old.date(),
1297 match,
1297 match,
1298 editor=editor,
1298 editor=editor,
1299 extra=extra)
1299 extra=extra)
1300
1300
1301 current = repo._bookmarkcurrent
1301 current = repo._bookmarkcurrent
1302 marks = old.bookmarks()
1302 marks = old.bookmarks()
1303 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1303 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1304 if node == old.node():
1304 if node == old.node():
1305 ui.status(_("nothing changed\n"))
1305 ui.status(_("nothing changed\n"))
1306 return 1
1306 return 1
1307 elif marks:
1307 elif marks:
1308 ui.debug('moving bookmarks %r from %s to %s\n' %
1308 ui.debug('moving bookmarks %r from %s to %s\n' %
1309 (marks, old.hex(), hex(node)))
1309 (marks, old.hex(), hex(node)))
1310 for bm in marks:
1310 for bm in marks:
1311 repo._bookmarks[bm] = node
1311 repo._bookmarks[bm] = node
1312 if bm == current:
1312 if bm == current:
1313 bookmarks.setcurrent(repo, bm)
1313 bookmarks.setcurrent(repo, bm)
1314 bookmarks.write(repo)
1314 bookmarks.write(repo)
1315 else:
1315 else:
1316 e = cmdutil.commiteditor
1316 e = cmdutil.commiteditor
1317 if opts.get('force_editor'):
1317 if opts.get('force_editor'):
1318 e = cmdutil.commitforceeditor
1318 e = cmdutil.commitforceeditor
1319
1319
1320 def commitfunc(ui, repo, message, match, opts):
1320 def commitfunc(ui, repo, message, match, opts):
1321 return repo.commit(message, opts.get('user'), opts.get('date'),
1321 return repo.commit(message, opts.get('user'), opts.get('date'),
1322 match, editor=e, extra=extra)
1322 match, editor=e, extra=extra)
1323
1323
1324 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1324 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1325
1325
1326 if not node:
1326 if not node:
1327 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1327 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1328 if stat[3]:
1328 if stat[3]:
1329 ui.status(_("nothing changed (%d missing files, see "
1329 ui.status(_("nothing changed (%d missing files, see "
1330 "'hg status')\n") % len(stat[3]))
1330 "'hg status')\n") % len(stat[3]))
1331 else:
1331 else:
1332 ui.status(_("nothing changed\n"))
1332 ui.status(_("nothing changed\n"))
1333 return 1
1333 return 1
1334
1334
1335 ctx = repo[node]
1335 ctx = repo[node]
1336 parents = ctx.parents()
1336 parents = ctx.parents()
1337
1337
1338 if (not opts.get('amend') and bheads and node not in bheads and not
1338 if (not opts.get('amend') and bheads and node not in bheads and not
1339 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1339 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1340 ui.status(_('created new head\n'))
1340 ui.status(_('created new head\n'))
1341 # The message is not printed for initial roots. For the other
1341 # The message is not printed for initial roots. For the other
1342 # changesets, it is printed in the following situations:
1342 # changesets, it is printed in the following situations:
1343 #
1343 #
1344 # Par column: for the 2 parents with ...
1344 # Par column: for the 2 parents with ...
1345 # N: null or no parent
1345 # N: null or no parent
1346 # B: parent is on another named branch
1346 # B: parent is on another named branch
1347 # C: parent is a regular non head changeset
1347 # C: parent is a regular non head changeset
1348 # H: parent was a branch head of the current branch
1348 # H: parent was a branch head of the current branch
1349 # Msg column: whether we print "created new head" message
1349 # Msg column: whether we print "created new head" message
1350 # In the following, it is assumed that there already exists some
1350 # In the following, it is assumed that there already exists some
1351 # initial branch heads of the current branch, otherwise nothing is
1351 # initial branch heads of the current branch, otherwise nothing is
1352 # printed anyway.
1352 # printed anyway.
1353 #
1353 #
1354 # Par Msg Comment
1354 # Par Msg Comment
1355 # NN y additional topo root
1355 # NN y additional topo root
1356 #
1356 #
1357 # BN y additional branch root
1357 # BN y additional branch root
1358 # CN y additional topo head
1358 # CN y additional topo head
1359 # HN n usual case
1359 # HN n usual case
1360 #
1360 #
1361 # BB y weird additional branch root
1361 # BB y weird additional branch root
1362 # CB y branch merge
1362 # CB y branch merge
1363 # HB n merge with named branch
1363 # HB n merge with named branch
1364 #
1364 #
1365 # CC y additional head from merge
1365 # CC y additional head from merge
1366 # CH n merge with a head
1366 # CH n merge with a head
1367 #
1367 #
1368 # HH n head merge: head count decreases
1368 # HH n head merge: head count decreases
1369
1369
1370 if not opts.get('close_branch'):
1370 if not opts.get('close_branch'):
1371 for r in parents:
1371 for r in parents:
1372 if r.closesbranch() and r.branch() == branch:
1372 if r.closesbranch() and r.branch() == branch:
1373 ui.status(_('reopening closed branch head %d\n') % r)
1373 ui.status(_('reopening closed branch head %d\n') % r)
1374
1374
1375 if ui.debugflag:
1375 if ui.debugflag:
1376 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1376 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1377 elif ui.verbose:
1377 elif ui.verbose:
1378 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1378 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1379
1379
1380 @command('copy|cp',
1380 @command('copy|cp',
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1383 ] + walkopts + dryrunopts,
1383 ] + walkopts + dryrunopts,
1384 _('[OPTION]... [SOURCE]... DEST'))
1384 _('[OPTION]... [SOURCE]... DEST'))
1385 def copy(ui, repo, *pats, **opts):
1385 def copy(ui, repo, *pats, **opts):
1386 """mark files as copied for the next commit
1386 """mark files as copied for the next commit
1387
1387
1388 Mark dest as having copies of source files. If dest is a
1388 Mark dest as having copies of source files. If dest is a
1389 directory, copies are put in that directory. If dest is a file,
1389 directory, copies are put in that directory. If dest is a file,
1390 the source must be a single file.
1390 the source must be a single file.
1391
1391
1392 By default, this command copies the contents of files as they
1392 By default, this command copies the contents of files as they
1393 exist in the working directory. If invoked with -A/--after, the
1393 exist in the working directory. If invoked with -A/--after, the
1394 operation is recorded, but no copying is performed.
1394 operation is recorded, but no copying is performed.
1395
1395
1396 This command takes effect with the next commit. To undo a copy
1396 This command takes effect with the next commit. To undo a copy
1397 before that, see :hg:`revert`.
1397 before that, see :hg:`revert`.
1398
1398
1399 Returns 0 on success, 1 if errors are encountered.
1399 Returns 0 on success, 1 if errors are encountered.
1400 """
1400 """
1401 wlock = repo.wlock(False)
1401 wlock = repo.wlock(False)
1402 try:
1402 try:
1403 return cmdutil.copy(ui, repo, pats, opts)
1403 return cmdutil.copy(ui, repo, pats, opts)
1404 finally:
1404 finally:
1405 wlock.release()
1405 wlock.release()
1406
1406
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1408 def debugancestor(ui, repo, *args):
1408 def debugancestor(ui, repo, *args):
1409 """find the ancestor revision of two revisions in a given index"""
1409 """find the ancestor revision of two revisions in a given index"""
1410 if len(args) == 3:
1410 if len(args) == 3:
1411 index, rev1, rev2 = args
1411 index, rev1, rev2 = args
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1413 lookup = r.lookup
1413 lookup = r.lookup
1414 elif len(args) == 2:
1414 elif len(args) == 2:
1415 if not repo:
1415 if not repo:
1416 raise util.Abort(_("there is no Mercurial repository here "
1416 raise util.Abort(_("there is no Mercurial repository here "
1417 "(.hg not found)"))
1417 "(.hg not found)"))
1418 rev1, rev2 = args
1418 rev1, rev2 = args
1419 r = repo.changelog
1419 r = repo.changelog
1420 lookup = repo.lookup
1420 lookup = repo.lookup
1421 else:
1421 else:
1422 raise util.Abort(_('either two or three arguments required'))
1422 raise util.Abort(_('either two or three arguments required'))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1425
1425
1426 @command('debugbuilddag',
1426 @command('debugbuilddag',
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1430 _('[OPTION]... [TEXT]'))
1430 _('[OPTION]... [TEXT]'))
1431 def debugbuilddag(ui, repo, text=None,
1431 def debugbuilddag(ui, repo, text=None,
1432 mergeable_file=False,
1432 mergeable_file=False,
1433 overwritten_file=False,
1433 overwritten_file=False,
1434 new_file=False):
1434 new_file=False):
1435 """builds a repo with a given DAG from scratch in the current empty repo
1435 """builds a repo with a given DAG from scratch in the current empty repo
1436
1436
1437 The description of the DAG is read from stdin if not given on the
1437 The description of the DAG is read from stdin if not given on the
1438 command line.
1438 command line.
1439
1439
1440 Elements:
1440 Elements:
1441
1441
1442 - "+n" is a linear run of n nodes based on the current default parent
1442 - "+n" is a linear run of n nodes based on the current default parent
1443 - "." is a single node based on the current default parent
1443 - "." is a single node based on the current default parent
1444 - "$" resets the default parent to null (implied at the start);
1444 - "$" resets the default parent to null (implied at the start);
1445 otherwise the default parent is always the last node created
1445 otherwise the default parent is always the last node created
1446 - "<p" sets the default parent to the backref p
1446 - "<p" sets the default parent to the backref p
1447 - "*p" is a fork at parent p, which is a backref
1447 - "*p" is a fork at parent p, which is a backref
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1449 - "/p2" is a merge of the preceding node and p2
1449 - "/p2" is a merge of the preceding node and p2
1450 - ":tag" defines a local tag for the preceding node
1450 - ":tag" defines a local tag for the preceding node
1451 - "@branch" sets the named branch for subsequent nodes
1451 - "@branch" sets the named branch for subsequent nodes
1452 - "#...\\n" is a comment up to the end of the line
1452 - "#...\\n" is a comment up to the end of the line
1453
1453
1454 Whitespace between the above elements is ignored.
1454 Whitespace between the above elements is ignored.
1455
1455
1456 A backref is either
1456 A backref is either
1457
1457
1458 - a number n, which references the node curr-n, where curr is the current
1458 - a number n, which references the node curr-n, where curr is the current
1459 node, or
1459 node, or
1460 - the name of a local tag you placed earlier using ":tag", or
1460 - the name of a local tag you placed earlier using ":tag", or
1461 - empty to denote the default parent.
1461 - empty to denote the default parent.
1462
1462
1463 All string valued-elements are either strictly alphanumeric, or must
1463 All string valued-elements are either strictly alphanumeric, or must
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1465 """
1465 """
1466
1466
1467 if text is None:
1467 if text is None:
1468 ui.status(_("reading DAG from stdin\n"))
1468 ui.status(_("reading DAG from stdin\n"))
1469 text = ui.fin.read()
1469 text = ui.fin.read()
1470
1470
1471 cl = repo.changelog
1471 cl = repo.changelog
1472 if len(cl) > 0:
1472 if len(cl) > 0:
1473 raise util.Abort(_('repository is not empty'))
1473 raise util.Abort(_('repository is not empty'))
1474
1474
1475 # determine number of revs in DAG
1475 # determine number of revs in DAG
1476 total = 0
1476 total = 0
1477 for type, data in dagparser.parsedag(text):
1477 for type, data in dagparser.parsedag(text):
1478 if type == 'n':
1478 if type == 'n':
1479 total += 1
1479 total += 1
1480
1480
1481 if mergeable_file:
1481 if mergeable_file:
1482 linesperrev = 2
1482 linesperrev = 2
1483 # make a file with k lines per rev
1483 # make a file with k lines per rev
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1485 initialmergedlines.append("")
1485 initialmergedlines.append("")
1486
1486
1487 tags = []
1487 tags = []
1488
1488
1489 lock = tr = None
1489 lock = tr = None
1490 try:
1490 try:
1491 lock = repo.lock()
1491 lock = repo.lock()
1492 tr = repo.transaction("builddag")
1492 tr = repo.transaction("builddag")
1493
1493
1494 at = -1
1494 at = -1
1495 atbranch = 'default'
1495 atbranch = 'default'
1496 nodeids = []
1496 nodeids = []
1497 id = 0
1497 id = 0
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1499 for type, data in dagparser.parsedag(text):
1499 for type, data in dagparser.parsedag(text):
1500 if type == 'n':
1500 if type == 'n':
1501 ui.note('node %s\n' % str(data))
1501 ui.note('node %s\n' % str(data))
1502 id, ps = data
1502 id, ps = data
1503
1503
1504 files = []
1504 files = []
1505 fctxs = {}
1505 fctxs = {}
1506
1506
1507 p2 = None
1507 p2 = None
1508 if mergeable_file:
1508 if mergeable_file:
1509 fn = "mf"
1509 fn = "mf"
1510 p1 = repo[ps[0]]
1510 p1 = repo[ps[0]]
1511 if len(ps) > 1:
1511 if len(ps) > 1:
1512 p2 = repo[ps[1]]
1512 p2 = repo[ps[1]]
1513 pa = p1.ancestor(p2)
1513 pa = p1.ancestor(p2)
1514 base, local, other = [x[fn].data() for x in pa, p1, p2]
1514 base, local, other = [x[fn].data() for x in pa, p1, p2]
1515 m3 = simplemerge.Merge3Text(base, local, other)
1515 m3 = simplemerge.Merge3Text(base, local, other)
1516 ml = [l.strip() for l in m3.merge_lines()]
1516 ml = [l.strip() for l in m3.merge_lines()]
1517 ml.append("")
1517 ml.append("")
1518 elif at > 0:
1518 elif at > 0:
1519 ml = p1[fn].data().split("\n")
1519 ml = p1[fn].data().split("\n")
1520 else:
1520 else:
1521 ml = initialmergedlines
1521 ml = initialmergedlines
1522 ml[id * linesperrev] += " r%i" % id
1522 ml[id * linesperrev] += " r%i" % id
1523 mergedtext = "\n".join(ml)
1523 mergedtext = "\n".join(ml)
1524 files.append(fn)
1524 files.append(fn)
1525 fctxs[fn] = context.memfilectx(fn, mergedtext)
1525 fctxs[fn] = context.memfilectx(fn, mergedtext)
1526
1526
1527 if overwritten_file:
1527 if overwritten_file:
1528 fn = "of"
1528 fn = "of"
1529 files.append(fn)
1529 files.append(fn)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531
1531
1532 if new_file:
1532 if new_file:
1533 fn = "nf%i" % id
1533 fn = "nf%i" % id
1534 files.append(fn)
1534 files.append(fn)
1535 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1535 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1536 if len(ps) > 1:
1536 if len(ps) > 1:
1537 if not p2:
1537 if not p2:
1538 p2 = repo[ps[1]]
1538 p2 = repo[ps[1]]
1539 for fn in p2:
1539 for fn in p2:
1540 if fn.startswith("nf"):
1540 if fn.startswith("nf"):
1541 files.append(fn)
1541 files.append(fn)
1542 fctxs[fn] = p2[fn]
1542 fctxs[fn] = p2[fn]
1543
1543
1544 def fctxfn(repo, cx, path):
1544 def fctxfn(repo, cx, path):
1545 return fctxs.get(path)
1545 return fctxs.get(path)
1546
1546
1547 if len(ps) == 0 or ps[0] < 0:
1547 if len(ps) == 0 or ps[0] < 0:
1548 pars = [None, None]
1548 pars = [None, None]
1549 elif len(ps) == 1:
1549 elif len(ps) == 1:
1550 pars = [nodeids[ps[0]], None]
1550 pars = [nodeids[ps[0]], None]
1551 else:
1551 else:
1552 pars = [nodeids[p] for p in ps]
1552 pars = [nodeids[p] for p in ps]
1553 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1553 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1554 date=(id, 0),
1554 date=(id, 0),
1555 user="debugbuilddag",
1555 user="debugbuilddag",
1556 extra={'branch': atbranch})
1556 extra={'branch': atbranch})
1557 nodeid = repo.commitctx(cx)
1557 nodeid = repo.commitctx(cx)
1558 nodeids.append(nodeid)
1558 nodeids.append(nodeid)
1559 at = id
1559 at = id
1560 elif type == 'l':
1560 elif type == 'l':
1561 id, name = data
1561 id, name = data
1562 ui.note('tag %s\n' % name)
1562 ui.note('tag %s\n' % name)
1563 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1563 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1564 elif type == 'a':
1564 elif type == 'a':
1565 ui.note('branch %s\n' % data)
1565 ui.note('branch %s\n' % data)
1566 atbranch = data
1566 atbranch = data
1567 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1567 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1568 tr.close()
1568 tr.close()
1569
1569
1570 if tags:
1570 if tags:
1571 repo.opener.write("localtags", "".join(tags))
1571 repo.opener.write("localtags", "".join(tags))
1572 finally:
1572 finally:
1573 ui.progress(_('building'), None)
1573 ui.progress(_('building'), None)
1574 release(tr, lock)
1574 release(tr, lock)
1575
1575
1576 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1576 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1577 def debugbundle(ui, bundlepath, all=None, **opts):
1577 def debugbundle(ui, bundlepath, all=None, **opts):
1578 """lists the contents of a bundle"""
1578 """lists the contents of a bundle"""
1579 f = url.open(ui, bundlepath)
1579 f = url.open(ui, bundlepath)
1580 try:
1580 try:
1581 gen = changegroup.readbundle(f, bundlepath)
1581 gen = changegroup.readbundle(f, bundlepath)
1582 if all:
1582 if all:
1583 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1583 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1584
1584
1585 def showchunks(named):
1585 def showchunks(named):
1586 ui.write("\n%s\n" % named)
1586 ui.write("\n%s\n" % named)
1587 chain = None
1587 chain = None
1588 while True:
1588 while True:
1589 chunkdata = gen.deltachunk(chain)
1589 chunkdata = gen.deltachunk(chain)
1590 if not chunkdata:
1590 if not chunkdata:
1591 break
1591 break
1592 node = chunkdata['node']
1592 node = chunkdata['node']
1593 p1 = chunkdata['p1']
1593 p1 = chunkdata['p1']
1594 p2 = chunkdata['p2']
1594 p2 = chunkdata['p2']
1595 cs = chunkdata['cs']
1595 cs = chunkdata['cs']
1596 deltabase = chunkdata['deltabase']
1596 deltabase = chunkdata['deltabase']
1597 delta = chunkdata['delta']
1597 delta = chunkdata['delta']
1598 ui.write("%s %s %s %s %s %s\n" %
1598 ui.write("%s %s %s %s %s %s\n" %
1599 (hex(node), hex(p1), hex(p2),
1599 (hex(node), hex(p1), hex(p2),
1600 hex(cs), hex(deltabase), len(delta)))
1600 hex(cs), hex(deltabase), len(delta)))
1601 chain = node
1601 chain = node
1602
1602
1603 chunkdata = gen.changelogheader()
1603 chunkdata = gen.changelogheader()
1604 showchunks("changelog")
1604 showchunks("changelog")
1605 chunkdata = gen.manifestheader()
1605 chunkdata = gen.manifestheader()
1606 showchunks("manifest")
1606 showchunks("manifest")
1607 while True:
1607 while True:
1608 chunkdata = gen.filelogheader()
1608 chunkdata = gen.filelogheader()
1609 if not chunkdata:
1609 if not chunkdata:
1610 break
1610 break
1611 fname = chunkdata['filename']
1611 fname = chunkdata['filename']
1612 showchunks(fname)
1612 showchunks(fname)
1613 else:
1613 else:
1614 chunkdata = gen.changelogheader()
1614 chunkdata = gen.changelogheader()
1615 chain = None
1615 chain = None
1616 while True:
1616 while True:
1617 chunkdata = gen.deltachunk(chain)
1617 chunkdata = gen.deltachunk(chain)
1618 if not chunkdata:
1618 if not chunkdata:
1619 break
1619 break
1620 node = chunkdata['node']
1620 node = chunkdata['node']
1621 ui.write("%s\n" % hex(node))
1621 ui.write("%s\n" % hex(node))
1622 chain = node
1622 chain = node
1623 finally:
1623 finally:
1624 f.close()
1624 f.close()
1625
1625
1626 @command('debugcheckstate', [], '')
1626 @command('debugcheckstate', [], '')
1627 def debugcheckstate(ui, repo):
1627 def debugcheckstate(ui, repo):
1628 """validate the correctness of the current dirstate"""
1628 """validate the correctness of the current dirstate"""
1629 parent1, parent2 = repo.dirstate.parents()
1629 parent1, parent2 = repo.dirstate.parents()
1630 m1 = repo[parent1].manifest()
1630 m1 = repo[parent1].manifest()
1631 m2 = repo[parent2].manifest()
1631 m2 = repo[parent2].manifest()
1632 errors = 0
1632 errors = 0
1633 for f in repo.dirstate:
1633 for f in repo.dirstate:
1634 state = repo.dirstate[f]
1634 state = repo.dirstate[f]
1635 if state in "nr" and f not in m1:
1635 if state in "nr" and f not in m1:
1636 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1636 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1637 errors += 1
1637 errors += 1
1638 if state in "a" and f in m1:
1638 if state in "a" and f in m1:
1639 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1639 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1640 errors += 1
1640 errors += 1
1641 if state in "m" and f not in m1 and f not in m2:
1641 if state in "m" and f not in m1 and f not in m2:
1642 ui.warn(_("%s in state %s, but not in either manifest\n") %
1642 ui.warn(_("%s in state %s, but not in either manifest\n") %
1643 (f, state))
1643 (f, state))
1644 errors += 1
1644 errors += 1
1645 for f in m1:
1645 for f in m1:
1646 state = repo.dirstate[f]
1646 state = repo.dirstate[f]
1647 if state not in "nrm":
1647 if state not in "nrm":
1648 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1648 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1649 errors += 1
1649 errors += 1
1650 if errors:
1650 if errors:
1651 error = _(".hg/dirstate inconsistent with current parent's manifest")
1651 error = _(".hg/dirstate inconsistent with current parent's manifest")
1652 raise util.Abort(error)
1652 raise util.Abort(error)
1653
1653
1654 @command('debugcommands', [], _('[COMMAND]'))
1654 @command('debugcommands', [], _('[COMMAND]'))
1655 def debugcommands(ui, cmd='', *args):
1655 def debugcommands(ui, cmd='', *args):
1656 """list all available commands and options"""
1656 """list all available commands and options"""
1657 for cmd, vals in sorted(table.iteritems()):
1657 for cmd, vals in sorted(table.iteritems()):
1658 cmd = cmd.split('|')[0].strip('^')
1658 cmd = cmd.split('|')[0].strip('^')
1659 opts = ', '.join([i[1] for i in vals[1]])
1659 opts = ', '.join([i[1] for i in vals[1]])
1660 ui.write('%s: %s\n' % (cmd, opts))
1660 ui.write('%s: %s\n' % (cmd, opts))
1661
1661
1662 @command('debugcomplete',
1662 @command('debugcomplete',
1663 [('o', 'options', None, _('show the command options'))],
1663 [('o', 'options', None, _('show the command options'))],
1664 _('[-o] CMD'))
1664 _('[-o] CMD'))
1665 def debugcomplete(ui, cmd='', **opts):
1665 def debugcomplete(ui, cmd='', **opts):
1666 """returns the completion list associated with the given command"""
1666 """returns the completion list associated with the given command"""
1667
1667
1668 if opts.get('options'):
1668 if opts.get('options'):
1669 options = []
1669 options = []
1670 otables = [globalopts]
1670 otables = [globalopts]
1671 if cmd:
1671 if cmd:
1672 aliases, entry = cmdutil.findcmd(cmd, table, False)
1672 aliases, entry = cmdutil.findcmd(cmd, table, False)
1673 otables.append(entry[1])
1673 otables.append(entry[1])
1674 for t in otables:
1674 for t in otables:
1675 for o in t:
1675 for o in t:
1676 if "(DEPRECATED)" in o[3]:
1676 if "(DEPRECATED)" in o[3]:
1677 continue
1677 continue
1678 if o[0]:
1678 if o[0]:
1679 options.append('-%s' % o[0])
1679 options.append('-%s' % o[0])
1680 options.append('--%s' % o[1])
1680 options.append('--%s' % o[1])
1681 ui.write("%s\n" % "\n".join(options))
1681 ui.write("%s\n" % "\n".join(options))
1682 return
1682 return
1683
1683
1684 cmdlist = cmdutil.findpossible(cmd, table)
1684 cmdlist = cmdutil.findpossible(cmd, table)
1685 if ui.verbose:
1685 if ui.verbose:
1686 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1686 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1687 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1687 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1688
1688
1689 @command('debugdag',
1689 @command('debugdag',
1690 [('t', 'tags', None, _('use tags as labels')),
1690 [('t', 'tags', None, _('use tags as labels')),
1691 ('b', 'branches', None, _('annotate with branch names')),
1691 ('b', 'branches', None, _('annotate with branch names')),
1692 ('', 'dots', None, _('use dots for runs')),
1692 ('', 'dots', None, _('use dots for runs')),
1693 ('s', 'spaces', None, _('separate elements by spaces'))],
1693 ('s', 'spaces', None, _('separate elements by spaces'))],
1694 _('[OPTION]... [FILE [REV]...]'))
1694 _('[OPTION]... [FILE [REV]...]'))
1695 def debugdag(ui, repo, file_=None, *revs, **opts):
1695 def debugdag(ui, repo, file_=None, *revs, **opts):
1696 """format the changelog or an index DAG as a concise textual description
1696 """format the changelog or an index DAG as a concise textual description
1697
1697
1698 If you pass a revlog index, the revlog's DAG is emitted. If you list
1698 If you pass a revlog index, the revlog's DAG is emitted. If you list
1699 revision numbers, they get labelled in the output as rN.
1699 revision numbers, they get labelled in the output as rN.
1700
1700
1701 Otherwise, the changelog DAG of the current repo is emitted.
1701 Otherwise, the changelog DAG of the current repo is emitted.
1702 """
1702 """
1703 spaces = opts.get('spaces')
1703 spaces = opts.get('spaces')
1704 dots = opts.get('dots')
1704 dots = opts.get('dots')
1705 if file_:
1705 if file_:
1706 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1706 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1707 revs = set((int(r) for r in revs))
1707 revs = set((int(r) for r in revs))
1708 def events():
1708 def events():
1709 for r in rlog:
1709 for r in rlog:
1710 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1710 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1711 if p != -1)))
1711 if p != -1)))
1712 if r in revs:
1712 if r in revs:
1713 yield 'l', (r, "r%i" % r)
1713 yield 'l', (r, "r%i" % r)
1714 elif repo:
1714 elif repo:
1715 cl = repo.changelog
1715 cl = repo.changelog
1716 tags = opts.get('tags')
1716 tags = opts.get('tags')
1717 branches = opts.get('branches')
1717 branches = opts.get('branches')
1718 if tags:
1718 if tags:
1719 labels = {}
1719 labels = {}
1720 for l, n in repo.tags().items():
1720 for l, n in repo.tags().items():
1721 labels.setdefault(cl.rev(n), []).append(l)
1721 labels.setdefault(cl.rev(n), []).append(l)
1722 def events():
1722 def events():
1723 b = "default"
1723 b = "default"
1724 for r in cl:
1724 for r in cl:
1725 if branches:
1725 if branches:
1726 newb = cl.read(cl.node(r))[5]['branch']
1726 newb = cl.read(cl.node(r))[5]['branch']
1727 if newb != b:
1727 if newb != b:
1728 yield 'a', newb
1728 yield 'a', newb
1729 b = newb
1729 b = newb
1730 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1730 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1731 if p != -1)))
1731 if p != -1)))
1732 if tags:
1732 if tags:
1733 ls = labels.get(r)
1733 ls = labels.get(r)
1734 if ls:
1734 if ls:
1735 for l in ls:
1735 for l in ls:
1736 yield 'l', (r, l)
1736 yield 'l', (r, l)
1737 else:
1737 else:
1738 raise util.Abort(_('need repo for changelog dag'))
1738 raise util.Abort(_('need repo for changelog dag'))
1739
1739
1740 for line in dagparser.dagtextlines(events(),
1740 for line in dagparser.dagtextlines(events(),
1741 addspaces=spaces,
1741 addspaces=spaces,
1742 wraplabels=True,
1742 wraplabels=True,
1743 wrapannotations=True,
1743 wrapannotations=True,
1744 wrapnonlinear=dots,
1744 wrapnonlinear=dots,
1745 usedots=dots,
1745 usedots=dots,
1746 maxlinewidth=70):
1746 maxlinewidth=70):
1747 ui.write(line)
1747 ui.write(line)
1748 ui.write("\n")
1748 ui.write("\n")
1749
1749
1750 @command('debugdata',
1750 @command('debugdata',
1751 [('c', 'changelog', False, _('open changelog')),
1751 [('c', 'changelog', False, _('open changelog')),
1752 ('m', 'manifest', False, _('open manifest'))],
1752 ('m', 'manifest', False, _('open manifest'))],
1753 _('-c|-m|FILE REV'))
1753 _('-c|-m|FILE REV'))
1754 def debugdata(ui, repo, file_, rev = None, **opts):
1754 def debugdata(ui, repo, file_, rev = None, **opts):
1755 """dump the contents of a data file revision"""
1755 """dump the contents of a data file revision"""
1756 if opts.get('changelog') or opts.get('manifest'):
1756 if opts.get('changelog') or opts.get('manifest'):
1757 file_, rev = None, file_
1757 file_, rev = None, file_
1758 elif rev is None:
1758 elif rev is None:
1759 raise error.CommandError('debugdata', _('invalid arguments'))
1759 raise error.CommandError('debugdata', _('invalid arguments'))
1760 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1760 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1761 try:
1761 try:
1762 ui.write(r.revision(r.lookup(rev)))
1762 ui.write(r.revision(r.lookup(rev)))
1763 except KeyError:
1763 except KeyError:
1764 raise util.Abort(_('invalid revision identifier %s') % rev)
1764 raise util.Abort(_('invalid revision identifier %s') % rev)
1765
1765
1766 @command('debugdate',
1766 @command('debugdate',
1767 [('e', 'extended', None, _('try extended date formats'))],
1767 [('e', 'extended', None, _('try extended date formats'))],
1768 _('[-e] DATE [RANGE]'))
1768 _('[-e] DATE [RANGE]'))
1769 def debugdate(ui, date, range=None, **opts):
1769 def debugdate(ui, date, range=None, **opts):
1770 """parse and display a date"""
1770 """parse and display a date"""
1771 if opts["extended"]:
1771 if opts["extended"]:
1772 d = util.parsedate(date, util.extendeddateformats)
1772 d = util.parsedate(date, util.extendeddateformats)
1773 else:
1773 else:
1774 d = util.parsedate(date)
1774 d = util.parsedate(date)
1775 ui.write("internal: %s %s\n" % d)
1775 ui.write("internal: %s %s\n" % d)
1776 ui.write("standard: %s\n" % util.datestr(d))
1776 ui.write("standard: %s\n" % util.datestr(d))
1777 if range:
1777 if range:
1778 m = util.matchdate(range)
1778 m = util.matchdate(range)
1779 ui.write("match: %s\n" % m(d[0]))
1779 ui.write("match: %s\n" % m(d[0]))
1780
1780
1781 @command('debugdiscovery',
1781 @command('debugdiscovery',
1782 [('', 'old', None, _('use old-style discovery')),
1782 [('', 'old', None, _('use old-style discovery')),
1783 ('', 'nonheads', None,
1783 ('', 'nonheads', None,
1784 _('use old-style discovery with non-heads included')),
1784 _('use old-style discovery with non-heads included')),
1785 ] + remoteopts,
1785 ] + remoteopts,
1786 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1786 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1787 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1787 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1788 """runs the changeset discovery protocol in isolation"""
1788 """runs the changeset discovery protocol in isolation"""
1789 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1789 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1790 opts.get('branch'))
1790 opts.get('branch'))
1791 remote = hg.peer(repo, opts, remoteurl)
1791 remote = hg.peer(repo, opts, remoteurl)
1792 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1792 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1793
1793
1794 # make sure tests are repeatable
1794 # make sure tests are repeatable
1795 random.seed(12323)
1795 random.seed(12323)
1796
1796
1797 def doit(localheads, remoteheads, remote=remote):
1797 def doit(localheads, remoteheads, remote=remote):
1798 if opts.get('old'):
1798 if opts.get('old'):
1799 if localheads:
1799 if localheads:
1800 raise util.Abort('cannot use localheads with old style '
1800 raise util.Abort('cannot use localheads with old style '
1801 'discovery')
1801 'discovery')
1802 if not util.safehasattr(remote, 'branches'):
1802 if not util.safehasattr(remote, 'branches'):
1803 # enable in-client legacy support
1803 # enable in-client legacy support
1804 remote = localrepo.locallegacypeer(remote.local())
1804 remote = localrepo.locallegacypeer(remote.local())
1805 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1805 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1806 force=True)
1806 force=True)
1807 common = set(common)
1807 common = set(common)
1808 if not opts.get('nonheads'):
1808 if not opts.get('nonheads'):
1809 ui.write("unpruned common: %s\n" % " ".join([short(n)
1809 ui.write("unpruned common: %s\n" % " ".join([short(n)
1810 for n in common]))
1810 for n in common]))
1811 dag = dagutil.revlogdag(repo.changelog)
1811 dag = dagutil.revlogdag(repo.changelog)
1812 all = dag.ancestorset(dag.internalizeall(common))
1812 all = dag.ancestorset(dag.internalizeall(common))
1813 common = dag.externalizeall(dag.headsetofconnecteds(all))
1813 common = dag.externalizeall(dag.headsetofconnecteds(all))
1814 else:
1814 else:
1815 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1815 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1816 common = set(common)
1816 common = set(common)
1817 rheads = set(hds)
1817 rheads = set(hds)
1818 lheads = set(repo.heads())
1818 lheads = set(repo.heads())
1819 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1819 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1820 if lheads <= common:
1820 if lheads <= common:
1821 ui.write("local is subset\n")
1821 ui.write("local is subset\n")
1822 elif rheads <= common:
1822 elif rheads <= common:
1823 ui.write("remote is subset\n")
1823 ui.write("remote is subset\n")
1824
1824
1825 serverlogs = opts.get('serverlog')
1825 serverlogs = opts.get('serverlog')
1826 if serverlogs:
1826 if serverlogs:
1827 for filename in serverlogs:
1827 for filename in serverlogs:
1828 logfile = open(filename, 'r')
1828 logfile = open(filename, 'r')
1829 try:
1829 try:
1830 line = logfile.readline()
1830 line = logfile.readline()
1831 while line:
1831 while line:
1832 parts = line.strip().split(';')
1832 parts = line.strip().split(';')
1833 op = parts[1]
1833 op = parts[1]
1834 if op == 'cg':
1834 if op == 'cg':
1835 pass
1835 pass
1836 elif op == 'cgss':
1836 elif op == 'cgss':
1837 doit(parts[2].split(' '), parts[3].split(' '))
1837 doit(parts[2].split(' '), parts[3].split(' '))
1838 elif op == 'unb':
1838 elif op == 'unb':
1839 doit(parts[3].split(' '), parts[2].split(' '))
1839 doit(parts[3].split(' '), parts[2].split(' '))
1840 line = logfile.readline()
1840 line = logfile.readline()
1841 finally:
1841 finally:
1842 logfile.close()
1842 logfile.close()
1843
1843
1844 else:
1844 else:
1845 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1845 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1846 opts.get('remote_head'))
1846 opts.get('remote_head'))
1847 localrevs = opts.get('local_head')
1847 localrevs = opts.get('local_head')
1848 doit(localrevs, remoterevs)
1848 doit(localrevs, remoterevs)
1849
1849
1850 @command('debugfileset', [], ('REVSPEC'))
1850 @command('debugfileset', [], ('REVSPEC'))
1851 def debugfileset(ui, repo, expr):
1851 def debugfileset(ui, repo, expr):
1852 '''parse and apply a fileset specification'''
1852 '''parse and apply a fileset specification'''
1853 if ui.verbose:
1853 if ui.verbose:
1854 tree = fileset.parse(expr)[0]
1854 tree = fileset.parse(expr)[0]
1855 ui.note(tree, "\n")
1855 ui.note(tree, "\n")
1856
1856
1857 for f in fileset.getfileset(repo[None], expr):
1857 for f in fileset.getfileset(repo[None], expr):
1858 ui.write("%s\n" % f)
1858 ui.write("%s\n" % f)
1859
1859
1860 @command('debugfsinfo', [], _('[PATH]'))
1860 @command('debugfsinfo', [], _('[PATH]'))
1861 def debugfsinfo(ui, path = "."):
1861 def debugfsinfo(ui, path = "."):
1862 """show information detected about current filesystem"""
1862 """show information detected about current filesystem"""
1863 util.writefile('.debugfsinfo', '')
1863 util.writefile('.debugfsinfo', '')
1864 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1864 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1865 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1865 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1866 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1866 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1867 and 'yes' or 'no'))
1867 and 'yes' or 'no'))
1868 os.unlink('.debugfsinfo')
1868 os.unlink('.debugfsinfo')
1869
1869
1870 @command('debuggetbundle',
1870 @command('debuggetbundle',
1871 [('H', 'head', [], _('id of head node'), _('ID')),
1871 [('H', 'head', [], _('id of head node'), _('ID')),
1872 ('C', 'common', [], _('id of common node'), _('ID')),
1872 ('C', 'common', [], _('id of common node'), _('ID')),
1873 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1873 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1874 _('REPO FILE [-H|-C ID]...'))
1874 _('REPO FILE [-H|-C ID]...'))
1875 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1875 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1876 """retrieves a bundle from a repo
1876 """retrieves a bundle from a repo
1877
1877
1878 Every ID must be a full-length hex node id string. Saves the bundle to the
1878 Every ID must be a full-length hex node id string. Saves the bundle to the
1879 given file.
1879 given file.
1880 """
1880 """
1881 repo = hg.peer(ui, opts, repopath)
1881 repo = hg.peer(ui, opts, repopath)
1882 if not repo.capable('getbundle'):
1882 if not repo.capable('getbundle'):
1883 raise util.Abort("getbundle() not supported by target repository")
1883 raise util.Abort("getbundle() not supported by target repository")
1884 args = {}
1884 args = {}
1885 if common:
1885 if common:
1886 args['common'] = [bin(s) for s in common]
1886 args['common'] = [bin(s) for s in common]
1887 if head:
1887 if head:
1888 args['heads'] = [bin(s) for s in head]
1888 args['heads'] = [bin(s) for s in head]
1889 bundle = repo.getbundle('debug', **args)
1889 bundle = repo.getbundle('debug', **args)
1890
1890
1891 bundletype = opts.get('type', 'bzip2').lower()
1891 bundletype = opts.get('type', 'bzip2').lower()
1892 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1892 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1893 bundletype = btypes.get(bundletype)
1893 bundletype = btypes.get(bundletype)
1894 if bundletype not in changegroup.bundletypes:
1894 if bundletype not in changegroup.bundletypes:
1895 raise util.Abort(_('unknown bundle type specified with --type'))
1895 raise util.Abort(_('unknown bundle type specified with --type'))
1896 changegroup.writebundle(bundle, bundlepath, bundletype)
1896 changegroup.writebundle(bundle, bundlepath, bundletype)
1897
1897
1898 @command('debugignore', [], '')
1898 @command('debugignore', [], '')
1899 def debugignore(ui, repo, *values, **opts):
1899 def debugignore(ui, repo, *values, **opts):
1900 """display the combined ignore pattern"""
1900 """display the combined ignore pattern"""
1901 ignore = repo.dirstate._ignore
1901 ignore = repo.dirstate._ignore
1902 includepat = getattr(ignore, 'includepat', None)
1902 includepat = getattr(ignore, 'includepat', None)
1903 if includepat is not None:
1903 if includepat is not None:
1904 ui.write("%s\n" % includepat)
1904 ui.write("%s\n" % includepat)
1905 else:
1905 else:
1906 raise util.Abort(_("no ignore patterns found"))
1906 raise util.Abort(_("no ignore patterns found"))
1907
1907
1908 @command('debugindex',
1908 @command('debugindex',
1909 [('c', 'changelog', False, _('open changelog')),
1909 [('c', 'changelog', False, _('open changelog')),
1910 ('m', 'manifest', False, _('open manifest')),
1910 ('m', 'manifest', False, _('open manifest')),
1911 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1911 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1912 _('[-f FORMAT] -c|-m|FILE'))
1912 _('[-f FORMAT] -c|-m|FILE'))
1913 def debugindex(ui, repo, file_ = None, **opts):
1913 def debugindex(ui, repo, file_ = None, **opts):
1914 """dump the contents of an index file"""
1914 """dump the contents of an index file"""
1915 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1915 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1916 format = opts.get('format', 0)
1916 format = opts.get('format', 0)
1917 if format not in (0, 1):
1917 if format not in (0, 1):
1918 raise util.Abort(_("unknown format %d") % format)
1918 raise util.Abort(_("unknown format %d") % format)
1919
1919
1920 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1920 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1921 if generaldelta:
1921 if generaldelta:
1922 basehdr = ' delta'
1922 basehdr = ' delta'
1923 else:
1923 else:
1924 basehdr = ' base'
1924 basehdr = ' base'
1925
1925
1926 if format == 0:
1926 if format == 0:
1927 ui.write(" rev offset length " + basehdr + " linkrev"
1927 ui.write(" rev offset length " + basehdr + " linkrev"
1928 " nodeid p1 p2\n")
1928 " nodeid p1 p2\n")
1929 elif format == 1:
1929 elif format == 1:
1930 ui.write(" rev flag offset length"
1930 ui.write(" rev flag offset length"
1931 " size " + basehdr + " link p1 p2"
1931 " size " + basehdr + " link p1 p2"
1932 " nodeid\n")
1932 " nodeid\n")
1933
1933
1934 for i in r:
1934 for i in r:
1935 node = r.node(i)
1935 node = r.node(i)
1936 if generaldelta:
1936 if generaldelta:
1937 base = r.deltaparent(i)
1937 base = r.deltaparent(i)
1938 else:
1938 else:
1939 base = r.chainbase(i)
1939 base = r.chainbase(i)
1940 if format == 0:
1940 if format == 0:
1941 try:
1941 try:
1942 pp = r.parents(node)
1942 pp = r.parents(node)
1943 except Exception:
1943 except Exception:
1944 pp = [nullid, nullid]
1944 pp = [nullid, nullid]
1945 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1945 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1946 i, r.start(i), r.length(i), base, r.linkrev(i),
1946 i, r.start(i), r.length(i), base, r.linkrev(i),
1947 short(node), short(pp[0]), short(pp[1])))
1947 short(node), short(pp[0]), short(pp[1])))
1948 elif format == 1:
1948 elif format == 1:
1949 pr = r.parentrevs(i)
1949 pr = r.parentrevs(i)
1950 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1950 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1951 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1951 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1952 base, r.linkrev(i), pr[0], pr[1], short(node)))
1952 base, r.linkrev(i), pr[0], pr[1], short(node)))
1953
1953
1954 @command('debugindexdot', [], _('FILE'))
1954 @command('debugindexdot', [], _('FILE'))
1955 def debugindexdot(ui, repo, file_):
1955 def debugindexdot(ui, repo, file_):
1956 """dump an index DAG as a graphviz dot file"""
1956 """dump an index DAG as a graphviz dot file"""
1957 r = None
1957 r = None
1958 if repo:
1958 if repo:
1959 filelog = repo.file(file_)
1959 filelog = repo.file(file_)
1960 if len(filelog):
1960 if len(filelog):
1961 r = filelog
1961 r = filelog
1962 if not r:
1962 if not r:
1963 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1963 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1964 ui.write("digraph G {\n")
1964 ui.write("digraph G {\n")
1965 for i in r:
1965 for i in r:
1966 node = r.node(i)
1966 node = r.node(i)
1967 pp = r.parents(node)
1967 pp = r.parents(node)
1968 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1968 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1969 if pp[1] != nullid:
1969 if pp[1] != nullid:
1970 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1970 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1971 ui.write("}\n")
1971 ui.write("}\n")
1972
1972
1973 @command('debuginstall', [], '')
1973 @command('debuginstall', [], '')
1974 def debuginstall(ui):
1974 def debuginstall(ui):
1975 '''test Mercurial installation
1975 '''test Mercurial installation
1976
1976
1977 Returns 0 on success.
1977 Returns 0 on success.
1978 '''
1978 '''
1979
1979
1980 def writetemp(contents):
1980 def writetemp(contents):
1981 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1981 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1982 f = os.fdopen(fd, "wb")
1982 f = os.fdopen(fd, "wb")
1983 f.write(contents)
1983 f.write(contents)
1984 f.close()
1984 f.close()
1985 return name
1985 return name
1986
1986
1987 problems = 0
1987 problems = 0
1988
1988
1989 # encoding
1989 # encoding
1990 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1990 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1991 try:
1991 try:
1992 encoding.fromlocal("test")
1992 encoding.fromlocal("test")
1993 except util.Abort, inst:
1993 except util.Abort, inst:
1994 ui.write(" %s\n" % inst)
1994 ui.write(" %s\n" % inst)
1995 ui.write(_(" (check that your locale is properly set)\n"))
1995 ui.write(_(" (check that your locale is properly set)\n"))
1996 problems += 1
1996 problems += 1
1997
1997
1998 # compiled modules
1998 # compiled modules
1999 ui.status(_("checking installed modules (%s)...\n")
1999 ui.status(_("checking installed modules (%s)...\n")
2000 % os.path.dirname(__file__))
2000 % os.path.dirname(__file__))
2001 try:
2001 try:
2002 import bdiff, mpatch, base85, osutil
2002 import bdiff, mpatch, base85, osutil
2003 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2003 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2004 except Exception, inst:
2004 except Exception, inst:
2005 ui.write(" %s\n" % inst)
2005 ui.write(" %s\n" % inst)
2006 ui.write(_(" One or more extensions could not be found"))
2006 ui.write(_(" One or more extensions could not be found"))
2007 ui.write(_(" (check that you compiled the extensions)\n"))
2007 ui.write(_(" (check that you compiled the extensions)\n"))
2008 problems += 1
2008 problems += 1
2009
2009
2010 # templates
2010 # templates
2011 import templater
2011 import templater
2012 p = templater.templatepath()
2012 p = templater.templatepath()
2013 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2013 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2014 try:
2014 try:
2015 templater.templater(templater.templatepath("map-cmdline.default"))
2015 templater.templater(templater.templatepath("map-cmdline.default"))
2016 except Exception, inst:
2016 except Exception, inst:
2017 ui.write(" %s\n" % inst)
2017 ui.write(" %s\n" % inst)
2018 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2018 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2019 problems += 1
2019 problems += 1
2020
2020
2021 # editor
2021 # editor
2022 ui.status(_("checking commit editor...\n"))
2022 ui.status(_("checking commit editor...\n"))
2023 editor = ui.geteditor()
2023 editor = ui.geteditor()
2024 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2024 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2025 if not cmdpath:
2025 if not cmdpath:
2026 if editor == 'vi':
2026 if editor == 'vi':
2027 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2027 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2028 ui.write(_(" (specify a commit editor in your configuration"
2028 ui.write(_(" (specify a commit editor in your configuration"
2029 " file)\n"))
2029 " file)\n"))
2030 else:
2030 else:
2031 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2031 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2032 ui.write(_(" (specify a commit editor in your configuration"
2032 ui.write(_(" (specify a commit editor in your configuration"
2033 " file)\n"))
2033 " file)\n"))
2034 problems += 1
2034 problems += 1
2035
2035
2036 # check username
2036 # check username
2037 ui.status(_("checking username...\n"))
2037 ui.status(_("checking username...\n"))
2038 try:
2038 try:
2039 ui.username()
2039 ui.username()
2040 except util.Abort, e:
2040 except util.Abort, e:
2041 ui.write(" %s\n" % e)
2041 ui.write(" %s\n" % e)
2042 ui.write(_(" (specify a username in your configuration file)\n"))
2042 ui.write(_(" (specify a username in your configuration file)\n"))
2043 problems += 1
2043 problems += 1
2044
2044
2045 if not problems:
2045 if not problems:
2046 ui.status(_("no problems detected\n"))
2046 ui.status(_("no problems detected\n"))
2047 else:
2047 else:
2048 ui.write(_("%s problems detected,"
2048 ui.write(_("%s problems detected,"
2049 " please check your install!\n") % problems)
2049 " please check your install!\n") % problems)
2050
2050
2051 return problems
2051 return problems
2052
2052
2053 @command('debugknown', [], _('REPO ID...'))
2053 @command('debugknown', [], _('REPO ID...'))
2054 def debugknown(ui, repopath, *ids, **opts):
2054 def debugknown(ui, repopath, *ids, **opts):
2055 """test whether node ids are known to a repo
2055 """test whether node ids are known to a repo
2056
2056
2057 Every ID must be a full-length hex node id string. Returns a list of 0s
2057 Every ID must be a full-length hex node id string. Returns a list of 0s
2058 and 1s indicating unknown/known.
2058 and 1s indicating unknown/known.
2059 """
2059 """
2060 repo = hg.peer(ui, opts, repopath)
2060 repo = hg.peer(ui, opts, repopath)
2061 if not repo.capable('known'):
2061 if not repo.capable('known'):
2062 raise util.Abort("known() not supported by target repository")
2062 raise util.Abort("known() not supported by target repository")
2063 flags = repo.known([bin(s) for s in ids])
2063 flags = repo.known([bin(s) for s in ids])
2064 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2064 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2065
2065
2066 @command('debugobsolete', [] + commitopts2,
2066 @command('debugobsolete', [] + commitopts2,
2067 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2067 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2068 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2068 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2069 """create arbitrary obsolete marker"""
2069 """create arbitrary obsolete marker"""
2070 if precursor is not None:
2070 if precursor is not None:
2071 metadata = {}
2071 metadata = {}
2072 if 'date' in opts:
2072 if 'date' in opts:
2073 metadata['date'] = opts['date']
2073 metadata['date'] = opts['date']
2074 metadata['user'] = opts['user'] or ui.username()
2074 metadata['user'] = opts['user'] or ui.username()
2075 succs = tuple(bin(succ) for succ in successors)
2075 succs = tuple(bin(succ) for succ in successors)
2076 l = repo.lock()
2076 l = repo.lock()
2077 try:
2077 try:
2078 tr = repo.transaction('debugobsolete')
2078 tr = repo.transaction('debugobsolete')
2079 try:
2079 try:
2080 repo.obsstore.create(tr, bin(precursor), succs, 0, metadata)
2080 repo.obsstore.create(tr, bin(precursor), succs, 0, metadata)
2081 tr.close()
2081 tr.close()
2082 finally:
2082 finally:
2083 tr.release()
2083 tr.release()
2084 finally:
2084 finally:
2085 l.release()
2085 l.release()
2086 else:
2086 else:
2087 for m in obsolete.allmarkers(repo):
2087 for m in obsolete.allmarkers(repo):
2088 ui.write(hex(m.precnode()))
2088 ui.write(hex(m.precnode()))
2089 for repl in m.succnodes():
2089 for repl in m.succnodes():
2090 ui.write(' ')
2090 ui.write(' ')
2091 ui.write(hex(repl))
2091 ui.write(hex(repl))
2092 ui.write(' %X ' % m._data[2])
2092 ui.write(' %X ' % m._data[2])
2093 ui.write(m.metadata())
2093 ui.write(m.metadata())
2094 ui.write('\n')
2094 ui.write('\n')
2095
2095
2096 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2096 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2097 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2097 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2098 '''access the pushkey key/value protocol
2098 '''access the pushkey key/value protocol
2099
2099
2100 With two args, list the keys in the given namespace.
2100 With two args, list the keys in the given namespace.
2101
2101
2102 With five args, set a key to new if it currently is set to old.
2102 With five args, set a key to new if it currently is set to old.
2103 Reports success or failure.
2103 Reports success or failure.
2104 '''
2104 '''
2105
2105
2106 target = hg.peer(ui, {}, repopath)
2106 target = hg.peer(ui, {}, repopath)
2107 if keyinfo:
2107 if keyinfo:
2108 key, old, new = keyinfo
2108 key, old, new = keyinfo
2109 r = target.pushkey(namespace, key, old, new)
2109 r = target.pushkey(namespace, key, old, new)
2110 ui.status(str(r) + '\n')
2110 ui.status(str(r) + '\n')
2111 return not r
2111 return not r
2112 else:
2112 else:
2113 for k, v in target.listkeys(namespace).iteritems():
2113 for k, v in target.listkeys(namespace).iteritems():
2114 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2114 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2115 v.encode('string-escape')))
2115 v.encode('string-escape')))
2116
2116
2117 @command('debugpvec', [], _('A B'))
2117 @command('debugpvec', [], _('A B'))
2118 def debugpvec(ui, repo, a, b=None):
2118 def debugpvec(ui, repo, a, b=None):
2119 ca = scmutil.revsingle(repo, a)
2119 ca = scmutil.revsingle(repo, a)
2120 cb = scmutil.revsingle(repo, b)
2120 cb = scmutil.revsingle(repo, b)
2121 pa = pvec.ctxpvec(ca)
2121 pa = pvec.ctxpvec(ca)
2122 pb = pvec.ctxpvec(cb)
2122 pb = pvec.ctxpvec(cb)
2123 if pa == pb:
2123 if pa == pb:
2124 rel = "="
2124 rel = "="
2125 elif pa > pb:
2125 elif pa > pb:
2126 rel = ">"
2126 rel = ">"
2127 elif pa < pb:
2127 elif pa < pb:
2128 rel = "<"
2128 rel = "<"
2129 elif pa | pb:
2129 elif pa | pb:
2130 rel = "|"
2130 rel = "|"
2131 ui.write(_("a: %s\n") % pa)
2131 ui.write(_("a: %s\n") % pa)
2132 ui.write(_("b: %s\n") % pb)
2132 ui.write(_("b: %s\n") % pb)
2133 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2133 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2134 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2134 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2135 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2135 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2136 pa.distance(pb), rel))
2136 pa.distance(pb), rel))
2137
2137
2138 @command('debugrebuildstate',
2138 @command('debugrebuildstate',
2139 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2139 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2140 _('[-r REV] [REV]'))
2140 _('[-r REV] [REV]'))
2141 def debugrebuildstate(ui, repo, rev="tip"):
2141 def debugrebuildstate(ui, repo, rev="tip"):
2142 """rebuild the dirstate as it would look like for the given revision"""
2142 """rebuild the dirstate as it would look like for the given revision"""
2143 ctx = scmutil.revsingle(repo, rev)
2143 ctx = scmutil.revsingle(repo, rev)
2144 wlock = repo.wlock()
2144 wlock = repo.wlock()
2145 try:
2145 try:
2146 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2146 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2147 finally:
2147 finally:
2148 wlock.release()
2148 wlock.release()
2149
2149
2150 @command('debugrename',
2150 @command('debugrename',
2151 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2151 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2152 _('[-r REV] FILE'))
2152 _('[-r REV] FILE'))
2153 def debugrename(ui, repo, file1, *pats, **opts):
2153 def debugrename(ui, repo, file1, *pats, **opts):
2154 """dump rename information"""
2154 """dump rename information"""
2155
2155
2156 ctx = scmutil.revsingle(repo, opts.get('rev'))
2156 ctx = scmutil.revsingle(repo, opts.get('rev'))
2157 m = scmutil.match(ctx, (file1,) + pats, opts)
2157 m = scmutil.match(ctx, (file1,) + pats, opts)
2158 for abs in ctx.walk(m):
2158 for abs in ctx.walk(m):
2159 fctx = ctx[abs]
2159 fctx = ctx[abs]
2160 o = fctx.filelog().renamed(fctx.filenode())
2160 o = fctx.filelog().renamed(fctx.filenode())
2161 rel = m.rel(abs)
2161 rel = m.rel(abs)
2162 if o:
2162 if o:
2163 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2163 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2164 else:
2164 else:
2165 ui.write(_("%s not renamed\n") % rel)
2165 ui.write(_("%s not renamed\n") % rel)
2166
2166
2167 @command('debugrevlog',
2167 @command('debugrevlog',
2168 [('c', 'changelog', False, _('open changelog')),
2168 [('c', 'changelog', False, _('open changelog')),
2169 ('m', 'manifest', False, _('open manifest')),
2169 ('m', 'manifest', False, _('open manifest')),
2170 ('d', 'dump', False, _('dump index data'))],
2170 ('d', 'dump', False, _('dump index data'))],
2171 _('-c|-m|FILE'))
2171 _('-c|-m|FILE'))
2172 def debugrevlog(ui, repo, file_ = None, **opts):
2172 def debugrevlog(ui, repo, file_ = None, **opts):
2173 """show data and statistics about a revlog"""
2173 """show data and statistics about a revlog"""
2174 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2174 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2175
2175
2176 if opts.get("dump"):
2176 if opts.get("dump"):
2177 numrevs = len(r)
2177 numrevs = len(r)
2178 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2178 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2179 " rawsize totalsize compression heads\n")
2179 " rawsize totalsize compression heads\n")
2180 ts = 0
2180 ts = 0
2181 heads = set()
2181 heads = set()
2182 for rev in xrange(numrevs):
2182 for rev in xrange(numrevs):
2183 dbase = r.deltaparent(rev)
2183 dbase = r.deltaparent(rev)
2184 if dbase == -1:
2184 if dbase == -1:
2185 dbase = rev
2185 dbase = rev
2186 cbase = r.chainbase(rev)
2186 cbase = r.chainbase(rev)
2187 p1, p2 = r.parentrevs(rev)
2187 p1, p2 = r.parentrevs(rev)
2188 rs = r.rawsize(rev)
2188 rs = r.rawsize(rev)
2189 ts = ts + rs
2189 ts = ts + rs
2190 heads -= set(r.parentrevs(rev))
2190 heads -= set(r.parentrevs(rev))
2191 heads.add(rev)
2191 heads.add(rev)
2192 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2192 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2193 (rev, p1, p2, r.start(rev), r.end(rev),
2193 (rev, p1, p2, r.start(rev), r.end(rev),
2194 r.start(dbase), r.start(cbase),
2194 r.start(dbase), r.start(cbase),
2195 r.start(p1), r.start(p2),
2195 r.start(p1), r.start(p2),
2196 rs, ts, ts / r.end(rev), len(heads)))
2196 rs, ts, ts / r.end(rev), len(heads)))
2197 return 0
2197 return 0
2198
2198
2199 v = r.version
2199 v = r.version
2200 format = v & 0xFFFF
2200 format = v & 0xFFFF
2201 flags = []
2201 flags = []
2202 gdelta = False
2202 gdelta = False
2203 if v & revlog.REVLOGNGINLINEDATA:
2203 if v & revlog.REVLOGNGINLINEDATA:
2204 flags.append('inline')
2204 flags.append('inline')
2205 if v & revlog.REVLOGGENERALDELTA:
2205 if v & revlog.REVLOGGENERALDELTA:
2206 gdelta = True
2206 gdelta = True
2207 flags.append('generaldelta')
2207 flags.append('generaldelta')
2208 if not flags:
2208 if not flags:
2209 flags = ['(none)']
2209 flags = ['(none)']
2210
2210
2211 nummerges = 0
2211 nummerges = 0
2212 numfull = 0
2212 numfull = 0
2213 numprev = 0
2213 numprev = 0
2214 nump1 = 0
2214 nump1 = 0
2215 nump2 = 0
2215 nump2 = 0
2216 numother = 0
2216 numother = 0
2217 nump1prev = 0
2217 nump1prev = 0
2218 nump2prev = 0
2218 nump2prev = 0
2219 chainlengths = []
2219 chainlengths = []
2220
2220
2221 datasize = [None, 0, 0L]
2221 datasize = [None, 0, 0L]
2222 fullsize = [None, 0, 0L]
2222 fullsize = [None, 0, 0L]
2223 deltasize = [None, 0, 0L]
2223 deltasize = [None, 0, 0L]
2224
2224
2225 def addsize(size, l):
2225 def addsize(size, l):
2226 if l[0] is None or size < l[0]:
2226 if l[0] is None or size < l[0]:
2227 l[0] = size
2227 l[0] = size
2228 if size > l[1]:
2228 if size > l[1]:
2229 l[1] = size
2229 l[1] = size
2230 l[2] += size
2230 l[2] += size
2231
2231
2232 numrevs = len(r)
2232 numrevs = len(r)
2233 for rev in xrange(numrevs):
2233 for rev in xrange(numrevs):
2234 p1, p2 = r.parentrevs(rev)
2234 p1, p2 = r.parentrevs(rev)
2235 delta = r.deltaparent(rev)
2235 delta = r.deltaparent(rev)
2236 if format > 0:
2236 if format > 0:
2237 addsize(r.rawsize(rev), datasize)
2237 addsize(r.rawsize(rev), datasize)
2238 if p2 != nullrev:
2238 if p2 != nullrev:
2239 nummerges += 1
2239 nummerges += 1
2240 size = r.length(rev)
2240 size = r.length(rev)
2241 if delta == nullrev:
2241 if delta == nullrev:
2242 chainlengths.append(0)
2242 chainlengths.append(0)
2243 numfull += 1
2243 numfull += 1
2244 addsize(size, fullsize)
2244 addsize(size, fullsize)
2245 else:
2245 else:
2246 chainlengths.append(chainlengths[delta] + 1)
2246 chainlengths.append(chainlengths[delta] + 1)
2247 addsize(size, deltasize)
2247 addsize(size, deltasize)
2248 if delta == rev - 1:
2248 if delta == rev - 1:
2249 numprev += 1
2249 numprev += 1
2250 if delta == p1:
2250 if delta == p1:
2251 nump1prev += 1
2251 nump1prev += 1
2252 elif delta == p2:
2252 elif delta == p2:
2253 nump2prev += 1
2253 nump2prev += 1
2254 elif delta == p1:
2254 elif delta == p1:
2255 nump1 += 1
2255 nump1 += 1
2256 elif delta == p2:
2256 elif delta == p2:
2257 nump2 += 1
2257 nump2 += 1
2258 elif delta != nullrev:
2258 elif delta != nullrev:
2259 numother += 1
2259 numother += 1
2260
2260
2261 # Adjust size min value for empty cases
2261 # Adjust size min value for empty cases
2262 for size in (datasize, fullsize, deltasize):
2262 for size in (datasize, fullsize, deltasize):
2263 if size[0] is None:
2263 if size[0] is None:
2264 size[0] = 0
2264 size[0] = 0
2265
2265
2266 numdeltas = numrevs - numfull
2266 numdeltas = numrevs - numfull
2267 numoprev = numprev - nump1prev - nump2prev
2267 numoprev = numprev - nump1prev - nump2prev
2268 totalrawsize = datasize[2]
2268 totalrawsize = datasize[2]
2269 datasize[2] /= numrevs
2269 datasize[2] /= numrevs
2270 fulltotal = fullsize[2]
2270 fulltotal = fullsize[2]
2271 fullsize[2] /= numfull
2271 fullsize[2] /= numfull
2272 deltatotal = deltasize[2]
2272 deltatotal = deltasize[2]
2273 if numrevs - numfull > 0:
2273 if numrevs - numfull > 0:
2274 deltasize[2] /= numrevs - numfull
2274 deltasize[2] /= numrevs - numfull
2275 totalsize = fulltotal + deltatotal
2275 totalsize = fulltotal + deltatotal
2276 avgchainlen = sum(chainlengths) / numrevs
2276 avgchainlen = sum(chainlengths) / numrevs
2277 compratio = totalrawsize / totalsize
2277 compratio = totalrawsize / totalsize
2278
2278
2279 basedfmtstr = '%%%dd\n'
2279 basedfmtstr = '%%%dd\n'
2280 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2280 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2281
2281
2282 def dfmtstr(max):
2282 def dfmtstr(max):
2283 return basedfmtstr % len(str(max))
2283 return basedfmtstr % len(str(max))
2284 def pcfmtstr(max, padding=0):
2284 def pcfmtstr(max, padding=0):
2285 return basepcfmtstr % (len(str(max)), ' ' * padding)
2285 return basepcfmtstr % (len(str(max)), ' ' * padding)
2286
2286
2287 def pcfmt(value, total):
2287 def pcfmt(value, total):
2288 return (value, 100 * float(value) / total)
2288 return (value, 100 * float(value) / total)
2289
2289
2290 ui.write('format : %d\n' % format)
2290 ui.write('format : %d\n' % format)
2291 ui.write('flags : %s\n' % ', '.join(flags))
2291 ui.write('flags : %s\n' % ', '.join(flags))
2292
2292
2293 ui.write('\n')
2293 ui.write('\n')
2294 fmt = pcfmtstr(totalsize)
2294 fmt = pcfmtstr(totalsize)
2295 fmt2 = dfmtstr(totalsize)
2295 fmt2 = dfmtstr(totalsize)
2296 ui.write('revisions : ' + fmt2 % numrevs)
2296 ui.write('revisions : ' + fmt2 % numrevs)
2297 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2297 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2298 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2298 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2299 ui.write('revisions : ' + fmt2 % numrevs)
2299 ui.write('revisions : ' + fmt2 % numrevs)
2300 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2300 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2301 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2301 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2302 ui.write('revision size : ' + fmt2 % totalsize)
2302 ui.write('revision size : ' + fmt2 % totalsize)
2303 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2303 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2304 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2304 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2305
2305
2306 ui.write('\n')
2306 ui.write('\n')
2307 fmt = dfmtstr(max(avgchainlen, compratio))
2307 fmt = dfmtstr(max(avgchainlen, compratio))
2308 ui.write('avg chain length : ' + fmt % avgchainlen)
2308 ui.write('avg chain length : ' + fmt % avgchainlen)
2309 ui.write('compression ratio : ' + fmt % compratio)
2309 ui.write('compression ratio : ' + fmt % compratio)
2310
2310
2311 if format > 0:
2311 if format > 0:
2312 ui.write('\n')
2312 ui.write('\n')
2313 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2313 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2314 % tuple(datasize))
2314 % tuple(datasize))
2315 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2315 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2316 % tuple(fullsize))
2316 % tuple(fullsize))
2317 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2317 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2318 % tuple(deltasize))
2318 % tuple(deltasize))
2319
2319
2320 if numdeltas > 0:
2320 if numdeltas > 0:
2321 ui.write('\n')
2321 ui.write('\n')
2322 fmt = pcfmtstr(numdeltas)
2322 fmt = pcfmtstr(numdeltas)
2323 fmt2 = pcfmtstr(numdeltas, 4)
2323 fmt2 = pcfmtstr(numdeltas, 4)
2324 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2324 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2325 if numprev > 0:
2325 if numprev > 0:
2326 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2326 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2327 numprev))
2327 numprev))
2328 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2328 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2329 numprev))
2329 numprev))
2330 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2330 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2331 numprev))
2331 numprev))
2332 if gdelta:
2332 if gdelta:
2333 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2333 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2334 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2334 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2335 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2335 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2336 numdeltas))
2336 numdeltas))
2337
2337
2338 @command('debugrevspec', [], ('REVSPEC'))
2338 @command('debugrevspec', [], ('REVSPEC'))
2339 def debugrevspec(ui, repo, expr):
2339 def debugrevspec(ui, repo, expr):
2340 """parse and apply a revision specification
2340 """parse and apply a revision specification
2341
2341
2342 Use --verbose to print the parsed tree before and after aliases
2342 Use --verbose to print the parsed tree before and after aliases
2343 expansion.
2343 expansion.
2344 """
2344 """
2345 if ui.verbose:
2345 if ui.verbose:
2346 tree = revset.parse(expr)[0]
2346 tree = revset.parse(expr)[0]
2347 ui.note(revset.prettyformat(tree), "\n")
2347 ui.note(revset.prettyformat(tree), "\n")
2348 newtree = revset.findaliases(ui, tree)
2348 newtree = revset.findaliases(ui, tree)
2349 if newtree != tree:
2349 if newtree != tree:
2350 ui.note(revset.prettyformat(newtree), "\n")
2350 ui.note(revset.prettyformat(newtree), "\n")
2351 func = revset.match(ui, expr)
2351 func = revset.match(ui, expr)
2352 for c in func(repo, range(len(repo))):
2352 for c in func(repo, range(len(repo))):
2353 ui.write("%s\n" % c)
2353 ui.write("%s\n" % c)
2354
2354
2355 @command('debugsetparents', [], _('REV1 [REV2]'))
2355 @command('debugsetparents', [], _('REV1 [REV2]'))
2356 def debugsetparents(ui, repo, rev1, rev2=None):
2356 def debugsetparents(ui, repo, rev1, rev2=None):
2357 """manually set the parents of the current working directory
2357 """manually set the parents of the current working directory
2358
2358
2359 This is useful for writing repository conversion tools, but should
2359 This is useful for writing repository conversion tools, but should
2360 be used with care.
2360 be used with care.
2361
2361
2362 Returns 0 on success.
2362 Returns 0 on success.
2363 """
2363 """
2364
2364
2365 r1 = scmutil.revsingle(repo, rev1).node()
2365 r1 = scmutil.revsingle(repo, rev1).node()
2366 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2366 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2367
2367
2368 wlock = repo.wlock()
2368 wlock = repo.wlock()
2369 try:
2369 try:
2370 repo.setparents(r1, r2)
2370 repo.setparents(r1, r2)
2371 finally:
2371 finally:
2372 wlock.release()
2372 wlock.release()
2373
2373
2374 @command('debugstate',
2374 @command('debugstate',
2375 [('', 'nodates', None, _('do not display the saved mtime')),
2375 [('', 'nodates', None, _('do not display the saved mtime')),
2376 ('', 'datesort', None, _('sort by saved mtime'))],
2376 ('', 'datesort', None, _('sort by saved mtime'))],
2377 _('[OPTION]...'))
2377 _('[OPTION]...'))
2378 def debugstate(ui, repo, nodates=None, datesort=None):
2378 def debugstate(ui, repo, nodates=None, datesort=None):
2379 """show the contents of the current dirstate"""
2379 """show the contents of the current dirstate"""
2380 timestr = ""
2380 timestr = ""
2381 showdate = not nodates
2381 showdate = not nodates
2382 if datesort:
2382 if datesort:
2383 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2383 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2384 else:
2384 else:
2385 keyfunc = None # sort by filename
2385 keyfunc = None # sort by filename
2386 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2386 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2387 if showdate:
2387 if showdate:
2388 if ent[3] == -1:
2388 if ent[3] == -1:
2389 # Pad or slice to locale representation
2389 # Pad or slice to locale representation
2390 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2390 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2391 time.localtime(0)))
2391 time.localtime(0)))
2392 timestr = 'unset'
2392 timestr = 'unset'
2393 timestr = (timestr[:locale_len] +
2393 timestr = (timestr[:locale_len] +
2394 ' ' * (locale_len - len(timestr)))
2394 ' ' * (locale_len - len(timestr)))
2395 else:
2395 else:
2396 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2396 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2397 time.localtime(ent[3]))
2397 time.localtime(ent[3]))
2398 if ent[1] & 020000:
2398 if ent[1] & 020000:
2399 mode = 'lnk'
2399 mode = 'lnk'
2400 else:
2400 else:
2401 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2401 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2402 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2402 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2403 for f in repo.dirstate.copies():
2403 for f in repo.dirstate.copies():
2404 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2404 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2405
2405
2406 @command('debugsub',
2406 @command('debugsub',
2407 [('r', 'rev', '',
2407 [('r', 'rev', '',
2408 _('revision to check'), _('REV'))],
2408 _('revision to check'), _('REV'))],
2409 _('[-r REV] [REV]'))
2409 _('[-r REV] [REV]'))
2410 def debugsub(ui, repo, rev=None):
2410 def debugsub(ui, repo, rev=None):
2411 ctx = scmutil.revsingle(repo, rev, None)
2411 ctx = scmutil.revsingle(repo, rev, None)
2412 for k, v in sorted(ctx.substate.items()):
2412 for k, v in sorted(ctx.substate.items()):
2413 ui.write('path %s\n' % k)
2413 ui.write('path %s\n' % k)
2414 ui.write(' source %s\n' % v[0])
2414 ui.write(' source %s\n' % v[0])
2415 ui.write(' revision %s\n' % v[1])
2415 ui.write(' revision %s\n' % v[1])
2416
2416
2417 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2417 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2418 def debugwalk(ui, repo, *pats, **opts):
2418 def debugwalk(ui, repo, *pats, **opts):
2419 """show how files match on given patterns"""
2419 """show how files match on given patterns"""
2420 m = scmutil.match(repo[None], pats, opts)
2420 m = scmutil.match(repo[None], pats, opts)
2421 items = list(repo.walk(m))
2421 items = list(repo.walk(m))
2422 if not items:
2422 if not items:
2423 return
2423 return
2424 f = lambda fn: fn
2424 f = lambda fn: fn
2425 if ui.configbool('ui', 'slash') and os.sep != '/':
2425 if ui.configbool('ui', 'slash') and os.sep != '/':
2426 f = lambda fn: util.normpath(fn)
2426 f = lambda fn: util.normpath(fn)
2427 fmt = 'f %%-%ds %%-%ds %%s' % (
2427 fmt = 'f %%-%ds %%-%ds %%s' % (
2428 max([len(abs) for abs in items]),
2428 max([len(abs) for abs in items]),
2429 max([len(m.rel(abs)) for abs in items]))
2429 max([len(m.rel(abs)) for abs in items]))
2430 for abs in items:
2430 for abs in items:
2431 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2431 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2432 ui.write("%s\n" % line.rstrip())
2432 ui.write("%s\n" % line.rstrip())
2433
2433
2434 @command('debugwireargs',
2434 @command('debugwireargs',
2435 [('', 'three', '', 'three'),
2435 [('', 'three', '', 'three'),
2436 ('', 'four', '', 'four'),
2436 ('', 'four', '', 'four'),
2437 ('', 'five', '', 'five'),
2437 ('', 'five', '', 'five'),
2438 ] + remoteopts,
2438 ] + remoteopts,
2439 _('REPO [OPTIONS]... [ONE [TWO]]'))
2439 _('REPO [OPTIONS]... [ONE [TWO]]'))
2440 def debugwireargs(ui, repopath, *vals, **opts):
2440 def debugwireargs(ui, repopath, *vals, **opts):
2441 repo = hg.peer(ui, opts, repopath)
2441 repo = hg.peer(ui, opts, repopath)
2442 for opt in remoteopts:
2442 for opt in remoteopts:
2443 del opts[opt[1]]
2443 del opts[opt[1]]
2444 args = {}
2444 args = {}
2445 for k, v in opts.iteritems():
2445 for k, v in opts.iteritems():
2446 if v:
2446 if v:
2447 args[k] = v
2447 args[k] = v
2448 # run twice to check that we don't mess up the stream for the next command
2448 # run twice to check that we don't mess up the stream for the next command
2449 res1 = repo.debugwireargs(*vals, **args)
2449 res1 = repo.debugwireargs(*vals, **args)
2450 res2 = repo.debugwireargs(*vals, **args)
2450 res2 = repo.debugwireargs(*vals, **args)
2451 ui.write("%s\n" % res1)
2451 ui.write("%s\n" % res1)
2452 if res1 != res2:
2452 if res1 != res2:
2453 ui.warn("%s\n" % res2)
2453 ui.warn("%s\n" % res2)
2454
2454
2455 @command('^diff',
2455 @command('^diff',
2456 [('r', 'rev', [], _('revision'), _('REV')),
2456 [('r', 'rev', [], _('revision'), _('REV')),
2457 ('c', 'change', '', _('change made by revision'), _('REV'))
2457 ('c', 'change', '', _('change made by revision'), _('REV'))
2458 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2458 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2459 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2459 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2460 def diff(ui, repo, *pats, **opts):
2460 def diff(ui, repo, *pats, **opts):
2461 """diff repository (or selected files)
2461 """diff repository (or selected files)
2462
2462
2463 Show differences between revisions for the specified files.
2463 Show differences between revisions for the specified files.
2464
2464
2465 Differences between files are shown using the unified diff format.
2465 Differences between files are shown using the unified diff format.
2466
2466
2467 .. note::
2467 .. note::
2468 diff may generate unexpected results for merges, as it will
2468 diff may generate unexpected results for merges, as it will
2469 default to comparing against the working directory's first
2469 default to comparing against the working directory's first
2470 parent changeset if no revisions are specified.
2470 parent changeset if no revisions are specified.
2471
2471
2472 When two revision arguments are given, then changes are shown
2472 When two revision arguments are given, then changes are shown
2473 between those revisions. If only one revision is specified then
2473 between those revisions. If only one revision is specified then
2474 that revision is compared to the working directory, and, when no
2474 that revision is compared to the working directory, and, when no
2475 revisions are specified, the working directory files are compared
2475 revisions are specified, the working directory files are compared
2476 to its parent.
2476 to its parent.
2477
2477
2478 Alternatively you can specify -c/--change with a revision to see
2478 Alternatively you can specify -c/--change with a revision to see
2479 the changes in that changeset relative to its first parent.
2479 the changes in that changeset relative to its first parent.
2480
2480
2481 Without the -a/--text option, diff will avoid generating diffs of
2481 Without the -a/--text option, diff will avoid generating diffs of
2482 files it detects as binary. With -a, diff will generate a diff
2482 files it detects as binary. With -a, diff will generate a diff
2483 anyway, probably with undesirable results.
2483 anyway, probably with undesirable results.
2484
2484
2485 Use the -g/--git option to generate diffs in the git extended diff
2485 Use the -g/--git option to generate diffs in the git extended diff
2486 format. For more information, read :hg:`help diffs`.
2486 format. For more information, read :hg:`help diffs`.
2487
2487
2488 .. container:: verbose
2488 .. container:: verbose
2489
2489
2490 Examples:
2490 Examples:
2491
2491
2492 - compare a file in the current working directory to its parent::
2492 - compare a file in the current working directory to its parent::
2493
2493
2494 hg diff foo.c
2494 hg diff foo.c
2495
2495
2496 - compare two historical versions of a directory, with rename info::
2496 - compare two historical versions of a directory, with rename info::
2497
2497
2498 hg diff --git -r 1.0:1.2 lib/
2498 hg diff --git -r 1.0:1.2 lib/
2499
2499
2500 - get change stats relative to the last change on some date::
2500 - get change stats relative to the last change on some date::
2501
2501
2502 hg diff --stat -r "date('may 2')"
2502 hg diff --stat -r "date('may 2')"
2503
2503
2504 - diff all newly-added files that contain a keyword::
2504 - diff all newly-added files that contain a keyword::
2505
2505
2506 hg diff "set:added() and grep(GNU)"
2506 hg diff "set:added() and grep(GNU)"
2507
2507
2508 - compare a revision and its parents::
2508 - compare a revision and its parents::
2509
2509
2510 hg diff -c 9353 # compare against first parent
2510 hg diff -c 9353 # compare against first parent
2511 hg diff -r 9353^:9353 # same using revset syntax
2511 hg diff -r 9353^:9353 # same using revset syntax
2512 hg diff -r 9353^2:9353 # compare against the second parent
2512 hg diff -r 9353^2:9353 # compare against the second parent
2513
2513
2514 Returns 0 on success.
2514 Returns 0 on success.
2515 """
2515 """
2516
2516
2517 revs = opts.get('rev')
2517 revs = opts.get('rev')
2518 change = opts.get('change')
2518 change = opts.get('change')
2519 stat = opts.get('stat')
2519 stat = opts.get('stat')
2520 reverse = opts.get('reverse')
2520 reverse = opts.get('reverse')
2521
2521
2522 if revs and change:
2522 if revs and change:
2523 msg = _('cannot specify --rev and --change at the same time')
2523 msg = _('cannot specify --rev and --change at the same time')
2524 raise util.Abort(msg)
2524 raise util.Abort(msg)
2525 elif change:
2525 elif change:
2526 node2 = scmutil.revsingle(repo, change, None).node()
2526 node2 = scmutil.revsingle(repo, change, None).node()
2527 node1 = repo[node2].p1().node()
2527 node1 = repo[node2].p1().node()
2528 else:
2528 else:
2529 node1, node2 = scmutil.revpair(repo, revs)
2529 node1, node2 = scmutil.revpair(repo, revs)
2530
2530
2531 if reverse:
2531 if reverse:
2532 node1, node2 = node2, node1
2532 node1, node2 = node2, node1
2533
2533
2534 diffopts = patch.diffopts(ui, opts)
2534 diffopts = patch.diffopts(ui, opts)
2535 m = scmutil.match(repo[node2], pats, opts)
2535 m = scmutil.match(repo[node2], pats, opts)
2536 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2536 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2537 listsubrepos=opts.get('subrepos'))
2537 listsubrepos=opts.get('subrepos'))
2538
2538
2539 @command('^export',
2539 @command('^export',
2540 [('o', 'output', '',
2540 [('o', 'output', '',
2541 _('print output to file with formatted name'), _('FORMAT')),
2541 _('print output to file with formatted name'), _('FORMAT')),
2542 ('', 'switch-parent', None, _('diff against the second parent')),
2542 ('', 'switch-parent', None, _('diff against the second parent')),
2543 ('r', 'rev', [], _('revisions to export'), _('REV')),
2543 ('r', 'rev', [], _('revisions to export'), _('REV')),
2544 ] + diffopts,
2544 ] + diffopts,
2545 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2545 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2546 def export(ui, repo, *changesets, **opts):
2546 def export(ui, repo, *changesets, **opts):
2547 """dump the header and diffs for one or more changesets
2547 """dump the header and diffs for one or more changesets
2548
2548
2549 Print the changeset header and diffs for one or more revisions.
2549 Print the changeset header and diffs for one or more revisions.
2550
2550
2551 The information shown in the changeset header is: author, date,
2551 The information shown in the changeset header is: author, date,
2552 branch name (if non-default), changeset hash, parent(s) and commit
2552 branch name (if non-default), changeset hash, parent(s) and commit
2553 comment.
2553 comment.
2554
2554
2555 .. note::
2555 .. note::
2556 export may generate unexpected diff output for merge
2556 export may generate unexpected diff output for merge
2557 changesets, as it will compare the merge changeset against its
2557 changesets, as it will compare the merge changeset against its
2558 first parent only.
2558 first parent only.
2559
2559
2560 Output may be to a file, in which case the name of the file is
2560 Output may be to a file, in which case the name of the file is
2561 given using a format string. The formatting rules are as follows:
2561 given using a format string. The formatting rules are as follows:
2562
2562
2563 :``%%``: literal "%" character
2563 :``%%``: literal "%" character
2564 :``%H``: changeset hash (40 hexadecimal digits)
2564 :``%H``: changeset hash (40 hexadecimal digits)
2565 :``%N``: number of patches being generated
2565 :``%N``: number of patches being generated
2566 :``%R``: changeset revision number
2566 :``%R``: changeset revision number
2567 :``%b``: basename of the exporting repository
2567 :``%b``: basename of the exporting repository
2568 :``%h``: short-form changeset hash (12 hexadecimal digits)
2568 :``%h``: short-form changeset hash (12 hexadecimal digits)
2569 :``%m``: first line of the commit message (only alphanumeric characters)
2569 :``%m``: first line of the commit message (only alphanumeric characters)
2570 :``%n``: zero-padded sequence number, starting at 1
2570 :``%n``: zero-padded sequence number, starting at 1
2571 :``%r``: zero-padded changeset revision number
2571 :``%r``: zero-padded changeset revision number
2572
2572
2573 Without the -a/--text option, export will avoid generating diffs
2573 Without the -a/--text option, export will avoid generating diffs
2574 of files it detects as binary. With -a, export will generate a
2574 of files it detects as binary. With -a, export will generate a
2575 diff anyway, probably with undesirable results.
2575 diff anyway, probably with undesirable results.
2576
2576
2577 Use the -g/--git option to generate diffs in the git extended diff
2577 Use the -g/--git option to generate diffs in the git extended diff
2578 format. See :hg:`help diffs` for more information.
2578 format. See :hg:`help diffs` for more information.
2579
2579
2580 With the --switch-parent option, the diff will be against the
2580 With the --switch-parent option, the diff will be against the
2581 second parent. It can be useful to review a merge.
2581 second parent. It can be useful to review a merge.
2582
2582
2583 .. container:: verbose
2583 .. container:: verbose
2584
2584
2585 Examples:
2585 Examples:
2586
2586
2587 - use export and import to transplant a bugfix to the current
2587 - use export and import to transplant a bugfix to the current
2588 branch::
2588 branch::
2589
2589
2590 hg export -r 9353 | hg import -
2590 hg export -r 9353 | hg import -
2591
2591
2592 - export all the changesets between two revisions to a file with
2592 - export all the changesets between two revisions to a file with
2593 rename information::
2593 rename information::
2594
2594
2595 hg export --git -r 123:150 > changes.txt
2595 hg export --git -r 123:150 > changes.txt
2596
2596
2597 - split outgoing changes into a series of patches with
2597 - split outgoing changes into a series of patches with
2598 descriptive names::
2598 descriptive names::
2599
2599
2600 hg export -r "outgoing()" -o "%n-%m.patch"
2600 hg export -r "outgoing()" -o "%n-%m.patch"
2601
2601
2602 Returns 0 on success.
2602 Returns 0 on success.
2603 """
2603 """
2604 changesets += tuple(opts.get('rev', []))
2604 changesets += tuple(opts.get('rev', []))
2605 revs = scmutil.revrange(repo, changesets)
2605 revs = scmutil.revrange(repo, changesets)
2606 if not revs:
2606 if not revs:
2607 raise util.Abort(_("export requires at least one changeset"))
2607 raise util.Abort(_("export requires at least one changeset"))
2608 if len(revs) > 1:
2608 if len(revs) > 1:
2609 ui.note(_('exporting patches:\n'))
2609 ui.note(_('exporting patches:\n'))
2610 else:
2610 else:
2611 ui.note(_('exporting patch:\n'))
2611 ui.note(_('exporting patch:\n'))
2612 cmdutil.export(repo, revs, template=opts.get('output'),
2612 cmdutil.export(repo, revs, template=opts.get('output'),
2613 switch_parent=opts.get('switch_parent'),
2613 switch_parent=opts.get('switch_parent'),
2614 opts=patch.diffopts(ui, opts))
2614 opts=patch.diffopts(ui, opts))
2615
2615
2616 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2616 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2617 def forget(ui, repo, *pats, **opts):
2617 def forget(ui, repo, *pats, **opts):
2618 """forget the specified files on the next commit
2618 """forget the specified files on the next commit
2619
2619
2620 Mark the specified files so they will no longer be tracked
2620 Mark the specified files so they will no longer be tracked
2621 after the next commit.
2621 after the next commit.
2622
2622
2623 This only removes files from the current branch, not from the
2623 This only removes files from the current branch, not from the
2624 entire project history, and it does not delete them from the
2624 entire project history, and it does not delete them from the
2625 working directory.
2625 working directory.
2626
2626
2627 To undo a forget before the next commit, see :hg:`add`.
2627 To undo a forget before the next commit, see :hg:`add`.
2628
2628
2629 .. container:: verbose
2629 .. container:: verbose
2630
2630
2631 Examples:
2631 Examples:
2632
2632
2633 - forget newly-added binary files::
2633 - forget newly-added binary files::
2634
2634
2635 hg forget "set:added() and binary()"
2635 hg forget "set:added() and binary()"
2636
2636
2637 - forget files that would be excluded by .hgignore::
2637 - forget files that would be excluded by .hgignore::
2638
2638
2639 hg forget "set:hgignore()"
2639 hg forget "set:hgignore()"
2640
2640
2641 Returns 0 on success.
2641 Returns 0 on success.
2642 """
2642 """
2643
2643
2644 if not pats:
2644 if not pats:
2645 raise util.Abort(_('no files specified'))
2645 raise util.Abort(_('no files specified'))
2646
2646
2647 m = scmutil.match(repo[None], pats, opts)
2647 m = scmutil.match(repo[None], pats, opts)
2648 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2648 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2649 return rejected and 1 or 0
2649 return rejected and 1 or 0
2650
2650
2651 @command(
2651 @command(
2652 'graft',
2652 'graft',
2653 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2653 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2654 ('c', 'continue', False, _('resume interrupted graft')),
2654 ('c', 'continue', False, _('resume interrupted graft')),
2655 ('e', 'edit', False, _('invoke editor on commit messages')),
2655 ('e', 'edit', False, _('invoke editor on commit messages')),
2656 ('', 'log', None, _('append graft info to log message')),
2656 ('', 'log', None, _('append graft info to log message')),
2657 ('D', 'currentdate', False,
2657 ('D', 'currentdate', False,
2658 _('record the current date as commit date')),
2658 _('record the current date as commit date')),
2659 ('U', 'currentuser', False,
2659 ('U', 'currentuser', False,
2660 _('record the current user as committer'), _('DATE'))]
2660 _('record the current user as committer'), _('DATE'))]
2661 + commitopts2 + mergetoolopts + dryrunopts,
2661 + commitopts2 + mergetoolopts + dryrunopts,
2662 _('[OPTION]... [-r] REV...'))
2662 _('[OPTION]... [-r] REV...'))
2663 def graft(ui, repo, *revs, **opts):
2663 def graft(ui, repo, *revs, **opts):
2664 '''copy changes from other branches onto the current branch
2664 '''copy changes from other branches onto the current branch
2665
2665
2666 This command uses Mercurial's merge logic to copy individual
2666 This command uses Mercurial's merge logic to copy individual
2667 changes from other branches without merging branches in the
2667 changes from other branches without merging branches in the
2668 history graph. This is sometimes known as 'backporting' or
2668 history graph. This is sometimes known as 'backporting' or
2669 'cherry-picking'. By default, graft will copy user, date, and
2669 'cherry-picking'. By default, graft will copy user, date, and
2670 description from the source changesets.
2670 description from the source changesets.
2671
2671
2672 Changesets that are ancestors of the current revision, that have
2672 Changesets that are ancestors of the current revision, that have
2673 already been grafted, or that are merges will be skipped.
2673 already been grafted, or that are merges will be skipped.
2674
2674
2675 If --log is specified, log messages will have a comment appended
2675 If --log is specified, log messages will have a comment appended
2676 of the form::
2676 of the form::
2677
2677
2678 (grafted from CHANGESETHASH)
2678 (grafted from CHANGESETHASH)
2679
2679
2680 If a graft merge results in conflicts, the graft process is
2680 If a graft merge results in conflicts, the graft process is
2681 interrupted so that the current merge can be manually resolved.
2681 interrupted so that the current merge can be manually resolved.
2682 Once all conflicts are addressed, the graft process can be
2682 Once all conflicts are addressed, the graft process can be
2683 continued with the -c/--continue option.
2683 continued with the -c/--continue option.
2684
2684
2685 .. note::
2685 .. note::
2686 The -c/--continue option does not reapply earlier options.
2686 The -c/--continue option does not reapply earlier options.
2687
2687
2688 .. container:: verbose
2688 .. container:: verbose
2689
2689
2690 Examples:
2690 Examples:
2691
2691
2692 - copy a single change to the stable branch and edit its description::
2692 - copy a single change to the stable branch and edit its description::
2693
2693
2694 hg update stable
2694 hg update stable
2695 hg graft --edit 9393
2695 hg graft --edit 9393
2696
2696
2697 - graft a range of changesets with one exception, updating dates::
2697 - graft a range of changesets with one exception, updating dates::
2698
2698
2699 hg graft -D "2085::2093 and not 2091"
2699 hg graft -D "2085::2093 and not 2091"
2700
2700
2701 - continue a graft after resolving conflicts::
2701 - continue a graft after resolving conflicts::
2702
2702
2703 hg graft -c
2703 hg graft -c
2704
2704
2705 - show the source of a grafted changeset::
2705 - show the source of a grafted changeset::
2706
2706
2707 hg log --debug -r tip
2707 hg log --debug -r tip
2708
2708
2709 Returns 0 on successful completion.
2709 Returns 0 on successful completion.
2710 '''
2710 '''
2711
2711
2712 revs = list(revs)
2712 revs = list(revs)
2713 revs.extend(opts['rev'])
2713 revs.extend(opts['rev'])
2714
2714
2715 if not opts.get('user') and opts.get('currentuser'):
2715 if not opts.get('user') and opts.get('currentuser'):
2716 opts['user'] = ui.username()
2716 opts['user'] = ui.username()
2717 if not opts.get('date') and opts.get('currentdate'):
2717 if not opts.get('date') and opts.get('currentdate'):
2718 opts['date'] = "%d %d" % util.makedate()
2718 opts['date'] = "%d %d" % util.makedate()
2719
2719
2720 editor = None
2720 editor = None
2721 if opts.get('edit'):
2721 if opts.get('edit'):
2722 editor = cmdutil.commitforceeditor
2722 editor = cmdutil.commitforceeditor
2723
2723
2724 cont = False
2724 cont = False
2725 if opts['continue']:
2725 if opts['continue']:
2726 cont = True
2726 cont = True
2727 if revs:
2727 if revs:
2728 raise util.Abort(_("can't specify --continue and revisions"))
2728 raise util.Abort(_("can't specify --continue and revisions"))
2729 # read in unfinished revisions
2729 # read in unfinished revisions
2730 try:
2730 try:
2731 nodes = repo.opener.read('graftstate').splitlines()
2731 nodes = repo.opener.read('graftstate').splitlines()
2732 revs = [repo[node].rev() for node in nodes]
2732 revs = [repo[node].rev() for node in nodes]
2733 except IOError, inst:
2733 except IOError, inst:
2734 if inst.errno != errno.ENOENT:
2734 if inst.errno != errno.ENOENT:
2735 raise
2735 raise
2736 raise util.Abort(_("no graft state found, can't continue"))
2736 raise util.Abort(_("no graft state found, can't continue"))
2737 else:
2737 else:
2738 cmdutil.bailifchanged(repo)
2738 cmdutil.bailifchanged(repo)
2739 if not revs:
2739 if not revs:
2740 raise util.Abort(_('no revisions specified'))
2740 raise util.Abort(_('no revisions specified'))
2741 revs = scmutil.revrange(repo, revs)
2741 revs = scmutil.revrange(repo, revs)
2742
2742
2743 # check for merges
2743 # check for merges
2744 for rev in repo.revs('%ld and merge()', revs):
2744 for rev in repo.revs('%ld and merge()', revs):
2745 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2745 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2746 revs.remove(rev)
2746 revs.remove(rev)
2747 if not revs:
2747 if not revs:
2748 return -1
2748 return -1
2749
2749
2750 # check for ancestors of dest branch
2750 # check for ancestors of dest branch
2751 for rev in repo.revs('::. and %ld', revs):
2751 for rev in repo.revs('::. and %ld', revs):
2752 ui.warn(_('skipping ancestor revision %s\n') % rev)
2752 ui.warn(_('skipping ancestor revision %s\n') % rev)
2753 revs.remove(rev)
2753 revs.remove(rev)
2754 if not revs:
2754 if not revs:
2755 return -1
2755 return -1
2756
2756
2757 # analyze revs for earlier grafts
2757 # analyze revs for earlier grafts
2758 ids = {}
2758 ids = {}
2759 for ctx in repo.set("%ld", revs):
2759 for ctx in repo.set("%ld", revs):
2760 ids[ctx.hex()] = ctx.rev()
2760 ids[ctx.hex()] = ctx.rev()
2761 n = ctx.extra().get('source')
2761 n = ctx.extra().get('source')
2762 if n:
2762 if n:
2763 ids[n] = ctx.rev()
2763 ids[n] = ctx.rev()
2764
2764
2765 # check ancestors for earlier grafts
2765 # check ancestors for earlier grafts
2766 ui.debug('scanning for duplicate grafts\n')
2766 ui.debug('scanning for duplicate grafts\n')
2767 for ctx in repo.set("::. - ::%ld", revs):
2767 for ctx in repo.set("::. - ::%ld", revs):
2768 n = ctx.extra().get('source')
2768 n = ctx.extra().get('source')
2769 if n in ids:
2769 if n in ids:
2770 r = repo[n].rev()
2770 r = repo[n].rev()
2771 if r in revs:
2771 if r in revs:
2772 ui.warn(_('skipping already grafted revision %s\n') % r)
2772 ui.warn(_('skipping already grafted revision %s\n') % r)
2773 revs.remove(r)
2773 revs.remove(r)
2774 elif ids[n] in revs:
2774 elif ids[n] in revs:
2775 ui.warn(_('skipping already grafted revision %s '
2775 ui.warn(_('skipping already grafted revision %s '
2776 '(same origin %d)\n') % (ids[n], r))
2776 '(same origin %d)\n') % (ids[n], r))
2777 revs.remove(ids[n])
2777 revs.remove(ids[n])
2778 elif ctx.hex() in ids:
2778 elif ctx.hex() in ids:
2779 r = ids[ctx.hex()]
2779 r = ids[ctx.hex()]
2780 ui.warn(_('skipping already grafted revision %s '
2780 ui.warn(_('skipping already grafted revision %s '
2781 '(was grafted from %d)\n') % (r, ctx.rev()))
2781 '(was grafted from %d)\n') % (r, ctx.rev()))
2782 revs.remove(r)
2782 revs.remove(r)
2783 if not revs:
2783 if not revs:
2784 return -1
2784 return -1
2785
2785
2786 wlock = repo.wlock()
2786 wlock = repo.wlock()
2787 try:
2787 try:
2788 for pos, ctx in enumerate(repo.set("%ld", revs)):
2788 for pos, ctx in enumerate(repo.set("%ld", revs)):
2789 current = repo['.']
2789 current = repo['.']
2790
2790
2791 ui.status(_('grafting revision %s\n') % ctx.rev())
2791 ui.status(_('grafting revision %s\n') % ctx.rev())
2792 if opts.get('dry_run'):
2792 if opts.get('dry_run'):
2793 continue
2793 continue
2794
2794
2795 # we don't merge the first commit when continuing
2795 # we don't merge the first commit when continuing
2796 if not cont:
2796 if not cont:
2797 # perform the graft merge with p1(rev) as 'ancestor'
2797 # perform the graft merge with p1(rev) as 'ancestor'
2798 try:
2798 try:
2799 # ui.forcemerge is an internal variable, do not document
2799 # ui.forcemerge is an internal variable, do not document
2800 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2800 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2801 stats = mergemod.update(repo, ctx.node(), True, True, False,
2801 stats = mergemod.update(repo, ctx.node(), True, True, False,
2802 ctx.p1().node())
2802 ctx.p1().node())
2803 finally:
2803 finally:
2804 repo.ui.setconfig('ui', 'forcemerge', '')
2804 repo.ui.setconfig('ui', 'forcemerge', '')
2805 # report any conflicts
2805 # report any conflicts
2806 if stats and stats[3] > 0:
2806 if stats and stats[3] > 0:
2807 # write out state for --continue
2807 # write out state for --continue
2808 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2808 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2809 repo.opener.write('graftstate', ''.join(nodelines))
2809 repo.opener.write('graftstate', ''.join(nodelines))
2810 raise util.Abort(
2810 raise util.Abort(
2811 _("unresolved conflicts, can't continue"),
2811 _("unresolved conflicts, can't continue"),
2812 hint=_('use hg resolve and hg graft --continue'))
2812 hint=_('use hg resolve and hg graft --continue'))
2813 else:
2813 else:
2814 cont = False
2814 cont = False
2815
2815
2816 # drop the second merge parent
2816 # drop the second merge parent
2817 repo.setparents(current.node(), nullid)
2817 repo.setparents(current.node(), nullid)
2818 repo.dirstate.write()
2818 repo.dirstate.write()
2819 # fix up dirstate for copies and renames
2819 # fix up dirstate for copies and renames
2820 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2820 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2821
2821
2822 # commit
2822 # commit
2823 source = ctx.extra().get('source')
2823 source = ctx.extra().get('source')
2824 if not source:
2824 if not source:
2825 source = ctx.hex()
2825 source = ctx.hex()
2826 extra = {'source': source}
2826 extra = {'source': source}
2827 user = ctx.user()
2827 user = ctx.user()
2828 if opts.get('user'):
2828 if opts.get('user'):
2829 user = opts['user']
2829 user = opts['user']
2830 date = ctx.date()
2830 date = ctx.date()
2831 if opts.get('date'):
2831 if opts.get('date'):
2832 date = opts['date']
2832 date = opts['date']
2833 message = ctx.description()
2833 message = ctx.description()
2834 if opts.get('log'):
2834 if opts.get('log'):
2835 message += '\n(grafted from %s)' % ctx.hex()
2835 message += '\n(grafted from %s)' % ctx.hex()
2836 node = repo.commit(text=message, user=user,
2836 node = repo.commit(text=message, user=user,
2837 date=date, extra=extra, editor=editor)
2837 date=date, extra=extra, editor=editor)
2838 if node is None:
2838 if node is None:
2839 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2839 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2840 finally:
2840 finally:
2841 wlock.release()
2841 wlock.release()
2842
2842
2843 # remove state when we complete successfully
2843 # remove state when we complete successfully
2844 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2844 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2845 util.unlinkpath(repo.join('graftstate'))
2845 util.unlinkpath(repo.join('graftstate'))
2846
2846
2847 return 0
2847 return 0
2848
2848
2849 @command('grep',
2849 @command('grep',
2850 [('0', 'print0', None, _('end fields with NUL')),
2850 [('0', 'print0', None, _('end fields with NUL')),
2851 ('', 'all', None, _('print all revisions that match')),
2851 ('', 'all', None, _('print all revisions that match')),
2852 ('a', 'text', None, _('treat all files as text')),
2852 ('a', 'text', None, _('treat all files as text')),
2853 ('f', 'follow', None,
2853 ('f', 'follow', None,
2854 _('follow changeset history,'
2854 _('follow changeset history,'
2855 ' or file history across copies and renames')),
2855 ' or file history across copies and renames')),
2856 ('i', 'ignore-case', None, _('ignore case when matching')),
2856 ('i', 'ignore-case', None, _('ignore case when matching')),
2857 ('l', 'files-with-matches', None,
2857 ('l', 'files-with-matches', None,
2858 _('print only filenames and revisions that match')),
2858 _('print only filenames and revisions that match')),
2859 ('n', 'line-number', None, _('print matching line numbers')),
2859 ('n', 'line-number', None, _('print matching line numbers')),
2860 ('r', 'rev', [],
2860 ('r', 'rev', [],
2861 _('only search files changed within revision range'), _('REV')),
2861 _('only search files changed within revision range'), _('REV')),
2862 ('u', 'user', None, _('list the author (long with -v)')),
2862 ('u', 'user', None, _('list the author (long with -v)')),
2863 ('d', 'date', None, _('list the date (short with -q)')),
2863 ('d', 'date', None, _('list the date (short with -q)')),
2864 ] + walkopts,
2864 ] + walkopts,
2865 _('[OPTION]... PATTERN [FILE]...'))
2865 _('[OPTION]... PATTERN [FILE]...'))
2866 def grep(ui, repo, pattern, *pats, **opts):
2866 def grep(ui, repo, pattern, *pats, **opts):
2867 """search for a pattern in specified files and revisions
2867 """search for a pattern in specified files and revisions
2868
2868
2869 Search revisions of files for a regular expression.
2869 Search revisions of files for a regular expression.
2870
2870
2871 This command behaves differently than Unix grep. It only accepts
2871 This command behaves differently than Unix grep. It only accepts
2872 Python/Perl regexps. It searches repository history, not the
2872 Python/Perl regexps. It searches repository history, not the
2873 working directory. It always prints the revision number in which a
2873 working directory. It always prints the revision number in which a
2874 match appears.
2874 match appears.
2875
2875
2876 By default, grep only prints output for the first revision of a
2876 By default, grep only prints output for the first revision of a
2877 file in which it finds a match. To get it to print every revision
2877 file in which it finds a match. To get it to print every revision
2878 that contains a change in match status ("-" for a match that
2878 that contains a change in match status ("-" for a match that
2879 becomes a non-match, or "+" for a non-match that becomes a match),
2879 becomes a non-match, or "+" for a non-match that becomes a match),
2880 use the --all flag.
2880 use the --all flag.
2881
2881
2882 Returns 0 if a match is found, 1 otherwise.
2882 Returns 0 if a match is found, 1 otherwise.
2883 """
2883 """
2884 reflags = re.M
2884 reflags = re.M
2885 if opts.get('ignore_case'):
2885 if opts.get('ignore_case'):
2886 reflags |= re.I
2886 reflags |= re.I
2887 try:
2887 try:
2888 regexp = re.compile(pattern, reflags)
2888 regexp = re.compile(pattern, reflags)
2889 except re.error, inst:
2889 except re.error, inst:
2890 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2890 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2891 return 1
2891 return 1
2892 sep, eol = ':', '\n'
2892 sep, eol = ':', '\n'
2893 if opts.get('print0'):
2893 if opts.get('print0'):
2894 sep = eol = '\0'
2894 sep = eol = '\0'
2895
2895
2896 getfile = util.lrucachefunc(repo.file)
2896 getfile = util.lrucachefunc(repo.file)
2897
2897
2898 def matchlines(body):
2898 def matchlines(body):
2899 begin = 0
2899 begin = 0
2900 linenum = 0
2900 linenum = 0
2901 while True:
2901 while True:
2902 match = regexp.search(body, begin)
2902 match = regexp.search(body, begin)
2903 if not match:
2903 if not match:
2904 break
2904 break
2905 mstart, mend = match.span()
2905 mstart, mend = match.span()
2906 linenum += body.count('\n', begin, mstart) + 1
2906 linenum += body.count('\n', begin, mstart) + 1
2907 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2907 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2908 begin = body.find('\n', mend) + 1 or len(body) + 1
2908 begin = body.find('\n', mend) + 1 or len(body) + 1
2909 lend = begin - 1
2909 lend = begin - 1
2910 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2910 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2911
2911
2912 class linestate(object):
2912 class linestate(object):
2913 def __init__(self, line, linenum, colstart, colend):
2913 def __init__(self, line, linenum, colstart, colend):
2914 self.line = line
2914 self.line = line
2915 self.linenum = linenum
2915 self.linenum = linenum
2916 self.colstart = colstart
2916 self.colstart = colstart
2917 self.colend = colend
2917 self.colend = colend
2918
2918
2919 def __hash__(self):
2919 def __hash__(self):
2920 return hash((self.linenum, self.line))
2920 return hash((self.linenum, self.line))
2921
2921
2922 def __eq__(self, other):
2922 def __eq__(self, other):
2923 return self.line == other.line
2923 return self.line == other.line
2924
2924
2925 matches = {}
2925 matches = {}
2926 copies = {}
2926 copies = {}
2927 def grepbody(fn, rev, body):
2927 def grepbody(fn, rev, body):
2928 matches[rev].setdefault(fn, [])
2928 matches[rev].setdefault(fn, [])
2929 m = matches[rev][fn]
2929 m = matches[rev][fn]
2930 for lnum, cstart, cend, line in matchlines(body):
2930 for lnum, cstart, cend, line in matchlines(body):
2931 s = linestate(line, lnum, cstart, cend)
2931 s = linestate(line, lnum, cstart, cend)
2932 m.append(s)
2932 m.append(s)
2933
2933
2934 def difflinestates(a, b):
2934 def difflinestates(a, b):
2935 sm = difflib.SequenceMatcher(None, a, b)
2935 sm = difflib.SequenceMatcher(None, a, b)
2936 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2936 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2937 if tag == 'insert':
2937 if tag == 'insert':
2938 for i in xrange(blo, bhi):
2938 for i in xrange(blo, bhi):
2939 yield ('+', b[i])
2939 yield ('+', b[i])
2940 elif tag == 'delete':
2940 elif tag == 'delete':
2941 for i in xrange(alo, ahi):
2941 for i in xrange(alo, ahi):
2942 yield ('-', a[i])
2942 yield ('-', a[i])
2943 elif tag == 'replace':
2943 elif tag == 'replace':
2944 for i in xrange(alo, ahi):
2944 for i in xrange(alo, ahi):
2945 yield ('-', a[i])
2945 yield ('-', a[i])
2946 for i in xrange(blo, bhi):
2946 for i in xrange(blo, bhi):
2947 yield ('+', b[i])
2947 yield ('+', b[i])
2948
2948
2949 def display(fn, ctx, pstates, states):
2949 def display(fn, ctx, pstates, states):
2950 rev = ctx.rev()
2950 rev = ctx.rev()
2951 datefunc = ui.quiet and util.shortdate or util.datestr
2951 datefunc = ui.quiet and util.shortdate or util.datestr
2952 found = False
2952 found = False
2953 filerevmatches = {}
2953 filerevmatches = {}
2954 def binary():
2954 def binary():
2955 flog = getfile(fn)
2955 flog = getfile(fn)
2956 return util.binary(flog.read(ctx.filenode(fn)))
2956 return util.binary(flog.read(ctx.filenode(fn)))
2957
2957
2958 if opts.get('all'):
2958 if opts.get('all'):
2959 iter = difflinestates(pstates, states)
2959 iter = difflinestates(pstates, states)
2960 else:
2960 else:
2961 iter = [('', l) for l in states]
2961 iter = [('', l) for l in states]
2962 for change, l in iter:
2962 for change, l in iter:
2963 cols = [fn, str(rev)]
2963 cols = [fn, str(rev)]
2964 before, match, after = None, None, None
2964 before, match, after = None, None, None
2965 if opts.get('line_number'):
2965 if opts.get('line_number'):
2966 cols.append(str(l.linenum))
2966 cols.append(str(l.linenum))
2967 if opts.get('all'):
2967 if opts.get('all'):
2968 cols.append(change)
2968 cols.append(change)
2969 if opts.get('user'):
2969 if opts.get('user'):
2970 cols.append(ui.shortuser(ctx.user()))
2970 cols.append(ui.shortuser(ctx.user()))
2971 if opts.get('date'):
2971 if opts.get('date'):
2972 cols.append(datefunc(ctx.date()))
2972 cols.append(datefunc(ctx.date()))
2973 if opts.get('files_with_matches'):
2973 if opts.get('files_with_matches'):
2974 c = (fn, rev)
2974 c = (fn, rev)
2975 if c in filerevmatches:
2975 if c in filerevmatches:
2976 continue
2976 continue
2977 filerevmatches[c] = 1
2977 filerevmatches[c] = 1
2978 else:
2978 else:
2979 before = l.line[:l.colstart]
2979 before = l.line[:l.colstart]
2980 match = l.line[l.colstart:l.colend]
2980 match = l.line[l.colstart:l.colend]
2981 after = l.line[l.colend:]
2981 after = l.line[l.colend:]
2982 ui.write(sep.join(cols))
2982 ui.write(sep.join(cols))
2983 if before is not None:
2983 if before is not None:
2984 if not opts.get('text') and binary():
2984 if not opts.get('text') and binary():
2985 ui.write(sep + " Binary file matches")
2985 ui.write(sep + " Binary file matches")
2986 else:
2986 else:
2987 ui.write(sep + before)
2987 ui.write(sep + before)
2988 ui.write(match, label='grep.match')
2988 ui.write(match, label='grep.match')
2989 ui.write(after)
2989 ui.write(after)
2990 ui.write(eol)
2990 ui.write(eol)
2991 found = True
2991 found = True
2992 return found
2992 return found
2993
2993
2994 skip = {}
2994 skip = {}
2995 revfiles = {}
2995 revfiles = {}
2996 matchfn = scmutil.match(repo[None], pats, opts)
2996 matchfn = scmutil.match(repo[None], pats, opts)
2997 found = False
2997 found = False
2998 follow = opts.get('follow')
2998 follow = opts.get('follow')
2999
2999
3000 def prep(ctx, fns):
3000 def prep(ctx, fns):
3001 rev = ctx.rev()
3001 rev = ctx.rev()
3002 pctx = ctx.p1()
3002 pctx = ctx.p1()
3003 parent = pctx.rev()
3003 parent = pctx.rev()
3004 matches.setdefault(rev, {})
3004 matches.setdefault(rev, {})
3005 matches.setdefault(parent, {})
3005 matches.setdefault(parent, {})
3006 files = revfiles.setdefault(rev, [])
3006 files = revfiles.setdefault(rev, [])
3007 for fn in fns:
3007 for fn in fns:
3008 flog = getfile(fn)
3008 flog = getfile(fn)
3009 try:
3009 try:
3010 fnode = ctx.filenode(fn)
3010 fnode = ctx.filenode(fn)
3011 except error.LookupError:
3011 except error.LookupError:
3012 continue
3012 continue
3013
3013
3014 copied = flog.renamed(fnode)
3014 copied = flog.renamed(fnode)
3015 copy = follow and copied and copied[0]
3015 copy = follow and copied and copied[0]
3016 if copy:
3016 if copy:
3017 copies.setdefault(rev, {})[fn] = copy
3017 copies.setdefault(rev, {})[fn] = copy
3018 if fn in skip:
3018 if fn in skip:
3019 if copy:
3019 if copy:
3020 skip[copy] = True
3020 skip[copy] = True
3021 continue
3021 continue
3022 files.append(fn)
3022 files.append(fn)
3023
3023
3024 if fn not in matches[rev]:
3024 if fn not in matches[rev]:
3025 grepbody(fn, rev, flog.read(fnode))
3025 grepbody(fn, rev, flog.read(fnode))
3026
3026
3027 pfn = copy or fn
3027 pfn = copy or fn
3028 if pfn not in matches[parent]:
3028 if pfn not in matches[parent]:
3029 try:
3029 try:
3030 fnode = pctx.filenode(pfn)
3030 fnode = pctx.filenode(pfn)
3031 grepbody(pfn, parent, flog.read(fnode))
3031 grepbody(pfn, parent, flog.read(fnode))
3032 except error.LookupError:
3032 except error.LookupError:
3033 pass
3033 pass
3034
3034
3035 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3035 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3036 rev = ctx.rev()
3036 rev = ctx.rev()
3037 parent = ctx.p1().rev()
3037 parent = ctx.p1().rev()
3038 for fn in sorted(revfiles.get(rev, [])):
3038 for fn in sorted(revfiles.get(rev, [])):
3039 states = matches[rev][fn]
3039 states = matches[rev][fn]
3040 copy = copies.get(rev, {}).get(fn)
3040 copy = copies.get(rev, {}).get(fn)
3041 if fn in skip:
3041 if fn in skip:
3042 if copy:
3042 if copy:
3043 skip[copy] = True
3043 skip[copy] = True
3044 continue
3044 continue
3045 pstates = matches.get(parent, {}).get(copy or fn, [])
3045 pstates = matches.get(parent, {}).get(copy or fn, [])
3046 if pstates or states:
3046 if pstates or states:
3047 r = display(fn, ctx, pstates, states)
3047 r = display(fn, ctx, pstates, states)
3048 found = found or r
3048 found = found or r
3049 if r and not opts.get('all'):
3049 if r and not opts.get('all'):
3050 skip[fn] = True
3050 skip[fn] = True
3051 if copy:
3051 if copy:
3052 skip[copy] = True
3052 skip[copy] = True
3053 del matches[rev]
3053 del matches[rev]
3054 del revfiles[rev]
3054 del revfiles[rev]
3055
3055
3056 return not found
3056 return not found
3057
3057
3058 @command('heads',
3058 @command('heads',
3059 [('r', 'rev', '',
3059 [('r', 'rev', '',
3060 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3060 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3061 ('t', 'topo', False, _('show topological heads only')),
3061 ('t', 'topo', False, _('show topological heads only')),
3062 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3062 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3063 ('c', 'closed', False, _('show normal and closed branch heads')),
3063 ('c', 'closed', False, _('show normal and closed branch heads')),
3064 ] + templateopts,
3064 ] + templateopts,
3065 _('[-ct] [-r STARTREV] [REV]...'))
3065 _('[-ct] [-r STARTREV] [REV]...'))
3066 def heads(ui, repo, *branchrevs, **opts):
3066 def heads(ui, repo, *branchrevs, **opts):
3067 """show current repository heads or show branch heads
3067 """show current repository heads or show branch heads
3068
3068
3069 With no arguments, show all repository branch heads.
3069 With no arguments, show all repository branch heads.
3070
3070
3071 Repository "heads" are changesets with no child changesets. They are
3071 Repository "heads" are changesets with no child changesets. They are
3072 where development generally takes place and are the usual targets
3072 where development generally takes place and are the usual targets
3073 for update and merge operations. Branch heads are changesets that have
3073 for update and merge operations. Branch heads are changesets that have
3074 no child changeset on the same branch.
3074 no child changeset on the same branch.
3075
3075
3076 If one or more REVs are given, only branch heads on the branches
3076 If one or more REVs are given, only branch heads on the branches
3077 associated with the specified changesets are shown. This means
3077 associated with the specified changesets are shown. This means
3078 that you can use :hg:`heads foo` to see the heads on a branch
3078 that you can use :hg:`heads foo` to see the heads on a branch
3079 named ``foo``.
3079 named ``foo``.
3080
3080
3081 If -c/--closed is specified, also show branch heads marked closed
3081 If -c/--closed is specified, also show branch heads marked closed
3082 (see :hg:`commit --close-branch`).
3082 (see :hg:`commit --close-branch`).
3083
3083
3084 If STARTREV is specified, only those heads that are descendants of
3084 If STARTREV is specified, only those heads that are descendants of
3085 STARTREV will be displayed.
3085 STARTREV will be displayed.
3086
3086
3087 If -t/--topo is specified, named branch mechanics will be ignored and only
3087 If -t/--topo is specified, named branch mechanics will be ignored and only
3088 changesets without children will be shown.
3088 changesets without children will be shown.
3089
3089
3090 Returns 0 if matching heads are found, 1 if not.
3090 Returns 0 if matching heads are found, 1 if not.
3091 """
3091 """
3092
3092
3093 start = None
3093 start = None
3094 if 'rev' in opts:
3094 if 'rev' in opts:
3095 start = scmutil.revsingle(repo, opts['rev'], None).node()
3095 start = scmutil.revsingle(repo, opts['rev'], None).node()
3096
3096
3097 if opts.get('topo'):
3097 if opts.get('topo'):
3098 heads = [repo[h] for h in repo.heads(start)]
3098 heads = [repo[h] for h in repo.heads(start)]
3099 else:
3099 else:
3100 heads = []
3100 heads = []
3101 for branch in repo.branchmap():
3101 for branch in repo.branchmap():
3102 heads += repo.branchheads(branch, start, opts.get('closed'))
3102 heads += repo.branchheads(branch, start, opts.get('closed'))
3103 heads = [repo[h] for h in heads]
3103 heads = [repo[h] for h in heads]
3104
3104
3105 if branchrevs:
3105 if branchrevs:
3106 branches = set(repo[br].branch() for br in branchrevs)
3106 branches = set(repo[br].branch() for br in branchrevs)
3107 heads = [h for h in heads if h.branch() in branches]
3107 heads = [h for h in heads if h.branch() in branches]
3108
3108
3109 if opts.get('active') and branchrevs:
3109 if opts.get('active') and branchrevs:
3110 dagheads = repo.heads(start)
3110 dagheads = repo.heads(start)
3111 heads = [h for h in heads if h.node() in dagheads]
3111 heads = [h for h in heads if h.node() in dagheads]
3112
3112
3113 if branchrevs:
3113 if branchrevs:
3114 haveheads = set(h.branch() for h in heads)
3114 haveheads = set(h.branch() for h in heads)
3115 if branches - haveheads:
3115 if branches - haveheads:
3116 headless = ', '.join(b for b in branches - haveheads)
3116 headless = ', '.join(b for b in branches - haveheads)
3117 msg = _('no open branch heads found on branches %s')
3117 msg = _('no open branch heads found on branches %s')
3118 if opts.get('rev'):
3118 if opts.get('rev'):
3119 msg += _(' (started at %s)') % opts['rev']
3119 msg += _(' (started at %s)') % opts['rev']
3120 ui.warn((msg + '\n') % headless)
3120 ui.warn((msg + '\n') % headless)
3121
3121
3122 if not heads:
3122 if not heads:
3123 return 1
3123 return 1
3124
3124
3125 heads = sorted(heads, key=lambda x: -x.rev())
3125 heads = sorted(heads, key=lambda x: -x.rev())
3126 displayer = cmdutil.show_changeset(ui, repo, opts)
3126 displayer = cmdutil.show_changeset(ui, repo, opts)
3127 for ctx in heads:
3127 for ctx in heads:
3128 displayer.show(ctx)
3128 displayer.show(ctx)
3129 displayer.close()
3129 displayer.close()
3130
3130
3131 @command('help',
3131 @command('help',
3132 [('e', 'extension', None, _('show only help for extensions')),
3132 [('e', 'extension', None, _('show only help for extensions')),
3133 ('c', 'command', None, _('show only help for commands')),
3133 ('c', 'command', None, _('show only help for commands')),
3134 ('k', 'keyword', '', _('show topics matching keyword')),
3134 ('k', 'keyword', '', _('show topics matching keyword')),
3135 ],
3135 ],
3136 _('[-ec] [TOPIC]'))
3136 _('[-ec] [TOPIC]'))
3137 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3137 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3138 """show help for a given topic or a help overview
3138 """show help for a given topic or a help overview
3139
3139
3140 With no arguments, print a list of commands with short help messages.
3140 With no arguments, print a list of commands with short help messages.
3141
3141
3142 Given a topic, extension, or command name, print help for that
3142 Given a topic, extension, or command name, print help for that
3143 topic.
3143 topic.
3144
3144
3145 Returns 0 if successful.
3145 Returns 0 if successful.
3146 """
3146 """
3147
3147
3148 textwidth = min(ui.termwidth(), 80) - 2
3148 textwidth = min(ui.termwidth(), 80) - 2
3149
3149
3150 def helpcmd(name):
3150 def helpcmd(name):
3151 try:
3151 try:
3152 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3152 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3153 except error.AmbiguousCommand, inst:
3153 except error.AmbiguousCommand, inst:
3154 # py3k fix: except vars can't be used outside the scope of the
3154 # py3k fix: except vars can't be used outside the scope of the
3155 # except block, nor can be used inside a lambda. python issue4617
3155 # except block, nor can be used inside a lambda. python issue4617
3156 prefix = inst.args[0]
3156 prefix = inst.args[0]
3157 select = lambda c: c.lstrip('^').startswith(prefix)
3157 select = lambda c: c.lstrip('^').startswith(prefix)
3158 rst = helplist(select)
3158 rst = helplist(select)
3159 return rst
3159 return rst
3160
3160
3161 rst = []
3161 rst = []
3162
3162
3163 # check if it's an invalid alias and display its error if it is
3163 # check if it's an invalid alias and display its error if it is
3164 if getattr(entry[0], 'badalias', False):
3164 if getattr(entry[0], 'badalias', False):
3165 if not unknowncmd:
3165 if not unknowncmd:
3166 ui.pushbuffer()
3166 ui.pushbuffer()
3167 entry[0](ui)
3167 entry[0](ui)
3168 rst.append(ui.popbuffer())
3168 rst.append(ui.popbuffer())
3169 return rst
3169 return rst
3170
3170
3171 # synopsis
3171 # synopsis
3172 if len(entry) > 2:
3172 if len(entry) > 2:
3173 if entry[2].startswith('hg'):
3173 if entry[2].startswith('hg'):
3174 rst.append("%s\n" % entry[2])
3174 rst.append("%s\n" % entry[2])
3175 else:
3175 else:
3176 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3176 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3177 else:
3177 else:
3178 rst.append('hg %s\n' % aliases[0])
3178 rst.append('hg %s\n' % aliases[0])
3179 # aliases
3179 # aliases
3180 if full and not ui.quiet and len(aliases) > 1:
3180 if full and not ui.quiet and len(aliases) > 1:
3181 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3181 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3182 rst.append('\n')
3182 rst.append('\n')
3183
3183
3184 # description
3184 # description
3185 doc = gettext(entry[0].__doc__)
3185 doc = gettext(entry[0].__doc__)
3186 if not doc:
3186 if not doc:
3187 doc = _("(no help text available)")
3187 doc = _("(no help text available)")
3188 if util.safehasattr(entry[0], 'definition'): # aliased command
3188 if util.safehasattr(entry[0], 'definition'): # aliased command
3189 if entry[0].definition.startswith('!'): # shell alias
3189 if entry[0].definition.startswith('!'): # shell alias
3190 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3190 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3191 else:
3191 else:
3192 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3192 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3193 doc = doc.splitlines(True)
3193 doc = doc.splitlines(True)
3194 if ui.quiet or not full:
3194 if ui.quiet or not full:
3195 rst.append(doc[0])
3195 rst.append(doc[0])
3196 else:
3196 else:
3197 rst.extend(doc)
3197 rst.extend(doc)
3198 rst.append('\n')
3198 rst.append('\n')
3199
3199
3200 # check if this command shadows a non-trivial (multi-line)
3200 # check if this command shadows a non-trivial (multi-line)
3201 # extension help text
3201 # extension help text
3202 try:
3202 try:
3203 mod = extensions.find(name)
3203 mod = extensions.find(name)
3204 doc = gettext(mod.__doc__) or ''
3204 doc = gettext(mod.__doc__) or ''
3205 if '\n' in doc.strip():
3205 if '\n' in doc.strip():
3206 msg = _('use "hg help -e %s" to show help for '
3206 msg = _('use "hg help -e %s" to show help for '
3207 'the %s extension') % (name, name)
3207 'the %s extension') % (name, name)
3208 rst.append('\n%s\n' % msg)
3208 rst.append('\n%s\n' % msg)
3209 except KeyError:
3209 except KeyError:
3210 pass
3210 pass
3211
3211
3212 # options
3212 # options
3213 if not ui.quiet and entry[1]:
3213 if not ui.quiet and entry[1]:
3214 rst.append('\n%s\n\n' % _("options:"))
3214 rst.append('\n%s\n\n' % _("options:"))
3215 rst.append(help.optrst(entry[1], ui.verbose))
3215 rst.append(help.optrst(entry[1], ui.verbose))
3216
3216
3217 if ui.verbose:
3217 if ui.verbose:
3218 rst.append('\n%s\n\n' % _("global options:"))
3218 rst.append('\n%s\n\n' % _("global options:"))
3219 rst.append(help.optrst(globalopts, ui.verbose))
3219 rst.append(help.optrst(globalopts, ui.verbose))
3220
3220
3221 if not ui.verbose:
3221 if not ui.verbose:
3222 if not full:
3222 if not full:
3223 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3223 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3224 % name)
3224 % name)
3225 elif not ui.quiet:
3225 elif not ui.quiet:
3226 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3226 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3227 % name)
3227 % name)
3228 return rst
3228 return rst
3229
3229
3230
3230
3231 def helplist(select=None):
3231 def helplist(select=None):
3232 # list of commands
3232 # list of commands
3233 if name == "shortlist":
3233 if name == "shortlist":
3234 header = _('basic commands:\n\n')
3234 header = _('basic commands:\n\n')
3235 else:
3235 else:
3236 header = _('list of commands:\n\n')
3236 header = _('list of commands:\n\n')
3237
3237
3238 h = {}
3238 h = {}
3239 cmds = {}
3239 cmds = {}
3240 for c, e in table.iteritems():
3240 for c, e in table.iteritems():
3241 f = c.split("|", 1)[0]
3241 f = c.split("|", 1)[0]
3242 if select and not select(f):
3242 if select and not select(f):
3243 continue
3243 continue
3244 if (not select and name != 'shortlist' and
3244 if (not select and name != 'shortlist' and
3245 e[0].__module__ != __name__):
3245 e[0].__module__ != __name__):
3246 continue
3246 continue
3247 if name == "shortlist" and not f.startswith("^"):
3247 if name == "shortlist" and not f.startswith("^"):
3248 continue
3248 continue
3249 f = f.lstrip("^")
3249 f = f.lstrip("^")
3250 if not ui.debugflag and f.startswith("debug"):
3250 if not ui.debugflag and f.startswith("debug"):
3251 continue
3251 continue
3252 doc = e[0].__doc__
3252 doc = e[0].__doc__
3253 if doc and 'DEPRECATED' in doc and not ui.verbose:
3253 if doc and 'DEPRECATED' in doc and not ui.verbose:
3254 continue
3254 continue
3255 doc = gettext(doc)
3255 doc = gettext(doc)
3256 if not doc:
3256 if not doc:
3257 doc = _("(no help text available)")
3257 doc = _("(no help text available)")
3258 h[f] = doc.splitlines()[0].rstrip()
3258 h[f] = doc.splitlines()[0].rstrip()
3259 cmds[f] = c.lstrip("^")
3259 cmds[f] = c.lstrip("^")
3260
3260
3261 rst = []
3261 rst = []
3262 if not h:
3262 if not h:
3263 if not ui.quiet:
3263 if not ui.quiet:
3264 rst.append(_('no commands defined\n'))
3264 rst.append(_('no commands defined\n'))
3265 return rst
3265 return rst
3266
3266
3267 if not ui.quiet:
3267 if not ui.quiet:
3268 rst.append(header)
3268 rst.append(header)
3269 fns = sorted(h)
3269 fns = sorted(h)
3270 for f in fns:
3270 for f in fns:
3271 if ui.verbose:
3271 if ui.verbose:
3272 commands = cmds[f].replace("|",", ")
3272 commands = cmds[f].replace("|",", ")
3273 rst.append(" :%s: %s\n" % (commands, h[f]))
3273 rst.append(" :%s: %s\n" % (commands, h[f]))
3274 else:
3274 else:
3275 rst.append(' :%s: %s\n' % (f, h[f]))
3275 rst.append(' :%s: %s\n' % (f, h[f]))
3276
3276
3277 if not name:
3277 if not name:
3278 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3278 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3279 if exts:
3279 if exts:
3280 rst.append('\n')
3280 rst.append('\n')
3281 rst.extend(exts)
3281 rst.extend(exts)
3282
3282
3283 rst.append(_("\nadditional help topics:\n\n"))
3283 rst.append(_("\nadditional help topics:\n\n"))
3284 topics = []
3284 topics = []
3285 for names, header, doc in help.helptable:
3285 for names, header, doc in help.helptable:
3286 topics.append((sorted(names, key=len, reverse=True)[0], header))
3286 topics.append((sorted(names, key=len, reverse=True)[0], header))
3287 for t, desc in topics:
3287 for t, desc in topics:
3288 rst.append(" :%s: %s\n" % (t, desc))
3288 rst.append(" :%s: %s\n" % (t, desc))
3289
3289
3290 optlist = []
3290 optlist = []
3291 if not ui.quiet:
3291 if not ui.quiet:
3292 if ui.verbose:
3292 if ui.verbose:
3293 optlist.append((_("global options:"), globalopts))
3293 optlist.append((_("global options:"), globalopts))
3294 if name == 'shortlist':
3294 if name == 'shortlist':
3295 optlist.append((_('use "hg help" for the full list '
3295 optlist.append((_('use "hg help" for the full list '
3296 'of commands'), ()))
3296 'of commands'), ()))
3297 else:
3297 else:
3298 if name == 'shortlist':
3298 if name == 'shortlist':
3299 msg = _('use "hg help" for the full list of commands '
3299 msg = _('use "hg help" for the full list of commands '
3300 'or "hg -v" for details')
3300 'or "hg -v" for details')
3301 elif name and not full:
3301 elif name and not full:
3302 msg = _('use "hg help %s" to show the full help '
3302 msg = _('use "hg help %s" to show the full help '
3303 'text') % name
3303 'text') % name
3304 else:
3304 else:
3305 msg = _('use "hg -v help%s" to show builtin aliases and '
3305 msg = _('use "hg -v help%s" to show builtin aliases and '
3306 'global options') % (name and " " + name or "")
3306 'global options') % (name and " " + name or "")
3307 optlist.append((msg, ()))
3307 optlist.append((msg, ()))
3308
3308
3309 if optlist:
3309 if optlist:
3310 for title, options in optlist:
3310 for title, options in optlist:
3311 rst.append('\n%s\n' % title)
3311 rst.append('\n%s\n' % title)
3312 if options:
3312 if options:
3313 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3313 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3314 return rst
3314 return rst
3315
3315
3316 def helptopic(name):
3316 def helptopic(name):
3317 for names, header, doc in help.helptable:
3317 for names, header, doc in help.helptable:
3318 if name in names:
3318 if name in names:
3319 break
3319 break
3320 else:
3320 else:
3321 raise error.UnknownCommand(name)
3321 raise error.UnknownCommand(name)
3322
3322
3323 rst = ["%s\n\n" % header]
3323 rst = ["%s\n\n" % header]
3324 # description
3324 # description
3325 if not doc:
3325 if not doc:
3326 rst.append(" %s\n" % _("(no help text available)"))
3326 rst.append(" %s\n" % _("(no help text available)"))
3327 if util.safehasattr(doc, '__call__'):
3327 if util.safehasattr(doc, '__call__'):
3328 rst += [" %s\n" % l for l in doc().splitlines()]
3328 rst += [" %s\n" % l for l in doc().splitlines()]
3329
3329
3330 try:
3330 try:
3331 cmdutil.findcmd(name, table)
3331 cmdutil.findcmd(name, table)
3332 rst.append(_('\nuse "hg help -c %s" to see help for '
3332 rst.append(_('\nuse "hg help -c %s" to see help for '
3333 'the %s command\n') % (name, name))
3333 'the %s command\n') % (name, name))
3334 except error.UnknownCommand:
3334 except error.UnknownCommand:
3335 pass
3335 pass
3336 return rst
3336 return rst
3337
3337
3338 def helpext(name):
3338 def helpext(name):
3339 try:
3339 try:
3340 mod = extensions.find(name)
3340 mod = extensions.find(name)
3341 doc = gettext(mod.__doc__) or _('no help text available')
3341 doc = gettext(mod.__doc__) or _('no help text available')
3342 except KeyError:
3342 except KeyError:
3343 mod = None
3343 mod = None
3344 doc = extensions.disabledext(name)
3344 doc = extensions.disabledext(name)
3345 if not doc:
3345 if not doc:
3346 raise error.UnknownCommand(name)
3346 raise error.UnknownCommand(name)
3347
3347
3348 if '\n' not in doc:
3348 if '\n' not in doc:
3349 head, tail = doc, ""
3349 head, tail = doc, ""
3350 else:
3350 else:
3351 head, tail = doc.split('\n', 1)
3351 head, tail = doc.split('\n', 1)
3352 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3352 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3353 if tail:
3353 if tail:
3354 rst.extend(tail.splitlines(True))
3354 rst.extend(tail.splitlines(True))
3355 rst.append('\n')
3355 rst.append('\n')
3356
3356
3357 if mod:
3357 if mod:
3358 try:
3358 try:
3359 ct = mod.cmdtable
3359 ct = mod.cmdtable
3360 except AttributeError:
3360 except AttributeError:
3361 ct = {}
3361 ct = {}
3362 modcmds = set([c.split('|', 1)[0] for c in ct])
3362 modcmds = set([c.split('|', 1)[0] for c in ct])
3363 rst.extend(helplist(modcmds.__contains__))
3363 rst.extend(helplist(modcmds.__contains__))
3364 else:
3364 else:
3365 rst.append(_('use "hg help extensions" for information on enabling '
3365 rst.append(_('use "hg help extensions" for information on enabling '
3366 'extensions\n'))
3366 'extensions\n'))
3367 return rst
3367 return rst
3368
3368
3369 def helpextcmd(name):
3369 def helpextcmd(name):
3370 cmd, ext, mod = extensions.disabledcmd(ui, name,
3370 cmd, ext, mod = extensions.disabledcmd(ui, name,
3371 ui.configbool('ui', 'strict'))
3371 ui.configbool('ui', 'strict'))
3372 doc = gettext(mod.__doc__).splitlines()[0]
3372 doc = gettext(mod.__doc__).splitlines()[0]
3373
3373
3374 rst = help.listexts(_("'%s' is provided by the following "
3374 rst = help.listexts(_("'%s' is provided by the following "
3375 "extension:") % cmd, {ext: doc}, indent=4)
3375 "extension:") % cmd, {ext: doc}, indent=4)
3376 rst.append('\n')
3376 rst.append('\n')
3377 rst.append(_('use "hg help extensions" for information on enabling '
3377 rst.append(_('use "hg help extensions" for information on enabling '
3378 'extensions\n'))
3378 'extensions\n'))
3379 return rst
3379 return rst
3380
3380
3381
3381
3382 rst = []
3382 rst = []
3383 kw = opts.get('keyword')
3383 kw = opts.get('keyword')
3384 if kw:
3384 if kw:
3385 matches = help.topicmatch(kw)
3385 matches = help.topicmatch(kw)
3386 for t, title in (('topics', _('Topics')),
3386 for t, title in (('topics', _('Topics')),
3387 ('commands', _('Commands')),
3387 ('commands', _('Commands')),
3388 ('extensions', _('Extensions')),
3388 ('extensions', _('Extensions')),
3389 ('extensioncommands', _('Extension Commands'))):
3389 ('extensioncommands', _('Extension Commands'))):
3390 if matches[t]:
3390 if matches[t]:
3391 rst.append('%s:\n\n' % title)
3391 rst.append('%s:\n\n' % title)
3392 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3392 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3393 rst.append('\n')
3393 rst.append('\n')
3394 elif name and name != 'shortlist':
3394 elif name and name != 'shortlist':
3395 i = None
3395 i = None
3396 if unknowncmd:
3396 if unknowncmd:
3397 queries = (helpextcmd,)
3397 queries = (helpextcmd,)
3398 elif opts.get('extension'):
3398 elif opts.get('extension'):
3399 queries = (helpext,)
3399 queries = (helpext,)
3400 elif opts.get('command'):
3400 elif opts.get('command'):
3401 queries = (helpcmd,)
3401 queries = (helpcmd,)
3402 else:
3402 else:
3403 queries = (helptopic, helpcmd, helpext, helpextcmd)
3403 queries = (helptopic, helpcmd, helpext, helpextcmd)
3404 for f in queries:
3404 for f in queries:
3405 try:
3405 try:
3406 rst = f(name)
3406 rst = f(name)
3407 i = None
3407 i = None
3408 break
3408 break
3409 except error.UnknownCommand, inst:
3409 except error.UnknownCommand, inst:
3410 i = inst
3410 i = inst
3411 if i:
3411 if i:
3412 raise i
3412 raise i
3413 else:
3413 else:
3414 # program name
3414 # program name
3415 if not ui.quiet:
3415 if not ui.quiet:
3416 rst = [_("Mercurial Distributed SCM\n"), '\n']
3416 rst = [_("Mercurial Distributed SCM\n"), '\n']
3417 rst.extend(helplist())
3417 rst.extend(helplist())
3418
3418
3419 keep = ui.verbose and ['verbose'] or []
3419 keep = ui.verbose and ['verbose'] or []
3420 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3420 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3421 ui.write(formatted)
3421 ui.write(formatted)
3422
3422
3423
3423
3424 @command('identify|id',
3424 @command('identify|id',
3425 [('r', 'rev', '',
3425 [('r', 'rev', '',
3426 _('identify the specified revision'), _('REV')),
3426 _('identify the specified revision'), _('REV')),
3427 ('n', 'num', None, _('show local revision number')),
3427 ('n', 'num', None, _('show local revision number')),
3428 ('i', 'id', None, _('show global revision id')),
3428 ('i', 'id', None, _('show global revision id')),
3429 ('b', 'branch', None, _('show branch')),
3429 ('b', 'branch', None, _('show branch')),
3430 ('t', 'tags', None, _('show tags')),
3430 ('t', 'tags', None, _('show tags')),
3431 ('B', 'bookmarks', None, _('show bookmarks')),
3431 ('B', 'bookmarks', None, _('show bookmarks')),
3432 ] + remoteopts,
3432 ] + remoteopts,
3433 _('[-nibtB] [-r REV] [SOURCE]'))
3433 _('[-nibtB] [-r REV] [SOURCE]'))
3434 def identify(ui, repo, source=None, rev=None,
3434 def identify(ui, repo, source=None, rev=None,
3435 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3435 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3436 """identify the working copy or specified revision
3436 """identify the working copy or specified revision
3437
3437
3438 Print a summary identifying the repository state at REV using one or
3438 Print a summary identifying the repository state at REV using one or
3439 two parent hash identifiers, followed by a "+" if the working
3439 two parent hash identifiers, followed by a "+" if the working
3440 directory has uncommitted changes, the branch name (if not default),
3440 directory has uncommitted changes, the branch name (if not default),
3441 a list of tags, and a list of bookmarks.
3441 a list of tags, and a list of bookmarks.
3442
3442
3443 When REV is not given, print a summary of the current state of the
3443 When REV is not given, print a summary of the current state of the
3444 repository.
3444 repository.
3445
3445
3446 Specifying a path to a repository root or Mercurial bundle will
3446 Specifying a path to a repository root or Mercurial bundle will
3447 cause lookup to operate on that repository/bundle.
3447 cause lookup to operate on that repository/bundle.
3448
3448
3449 .. container:: verbose
3449 .. container:: verbose
3450
3450
3451 Examples:
3451 Examples:
3452
3452
3453 - generate a build identifier for the working directory::
3453 - generate a build identifier for the working directory::
3454
3454
3455 hg id --id > build-id.dat
3455 hg id --id > build-id.dat
3456
3456
3457 - find the revision corresponding to a tag::
3457 - find the revision corresponding to a tag::
3458
3458
3459 hg id -n -r 1.3
3459 hg id -n -r 1.3
3460
3460
3461 - check the most recent revision of a remote repository::
3461 - check the most recent revision of a remote repository::
3462
3462
3463 hg id -r tip http://selenic.com/hg/
3463 hg id -r tip http://selenic.com/hg/
3464
3464
3465 Returns 0 if successful.
3465 Returns 0 if successful.
3466 """
3466 """
3467
3467
3468 if not repo and not source:
3468 if not repo and not source:
3469 raise util.Abort(_("there is no Mercurial repository here "
3469 raise util.Abort(_("there is no Mercurial repository here "
3470 "(.hg not found)"))
3470 "(.hg not found)"))
3471
3471
3472 hexfunc = ui.debugflag and hex or short
3472 hexfunc = ui.debugflag and hex or short
3473 default = not (num or id or branch or tags or bookmarks)
3473 default = not (num or id or branch or tags or bookmarks)
3474 output = []
3474 output = []
3475 revs = []
3475 revs = []
3476
3476
3477 if source:
3477 if source:
3478 source, branches = hg.parseurl(ui.expandpath(source))
3478 source, branches = hg.parseurl(ui.expandpath(source))
3479 peer = hg.peer(ui, opts, source)
3479 peer = hg.peer(ui, opts, source)
3480 repo = peer.local()
3480 repo = peer.local()
3481 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3481 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3482
3482
3483 if not repo:
3483 if not repo:
3484 if num or branch or tags:
3484 if num or branch or tags:
3485 raise util.Abort(
3485 raise util.Abort(
3486 _("can't query remote revision number, branch, or tags"))
3486 _("can't query remote revision number, branch, or tags"))
3487 if not rev and revs:
3487 if not rev and revs:
3488 rev = revs[0]
3488 rev = revs[0]
3489 if not rev:
3489 if not rev:
3490 rev = "tip"
3490 rev = "tip"
3491
3491
3492 remoterev = peer.lookup(rev)
3492 remoterev = peer.lookup(rev)
3493 if default or id:
3493 if default or id:
3494 output = [hexfunc(remoterev)]
3494 output = [hexfunc(remoterev)]
3495
3495
3496 def getbms():
3496 def getbms():
3497 bms = []
3497 bms = []
3498
3498
3499 if 'bookmarks' in peer.listkeys('namespaces'):
3499 if 'bookmarks' in peer.listkeys('namespaces'):
3500 hexremoterev = hex(remoterev)
3500 hexremoterev = hex(remoterev)
3501 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3501 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3502 if bmr == hexremoterev]
3502 if bmr == hexremoterev]
3503
3503
3504 return bms
3504 return bms
3505
3505
3506 if bookmarks:
3506 if bookmarks:
3507 output.extend(getbms())
3507 output.extend(getbms())
3508 elif default and not ui.quiet:
3508 elif default and not ui.quiet:
3509 # multiple bookmarks for a single parent separated by '/'
3509 # multiple bookmarks for a single parent separated by '/'
3510 bm = '/'.join(getbms())
3510 bm = '/'.join(getbms())
3511 if bm:
3511 if bm:
3512 output.append(bm)
3512 output.append(bm)
3513 else:
3513 else:
3514 if not rev:
3514 if not rev:
3515 ctx = repo[None]
3515 ctx = repo[None]
3516 parents = ctx.parents()
3516 parents = ctx.parents()
3517 changed = ""
3517 changed = ""
3518 if default or id or num:
3518 if default or id or num:
3519 if (util.any(repo.status())
3519 if (util.any(repo.status())
3520 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3520 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3521 changed = '+'
3521 changed = '+'
3522 if default or id:
3522 if default or id:
3523 output = ["%s%s" %
3523 output = ["%s%s" %
3524 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3524 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3525 if num:
3525 if num:
3526 output.append("%s%s" %
3526 output.append("%s%s" %
3527 ('+'.join([str(p.rev()) for p in parents]), changed))
3527 ('+'.join([str(p.rev()) for p in parents]), changed))
3528 else:
3528 else:
3529 ctx = scmutil.revsingle(repo, rev)
3529 ctx = scmutil.revsingle(repo, rev)
3530 if default or id:
3530 if default or id:
3531 output = [hexfunc(ctx.node())]
3531 output = [hexfunc(ctx.node())]
3532 if num:
3532 if num:
3533 output.append(str(ctx.rev()))
3533 output.append(str(ctx.rev()))
3534
3534
3535 if default and not ui.quiet:
3535 if default and not ui.quiet:
3536 b = ctx.branch()
3536 b = ctx.branch()
3537 if b != 'default':
3537 if b != 'default':
3538 output.append("(%s)" % b)
3538 output.append("(%s)" % b)
3539
3539
3540 # multiple tags for a single parent separated by '/'
3540 # multiple tags for a single parent separated by '/'
3541 t = '/'.join(ctx.tags())
3541 t = '/'.join(ctx.tags())
3542 if t:
3542 if t:
3543 output.append(t)
3543 output.append(t)
3544
3544
3545 # multiple bookmarks for a single parent separated by '/'
3545 # multiple bookmarks for a single parent separated by '/'
3546 bm = '/'.join(ctx.bookmarks())
3546 bm = '/'.join(ctx.bookmarks())
3547 if bm:
3547 if bm:
3548 output.append(bm)
3548 output.append(bm)
3549 else:
3549 else:
3550 if branch:
3550 if branch:
3551 output.append(ctx.branch())
3551 output.append(ctx.branch())
3552
3552
3553 if tags:
3553 if tags:
3554 output.extend(ctx.tags())
3554 output.extend(ctx.tags())
3555
3555
3556 if bookmarks:
3556 if bookmarks:
3557 output.extend(ctx.bookmarks())
3557 output.extend(ctx.bookmarks())
3558
3558
3559 ui.write("%s\n" % ' '.join(output))
3559 ui.write("%s\n" % ' '.join(output))
3560
3560
3561 @command('import|patch',
3561 @command('import|patch',
3562 [('p', 'strip', 1,
3562 [('p', 'strip', 1,
3563 _('directory strip option for patch. This has the same '
3563 _('directory strip option for patch. This has the same '
3564 'meaning as the corresponding patch option'), _('NUM')),
3564 'meaning as the corresponding patch option'), _('NUM')),
3565 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3565 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3566 ('e', 'edit', False, _('invoke editor on commit messages')),
3566 ('e', 'edit', False, _('invoke editor on commit messages')),
3567 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3567 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3568 ('', 'no-commit', None,
3568 ('', 'no-commit', None,
3569 _("don't commit, just update the working directory")),
3569 _("don't commit, just update the working directory")),
3570 ('', 'bypass', None,
3570 ('', 'bypass', None,
3571 _("apply patch without touching the working directory")),
3571 _("apply patch without touching the working directory")),
3572 ('', 'exact', None,
3572 ('', 'exact', None,
3573 _('apply patch to the nodes from which it was generated')),
3573 _('apply patch to the nodes from which it was generated')),
3574 ('', 'import-branch', None,
3574 ('', 'import-branch', None,
3575 _('use any branch information in patch (implied by --exact)'))] +
3575 _('use any branch information in patch (implied by --exact)'))] +
3576 commitopts + commitopts2 + similarityopts,
3576 commitopts + commitopts2 + similarityopts,
3577 _('[OPTION]... PATCH...'))
3577 _('[OPTION]... PATCH...'))
3578 def import_(ui, repo, patch1=None, *patches, **opts):
3578 def import_(ui, repo, patch1=None, *patches, **opts):
3579 """import an ordered set of patches
3579 """import an ordered set of patches
3580
3580
3581 Import a list of patches and commit them individually (unless
3581 Import a list of patches and commit them individually (unless
3582 --no-commit is specified).
3582 --no-commit is specified).
3583
3583
3584 If there are outstanding changes in the working directory, import
3584 If there are outstanding changes in the working directory, import
3585 will abort unless given the -f/--force flag.
3585 will abort unless given the -f/--force flag.
3586
3586
3587 You can import a patch straight from a mail message. Even patches
3587 You can import a patch straight from a mail message. Even patches
3588 as attachments work (to use the body part, it must have type
3588 as attachments work (to use the body part, it must have type
3589 text/plain or text/x-patch). From and Subject headers of email
3589 text/plain or text/x-patch). From and Subject headers of email
3590 message are used as default committer and commit message. All
3590 message are used as default committer and commit message. All
3591 text/plain body parts before first diff are added to commit
3591 text/plain body parts before first diff are added to commit
3592 message.
3592 message.
3593
3593
3594 If the imported patch was generated by :hg:`export`, user and
3594 If the imported patch was generated by :hg:`export`, user and
3595 description from patch override values from message headers and
3595 description from patch override values from message headers and
3596 body. Values given on command line with -m/--message and -u/--user
3596 body. Values given on command line with -m/--message and -u/--user
3597 override these.
3597 override these.
3598
3598
3599 If --exact is specified, import will set the working directory to
3599 If --exact is specified, import will set the working directory to
3600 the parent of each patch before applying it, and will abort if the
3600 the parent of each patch before applying it, and will abort if the
3601 resulting changeset has a different ID than the one recorded in
3601 resulting changeset has a different ID than the one recorded in
3602 the patch. This may happen due to character set problems or other
3602 the patch. This may happen due to character set problems or other
3603 deficiencies in the text patch format.
3603 deficiencies in the text patch format.
3604
3604
3605 Use --bypass to apply and commit patches directly to the
3605 Use --bypass to apply and commit patches directly to the
3606 repository, not touching the working directory. Without --exact,
3606 repository, not touching the working directory. Without --exact,
3607 patches will be applied on top of the working directory parent
3607 patches will be applied on top of the working directory parent
3608 revision.
3608 revision.
3609
3609
3610 With -s/--similarity, hg will attempt to discover renames and
3610 With -s/--similarity, hg will attempt to discover renames and
3611 copies in the patch in the same way as :hg:`addremove`.
3611 copies in the patch in the same way as :hg:`addremove`.
3612
3612
3613 To read a patch from standard input, use "-" as the patch name. If
3613 To read a patch from standard input, use "-" as the patch name. If
3614 a URL is specified, the patch will be downloaded from it.
3614 a URL is specified, the patch will be downloaded from it.
3615 See :hg:`help dates` for a list of formats valid for -d/--date.
3615 See :hg:`help dates` for a list of formats valid for -d/--date.
3616
3616
3617 .. container:: verbose
3617 .. container:: verbose
3618
3618
3619 Examples:
3619 Examples:
3620
3620
3621 - import a traditional patch from a website and detect renames::
3621 - import a traditional patch from a website and detect renames::
3622
3622
3623 hg import -s 80 http://example.com/bugfix.patch
3623 hg import -s 80 http://example.com/bugfix.patch
3624
3624
3625 - import a changeset from an hgweb server::
3625 - import a changeset from an hgweb server::
3626
3626
3627 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3627 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3628
3628
3629 - import all the patches in an Unix-style mbox::
3629 - import all the patches in an Unix-style mbox::
3630
3630
3631 hg import incoming-patches.mbox
3631 hg import incoming-patches.mbox
3632
3632
3633 - attempt to exactly restore an exported changeset (not always
3633 - attempt to exactly restore an exported changeset (not always
3634 possible)::
3634 possible)::
3635
3635
3636 hg import --exact proposed-fix.patch
3636 hg import --exact proposed-fix.patch
3637
3637
3638 Returns 0 on success.
3638 Returns 0 on success.
3639 """
3639 """
3640
3640
3641 if not patch1:
3641 if not patch1:
3642 raise util.Abort(_('need at least one patch to import'))
3642 raise util.Abort(_('need at least one patch to import'))
3643
3643
3644 patches = (patch1,) + patches
3644 patches = (patch1,) + patches
3645
3645
3646 date = opts.get('date')
3646 date = opts.get('date')
3647 if date:
3647 if date:
3648 opts['date'] = util.parsedate(date)
3648 opts['date'] = util.parsedate(date)
3649
3649
3650 editor = cmdutil.commiteditor
3650 editor = cmdutil.commiteditor
3651 if opts.get('edit'):
3651 if opts.get('edit'):
3652 editor = cmdutil.commitforceeditor
3652 editor = cmdutil.commitforceeditor
3653
3653
3654 update = not opts.get('bypass')
3654 update = not opts.get('bypass')
3655 if not update and opts.get('no_commit'):
3655 if not update and opts.get('no_commit'):
3656 raise util.Abort(_('cannot use --no-commit with --bypass'))
3656 raise util.Abort(_('cannot use --no-commit with --bypass'))
3657 try:
3657 try:
3658 sim = float(opts.get('similarity') or 0)
3658 sim = float(opts.get('similarity') or 0)
3659 except ValueError:
3659 except ValueError:
3660 raise util.Abort(_('similarity must be a number'))
3660 raise util.Abort(_('similarity must be a number'))
3661 if sim < 0 or sim > 100:
3661 if sim < 0 or sim > 100:
3662 raise util.Abort(_('similarity must be between 0 and 100'))
3662 raise util.Abort(_('similarity must be between 0 and 100'))
3663 if sim and not update:
3663 if sim and not update:
3664 raise util.Abort(_('cannot use --similarity with --bypass'))
3664 raise util.Abort(_('cannot use --similarity with --bypass'))
3665
3665
3666 if (opts.get('exact') or not opts.get('force')) and update:
3666 if (opts.get('exact') or not opts.get('force')) and update:
3667 cmdutil.bailifchanged(repo)
3667 cmdutil.bailifchanged(repo)
3668
3668
3669 base = opts["base"]
3669 base = opts["base"]
3670 strip = opts["strip"]
3670 strip = opts["strip"]
3671 wlock = lock = tr = None
3671 wlock = lock = tr = None
3672 msgs = []
3672 msgs = []
3673
3673
3674 def checkexact(repo, n, nodeid):
3674 def checkexact(repo, n, nodeid):
3675 if opts.get('exact') and hex(n) != nodeid:
3675 if opts.get('exact') and hex(n) != nodeid:
3676 repo.rollback()
3676 repo.rollback()
3677 raise util.Abort(_('patch is damaged or loses information'))
3677 raise util.Abort(_('patch is damaged or loses information'))
3678
3678
3679 def tryone(ui, hunk, parents):
3679 def tryone(ui, hunk, parents):
3680 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3680 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3681 patch.extract(ui, hunk)
3681 patch.extract(ui, hunk)
3682
3682
3683 if not tmpname:
3683 if not tmpname:
3684 return (None, None)
3684 return (None, None)
3685 msg = _('applied to working directory')
3685 msg = _('applied to working directory')
3686
3686
3687 try:
3687 try:
3688 cmdline_message = cmdutil.logmessage(ui, opts)
3688 cmdline_message = cmdutil.logmessage(ui, opts)
3689 if cmdline_message:
3689 if cmdline_message:
3690 # pickup the cmdline msg
3690 # pickup the cmdline msg
3691 message = cmdline_message
3691 message = cmdline_message
3692 elif message:
3692 elif message:
3693 # pickup the patch msg
3693 # pickup the patch msg
3694 message = message.strip()
3694 message = message.strip()
3695 else:
3695 else:
3696 # launch the editor
3696 # launch the editor
3697 message = None
3697 message = None
3698 ui.debug('message:\n%s\n' % message)
3698 ui.debug('message:\n%s\n' % message)
3699
3699
3700 if len(parents) == 1:
3700 if len(parents) == 1:
3701 parents.append(repo[nullid])
3701 parents.append(repo[nullid])
3702 if opts.get('exact'):
3702 if opts.get('exact'):
3703 if not nodeid or not p1:
3703 if not nodeid or not p1:
3704 raise util.Abort(_('not a Mercurial patch'))
3704 raise util.Abort(_('not a Mercurial patch'))
3705 p1 = repo[p1]
3705 p1 = repo[p1]
3706 p2 = repo[p2 or nullid]
3706 p2 = repo[p2 or nullid]
3707 elif p2:
3707 elif p2:
3708 try:
3708 try:
3709 p1 = repo[p1]
3709 p1 = repo[p1]
3710 p2 = repo[p2]
3710 p2 = repo[p2]
3711 # Without any options, consider p2 only if the
3711 # Without any options, consider p2 only if the
3712 # patch is being applied on top of the recorded
3712 # patch is being applied on top of the recorded
3713 # first parent.
3713 # first parent.
3714 if p1 != parents[0]:
3714 if p1 != parents[0]:
3715 p1 = parents[0]
3715 p1 = parents[0]
3716 p2 = repo[nullid]
3716 p2 = repo[nullid]
3717 except error.RepoError:
3717 except error.RepoError:
3718 p1, p2 = parents
3718 p1, p2 = parents
3719 else:
3719 else:
3720 p1, p2 = parents
3720 p1, p2 = parents
3721
3721
3722 n = None
3722 n = None
3723 if update:
3723 if update:
3724 if p1 != parents[0]:
3724 if p1 != parents[0]:
3725 hg.clean(repo, p1.node())
3725 hg.clean(repo, p1.node())
3726 if p2 != parents[1]:
3726 if p2 != parents[1]:
3727 repo.setparents(p1.node(), p2.node())
3727 repo.setparents(p1.node(), p2.node())
3728
3728
3729 if opts.get('exact') or opts.get('import_branch'):
3729 if opts.get('exact') or opts.get('import_branch'):
3730 repo.dirstate.setbranch(branch or 'default')
3730 repo.dirstate.setbranch(branch or 'default')
3731
3731
3732 files = set()
3732 files = set()
3733 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3733 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3734 eolmode=None, similarity=sim / 100.0)
3734 eolmode=None, similarity=sim / 100.0)
3735 files = list(files)
3735 files = list(files)
3736 if opts.get('no_commit'):
3736 if opts.get('no_commit'):
3737 if message:
3737 if message:
3738 msgs.append(message)
3738 msgs.append(message)
3739 else:
3739 else:
3740 if opts.get('exact') or p2:
3740 if opts.get('exact') or p2:
3741 # If you got here, you either use --force and know what
3741 # If you got here, you either use --force and know what
3742 # you are doing or used --exact or a merge patch while
3742 # you are doing or used --exact or a merge patch while
3743 # being updated to its first parent.
3743 # being updated to its first parent.
3744 m = None
3744 m = None
3745 else:
3745 else:
3746 m = scmutil.matchfiles(repo, files or [])
3746 m = scmutil.matchfiles(repo, files or [])
3747 n = repo.commit(message, opts.get('user') or user,
3747 n = repo.commit(message, opts.get('user') or user,
3748 opts.get('date') or date, match=m,
3748 opts.get('date') or date, match=m,
3749 editor=editor)
3749 editor=editor)
3750 checkexact(repo, n, nodeid)
3750 checkexact(repo, n, nodeid)
3751 else:
3751 else:
3752 if opts.get('exact') or opts.get('import_branch'):
3752 if opts.get('exact') or opts.get('import_branch'):
3753 branch = branch or 'default'
3753 branch = branch or 'default'
3754 else:
3754 else:
3755 branch = p1.branch()
3755 branch = p1.branch()
3756 store = patch.filestore()
3756 store = patch.filestore()
3757 try:
3757 try:
3758 files = set()
3758 files = set()
3759 try:
3759 try:
3760 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3760 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3761 files, eolmode=None)
3761 files, eolmode=None)
3762 except patch.PatchError, e:
3762 except patch.PatchError, e:
3763 raise util.Abort(str(e))
3763 raise util.Abort(str(e))
3764 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3764 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3765 message,
3765 message,
3766 opts.get('user') or user,
3766 opts.get('user') or user,
3767 opts.get('date') or date,
3767 opts.get('date') or date,
3768 branch, files, store,
3768 branch, files, store,
3769 editor=cmdutil.commiteditor)
3769 editor=cmdutil.commiteditor)
3770 repo.savecommitmessage(memctx.description())
3770 repo.savecommitmessage(memctx.description())
3771 n = memctx.commit()
3771 n = memctx.commit()
3772 checkexact(repo, n, nodeid)
3772 checkexact(repo, n, nodeid)
3773 finally:
3773 finally:
3774 store.close()
3774 store.close()
3775 if n:
3775 if n:
3776 # i18n: refers to a short changeset id
3776 # i18n: refers to a short changeset id
3777 msg = _('created %s') % short(n)
3777 msg = _('created %s') % short(n)
3778 return (msg, n)
3778 return (msg, n)
3779 finally:
3779 finally:
3780 os.unlink(tmpname)
3780 os.unlink(tmpname)
3781
3781
3782 try:
3782 try:
3783 try:
3783 try:
3784 wlock = repo.wlock()
3784 wlock = repo.wlock()
3785 if not opts.get('no_commit'):
3785 if not opts.get('no_commit'):
3786 lock = repo.lock()
3786 lock = repo.lock()
3787 tr = repo.transaction('import')
3787 tr = repo.transaction('import')
3788 parents = repo.parents()
3788 parents = repo.parents()
3789 for patchurl in patches:
3789 for patchurl in patches:
3790 if patchurl == '-':
3790 if patchurl == '-':
3791 ui.status(_('applying patch from stdin\n'))
3791 ui.status(_('applying patch from stdin\n'))
3792 patchfile = ui.fin
3792 patchfile = ui.fin
3793 patchurl = 'stdin' # for error message
3793 patchurl = 'stdin' # for error message
3794 else:
3794 else:
3795 patchurl = os.path.join(base, patchurl)
3795 patchurl = os.path.join(base, patchurl)
3796 ui.status(_('applying %s\n') % patchurl)
3796 ui.status(_('applying %s\n') % patchurl)
3797 patchfile = url.open(ui, patchurl)
3797 patchfile = url.open(ui, patchurl)
3798
3798
3799 haspatch = False
3799 haspatch = False
3800 for hunk in patch.split(patchfile):
3800 for hunk in patch.split(patchfile):
3801 (msg, node) = tryone(ui, hunk, parents)
3801 (msg, node) = tryone(ui, hunk, parents)
3802 if msg:
3802 if msg:
3803 haspatch = True
3803 haspatch = True
3804 ui.note(msg + '\n')
3804 ui.note(msg + '\n')
3805 if update or opts.get('exact'):
3805 if update or opts.get('exact'):
3806 parents = repo.parents()
3806 parents = repo.parents()
3807 else:
3807 else:
3808 parents = [repo[node]]
3808 parents = [repo[node]]
3809
3809
3810 if not haspatch:
3810 if not haspatch:
3811 raise util.Abort(_('%s: no diffs found') % patchurl)
3811 raise util.Abort(_('%s: no diffs found') % patchurl)
3812
3812
3813 if tr:
3813 if tr:
3814 tr.close()
3814 tr.close()
3815 if msgs:
3815 if msgs:
3816 repo.savecommitmessage('\n* * *\n'.join(msgs))
3816 repo.savecommitmessage('\n* * *\n'.join(msgs))
3817 except: # re-raises
3817 except: # re-raises
3818 # wlock.release() indirectly calls dirstate.write(): since
3818 # wlock.release() indirectly calls dirstate.write(): since
3819 # we're crashing, we do not want to change the working dir
3819 # we're crashing, we do not want to change the working dir
3820 # parent after all, so make sure it writes nothing
3820 # parent after all, so make sure it writes nothing
3821 repo.dirstate.invalidate()
3821 repo.dirstate.invalidate()
3822 raise
3822 raise
3823 finally:
3823 finally:
3824 if tr:
3824 if tr:
3825 tr.release()
3825 tr.release()
3826 release(lock, wlock)
3826 release(lock, wlock)
3827
3827
3828 @command('incoming|in',
3828 @command('incoming|in',
3829 [('f', 'force', None,
3829 [('f', 'force', None,
3830 _('run even if remote repository is unrelated')),
3830 _('run even if remote repository is unrelated')),
3831 ('n', 'newest-first', None, _('show newest record first')),
3831 ('n', 'newest-first', None, _('show newest record first')),
3832 ('', 'bundle', '',
3832 ('', 'bundle', '',
3833 _('file to store the bundles into'), _('FILE')),
3833 _('file to store the bundles into'), _('FILE')),
3834 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3834 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3835 ('B', 'bookmarks', False, _("compare bookmarks")),
3835 ('B', 'bookmarks', False, _("compare bookmarks")),
3836 ('b', 'branch', [],
3836 ('b', 'branch', [],
3837 _('a specific branch you would like to pull'), _('BRANCH')),
3837 _('a specific branch you would like to pull'), _('BRANCH')),
3838 ] + logopts + remoteopts + subrepoopts,
3838 ] + logopts + remoteopts + subrepoopts,
3839 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3839 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3840 def incoming(ui, repo, source="default", **opts):
3840 def incoming(ui, repo, source="default", **opts):
3841 """show new changesets found in source
3841 """show new changesets found in source
3842
3842
3843 Show new changesets found in the specified path/URL or the default
3843 Show new changesets found in the specified path/URL or the default
3844 pull location. These are the changesets that would have been pulled
3844 pull location. These are the changesets that would have been pulled
3845 if a pull at the time you issued this command.
3845 if a pull at the time you issued this command.
3846
3846
3847 For remote repository, using --bundle avoids downloading the
3847 For remote repository, using --bundle avoids downloading the
3848 changesets twice if the incoming is followed by a pull.
3848 changesets twice if the incoming is followed by a pull.
3849
3849
3850 See pull for valid source format details.
3850 See pull for valid source format details.
3851
3851
3852 Returns 0 if there are incoming changes, 1 otherwise.
3852 Returns 0 if there are incoming changes, 1 otherwise.
3853 """
3853 """
3854 if opts.get('graph'):
3854 if opts.get('graph'):
3855 cmdutil.checkunsupportedgraphflags([], opts)
3855 cmdutil.checkunsupportedgraphflags([], opts)
3856 def display(other, chlist, displayer):
3856 def display(other, chlist, displayer):
3857 revdag = cmdutil.graphrevs(other, chlist, opts)
3857 revdag = cmdutil.graphrevs(other, chlist, opts)
3858 showparents = [ctx.node() for ctx in repo[None].parents()]
3858 showparents = [ctx.node() for ctx in repo[None].parents()]
3859 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3859 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3860 graphmod.asciiedges)
3860 graphmod.asciiedges)
3861
3861
3862 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3862 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3863 return 0
3863 return 0
3864
3864
3865 if opts.get('bundle') and opts.get('subrepos'):
3865 if opts.get('bundle') and opts.get('subrepos'):
3866 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3866 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3867
3867
3868 if opts.get('bookmarks'):
3868 if opts.get('bookmarks'):
3869 source, branches = hg.parseurl(ui.expandpath(source),
3869 source, branches = hg.parseurl(ui.expandpath(source),
3870 opts.get('branch'))
3870 opts.get('branch'))
3871 other = hg.peer(repo, opts, source)
3871 other = hg.peer(repo, opts, source)
3872 if 'bookmarks' not in other.listkeys('namespaces'):
3872 if 'bookmarks' not in other.listkeys('namespaces'):
3873 ui.warn(_("remote doesn't support bookmarks\n"))
3873 ui.warn(_("remote doesn't support bookmarks\n"))
3874 return 0
3874 return 0
3875 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3875 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3876 return bookmarks.diff(ui, repo, other)
3876 return bookmarks.diff(ui, repo, other)
3877
3877
3878 repo._subtoppath = ui.expandpath(source)
3878 repo._subtoppath = ui.expandpath(source)
3879 try:
3879 try:
3880 return hg.incoming(ui, repo, source, opts)
3880 return hg.incoming(ui, repo, source, opts)
3881 finally:
3881 finally:
3882 del repo._subtoppath
3882 del repo._subtoppath
3883
3883
3884
3884
3885 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3885 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3886 def init(ui, dest=".", **opts):
3886 def init(ui, dest=".", **opts):
3887 """create a new repository in the given directory
3887 """create a new repository in the given directory
3888
3888
3889 Initialize a new repository in the given directory. If the given
3889 Initialize a new repository in the given directory. If the given
3890 directory does not exist, it will be created.
3890 directory does not exist, it will be created.
3891
3891
3892 If no directory is given, the current directory is used.
3892 If no directory is given, the current directory is used.
3893
3893
3894 It is possible to specify an ``ssh://`` URL as the destination.
3894 It is possible to specify an ``ssh://`` URL as the destination.
3895 See :hg:`help urls` for more information.
3895 See :hg:`help urls` for more information.
3896
3896
3897 Returns 0 on success.
3897 Returns 0 on success.
3898 """
3898 """
3899 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3899 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3900
3900
3901 @command('locate',
3901 @command('locate',
3902 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3902 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3903 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3903 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3904 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3904 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3905 ] + walkopts,
3905 ] + walkopts,
3906 _('[OPTION]... [PATTERN]...'))
3906 _('[OPTION]... [PATTERN]...'))
3907 def locate(ui, repo, *pats, **opts):
3907 def locate(ui, repo, *pats, **opts):
3908 """locate files matching specific patterns
3908 """locate files matching specific patterns
3909
3909
3910 Print files under Mercurial control in the working directory whose
3910 Print files under Mercurial control in the working directory whose
3911 names match the given patterns.
3911 names match the given patterns.
3912
3912
3913 By default, this command searches all directories in the working
3913 By default, this command searches all directories in the working
3914 directory. To search just the current directory and its
3914 directory. To search just the current directory and its
3915 subdirectories, use "--include .".
3915 subdirectories, use "--include .".
3916
3916
3917 If no patterns are given to match, this command prints the names
3917 If no patterns are given to match, this command prints the names
3918 of all files under Mercurial control in the working directory.
3918 of all files under Mercurial control in the working directory.
3919
3919
3920 If you want to feed the output of this command into the "xargs"
3920 If you want to feed the output of this command into the "xargs"
3921 command, use the -0 option to both this command and "xargs". This
3921 command, use the -0 option to both this command and "xargs". This
3922 will avoid the problem of "xargs" treating single filenames that
3922 will avoid the problem of "xargs" treating single filenames that
3923 contain whitespace as multiple filenames.
3923 contain whitespace as multiple filenames.
3924
3924
3925 Returns 0 if a match is found, 1 otherwise.
3925 Returns 0 if a match is found, 1 otherwise.
3926 """
3926 """
3927 end = opts.get('print0') and '\0' or '\n'
3927 end = opts.get('print0') and '\0' or '\n'
3928 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3928 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3929
3929
3930 ret = 1
3930 ret = 1
3931 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3931 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3932 m.bad = lambda x, y: False
3932 m.bad = lambda x, y: False
3933 for abs in repo[rev].walk(m):
3933 for abs in repo[rev].walk(m):
3934 if not rev and abs not in repo.dirstate:
3934 if not rev and abs not in repo.dirstate:
3935 continue
3935 continue
3936 if opts.get('fullpath'):
3936 if opts.get('fullpath'):
3937 ui.write(repo.wjoin(abs), end)
3937 ui.write(repo.wjoin(abs), end)
3938 else:
3938 else:
3939 ui.write(((pats and m.rel(abs)) or abs), end)
3939 ui.write(((pats and m.rel(abs)) or abs), end)
3940 ret = 0
3940 ret = 0
3941
3941
3942 return ret
3942 return ret
3943
3943
3944 @command('^log|history',
3944 @command('^log|history',
3945 [('f', 'follow', None,
3945 [('f', 'follow', None,
3946 _('follow changeset history, or file history across copies and renames')),
3946 _('follow changeset history, or file history across copies and renames')),
3947 ('', 'follow-first', None,
3947 ('', 'follow-first', None,
3948 _('only follow the first parent of merge changesets (DEPRECATED)')),
3948 _('only follow the first parent of merge changesets (DEPRECATED)')),
3949 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3949 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3950 ('C', 'copies', None, _('show copied files')),
3950 ('C', 'copies', None, _('show copied files')),
3951 ('k', 'keyword', [],
3951 ('k', 'keyword', [],
3952 _('do case-insensitive search for a given text'), _('TEXT')),
3952 _('do case-insensitive search for a given text'), _('TEXT')),
3953 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3953 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3954 ('', 'removed', None, _('include revisions where files were removed')),
3954 ('', 'removed', None, _('include revisions where files were removed')),
3955 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3955 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3956 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3956 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3957 ('', 'only-branch', [],
3957 ('', 'only-branch', [],
3958 _('show only changesets within the given named branch (DEPRECATED)'),
3958 _('show only changesets within the given named branch (DEPRECATED)'),
3959 _('BRANCH')),
3959 _('BRANCH')),
3960 ('b', 'branch', [],
3960 ('b', 'branch', [],
3961 _('show changesets within the given named branch'), _('BRANCH')),
3961 _('show changesets within the given named branch'), _('BRANCH')),
3962 ('P', 'prune', [],
3962 ('P', 'prune', [],
3963 _('do not display revision or any of its ancestors'), _('REV')),
3963 _('do not display revision or any of its ancestors'), _('REV')),
3964 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3964 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3965 ] + logopts + walkopts,
3965 ] + logopts + walkopts,
3966 _('[OPTION]... [FILE]'))
3966 _('[OPTION]... [FILE]'))
3967 def log(ui, repo, *pats, **opts):
3967 def log(ui, repo, *pats, **opts):
3968 """show revision history of entire repository or files
3968 """show revision history of entire repository or files
3969
3969
3970 Print the revision history of the specified files or the entire
3970 Print the revision history of the specified files or the entire
3971 project.
3971 project.
3972
3972
3973 If no revision range is specified, the default is ``tip:0`` unless
3973 If no revision range is specified, the default is ``tip:0`` unless
3974 --follow is set, in which case the working directory parent is
3974 --follow is set, in which case the working directory parent is
3975 used as the starting revision.
3975 used as the starting revision.
3976
3976
3977 File history is shown without following rename or copy history of
3977 File history is shown without following rename or copy history of
3978 files. Use -f/--follow with a filename to follow history across
3978 files. Use -f/--follow with a filename to follow history across
3979 renames and copies. --follow without a filename will only show
3979 renames and copies. --follow without a filename will only show
3980 ancestors or descendants of the starting revision.
3980 ancestors or descendants of the starting revision.
3981
3981
3982 By default this command prints revision number and changeset id,
3982 By default this command prints revision number and changeset id,
3983 tags, non-trivial parents, user, date and time, and a summary for
3983 tags, non-trivial parents, user, date and time, and a summary for
3984 each commit. When the -v/--verbose switch is used, the list of
3984 each commit. When the -v/--verbose switch is used, the list of
3985 changed files and full commit message are shown.
3985 changed files and full commit message are shown.
3986
3986
3987 .. note::
3987 .. note::
3988 log -p/--patch may generate unexpected diff output for merge
3988 log -p/--patch may generate unexpected diff output for merge
3989 changesets, as it will only compare the merge changeset against
3989 changesets, as it will only compare the merge changeset against
3990 its first parent. Also, only files different from BOTH parents
3990 its first parent. Also, only files different from BOTH parents
3991 will appear in files:.
3991 will appear in files:.
3992
3992
3993 .. note::
3993 .. note::
3994 for performance reasons, log FILE may omit duplicate changes
3994 for performance reasons, log FILE may omit duplicate changes
3995 made on branches and will not show deletions. To see all
3995 made on branches and will not show deletions. To see all
3996 changes including duplicates and deletions, use the --removed
3996 changes including duplicates and deletions, use the --removed
3997 switch.
3997 switch.
3998
3998
3999 .. container:: verbose
3999 .. container:: verbose
4000
4000
4001 Some examples:
4001 Some examples:
4002
4002
4003 - changesets with full descriptions and file lists::
4003 - changesets with full descriptions and file lists::
4004
4004
4005 hg log -v
4005 hg log -v
4006
4006
4007 - changesets ancestral to the working directory::
4007 - changesets ancestral to the working directory::
4008
4008
4009 hg log -f
4009 hg log -f
4010
4010
4011 - last 10 commits on the current branch::
4011 - last 10 commits on the current branch::
4012
4012
4013 hg log -l 10 -b .
4013 hg log -l 10 -b .
4014
4014
4015 - changesets showing all modifications of a file, including removals::
4015 - changesets showing all modifications of a file, including removals::
4016
4016
4017 hg log --removed file.c
4017 hg log --removed file.c
4018
4018
4019 - all changesets that touch a directory, with diffs, excluding merges::
4019 - all changesets that touch a directory, with diffs, excluding merges::
4020
4020
4021 hg log -Mp lib/
4021 hg log -Mp lib/
4022
4022
4023 - all revision numbers that match a keyword::
4023 - all revision numbers that match a keyword::
4024
4024
4025 hg log -k bug --template "{rev}\\n"
4025 hg log -k bug --template "{rev}\\n"
4026
4026
4027 - check if a given changeset is included is a tagged release::
4027 - check if a given changeset is included is a tagged release::
4028
4028
4029 hg log -r "a21ccf and ancestor(1.9)"
4029 hg log -r "a21ccf and ancestor(1.9)"
4030
4030
4031 - find all changesets by some user in a date range::
4031 - find all changesets by some user in a date range::
4032
4032
4033 hg log -k alice -d "may 2008 to jul 2008"
4033 hg log -k alice -d "may 2008 to jul 2008"
4034
4034
4035 - summary of all changesets after the last tag::
4035 - summary of all changesets after the last tag::
4036
4036
4037 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4037 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4038
4038
4039 See :hg:`help dates` for a list of formats valid for -d/--date.
4039 See :hg:`help dates` for a list of formats valid for -d/--date.
4040
4040
4041 See :hg:`help revisions` and :hg:`help revsets` for more about
4041 See :hg:`help revisions` and :hg:`help revsets` for more about
4042 specifying revisions.
4042 specifying revisions.
4043
4043
4044 See :hg:`help templates` for more about pre-packaged styles and
4044 See :hg:`help templates` for more about pre-packaged styles and
4045 specifying custom templates.
4045 specifying custom templates.
4046
4046
4047 Returns 0 on success.
4047 Returns 0 on success.
4048 """
4048 """
4049 if opts.get('graph'):
4049 if opts.get('graph'):
4050 return cmdutil.graphlog(ui, repo, *pats, **opts)
4050 return cmdutil.graphlog(ui, repo, *pats, **opts)
4051
4051
4052 matchfn = scmutil.match(repo[None], pats, opts)
4052 matchfn = scmutil.match(repo[None], pats, opts)
4053 limit = cmdutil.loglimit(opts)
4053 limit = cmdutil.loglimit(opts)
4054 count = 0
4054 count = 0
4055
4055
4056 getrenamed, endrev = None, None
4056 getrenamed, endrev = None, None
4057 if opts.get('copies'):
4057 if opts.get('copies'):
4058 if opts.get('rev'):
4058 if opts.get('rev'):
4059 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4059 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4060 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4060 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4061
4061
4062 df = False
4062 df = False
4063 if opts["date"]:
4063 if opts["date"]:
4064 df = util.matchdate(opts["date"])
4064 df = util.matchdate(opts["date"])
4065
4065
4066 branches = opts.get('branch', []) + opts.get('only_branch', [])
4066 branches = opts.get('branch', []) + opts.get('only_branch', [])
4067 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4067 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4068
4068
4069 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4069 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4070 def prep(ctx, fns):
4070 def prep(ctx, fns):
4071 rev = ctx.rev()
4071 rev = ctx.rev()
4072 parents = [p for p in repo.changelog.parentrevs(rev)
4072 parents = [p for p in repo.changelog.parentrevs(rev)
4073 if p != nullrev]
4073 if p != nullrev]
4074 if opts.get('no_merges') and len(parents) == 2:
4074 if opts.get('no_merges') and len(parents) == 2:
4075 return
4075 return
4076 if opts.get('only_merges') and len(parents) != 2:
4076 if opts.get('only_merges') and len(parents) != 2:
4077 return
4077 return
4078 if opts.get('branch') and ctx.branch() not in opts['branch']:
4078 if opts.get('branch') and ctx.branch() not in opts['branch']:
4079 return
4079 return
4080 if not opts.get('hidden') and ctx.hidden():
4080 if not opts.get('hidden') and ctx.hidden():
4081 return
4081 return
4082 if df and not df(ctx.date()[0]):
4082 if df and not df(ctx.date()[0]):
4083 return
4083 return
4084
4084
4085 lower = encoding.lower
4085 lower = encoding.lower
4086 if opts.get('user'):
4086 if opts.get('user'):
4087 luser = lower(ctx.user())
4087 luser = lower(ctx.user())
4088 for k in [lower(x) for x in opts['user']]:
4088 for k in [lower(x) for x in opts['user']]:
4089 if (k in luser):
4089 if (k in luser):
4090 break
4090 break
4091 else:
4091 else:
4092 return
4092 return
4093 if opts.get('keyword'):
4093 if opts.get('keyword'):
4094 luser = lower(ctx.user())
4094 luser = lower(ctx.user())
4095 ldesc = lower(ctx.description())
4095 ldesc = lower(ctx.description())
4096 lfiles = lower(" ".join(ctx.files()))
4096 lfiles = lower(" ".join(ctx.files()))
4097 for k in [lower(x) for x in opts['keyword']]:
4097 for k in [lower(x) for x in opts['keyword']]:
4098 if (k in luser or k in ldesc or k in lfiles):
4098 if (k in luser or k in ldesc or k in lfiles):
4099 break
4099 break
4100 else:
4100 else:
4101 return
4101 return
4102
4102
4103 copies = None
4103 copies = None
4104 if getrenamed is not None and rev:
4104 if getrenamed is not None and rev:
4105 copies = []
4105 copies = []
4106 for fn in ctx.files():
4106 for fn in ctx.files():
4107 rename = getrenamed(fn, rev)
4107 rename = getrenamed(fn, rev)
4108 if rename:
4108 if rename:
4109 copies.append((fn, rename[0]))
4109 copies.append((fn, rename[0]))
4110
4110
4111 revmatchfn = None
4111 revmatchfn = None
4112 if opts.get('patch') or opts.get('stat'):
4112 if opts.get('patch') or opts.get('stat'):
4113 if opts.get('follow') or opts.get('follow_first'):
4113 if opts.get('follow') or opts.get('follow_first'):
4114 # note: this might be wrong when following through merges
4114 # note: this might be wrong when following through merges
4115 revmatchfn = scmutil.match(repo[None], fns, default='path')
4115 revmatchfn = scmutil.match(repo[None], fns, default='path')
4116 else:
4116 else:
4117 revmatchfn = matchfn
4117 revmatchfn = matchfn
4118
4118
4119 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4119 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4120
4120
4121 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4121 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4122 if count == limit:
4122 if count == limit:
4123 break
4123 break
4124 if displayer.flush(ctx.rev()):
4124 if displayer.flush(ctx.rev()):
4125 count += 1
4125 count += 1
4126 displayer.close()
4126 displayer.close()
4127
4127
4128 @command('manifest',
4128 @command('manifest',
4129 [('r', 'rev', '', _('revision to display'), _('REV')),
4129 [('r', 'rev', '', _('revision to display'), _('REV')),
4130 ('', 'all', False, _("list files from all revisions"))],
4130 ('', 'all', False, _("list files from all revisions"))],
4131 _('[-r REV]'))
4131 _('[-r REV]'))
4132 def manifest(ui, repo, node=None, rev=None, **opts):
4132 def manifest(ui, repo, node=None, rev=None, **opts):
4133 """output the current or given revision of the project manifest
4133 """output the current or given revision of the project manifest
4134
4134
4135 Print a list of version controlled files for the given revision.
4135 Print a list of version controlled files for the given revision.
4136 If no revision is given, the first parent of the working directory
4136 If no revision is given, the first parent of the working directory
4137 is used, or the null revision if no revision is checked out.
4137 is used, or the null revision if no revision is checked out.
4138
4138
4139 With -v, print file permissions, symlink and executable bits.
4139 With -v, print file permissions, symlink and executable bits.
4140 With --debug, print file revision hashes.
4140 With --debug, print file revision hashes.
4141
4141
4142 If option --all is specified, the list of all files from all revisions
4142 If option --all is specified, the list of all files from all revisions
4143 is printed. This includes deleted and renamed files.
4143 is printed. This includes deleted and renamed files.
4144
4144
4145 Returns 0 on success.
4145 Returns 0 on success.
4146 """
4146 """
4147 if opts.get('all'):
4147 if opts.get('all'):
4148 if rev or node:
4148 if rev or node:
4149 raise util.Abort(_("can't specify a revision with --all"))
4149 raise util.Abort(_("can't specify a revision with --all"))
4150
4150
4151 res = []
4151 res = []
4152 prefix = "data/"
4152 prefix = "data/"
4153 suffix = ".i"
4153 suffix = ".i"
4154 plen = len(prefix)
4154 plen = len(prefix)
4155 slen = len(suffix)
4155 slen = len(suffix)
4156 lock = repo.lock()
4156 lock = repo.lock()
4157 try:
4157 try:
4158 for fn, b, size in repo.store.datafiles():
4158 for fn, b, size in repo.store.datafiles():
4159 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4159 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4160 res.append(fn[plen:-slen])
4160 res.append(fn[plen:-slen])
4161 finally:
4161 finally:
4162 lock.release()
4162 lock.release()
4163 for f in sorted(res):
4163 for f in sorted(res):
4164 ui.write("%s\n" % f)
4164 ui.write("%s\n" % f)
4165 return
4165 return
4166
4166
4167 if rev and node:
4167 if rev and node:
4168 raise util.Abort(_("please specify just one revision"))
4168 raise util.Abort(_("please specify just one revision"))
4169
4169
4170 if not node:
4170 if not node:
4171 node = rev
4171 node = rev
4172
4172
4173 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4173 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4174 ctx = scmutil.revsingle(repo, node)
4174 ctx = scmutil.revsingle(repo, node)
4175 for f in ctx:
4175 for f in ctx:
4176 if ui.debugflag:
4176 if ui.debugflag:
4177 ui.write("%40s " % hex(ctx.manifest()[f]))
4177 ui.write("%40s " % hex(ctx.manifest()[f]))
4178 if ui.verbose:
4178 if ui.verbose:
4179 ui.write(decor[ctx.flags(f)])
4179 ui.write(decor[ctx.flags(f)])
4180 ui.write("%s\n" % f)
4180 ui.write("%s\n" % f)
4181
4181
4182 @command('^merge',
4182 @command('^merge',
4183 [('f', 'force', None, _('force a merge with outstanding changes')),
4183 [('f', 'force', None, _('force a merge with outstanding changes')),
4184 ('r', 'rev', '', _('revision to merge'), _('REV')),
4184 ('r', 'rev', '', _('revision to merge'), _('REV')),
4185 ('P', 'preview', None,
4185 ('P', 'preview', None,
4186 _('review revisions to merge (no merge is performed)'))
4186 _('review revisions to merge (no merge is performed)'))
4187 ] + mergetoolopts,
4187 ] + mergetoolopts,
4188 _('[-P] [-f] [[-r] REV]'))
4188 _('[-P] [-f] [[-r] REV]'))
4189 def merge(ui, repo, node=None, **opts):
4189 def merge(ui, repo, node=None, **opts):
4190 """merge working directory with another revision
4190 """merge working directory with another revision
4191
4191
4192 The current working directory is updated with all changes made in
4192 The current working directory is updated with all changes made in
4193 the requested revision since the last common predecessor revision.
4193 the requested revision since the last common predecessor revision.
4194
4194
4195 Files that changed between either parent are marked as changed for
4195 Files that changed between either parent are marked as changed for
4196 the next commit and a commit must be performed before any further
4196 the next commit and a commit must be performed before any further
4197 updates to the repository are allowed. The next commit will have
4197 updates to the repository are allowed. The next commit will have
4198 two parents.
4198 two parents.
4199
4199
4200 ``--tool`` can be used to specify the merge tool used for file
4200 ``--tool`` can be used to specify the merge tool used for file
4201 merges. It overrides the HGMERGE environment variable and your
4201 merges. It overrides the HGMERGE environment variable and your
4202 configuration files. See :hg:`help merge-tools` for options.
4202 configuration files. See :hg:`help merge-tools` for options.
4203
4203
4204 If no revision is specified, the working directory's parent is a
4204 If no revision is specified, the working directory's parent is a
4205 head revision, and the current branch contains exactly one other
4205 head revision, and the current branch contains exactly one other
4206 head, the other head is merged with by default. Otherwise, an
4206 head, the other head is merged with by default. Otherwise, an
4207 explicit revision with which to merge with must be provided.
4207 explicit revision with which to merge with must be provided.
4208
4208
4209 :hg:`resolve` must be used to resolve unresolved files.
4209 :hg:`resolve` must be used to resolve unresolved files.
4210
4210
4211 To undo an uncommitted merge, use :hg:`update --clean .` which
4211 To undo an uncommitted merge, use :hg:`update --clean .` which
4212 will check out a clean copy of the original merge parent, losing
4212 will check out a clean copy of the original merge parent, losing
4213 all changes.
4213 all changes.
4214
4214
4215 Returns 0 on success, 1 if there are unresolved files.
4215 Returns 0 on success, 1 if there are unresolved files.
4216 """
4216 """
4217
4217
4218 if opts.get('rev') and node:
4218 if opts.get('rev') and node:
4219 raise util.Abort(_("please specify just one revision"))
4219 raise util.Abort(_("please specify just one revision"))
4220 if not node:
4220 if not node:
4221 node = opts.get('rev')
4221 node = opts.get('rev')
4222
4222
4223 if node:
4223 if node:
4224 node = scmutil.revsingle(repo, node).node()
4224 node = scmutil.revsingle(repo, node).node()
4225
4225
4226 if not node and repo._bookmarkcurrent:
4226 if not node and repo._bookmarkcurrent:
4227 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4227 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4228 curhead = repo[repo._bookmarkcurrent]
4228 curhead = repo[repo._bookmarkcurrent]
4229 if len(bmheads) == 2:
4229 if len(bmheads) == 2:
4230 if curhead == bmheads[0]:
4230 if curhead == bmheads[0]:
4231 node = bmheads[1]
4231 node = bmheads[1]
4232 else:
4232 else:
4233 node = bmheads[0]
4233 node = bmheads[0]
4234 elif len(bmheads) > 2:
4234 elif len(bmheads) > 2:
4235 raise util.Abort(_("multiple matching bookmarks to merge - "
4235 raise util.Abort(_("multiple matching bookmarks to merge - "
4236 "please merge with an explicit rev or bookmark"),
4236 "please merge with an explicit rev or bookmark"),
4237 hint=_("run 'hg heads' to see all heads"))
4237 hint=_("run 'hg heads' to see all heads"))
4238 elif len(bmheads) <= 1:
4238 elif len(bmheads) <= 1:
4239 raise util.Abort(_("no matching bookmark to merge - "
4239 raise util.Abort(_("no matching bookmark to merge - "
4240 "please merge with an explicit rev or bookmark"),
4240 "please merge with an explicit rev or bookmark"),
4241 hint=_("run 'hg heads' to see all heads"))
4241 hint=_("run 'hg heads' to see all heads"))
4242
4242
4243 if not node and not repo._bookmarkcurrent:
4243 if not node and not repo._bookmarkcurrent:
4244 branch = repo[None].branch()
4244 branch = repo[None].branch()
4245 bheads = repo.branchheads(branch)
4245 bheads = repo.branchheads(branch)
4246 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4246 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4247
4247
4248 if len(nbhs) > 2:
4248 if len(nbhs) > 2:
4249 raise util.Abort(_("branch '%s' has %d heads - "
4249 raise util.Abort(_("branch '%s' has %d heads - "
4250 "please merge with an explicit rev")
4250 "please merge with an explicit rev")
4251 % (branch, len(bheads)),
4251 % (branch, len(bheads)),
4252 hint=_("run 'hg heads .' to see heads"))
4252 hint=_("run 'hg heads .' to see heads"))
4253
4253
4254 parent = repo.dirstate.p1()
4254 parent = repo.dirstate.p1()
4255 if len(nbhs) == 1:
4255 if len(nbhs) == 1:
4256 if len(bheads) > 1:
4256 if len(bheads) > 1:
4257 raise util.Abort(_("heads are bookmarked - "
4257 raise util.Abort(_("heads are bookmarked - "
4258 "please merge with an explicit rev"),
4258 "please merge with an explicit rev"),
4259 hint=_("run 'hg heads' to see all heads"))
4259 hint=_("run 'hg heads' to see all heads"))
4260 if len(repo.heads()) > 1:
4260 if len(repo.heads()) > 1:
4261 raise util.Abort(_("branch '%s' has one head - "
4261 raise util.Abort(_("branch '%s' has one head - "
4262 "please merge with an explicit rev")
4262 "please merge with an explicit rev")
4263 % branch,
4263 % branch,
4264 hint=_("run 'hg heads' to see all heads"))
4264 hint=_("run 'hg heads' to see all heads"))
4265 msg, hint = _('nothing to merge'), None
4265 msg, hint = _('nothing to merge'), None
4266 if parent != repo.lookup(branch):
4266 if parent != repo.lookup(branch):
4267 hint = _("use 'hg update' instead")
4267 hint = _("use 'hg update' instead")
4268 raise util.Abort(msg, hint=hint)
4268 raise util.Abort(msg, hint=hint)
4269
4269
4270 if parent not in bheads:
4270 if parent not in bheads:
4271 raise util.Abort(_('working directory not at a head revision'),
4271 raise util.Abort(_('working directory not at a head revision'),
4272 hint=_("use 'hg update' or merge with an "
4272 hint=_("use 'hg update' or merge with an "
4273 "explicit revision"))
4273 "explicit revision"))
4274 if parent == nbhs[0]:
4274 if parent == nbhs[0]:
4275 node = nbhs[-1]
4275 node = nbhs[-1]
4276 else:
4276 else:
4277 node = nbhs[0]
4277 node = nbhs[0]
4278
4278
4279 if opts.get('preview'):
4279 if opts.get('preview'):
4280 # find nodes that are ancestors of p2 but not of p1
4280 # find nodes that are ancestors of p2 but not of p1
4281 p1 = repo.lookup('.')
4281 p1 = repo.lookup('.')
4282 p2 = repo.lookup(node)
4282 p2 = repo.lookup(node)
4283 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4283 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4284
4284
4285 displayer = cmdutil.show_changeset(ui, repo, opts)
4285 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 for node in nodes:
4286 for node in nodes:
4287 displayer.show(repo[node])
4287 displayer.show(repo[node])
4288 displayer.close()
4288 displayer.close()
4289 return 0
4289 return 0
4290
4290
4291 try:
4291 try:
4292 # ui.forcemerge is an internal variable, do not document
4292 # ui.forcemerge is an internal variable, do not document
4293 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4293 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4294 return hg.merge(repo, node, force=opts.get('force'))
4294 return hg.merge(repo, node, force=opts.get('force'))
4295 finally:
4295 finally:
4296 ui.setconfig('ui', 'forcemerge', '')
4296 ui.setconfig('ui', 'forcemerge', '')
4297
4297
4298 @command('outgoing|out',
4298 @command('outgoing|out',
4299 [('f', 'force', None, _('run even when the destination is unrelated')),
4299 [('f', 'force', None, _('run even when the destination is unrelated')),
4300 ('r', 'rev', [],
4300 ('r', 'rev', [],
4301 _('a changeset intended to be included in the destination'), _('REV')),
4301 _('a changeset intended to be included in the destination'), _('REV')),
4302 ('n', 'newest-first', None, _('show newest record first')),
4302 ('n', 'newest-first', None, _('show newest record first')),
4303 ('B', 'bookmarks', False, _('compare bookmarks')),
4303 ('B', 'bookmarks', False, _('compare bookmarks')),
4304 ('b', 'branch', [], _('a specific branch you would like to push'),
4304 ('b', 'branch', [], _('a specific branch you would like to push'),
4305 _('BRANCH')),
4305 _('BRANCH')),
4306 ] + logopts + remoteopts + subrepoopts,
4306 ] + logopts + remoteopts + subrepoopts,
4307 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4307 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4308 def outgoing(ui, repo, dest=None, **opts):
4308 def outgoing(ui, repo, dest=None, **opts):
4309 """show changesets not found in the destination
4309 """show changesets not found in the destination
4310
4310
4311 Show changesets not found in the specified destination repository
4311 Show changesets not found in the specified destination repository
4312 or the default push location. These are the changesets that would
4312 or the default push location. These are the changesets that would
4313 be pushed if a push was requested.
4313 be pushed if a push was requested.
4314
4314
4315 See pull for details of valid destination formats.
4315 See pull for details of valid destination formats.
4316
4316
4317 Returns 0 if there are outgoing changes, 1 otherwise.
4317 Returns 0 if there are outgoing changes, 1 otherwise.
4318 """
4318 """
4319 if opts.get('graph'):
4319 if opts.get('graph'):
4320 cmdutil.checkunsupportedgraphflags([], opts)
4320 cmdutil.checkunsupportedgraphflags([], opts)
4321 o = hg._outgoing(ui, repo, dest, opts)
4321 o = hg._outgoing(ui, repo, dest, opts)
4322 if o is None:
4322 if o is None:
4323 return
4323 return
4324
4324
4325 revdag = cmdutil.graphrevs(repo, o, opts)
4325 revdag = cmdutil.graphrevs(repo, o, opts)
4326 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4326 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4329 graphmod.asciiedges)
4329 graphmod.asciiedges)
4330 return 0
4330 return 0
4331
4331
4332 if opts.get('bookmarks'):
4332 if opts.get('bookmarks'):
4333 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4333 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4334 dest, branches = hg.parseurl(dest, opts.get('branch'))
4334 dest, branches = hg.parseurl(dest, opts.get('branch'))
4335 other = hg.peer(repo, opts, dest)
4335 other = hg.peer(repo, opts, dest)
4336 if 'bookmarks' not in other.listkeys('namespaces'):
4336 if 'bookmarks' not in other.listkeys('namespaces'):
4337 ui.warn(_("remote doesn't support bookmarks\n"))
4337 ui.warn(_("remote doesn't support bookmarks\n"))
4338 return 0
4338 return 0
4339 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4339 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4340 return bookmarks.diff(ui, other, repo)
4340 return bookmarks.diff(ui, other, repo)
4341
4341
4342 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4342 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4343 try:
4343 try:
4344 return hg.outgoing(ui, repo, dest, opts)
4344 return hg.outgoing(ui, repo, dest, opts)
4345 finally:
4345 finally:
4346 del repo._subtoppath
4346 del repo._subtoppath
4347
4347
4348 @command('parents',
4348 @command('parents',
4349 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4349 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4350 ] + templateopts,
4350 ] + templateopts,
4351 _('[-r REV] [FILE]'))
4351 _('[-r REV] [FILE]'))
4352 def parents(ui, repo, file_=None, **opts):
4352 def parents(ui, repo, file_=None, **opts):
4353 """show the parents of the working directory or revision
4353 """show the parents of the working directory or revision
4354
4354
4355 Print the working directory's parent revisions. If a revision is
4355 Print the working directory's parent revisions. If a revision is
4356 given via -r/--rev, the parent of that revision will be printed.
4356 given via -r/--rev, the parent of that revision will be printed.
4357 If a file argument is given, the revision in which the file was
4357 If a file argument is given, the revision in which the file was
4358 last changed (before the working directory revision or the
4358 last changed (before the working directory revision or the
4359 argument to --rev if given) is printed.
4359 argument to --rev if given) is printed.
4360
4360
4361 Returns 0 on success.
4361 Returns 0 on success.
4362 """
4362 """
4363
4363
4364 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4364 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4365
4365
4366 if file_:
4366 if file_:
4367 m = scmutil.match(ctx, (file_,), opts)
4367 m = scmutil.match(ctx, (file_,), opts)
4368 if m.anypats() or len(m.files()) != 1:
4368 if m.anypats() or len(m.files()) != 1:
4369 raise util.Abort(_('can only specify an explicit filename'))
4369 raise util.Abort(_('can only specify an explicit filename'))
4370 file_ = m.files()[0]
4370 file_ = m.files()[0]
4371 filenodes = []
4371 filenodes = []
4372 for cp in ctx.parents():
4372 for cp in ctx.parents():
4373 if not cp:
4373 if not cp:
4374 continue
4374 continue
4375 try:
4375 try:
4376 filenodes.append(cp.filenode(file_))
4376 filenodes.append(cp.filenode(file_))
4377 except error.LookupError:
4377 except error.LookupError:
4378 pass
4378 pass
4379 if not filenodes:
4379 if not filenodes:
4380 raise util.Abort(_("'%s' not found in manifest!") % file_)
4380 raise util.Abort(_("'%s' not found in manifest!") % file_)
4381 fl = repo.file(file_)
4381 fl = repo.file(file_)
4382 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4382 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4383 else:
4383 else:
4384 p = [cp.node() for cp in ctx.parents()]
4384 p = [cp.node() for cp in ctx.parents()]
4385
4385
4386 displayer = cmdutil.show_changeset(ui, repo, opts)
4386 displayer = cmdutil.show_changeset(ui, repo, opts)
4387 for n in p:
4387 for n in p:
4388 if n != nullid:
4388 if n != nullid:
4389 displayer.show(repo[n])
4389 displayer.show(repo[n])
4390 displayer.close()
4390 displayer.close()
4391
4391
4392 @command('paths', [], _('[NAME]'))
4392 @command('paths', [], _('[NAME]'))
4393 def paths(ui, repo, search=None):
4393 def paths(ui, repo, search=None):
4394 """show aliases for remote repositories
4394 """show aliases for remote repositories
4395
4395
4396 Show definition of symbolic path name NAME. If no name is given,
4396 Show definition of symbolic path name NAME. If no name is given,
4397 show definition of all available names.
4397 show definition of all available names.
4398
4398
4399 Option -q/--quiet suppresses all output when searching for NAME
4399 Option -q/--quiet suppresses all output when searching for NAME
4400 and shows only the path names when listing all definitions.
4400 and shows only the path names when listing all definitions.
4401
4401
4402 Path names are defined in the [paths] section of your
4402 Path names are defined in the [paths] section of your
4403 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4403 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4404 repository, ``.hg/hgrc`` is used, too.
4404 repository, ``.hg/hgrc`` is used, too.
4405
4405
4406 The path names ``default`` and ``default-push`` have a special
4406 The path names ``default`` and ``default-push`` have a special
4407 meaning. When performing a push or pull operation, they are used
4407 meaning. When performing a push or pull operation, they are used
4408 as fallbacks if no location is specified on the command-line.
4408 as fallbacks if no location is specified on the command-line.
4409 When ``default-push`` is set, it will be used for push and
4409 When ``default-push`` is set, it will be used for push and
4410 ``default`` will be used for pull; otherwise ``default`` is used
4410 ``default`` will be used for pull; otherwise ``default`` is used
4411 as the fallback for both. When cloning a repository, the clone
4411 as the fallback for both. When cloning a repository, the clone
4412 source is written as ``default`` in ``.hg/hgrc``. Note that
4412 source is written as ``default`` in ``.hg/hgrc``. Note that
4413 ``default`` and ``default-push`` apply to all inbound (e.g.
4413 ``default`` and ``default-push`` apply to all inbound (e.g.
4414 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4414 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4415 :hg:`bundle`) operations.
4415 :hg:`bundle`) operations.
4416
4416
4417 See :hg:`help urls` for more information.
4417 See :hg:`help urls` for more information.
4418
4418
4419 Returns 0 on success.
4419 Returns 0 on success.
4420 """
4420 """
4421 if search:
4421 if search:
4422 for name, path in ui.configitems("paths"):
4422 for name, path in ui.configitems("paths"):
4423 if name == search:
4423 if name == search:
4424 ui.status("%s\n" % util.hidepassword(path))
4424 ui.status("%s\n" % util.hidepassword(path))
4425 return
4425 return
4426 if not ui.quiet:
4426 if not ui.quiet:
4427 ui.warn(_("not found!\n"))
4427 ui.warn(_("not found!\n"))
4428 return 1
4428 return 1
4429 else:
4429 else:
4430 for name, path in ui.configitems("paths"):
4430 for name, path in ui.configitems("paths"):
4431 if ui.quiet:
4431 if ui.quiet:
4432 ui.write("%s\n" % name)
4432 ui.write("%s\n" % name)
4433 else:
4433 else:
4434 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4434 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4435
4435
4436 @command('^phase',
4436 @command('^phase',
4437 [('p', 'public', False, _('set changeset phase to public')),
4437 [('p', 'public', False, _('set changeset phase to public')),
4438 ('d', 'draft', False, _('set changeset phase to draft')),
4438 ('d', 'draft', False, _('set changeset phase to draft')),
4439 ('s', 'secret', False, _('set changeset phase to secret')),
4439 ('s', 'secret', False, _('set changeset phase to secret')),
4440 ('f', 'force', False, _('allow to move boundary backward')),
4440 ('f', 'force', False, _('allow to move boundary backward')),
4441 ('r', 'rev', [], _('target revision'), _('REV')),
4441 ('r', 'rev', [], _('target revision'), _('REV')),
4442 ],
4442 ],
4443 _('[-p|-d|-s] [-f] [-r] REV...'))
4443 _('[-p|-d|-s] [-f] [-r] REV...'))
4444 def phase(ui, repo, *revs, **opts):
4444 def phase(ui, repo, *revs, **opts):
4445 """set or show the current phase name
4445 """set or show the current phase name
4446
4446
4447 With no argument, show the phase name of specified revisions.
4447 With no argument, show the phase name of specified revisions.
4448
4448
4449 With one of -p/--public, -d/--draft or -s/--secret, change the
4449 With one of -p/--public, -d/--draft or -s/--secret, change the
4450 phase value of the specified revisions.
4450 phase value of the specified revisions.
4451
4451
4452 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4452 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4453 lower phase to an higher phase. Phases are ordered as follows::
4453 lower phase to an higher phase. Phases are ordered as follows::
4454
4454
4455 public < draft < secret
4455 public < draft < secret
4456
4456
4457 Return 0 on success, 1 if no phases were changed or some could not
4457 Return 0 on success, 1 if no phases were changed or some could not
4458 be changed.
4458 be changed.
4459 """
4459 """
4460 # search for a unique phase argument
4460 # search for a unique phase argument
4461 targetphase = None
4461 targetphase = None
4462 for idx, name in enumerate(phases.phasenames):
4462 for idx, name in enumerate(phases.phasenames):
4463 if opts[name]:
4463 if opts[name]:
4464 if targetphase is not None:
4464 if targetphase is not None:
4465 raise util.Abort(_('only one phase can be specified'))
4465 raise util.Abort(_('only one phase can be specified'))
4466 targetphase = idx
4466 targetphase = idx
4467
4467
4468 # look for specified revision
4468 # look for specified revision
4469 revs = list(revs)
4469 revs = list(revs)
4470 revs.extend(opts['rev'])
4470 revs.extend(opts['rev'])
4471 if not revs:
4471 if not revs:
4472 raise util.Abort(_('no revisions specified'))
4472 raise util.Abort(_('no revisions specified'))
4473
4473
4474 revs = scmutil.revrange(repo, revs)
4474 revs = scmutil.revrange(repo, revs)
4475
4475
4476 lock = None
4476 lock = None
4477 ret = 0
4477 ret = 0
4478 if targetphase is None:
4478 if targetphase is None:
4479 # display
4479 # display
4480 for r in revs:
4480 for r in revs:
4481 ctx = repo[r]
4481 ctx = repo[r]
4482 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4482 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4483 else:
4483 else:
4484 lock = repo.lock()
4484 lock = repo.lock()
4485 try:
4485 try:
4486 # set phase
4486 # set phase
4487 if not revs:
4487 if not revs:
4488 raise util.Abort(_('empty revision set'))
4488 raise util.Abort(_('empty revision set'))
4489 nodes = [repo[r].node() for r in revs]
4489 nodes = [repo[r].node() for r in revs]
4490 olddata = repo._phasecache.getphaserevs(repo)[:]
4490 olddata = repo._phasecache.getphaserevs(repo)[:]
4491 phases.advanceboundary(repo, targetphase, nodes)
4491 phases.advanceboundary(repo, targetphase, nodes)
4492 if opts['force']:
4492 if opts['force']:
4493 phases.retractboundary(repo, targetphase, nodes)
4493 phases.retractboundary(repo, targetphase, nodes)
4494 finally:
4494 finally:
4495 lock.release()
4495 lock.release()
4496 newdata = repo._phasecache.getphaserevs(repo)
4496 newdata = repo._phasecache.getphaserevs(repo)
4497 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4497 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4498 rejected = [n for n in nodes
4498 rejected = [n for n in nodes
4499 if newdata[repo[n].rev()] < targetphase]
4499 if newdata[repo[n].rev()] < targetphase]
4500 if rejected:
4500 if rejected:
4501 ui.warn(_('cannot move %i changesets to a more permissive '
4501 ui.warn(_('cannot move %i changesets to a more permissive '
4502 'phase, use --force\n') % len(rejected))
4502 'phase, use --force\n') % len(rejected))
4503 ret = 1
4503 ret = 1
4504 if changes:
4504 if changes:
4505 msg = _('phase changed for %i changesets\n') % changes
4505 msg = _('phase changed for %i changesets\n') % changes
4506 if ret:
4506 if ret:
4507 ui.status(msg)
4507 ui.status(msg)
4508 else:
4508 else:
4509 ui.note(msg)
4509 ui.note(msg)
4510 else:
4510 else:
4511 ui.warn(_('no phases changed\n'))
4511 ui.warn(_('no phases changed\n'))
4512 ret = 1
4512 ret = 1
4513 return ret
4513 return ret
4514
4514
4515 def postincoming(ui, repo, modheads, optupdate, checkout):
4515 def postincoming(ui, repo, modheads, optupdate, checkout):
4516 if modheads == 0:
4516 if modheads == 0:
4517 return
4517 return
4518 if optupdate:
4518 if optupdate:
4519 movemarkfrom = repo['.'].node()
4519 movemarkfrom = repo['.'].node()
4520 try:
4520 try:
4521 ret = hg.update(repo, checkout)
4521 ret = hg.update(repo, checkout)
4522 except util.Abort, inst:
4522 except util.Abort, inst:
4523 ui.warn(_("not updating: %s\n") % str(inst))
4523 ui.warn(_("not updating: %s\n") % str(inst))
4524 return 0
4524 return 0
4525 if not ret and not checkout:
4525 if not ret and not checkout:
4526 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4526 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4527 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4527 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4528 return ret
4528 return ret
4529 if modheads > 1:
4529 if modheads > 1:
4530 currentbranchheads = len(repo.branchheads())
4530 currentbranchheads = len(repo.branchheads())
4531 if currentbranchheads == modheads:
4531 if currentbranchheads == modheads:
4532 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4532 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4533 elif currentbranchheads > 1:
4533 elif currentbranchheads > 1:
4534 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4534 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4535 "merge)\n"))
4535 "merge)\n"))
4536 else:
4536 else:
4537 ui.status(_("(run 'hg heads' to see heads)\n"))
4537 ui.status(_("(run 'hg heads' to see heads)\n"))
4538 else:
4538 else:
4539 ui.status(_("(run 'hg update' to get a working copy)\n"))
4539 ui.status(_("(run 'hg update' to get a working copy)\n"))
4540
4540
4541 @command('^pull',
4541 @command('^pull',
4542 [('u', 'update', None,
4542 [('u', 'update', None,
4543 _('update to new branch head if changesets were pulled')),
4543 _('update to new branch head if changesets were pulled')),
4544 ('f', 'force', None, _('run even when remote repository is unrelated')),
4544 ('f', 'force', None, _('run even when remote repository is unrelated')),
4545 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4545 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4546 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4546 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4547 ('b', 'branch', [], _('a specific branch you would like to pull'),
4547 ('b', 'branch', [], _('a specific branch you would like to pull'),
4548 _('BRANCH')),
4548 _('BRANCH')),
4549 ] + remoteopts,
4549 ] + remoteopts,
4550 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4550 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4551 def pull(ui, repo, source="default", **opts):
4551 def pull(ui, repo, source="default", **opts):
4552 """pull changes from the specified source
4552 """pull changes from the specified source
4553
4553
4554 Pull changes from a remote repository to a local one.
4554 Pull changes from a remote repository to a local one.
4555
4555
4556 This finds all changes from the repository at the specified path
4556 This finds all changes from the repository at the specified path
4557 or URL and adds them to a local repository (the current one unless
4557 or URL and adds them to a local repository (the current one unless
4558 -R is specified). By default, this does not update the copy of the
4558 -R is specified). By default, this does not update the copy of the
4559 project in the working directory.
4559 project in the working directory.
4560
4560
4561 Use :hg:`incoming` if you want to see what would have been added
4561 Use :hg:`incoming` if you want to see what would have been added
4562 by a pull at the time you issued this command. If you then decide
4562 by a pull at the time you issued this command. If you then decide
4563 to add those changes to the repository, you should use :hg:`pull
4563 to add those changes to the repository, you should use :hg:`pull
4564 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4564 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4565
4565
4566 If SOURCE is omitted, the 'default' path will be used.
4566 If SOURCE is omitted, the 'default' path will be used.
4567 See :hg:`help urls` for more information.
4567 See :hg:`help urls` for more information.
4568
4568
4569 Returns 0 on success, 1 if an update had unresolved files.
4569 Returns 0 on success, 1 if an update had unresolved files.
4570 """
4570 """
4571 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4571 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4572 other = hg.peer(repo, opts, source)
4572 other = hg.peer(repo, opts, source)
4573 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4573 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4574 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4574 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4575
4575
4576 if opts.get('bookmark'):
4576 if opts.get('bookmark'):
4577 if not revs:
4577 if not revs:
4578 revs = []
4578 revs = []
4579 rb = other.listkeys('bookmarks')
4579 rb = other.listkeys('bookmarks')
4580 for b in opts['bookmark']:
4580 for b in opts['bookmark']:
4581 if b not in rb:
4581 if b not in rb:
4582 raise util.Abort(_('remote bookmark %s not found!') % b)
4582 raise util.Abort(_('remote bookmark %s not found!') % b)
4583 revs.append(rb[b])
4583 revs.append(rb[b])
4584
4584
4585 if revs:
4585 if revs:
4586 try:
4586 try:
4587 revs = [other.lookup(rev) for rev in revs]
4587 revs = [other.lookup(rev) for rev in revs]
4588 except error.CapabilityError:
4588 except error.CapabilityError:
4589 err = _("other repository doesn't support revision lookup, "
4589 err = _("other repository doesn't support revision lookup, "
4590 "so a rev cannot be specified.")
4590 "so a rev cannot be specified.")
4591 raise util.Abort(err)
4591 raise util.Abort(err)
4592
4592
4593 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4593 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4594 bookmarks.updatefromremote(ui, repo, other, source)
4594 bookmarks.updatefromremote(ui, repo, other, source)
4595 if checkout:
4595 if checkout:
4596 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4596 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4597 repo._subtoppath = source
4597 repo._subtoppath = source
4598 try:
4598 try:
4599 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4599 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4600
4600
4601 finally:
4601 finally:
4602 del repo._subtoppath
4602 del repo._subtoppath
4603
4603
4604 # update specified bookmarks
4604 # update specified bookmarks
4605 if opts.get('bookmark'):
4605 if opts.get('bookmark'):
4606 for b in opts['bookmark']:
4606 for b in opts['bookmark']:
4607 # explicit pull overrides local bookmark if any
4607 # explicit pull overrides local bookmark if any
4608 ui.status(_("importing bookmark %s\n") % b)
4608 ui.status(_("importing bookmark %s\n") % b)
4609 repo._bookmarks[b] = repo[rb[b]].node()
4609 repo._bookmarks[b] = repo[rb[b]].node()
4610 bookmarks.write(repo)
4610 bookmarks.write(repo)
4611
4611
4612 return ret
4612 return ret
4613
4613
4614 @command('^push',
4614 @command('^push',
4615 [('f', 'force', None, _('force push')),
4615 [('f', 'force', None, _('force push')),
4616 ('r', 'rev', [],
4616 ('r', 'rev', [],
4617 _('a changeset intended to be included in the destination'),
4617 _('a changeset intended to be included in the destination'),
4618 _('REV')),
4618 _('REV')),
4619 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4619 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4620 ('b', 'branch', [],
4620 ('b', 'branch', [],
4621 _('a specific branch you would like to push'), _('BRANCH')),
4621 _('a specific branch you would like to push'), _('BRANCH')),
4622 ('', 'new-branch', False, _('allow pushing a new branch')),
4622 ('', 'new-branch', False, _('allow pushing a new branch')),
4623 ] + remoteopts,
4623 ] + remoteopts,
4624 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4624 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4625 def push(ui, repo, dest=None, **opts):
4625 def push(ui, repo, dest=None, **opts):
4626 """push changes to the specified destination
4626 """push changes to the specified destination
4627
4627
4628 Push changesets from the local repository to the specified
4628 Push changesets from the local repository to the specified
4629 destination.
4629 destination.
4630
4630
4631 This operation is symmetrical to pull: it is identical to a pull
4631 This operation is symmetrical to pull: it is identical to a pull
4632 in the destination repository from the current one.
4632 in the destination repository from the current one.
4633
4633
4634 By default, push will not allow creation of new heads at the
4634 By default, push will not allow creation of new heads at the
4635 destination, since multiple heads would make it unclear which head
4635 destination, since multiple heads would make it unclear which head
4636 to use. In this situation, it is recommended to pull and merge
4636 to use. In this situation, it is recommended to pull and merge
4637 before pushing.
4637 before pushing.
4638
4638
4639 Use --new-branch if you want to allow push to create a new named
4639 Use --new-branch if you want to allow push to create a new named
4640 branch that is not present at the destination. This allows you to
4640 branch that is not present at the destination. This allows you to
4641 only create a new branch without forcing other changes.
4641 only create a new branch without forcing other changes.
4642
4642
4643 Use -f/--force to override the default behavior and push all
4643 Use -f/--force to override the default behavior and push all
4644 changesets on all branches.
4644 changesets on all branches.
4645
4645
4646 If -r/--rev is used, the specified revision and all its ancestors
4646 If -r/--rev is used, the specified revision and all its ancestors
4647 will be pushed to the remote repository.
4647 will be pushed to the remote repository.
4648
4648
4649 If -B/--bookmark is used, the specified bookmarked revision, its
4649 If -B/--bookmark is used, the specified bookmarked revision, its
4650 ancestors, and the bookmark will be pushed to the remote
4650 ancestors, and the bookmark will be pushed to the remote
4651 repository.
4651 repository.
4652
4652
4653 Please see :hg:`help urls` for important details about ``ssh://``
4653 Please see :hg:`help urls` for important details about ``ssh://``
4654 URLs. If DESTINATION is omitted, a default path will be used.
4654 URLs. If DESTINATION is omitted, a default path will be used.
4655
4655
4656 Returns 0 if push was successful, 1 if nothing to push.
4656 Returns 0 if push was successful, 1 if nothing to push.
4657 """
4657 """
4658
4658
4659 if opts.get('bookmark'):
4659 if opts.get('bookmark'):
4660 for b in opts['bookmark']:
4660 for b in opts['bookmark']:
4661 # translate -B options to -r so changesets get pushed
4661 # translate -B options to -r so changesets get pushed
4662 if b in repo._bookmarks:
4662 if b in repo._bookmarks:
4663 opts.setdefault('rev', []).append(b)
4663 opts.setdefault('rev', []).append(b)
4664 else:
4664 else:
4665 # if we try to push a deleted bookmark, translate it to null
4665 # if we try to push a deleted bookmark, translate it to null
4666 # this lets simultaneous -r, -b options continue working
4666 # this lets simultaneous -r, -b options continue working
4667 opts.setdefault('rev', []).append("null")
4667 opts.setdefault('rev', []).append("null")
4668
4668
4669 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4669 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4670 dest, branches = hg.parseurl(dest, opts.get('branch'))
4670 dest, branches = hg.parseurl(dest, opts.get('branch'))
4671 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4671 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4672 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4672 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4673 other = hg.peer(repo, opts, dest)
4673 other = hg.peer(repo, opts, dest)
4674 if revs:
4674 if revs:
4675 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4675 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4676
4676
4677 repo._subtoppath = dest
4677 repo._subtoppath = dest
4678 try:
4678 try:
4679 # push subrepos depth-first for coherent ordering
4679 # push subrepos depth-first for coherent ordering
4680 c = repo['']
4680 c = repo['']
4681 subs = c.substate # only repos that are committed
4681 subs = c.substate # only repos that are committed
4682 for s in sorted(subs):
4682 for s in sorted(subs):
4683 if c.sub(s).push(opts) == 0:
4683 if c.sub(s).push(opts) == 0:
4684 return False
4684 return False
4685 finally:
4685 finally:
4686 del repo._subtoppath
4686 del repo._subtoppath
4687 result = repo.push(other, opts.get('force'), revs=revs,
4687 result = repo.push(other, opts.get('force'), revs=revs,
4688 newbranch=opts.get('new_branch'))
4688 newbranch=opts.get('new_branch'))
4689
4689
4690 result = not result
4690 result = not result
4691
4691
4692 if opts.get('bookmark'):
4692 if opts.get('bookmark'):
4693 rb = other.listkeys('bookmarks')
4693 rb = other.listkeys('bookmarks')
4694 for b in opts['bookmark']:
4694 for b in opts['bookmark']:
4695 # explicit push overrides remote bookmark if any
4695 # explicit push overrides remote bookmark if any
4696 if b in repo._bookmarks:
4696 if b in repo._bookmarks:
4697 ui.status(_("exporting bookmark %s\n") % b)
4697 ui.status(_("exporting bookmark %s\n") % b)
4698 new = repo[b].hex()
4698 new = repo[b].hex()
4699 elif b in rb:
4699 elif b in rb:
4700 ui.status(_("deleting remote bookmark %s\n") % b)
4700 ui.status(_("deleting remote bookmark %s\n") % b)
4701 new = '' # delete
4701 new = '' # delete
4702 else:
4702 else:
4703 ui.warn(_('bookmark %s does not exist on the local '
4703 ui.warn(_('bookmark %s does not exist on the local '
4704 'or remote repository!\n') % b)
4704 'or remote repository!\n') % b)
4705 return 2
4705 return 2
4706 old = rb.get(b, '')
4706 old = rb.get(b, '')
4707 r = other.pushkey('bookmarks', b, old, new)
4707 r = other.pushkey('bookmarks', b, old, new)
4708 if not r:
4708 if not r:
4709 ui.warn(_('updating bookmark %s failed!\n') % b)
4709 ui.warn(_('updating bookmark %s failed!\n') % b)
4710 if not result:
4710 if not result:
4711 result = 2
4711 result = 2
4712
4712
4713 return result
4713 return result
4714
4714
4715 @command('recover', [])
4715 @command('recover', [])
4716 def recover(ui, repo):
4716 def recover(ui, repo):
4717 """roll back an interrupted transaction
4717 """roll back an interrupted transaction
4718
4718
4719 Recover from an interrupted commit or pull.
4719 Recover from an interrupted commit or pull.
4720
4720
4721 This command tries to fix the repository status after an
4721 This command tries to fix the repository status after an
4722 interrupted operation. It should only be necessary when Mercurial
4722 interrupted operation. It should only be necessary when Mercurial
4723 suggests it.
4723 suggests it.
4724
4724
4725 Returns 0 if successful, 1 if nothing to recover or verify fails.
4725 Returns 0 if successful, 1 if nothing to recover or verify fails.
4726 """
4726 """
4727 if repo.recover():
4727 if repo.recover():
4728 return hg.verify(repo)
4728 return hg.verify(repo)
4729 return 1
4729 return 1
4730
4730
4731 @command('^remove|rm',
4731 @command('^remove|rm',
4732 [('A', 'after', None, _('record delete for missing files')),
4732 [('A', 'after', None, _('record delete for missing files')),
4733 ('f', 'force', None,
4733 ('f', 'force', None,
4734 _('remove (and delete) file even if added or modified')),
4734 _('remove (and delete) file even if added or modified')),
4735 ] + walkopts,
4735 ] + walkopts,
4736 _('[OPTION]... FILE...'))
4736 _('[OPTION]... FILE...'))
4737 def remove(ui, repo, *pats, **opts):
4737 def remove(ui, repo, *pats, **opts):
4738 """remove the specified files on the next commit
4738 """remove the specified files on the next commit
4739
4739
4740 Schedule the indicated files for removal from the current branch.
4740 Schedule the indicated files for removal from the current branch.
4741
4741
4742 This command schedules the files to be removed at the next commit.
4742 This command schedules the files to be removed at the next commit.
4743 To undo a remove before that, see :hg:`revert`. To undo added
4743 To undo a remove before that, see :hg:`revert`. To undo added
4744 files, see :hg:`forget`.
4744 files, see :hg:`forget`.
4745
4745
4746 .. container:: verbose
4746 .. container:: verbose
4747
4747
4748 -A/--after can be used to remove only files that have already
4748 -A/--after can be used to remove only files that have already
4749 been deleted, -f/--force can be used to force deletion, and -Af
4749 been deleted, -f/--force can be used to force deletion, and -Af
4750 can be used to remove files from the next revision without
4750 can be used to remove files from the next revision without
4751 deleting them from the working directory.
4751 deleting them from the working directory.
4752
4752
4753 The following table details the behavior of remove for different
4753 The following table details the behavior of remove for different
4754 file states (columns) and option combinations (rows). The file
4754 file states (columns) and option combinations (rows). The file
4755 states are Added [A], Clean [C], Modified [M] and Missing [!]
4755 states are Added [A], Clean [C], Modified [M] and Missing [!]
4756 (as reported by :hg:`status`). The actions are Warn, Remove
4756 (as reported by :hg:`status`). The actions are Warn, Remove
4757 (from branch) and Delete (from disk):
4757 (from branch) and Delete (from disk):
4758
4758
4759 ======= == == == ==
4759 ======= == == == ==
4760 A C M !
4760 A C M !
4761 ======= == == == ==
4761 ======= == == == ==
4762 none W RD W R
4762 none W RD W R
4763 -f R RD RD R
4763 -f R RD RD R
4764 -A W W W R
4764 -A W W W R
4765 -Af R R R R
4765 -Af R R R R
4766 ======= == == == ==
4766 ======= == == == ==
4767
4767
4768 Note that remove never deletes files in Added [A] state from the
4768 Note that remove never deletes files in Added [A] state from the
4769 working directory, not even if option --force is specified.
4769 working directory, not even if option --force is specified.
4770
4770
4771 Returns 0 on success, 1 if any warnings encountered.
4771 Returns 0 on success, 1 if any warnings encountered.
4772 """
4772 """
4773
4773
4774 ret = 0
4774 ret = 0
4775 after, force = opts.get('after'), opts.get('force')
4775 after, force = opts.get('after'), opts.get('force')
4776 if not pats and not after:
4776 if not pats and not after:
4777 raise util.Abort(_('no files specified'))
4777 raise util.Abort(_('no files specified'))
4778
4778
4779 m = scmutil.match(repo[None], pats, opts)
4779 m = scmutil.match(repo[None], pats, opts)
4780 s = repo.status(match=m, clean=True)
4780 s = repo.status(match=m, clean=True)
4781 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4781 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4782
4782
4783 for f in m.files():
4783 for f in m.files():
4784 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4784 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4785 if os.path.exists(m.rel(f)):
4785 if os.path.exists(m.rel(f)):
4786 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4786 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4787 ret = 1
4787 ret = 1
4788
4788
4789 if force:
4789 if force:
4790 list = modified + deleted + clean + added
4790 list = modified + deleted + clean + added
4791 elif after:
4791 elif after:
4792 list = deleted
4792 list = deleted
4793 for f in modified + added + clean:
4793 for f in modified + added + clean:
4794 ui.warn(_('not removing %s: file still exists (use -f'
4794 ui.warn(_('not removing %s: file still exists (use -f'
4795 ' to force removal)\n') % m.rel(f))
4795 ' to force removal)\n') % m.rel(f))
4796 ret = 1
4796 ret = 1
4797 else:
4797 else:
4798 list = deleted + clean
4798 list = deleted + clean
4799 for f in modified:
4799 for f in modified:
4800 ui.warn(_('not removing %s: file is modified (use -f'
4800 ui.warn(_('not removing %s: file is modified (use -f'
4801 ' to force removal)\n') % m.rel(f))
4801 ' to force removal)\n') % m.rel(f))
4802 ret = 1
4802 ret = 1
4803 for f in added:
4803 for f in added:
4804 ui.warn(_('not removing %s: file has been marked for add'
4804 ui.warn(_('not removing %s: file has been marked for add'
4805 ' (use forget to undo)\n') % m.rel(f))
4805 ' (use forget to undo)\n') % m.rel(f))
4806 ret = 1
4806 ret = 1
4807
4807
4808 for f in sorted(list):
4808 for f in sorted(list):
4809 if ui.verbose or not m.exact(f):
4809 if ui.verbose or not m.exact(f):
4810 ui.status(_('removing %s\n') % m.rel(f))
4810 ui.status(_('removing %s\n') % m.rel(f))
4811
4811
4812 wlock = repo.wlock()
4812 wlock = repo.wlock()
4813 try:
4813 try:
4814 if not after:
4814 if not after:
4815 for f in list:
4815 for f in list:
4816 if f in added:
4816 if f in added:
4817 continue # we never unlink added files on remove
4817 continue # we never unlink added files on remove
4818 try:
4818 try:
4819 util.unlinkpath(repo.wjoin(f))
4819 util.unlinkpath(repo.wjoin(f))
4820 except OSError, inst:
4820 except OSError, inst:
4821 if inst.errno != errno.ENOENT:
4821 if inst.errno != errno.ENOENT:
4822 raise
4822 raise
4823 repo[None].forget(list)
4823 repo[None].forget(list)
4824 finally:
4824 finally:
4825 wlock.release()
4825 wlock.release()
4826
4826
4827 return ret
4827 return ret
4828
4828
4829 @command('rename|move|mv',
4829 @command('rename|move|mv',
4830 [('A', 'after', None, _('record a rename that has already occurred')),
4830 [('A', 'after', None, _('record a rename that has already occurred')),
4831 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4831 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4832 ] + walkopts + dryrunopts,
4832 ] + walkopts + dryrunopts,
4833 _('[OPTION]... SOURCE... DEST'))
4833 _('[OPTION]... SOURCE... DEST'))
4834 def rename(ui, repo, *pats, **opts):
4834 def rename(ui, repo, *pats, **opts):
4835 """rename files; equivalent of copy + remove
4835 """rename files; equivalent of copy + remove
4836
4836
4837 Mark dest as copies of sources; mark sources for deletion. If dest
4837 Mark dest as copies of sources; mark sources for deletion. If dest
4838 is a directory, copies are put in that directory. If dest is a
4838 is a directory, copies are put in that directory. If dest is a
4839 file, there can only be one source.
4839 file, there can only be one source.
4840
4840
4841 By default, this command copies the contents of files as they
4841 By default, this command copies the contents of files as they
4842 exist in the working directory. If invoked with -A/--after, the
4842 exist in the working directory. If invoked with -A/--after, the
4843 operation is recorded, but no copying is performed.
4843 operation is recorded, but no copying is performed.
4844
4844
4845 This command takes effect at the next commit. To undo a rename
4845 This command takes effect at the next commit. To undo a rename
4846 before that, see :hg:`revert`.
4846 before that, see :hg:`revert`.
4847
4847
4848 Returns 0 on success, 1 if errors are encountered.
4848 Returns 0 on success, 1 if errors are encountered.
4849 """
4849 """
4850 wlock = repo.wlock(False)
4850 wlock = repo.wlock(False)
4851 try:
4851 try:
4852 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4852 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4853 finally:
4853 finally:
4854 wlock.release()
4854 wlock.release()
4855
4855
4856 @command('resolve',
4856 @command('resolve',
4857 [('a', 'all', None, _('select all unresolved files')),
4857 [('a', 'all', None, _('select all unresolved files')),
4858 ('l', 'list', None, _('list state of files needing merge')),
4858 ('l', 'list', None, _('list state of files needing merge')),
4859 ('m', 'mark', None, _('mark files as resolved')),
4859 ('m', 'mark', None, _('mark files as resolved')),
4860 ('u', 'unmark', None, _('mark files as unresolved')),
4860 ('u', 'unmark', None, _('mark files as unresolved')),
4861 ('n', 'no-status', None, _('hide status prefix'))]
4861 ('n', 'no-status', None, _('hide status prefix'))]
4862 + mergetoolopts + walkopts,
4862 + mergetoolopts + walkopts,
4863 _('[OPTION]... [FILE]...'))
4863 _('[OPTION]... [FILE]...'))
4864 def resolve(ui, repo, *pats, **opts):
4864 def resolve(ui, repo, *pats, **opts):
4865 """redo merges or set/view the merge status of files
4865 """redo merges or set/view the merge status of files
4866
4866
4867 Merges with unresolved conflicts are often the result of
4867 Merges with unresolved conflicts are often the result of
4868 non-interactive merging using the ``internal:merge`` configuration
4868 non-interactive merging using the ``internal:merge`` configuration
4869 setting, or a command-line merge tool like ``diff3``. The resolve
4869 setting, or a command-line merge tool like ``diff3``. The resolve
4870 command is used to manage the files involved in a merge, after
4870 command is used to manage the files involved in a merge, after
4871 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4871 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4872 working directory must have two parents). See :hg:`help
4872 working directory must have two parents). See :hg:`help
4873 merge-tools` for information on configuring merge tools.
4873 merge-tools` for information on configuring merge tools.
4874
4874
4875 The resolve command can be used in the following ways:
4875 The resolve command can be used in the following ways:
4876
4876
4877 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4877 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4878 files, discarding any previous merge attempts. Re-merging is not
4878 files, discarding any previous merge attempts. Re-merging is not
4879 performed for files already marked as resolved. Use ``--all/-a``
4879 performed for files already marked as resolved. Use ``--all/-a``
4880 to select all unresolved files. ``--tool`` can be used to specify
4880 to select all unresolved files. ``--tool`` can be used to specify
4881 the merge tool used for the given files. It overrides the HGMERGE
4881 the merge tool used for the given files. It overrides the HGMERGE
4882 environment variable and your configuration files. Previous file
4882 environment variable and your configuration files. Previous file
4883 contents are saved with a ``.orig`` suffix.
4883 contents are saved with a ``.orig`` suffix.
4884
4884
4885 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4885 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4886 (e.g. after having manually fixed-up the files). The default is
4886 (e.g. after having manually fixed-up the files). The default is
4887 to mark all unresolved files.
4887 to mark all unresolved files.
4888
4888
4889 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4889 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4890 default is to mark all resolved files.
4890 default is to mark all resolved files.
4891
4891
4892 - :hg:`resolve -l`: list files which had or still have conflicts.
4892 - :hg:`resolve -l`: list files which had or still have conflicts.
4893 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4893 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4894
4894
4895 Note that Mercurial will not let you commit files with unresolved
4895 Note that Mercurial will not let you commit files with unresolved
4896 merge conflicts. You must use :hg:`resolve -m ...` before you can
4896 merge conflicts. You must use :hg:`resolve -m ...` before you can
4897 commit after a conflicting merge.
4897 commit after a conflicting merge.
4898
4898
4899 Returns 0 on success, 1 if any files fail a resolve attempt.
4899 Returns 0 on success, 1 if any files fail a resolve attempt.
4900 """
4900 """
4901
4901
4902 all, mark, unmark, show, nostatus = \
4902 all, mark, unmark, show, nostatus = \
4903 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4903 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4904
4904
4905 if (show and (mark or unmark)) or (mark and unmark):
4905 if (show and (mark or unmark)) or (mark and unmark):
4906 raise util.Abort(_("too many options specified"))
4906 raise util.Abort(_("too many options specified"))
4907 if pats and all:
4907 if pats and all:
4908 raise util.Abort(_("can't specify --all and patterns"))
4908 raise util.Abort(_("can't specify --all and patterns"))
4909 if not (all or pats or show or mark or unmark):
4909 if not (all or pats or show or mark or unmark):
4910 raise util.Abort(_('no files or directories specified; '
4910 raise util.Abort(_('no files or directories specified; '
4911 'use --all to remerge all files'))
4911 'use --all to remerge all files'))
4912
4912
4913 ms = mergemod.mergestate(repo)
4913 ms = mergemod.mergestate(repo)
4914 m = scmutil.match(repo[None], pats, opts)
4914 m = scmutil.match(repo[None], pats, opts)
4915 ret = 0
4915 ret = 0
4916
4916
4917 for f in ms:
4917 for f in ms:
4918 if m(f):
4918 if m(f):
4919 if show:
4919 if show:
4920 if nostatus:
4920 if nostatus:
4921 ui.write("%s\n" % f)
4921 ui.write("%s\n" % f)
4922 else:
4922 else:
4923 ui.write("%s %s\n" % (ms[f].upper(), f),
4923 ui.write("%s %s\n" % (ms[f].upper(), f),
4924 label='resolve.' +
4924 label='resolve.' +
4925 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4925 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4926 elif mark:
4926 elif mark:
4927 ms.mark(f, "r")
4927 ms.mark(f, "r")
4928 elif unmark:
4928 elif unmark:
4929 ms.mark(f, "u")
4929 ms.mark(f, "u")
4930 else:
4930 else:
4931 wctx = repo[None]
4931 wctx = repo[None]
4932 mctx = wctx.parents()[-1]
4932 mctx = wctx.parents()[-1]
4933
4933
4934 # backup pre-resolve (merge uses .orig for its own purposes)
4934 # backup pre-resolve (merge uses .orig for its own purposes)
4935 a = repo.wjoin(f)
4935 a = repo.wjoin(f)
4936 util.copyfile(a, a + ".resolve")
4936 util.copyfile(a, a + ".resolve")
4937
4937
4938 try:
4938 try:
4939 # resolve file
4939 # resolve file
4940 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4940 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4941 if ms.resolve(f, wctx, mctx):
4941 if ms.resolve(f, wctx, mctx):
4942 ret = 1
4942 ret = 1
4943 finally:
4943 finally:
4944 ui.setconfig('ui', 'forcemerge', '')
4944 ui.setconfig('ui', 'forcemerge', '')
4945
4945
4946 # replace filemerge's .orig file with our resolve file
4946 # replace filemerge's .orig file with our resolve file
4947 util.rename(a + ".resolve", a + ".orig")
4947 util.rename(a + ".resolve", a + ".orig")
4948
4948
4949 ms.commit()
4949 ms.commit()
4950 return ret
4950 return ret
4951
4951
4952 @command('revert',
4952 @command('revert',
4953 [('a', 'all', None, _('revert all changes when no arguments given')),
4953 [('a', 'all', None, _('revert all changes when no arguments given')),
4954 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4954 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4955 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4955 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4956 ('C', 'no-backup', None, _('do not save backup copies of files')),
4956 ('C', 'no-backup', None, _('do not save backup copies of files')),
4957 ] + walkopts + dryrunopts,
4957 ] + walkopts + dryrunopts,
4958 _('[OPTION]... [-r REV] [NAME]...'))
4958 _('[OPTION]... [-r REV] [NAME]...'))
4959 def revert(ui, repo, *pats, **opts):
4959 def revert(ui, repo, *pats, **opts):
4960 """restore files to their checkout state
4960 """restore files to their checkout state
4961
4961
4962 .. note::
4962 .. note::
4963
4963
4964 To check out earlier revisions, you should use :hg:`update REV`.
4964 To check out earlier revisions, you should use :hg:`update REV`.
4965 To cancel an uncommitted merge (and lose your changes), use
4965 To cancel an uncommitted merge (and lose your changes), use
4966 :hg:`update --clean .`.
4966 :hg:`update --clean .`.
4967
4967
4968 With no revision specified, revert the specified files or directories
4968 With no revision specified, revert the specified files or directories
4969 to the contents they had in the parent of the working directory.
4969 to the contents they had in the parent of the working directory.
4970 This restores the contents of files to an unmodified
4970 This restores the contents of files to an unmodified
4971 state and unschedules adds, removes, copies, and renames. If the
4971 state and unschedules adds, removes, copies, and renames. If the
4972 working directory has two parents, you must explicitly specify a
4972 working directory has two parents, you must explicitly specify a
4973 revision.
4973 revision.
4974
4974
4975 Using the -r/--rev or -d/--date options, revert the given files or
4975 Using the -r/--rev or -d/--date options, revert the given files or
4976 directories to their states as of a specific revision. Because
4976 directories to their states as of a specific revision. Because
4977 revert does not change the working directory parents, this will
4977 revert does not change the working directory parents, this will
4978 cause these files to appear modified. This can be helpful to "back
4978 cause these files to appear modified. This can be helpful to "back
4979 out" some or all of an earlier change. See :hg:`backout` for a
4979 out" some or all of an earlier change. See :hg:`backout` for a
4980 related method.
4980 related method.
4981
4981
4982 Modified files are saved with a .orig suffix before reverting.
4982 Modified files are saved with a .orig suffix before reverting.
4983 To disable these backups, use --no-backup.
4983 To disable these backups, use --no-backup.
4984
4984
4985 See :hg:`help dates` for a list of formats valid for -d/--date.
4985 See :hg:`help dates` for a list of formats valid for -d/--date.
4986
4986
4987 Returns 0 on success.
4987 Returns 0 on success.
4988 """
4988 """
4989
4989
4990 if opts.get("date"):
4990 if opts.get("date"):
4991 if opts.get("rev"):
4991 if opts.get("rev"):
4992 raise util.Abort(_("you can't specify a revision and a date"))
4992 raise util.Abort(_("you can't specify a revision and a date"))
4993 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4993 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4994
4994
4995 parent, p2 = repo.dirstate.parents()
4995 parent, p2 = repo.dirstate.parents()
4996 if not opts.get('rev') and p2 != nullid:
4996 if not opts.get('rev') and p2 != nullid:
4997 # revert after merge is a trap for new users (issue2915)
4997 # revert after merge is a trap for new users (issue2915)
4998 raise util.Abort(_('uncommitted merge with no revision specified'),
4998 raise util.Abort(_('uncommitted merge with no revision specified'),
4999 hint=_('use "hg update" or see "hg help revert"'))
4999 hint=_('use "hg update" or see "hg help revert"'))
5000
5000
5001 ctx = scmutil.revsingle(repo, opts.get('rev'))
5001 ctx = scmutil.revsingle(repo, opts.get('rev'))
5002
5002
5003 if not pats and not opts.get('all'):
5003 if not pats and not opts.get('all'):
5004 msg = _("no files or directories specified")
5004 msg = _("no files or directories specified")
5005 if p2 != nullid:
5005 if p2 != nullid:
5006 hint = _("uncommitted merge, use --all to discard all changes,"
5006 hint = _("uncommitted merge, use --all to discard all changes,"
5007 " or 'hg update -C .' to abort the merge")
5007 " or 'hg update -C .' to abort the merge")
5008 raise util.Abort(msg, hint=hint)
5008 raise util.Abort(msg, hint=hint)
5009 dirty = util.any(repo.status())
5009 dirty = util.any(repo.status())
5010 node = ctx.node()
5010 node = ctx.node()
5011 if node != parent:
5011 if node != parent:
5012 if dirty:
5012 if dirty:
5013 hint = _("uncommitted changes, use --all to discard all"
5013 hint = _("uncommitted changes, use --all to discard all"
5014 " changes, or 'hg update %s' to update") % ctx.rev()
5014 " changes, or 'hg update %s' to update") % ctx.rev()
5015 else:
5015 else:
5016 hint = _("use --all to revert all files,"
5016 hint = _("use --all to revert all files,"
5017 " or 'hg update %s' to update") % ctx.rev()
5017 " or 'hg update %s' to update") % ctx.rev()
5018 elif dirty:
5018 elif dirty:
5019 hint = _("uncommitted changes, use --all to discard all changes")
5019 hint = _("uncommitted changes, use --all to discard all changes")
5020 else:
5020 else:
5021 hint = _("use --all to revert all files")
5021 hint = _("use --all to revert all files")
5022 raise util.Abort(msg, hint=hint)
5022 raise util.Abort(msg, hint=hint)
5023
5023
5024 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5024 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5025
5025
5026 @command('rollback', dryrunopts +
5026 @command('rollback', dryrunopts +
5027 [('f', 'force', False, _('ignore safety measures'))])
5027 [('f', 'force', False, _('ignore safety measures'))])
5028 def rollback(ui, repo, **opts):
5028 def rollback(ui, repo, **opts):
5029 """roll back the last transaction (dangerous)
5029 """roll back the last transaction (dangerous)
5030
5030
5031 This command should be used with care. There is only one level of
5031 This command should be used with care. There is only one level of
5032 rollback, and there is no way to undo a rollback. It will also
5032 rollback, and there is no way to undo a rollback. It will also
5033 restore the dirstate at the time of the last transaction, losing
5033 restore the dirstate at the time of the last transaction, losing
5034 any dirstate changes since that time. This command does not alter
5034 any dirstate changes since that time. This command does not alter
5035 the working directory.
5035 the working directory.
5036
5036
5037 Transactions are used to encapsulate the effects of all commands
5037 Transactions are used to encapsulate the effects of all commands
5038 that create new changesets or propagate existing changesets into a
5038 that create new changesets or propagate existing changesets into a
5039 repository.
5039 repository.
5040
5040
5041 .. container:: verbose
5041 .. container:: verbose
5042
5042
5043 For example, the following commands are transactional, and their
5043 For example, the following commands are transactional, and their
5044 effects can be rolled back:
5044 effects can be rolled back:
5045
5045
5046 - commit
5046 - commit
5047 - import
5047 - import
5048 - pull
5048 - pull
5049 - push (with this repository as the destination)
5049 - push (with this repository as the destination)
5050 - unbundle
5050 - unbundle
5051
5051
5052 To avoid permanent data loss, rollback will refuse to rollback a
5052 To avoid permanent data loss, rollback will refuse to rollback a
5053 commit transaction if it isn't checked out. Use --force to
5053 commit transaction if it isn't checked out. Use --force to
5054 override this protection.
5054 override this protection.
5055
5055
5056 This command is not intended for use on public repositories. Once
5056 This command is not intended for use on public repositories. Once
5057 changes are visible for pull by other users, rolling a transaction
5057 changes are visible for pull by other users, rolling a transaction
5058 back locally is ineffective (someone else may already have pulled
5058 back locally is ineffective (someone else may already have pulled
5059 the changes). Furthermore, a race is possible with readers of the
5059 the changes). Furthermore, a race is possible with readers of the
5060 repository; for example an in-progress pull from the repository
5060 repository; for example an in-progress pull from the repository
5061 may fail if a rollback is performed.
5061 may fail if a rollback is performed.
5062
5062
5063 Returns 0 on success, 1 if no rollback data is available.
5063 Returns 0 on success, 1 if no rollback data is available.
5064 """
5064 """
5065 return repo.rollback(dryrun=opts.get('dry_run'),
5065 return repo.rollback(dryrun=opts.get('dry_run'),
5066 force=opts.get('force'))
5066 force=opts.get('force'))
5067
5067
5068 @command('root', [])
5068 @command('root', [])
5069 def root(ui, repo):
5069 def root(ui, repo):
5070 """print the root (top) of the current working directory
5070 """print the root (top) of the current working directory
5071
5071
5072 Print the root directory of the current repository.
5072 Print the root directory of the current repository.
5073
5073
5074 Returns 0 on success.
5074 Returns 0 on success.
5075 """
5075 """
5076 ui.write(repo.root + "\n")
5076 ui.write(repo.root + "\n")
5077
5077
5078 @command('^serve',
5078 @command('^serve',
5079 [('A', 'accesslog', '', _('name of access log file to write to'),
5079 [('A', 'accesslog', '', _('name of access log file to write to'),
5080 _('FILE')),
5080 _('FILE')),
5081 ('d', 'daemon', None, _('run server in background')),
5081 ('d', 'daemon', None, _('run server in background')),
5082 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5082 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5083 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5083 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5084 # use string type, then we can check if something was passed
5084 # use string type, then we can check if something was passed
5085 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5085 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5086 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5086 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5087 _('ADDR')),
5087 _('ADDR')),
5088 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5088 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5089 _('PREFIX')),
5089 _('PREFIX')),
5090 ('n', 'name', '',
5090 ('n', 'name', '',
5091 _('name to show in web pages (default: working directory)'), _('NAME')),
5091 _('name to show in web pages (default: working directory)'), _('NAME')),
5092 ('', 'web-conf', '',
5092 ('', 'web-conf', '',
5093 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5093 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5094 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5094 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5095 _('FILE')),
5095 _('FILE')),
5096 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5096 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5097 ('', 'stdio', None, _('for remote clients')),
5097 ('', 'stdio', None, _('for remote clients')),
5098 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5098 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5099 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5099 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5100 ('', 'style', '', _('template style to use'), _('STYLE')),
5100 ('', 'style', '', _('template style to use'), _('STYLE')),
5101 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5101 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5102 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5102 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5103 _('[OPTION]...'))
5103 _('[OPTION]...'))
5104 def serve(ui, repo, **opts):
5104 def serve(ui, repo, **opts):
5105 """start stand-alone webserver
5105 """start stand-alone webserver
5106
5106
5107 Start a local HTTP repository browser and pull server. You can use
5107 Start a local HTTP repository browser and pull server. You can use
5108 this for ad-hoc sharing and browsing of repositories. It is
5108 this for ad-hoc sharing and browsing of repositories. It is
5109 recommended to use a real web server to serve a repository for
5109 recommended to use a real web server to serve a repository for
5110 longer periods of time.
5110 longer periods of time.
5111
5111
5112 Please note that the server does not implement access control.
5112 Please note that the server does not implement access control.
5113 This means that, by default, anybody can read from the server and
5113 This means that, by default, anybody can read from the server and
5114 nobody can write to it by default. Set the ``web.allow_push``
5114 nobody can write to it by default. Set the ``web.allow_push``
5115 option to ``*`` to allow everybody to push to the server. You
5115 option to ``*`` to allow everybody to push to the server. You
5116 should use a real web server if you need to authenticate users.
5116 should use a real web server if you need to authenticate users.
5117
5117
5118 By default, the server logs accesses to stdout and errors to
5118 By default, the server logs accesses to stdout and errors to
5119 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5119 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5120 files.
5120 files.
5121
5121
5122 To have the server choose a free port number to listen on, specify
5122 To have the server choose a free port number to listen on, specify
5123 a port number of 0; in this case, the server will print the port
5123 a port number of 0; in this case, the server will print the port
5124 number it uses.
5124 number it uses.
5125
5125
5126 Returns 0 on success.
5126 Returns 0 on success.
5127 """
5127 """
5128
5128
5129 if opts["stdio"] and opts["cmdserver"]:
5129 if opts["stdio"] and opts["cmdserver"]:
5130 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5130 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5131
5131
5132 def checkrepo():
5132 def checkrepo():
5133 if repo is None:
5133 if repo is None:
5134 raise error.RepoError(_("there is no Mercurial repository here"
5134 raise error.RepoError(_("there is no Mercurial repository here"
5135 " (.hg not found)"))
5135 " (.hg not found)"))
5136
5136
5137 if opts["stdio"]:
5137 if opts["stdio"]:
5138 checkrepo()
5138 checkrepo()
5139 s = sshserver.sshserver(ui, repo)
5139 s = sshserver.sshserver(ui, repo)
5140 s.serve_forever()
5140 s.serve_forever()
5141
5141
5142 if opts["cmdserver"]:
5142 if opts["cmdserver"]:
5143 checkrepo()
5143 checkrepo()
5144 s = commandserver.server(ui, repo, opts["cmdserver"])
5144 s = commandserver.server(ui, repo, opts["cmdserver"])
5145 return s.serve()
5145 return s.serve()
5146
5146
5147 # this way we can check if something was given in the command-line
5147 # this way we can check if something was given in the command-line
5148 if opts.get('port'):
5148 if opts.get('port'):
5149 opts['port'] = util.getport(opts.get('port'))
5149 opts['port'] = util.getport(opts.get('port'))
5150
5150
5151 baseui = repo and repo.baseui or ui
5151 baseui = repo and repo.baseui or ui
5152 optlist = ("name templates style address port prefix ipv6"
5152 optlist = ("name templates style address port prefix ipv6"
5153 " accesslog errorlog certificate encoding")
5153 " accesslog errorlog certificate encoding")
5154 for o in optlist.split():
5154 for o in optlist.split():
5155 val = opts.get(o, '')
5155 val = opts.get(o, '')
5156 if val in (None, ''): # should check against default options instead
5156 if val in (None, ''): # should check against default options instead
5157 continue
5157 continue
5158 baseui.setconfig("web", o, val)
5158 baseui.setconfig("web", o, val)
5159 if repo and repo.ui != baseui:
5159 if repo and repo.ui != baseui:
5160 repo.ui.setconfig("web", o, val)
5160 repo.ui.setconfig("web", o, val)
5161
5161
5162 o = opts.get('web_conf') or opts.get('webdir_conf')
5162 o = opts.get('web_conf') or opts.get('webdir_conf')
5163 if not o:
5163 if not o:
5164 if not repo:
5164 if not repo:
5165 raise error.RepoError(_("there is no Mercurial repository"
5165 raise error.RepoError(_("there is no Mercurial repository"
5166 " here (.hg not found)"))
5166 " here (.hg not found)"))
5167 o = repo.root
5167 o = repo.root
5168
5168
5169 app = hgweb.hgweb(o, baseui=ui)
5169 app = hgweb.hgweb(o, baseui=ui)
5170
5170
5171 class service(object):
5171 class service(object):
5172 def init(self):
5172 def init(self):
5173 util.setsignalhandler()
5173 util.setsignalhandler()
5174 self.httpd = hgweb.server.create_server(ui, app)
5174 self.httpd = hgweb.server.create_server(ui, app)
5175
5175
5176 if opts['port'] and not ui.verbose:
5176 if opts['port'] and not ui.verbose:
5177 return
5177 return
5178
5178
5179 if self.httpd.prefix:
5179 if self.httpd.prefix:
5180 prefix = self.httpd.prefix.strip('/') + '/'
5180 prefix = self.httpd.prefix.strip('/') + '/'
5181 else:
5181 else:
5182 prefix = ''
5182 prefix = ''
5183
5183
5184 port = ':%d' % self.httpd.port
5184 port = ':%d' % self.httpd.port
5185 if port == ':80':
5185 if port == ':80':
5186 port = ''
5186 port = ''
5187
5187
5188 bindaddr = self.httpd.addr
5188 bindaddr = self.httpd.addr
5189 if bindaddr == '0.0.0.0':
5189 if bindaddr == '0.0.0.0':
5190 bindaddr = '*'
5190 bindaddr = '*'
5191 elif ':' in bindaddr: # IPv6
5191 elif ':' in bindaddr: # IPv6
5192 bindaddr = '[%s]' % bindaddr
5192 bindaddr = '[%s]' % bindaddr
5193
5193
5194 fqaddr = self.httpd.fqaddr
5194 fqaddr = self.httpd.fqaddr
5195 if ':' in fqaddr:
5195 if ':' in fqaddr:
5196 fqaddr = '[%s]' % fqaddr
5196 fqaddr = '[%s]' % fqaddr
5197 if opts['port']:
5197 if opts['port']:
5198 write = ui.status
5198 write = ui.status
5199 else:
5199 else:
5200 write = ui.write
5200 write = ui.write
5201 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5201 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5202 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5202 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5203
5203
5204 def run(self):
5204 def run(self):
5205 self.httpd.serve_forever()
5205 self.httpd.serve_forever()
5206
5206
5207 service = service()
5207 service = service()
5208
5208
5209 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5209 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5210
5210
5211 @command('showconfig|debugconfig',
5211 @command('showconfig|debugconfig',
5212 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5212 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5213 _('[-u] [NAME]...'))
5213 _('[-u] [NAME]...'))
5214 def showconfig(ui, repo, *values, **opts):
5214 def showconfig(ui, repo, *values, **opts):
5215 """show combined config settings from all hgrc files
5215 """show combined config settings from all hgrc files
5216
5216
5217 With no arguments, print names and values of all config items.
5217 With no arguments, print names and values of all config items.
5218
5218
5219 With one argument of the form section.name, print just the value
5219 With one argument of the form section.name, print just the value
5220 of that config item.
5220 of that config item.
5221
5221
5222 With multiple arguments, print names and values of all config
5222 With multiple arguments, print names and values of all config
5223 items with matching section names.
5223 items with matching section names.
5224
5224
5225 With --debug, the source (filename and line number) is printed
5225 With --debug, the source (filename and line number) is printed
5226 for each config item.
5226 for each config item.
5227
5227
5228 Returns 0 on success.
5228 Returns 0 on success.
5229 """
5229 """
5230
5230
5231 for f in scmutil.rcpath():
5231 for f in scmutil.rcpath():
5232 ui.debug('read config from: %s\n' % f)
5232 ui.debug('read config from: %s\n' % f)
5233 untrusted = bool(opts.get('untrusted'))
5233 untrusted = bool(opts.get('untrusted'))
5234 if values:
5234 if values:
5235 sections = [v for v in values if '.' not in v]
5235 sections = [v for v in values if '.' not in v]
5236 items = [v for v in values if '.' in v]
5236 items = [v for v in values if '.' in v]
5237 if len(items) > 1 or items and sections:
5237 if len(items) > 1 or items and sections:
5238 raise util.Abort(_('only one config item permitted'))
5238 raise util.Abort(_('only one config item permitted'))
5239 for section, name, value in ui.walkconfig(untrusted=untrusted):
5239 for section, name, value in ui.walkconfig(untrusted=untrusted):
5240 value = str(value).replace('\n', '\\n')
5240 value = str(value).replace('\n', '\\n')
5241 sectname = section + '.' + name
5241 sectname = section + '.' + name
5242 if values:
5242 if values:
5243 for v in values:
5243 for v in values:
5244 if v == section:
5244 if v == section:
5245 ui.debug('%s: ' %
5245 ui.debug('%s: ' %
5246 ui.configsource(section, name, untrusted))
5246 ui.configsource(section, name, untrusted))
5247 ui.write('%s=%s\n' % (sectname, value))
5247 ui.write('%s=%s\n' % (sectname, value))
5248 elif v == sectname:
5248 elif v == sectname:
5249 ui.debug('%s: ' %
5249 ui.debug('%s: ' %
5250 ui.configsource(section, name, untrusted))
5250 ui.configsource(section, name, untrusted))
5251 ui.write(value, '\n')
5251 ui.write(value, '\n')
5252 else:
5252 else:
5253 ui.debug('%s: ' %
5253 ui.debug('%s: ' %
5254 ui.configsource(section, name, untrusted))
5254 ui.configsource(section, name, untrusted))
5255 ui.write('%s=%s\n' % (sectname, value))
5255 ui.write('%s=%s\n' % (sectname, value))
5256
5256
5257 @command('^status|st',
5257 @command('^status|st',
5258 [('A', 'all', None, _('show status of all files')),
5258 [('A', 'all', None, _('show status of all files')),
5259 ('m', 'modified', None, _('show only modified files')),
5259 ('m', 'modified', None, _('show only modified files')),
5260 ('a', 'added', None, _('show only added files')),
5260 ('a', 'added', None, _('show only added files')),
5261 ('r', 'removed', None, _('show only removed files')),
5261 ('r', 'removed', None, _('show only removed files')),
5262 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5262 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5263 ('c', 'clean', None, _('show only files without changes')),
5263 ('c', 'clean', None, _('show only files without changes')),
5264 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5264 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5265 ('i', 'ignored', None, _('show only ignored files')),
5265 ('i', 'ignored', None, _('show only ignored files')),
5266 ('n', 'no-status', None, _('hide status prefix')),
5266 ('n', 'no-status', None, _('hide status prefix')),
5267 ('C', 'copies', None, _('show source of copied files')),
5267 ('C', 'copies', None, _('show source of copied files')),
5268 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5268 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5269 ('', 'rev', [], _('show difference from revision'), _('REV')),
5269 ('', 'rev', [], _('show difference from revision'), _('REV')),
5270 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5270 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5271 ] + walkopts + subrepoopts,
5271 ] + walkopts + subrepoopts,
5272 _('[OPTION]... [FILE]...'))
5272 _('[OPTION]... [FILE]...'))
5273 def status(ui, repo, *pats, **opts):
5273 def status(ui, repo, *pats, **opts):
5274 """show changed files in the working directory
5274 """show changed files in the working directory
5275
5275
5276 Show status of files in the repository. If names are given, only
5276 Show status of files in the repository. If names are given, only
5277 files that match are shown. Files that are clean or ignored or
5277 files that match are shown. Files that are clean or ignored or
5278 the source of a copy/move operation, are not listed unless
5278 the source of a copy/move operation, are not listed unless
5279 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5279 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5280 Unless options described with "show only ..." are given, the
5280 Unless options described with "show only ..." are given, the
5281 options -mardu are used.
5281 options -mardu are used.
5282
5282
5283 Option -q/--quiet hides untracked (unknown and ignored) files
5283 Option -q/--quiet hides untracked (unknown and ignored) files
5284 unless explicitly requested with -u/--unknown or -i/--ignored.
5284 unless explicitly requested with -u/--unknown or -i/--ignored.
5285
5285
5286 .. note::
5286 .. note::
5287 status may appear to disagree with diff if permissions have
5287 status may appear to disagree with diff if permissions have
5288 changed or a merge has occurred. The standard diff format does
5288 changed or a merge has occurred. The standard diff format does
5289 not report permission changes and diff only reports changes
5289 not report permission changes and diff only reports changes
5290 relative to one merge parent.
5290 relative to one merge parent.
5291
5291
5292 If one revision is given, it is used as the base revision.
5292 If one revision is given, it is used as the base revision.
5293 If two revisions are given, the differences between them are
5293 If two revisions are given, the differences between them are
5294 shown. The --change option can also be used as a shortcut to list
5294 shown. The --change option can also be used as a shortcut to list
5295 the changed files of a revision from its first parent.
5295 the changed files of a revision from its first parent.
5296
5296
5297 The codes used to show the status of files are::
5297 The codes used to show the status of files are::
5298
5298
5299 M = modified
5299 M = modified
5300 A = added
5300 A = added
5301 R = removed
5301 R = removed
5302 C = clean
5302 C = clean
5303 ! = missing (deleted by non-hg command, but still tracked)
5303 ! = missing (deleted by non-hg command, but still tracked)
5304 ? = not tracked
5304 ? = not tracked
5305 I = ignored
5305 I = ignored
5306 = origin of the previous file listed as A (added)
5306 = origin of the previous file listed as A (added)
5307
5307
5308 .. container:: verbose
5308 .. container:: verbose
5309
5309
5310 Examples:
5310 Examples:
5311
5311
5312 - show changes in the working directory relative to a
5312 - show changes in the working directory relative to a
5313 changeset::
5313 changeset::
5314
5314
5315 hg status --rev 9353
5315 hg status --rev 9353
5316
5316
5317 - show all changes including copies in an existing changeset::
5317 - show all changes including copies in an existing changeset::
5318
5318
5319 hg status --copies --change 9353
5319 hg status --copies --change 9353
5320
5320
5321 - get a NUL separated list of added files, suitable for xargs::
5321 - get a NUL separated list of added files, suitable for xargs::
5322
5322
5323 hg status -an0
5323 hg status -an0
5324
5324
5325 Returns 0 on success.
5325 Returns 0 on success.
5326 """
5326 """
5327
5327
5328 revs = opts.get('rev')
5328 revs = opts.get('rev')
5329 change = opts.get('change')
5329 change = opts.get('change')
5330
5330
5331 if revs and change:
5331 if revs and change:
5332 msg = _('cannot specify --rev and --change at the same time')
5332 msg = _('cannot specify --rev and --change at the same time')
5333 raise util.Abort(msg)
5333 raise util.Abort(msg)
5334 elif change:
5334 elif change:
5335 node2 = scmutil.revsingle(repo, change, None).node()
5335 node2 = scmutil.revsingle(repo, change, None).node()
5336 node1 = repo[node2].p1().node()
5336 node1 = repo[node2].p1().node()
5337 else:
5337 else:
5338 node1, node2 = scmutil.revpair(repo, revs)
5338 node1, node2 = scmutil.revpair(repo, revs)
5339
5339
5340 cwd = (pats and repo.getcwd()) or ''
5340 cwd = (pats and repo.getcwd()) or ''
5341 end = opts.get('print0') and '\0' or '\n'
5341 end = opts.get('print0') and '\0' or '\n'
5342 copy = {}
5342 copy = {}
5343 states = 'modified added removed deleted unknown ignored clean'.split()
5343 states = 'modified added removed deleted unknown ignored clean'.split()
5344 show = [k for k in states if opts.get(k)]
5344 show = [k for k in states if opts.get(k)]
5345 if opts.get('all'):
5345 if opts.get('all'):
5346 show += ui.quiet and (states[:4] + ['clean']) or states
5346 show += ui.quiet and (states[:4] + ['clean']) or states
5347 if not show:
5347 if not show:
5348 show = ui.quiet and states[:4] or states[:5]
5348 show = ui.quiet and states[:4] or states[:5]
5349
5349
5350 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5350 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5351 'ignored' in show, 'clean' in show, 'unknown' in show,
5351 'ignored' in show, 'clean' in show, 'unknown' in show,
5352 opts.get('subrepos'))
5352 opts.get('subrepos'))
5353 changestates = zip(states, 'MAR!?IC', stat)
5353 changestates = zip(states, 'MAR!?IC', stat)
5354
5354
5355 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5355 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5356 copy = copies.pathcopies(repo[node1], repo[node2])
5356 copy = copies.pathcopies(repo[node1], repo[node2])
5357
5357
5358 fm = ui.formatter('status', opts)
5358 fm = ui.formatter('status', opts)
5359 format = '%s %s' + end
5359 format = '%s %s' + end
5360 if opts.get('no_status'):
5360 if opts.get('no_status'):
5361 format = '%.0s%s' + end
5361 format = '%.0s%s' + end
5362
5362
5363 for state, char, files in changestates:
5363 for state, char, files in changestates:
5364 if state in show:
5364 if state in show:
5365 label = 'status.' + state
5365 label = 'status.' + state
5366 for f in files:
5366 for f in files:
5367 fm.startitem()
5367 fm.startitem()
5368 fm.write("status path", format, char,
5368 fm.write("status path", format, char,
5369 repo.pathto(f, cwd), label=label)
5369 repo.pathto(f, cwd), label=label)
5370 if f in copy:
5370 if f in copy:
5371 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5371 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5372 label='status.copied')
5372 label='status.copied')
5373 fm.end()
5373 fm.end()
5374
5374
5375 @command('^summary|sum',
5375 @command('^summary|sum',
5376 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5376 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5377 def summary(ui, repo, **opts):
5377 def summary(ui, repo, **opts):
5378 """summarize working directory state
5378 """summarize working directory state
5379
5379
5380 This generates a brief summary of the working directory state,
5380 This generates a brief summary of the working directory state,
5381 including parents, branch, commit status, and available updates.
5381 including parents, branch, commit status, and available updates.
5382
5382
5383 With the --remote option, this will check the default paths for
5383 With the --remote option, this will check the default paths for
5384 incoming and outgoing changes. This can be time-consuming.
5384 incoming and outgoing changes. This can be time-consuming.
5385
5385
5386 Returns 0 on success.
5386 Returns 0 on success.
5387 """
5387 """
5388
5388
5389 ctx = repo[None]
5389 ctx = repo[None]
5390 parents = ctx.parents()
5390 parents = ctx.parents()
5391 pnode = parents[0].node()
5391 pnode = parents[0].node()
5392 marks = []
5392 marks = []
5393
5393
5394 for p in parents:
5394 for p in parents:
5395 # label with log.changeset (instead of log.parent) since this
5395 # label with log.changeset (instead of log.parent) since this
5396 # shows a working directory parent *changeset*:
5396 # shows a working directory parent *changeset*:
5397 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5397 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5398 label='log.changeset')
5398 label='log.changeset')
5399 ui.write(' '.join(p.tags()), label='log.tag')
5399 ui.write(' '.join(p.tags()), label='log.tag')
5400 if p.bookmarks():
5400 if p.bookmarks():
5401 marks.extend(p.bookmarks())
5401 marks.extend(p.bookmarks())
5402 if p.rev() == -1:
5402 if p.rev() == -1:
5403 if not len(repo):
5403 if not len(repo):
5404 ui.write(_(' (empty repository)'))
5404 ui.write(_(' (empty repository)'))
5405 else:
5405 else:
5406 ui.write(_(' (no revision checked out)'))
5406 ui.write(_(' (no revision checked out)'))
5407 ui.write('\n')
5407 ui.write('\n')
5408 if p.description():
5408 if p.description():
5409 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5409 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5410 label='log.summary')
5410 label='log.summary')
5411
5411
5412 branch = ctx.branch()
5412 branch = ctx.branch()
5413 bheads = repo.branchheads(branch)
5413 bheads = repo.branchheads(branch)
5414 m = _('branch: %s\n') % branch
5414 m = _('branch: %s\n') % branch
5415 if branch != 'default':
5415 if branch != 'default':
5416 ui.write(m, label='log.branch')
5416 ui.write(m, label='log.branch')
5417 else:
5417 else:
5418 ui.status(m, label='log.branch')
5418 ui.status(m, label='log.branch')
5419
5419
5420 if marks:
5420 if marks:
5421 current = repo._bookmarkcurrent
5421 current = repo._bookmarkcurrent
5422 ui.write(_('bookmarks:'), label='log.bookmark')
5422 ui.write(_('bookmarks:'), label='log.bookmark')
5423 if current is not None:
5423 if current is not None:
5424 try:
5424 try:
5425 marks.remove(current)
5425 marks.remove(current)
5426 ui.write(' *' + current, label='bookmarks.current')
5426 ui.write(' *' + current, label='bookmarks.current')
5427 except ValueError:
5427 except ValueError:
5428 # current bookmark not in parent ctx marks
5428 # current bookmark not in parent ctx marks
5429 pass
5429 pass
5430 for m in marks:
5430 for m in marks:
5431 ui.write(' ' + m, label='log.bookmark')
5431 ui.write(' ' + m, label='log.bookmark')
5432 ui.write('\n', label='log.bookmark')
5432 ui.write('\n', label='log.bookmark')
5433
5433
5434 st = list(repo.status(unknown=True))[:6]
5434 st = list(repo.status(unknown=True))[:6]
5435
5435
5436 c = repo.dirstate.copies()
5436 c = repo.dirstate.copies()
5437 copied, renamed = [], []
5437 copied, renamed = [], []
5438 for d, s in c.iteritems():
5438 for d, s in c.iteritems():
5439 if s in st[2]:
5439 if s in st[2]:
5440 st[2].remove(s)
5440 st[2].remove(s)
5441 renamed.append(d)
5441 renamed.append(d)
5442 else:
5442 else:
5443 copied.append(d)
5443 copied.append(d)
5444 if d in st[1]:
5444 if d in st[1]:
5445 st[1].remove(d)
5445 st[1].remove(d)
5446 st.insert(3, renamed)
5446 st.insert(3, renamed)
5447 st.insert(4, copied)
5447 st.insert(4, copied)
5448
5448
5449 ms = mergemod.mergestate(repo)
5449 ms = mergemod.mergestate(repo)
5450 st.append([f for f in ms if ms[f] == 'u'])
5450 st.append([f for f in ms if ms[f] == 'u'])
5451
5451
5452 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5452 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5453 st.append(subs)
5453 st.append(subs)
5454
5454
5455 labels = [ui.label(_('%d modified'), 'status.modified'),
5455 labels = [ui.label(_('%d modified'), 'status.modified'),
5456 ui.label(_('%d added'), 'status.added'),
5456 ui.label(_('%d added'), 'status.added'),
5457 ui.label(_('%d removed'), 'status.removed'),
5457 ui.label(_('%d removed'), 'status.removed'),
5458 ui.label(_('%d renamed'), 'status.copied'),
5458 ui.label(_('%d renamed'), 'status.copied'),
5459 ui.label(_('%d copied'), 'status.copied'),
5459 ui.label(_('%d copied'), 'status.copied'),
5460 ui.label(_('%d deleted'), 'status.deleted'),
5460 ui.label(_('%d deleted'), 'status.deleted'),
5461 ui.label(_('%d unknown'), 'status.unknown'),
5461 ui.label(_('%d unknown'), 'status.unknown'),
5462 ui.label(_('%d ignored'), 'status.ignored'),
5462 ui.label(_('%d ignored'), 'status.ignored'),
5463 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5463 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5464 ui.label(_('%d subrepos'), 'status.modified')]
5464 ui.label(_('%d subrepos'), 'status.modified')]
5465 t = []
5465 t = []
5466 for s, l in zip(st, labels):
5466 for s, l in zip(st, labels):
5467 if s:
5467 if s:
5468 t.append(l % len(s))
5468 t.append(l % len(s))
5469
5469
5470 t = ', '.join(t)
5470 t = ', '.join(t)
5471 cleanworkdir = False
5471 cleanworkdir = False
5472
5472
5473 if len(parents) > 1:
5473 if len(parents) > 1:
5474 t += _(' (merge)')
5474 t += _(' (merge)')
5475 elif branch != parents[0].branch():
5475 elif branch != parents[0].branch():
5476 t += _(' (new branch)')
5476 t += _(' (new branch)')
5477 elif (parents[0].closesbranch() and
5477 elif (parents[0].closesbranch() and
5478 pnode in repo.branchheads(branch, closed=True)):
5478 pnode in repo.branchheads(branch, closed=True)):
5479 t += _(' (head closed)')
5479 t += _(' (head closed)')
5480 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5480 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5481 t += _(' (clean)')
5481 t += _(' (clean)')
5482 cleanworkdir = True
5482 cleanworkdir = True
5483 elif pnode not in bheads:
5483 elif pnode not in bheads:
5484 t += _(' (new branch head)')
5484 t += _(' (new branch head)')
5485
5485
5486 if cleanworkdir:
5486 if cleanworkdir:
5487 ui.status(_('commit: %s\n') % t.strip())
5487 ui.status(_('commit: %s\n') % t.strip())
5488 else:
5488 else:
5489 ui.write(_('commit: %s\n') % t.strip())
5489 ui.write(_('commit: %s\n') % t.strip())
5490
5490
5491 # all ancestors of branch heads - all ancestors of parent = new csets
5491 # all ancestors of branch heads - all ancestors of parent = new csets
5492 new = [0] * len(repo)
5492 new = [0] * len(repo)
5493 cl = repo.changelog
5493 cl = repo.changelog
5494 for a in [cl.rev(n) for n in bheads]:
5494 for a in [cl.rev(n) for n in bheads]:
5495 new[a] = 1
5495 new[a] = 1
5496 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5496 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5497 new[a] = 1
5497 new[a] = 1
5498 for a in [p.rev() for p in parents]:
5498 for a in [p.rev() for p in parents]:
5499 if a >= 0:
5499 if a >= 0:
5500 new[a] = 0
5500 new[a] = 0
5501 for a in cl.ancestors([p.rev() for p in parents]):
5501 for a in cl.ancestors([p.rev() for p in parents]):
5502 new[a] = 0
5502 new[a] = 0
5503 new = sum(new)
5503 new = sum(new)
5504
5504
5505 if new == 0:
5505 if new == 0:
5506 ui.status(_('update: (current)\n'))
5506 ui.status(_('update: (current)\n'))
5507 elif pnode not in bheads:
5507 elif pnode not in bheads:
5508 ui.write(_('update: %d new changesets (update)\n') % new)
5508 ui.write(_('update: %d new changesets (update)\n') % new)
5509 else:
5509 else:
5510 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5510 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5511 (new, len(bheads)))
5511 (new, len(bheads)))
5512
5512
5513 if opts.get('remote'):
5513 if opts.get('remote'):
5514 t = []
5514 t = []
5515 source, branches = hg.parseurl(ui.expandpath('default'))
5515 source, branches = hg.parseurl(ui.expandpath('default'))
5516 other = hg.peer(repo, {}, source)
5516 other = hg.peer(repo, {}, source)
5517 revs, checkout = hg.addbranchrevs(repo, other, branches,
5517 revs, checkout = hg.addbranchrevs(repo, other, branches,
5518 opts.get('rev'))
5518 opts.get('rev'))
5519 ui.debug('comparing with %s\n' % util.hidepassword(source))
5519 ui.debug('comparing with %s\n' % util.hidepassword(source))
5520 repo.ui.pushbuffer()
5520 repo.ui.pushbuffer()
5521 commoninc = discovery.findcommonincoming(repo, other)
5521 commoninc = discovery.findcommonincoming(repo, other)
5522 _common, incoming, _rheads = commoninc
5522 _common, incoming, _rheads = commoninc
5523 repo.ui.popbuffer()
5523 repo.ui.popbuffer()
5524 if incoming:
5524 if incoming:
5525 t.append(_('1 or more incoming'))
5525 t.append(_('1 or more incoming'))
5526
5526
5527 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5527 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5528 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5528 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5529 if source != dest:
5529 if source != dest:
5530 other = hg.peer(repo, {}, dest)
5530 other = hg.peer(repo, {}, dest)
5531 commoninc = None
5531 commoninc = None
5532 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5532 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5533 repo.ui.pushbuffer()
5533 repo.ui.pushbuffer()
5534 outgoing = discovery.findcommonoutgoing(repo, other,
5534 outgoing = discovery.findcommonoutgoing(repo, other,
5535 commoninc=commoninc)
5535 commoninc=commoninc)
5536 repo.ui.popbuffer()
5536 repo.ui.popbuffer()
5537 o = outgoing.missing
5537 o = outgoing.missing
5538 if o:
5538 if o:
5539 t.append(_('%d outgoing') % len(o))
5539 t.append(_('%d outgoing') % len(o))
5540 if 'bookmarks' in other.listkeys('namespaces'):
5540 if 'bookmarks' in other.listkeys('namespaces'):
5541 lmarks = repo.listkeys('bookmarks')
5541 lmarks = repo.listkeys('bookmarks')
5542 rmarks = other.listkeys('bookmarks')
5542 rmarks = other.listkeys('bookmarks')
5543 diff = set(rmarks) - set(lmarks)
5543 diff = set(rmarks) - set(lmarks)
5544 if len(diff) > 0:
5544 if len(diff) > 0:
5545 t.append(_('%d incoming bookmarks') % len(diff))
5545 t.append(_('%d incoming bookmarks') % len(diff))
5546 diff = set(lmarks) - set(rmarks)
5546 diff = set(lmarks) - set(rmarks)
5547 if len(diff) > 0:
5547 if len(diff) > 0:
5548 t.append(_('%d outgoing bookmarks') % len(diff))
5548 t.append(_('%d outgoing bookmarks') % len(diff))
5549
5549
5550 if t:
5550 if t:
5551 ui.write(_('remote: %s\n') % (', '.join(t)))
5551 ui.write(_('remote: %s\n') % (', '.join(t)))
5552 else:
5552 else:
5553 ui.status(_('remote: (synced)\n'))
5553 ui.status(_('remote: (synced)\n'))
5554
5554
5555 @command('tag',
5555 @command('tag',
5556 [('f', 'force', None, _('force tag')),
5556 [('f', 'force', None, _('force tag')),
5557 ('l', 'local', None, _('make the tag local')),
5557 ('l', 'local', None, _('make the tag local')),
5558 ('r', 'rev', '', _('revision to tag'), _('REV')),
5558 ('r', 'rev', '', _('revision to tag'), _('REV')),
5559 ('', 'remove', None, _('remove a tag')),
5559 ('', 'remove', None, _('remove a tag')),
5560 # -l/--local is already there, commitopts cannot be used
5560 # -l/--local is already there, commitopts cannot be used
5561 ('e', 'edit', None, _('edit commit message')),
5561 ('e', 'edit', None, _('edit commit message')),
5562 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5562 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5563 ] + commitopts2,
5563 ] + commitopts2,
5564 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5564 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5565 def tag(ui, repo, name1, *names, **opts):
5565 def tag(ui, repo, name1, *names, **opts):
5566 """add one or more tags for the current or given revision
5566 """add one or more tags for the current or given revision
5567
5567
5568 Name a particular revision using <name>.
5568 Name a particular revision using <name>.
5569
5569
5570 Tags are used to name particular revisions of the repository and are
5570 Tags are used to name particular revisions of the repository and are
5571 very useful to compare different revisions, to go back to significant
5571 very useful to compare different revisions, to go back to significant
5572 earlier versions or to mark branch points as releases, etc. Changing
5572 earlier versions or to mark branch points as releases, etc. Changing
5573 an existing tag is normally disallowed; use -f/--force to override.
5573 an existing tag is normally disallowed; use -f/--force to override.
5574
5574
5575 If no revision is given, the parent of the working directory is
5575 If no revision is given, the parent of the working directory is
5576 used, or tip if no revision is checked out.
5576 used, or tip if no revision is checked out.
5577
5577
5578 To facilitate version control, distribution, and merging of tags,
5578 To facilitate version control, distribution, and merging of tags,
5579 they are stored as a file named ".hgtags" which is managed similarly
5579 they are stored as a file named ".hgtags" which is managed similarly
5580 to other project files and can be hand-edited if necessary. This
5580 to other project files and can be hand-edited if necessary. This
5581 also means that tagging creates a new commit. The file
5581 also means that tagging creates a new commit. The file
5582 ".hg/localtags" is used for local tags (not shared among
5582 ".hg/localtags" is used for local tags (not shared among
5583 repositories).
5583 repositories).
5584
5584
5585 Tag commits are usually made at the head of a branch. If the parent
5585 Tag commits are usually made at the head of a branch. If the parent
5586 of the working directory is not a branch head, :hg:`tag` aborts; use
5586 of the working directory is not a branch head, :hg:`tag` aborts; use
5587 -f/--force to force the tag commit to be based on a non-head
5587 -f/--force to force the tag commit to be based on a non-head
5588 changeset.
5588 changeset.
5589
5589
5590 See :hg:`help dates` for a list of formats valid for -d/--date.
5590 See :hg:`help dates` for a list of formats valid for -d/--date.
5591
5591
5592 Since tag names have priority over branch names during revision
5592 Since tag names have priority over branch names during revision
5593 lookup, using an existing branch name as a tag name is discouraged.
5593 lookup, using an existing branch name as a tag name is discouraged.
5594
5594
5595 Returns 0 on success.
5595 Returns 0 on success.
5596 """
5596 """
5597 wlock = lock = None
5597 wlock = lock = None
5598 try:
5598 try:
5599 wlock = repo.wlock()
5599 wlock = repo.wlock()
5600 lock = repo.lock()
5600 lock = repo.lock()
5601 rev_ = "."
5601 rev_ = "."
5602 names = [t.strip() for t in (name1,) + names]
5602 names = [t.strip() for t in (name1,) + names]
5603 if len(names) != len(set(names)):
5603 if len(names) != len(set(names)):
5604 raise util.Abort(_('tag names must be unique'))
5604 raise util.Abort(_('tag names must be unique'))
5605 for n in names:
5605 for n in names:
5606 if n in ['tip', '.', 'null']:
5606 if n in ['tip', '.', 'null']:
5607 raise util.Abort(_("the name '%s' is reserved") % n)
5607 raise util.Abort(_("the name '%s' is reserved") % n)
5608 if not n:
5608 if not n:
5609 raise util.Abort(_('tag names cannot consist entirely of '
5609 raise util.Abort(_('tag names cannot consist entirely of '
5610 'whitespace'))
5610 'whitespace'))
5611 if opts.get('rev') and opts.get('remove'):
5611 if opts.get('rev') and opts.get('remove'):
5612 raise util.Abort(_("--rev and --remove are incompatible"))
5612 raise util.Abort(_("--rev and --remove are incompatible"))
5613 if opts.get('rev'):
5613 if opts.get('rev'):
5614 rev_ = opts['rev']
5614 rev_ = opts['rev']
5615 message = opts.get('message')
5615 message = opts.get('message')
5616 if opts.get('remove'):
5616 if opts.get('remove'):
5617 expectedtype = opts.get('local') and 'local' or 'global'
5617 expectedtype = opts.get('local') and 'local' or 'global'
5618 for n in names:
5618 for n in names:
5619 if not repo.tagtype(n):
5619 if not repo.tagtype(n):
5620 raise util.Abort(_("tag '%s' does not exist") % n)
5620 raise util.Abort(_("tag '%s' does not exist") % n)
5621 if repo.tagtype(n) != expectedtype:
5621 if repo.tagtype(n) != expectedtype:
5622 if expectedtype == 'global':
5622 if expectedtype == 'global':
5623 raise util.Abort(_("tag '%s' is not a global tag") % n)
5623 raise util.Abort(_("tag '%s' is not a global tag") % n)
5624 else:
5624 else:
5625 raise util.Abort(_("tag '%s' is not a local tag") % n)
5625 raise util.Abort(_("tag '%s' is not a local tag") % n)
5626 rev_ = nullid
5626 rev_ = nullid
5627 if not message:
5627 if not message:
5628 # we don't translate commit messages
5628 # we don't translate commit messages
5629 message = 'Removed tag %s' % ', '.join(names)
5629 message = 'Removed tag %s' % ', '.join(names)
5630 elif not opts.get('force'):
5630 elif not opts.get('force'):
5631 for n in names:
5631 for n in names:
5632 if n in repo.tags():
5632 if n in repo.tags():
5633 raise util.Abort(_("tag '%s' already exists "
5633 raise util.Abort(_("tag '%s' already exists "
5634 "(use -f to force)") % n)
5634 "(use -f to force)") % n)
5635 if not opts.get('local'):
5635 if not opts.get('local'):
5636 p1, p2 = repo.dirstate.parents()
5636 p1, p2 = repo.dirstate.parents()
5637 if p2 != nullid:
5637 if p2 != nullid:
5638 raise util.Abort(_('uncommitted merge'))
5638 raise util.Abort(_('uncommitted merge'))
5639 bheads = repo.branchheads()
5639 bheads = repo.branchheads()
5640 if not opts.get('force') and bheads and p1 not in bheads:
5640 if not opts.get('force') and bheads and p1 not in bheads:
5641 raise util.Abort(_('not at a branch head (use -f to force)'))
5641 raise util.Abort(_('not at a branch head (use -f to force)'))
5642 r = scmutil.revsingle(repo, rev_).node()
5642 r = scmutil.revsingle(repo, rev_).node()
5643
5643
5644 if not message:
5644 if not message:
5645 # we don't translate commit messages
5645 # we don't translate commit messages
5646 message = ('Added tag %s for changeset %s' %
5646 message = ('Added tag %s for changeset %s' %
5647 (', '.join(names), short(r)))
5647 (', '.join(names), short(r)))
5648
5648
5649 date = opts.get('date')
5649 date = opts.get('date')
5650 if date:
5650 if date:
5651 date = util.parsedate(date)
5651 date = util.parsedate(date)
5652
5652
5653 if opts.get('edit'):
5653 if opts.get('edit'):
5654 message = ui.edit(message, ui.username())
5654 message = ui.edit(message, ui.username())
5655
5655
5656 # don't allow tagging the null rev
5656 # don't allow tagging the null rev
5657 if (not opts.get('remove') and
5657 if (not opts.get('remove') and
5658 scmutil.revsingle(repo, rev_).rev() == nullrev):
5658 scmutil.revsingle(repo, rev_).rev() == nullrev):
5659 raise util.Abort(_("null revision specified"))
5659 raise util.Abort(_("null revision specified"))
5660
5660
5661 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5661 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5662 finally:
5662 finally:
5663 release(lock, wlock)
5663 release(lock, wlock)
5664
5664
5665 @command('tags', [], '')
5665 @command('tags', [], '')
5666 def tags(ui, repo):
5666 def tags(ui, repo):
5667 """list repository tags
5667 """list repository tags
5668
5668
5669 This lists both regular and local tags. When the -v/--verbose
5669 This lists both regular and local tags. When the -v/--verbose
5670 switch is used, a third column "local" is printed for local tags.
5670 switch is used, a third column "local" is printed for local tags.
5671
5671
5672 Returns 0 on success.
5672 Returns 0 on success.
5673 """
5673 """
5674
5674
5675 hexfunc = ui.debugflag and hex or short
5675 hexfunc = ui.debugflag and hex or short
5676 tagtype = ""
5676 tagtype = ""
5677
5677
5678 for t, n in reversed(repo.tagslist()):
5678 for t, n in reversed(repo.tagslist()):
5679 if ui.quiet:
5679 if ui.quiet:
5680 ui.write("%s\n" % t, label='tags.normal')
5680 ui.write("%s\n" % t, label='tags.normal')
5681 continue
5681 continue
5682
5682
5683 hn = hexfunc(n)
5683 hn = hexfunc(n)
5684 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5684 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5685 rev = ui.label(r, 'log.changeset')
5685 rev = ui.label(r, 'log.changeset')
5686 spaces = " " * (30 - encoding.colwidth(t))
5686 spaces = " " * (30 - encoding.colwidth(t))
5687
5687
5688 tag = ui.label(t, 'tags.normal')
5688 tag = ui.label(t, 'tags.normal')
5689 if ui.verbose:
5689 if ui.verbose:
5690 if repo.tagtype(t) == 'local':
5690 if repo.tagtype(t) == 'local':
5691 tagtype = " local"
5691 tagtype = " local"
5692 tag = ui.label(t, 'tags.local')
5692 tag = ui.label(t, 'tags.local')
5693 else:
5693 else:
5694 tagtype = ""
5694 tagtype = ""
5695 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5695 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5696
5696
5697 @command('tip',
5697 @command('tip',
5698 [('p', 'patch', None, _('show patch')),
5698 [('p', 'patch', None, _('show patch')),
5699 ('g', 'git', None, _('use git extended diff format')),
5699 ('g', 'git', None, _('use git extended diff format')),
5700 ] + templateopts,
5700 ] + templateopts,
5701 _('[-p] [-g]'))
5701 _('[-p] [-g]'))
5702 def tip(ui, repo, **opts):
5702 def tip(ui, repo, **opts):
5703 """show the tip revision
5703 """show the tip revision
5704
5704
5705 The tip revision (usually just called the tip) is the changeset
5705 The tip revision (usually just called the tip) is the changeset
5706 most recently added to the repository (and therefore the most
5706 most recently added to the repository (and therefore the most
5707 recently changed head).
5707 recently changed head).
5708
5708
5709 If you have just made a commit, that commit will be the tip. If
5709 If you have just made a commit, that commit will be the tip. If
5710 you have just pulled changes from another repository, the tip of
5710 you have just pulled changes from another repository, the tip of
5711 that repository becomes the current tip. The "tip" tag is special
5711 that repository becomes the current tip. The "tip" tag is special
5712 and cannot be renamed or assigned to a different changeset.
5712 and cannot be renamed or assigned to a different changeset.
5713
5713
5714 Returns 0 on success.
5714 Returns 0 on success.
5715 """
5715 """
5716 displayer = cmdutil.show_changeset(ui, repo, opts)
5716 displayer = cmdutil.show_changeset(ui, repo, opts)
5717 displayer.show(repo[len(repo) - 1])
5717 displayer.show(repo[len(repo) - 1])
5718 displayer.close()
5718 displayer.close()
5719
5719
5720 @command('unbundle',
5720 @command('unbundle',
5721 [('u', 'update', None,
5721 [('u', 'update', None,
5722 _('update to new branch head if changesets were unbundled'))],
5722 _('update to new branch head if changesets were unbundled'))],
5723 _('[-u] FILE...'))
5723 _('[-u] FILE...'))
5724 def unbundle(ui, repo, fname1, *fnames, **opts):
5724 def unbundle(ui, repo, fname1, *fnames, **opts):
5725 """apply one or more changegroup files
5725 """apply one or more changegroup files
5726
5726
5727 Apply one or more compressed changegroup files generated by the
5727 Apply one or more compressed changegroup files generated by the
5728 bundle command.
5728 bundle command.
5729
5729
5730 Returns 0 on success, 1 if an update has unresolved files.
5730 Returns 0 on success, 1 if an update has unresolved files.
5731 """
5731 """
5732 fnames = (fname1,) + fnames
5732 fnames = (fname1,) + fnames
5733
5733
5734 lock = repo.lock()
5734 lock = repo.lock()
5735 wc = repo['.']
5735 wc = repo['.']
5736 try:
5736 try:
5737 for fname in fnames:
5737 for fname in fnames:
5738 f = url.open(ui, fname)
5738 f = url.open(ui, fname)
5739 gen = changegroup.readbundle(f, fname)
5739 gen = changegroup.readbundle(f, fname)
5740 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5740 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5741 finally:
5741 finally:
5742 lock.release()
5742 lock.release()
5743 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5743 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5744 return postincoming(ui, repo, modheads, opts.get('update'), None)
5744 return postincoming(ui, repo, modheads, opts.get('update'), None)
5745
5745
5746 @command('^update|up|checkout|co',
5746 @command('^update|up|checkout|co',
5747 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5747 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5748 ('c', 'check', None,
5748 ('c', 'check', None,
5749 _('update across branches if no uncommitted changes')),
5749 _('update across branches if no uncommitted changes')),
5750 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5750 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5751 ('r', 'rev', '', _('revision'), _('REV'))],
5751 ('r', 'rev', '', _('revision'), _('REV'))],
5752 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5752 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5753 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5753 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5754 """update working directory (or switch revisions)
5754 """update working directory (or switch revisions)
5755
5755
5756 Update the repository's working directory to the specified
5756 Update the repository's working directory to the specified
5757 changeset. If no changeset is specified, update to the tip of the
5757 changeset. If no changeset is specified, update to the tip of the
5758 current named branch and move the current bookmark (see :hg:`help
5758 current named branch and move the current bookmark (see :hg:`help
5759 bookmarks`).
5759 bookmarks`).
5760
5760
5761 Update sets the working directory's parent revison to the specified
5761 Update sets the working directory's parent revison to the specified
5762 changeset (see :hg:`help parents`).
5762 changeset (see :hg:`help parents`).
5763
5763
5764 If the changeset is not a descendant or ancestor of the working
5764 If the changeset is not a descendant or ancestor of the working
5765 directory's parent, the update is aborted. With the -c/--check
5765 directory's parent, the update is aborted. With the -c/--check
5766 option, the working directory is checked for uncommitted changes; if
5766 option, the working directory is checked for uncommitted changes; if
5767 none are found, the working directory is updated to the specified
5767 none are found, the working directory is updated to the specified
5768 changeset.
5768 changeset.
5769
5769
5770 .. container:: verbose
5770 .. container:: verbose
5771
5771
5772 The following rules apply when the working directory contains
5772 The following rules apply when the working directory contains
5773 uncommitted changes:
5773 uncommitted changes:
5774
5774
5775 1. If neither -c/--check nor -C/--clean is specified, and if
5775 1. If neither -c/--check nor -C/--clean is specified, and if
5776 the requested changeset is an ancestor or descendant of
5776 the requested changeset is an ancestor or descendant of
5777 the working directory's parent, the uncommitted changes
5777 the working directory's parent, the uncommitted changes
5778 are merged into the requested changeset and the merged
5778 are merged into the requested changeset and the merged
5779 result is left uncommitted. If the requested changeset is
5779 result is left uncommitted. If the requested changeset is
5780 not an ancestor or descendant (that is, it is on another
5780 not an ancestor or descendant (that is, it is on another
5781 branch), the update is aborted and the uncommitted changes
5781 branch), the update is aborted and the uncommitted changes
5782 are preserved.
5782 are preserved.
5783
5783
5784 2. With the -c/--check option, the update is aborted and the
5784 2. With the -c/--check option, the update is aborted and the
5785 uncommitted changes are preserved.
5785 uncommitted changes are preserved.
5786
5786
5787 3. With the -C/--clean option, uncommitted changes are discarded and
5787 3. With the -C/--clean option, uncommitted changes are discarded and
5788 the working directory is updated to the requested changeset.
5788 the working directory is updated to the requested changeset.
5789
5789
5790 To cancel an uncommitted merge (and lose your changes), use
5790 To cancel an uncommitted merge (and lose your changes), use
5791 :hg:`update --clean .`.
5791 :hg:`update --clean .`.
5792
5792
5793 Use null as the changeset to remove the working directory (like
5793 Use null as the changeset to remove the working directory (like
5794 :hg:`clone -U`).
5794 :hg:`clone -U`).
5795
5795
5796 If you want to revert just one file to an older revision, use
5796 If you want to revert just one file to an older revision, use
5797 :hg:`revert [-r REV] NAME`.
5797 :hg:`revert [-r REV] NAME`.
5798
5798
5799 See :hg:`help dates` for a list of formats valid for -d/--date.
5799 See :hg:`help dates` for a list of formats valid for -d/--date.
5800
5800
5801 Returns 0 on success, 1 if there are unresolved files.
5801 Returns 0 on success, 1 if there are unresolved files.
5802 """
5802 """
5803 if rev and node:
5803 if rev and node:
5804 raise util.Abort(_("please specify just one revision"))
5804 raise util.Abort(_("please specify just one revision"))
5805
5805
5806 if rev is None or rev == '':
5806 if rev is None or rev == '':
5807 rev = node
5807 rev = node
5808
5808
5809 # with no argument, we also move the current bookmark, if any
5809 # with no argument, we also move the current bookmark, if any
5810 movemarkfrom = None
5810 movemarkfrom = None
5811 if rev is None or node == '':
5811 if rev is None or node == '':
5812 movemarkfrom = repo['.'].node()
5812 movemarkfrom = repo['.'].node()
5813
5813
5814 # if we defined a bookmark, we have to remember the original bookmark name
5814 # if we defined a bookmark, we have to remember the original bookmark name
5815 brev = rev
5815 brev = rev
5816 rev = scmutil.revsingle(repo, rev, rev).rev()
5816 rev = scmutil.revsingle(repo, rev, rev).rev()
5817
5817
5818 if check and clean:
5818 if check and clean:
5819 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5819 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5820
5820
5821 if date:
5821 if date:
5822 if rev is not None:
5822 if rev is not None:
5823 raise util.Abort(_("you can't specify a revision and a date"))
5823 raise util.Abort(_("you can't specify a revision and a date"))
5824 rev = cmdutil.finddate(ui, repo, date)
5824 rev = cmdutil.finddate(ui, repo, date)
5825
5825
5826 if check:
5826 if check:
5827 c = repo[None]
5827 c = repo[None]
5828 if c.dirty(merge=False, branch=False):
5828 if c.dirty(merge=False, branch=False):
5829 raise util.Abort(_("uncommitted local changes"))
5829 raise util.Abort(_("uncommitted local changes"))
5830 if rev is None:
5830 if rev is None:
5831 rev = repo[repo[None].branch()].rev()
5831 rev = repo[repo[None].branch()].rev()
5832 mergemod._checkunknown(repo, repo[None], repo[rev])
5832 mergemod._checkunknown(repo, repo[None], repo[rev])
5833
5833
5834 if clean:
5834 if clean:
5835 ret = hg.clean(repo, rev)
5835 ret = hg.clean(repo, rev)
5836 else:
5836 else:
5837 ret = hg.update(repo, rev)
5837 ret = hg.update(repo, rev)
5838
5838
5839 if not ret and movemarkfrom:
5839 if not ret and movemarkfrom:
5840 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5840 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5841 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5841 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5842 elif brev in repo._bookmarks:
5842 elif brev in repo._bookmarks:
5843 bookmarks.setcurrent(repo, brev)
5843 bookmarks.setcurrent(repo, brev)
5844 elif brev:
5844 elif brev:
5845 bookmarks.unsetcurrent(repo)
5845 bookmarks.unsetcurrent(repo)
5846
5846
5847 return ret
5847 return ret
5848
5848
5849 @command('verify', [])
5849 @command('verify', [])
5850 def verify(ui, repo):
5850 def verify(ui, repo):
5851 """verify the integrity of the repository
5851 """verify the integrity of the repository
5852
5852
5853 Verify the integrity of the current repository.
5853 Verify the integrity of the current repository.
5854
5854
5855 This will perform an extensive check of the repository's
5855 This will perform an extensive check of the repository's
5856 integrity, validating the hashes and checksums of each entry in
5856 integrity, validating the hashes and checksums of each entry in
5857 the changelog, manifest, and tracked files, as well as the
5857 the changelog, manifest, and tracked files, as well as the
5858 integrity of their crosslinks and indices.
5858 integrity of their crosslinks and indices.
5859
5859
5860 Returns 0 on success, 1 if errors are encountered.
5860 Returns 0 on success, 1 if errors are encountered.
5861 """
5861 """
5862 return hg.verify(repo)
5862 return hg.verify(repo)
5863
5863
5864 @command('version', [])
5864 @command('version', [])
5865 def version_(ui):
5865 def version_(ui):
5866 """output version and copyright information"""
5866 """output version and copyright information"""
5867 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5867 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5868 % util.version())
5868 % util.version())
5869 ui.status(_(
5869 ui.status(_(
5870 "(see http://mercurial.selenic.com for more information)\n"
5870 "(see http://mercurial.selenic.com for more information)\n"
5871 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5871 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5872 "This is free software; see the source for copying conditions. "
5872 "This is free software; see the source for copying conditions. "
5873 "There is NO\nwarranty; "
5873 "There is NO\nwarranty; "
5874 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5874 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5875 ))
5875 ))
5876
5876
5877 norepo = ("clone init version help debugcommands debugcomplete"
5877 norepo = ("clone init version help debugcommands debugcomplete"
5878 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5878 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5879 " debugknown debuggetbundle debugbundle")
5879 " debugknown debuggetbundle debugbundle")
5880 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5880 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5881 " debugdata debugindex debugindexdot debugrevlog")
5881 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now