##// END OF EJS Templates
help: document '@' bookmark in 'help bookmarks' and 'help clone'
Kevin Bullock -
r18474:e031e10c stable
parent child Browse files
Show More
@@ -1,6044 +1,6051 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, 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 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 hg.clean(repo, node, show_stats=False)
459 hg.clean(repo, node, show_stats=False)
460 repo.dirstate.setbranch(branch)
460 repo.dirstate.setbranch(branch)
461 revert_opts = opts.copy()
461 revert_opts = opts.copy()
462 revert_opts['date'] = None
462 revert_opts['date'] = None
463 revert_opts['all'] = True
463 revert_opts['all'] = True
464 revert_opts['rev'] = hex(parent)
464 revert_opts['rev'] = hex(parent)
465 revert_opts['no_backup'] = None
465 revert_opts['no_backup'] = None
466 revert(ui, repo, **revert_opts)
466 revert(ui, repo, **revert_opts)
467 if not opts.get('merge') and op1 != node:
467 if not opts.get('merge') and op1 != node:
468 try:
468 try:
469 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
470 return hg.update(repo, op1)
470 return hg.update(repo, op1)
471 finally:
471 finally:
472 ui.setconfig('ui', 'forcemerge', '')
472 ui.setconfig('ui', 'forcemerge', '')
473
473
474 commit_opts = opts.copy()
474 commit_opts = opts.copy()
475 commit_opts['addremove'] = False
475 commit_opts['addremove'] = False
476 if not commit_opts['message'] and not commit_opts['logfile']:
476 if not commit_opts['message'] and not commit_opts['logfile']:
477 # we don't translate commit messages
477 # we don't translate commit messages
478 commit_opts['message'] = "Backed out changeset %s" % short(node)
478 commit_opts['message'] = "Backed out changeset %s" % short(node)
479 commit_opts['force_editor'] = True
479 commit_opts['force_editor'] = True
480 commit(ui, repo, **commit_opts)
480 commit(ui, repo, **commit_opts)
481 def nice(node):
481 def nice(node):
482 return '%d:%s' % (repo.changelog.rev(node), short(node))
482 return '%d:%s' % (repo.changelog.rev(node), short(node))
483 ui.status(_('changeset %s backs out changeset %s\n') %
483 ui.status(_('changeset %s backs out changeset %s\n') %
484 (nice(repo.changelog.tip()), nice(node)))
484 (nice(repo.changelog.tip()), nice(node)))
485 if opts.get('merge') and op1 != node:
485 if opts.get('merge') and op1 != node:
486 hg.clean(repo, op1, show_stats=False)
486 hg.clean(repo, op1, show_stats=False)
487 ui.status(_('merging with changeset %s\n')
487 ui.status(_('merging with changeset %s\n')
488 % nice(repo.changelog.tip()))
488 % nice(repo.changelog.tip()))
489 try:
489 try:
490 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
490 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
491 return hg.merge(repo, hex(repo.changelog.tip()))
491 return hg.merge(repo, hex(repo.changelog.tip()))
492 finally:
492 finally:
493 ui.setconfig('ui', 'forcemerge', '')
493 ui.setconfig('ui', 'forcemerge', '')
494 finally:
494 finally:
495 wlock.release()
495 wlock.release()
496 return 0
496 return 0
497
497
498 @command('bisect',
498 @command('bisect',
499 [('r', 'reset', False, _('reset bisect state')),
499 [('r', 'reset', False, _('reset bisect state')),
500 ('g', 'good', False, _('mark changeset good')),
500 ('g', 'good', False, _('mark changeset good')),
501 ('b', 'bad', False, _('mark changeset bad')),
501 ('b', 'bad', False, _('mark changeset bad')),
502 ('s', 'skip', False, _('skip testing changeset')),
502 ('s', 'skip', False, _('skip testing changeset')),
503 ('e', 'extend', False, _('extend the bisect range')),
503 ('e', 'extend', False, _('extend the bisect range')),
504 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
504 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
505 ('U', 'noupdate', False, _('do not update to target'))],
505 ('U', 'noupdate', False, _('do not update to target'))],
506 _("[-gbsr] [-U] [-c CMD] [REV]"))
506 _("[-gbsr] [-U] [-c CMD] [REV]"))
507 def bisect(ui, repo, rev=None, extra=None, command=None,
507 def bisect(ui, repo, rev=None, extra=None, command=None,
508 reset=None, good=None, bad=None, skip=None, extend=None,
508 reset=None, good=None, bad=None, skip=None, extend=None,
509 noupdate=None):
509 noupdate=None):
510 """subdivision search of changesets
510 """subdivision search of changesets
511
511
512 This command helps to find changesets which introduce problems. To
512 This command helps to find changesets which introduce problems. To
513 use, mark the earliest changeset you know exhibits the problem as
513 use, mark the earliest changeset you know exhibits the problem as
514 bad, then mark the latest changeset which is free from the problem
514 bad, then mark the latest changeset which is free from the problem
515 as good. Bisect will update your working directory to a revision
515 as good. Bisect will update your working directory to a revision
516 for testing (unless the -U/--noupdate option is specified). Once
516 for testing (unless the -U/--noupdate option is specified). Once
517 you have performed tests, mark the working directory as good or
517 you have performed tests, mark the working directory as good or
518 bad, and bisect will either update to another candidate changeset
518 bad, and bisect will either update to another candidate changeset
519 or announce that it has found the bad revision.
519 or announce that it has found the bad revision.
520
520
521 As a shortcut, you can also use the revision argument to mark a
521 As a shortcut, you can also use the revision argument to mark a
522 revision as good or bad without checking it out first.
522 revision as good or bad without checking it out first.
523
523
524 If you supply a command, it will be used for automatic bisection.
524 If you supply a command, it will be used for automatic bisection.
525 The environment variable HG_NODE will contain the ID of the
525 The environment variable HG_NODE will contain the ID of the
526 changeset being tested. The exit status of the command will be
526 changeset being tested. The exit status of the command will be
527 used to mark revisions as good or bad: status 0 means good, 125
527 used to mark revisions as good or bad: status 0 means good, 125
528 means to skip the revision, 127 (command not found) will abort the
528 means to skip the revision, 127 (command not found) will abort the
529 bisection, and any other non-zero exit status means the revision
529 bisection, and any other non-zero exit status means the revision
530 is bad.
530 is bad.
531
531
532 .. container:: verbose
532 .. container:: verbose
533
533
534 Some examples:
534 Some examples:
535
535
536 - start a bisection with known bad revision 12, and good revision 34::
536 - start a bisection with known bad revision 12, and good revision 34::
537
537
538 hg bisect --bad 34
538 hg bisect --bad 34
539 hg bisect --good 12
539 hg bisect --good 12
540
540
541 - advance the current bisection by marking current revision as good or
541 - advance the current bisection by marking current revision as good or
542 bad::
542 bad::
543
543
544 hg bisect --good
544 hg bisect --good
545 hg bisect --bad
545 hg bisect --bad
546
546
547 - mark the current revision, or a known revision, to be skipped (e.g. if
547 - mark the current revision, or a known revision, to be skipped (e.g. if
548 that revision is not usable because of another issue)::
548 that revision is not usable because of another issue)::
549
549
550 hg bisect --skip
550 hg bisect --skip
551 hg bisect --skip 23
551 hg bisect --skip 23
552
552
553 - skip all revisions that do not touch directories ``foo`` or ``bar``
553 - skip all revisions that do not touch directories ``foo`` or ``bar``
554
554
555 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
555 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
556
556
557 - forget the current bisection::
557 - forget the current bisection::
558
558
559 hg bisect --reset
559 hg bisect --reset
560
560
561 - use 'make && make tests' to automatically find the first broken
561 - use 'make && make tests' to automatically find the first broken
562 revision::
562 revision::
563
563
564 hg bisect --reset
564 hg bisect --reset
565 hg bisect --bad 34
565 hg bisect --bad 34
566 hg bisect --good 12
566 hg bisect --good 12
567 hg bisect --command 'make && make tests'
567 hg bisect --command 'make && make tests'
568
568
569 - see all changesets whose states are already known in the current
569 - see all changesets whose states are already known in the current
570 bisection::
570 bisection::
571
571
572 hg log -r "bisect(pruned)"
572 hg log -r "bisect(pruned)"
573
573
574 - see the changeset currently being bisected (especially useful
574 - see the changeset currently being bisected (especially useful
575 if running with -U/--noupdate)::
575 if running with -U/--noupdate)::
576
576
577 hg log -r "bisect(current)"
577 hg log -r "bisect(current)"
578
578
579 - see all changesets that took part in the current bisection::
579 - see all changesets that took part in the current bisection::
580
580
581 hg log -r "bisect(range)"
581 hg log -r "bisect(range)"
582
582
583 - with the graphlog extension, you can even get a nice graph::
583 - with the graphlog extension, you can even get a nice graph::
584
584
585 hg log --graph -r "bisect(range)"
585 hg log --graph -r "bisect(range)"
586
586
587 See :hg:`help revsets` for more about the `bisect()` keyword.
587 See :hg:`help revsets` for more about the `bisect()` keyword.
588
588
589 Returns 0 on success.
589 Returns 0 on success.
590 """
590 """
591 def extendbisectrange(nodes, good):
591 def extendbisectrange(nodes, good):
592 # bisect is incomplete when it ends on a merge node and
592 # bisect is incomplete when it ends on a merge node and
593 # one of the parent was not checked.
593 # one of the parent was not checked.
594 parents = repo[nodes[0]].parents()
594 parents = repo[nodes[0]].parents()
595 if len(parents) > 1:
595 if len(parents) > 1:
596 side = good and state['bad'] or state['good']
596 side = good and state['bad'] or state['good']
597 num = len(set(i.node() for i in parents) & set(side))
597 num = len(set(i.node() for i in parents) & set(side))
598 if num == 1:
598 if num == 1:
599 return parents[0].ancestor(parents[1])
599 return parents[0].ancestor(parents[1])
600 return None
600 return None
601
601
602 def print_result(nodes, good):
602 def print_result(nodes, good):
603 displayer = cmdutil.show_changeset(ui, repo, {})
603 displayer = cmdutil.show_changeset(ui, repo, {})
604 if len(nodes) == 1:
604 if len(nodes) == 1:
605 # narrowed it down to a single revision
605 # narrowed it down to a single revision
606 if good:
606 if good:
607 ui.write(_("The first good revision is:\n"))
607 ui.write(_("The first good revision is:\n"))
608 else:
608 else:
609 ui.write(_("The first bad revision is:\n"))
609 ui.write(_("The first bad revision is:\n"))
610 displayer.show(repo[nodes[0]])
610 displayer.show(repo[nodes[0]])
611 extendnode = extendbisectrange(nodes, good)
611 extendnode = extendbisectrange(nodes, good)
612 if extendnode is not None:
612 if extendnode is not None:
613 ui.write(_('Not all ancestors of this changeset have been'
613 ui.write(_('Not all ancestors of this changeset have been'
614 ' checked.\nUse bisect --extend to continue the '
614 ' checked.\nUse bisect --extend to continue the '
615 'bisection from\nthe common ancestor, %s.\n')
615 'bisection from\nthe common ancestor, %s.\n')
616 % extendnode)
616 % extendnode)
617 else:
617 else:
618 # multiple possible revisions
618 # multiple possible revisions
619 if good:
619 if good:
620 ui.write(_("Due to skipped revisions, the first "
620 ui.write(_("Due to skipped revisions, the first "
621 "good revision could be any of:\n"))
621 "good revision could be any of:\n"))
622 else:
622 else:
623 ui.write(_("Due to skipped revisions, the first "
623 ui.write(_("Due to skipped revisions, the first "
624 "bad revision could be any of:\n"))
624 "bad revision could be any of:\n"))
625 for n in nodes:
625 for n in nodes:
626 displayer.show(repo[n])
626 displayer.show(repo[n])
627 displayer.close()
627 displayer.close()
628
628
629 def check_state(state, interactive=True):
629 def check_state(state, interactive=True):
630 if not state['good'] or not state['bad']:
630 if not state['good'] or not state['bad']:
631 if (good or bad or skip or reset) and interactive:
631 if (good or bad or skip or reset) and interactive:
632 return
632 return
633 if not state['good']:
633 if not state['good']:
634 raise util.Abort(_('cannot bisect (no known good revisions)'))
634 raise util.Abort(_('cannot bisect (no known good revisions)'))
635 else:
635 else:
636 raise util.Abort(_('cannot bisect (no known bad revisions)'))
636 raise util.Abort(_('cannot bisect (no known bad revisions)'))
637 return True
637 return True
638
638
639 # backward compatibility
639 # backward compatibility
640 if rev in "good bad reset init".split():
640 if rev in "good bad reset init".split():
641 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
641 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
642 cmd, rev, extra = rev, extra, None
642 cmd, rev, extra = rev, extra, None
643 if cmd == "good":
643 if cmd == "good":
644 good = True
644 good = True
645 elif cmd == "bad":
645 elif cmd == "bad":
646 bad = True
646 bad = True
647 else:
647 else:
648 reset = True
648 reset = True
649 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
649 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
650 raise util.Abort(_('incompatible arguments'))
650 raise util.Abort(_('incompatible arguments'))
651
651
652 if reset:
652 if reset:
653 p = repo.join("bisect.state")
653 p = repo.join("bisect.state")
654 if os.path.exists(p):
654 if os.path.exists(p):
655 os.unlink(p)
655 os.unlink(p)
656 return
656 return
657
657
658 state = hbisect.load_state(repo)
658 state = hbisect.load_state(repo)
659
659
660 if command:
660 if command:
661 changesets = 1
661 changesets = 1
662 try:
662 try:
663 node = state['current'][0]
663 node = state['current'][0]
664 except LookupError:
664 except LookupError:
665 if noupdate:
665 if noupdate:
666 raise util.Abort(_('current bisect revision is unknown - '
666 raise util.Abort(_('current bisect revision is unknown - '
667 'start a new bisect to fix'))
667 'start a new bisect to fix'))
668 node, p2 = repo.dirstate.parents()
668 node, p2 = repo.dirstate.parents()
669 if p2 != nullid:
669 if p2 != nullid:
670 raise util.Abort(_('current bisect revision is a merge'))
670 raise util.Abort(_('current bisect revision is a merge'))
671 try:
671 try:
672 while changesets:
672 while changesets:
673 # update state
673 # update state
674 state['current'] = [node]
674 state['current'] = [node]
675 hbisect.save_state(repo, state)
675 hbisect.save_state(repo, state)
676 status = util.system(command,
676 status = util.system(command,
677 environ={'HG_NODE': hex(node)},
677 environ={'HG_NODE': hex(node)},
678 out=ui.fout)
678 out=ui.fout)
679 if status == 125:
679 if status == 125:
680 transition = "skip"
680 transition = "skip"
681 elif status == 0:
681 elif status == 0:
682 transition = "good"
682 transition = "good"
683 # status < 0 means process was killed
683 # status < 0 means process was killed
684 elif status == 127:
684 elif status == 127:
685 raise util.Abort(_("failed to execute %s") % command)
685 raise util.Abort(_("failed to execute %s") % command)
686 elif status < 0:
686 elif status < 0:
687 raise util.Abort(_("%s killed") % command)
687 raise util.Abort(_("%s killed") % command)
688 else:
688 else:
689 transition = "bad"
689 transition = "bad"
690 ctx = scmutil.revsingle(repo, rev, node)
690 ctx = scmutil.revsingle(repo, rev, node)
691 rev = None # clear for future iterations
691 rev = None # clear for future iterations
692 state[transition].append(ctx.node())
692 state[transition].append(ctx.node())
693 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
693 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
694 check_state(state, interactive=False)
694 check_state(state, interactive=False)
695 # bisect
695 # bisect
696 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
696 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
697 # update to next check
697 # update to next check
698 node = nodes[0]
698 node = nodes[0]
699 if not noupdate:
699 if not noupdate:
700 cmdutil.bailifchanged(repo)
700 cmdutil.bailifchanged(repo)
701 hg.clean(repo, node, show_stats=False)
701 hg.clean(repo, node, show_stats=False)
702 finally:
702 finally:
703 state['current'] = [node]
703 state['current'] = [node]
704 hbisect.save_state(repo, state)
704 hbisect.save_state(repo, state)
705 print_result(nodes, good)
705 print_result(nodes, good)
706 return
706 return
707
707
708 # update state
708 # update state
709
709
710 if rev:
710 if rev:
711 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
711 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
712 else:
712 else:
713 nodes = [repo.lookup('.')]
713 nodes = [repo.lookup('.')]
714
714
715 if good or bad or skip:
715 if good or bad or skip:
716 if good:
716 if good:
717 state['good'] += nodes
717 state['good'] += nodes
718 elif bad:
718 elif bad:
719 state['bad'] += nodes
719 state['bad'] += nodes
720 elif skip:
720 elif skip:
721 state['skip'] += nodes
721 state['skip'] += nodes
722 hbisect.save_state(repo, state)
722 hbisect.save_state(repo, state)
723
723
724 if not check_state(state):
724 if not check_state(state):
725 return
725 return
726
726
727 # actually bisect
727 # actually bisect
728 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
728 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
729 if extend:
729 if extend:
730 if not changesets:
730 if not changesets:
731 extendnode = extendbisectrange(nodes, good)
731 extendnode = extendbisectrange(nodes, good)
732 if extendnode is not None:
732 if extendnode is not None:
733 ui.write(_("Extending search to changeset %d:%s\n"
733 ui.write(_("Extending search to changeset %d:%s\n"
734 % (extendnode.rev(), extendnode)))
734 % (extendnode.rev(), extendnode)))
735 state['current'] = [extendnode.node()]
735 state['current'] = [extendnode.node()]
736 hbisect.save_state(repo, state)
736 hbisect.save_state(repo, state)
737 if noupdate:
737 if noupdate:
738 return
738 return
739 cmdutil.bailifchanged(repo)
739 cmdutil.bailifchanged(repo)
740 return hg.clean(repo, extendnode.node())
740 return hg.clean(repo, extendnode.node())
741 raise util.Abort(_("nothing to extend"))
741 raise util.Abort(_("nothing to extend"))
742
742
743 if changesets == 0:
743 if changesets == 0:
744 print_result(nodes, good)
744 print_result(nodes, good)
745 else:
745 else:
746 assert len(nodes) == 1 # only a single node can be tested next
746 assert len(nodes) == 1 # only a single node can be tested next
747 node = nodes[0]
747 node = nodes[0]
748 # compute the approximate number of remaining tests
748 # compute the approximate number of remaining tests
749 tests, size = 0, 2
749 tests, size = 0, 2
750 while size <= changesets:
750 while size <= changesets:
751 tests, size = tests + 1, size * 2
751 tests, size = tests + 1, size * 2
752 rev = repo.changelog.rev(node)
752 rev = repo.changelog.rev(node)
753 ui.write(_("Testing changeset %d:%s "
753 ui.write(_("Testing changeset %d:%s "
754 "(%d changesets remaining, ~%d tests)\n")
754 "(%d changesets remaining, ~%d tests)\n")
755 % (rev, short(node), changesets, tests))
755 % (rev, short(node), changesets, tests))
756 state['current'] = [node]
756 state['current'] = [node]
757 hbisect.save_state(repo, state)
757 hbisect.save_state(repo, state)
758 if not noupdate:
758 if not noupdate:
759 cmdutil.bailifchanged(repo)
759 cmdutil.bailifchanged(repo)
760 return hg.clean(repo, node)
760 return hg.clean(repo, node)
761
761
762 @command('bookmarks|bookmark',
762 @command('bookmarks|bookmark',
763 [('f', 'force', False, _('force')),
763 [('f', 'force', False, _('force')),
764 ('r', 'rev', '', _('revision'), _('REV')),
764 ('r', 'rev', '', _('revision'), _('REV')),
765 ('d', 'delete', False, _('delete a given bookmark')),
765 ('d', 'delete', False, _('delete a given bookmark')),
766 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
766 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
767 ('i', 'inactive', False, _('mark a bookmark inactive'))],
767 ('i', 'inactive', False, _('mark a bookmark inactive'))],
768 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
768 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
769 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
769 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
770 rename=None, inactive=False):
770 rename=None, inactive=False):
771 '''track a line of development with movable markers
771 '''track a line of development with movable markers
772
772
773 Bookmarks are pointers to certain commits that move when committing.
773 Bookmarks are pointers to certain commits that move when committing.
774 Bookmarks are local. They can be renamed, copied and deleted. It is
774 Bookmarks are local. They can be renamed, copied and deleted. It is
775 possible to use :hg:`merge NAME` to merge from a given bookmark, and
775 possible to use :hg:`merge NAME` to merge from a given bookmark, and
776 :hg:`update NAME` to update to a given bookmark.
776 :hg:`update NAME` to update to a given bookmark.
777
777
778 You can use :hg:`bookmark NAME` to set a bookmark on the working
778 You can use :hg:`bookmark NAME` to set a bookmark on the working
779 directory's parent revision with the given name. If you specify
779 directory's parent revision with the given name. If you specify
780 a revision using -r REV (where REV may be an existing bookmark),
780 a revision using -r REV (where REV may be an existing bookmark),
781 the bookmark is assigned to that revision.
781 the bookmark is assigned to that revision.
782
782
783 Bookmarks can be pushed and pulled between repositories (see :hg:`help
783 Bookmarks can be pushed and pulled between repositories (see :hg:`help
784 push` and :hg:`help pull`). This requires both the local and remote
784 push` and :hg:`help pull`). This requires both the local and remote
785 repositories to support bookmarks. For versions prior to 1.8, this means
785 repositories to support bookmarks. For versions prior to 1.8, this means
786 the bookmarks extension must be enabled.
786 the bookmarks extension must be enabled.
787
787
788 If you set a bookmark called '@', new clones of the repository will
789 have that revision checked out (and the bookmark made active) by
790 default.
791
788 With -i/--inactive, the new bookmark will not be made the active
792 With -i/--inactive, the new bookmark will not be made the active
789 bookmark. If -r/--rev is given, the new bookmark will not be made
793 bookmark. If -r/--rev is given, the new bookmark will not be made
790 active even if -i/--inactive is not given. If no NAME is given, the
794 active even if -i/--inactive is not given. If no NAME is given, the
791 current active bookmark will be marked inactive.
795 current active bookmark will be marked inactive.
792 '''
796 '''
793 hexfn = ui.debugflag and hex or short
797 hexfn = ui.debugflag and hex or short
794 marks = repo._bookmarks
798 marks = repo._bookmarks
795 cur = repo.changectx('.').node()
799 cur = repo.changectx('.').node()
796
800
797 def checkformat(mark):
801 def checkformat(mark):
798 mark = mark.strip()
802 mark = mark.strip()
799 if not mark:
803 if not mark:
800 raise util.Abort(_("bookmark names cannot consist entirely of "
804 raise util.Abort(_("bookmark names cannot consist entirely of "
801 "whitespace"))
805 "whitespace"))
802 scmutil.checknewlabel(repo, mark, 'bookmark')
806 scmutil.checknewlabel(repo, mark, 'bookmark')
803 return mark
807 return mark
804
808
805 def checkconflict(repo, mark, force=False):
809 def checkconflict(repo, mark, force=False):
806 if mark in marks and not force:
810 if mark in marks and not force:
807 raise util.Abort(_("bookmark '%s' already exists "
811 raise util.Abort(_("bookmark '%s' already exists "
808 "(use -f to force)") % mark)
812 "(use -f to force)") % mark)
809 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
813 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
810 and not force):
814 and not force):
811 raise util.Abort(
815 raise util.Abort(
812 _("a bookmark cannot have the name of an existing branch"))
816 _("a bookmark cannot have the name of an existing branch"))
813
817
814 if delete and rename:
818 if delete and rename:
815 raise util.Abort(_("--delete and --rename are incompatible"))
819 raise util.Abort(_("--delete and --rename are incompatible"))
816 if delete and rev:
820 if delete and rev:
817 raise util.Abort(_("--rev is incompatible with --delete"))
821 raise util.Abort(_("--rev is incompatible with --delete"))
818 if rename and rev:
822 if rename and rev:
819 raise util.Abort(_("--rev is incompatible with --rename"))
823 raise util.Abort(_("--rev is incompatible with --rename"))
820 if mark is None and (delete or rev):
824 if mark is None and (delete or rev):
821 raise util.Abort(_("bookmark name required"))
825 raise util.Abort(_("bookmark name required"))
822
826
823 if delete:
827 if delete:
824 if mark not in marks:
828 if mark not in marks:
825 raise util.Abort(_("bookmark '%s' does not exist") % mark)
829 raise util.Abort(_("bookmark '%s' does not exist") % mark)
826 if mark == repo._bookmarkcurrent:
830 if mark == repo._bookmarkcurrent:
827 bookmarks.setcurrent(repo, None)
831 bookmarks.setcurrent(repo, None)
828 del marks[mark]
832 del marks[mark]
829 marks.write()
833 marks.write()
830
834
831 elif rename:
835 elif rename:
832 if mark is None:
836 if mark is None:
833 raise util.Abort(_("new bookmark name required"))
837 raise util.Abort(_("new bookmark name required"))
834 mark = checkformat(mark)
838 mark = checkformat(mark)
835 if rename not in marks:
839 if rename not in marks:
836 raise util.Abort(_("bookmark '%s' does not exist") % rename)
840 raise util.Abort(_("bookmark '%s' does not exist") % rename)
837 checkconflict(repo, mark, force)
841 checkconflict(repo, mark, force)
838 marks[mark] = marks[rename]
842 marks[mark] = marks[rename]
839 if repo._bookmarkcurrent == rename and not inactive:
843 if repo._bookmarkcurrent == rename and not inactive:
840 bookmarks.setcurrent(repo, mark)
844 bookmarks.setcurrent(repo, mark)
841 del marks[rename]
845 del marks[rename]
842 marks.write()
846 marks.write()
843
847
844 elif mark is not None:
848 elif mark is not None:
845 mark = checkformat(mark)
849 mark = checkformat(mark)
846 if inactive and mark == repo._bookmarkcurrent:
850 if inactive and mark == repo._bookmarkcurrent:
847 bookmarks.setcurrent(repo, None)
851 bookmarks.setcurrent(repo, None)
848 return
852 return
849 checkconflict(repo, mark, force)
853 checkconflict(repo, mark, force)
850 if rev:
854 if rev:
851 marks[mark] = scmutil.revsingle(repo, rev).node()
855 marks[mark] = scmutil.revsingle(repo, rev).node()
852 else:
856 else:
853 marks[mark] = cur
857 marks[mark] = cur
854 if not inactive and cur == marks[mark]:
858 if not inactive and cur == marks[mark]:
855 bookmarks.setcurrent(repo, mark)
859 bookmarks.setcurrent(repo, mark)
856 marks.write()
860 marks.write()
857
861
858 # Same message whether trying to deactivate the current bookmark (-i
862 # Same message whether trying to deactivate the current bookmark (-i
859 # with no NAME) or listing bookmarks
863 # with no NAME) or listing bookmarks
860 elif len(marks) == 0:
864 elif len(marks) == 0:
861 ui.status(_("no bookmarks set\n"))
865 ui.status(_("no bookmarks set\n"))
862
866
863 elif inactive:
867 elif inactive:
864 if not repo._bookmarkcurrent:
868 if not repo._bookmarkcurrent:
865 ui.status(_("no active bookmark\n"))
869 ui.status(_("no active bookmark\n"))
866 else:
870 else:
867 bookmarks.setcurrent(repo, None)
871 bookmarks.setcurrent(repo, None)
868
872
869 else: # show bookmarks
873 else: # show bookmarks
870 for bmark, n in sorted(marks.iteritems()):
874 for bmark, n in sorted(marks.iteritems()):
871 current = repo._bookmarkcurrent
875 current = repo._bookmarkcurrent
872 if bmark == current and n == cur:
876 if bmark == current and n == cur:
873 prefix, label = '*', 'bookmarks.current'
877 prefix, label = '*', 'bookmarks.current'
874 else:
878 else:
875 prefix, label = ' ', ''
879 prefix, label = ' ', ''
876
880
877 if ui.quiet:
881 if ui.quiet:
878 ui.write("%s\n" % bmark, label=label)
882 ui.write("%s\n" % bmark, label=label)
879 else:
883 else:
880 ui.write(" %s %-25s %d:%s\n" % (
884 ui.write(" %s %-25s %d:%s\n" % (
881 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
885 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
882 label=label)
886 label=label)
883
887
884 @command('branch',
888 @command('branch',
885 [('f', 'force', None,
889 [('f', 'force', None,
886 _('set branch name even if it shadows an existing branch')),
890 _('set branch name even if it shadows an existing branch')),
887 ('C', 'clean', None, _('reset branch name to parent branch name'))],
891 ('C', 'clean', None, _('reset branch name to parent branch name'))],
888 _('[-fC] [NAME]'))
892 _('[-fC] [NAME]'))
889 def branch(ui, repo, label=None, **opts):
893 def branch(ui, repo, label=None, **opts):
890 """set or show the current branch name
894 """set or show the current branch name
891
895
892 .. note::
896 .. note::
893 Branch names are permanent and global. Use :hg:`bookmark` to create a
897 Branch names are permanent and global. Use :hg:`bookmark` to create a
894 light-weight bookmark instead. See :hg:`help glossary` for more
898 light-weight bookmark instead. See :hg:`help glossary` for more
895 information about named branches and bookmarks.
899 information about named branches and bookmarks.
896
900
897 With no argument, show the current branch name. With one argument,
901 With no argument, show the current branch name. With one argument,
898 set the working directory branch name (the branch will not exist
902 set the working directory branch name (the branch will not exist
899 in the repository until the next commit). Standard practice
903 in the repository until the next commit). Standard practice
900 recommends that primary development take place on the 'default'
904 recommends that primary development take place on the 'default'
901 branch.
905 branch.
902
906
903 Unless -f/--force is specified, branch will not let you set a
907 Unless -f/--force is specified, branch will not let you set a
904 branch name that already exists, even if it's inactive.
908 branch name that already exists, even if it's inactive.
905
909
906 Use -C/--clean to reset the working directory branch to that of
910 Use -C/--clean to reset the working directory branch to that of
907 the parent of the working directory, negating a previous branch
911 the parent of the working directory, negating a previous branch
908 change.
912 change.
909
913
910 Use the command :hg:`update` to switch to an existing branch. Use
914 Use the command :hg:`update` to switch to an existing branch. Use
911 :hg:`commit --close-branch` to mark this branch as closed.
915 :hg:`commit --close-branch` to mark this branch as closed.
912
916
913 Returns 0 on success.
917 Returns 0 on success.
914 """
918 """
915 if not opts.get('clean') and not label:
919 if not opts.get('clean') and not label:
916 ui.write("%s\n" % repo.dirstate.branch())
920 ui.write("%s\n" % repo.dirstate.branch())
917 return
921 return
918
922
919 wlock = repo.wlock()
923 wlock = repo.wlock()
920 try:
924 try:
921 if opts.get('clean'):
925 if opts.get('clean'):
922 label = repo[None].p1().branch()
926 label = repo[None].p1().branch()
923 repo.dirstate.setbranch(label)
927 repo.dirstate.setbranch(label)
924 ui.status(_('reset working directory to branch %s\n') % label)
928 ui.status(_('reset working directory to branch %s\n') % label)
925 elif label:
929 elif label:
926 if not opts.get('force') and label in repo.branchmap():
930 if not opts.get('force') and label in repo.branchmap():
927 if label not in [p.branch() for p in repo.parents()]:
931 if label not in [p.branch() for p in repo.parents()]:
928 raise util.Abort(_('a branch of the same name already'
932 raise util.Abort(_('a branch of the same name already'
929 ' exists'),
933 ' exists'),
930 # i18n: "it" refers to an existing branch
934 # i18n: "it" refers to an existing branch
931 hint=_("use 'hg update' to switch to it"))
935 hint=_("use 'hg update' to switch to it"))
932 scmutil.checknewlabel(repo, label, 'branch')
936 scmutil.checknewlabel(repo, label, 'branch')
933 repo.dirstate.setbranch(label)
937 repo.dirstate.setbranch(label)
934 ui.status(_('marked working directory as branch %s\n') % label)
938 ui.status(_('marked working directory as branch %s\n') % label)
935 ui.status(_('(branches are permanent and global, '
939 ui.status(_('(branches are permanent and global, '
936 'did you want a bookmark?)\n'))
940 'did you want a bookmark?)\n'))
937 finally:
941 finally:
938 wlock.release()
942 wlock.release()
939
943
940 @command('branches',
944 @command('branches',
941 [('a', 'active', False, _('show only branches that have unmerged heads')),
945 [('a', 'active', False, _('show only branches that have unmerged heads')),
942 ('c', 'closed', False, _('show normal and closed branches'))],
946 ('c', 'closed', False, _('show normal and closed branches'))],
943 _('[-ac]'))
947 _('[-ac]'))
944 def branches(ui, repo, active=False, closed=False):
948 def branches(ui, repo, active=False, closed=False):
945 """list repository named branches
949 """list repository named branches
946
950
947 List the repository's named branches, indicating which ones are
951 List the repository's named branches, indicating which ones are
948 inactive. If -c/--closed is specified, also list branches which have
952 inactive. If -c/--closed is specified, also list branches which have
949 been marked closed (see :hg:`commit --close-branch`).
953 been marked closed (see :hg:`commit --close-branch`).
950
954
951 If -a/--active is specified, only show active branches. A branch
955 If -a/--active is specified, only show active branches. A branch
952 is considered active if it contains repository heads.
956 is considered active if it contains repository heads.
953
957
954 Use the command :hg:`update` to switch to an existing branch.
958 Use the command :hg:`update` to switch to an existing branch.
955
959
956 Returns 0.
960 Returns 0.
957 """
961 """
958
962
959 hexfunc = ui.debugflag and hex or short
963 hexfunc = ui.debugflag and hex or short
960
964
961 activebranches = set([repo[n].branch() for n in repo.heads()])
965 activebranches = set([repo[n].branch() for n in repo.heads()])
962 branches = []
966 branches = []
963 for tag, heads in repo.branchmap().iteritems():
967 for tag, heads in repo.branchmap().iteritems():
964 for h in reversed(heads):
968 for h in reversed(heads):
965 ctx = repo[h]
969 ctx = repo[h]
966 isopen = not ctx.closesbranch()
970 isopen = not ctx.closesbranch()
967 if isopen:
971 if isopen:
968 tip = ctx
972 tip = ctx
969 break
973 break
970 else:
974 else:
971 tip = repo[heads[-1]]
975 tip = repo[heads[-1]]
972 isactive = tag in activebranches and isopen
976 isactive = tag in activebranches and isopen
973 branches.append((tip, isactive, isopen))
977 branches.append((tip, isactive, isopen))
974 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
978 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
975 reverse=True)
979 reverse=True)
976
980
977 for ctx, isactive, isopen in branches:
981 for ctx, isactive, isopen in branches:
978 if (not active) or isactive:
982 if (not active) or isactive:
979 if isactive:
983 if isactive:
980 label = 'branches.active'
984 label = 'branches.active'
981 notice = ''
985 notice = ''
982 elif not isopen:
986 elif not isopen:
983 if not closed:
987 if not closed:
984 continue
988 continue
985 label = 'branches.closed'
989 label = 'branches.closed'
986 notice = _(' (closed)')
990 notice = _(' (closed)')
987 else:
991 else:
988 label = 'branches.inactive'
992 label = 'branches.inactive'
989 notice = _(' (inactive)')
993 notice = _(' (inactive)')
990 if ctx.branch() == repo.dirstate.branch():
994 if ctx.branch() == repo.dirstate.branch():
991 label = 'branches.current'
995 label = 'branches.current'
992 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
996 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
993 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
997 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
994 'log.changeset changeset.%s' % ctx.phasestr())
998 'log.changeset changeset.%s' % ctx.phasestr())
995 tag = ui.label(ctx.branch(), label)
999 tag = ui.label(ctx.branch(), label)
996 if ui.quiet:
1000 if ui.quiet:
997 ui.write("%s\n" % tag)
1001 ui.write("%s\n" % tag)
998 else:
1002 else:
999 ui.write("%s %s%s\n" % (tag, rev, notice))
1003 ui.write("%s %s%s\n" % (tag, rev, notice))
1000
1004
1001 @command('bundle',
1005 @command('bundle',
1002 [('f', 'force', None, _('run even when the destination is unrelated')),
1006 [('f', 'force', None, _('run even when the destination is unrelated')),
1003 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1007 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1004 _('REV')),
1008 _('REV')),
1005 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1009 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1006 _('BRANCH')),
1010 _('BRANCH')),
1007 ('', 'base', [],
1011 ('', 'base', [],
1008 _('a base changeset assumed to be available at the destination'),
1012 _('a base changeset assumed to be available at the destination'),
1009 _('REV')),
1013 _('REV')),
1010 ('a', 'all', None, _('bundle all changesets in the repository')),
1014 ('a', 'all', None, _('bundle all changesets in the repository')),
1011 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1015 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1012 ] + remoteopts,
1016 ] + remoteopts,
1013 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1017 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1014 def bundle(ui, repo, fname, dest=None, **opts):
1018 def bundle(ui, repo, fname, dest=None, **opts):
1015 """create a changegroup file
1019 """create a changegroup file
1016
1020
1017 Generate a compressed changegroup file collecting changesets not
1021 Generate a compressed changegroup file collecting changesets not
1018 known to be in another repository.
1022 known to be in another repository.
1019
1023
1020 If you omit the destination repository, then hg assumes the
1024 If you omit the destination repository, then hg assumes the
1021 destination will have all the nodes you specify with --base
1025 destination will have all the nodes you specify with --base
1022 parameters. To create a bundle containing all changesets, use
1026 parameters. To create a bundle containing all changesets, use
1023 -a/--all (or --base null).
1027 -a/--all (or --base null).
1024
1028
1025 You can change compression method with the -t/--type option.
1029 You can change compression method with the -t/--type option.
1026 The available compression methods are: none, bzip2, and
1030 The available compression methods are: none, bzip2, and
1027 gzip (by default, bundles are compressed using bzip2).
1031 gzip (by default, bundles are compressed using bzip2).
1028
1032
1029 The bundle file can then be transferred using conventional means
1033 The bundle file can then be transferred using conventional means
1030 and applied to another repository with the unbundle or pull
1034 and applied to another repository with the unbundle or pull
1031 command. This is useful when direct push and pull are not
1035 command. This is useful when direct push and pull are not
1032 available or when exporting an entire repository is undesirable.
1036 available or when exporting an entire repository is undesirable.
1033
1037
1034 Applying bundles preserves all changeset contents including
1038 Applying bundles preserves all changeset contents including
1035 permissions, copy/rename information, and revision history.
1039 permissions, copy/rename information, and revision history.
1036
1040
1037 Returns 0 on success, 1 if no changes found.
1041 Returns 0 on success, 1 if no changes found.
1038 """
1042 """
1039 revs = None
1043 revs = None
1040 if 'rev' in opts:
1044 if 'rev' in opts:
1041 revs = scmutil.revrange(repo, opts['rev'])
1045 revs = scmutil.revrange(repo, opts['rev'])
1042
1046
1043 bundletype = opts.get('type', 'bzip2').lower()
1047 bundletype = opts.get('type', 'bzip2').lower()
1044 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1048 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1045 bundletype = btypes.get(bundletype)
1049 bundletype = btypes.get(bundletype)
1046 if bundletype not in changegroup.bundletypes:
1050 if bundletype not in changegroup.bundletypes:
1047 raise util.Abort(_('unknown bundle type specified with --type'))
1051 raise util.Abort(_('unknown bundle type specified with --type'))
1048
1052
1049 if opts.get('all'):
1053 if opts.get('all'):
1050 base = ['null']
1054 base = ['null']
1051 else:
1055 else:
1052 base = scmutil.revrange(repo, opts.get('base'))
1056 base = scmutil.revrange(repo, opts.get('base'))
1053 if base:
1057 if base:
1054 if dest:
1058 if dest:
1055 raise util.Abort(_("--base is incompatible with specifying "
1059 raise util.Abort(_("--base is incompatible with specifying "
1056 "a destination"))
1060 "a destination"))
1057 common = [repo.lookup(rev) for rev in base]
1061 common = [repo.lookup(rev) for rev in base]
1058 heads = revs and map(repo.lookup, revs) or revs
1062 heads = revs and map(repo.lookup, revs) or revs
1059 cg = repo.getbundle('bundle', heads=heads, common=common)
1063 cg = repo.getbundle('bundle', heads=heads, common=common)
1060 outgoing = None
1064 outgoing = None
1061 else:
1065 else:
1062 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1066 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1063 dest, branches = hg.parseurl(dest, opts.get('branch'))
1067 dest, branches = hg.parseurl(dest, opts.get('branch'))
1064 other = hg.peer(repo, opts, dest)
1068 other = hg.peer(repo, opts, dest)
1065 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1069 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1066 heads = revs and map(repo.lookup, revs) or revs
1070 heads = revs and map(repo.lookup, revs) or revs
1067 outgoing = discovery.findcommonoutgoing(repo, other,
1071 outgoing = discovery.findcommonoutgoing(repo, other,
1068 onlyheads=heads,
1072 onlyheads=heads,
1069 force=opts.get('force'),
1073 force=opts.get('force'),
1070 portable=True)
1074 portable=True)
1071 cg = repo.getlocalbundle('bundle', outgoing)
1075 cg = repo.getlocalbundle('bundle', outgoing)
1072 if not cg:
1076 if not cg:
1073 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1077 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1074 return 1
1078 return 1
1075
1079
1076 changegroup.writebundle(cg, fname, bundletype)
1080 changegroup.writebundle(cg, fname, bundletype)
1077
1081
1078 @command('cat',
1082 @command('cat',
1079 [('o', 'output', '',
1083 [('o', 'output', '',
1080 _('print output to file with formatted name'), _('FORMAT')),
1084 _('print output to file with formatted name'), _('FORMAT')),
1081 ('r', 'rev', '', _('print the given revision'), _('REV')),
1085 ('r', 'rev', '', _('print the given revision'), _('REV')),
1082 ('', 'decode', None, _('apply any matching decode filter')),
1086 ('', 'decode', None, _('apply any matching decode filter')),
1083 ] + walkopts,
1087 ] + walkopts,
1084 _('[OPTION]... FILE...'))
1088 _('[OPTION]... FILE...'))
1085 def cat(ui, repo, file1, *pats, **opts):
1089 def cat(ui, repo, file1, *pats, **opts):
1086 """output the current or given revision of files
1090 """output the current or given revision of files
1087
1091
1088 Print the specified files as they were at the given revision. If
1092 Print the specified files as they were at the given revision. If
1089 no revision is given, the parent of the working directory is used,
1093 no revision is given, the parent of the working directory is used,
1090 or tip if no revision is checked out.
1094 or tip if no revision is checked out.
1091
1095
1092 Output may be to a file, in which case the name of the file is
1096 Output may be to a file, in which case the name of the file is
1093 given using a format string. The formatting rules are the same as
1097 given using a format string. The formatting rules are the same as
1094 for the export command, with the following additions:
1098 for the export command, with the following additions:
1095
1099
1096 :``%s``: basename of file being printed
1100 :``%s``: basename of file being printed
1097 :``%d``: dirname of file being printed, or '.' if in repository root
1101 :``%d``: dirname of file being printed, or '.' if in repository root
1098 :``%p``: root-relative path name of file being printed
1102 :``%p``: root-relative path name of file being printed
1099
1103
1100 Returns 0 on success.
1104 Returns 0 on success.
1101 """
1105 """
1102 ctx = scmutil.revsingle(repo, opts.get('rev'))
1106 ctx = scmutil.revsingle(repo, opts.get('rev'))
1103 err = 1
1107 err = 1
1104 m = scmutil.match(ctx, (file1,) + pats, opts)
1108 m = scmutil.match(ctx, (file1,) + pats, opts)
1105 for abs in ctx.walk(m):
1109 for abs in ctx.walk(m):
1106 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1110 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1107 pathname=abs)
1111 pathname=abs)
1108 data = ctx[abs].data()
1112 data = ctx[abs].data()
1109 if opts.get('decode'):
1113 if opts.get('decode'):
1110 data = repo.wwritedata(abs, data)
1114 data = repo.wwritedata(abs, data)
1111 fp.write(data)
1115 fp.write(data)
1112 fp.close()
1116 fp.close()
1113 err = 0
1117 err = 0
1114 return err
1118 return err
1115
1119
1116 @command('^clone',
1120 @command('^clone',
1117 [('U', 'noupdate', None,
1121 [('U', 'noupdate', None,
1118 _('the clone will include an empty working copy (only a repository)')),
1122 _('the clone will include an empty working copy (only a repository)')),
1119 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1123 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1120 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1124 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1121 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1125 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1122 ('', 'pull', None, _('use pull protocol to copy metadata')),
1126 ('', 'pull', None, _('use pull protocol to copy metadata')),
1123 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1127 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1124 ] + remoteopts,
1128 ] + remoteopts,
1125 _('[OPTION]... SOURCE [DEST]'))
1129 _('[OPTION]... SOURCE [DEST]'))
1126 def clone(ui, source, dest=None, **opts):
1130 def clone(ui, source, dest=None, **opts):
1127 """make a copy of an existing repository
1131 """make a copy of an existing repository
1128
1132
1129 Create a copy of an existing repository in a new directory.
1133 Create a copy of an existing repository in a new directory.
1130
1134
1131 If no destination directory name is specified, it defaults to the
1135 If no destination directory name is specified, it defaults to the
1132 basename of the source.
1136 basename of the source.
1133
1137
1134 The location of the source is added to the new repository's
1138 The location of the source is added to the new repository's
1135 ``.hg/hgrc`` file, as the default to be used for future pulls.
1139 ``.hg/hgrc`` file, as the default to be used for future pulls.
1136
1140
1137 Only local paths and ``ssh://`` URLs are supported as
1141 Only local paths and ``ssh://`` URLs are supported as
1138 destinations. For ``ssh://`` destinations, no working directory or
1142 destinations. For ``ssh://`` destinations, no working directory or
1139 ``.hg/hgrc`` will be created on the remote side.
1143 ``.hg/hgrc`` will be created on the remote side.
1140
1144
1141 To pull only a subset of changesets, specify one or more revisions
1145 To pull only a subset of changesets, specify one or more revisions
1142 identifiers with -r/--rev or branches with -b/--branch. The
1146 identifiers with -r/--rev or branches with -b/--branch. The
1143 resulting clone will contain only the specified changesets and
1147 resulting clone will contain only the specified changesets and
1144 their ancestors. These options (or 'clone src#rev dest') imply
1148 their ancestors. These options (or 'clone src#rev dest') imply
1145 --pull, even for local source repositories. Note that specifying a
1149 --pull, even for local source repositories. Note that specifying a
1146 tag will include the tagged changeset but not the changeset
1150 tag will include the tagged changeset but not the changeset
1147 containing the tag.
1151 containing the tag.
1148
1152
1153 If the source repository has a bookmark called '@' set, that
1154 revision will be checked out in the new repository by default.
1155
1149 To check out a particular version, use -u/--update, or
1156 To check out a particular version, use -u/--update, or
1150 -U/--noupdate to create a clone with no working directory.
1157 -U/--noupdate to create a clone with no working directory.
1151
1158
1152 .. container:: verbose
1159 .. container:: verbose
1153
1160
1154 For efficiency, hardlinks are used for cloning whenever the
1161 For efficiency, hardlinks are used for cloning whenever the
1155 source and destination are on the same filesystem (note this
1162 source and destination are on the same filesystem (note this
1156 applies only to the repository data, not to the working
1163 applies only to the repository data, not to the working
1157 directory). Some filesystems, such as AFS, implement hardlinking
1164 directory). Some filesystems, such as AFS, implement hardlinking
1158 incorrectly, but do not report errors. In these cases, use the
1165 incorrectly, but do not report errors. In these cases, use the
1159 --pull option to avoid hardlinking.
1166 --pull option to avoid hardlinking.
1160
1167
1161 In some cases, you can clone repositories and the working
1168 In some cases, you can clone repositories and the working
1162 directory using full hardlinks with ::
1169 directory using full hardlinks with ::
1163
1170
1164 $ cp -al REPO REPOCLONE
1171 $ cp -al REPO REPOCLONE
1165
1172
1166 This is the fastest way to clone, but it is not always safe. The
1173 This is the fastest way to clone, but it is not always safe. The
1167 operation is not atomic (making sure REPO is not modified during
1174 operation is not atomic (making sure REPO is not modified during
1168 the operation is up to you) and you have to make sure your
1175 the operation is up to you) and you have to make sure your
1169 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1176 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1170 so). Also, this is not compatible with certain extensions that
1177 so). Also, this is not compatible with certain extensions that
1171 place their metadata under the .hg directory, such as mq.
1178 place their metadata under the .hg directory, such as mq.
1172
1179
1173 Mercurial will update the working directory to the first applicable
1180 Mercurial will update the working directory to the first applicable
1174 revision from this list:
1181 revision from this list:
1175
1182
1176 a) null if -U or the source repository has no changesets
1183 a) null if -U or the source repository has no changesets
1177 b) if -u . and the source repository is local, the first parent of
1184 b) if -u . and the source repository is local, the first parent of
1178 the source repository's working directory
1185 the source repository's working directory
1179 c) the changeset specified with -u (if a branch name, this means the
1186 c) the changeset specified with -u (if a branch name, this means the
1180 latest head of that branch)
1187 latest head of that branch)
1181 d) the changeset specified with -r
1188 d) the changeset specified with -r
1182 e) the tipmost head specified with -b
1189 e) the tipmost head specified with -b
1183 f) the tipmost head specified with the url#branch source syntax
1190 f) the tipmost head specified with the url#branch source syntax
1184 g) the tipmost head of the default branch
1191 g) the tipmost head of the default branch
1185 h) tip
1192 h) tip
1186
1193
1187 Examples:
1194 Examples:
1188
1195
1189 - clone a remote repository to a new directory named hg/::
1196 - clone a remote repository to a new directory named hg/::
1190
1197
1191 hg clone http://selenic.com/hg
1198 hg clone http://selenic.com/hg
1192
1199
1193 - create a lightweight local clone::
1200 - create a lightweight local clone::
1194
1201
1195 hg clone project/ project-feature/
1202 hg clone project/ project-feature/
1196
1203
1197 - clone from an absolute path on an ssh server (note double-slash)::
1204 - clone from an absolute path on an ssh server (note double-slash)::
1198
1205
1199 hg clone ssh://user@server//home/projects/alpha/
1206 hg clone ssh://user@server//home/projects/alpha/
1200
1207
1201 - do a high-speed clone over a LAN while checking out a
1208 - do a high-speed clone over a LAN while checking out a
1202 specified version::
1209 specified version::
1203
1210
1204 hg clone --uncompressed http://server/repo -u 1.5
1211 hg clone --uncompressed http://server/repo -u 1.5
1205
1212
1206 - create a repository without changesets after a particular revision::
1213 - create a repository without changesets after a particular revision::
1207
1214
1208 hg clone -r 04e544 experimental/ good/
1215 hg clone -r 04e544 experimental/ good/
1209
1216
1210 - clone (and track) a particular named branch::
1217 - clone (and track) a particular named branch::
1211
1218
1212 hg clone http://selenic.com/hg#stable
1219 hg clone http://selenic.com/hg#stable
1213
1220
1214 See :hg:`help urls` for details on specifying URLs.
1221 See :hg:`help urls` for details on specifying URLs.
1215
1222
1216 Returns 0 on success.
1223 Returns 0 on success.
1217 """
1224 """
1218 if opts.get('noupdate') and opts.get('updaterev'):
1225 if opts.get('noupdate') and opts.get('updaterev'):
1219 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1226 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1220
1227
1221 r = hg.clone(ui, opts, source, dest,
1228 r = hg.clone(ui, opts, source, dest,
1222 pull=opts.get('pull'),
1229 pull=opts.get('pull'),
1223 stream=opts.get('uncompressed'),
1230 stream=opts.get('uncompressed'),
1224 rev=opts.get('rev'),
1231 rev=opts.get('rev'),
1225 update=opts.get('updaterev') or not opts.get('noupdate'),
1232 update=opts.get('updaterev') or not opts.get('noupdate'),
1226 branch=opts.get('branch'))
1233 branch=opts.get('branch'))
1227
1234
1228 return r is None
1235 return r is None
1229
1236
1230 @command('^commit|ci',
1237 @command('^commit|ci',
1231 [('A', 'addremove', None,
1238 [('A', 'addremove', None,
1232 _('mark new/missing files as added/removed before committing')),
1239 _('mark new/missing files as added/removed before committing')),
1233 ('', 'close-branch', None,
1240 ('', 'close-branch', None,
1234 _('mark a branch as closed, hiding it from the branch list')),
1241 _('mark a branch as closed, hiding it from the branch list')),
1235 ('', 'amend', None, _('amend the parent of the working dir')),
1242 ('', 'amend', None, _('amend the parent of the working dir')),
1236 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1243 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1237 _('[OPTION]... [FILE]...'))
1244 _('[OPTION]... [FILE]...'))
1238 def commit(ui, repo, *pats, **opts):
1245 def commit(ui, repo, *pats, **opts):
1239 """commit the specified files or all outstanding changes
1246 """commit the specified files or all outstanding changes
1240
1247
1241 Commit changes to the given files into the repository. Unlike a
1248 Commit changes to the given files into the repository. Unlike a
1242 centralized SCM, this operation is a local operation. See
1249 centralized SCM, this operation is a local operation. See
1243 :hg:`push` for a way to actively distribute your changes.
1250 :hg:`push` for a way to actively distribute your changes.
1244
1251
1245 If a list of files is omitted, all changes reported by :hg:`status`
1252 If a list of files is omitted, all changes reported by :hg:`status`
1246 will be committed.
1253 will be committed.
1247
1254
1248 If you are committing the result of a merge, do not provide any
1255 If you are committing the result of a merge, do not provide any
1249 filenames or -I/-X filters.
1256 filenames or -I/-X filters.
1250
1257
1251 If no commit message is specified, Mercurial starts your
1258 If no commit message is specified, Mercurial starts your
1252 configured editor where you can enter a message. In case your
1259 configured editor where you can enter a message. In case your
1253 commit fails, you will find a backup of your message in
1260 commit fails, you will find a backup of your message in
1254 ``.hg/last-message.txt``.
1261 ``.hg/last-message.txt``.
1255
1262
1256 The --amend flag can be used to amend the parent of the
1263 The --amend flag can be used to amend the parent of the
1257 working directory with a new commit that contains the changes
1264 working directory with a new commit that contains the changes
1258 in the parent in addition to those currently reported by :hg:`status`,
1265 in the parent in addition to those currently reported by :hg:`status`,
1259 if there are any. The old commit is stored in a backup bundle in
1266 if there are any. The old commit is stored in a backup bundle in
1260 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1267 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1261 on how to restore it).
1268 on how to restore it).
1262
1269
1263 Message, user and date are taken from the amended commit unless
1270 Message, user and date are taken from the amended commit unless
1264 specified. When a message isn't specified on the command line,
1271 specified. When a message isn't specified on the command line,
1265 the editor will open with the message of the amended commit.
1272 the editor will open with the message of the amended commit.
1266
1273
1267 It is not possible to amend public changesets (see :hg:`help phases`)
1274 It is not possible to amend public changesets (see :hg:`help phases`)
1268 or changesets that have children.
1275 or changesets that have children.
1269
1276
1270 See :hg:`help dates` for a list of formats valid for -d/--date.
1277 See :hg:`help dates` for a list of formats valid for -d/--date.
1271
1278
1272 Returns 0 on success, 1 if nothing changed.
1279 Returns 0 on success, 1 if nothing changed.
1273 """
1280 """
1274 if opts.get('subrepos'):
1281 if opts.get('subrepos'):
1275 # Let --subrepos on the command line override config setting.
1282 # Let --subrepos on the command line override config setting.
1276 ui.setconfig('ui', 'commitsubrepos', True)
1283 ui.setconfig('ui', 'commitsubrepos', True)
1277
1284
1278 extra = {}
1285 extra = {}
1279 if opts.get('close_branch'):
1286 if opts.get('close_branch'):
1280 if repo['.'].node() not in repo.branchheads():
1287 if repo['.'].node() not in repo.branchheads():
1281 # The topo heads set is included in the branch heads set of the
1288 # The topo heads set is included in the branch heads set of the
1282 # current branch, so it's sufficient to test branchheads
1289 # current branch, so it's sufficient to test branchheads
1283 raise util.Abort(_('can only close branch heads'))
1290 raise util.Abort(_('can only close branch heads'))
1284 extra['close'] = 1
1291 extra['close'] = 1
1285
1292
1286 branch = repo[None].branch()
1293 branch = repo[None].branch()
1287 bheads = repo.branchheads(branch)
1294 bheads = repo.branchheads(branch)
1288
1295
1289 if opts.get('amend'):
1296 if opts.get('amend'):
1290 if ui.configbool('ui', 'commitsubrepos'):
1297 if ui.configbool('ui', 'commitsubrepos'):
1291 raise util.Abort(_('cannot amend recursively'))
1298 raise util.Abort(_('cannot amend recursively'))
1292
1299
1293 old = repo['.']
1300 old = repo['.']
1294 if old.phase() == phases.public:
1301 if old.phase() == phases.public:
1295 raise util.Abort(_('cannot amend public changesets'))
1302 raise util.Abort(_('cannot amend public changesets'))
1296 if len(old.parents()) > 1:
1303 if len(old.parents()) > 1:
1297 raise util.Abort(_('cannot amend merge changesets'))
1304 raise util.Abort(_('cannot amend merge changesets'))
1298 if len(repo[None].parents()) > 1:
1305 if len(repo[None].parents()) > 1:
1299 raise util.Abort(_('cannot amend while merging'))
1306 raise util.Abort(_('cannot amend while merging'))
1300 if (not obsolete._enabled) and old.children():
1307 if (not obsolete._enabled) and old.children():
1301 raise util.Abort(_('cannot amend changeset with children'))
1308 raise util.Abort(_('cannot amend changeset with children'))
1302
1309
1303 e = cmdutil.commiteditor
1310 e = cmdutil.commiteditor
1304 if opts.get('force_editor'):
1311 if opts.get('force_editor'):
1305 e = cmdutil.commitforceeditor
1312 e = cmdutil.commitforceeditor
1306
1313
1307 def commitfunc(ui, repo, message, match, opts):
1314 def commitfunc(ui, repo, message, match, opts):
1308 editor = e
1315 editor = e
1309 # message contains text from -m or -l, if it's empty,
1316 # message contains text from -m or -l, if it's empty,
1310 # open the editor with the old message
1317 # open the editor with the old message
1311 if not message:
1318 if not message:
1312 message = old.description()
1319 message = old.description()
1313 editor = cmdutil.commitforceeditor
1320 editor = cmdutil.commitforceeditor
1314 return repo.commit(message,
1321 return repo.commit(message,
1315 opts.get('user') or old.user(),
1322 opts.get('user') or old.user(),
1316 opts.get('date') or old.date(),
1323 opts.get('date') or old.date(),
1317 match,
1324 match,
1318 editor=editor,
1325 editor=editor,
1319 extra=extra)
1326 extra=extra)
1320
1327
1321 current = repo._bookmarkcurrent
1328 current = repo._bookmarkcurrent
1322 marks = old.bookmarks()
1329 marks = old.bookmarks()
1323 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1330 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1324 if node == old.node():
1331 if node == old.node():
1325 ui.status(_("nothing changed\n"))
1332 ui.status(_("nothing changed\n"))
1326 return 1
1333 return 1
1327 elif marks:
1334 elif marks:
1328 ui.debug('moving bookmarks %r from %s to %s\n' %
1335 ui.debug('moving bookmarks %r from %s to %s\n' %
1329 (marks, old.hex(), hex(node)))
1336 (marks, old.hex(), hex(node)))
1330 newmarks = repo._bookmarks
1337 newmarks = repo._bookmarks
1331 for bm in marks:
1338 for bm in marks:
1332 newmarks[bm] = node
1339 newmarks[bm] = node
1333 if bm == current:
1340 if bm == current:
1334 bookmarks.setcurrent(repo, bm)
1341 bookmarks.setcurrent(repo, bm)
1335 newmarks.write()
1342 newmarks.write()
1336 else:
1343 else:
1337 e = cmdutil.commiteditor
1344 e = cmdutil.commiteditor
1338 if opts.get('force_editor'):
1345 if opts.get('force_editor'):
1339 e = cmdutil.commitforceeditor
1346 e = cmdutil.commitforceeditor
1340
1347
1341 def commitfunc(ui, repo, message, match, opts):
1348 def commitfunc(ui, repo, message, match, opts):
1342 return repo.commit(message, opts.get('user'), opts.get('date'),
1349 return repo.commit(message, opts.get('user'), opts.get('date'),
1343 match, editor=e, extra=extra)
1350 match, editor=e, extra=extra)
1344
1351
1345 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1352 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1346
1353
1347 if not node:
1354 if not node:
1348 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1355 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1349 if stat[3]:
1356 if stat[3]:
1350 ui.status(_("nothing changed (%d missing files, see "
1357 ui.status(_("nothing changed (%d missing files, see "
1351 "'hg status')\n") % len(stat[3]))
1358 "'hg status')\n") % len(stat[3]))
1352 else:
1359 else:
1353 ui.status(_("nothing changed\n"))
1360 ui.status(_("nothing changed\n"))
1354 return 1
1361 return 1
1355
1362
1356 ctx = repo[node]
1363 ctx = repo[node]
1357 parents = ctx.parents()
1364 parents = ctx.parents()
1358
1365
1359 if (not opts.get('amend') and bheads and node not in bheads and not
1366 if (not opts.get('amend') and bheads and node not in bheads and not
1360 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1367 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1361 ui.status(_('created new head\n'))
1368 ui.status(_('created new head\n'))
1362 # The message is not printed for initial roots. For the other
1369 # The message is not printed for initial roots. For the other
1363 # changesets, it is printed in the following situations:
1370 # changesets, it is printed in the following situations:
1364 #
1371 #
1365 # Par column: for the 2 parents with ...
1372 # Par column: for the 2 parents with ...
1366 # N: null or no parent
1373 # N: null or no parent
1367 # B: parent is on another named branch
1374 # B: parent is on another named branch
1368 # C: parent is a regular non head changeset
1375 # C: parent is a regular non head changeset
1369 # H: parent was a branch head of the current branch
1376 # H: parent was a branch head of the current branch
1370 # Msg column: whether we print "created new head" message
1377 # Msg column: whether we print "created new head" message
1371 # In the following, it is assumed that there already exists some
1378 # In the following, it is assumed that there already exists some
1372 # initial branch heads of the current branch, otherwise nothing is
1379 # initial branch heads of the current branch, otherwise nothing is
1373 # printed anyway.
1380 # printed anyway.
1374 #
1381 #
1375 # Par Msg Comment
1382 # Par Msg Comment
1376 # N N y additional topo root
1383 # N N y additional topo root
1377 #
1384 #
1378 # B N y additional branch root
1385 # B N y additional branch root
1379 # C N y additional topo head
1386 # C N y additional topo head
1380 # H N n usual case
1387 # H N n usual case
1381 #
1388 #
1382 # B B y weird additional branch root
1389 # B B y weird additional branch root
1383 # C B y branch merge
1390 # C B y branch merge
1384 # H B n merge with named branch
1391 # H B n merge with named branch
1385 #
1392 #
1386 # C C y additional head from merge
1393 # C C y additional head from merge
1387 # C H n merge with a head
1394 # C H n merge with a head
1388 #
1395 #
1389 # H H n head merge: head count decreases
1396 # H H n head merge: head count decreases
1390
1397
1391 if not opts.get('close_branch'):
1398 if not opts.get('close_branch'):
1392 for r in parents:
1399 for r in parents:
1393 if r.closesbranch() and r.branch() == branch:
1400 if r.closesbranch() and r.branch() == branch:
1394 ui.status(_('reopening closed branch head %d\n') % r)
1401 ui.status(_('reopening closed branch head %d\n') % r)
1395
1402
1396 if ui.debugflag:
1403 if ui.debugflag:
1397 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1404 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1398 elif ui.verbose:
1405 elif ui.verbose:
1399 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1406 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1400
1407
1401 @command('copy|cp',
1408 @command('copy|cp',
1402 [('A', 'after', None, _('record a copy that has already occurred')),
1409 [('A', 'after', None, _('record a copy that has already occurred')),
1403 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1410 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1404 ] + walkopts + dryrunopts,
1411 ] + walkopts + dryrunopts,
1405 _('[OPTION]... [SOURCE]... DEST'))
1412 _('[OPTION]... [SOURCE]... DEST'))
1406 def copy(ui, repo, *pats, **opts):
1413 def copy(ui, repo, *pats, **opts):
1407 """mark files as copied for the next commit
1414 """mark files as copied for the next commit
1408
1415
1409 Mark dest as having copies of source files. If dest is a
1416 Mark dest as having copies of source files. If dest is a
1410 directory, copies are put in that directory. If dest is a file,
1417 directory, copies are put in that directory. If dest is a file,
1411 the source must be a single file.
1418 the source must be a single file.
1412
1419
1413 By default, this command copies the contents of files as they
1420 By default, this command copies the contents of files as they
1414 exist in the working directory. If invoked with -A/--after, the
1421 exist in the working directory. If invoked with -A/--after, the
1415 operation is recorded, but no copying is performed.
1422 operation is recorded, but no copying is performed.
1416
1423
1417 This command takes effect with the next commit. To undo a copy
1424 This command takes effect with the next commit. To undo a copy
1418 before that, see :hg:`revert`.
1425 before that, see :hg:`revert`.
1419
1426
1420 Returns 0 on success, 1 if errors are encountered.
1427 Returns 0 on success, 1 if errors are encountered.
1421 """
1428 """
1422 wlock = repo.wlock(False)
1429 wlock = repo.wlock(False)
1423 try:
1430 try:
1424 return cmdutil.copy(ui, repo, pats, opts)
1431 return cmdutil.copy(ui, repo, pats, opts)
1425 finally:
1432 finally:
1426 wlock.release()
1433 wlock.release()
1427
1434
1428 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1435 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1429 def debugancestor(ui, repo, *args):
1436 def debugancestor(ui, repo, *args):
1430 """find the ancestor revision of two revisions in a given index"""
1437 """find the ancestor revision of two revisions in a given index"""
1431 if len(args) == 3:
1438 if len(args) == 3:
1432 index, rev1, rev2 = args
1439 index, rev1, rev2 = args
1433 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1440 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1434 lookup = r.lookup
1441 lookup = r.lookup
1435 elif len(args) == 2:
1442 elif len(args) == 2:
1436 if not repo:
1443 if not repo:
1437 raise util.Abort(_("there is no Mercurial repository here "
1444 raise util.Abort(_("there is no Mercurial repository here "
1438 "(.hg not found)"))
1445 "(.hg not found)"))
1439 rev1, rev2 = args
1446 rev1, rev2 = args
1440 r = repo.changelog
1447 r = repo.changelog
1441 lookup = repo.lookup
1448 lookup = repo.lookup
1442 else:
1449 else:
1443 raise util.Abort(_('either two or three arguments required'))
1450 raise util.Abort(_('either two or three arguments required'))
1444 a = r.ancestor(lookup(rev1), lookup(rev2))
1451 a = r.ancestor(lookup(rev1), lookup(rev2))
1445 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1452 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1446
1453
1447 @command('debugbuilddag',
1454 @command('debugbuilddag',
1448 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1455 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1449 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1456 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1450 ('n', 'new-file', None, _('add new file at each rev'))],
1457 ('n', 'new-file', None, _('add new file at each rev'))],
1451 _('[OPTION]... [TEXT]'))
1458 _('[OPTION]... [TEXT]'))
1452 def debugbuilddag(ui, repo, text=None,
1459 def debugbuilddag(ui, repo, text=None,
1453 mergeable_file=False,
1460 mergeable_file=False,
1454 overwritten_file=False,
1461 overwritten_file=False,
1455 new_file=False):
1462 new_file=False):
1456 """builds a repo with a given DAG from scratch in the current empty repo
1463 """builds a repo with a given DAG from scratch in the current empty repo
1457
1464
1458 The description of the DAG is read from stdin if not given on the
1465 The description of the DAG is read from stdin if not given on the
1459 command line.
1466 command line.
1460
1467
1461 Elements:
1468 Elements:
1462
1469
1463 - "+n" is a linear run of n nodes based on the current default parent
1470 - "+n" is a linear run of n nodes based on the current default parent
1464 - "." is a single node based on the current default parent
1471 - "." is a single node based on the current default parent
1465 - "$" resets the default parent to null (implied at the start);
1472 - "$" resets the default parent to null (implied at the start);
1466 otherwise the default parent is always the last node created
1473 otherwise the default parent is always the last node created
1467 - "<p" sets the default parent to the backref p
1474 - "<p" sets the default parent to the backref p
1468 - "*p" is a fork at parent p, which is a backref
1475 - "*p" is a fork at parent p, which is a backref
1469 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1476 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1470 - "/p2" is a merge of the preceding node and p2
1477 - "/p2" is a merge of the preceding node and p2
1471 - ":tag" defines a local tag for the preceding node
1478 - ":tag" defines a local tag for the preceding node
1472 - "@branch" sets the named branch for subsequent nodes
1479 - "@branch" sets the named branch for subsequent nodes
1473 - "#...\\n" is a comment up to the end of the line
1480 - "#...\\n" is a comment up to the end of the line
1474
1481
1475 Whitespace between the above elements is ignored.
1482 Whitespace between the above elements is ignored.
1476
1483
1477 A backref is either
1484 A backref is either
1478
1485
1479 - a number n, which references the node curr-n, where curr is the current
1486 - a number n, which references the node curr-n, where curr is the current
1480 node, or
1487 node, or
1481 - the name of a local tag you placed earlier using ":tag", or
1488 - the name of a local tag you placed earlier using ":tag", or
1482 - empty to denote the default parent.
1489 - empty to denote the default parent.
1483
1490
1484 All string valued-elements are either strictly alphanumeric, or must
1491 All string valued-elements are either strictly alphanumeric, or must
1485 be enclosed in double quotes ("..."), with "\\" as escape character.
1492 be enclosed in double quotes ("..."), with "\\" as escape character.
1486 """
1493 """
1487
1494
1488 if text is None:
1495 if text is None:
1489 ui.status(_("reading DAG from stdin\n"))
1496 ui.status(_("reading DAG from stdin\n"))
1490 text = ui.fin.read()
1497 text = ui.fin.read()
1491
1498
1492 cl = repo.changelog
1499 cl = repo.changelog
1493 if len(cl) > 0:
1500 if len(cl) > 0:
1494 raise util.Abort(_('repository is not empty'))
1501 raise util.Abort(_('repository is not empty'))
1495
1502
1496 # determine number of revs in DAG
1503 # determine number of revs in DAG
1497 total = 0
1504 total = 0
1498 for type, data in dagparser.parsedag(text):
1505 for type, data in dagparser.parsedag(text):
1499 if type == 'n':
1506 if type == 'n':
1500 total += 1
1507 total += 1
1501
1508
1502 if mergeable_file:
1509 if mergeable_file:
1503 linesperrev = 2
1510 linesperrev = 2
1504 # make a file with k lines per rev
1511 # make a file with k lines per rev
1505 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1512 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1506 initialmergedlines.append("")
1513 initialmergedlines.append("")
1507
1514
1508 tags = []
1515 tags = []
1509
1516
1510 lock = tr = None
1517 lock = tr = None
1511 try:
1518 try:
1512 lock = repo.lock()
1519 lock = repo.lock()
1513 tr = repo.transaction("builddag")
1520 tr = repo.transaction("builddag")
1514
1521
1515 at = -1
1522 at = -1
1516 atbranch = 'default'
1523 atbranch = 'default'
1517 nodeids = []
1524 nodeids = []
1518 id = 0
1525 id = 0
1519 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1526 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1520 for type, data in dagparser.parsedag(text):
1527 for type, data in dagparser.parsedag(text):
1521 if type == 'n':
1528 if type == 'n':
1522 ui.note(('node %s\n' % str(data)))
1529 ui.note(('node %s\n' % str(data)))
1523 id, ps = data
1530 id, ps = data
1524
1531
1525 files = []
1532 files = []
1526 fctxs = {}
1533 fctxs = {}
1527
1534
1528 p2 = None
1535 p2 = None
1529 if mergeable_file:
1536 if mergeable_file:
1530 fn = "mf"
1537 fn = "mf"
1531 p1 = repo[ps[0]]
1538 p1 = repo[ps[0]]
1532 if len(ps) > 1:
1539 if len(ps) > 1:
1533 p2 = repo[ps[1]]
1540 p2 = repo[ps[1]]
1534 pa = p1.ancestor(p2)
1541 pa = p1.ancestor(p2)
1535 base, local, other = [x[fn].data() for x in (pa, p1,
1542 base, local, other = [x[fn].data() for x in (pa, p1,
1536 p2)]
1543 p2)]
1537 m3 = simplemerge.Merge3Text(base, local, other)
1544 m3 = simplemerge.Merge3Text(base, local, other)
1538 ml = [l.strip() for l in m3.merge_lines()]
1545 ml = [l.strip() for l in m3.merge_lines()]
1539 ml.append("")
1546 ml.append("")
1540 elif at > 0:
1547 elif at > 0:
1541 ml = p1[fn].data().split("\n")
1548 ml = p1[fn].data().split("\n")
1542 else:
1549 else:
1543 ml = initialmergedlines
1550 ml = initialmergedlines
1544 ml[id * linesperrev] += " r%i" % id
1551 ml[id * linesperrev] += " r%i" % id
1545 mergedtext = "\n".join(ml)
1552 mergedtext = "\n".join(ml)
1546 files.append(fn)
1553 files.append(fn)
1547 fctxs[fn] = context.memfilectx(fn, mergedtext)
1554 fctxs[fn] = context.memfilectx(fn, mergedtext)
1548
1555
1549 if overwritten_file:
1556 if overwritten_file:
1550 fn = "of"
1557 fn = "of"
1551 files.append(fn)
1558 files.append(fn)
1552 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1559 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1553
1560
1554 if new_file:
1561 if new_file:
1555 fn = "nf%i" % id
1562 fn = "nf%i" % id
1556 files.append(fn)
1563 files.append(fn)
1557 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1564 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1558 if len(ps) > 1:
1565 if len(ps) > 1:
1559 if not p2:
1566 if not p2:
1560 p2 = repo[ps[1]]
1567 p2 = repo[ps[1]]
1561 for fn in p2:
1568 for fn in p2:
1562 if fn.startswith("nf"):
1569 if fn.startswith("nf"):
1563 files.append(fn)
1570 files.append(fn)
1564 fctxs[fn] = p2[fn]
1571 fctxs[fn] = p2[fn]
1565
1572
1566 def fctxfn(repo, cx, path):
1573 def fctxfn(repo, cx, path):
1567 return fctxs.get(path)
1574 return fctxs.get(path)
1568
1575
1569 if len(ps) == 0 or ps[0] < 0:
1576 if len(ps) == 0 or ps[0] < 0:
1570 pars = [None, None]
1577 pars = [None, None]
1571 elif len(ps) == 1:
1578 elif len(ps) == 1:
1572 pars = [nodeids[ps[0]], None]
1579 pars = [nodeids[ps[0]], None]
1573 else:
1580 else:
1574 pars = [nodeids[p] for p in ps]
1581 pars = [nodeids[p] for p in ps]
1575 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1582 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1576 date=(id, 0),
1583 date=(id, 0),
1577 user="debugbuilddag",
1584 user="debugbuilddag",
1578 extra={'branch': atbranch})
1585 extra={'branch': atbranch})
1579 nodeid = repo.commitctx(cx)
1586 nodeid = repo.commitctx(cx)
1580 nodeids.append(nodeid)
1587 nodeids.append(nodeid)
1581 at = id
1588 at = id
1582 elif type == 'l':
1589 elif type == 'l':
1583 id, name = data
1590 id, name = data
1584 ui.note(('tag %s\n' % name))
1591 ui.note(('tag %s\n' % name))
1585 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1592 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1586 elif type == 'a':
1593 elif type == 'a':
1587 ui.note(('branch %s\n' % data))
1594 ui.note(('branch %s\n' % data))
1588 atbranch = data
1595 atbranch = data
1589 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1596 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1590 tr.close()
1597 tr.close()
1591
1598
1592 if tags:
1599 if tags:
1593 repo.opener.write("localtags", "".join(tags))
1600 repo.opener.write("localtags", "".join(tags))
1594 finally:
1601 finally:
1595 ui.progress(_('building'), None)
1602 ui.progress(_('building'), None)
1596 release(tr, lock)
1603 release(tr, lock)
1597
1604
1598 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1605 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1599 def debugbundle(ui, bundlepath, all=None, **opts):
1606 def debugbundle(ui, bundlepath, all=None, **opts):
1600 """lists the contents of a bundle"""
1607 """lists the contents of a bundle"""
1601 f = hg.openpath(ui, bundlepath)
1608 f = hg.openpath(ui, bundlepath)
1602 try:
1609 try:
1603 gen = changegroup.readbundle(f, bundlepath)
1610 gen = changegroup.readbundle(f, bundlepath)
1604 if all:
1611 if all:
1605 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1612 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1606
1613
1607 def showchunks(named):
1614 def showchunks(named):
1608 ui.write("\n%s\n" % named)
1615 ui.write("\n%s\n" % named)
1609 chain = None
1616 chain = None
1610 while True:
1617 while True:
1611 chunkdata = gen.deltachunk(chain)
1618 chunkdata = gen.deltachunk(chain)
1612 if not chunkdata:
1619 if not chunkdata:
1613 break
1620 break
1614 node = chunkdata['node']
1621 node = chunkdata['node']
1615 p1 = chunkdata['p1']
1622 p1 = chunkdata['p1']
1616 p2 = chunkdata['p2']
1623 p2 = chunkdata['p2']
1617 cs = chunkdata['cs']
1624 cs = chunkdata['cs']
1618 deltabase = chunkdata['deltabase']
1625 deltabase = chunkdata['deltabase']
1619 delta = chunkdata['delta']
1626 delta = chunkdata['delta']
1620 ui.write("%s %s %s %s %s %s\n" %
1627 ui.write("%s %s %s %s %s %s\n" %
1621 (hex(node), hex(p1), hex(p2),
1628 (hex(node), hex(p1), hex(p2),
1622 hex(cs), hex(deltabase), len(delta)))
1629 hex(cs), hex(deltabase), len(delta)))
1623 chain = node
1630 chain = node
1624
1631
1625 chunkdata = gen.changelogheader()
1632 chunkdata = gen.changelogheader()
1626 showchunks("changelog")
1633 showchunks("changelog")
1627 chunkdata = gen.manifestheader()
1634 chunkdata = gen.manifestheader()
1628 showchunks("manifest")
1635 showchunks("manifest")
1629 while True:
1636 while True:
1630 chunkdata = gen.filelogheader()
1637 chunkdata = gen.filelogheader()
1631 if not chunkdata:
1638 if not chunkdata:
1632 break
1639 break
1633 fname = chunkdata['filename']
1640 fname = chunkdata['filename']
1634 showchunks(fname)
1641 showchunks(fname)
1635 else:
1642 else:
1636 chunkdata = gen.changelogheader()
1643 chunkdata = gen.changelogheader()
1637 chain = None
1644 chain = None
1638 while True:
1645 while True:
1639 chunkdata = gen.deltachunk(chain)
1646 chunkdata = gen.deltachunk(chain)
1640 if not chunkdata:
1647 if not chunkdata:
1641 break
1648 break
1642 node = chunkdata['node']
1649 node = chunkdata['node']
1643 ui.write("%s\n" % hex(node))
1650 ui.write("%s\n" % hex(node))
1644 chain = node
1651 chain = node
1645 finally:
1652 finally:
1646 f.close()
1653 f.close()
1647
1654
1648 @command('debugcheckstate', [], '')
1655 @command('debugcheckstate', [], '')
1649 def debugcheckstate(ui, repo):
1656 def debugcheckstate(ui, repo):
1650 """validate the correctness of the current dirstate"""
1657 """validate the correctness of the current dirstate"""
1651 parent1, parent2 = repo.dirstate.parents()
1658 parent1, parent2 = repo.dirstate.parents()
1652 m1 = repo[parent1].manifest()
1659 m1 = repo[parent1].manifest()
1653 m2 = repo[parent2].manifest()
1660 m2 = repo[parent2].manifest()
1654 errors = 0
1661 errors = 0
1655 for f in repo.dirstate:
1662 for f in repo.dirstate:
1656 state = repo.dirstate[f]
1663 state = repo.dirstate[f]
1657 if state in "nr" and f not in m1:
1664 if state in "nr" and f not in m1:
1658 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1665 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1659 errors += 1
1666 errors += 1
1660 if state in "a" and f in m1:
1667 if state in "a" and f in m1:
1661 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1668 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1662 errors += 1
1669 errors += 1
1663 if state in "m" and f not in m1 and f not in m2:
1670 if state in "m" and f not in m1 and f not in m2:
1664 ui.warn(_("%s in state %s, but not in either manifest\n") %
1671 ui.warn(_("%s in state %s, but not in either manifest\n") %
1665 (f, state))
1672 (f, state))
1666 errors += 1
1673 errors += 1
1667 for f in m1:
1674 for f in m1:
1668 state = repo.dirstate[f]
1675 state = repo.dirstate[f]
1669 if state not in "nrm":
1676 if state not in "nrm":
1670 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1677 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1671 errors += 1
1678 errors += 1
1672 if errors:
1679 if errors:
1673 error = _(".hg/dirstate inconsistent with current parent's manifest")
1680 error = _(".hg/dirstate inconsistent with current parent's manifest")
1674 raise util.Abort(error)
1681 raise util.Abort(error)
1675
1682
1676 @command('debugcommands', [], _('[COMMAND]'))
1683 @command('debugcommands', [], _('[COMMAND]'))
1677 def debugcommands(ui, cmd='', *args):
1684 def debugcommands(ui, cmd='', *args):
1678 """list all available commands and options"""
1685 """list all available commands and options"""
1679 for cmd, vals in sorted(table.iteritems()):
1686 for cmd, vals in sorted(table.iteritems()):
1680 cmd = cmd.split('|')[0].strip('^')
1687 cmd = cmd.split('|')[0].strip('^')
1681 opts = ', '.join([i[1] for i in vals[1]])
1688 opts = ', '.join([i[1] for i in vals[1]])
1682 ui.write('%s: %s\n' % (cmd, opts))
1689 ui.write('%s: %s\n' % (cmd, opts))
1683
1690
1684 @command('debugcomplete',
1691 @command('debugcomplete',
1685 [('o', 'options', None, _('show the command options'))],
1692 [('o', 'options', None, _('show the command options'))],
1686 _('[-o] CMD'))
1693 _('[-o] CMD'))
1687 def debugcomplete(ui, cmd='', **opts):
1694 def debugcomplete(ui, cmd='', **opts):
1688 """returns the completion list associated with the given command"""
1695 """returns the completion list associated with the given command"""
1689
1696
1690 if opts.get('options'):
1697 if opts.get('options'):
1691 options = []
1698 options = []
1692 otables = [globalopts]
1699 otables = [globalopts]
1693 if cmd:
1700 if cmd:
1694 aliases, entry = cmdutil.findcmd(cmd, table, False)
1701 aliases, entry = cmdutil.findcmd(cmd, table, False)
1695 otables.append(entry[1])
1702 otables.append(entry[1])
1696 for t in otables:
1703 for t in otables:
1697 for o in t:
1704 for o in t:
1698 if "(DEPRECATED)" in o[3]:
1705 if "(DEPRECATED)" in o[3]:
1699 continue
1706 continue
1700 if o[0]:
1707 if o[0]:
1701 options.append('-%s' % o[0])
1708 options.append('-%s' % o[0])
1702 options.append('--%s' % o[1])
1709 options.append('--%s' % o[1])
1703 ui.write("%s\n" % "\n".join(options))
1710 ui.write("%s\n" % "\n".join(options))
1704 return
1711 return
1705
1712
1706 cmdlist = cmdutil.findpossible(cmd, table)
1713 cmdlist = cmdutil.findpossible(cmd, table)
1707 if ui.verbose:
1714 if ui.verbose:
1708 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1715 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1709 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1716 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1710
1717
1711 @command('debugdag',
1718 @command('debugdag',
1712 [('t', 'tags', None, _('use tags as labels')),
1719 [('t', 'tags', None, _('use tags as labels')),
1713 ('b', 'branches', None, _('annotate with branch names')),
1720 ('b', 'branches', None, _('annotate with branch names')),
1714 ('', 'dots', None, _('use dots for runs')),
1721 ('', 'dots', None, _('use dots for runs')),
1715 ('s', 'spaces', None, _('separate elements by spaces'))],
1722 ('s', 'spaces', None, _('separate elements by spaces'))],
1716 _('[OPTION]... [FILE [REV]...]'))
1723 _('[OPTION]... [FILE [REV]...]'))
1717 def debugdag(ui, repo, file_=None, *revs, **opts):
1724 def debugdag(ui, repo, file_=None, *revs, **opts):
1718 """format the changelog or an index DAG as a concise textual description
1725 """format the changelog or an index DAG as a concise textual description
1719
1726
1720 If you pass a revlog index, the revlog's DAG is emitted. If you list
1727 If you pass a revlog index, the revlog's DAG is emitted. If you list
1721 revision numbers, they get labeled in the output as rN.
1728 revision numbers, they get labeled in the output as rN.
1722
1729
1723 Otherwise, the changelog DAG of the current repo is emitted.
1730 Otherwise, the changelog DAG of the current repo is emitted.
1724 """
1731 """
1725 spaces = opts.get('spaces')
1732 spaces = opts.get('spaces')
1726 dots = opts.get('dots')
1733 dots = opts.get('dots')
1727 if file_:
1734 if file_:
1728 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1735 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1729 revs = set((int(r) for r in revs))
1736 revs = set((int(r) for r in revs))
1730 def events():
1737 def events():
1731 for r in rlog:
1738 for r in rlog:
1732 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1739 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1733 if p != -1)))
1740 if p != -1)))
1734 if r in revs:
1741 if r in revs:
1735 yield 'l', (r, "r%i" % r)
1742 yield 'l', (r, "r%i" % r)
1736 elif repo:
1743 elif repo:
1737 cl = repo.changelog
1744 cl = repo.changelog
1738 tags = opts.get('tags')
1745 tags = opts.get('tags')
1739 branches = opts.get('branches')
1746 branches = opts.get('branches')
1740 if tags:
1747 if tags:
1741 labels = {}
1748 labels = {}
1742 for l, n in repo.tags().items():
1749 for l, n in repo.tags().items():
1743 labels.setdefault(cl.rev(n), []).append(l)
1750 labels.setdefault(cl.rev(n), []).append(l)
1744 def events():
1751 def events():
1745 b = "default"
1752 b = "default"
1746 for r in cl:
1753 for r in cl:
1747 if branches:
1754 if branches:
1748 newb = cl.read(cl.node(r))[5]['branch']
1755 newb = cl.read(cl.node(r))[5]['branch']
1749 if newb != b:
1756 if newb != b:
1750 yield 'a', newb
1757 yield 'a', newb
1751 b = newb
1758 b = newb
1752 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1759 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1753 if p != -1)))
1760 if p != -1)))
1754 if tags:
1761 if tags:
1755 ls = labels.get(r)
1762 ls = labels.get(r)
1756 if ls:
1763 if ls:
1757 for l in ls:
1764 for l in ls:
1758 yield 'l', (r, l)
1765 yield 'l', (r, l)
1759 else:
1766 else:
1760 raise util.Abort(_('need repo for changelog dag'))
1767 raise util.Abort(_('need repo for changelog dag'))
1761
1768
1762 for line in dagparser.dagtextlines(events(),
1769 for line in dagparser.dagtextlines(events(),
1763 addspaces=spaces,
1770 addspaces=spaces,
1764 wraplabels=True,
1771 wraplabels=True,
1765 wrapannotations=True,
1772 wrapannotations=True,
1766 wrapnonlinear=dots,
1773 wrapnonlinear=dots,
1767 usedots=dots,
1774 usedots=dots,
1768 maxlinewidth=70):
1775 maxlinewidth=70):
1769 ui.write(line)
1776 ui.write(line)
1770 ui.write("\n")
1777 ui.write("\n")
1771
1778
1772 @command('debugdata',
1779 @command('debugdata',
1773 [('c', 'changelog', False, _('open changelog')),
1780 [('c', 'changelog', False, _('open changelog')),
1774 ('m', 'manifest', False, _('open manifest'))],
1781 ('m', 'manifest', False, _('open manifest'))],
1775 _('-c|-m|FILE REV'))
1782 _('-c|-m|FILE REV'))
1776 def debugdata(ui, repo, file_, rev = None, **opts):
1783 def debugdata(ui, repo, file_, rev = None, **opts):
1777 """dump the contents of a data file revision"""
1784 """dump the contents of a data file revision"""
1778 if opts.get('changelog') or opts.get('manifest'):
1785 if opts.get('changelog') or opts.get('manifest'):
1779 file_, rev = None, file_
1786 file_, rev = None, file_
1780 elif rev is None:
1787 elif rev is None:
1781 raise error.CommandError('debugdata', _('invalid arguments'))
1788 raise error.CommandError('debugdata', _('invalid arguments'))
1782 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1789 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1783 try:
1790 try:
1784 ui.write(r.revision(r.lookup(rev)))
1791 ui.write(r.revision(r.lookup(rev)))
1785 except KeyError:
1792 except KeyError:
1786 raise util.Abort(_('invalid revision identifier %s') % rev)
1793 raise util.Abort(_('invalid revision identifier %s') % rev)
1787
1794
1788 @command('debugdate',
1795 @command('debugdate',
1789 [('e', 'extended', None, _('try extended date formats'))],
1796 [('e', 'extended', None, _('try extended date formats'))],
1790 _('[-e] DATE [RANGE]'))
1797 _('[-e] DATE [RANGE]'))
1791 def debugdate(ui, date, range=None, **opts):
1798 def debugdate(ui, date, range=None, **opts):
1792 """parse and display a date"""
1799 """parse and display a date"""
1793 if opts["extended"]:
1800 if opts["extended"]:
1794 d = util.parsedate(date, util.extendeddateformats)
1801 d = util.parsedate(date, util.extendeddateformats)
1795 else:
1802 else:
1796 d = util.parsedate(date)
1803 d = util.parsedate(date)
1797 ui.write(("internal: %s %s\n") % d)
1804 ui.write(("internal: %s %s\n") % d)
1798 ui.write(("standard: %s\n") % util.datestr(d))
1805 ui.write(("standard: %s\n") % util.datestr(d))
1799 if range:
1806 if range:
1800 m = util.matchdate(range)
1807 m = util.matchdate(range)
1801 ui.write(("match: %s\n") % m(d[0]))
1808 ui.write(("match: %s\n") % m(d[0]))
1802
1809
1803 @command('debugdiscovery',
1810 @command('debugdiscovery',
1804 [('', 'old', None, _('use old-style discovery')),
1811 [('', 'old', None, _('use old-style discovery')),
1805 ('', 'nonheads', None,
1812 ('', 'nonheads', None,
1806 _('use old-style discovery with non-heads included')),
1813 _('use old-style discovery with non-heads included')),
1807 ] + remoteopts,
1814 ] + remoteopts,
1808 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1815 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1809 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1816 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1810 """runs the changeset discovery protocol in isolation"""
1817 """runs the changeset discovery protocol in isolation"""
1811 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1818 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1812 opts.get('branch'))
1819 opts.get('branch'))
1813 remote = hg.peer(repo, opts, remoteurl)
1820 remote = hg.peer(repo, opts, remoteurl)
1814 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1821 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1815
1822
1816 # make sure tests are repeatable
1823 # make sure tests are repeatable
1817 random.seed(12323)
1824 random.seed(12323)
1818
1825
1819 def doit(localheads, remoteheads, remote=remote):
1826 def doit(localheads, remoteheads, remote=remote):
1820 if opts.get('old'):
1827 if opts.get('old'):
1821 if localheads:
1828 if localheads:
1822 raise util.Abort('cannot use localheads with old style '
1829 raise util.Abort('cannot use localheads with old style '
1823 'discovery')
1830 'discovery')
1824 if not util.safehasattr(remote, 'branches'):
1831 if not util.safehasattr(remote, 'branches'):
1825 # enable in-client legacy support
1832 # enable in-client legacy support
1826 remote = localrepo.locallegacypeer(remote.local())
1833 remote = localrepo.locallegacypeer(remote.local())
1827 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1834 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1828 force=True)
1835 force=True)
1829 common = set(common)
1836 common = set(common)
1830 if not opts.get('nonheads'):
1837 if not opts.get('nonheads'):
1831 ui.write(("unpruned common: %s\n") %
1838 ui.write(("unpruned common: %s\n") %
1832 " ".join(sorted(short(n) for n in common)))
1839 " ".join(sorted(short(n) for n in common)))
1833 dag = dagutil.revlogdag(repo.changelog)
1840 dag = dagutil.revlogdag(repo.changelog)
1834 all = dag.ancestorset(dag.internalizeall(common))
1841 all = dag.ancestorset(dag.internalizeall(common))
1835 common = dag.externalizeall(dag.headsetofconnecteds(all))
1842 common = dag.externalizeall(dag.headsetofconnecteds(all))
1836 else:
1843 else:
1837 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1844 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1838 common = set(common)
1845 common = set(common)
1839 rheads = set(hds)
1846 rheads = set(hds)
1840 lheads = set(repo.heads())
1847 lheads = set(repo.heads())
1841 ui.write(("common heads: %s\n") %
1848 ui.write(("common heads: %s\n") %
1842 " ".join(sorted(short(n) for n in common)))
1849 " ".join(sorted(short(n) for n in common)))
1843 if lheads <= common:
1850 if lheads <= common:
1844 ui.write(("local is subset\n"))
1851 ui.write(("local is subset\n"))
1845 elif rheads <= common:
1852 elif rheads <= common:
1846 ui.write(("remote is subset\n"))
1853 ui.write(("remote is subset\n"))
1847
1854
1848 serverlogs = opts.get('serverlog')
1855 serverlogs = opts.get('serverlog')
1849 if serverlogs:
1856 if serverlogs:
1850 for filename in serverlogs:
1857 for filename in serverlogs:
1851 logfile = open(filename, 'r')
1858 logfile = open(filename, 'r')
1852 try:
1859 try:
1853 line = logfile.readline()
1860 line = logfile.readline()
1854 while line:
1861 while line:
1855 parts = line.strip().split(';')
1862 parts = line.strip().split(';')
1856 op = parts[1]
1863 op = parts[1]
1857 if op == 'cg':
1864 if op == 'cg':
1858 pass
1865 pass
1859 elif op == 'cgss':
1866 elif op == 'cgss':
1860 doit(parts[2].split(' '), parts[3].split(' '))
1867 doit(parts[2].split(' '), parts[3].split(' '))
1861 elif op == 'unb':
1868 elif op == 'unb':
1862 doit(parts[3].split(' '), parts[2].split(' '))
1869 doit(parts[3].split(' '), parts[2].split(' '))
1863 line = logfile.readline()
1870 line = logfile.readline()
1864 finally:
1871 finally:
1865 logfile.close()
1872 logfile.close()
1866
1873
1867 else:
1874 else:
1868 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1875 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1869 opts.get('remote_head'))
1876 opts.get('remote_head'))
1870 localrevs = opts.get('local_head')
1877 localrevs = opts.get('local_head')
1871 doit(localrevs, remoterevs)
1878 doit(localrevs, remoterevs)
1872
1879
1873 @command('debugfileset',
1880 @command('debugfileset',
1874 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1881 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1875 _('[-r REV] FILESPEC'))
1882 _('[-r REV] FILESPEC'))
1876 def debugfileset(ui, repo, expr, **opts):
1883 def debugfileset(ui, repo, expr, **opts):
1877 '''parse and apply a fileset specification'''
1884 '''parse and apply a fileset specification'''
1878 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1885 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1879 if ui.verbose:
1886 if ui.verbose:
1880 tree = fileset.parse(expr)[0]
1887 tree = fileset.parse(expr)[0]
1881 ui.note(tree, "\n")
1888 ui.note(tree, "\n")
1882
1889
1883 for f in fileset.getfileset(ctx, expr):
1890 for f in fileset.getfileset(ctx, expr):
1884 ui.write("%s\n" % f)
1891 ui.write("%s\n" % f)
1885
1892
1886 @command('debugfsinfo', [], _('[PATH]'))
1893 @command('debugfsinfo', [], _('[PATH]'))
1887 def debugfsinfo(ui, path = "."):
1894 def debugfsinfo(ui, path = "."):
1888 """show information detected about current filesystem"""
1895 """show information detected about current filesystem"""
1889 util.writefile('.debugfsinfo', '')
1896 util.writefile('.debugfsinfo', '')
1890 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1897 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1891 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1898 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1892 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1899 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1893 and 'yes' or 'no'))
1900 and 'yes' or 'no'))
1894 os.unlink('.debugfsinfo')
1901 os.unlink('.debugfsinfo')
1895
1902
1896 @command('debuggetbundle',
1903 @command('debuggetbundle',
1897 [('H', 'head', [], _('id of head node'), _('ID')),
1904 [('H', 'head', [], _('id of head node'), _('ID')),
1898 ('C', 'common', [], _('id of common node'), _('ID')),
1905 ('C', 'common', [], _('id of common node'), _('ID')),
1899 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1906 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1900 _('REPO FILE [-H|-C ID]...'))
1907 _('REPO FILE [-H|-C ID]...'))
1901 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1908 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1902 """retrieves a bundle from a repo
1909 """retrieves a bundle from a repo
1903
1910
1904 Every ID must be a full-length hex node id string. Saves the bundle to the
1911 Every ID must be a full-length hex node id string. Saves the bundle to the
1905 given file.
1912 given file.
1906 """
1913 """
1907 repo = hg.peer(ui, opts, repopath)
1914 repo = hg.peer(ui, opts, repopath)
1908 if not repo.capable('getbundle'):
1915 if not repo.capable('getbundle'):
1909 raise util.Abort("getbundle() not supported by target repository")
1916 raise util.Abort("getbundle() not supported by target repository")
1910 args = {}
1917 args = {}
1911 if common:
1918 if common:
1912 args['common'] = [bin(s) for s in common]
1919 args['common'] = [bin(s) for s in common]
1913 if head:
1920 if head:
1914 args['heads'] = [bin(s) for s in head]
1921 args['heads'] = [bin(s) for s in head]
1915 bundle = repo.getbundle('debug', **args)
1922 bundle = repo.getbundle('debug', **args)
1916
1923
1917 bundletype = opts.get('type', 'bzip2').lower()
1924 bundletype = opts.get('type', 'bzip2').lower()
1918 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1925 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1919 bundletype = btypes.get(bundletype)
1926 bundletype = btypes.get(bundletype)
1920 if bundletype not in changegroup.bundletypes:
1927 if bundletype not in changegroup.bundletypes:
1921 raise util.Abort(_('unknown bundle type specified with --type'))
1928 raise util.Abort(_('unknown bundle type specified with --type'))
1922 changegroup.writebundle(bundle, bundlepath, bundletype)
1929 changegroup.writebundle(bundle, bundlepath, bundletype)
1923
1930
1924 @command('debugignore', [], '')
1931 @command('debugignore', [], '')
1925 def debugignore(ui, repo, *values, **opts):
1932 def debugignore(ui, repo, *values, **opts):
1926 """display the combined ignore pattern"""
1933 """display the combined ignore pattern"""
1927 ignore = repo.dirstate._ignore
1934 ignore = repo.dirstate._ignore
1928 includepat = getattr(ignore, 'includepat', None)
1935 includepat = getattr(ignore, 'includepat', None)
1929 if includepat is not None:
1936 if includepat is not None:
1930 ui.write("%s\n" % includepat)
1937 ui.write("%s\n" % includepat)
1931 else:
1938 else:
1932 raise util.Abort(_("no ignore patterns found"))
1939 raise util.Abort(_("no ignore patterns found"))
1933
1940
1934 @command('debugindex',
1941 @command('debugindex',
1935 [('c', 'changelog', False, _('open changelog')),
1942 [('c', 'changelog', False, _('open changelog')),
1936 ('m', 'manifest', False, _('open manifest')),
1943 ('m', 'manifest', False, _('open manifest')),
1937 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1944 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1938 _('[-f FORMAT] -c|-m|FILE'))
1945 _('[-f FORMAT] -c|-m|FILE'))
1939 def debugindex(ui, repo, file_ = None, **opts):
1946 def debugindex(ui, repo, file_ = None, **opts):
1940 """dump the contents of an index file"""
1947 """dump the contents of an index file"""
1941 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1948 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1942 format = opts.get('format', 0)
1949 format = opts.get('format', 0)
1943 if format not in (0, 1):
1950 if format not in (0, 1):
1944 raise util.Abort(_("unknown format %d") % format)
1951 raise util.Abort(_("unknown format %d") % format)
1945
1952
1946 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1953 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1947 if generaldelta:
1954 if generaldelta:
1948 basehdr = ' delta'
1955 basehdr = ' delta'
1949 else:
1956 else:
1950 basehdr = ' base'
1957 basehdr = ' base'
1951
1958
1952 if format == 0:
1959 if format == 0:
1953 ui.write(" rev offset length " + basehdr + " linkrev"
1960 ui.write(" rev offset length " + basehdr + " linkrev"
1954 " nodeid p1 p2\n")
1961 " nodeid p1 p2\n")
1955 elif format == 1:
1962 elif format == 1:
1956 ui.write(" rev flag offset length"
1963 ui.write(" rev flag offset length"
1957 " size " + basehdr + " link p1 p2"
1964 " size " + basehdr + " link p1 p2"
1958 " nodeid\n")
1965 " nodeid\n")
1959
1966
1960 for i in r:
1967 for i in r:
1961 node = r.node(i)
1968 node = r.node(i)
1962 if generaldelta:
1969 if generaldelta:
1963 base = r.deltaparent(i)
1970 base = r.deltaparent(i)
1964 else:
1971 else:
1965 base = r.chainbase(i)
1972 base = r.chainbase(i)
1966 if format == 0:
1973 if format == 0:
1967 try:
1974 try:
1968 pp = r.parents(node)
1975 pp = r.parents(node)
1969 except Exception:
1976 except Exception:
1970 pp = [nullid, nullid]
1977 pp = [nullid, nullid]
1971 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1978 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1972 i, r.start(i), r.length(i), base, r.linkrev(i),
1979 i, r.start(i), r.length(i), base, r.linkrev(i),
1973 short(node), short(pp[0]), short(pp[1])))
1980 short(node), short(pp[0]), short(pp[1])))
1974 elif format == 1:
1981 elif format == 1:
1975 pr = r.parentrevs(i)
1982 pr = r.parentrevs(i)
1976 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1983 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1977 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1984 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1978 base, r.linkrev(i), pr[0], pr[1], short(node)))
1985 base, r.linkrev(i), pr[0], pr[1], short(node)))
1979
1986
1980 @command('debugindexdot', [], _('FILE'))
1987 @command('debugindexdot', [], _('FILE'))
1981 def debugindexdot(ui, repo, file_):
1988 def debugindexdot(ui, repo, file_):
1982 """dump an index DAG as a graphviz dot file"""
1989 """dump an index DAG as a graphviz dot file"""
1983 r = None
1990 r = None
1984 if repo:
1991 if repo:
1985 filelog = repo.file(file_)
1992 filelog = repo.file(file_)
1986 if len(filelog):
1993 if len(filelog):
1987 r = filelog
1994 r = filelog
1988 if not r:
1995 if not r:
1989 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1996 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1990 ui.write(("digraph G {\n"))
1997 ui.write(("digraph G {\n"))
1991 for i in r:
1998 for i in r:
1992 node = r.node(i)
1999 node = r.node(i)
1993 pp = r.parents(node)
2000 pp = r.parents(node)
1994 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2001 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1995 if pp[1] != nullid:
2002 if pp[1] != nullid:
1996 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2003 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1997 ui.write("}\n")
2004 ui.write("}\n")
1998
2005
1999 @command('debuginstall', [], '')
2006 @command('debuginstall', [], '')
2000 def debuginstall(ui):
2007 def debuginstall(ui):
2001 '''test Mercurial installation
2008 '''test Mercurial installation
2002
2009
2003 Returns 0 on success.
2010 Returns 0 on success.
2004 '''
2011 '''
2005
2012
2006 def writetemp(contents):
2013 def writetemp(contents):
2007 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2014 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2008 f = os.fdopen(fd, "wb")
2015 f = os.fdopen(fd, "wb")
2009 f.write(contents)
2016 f.write(contents)
2010 f.close()
2017 f.close()
2011 return name
2018 return name
2012
2019
2013 problems = 0
2020 problems = 0
2014
2021
2015 # encoding
2022 # encoding
2016 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2023 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2017 try:
2024 try:
2018 encoding.fromlocal("test")
2025 encoding.fromlocal("test")
2019 except util.Abort, inst:
2026 except util.Abort, inst:
2020 ui.write(" %s\n" % inst)
2027 ui.write(" %s\n" % inst)
2021 ui.write(_(" (check that your locale is properly set)\n"))
2028 ui.write(_(" (check that your locale is properly set)\n"))
2022 problems += 1
2029 problems += 1
2023
2030
2024 # Python lib
2031 # Python lib
2025 ui.status(_("checking Python lib (%s)...\n")
2032 ui.status(_("checking Python lib (%s)...\n")
2026 % os.path.dirname(os.__file__))
2033 % os.path.dirname(os.__file__))
2027
2034
2028 # compiled modules
2035 # compiled modules
2029 ui.status(_("checking installed modules (%s)...\n")
2036 ui.status(_("checking installed modules (%s)...\n")
2030 % os.path.dirname(__file__))
2037 % os.path.dirname(__file__))
2031 try:
2038 try:
2032 import bdiff, mpatch, base85, osutil
2039 import bdiff, mpatch, base85, osutil
2033 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2040 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2034 except Exception, inst:
2041 except Exception, inst:
2035 ui.write(" %s\n" % inst)
2042 ui.write(" %s\n" % inst)
2036 ui.write(_(" One or more extensions could not be found"))
2043 ui.write(_(" One or more extensions could not be found"))
2037 ui.write(_(" (check that you compiled the extensions)\n"))
2044 ui.write(_(" (check that you compiled the extensions)\n"))
2038 problems += 1
2045 problems += 1
2039
2046
2040 # templates
2047 # templates
2041 import templater
2048 import templater
2042 p = templater.templatepath()
2049 p = templater.templatepath()
2043 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2050 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2044 try:
2051 try:
2045 templater.templater(templater.templatepath("map-cmdline.default"))
2052 templater.templater(templater.templatepath("map-cmdline.default"))
2046 except Exception, inst:
2053 except Exception, inst:
2047 ui.write(" %s\n" % inst)
2054 ui.write(" %s\n" % inst)
2048 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2055 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2049 problems += 1
2056 problems += 1
2050
2057
2051 # editor
2058 # editor
2052 ui.status(_("checking commit editor...\n"))
2059 ui.status(_("checking commit editor...\n"))
2053 editor = ui.geteditor()
2060 editor = ui.geteditor()
2054 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2061 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2055 if not cmdpath:
2062 if not cmdpath:
2056 if editor == 'vi':
2063 if editor == 'vi':
2057 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2064 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2058 ui.write(_(" (specify a commit editor in your configuration"
2065 ui.write(_(" (specify a commit editor in your configuration"
2059 " file)\n"))
2066 " file)\n"))
2060 else:
2067 else:
2061 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2068 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2062 ui.write(_(" (specify a commit editor in your configuration"
2069 ui.write(_(" (specify a commit editor in your configuration"
2063 " file)\n"))
2070 " file)\n"))
2064 problems += 1
2071 problems += 1
2065
2072
2066 # check username
2073 # check username
2067 ui.status(_("checking username...\n"))
2074 ui.status(_("checking username...\n"))
2068 try:
2075 try:
2069 ui.username()
2076 ui.username()
2070 except util.Abort, e:
2077 except util.Abort, e:
2071 ui.write(" %s\n" % e)
2078 ui.write(" %s\n" % e)
2072 ui.write(_(" (specify a username in your configuration file)\n"))
2079 ui.write(_(" (specify a username in your configuration file)\n"))
2073 problems += 1
2080 problems += 1
2074
2081
2075 if not problems:
2082 if not problems:
2076 ui.status(_("no problems detected\n"))
2083 ui.status(_("no problems detected\n"))
2077 else:
2084 else:
2078 ui.write(_("%s problems detected,"
2085 ui.write(_("%s problems detected,"
2079 " please check your install!\n") % problems)
2086 " please check your install!\n") % problems)
2080
2087
2081 return problems
2088 return problems
2082
2089
2083 @command('debugknown', [], _('REPO ID...'))
2090 @command('debugknown', [], _('REPO ID...'))
2084 def debugknown(ui, repopath, *ids, **opts):
2091 def debugknown(ui, repopath, *ids, **opts):
2085 """test whether node ids are known to a repo
2092 """test whether node ids are known to a repo
2086
2093
2087 Every ID must be a full-length hex node id string. Returns a list of 0s
2094 Every ID must be a full-length hex node id string. Returns a list of 0s
2088 and 1s indicating unknown/known.
2095 and 1s indicating unknown/known.
2089 """
2096 """
2090 repo = hg.peer(ui, opts, repopath)
2097 repo = hg.peer(ui, opts, repopath)
2091 if not repo.capable('known'):
2098 if not repo.capable('known'):
2092 raise util.Abort("known() not supported by target repository")
2099 raise util.Abort("known() not supported by target repository")
2093 flags = repo.known([bin(s) for s in ids])
2100 flags = repo.known([bin(s) for s in ids])
2094 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2101 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2095
2102
2096 @command('debugobsolete',
2103 @command('debugobsolete',
2097 [('', 'flags', 0, _('markers flag')),
2104 [('', 'flags', 0, _('markers flag')),
2098 ] + commitopts2,
2105 ] + commitopts2,
2099 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2106 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2100 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2107 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2101 """create arbitrary obsolete marker"""
2108 """create arbitrary obsolete marker"""
2102 def parsenodeid(s):
2109 def parsenodeid(s):
2103 try:
2110 try:
2104 # We do not use revsingle/revrange functions here to accept
2111 # We do not use revsingle/revrange functions here to accept
2105 # arbitrary node identifiers, possibly not present in the
2112 # arbitrary node identifiers, possibly not present in the
2106 # local repository.
2113 # local repository.
2107 n = bin(s)
2114 n = bin(s)
2108 if len(n) != len(nullid):
2115 if len(n) != len(nullid):
2109 raise TypeError()
2116 raise TypeError()
2110 return n
2117 return n
2111 except TypeError:
2118 except TypeError:
2112 raise util.Abort('changeset references must be full hexadecimal '
2119 raise util.Abort('changeset references must be full hexadecimal '
2113 'node identifiers')
2120 'node identifiers')
2114
2121
2115 if precursor is not None:
2122 if precursor is not None:
2116 metadata = {}
2123 metadata = {}
2117 if 'date' in opts:
2124 if 'date' in opts:
2118 metadata['date'] = opts['date']
2125 metadata['date'] = opts['date']
2119 metadata['user'] = opts['user'] or ui.username()
2126 metadata['user'] = opts['user'] or ui.username()
2120 succs = tuple(parsenodeid(succ) for succ in successors)
2127 succs = tuple(parsenodeid(succ) for succ in successors)
2121 l = repo.lock()
2128 l = repo.lock()
2122 try:
2129 try:
2123 tr = repo.transaction('debugobsolete')
2130 tr = repo.transaction('debugobsolete')
2124 try:
2131 try:
2125 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2132 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2126 opts['flags'], metadata)
2133 opts['flags'], metadata)
2127 tr.close()
2134 tr.close()
2128 finally:
2135 finally:
2129 tr.release()
2136 tr.release()
2130 finally:
2137 finally:
2131 l.release()
2138 l.release()
2132 else:
2139 else:
2133 for m in obsolete.allmarkers(repo):
2140 for m in obsolete.allmarkers(repo):
2134 ui.write(hex(m.precnode()))
2141 ui.write(hex(m.precnode()))
2135 for repl in m.succnodes():
2142 for repl in m.succnodes():
2136 ui.write(' ')
2143 ui.write(' ')
2137 ui.write(hex(repl))
2144 ui.write(hex(repl))
2138 ui.write(' %X ' % m._data[2])
2145 ui.write(' %X ' % m._data[2])
2139 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2146 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2140 sorted(m.metadata().items()))))
2147 sorted(m.metadata().items()))))
2141 ui.write('\n')
2148 ui.write('\n')
2142
2149
2143 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2150 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2144 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2151 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2145 '''access the pushkey key/value protocol
2152 '''access the pushkey key/value protocol
2146
2153
2147 With two args, list the keys in the given namespace.
2154 With two args, list the keys in the given namespace.
2148
2155
2149 With five args, set a key to new if it currently is set to old.
2156 With five args, set a key to new if it currently is set to old.
2150 Reports success or failure.
2157 Reports success or failure.
2151 '''
2158 '''
2152
2159
2153 target = hg.peer(ui, {}, repopath)
2160 target = hg.peer(ui, {}, repopath)
2154 if keyinfo:
2161 if keyinfo:
2155 key, old, new = keyinfo
2162 key, old, new = keyinfo
2156 r = target.pushkey(namespace, key, old, new)
2163 r = target.pushkey(namespace, key, old, new)
2157 ui.status(str(r) + '\n')
2164 ui.status(str(r) + '\n')
2158 return not r
2165 return not r
2159 else:
2166 else:
2160 for k, v in sorted(target.listkeys(namespace).iteritems()):
2167 for k, v in sorted(target.listkeys(namespace).iteritems()):
2161 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2168 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2162 v.encode('string-escape')))
2169 v.encode('string-escape')))
2163
2170
2164 @command('debugpvec', [], _('A B'))
2171 @command('debugpvec', [], _('A B'))
2165 def debugpvec(ui, repo, a, b=None):
2172 def debugpvec(ui, repo, a, b=None):
2166 ca = scmutil.revsingle(repo, a)
2173 ca = scmutil.revsingle(repo, a)
2167 cb = scmutil.revsingle(repo, b)
2174 cb = scmutil.revsingle(repo, b)
2168 pa = pvec.ctxpvec(ca)
2175 pa = pvec.ctxpvec(ca)
2169 pb = pvec.ctxpvec(cb)
2176 pb = pvec.ctxpvec(cb)
2170 if pa == pb:
2177 if pa == pb:
2171 rel = "="
2178 rel = "="
2172 elif pa > pb:
2179 elif pa > pb:
2173 rel = ">"
2180 rel = ">"
2174 elif pa < pb:
2181 elif pa < pb:
2175 rel = "<"
2182 rel = "<"
2176 elif pa | pb:
2183 elif pa | pb:
2177 rel = "|"
2184 rel = "|"
2178 ui.write(_("a: %s\n") % pa)
2185 ui.write(_("a: %s\n") % pa)
2179 ui.write(_("b: %s\n") % pb)
2186 ui.write(_("b: %s\n") % pb)
2180 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2187 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2181 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2188 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2182 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2189 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2183 pa.distance(pb), rel))
2190 pa.distance(pb), rel))
2184
2191
2185 @command('debugrebuildstate',
2192 @command('debugrebuildstate',
2186 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2193 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2187 _('[-r REV] [REV]'))
2194 _('[-r REV] [REV]'))
2188 def debugrebuildstate(ui, repo, rev="tip"):
2195 def debugrebuildstate(ui, repo, rev="tip"):
2189 """rebuild the dirstate as it would look like for the given revision"""
2196 """rebuild the dirstate as it would look like for the given revision"""
2190 ctx = scmutil.revsingle(repo, rev)
2197 ctx = scmutil.revsingle(repo, rev)
2191 wlock = repo.wlock()
2198 wlock = repo.wlock()
2192 try:
2199 try:
2193 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2200 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2194 finally:
2201 finally:
2195 wlock.release()
2202 wlock.release()
2196
2203
2197 @command('debugrename',
2204 @command('debugrename',
2198 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2205 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2199 _('[-r REV] FILE'))
2206 _('[-r REV] FILE'))
2200 def debugrename(ui, repo, file1, *pats, **opts):
2207 def debugrename(ui, repo, file1, *pats, **opts):
2201 """dump rename information"""
2208 """dump rename information"""
2202
2209
2203 ctx = scmutil.revsingle(repo, opts.get('rev'))
2210 ctx = scmutil.revsingle(repo, opts.get('rev'))
2204 m = scmutil.match(ctx, (file1,) + pats, opts)
2211 m = scmutil.match(ctx, (file1,) + pats, opts)
2205 for abs in ctx.walk(m):
2212 for abs in ctx.walk(m):
2206 fctx = ctx[abs]
2213 fctx = ctx[abs]
2207 o = fctx.filelog().renamed(fctx.filenode())
2214 o = fctx.filelog().renamed(fctx.filenode())
2208 rel = m.rel(abs)
2215 rel = m.rel(abs)
2209 if o:
2216 if o:
2210 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2217 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2211 else:
2218 else:
2212 ui.write(_("%s not renamed\n") % rel)
2219 ui.write(_("%s not renamed\n") % rel)
2213
2220
2214 @command('debugrevlog',
2221 @command('debugrevlog',
2215 [('c', 'changelog', False, _('open changelog')),
2222 [('c', 'changelog', False, _('open changelog')),
2216 ('m', 'manifest', False, _('open manifest')),
2223 ('m', 'manifest', False, _('open manifest')),
2217 ('d', 'dump', False, _('dump index data'))],
2224 ('d', 'dump', False, _('dump index data'))],
2218 _('-c|-m|FILE'))
2225 _('-c|-m|FILE'))
2219 def debugrevlog(ui, repo, file_ = None, **opts):
2226 def debugrevlog(ui, repo, file_ = None, **opts):
2220 """show data and statistics about a revlog"""
2227 """show data and statistics about a revlog"""
2221 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2228 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2222
2229
2223 if opts.get("dump"):
2230 if opts.get("dump"):
2224 numrevs = len(r)
2231 numrevs = len(r)
2225 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2232 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2226 " rawsize totalsize compression heads\n")
2233 " rawsize totalsize compression heads\n")
2227 ts = 0
2234 ts = 0
2228 heads = set()
2235 heads = set()
2229 for rev in xrange(numrevs):
2236 for rev in xrange(numrevs):
2230 dbase = r.deltaparent(rev)
2237 dbase = r.deltaparent(rev)
2231 if dbase == -1:
2238 if dbase == -1:
2232 dbase = rev
2239 dbase = rev
2233 cbase = r.chainbase(rev)
2240 cbase = r.chainbase(rev)
2234 p1, p2 = r.parentrevs(rev)
2241 p1, p2 = r.parentrevs(rev)
2235 rs = r.rawsize(rev)
2242 rs = r.rawsize(rev)
2236 ts = ts + rs
2243 ts = ts + rs
2237 heads -= set(r.parentrevs(rev))
2244 heads -= set(r.parentrevs(rev))
2238 heads.add(rev)
2245 heads.add(rev)
2239 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2246 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2240 (rev, p1, p2, r.start(rev), r.end(rev),
2247 (rev, p1, p2, r.start(rev), r.end(rev),
2241 r.start(dbase), r.start(cbase),
2248 r.start(dbase), r.start(cbase),
2242 r.start(p1), r.start(p2),
2249 r.start(p1), r.start(p2),
2243 rs, ts, ts / r.end(rev), len(heads)))
2250 rs, ts, ts / r.end(rev), len(heads)))
2244 return 0
2251 return 0
2245
2252
2246 v = r.version
2253 v = r.version
2247 format = v & 0xFFFF
2254 format = v & 0xFFFF
2248 flags = []
2255 flags = []
2249 gdelta = False
2256 gdelta = False
2250 if v & revlog.REVLOGNGINLINEDATA:
2257 if v & revlog.REVLOGNGINLINEDATA:
2251 flags.append('inline')
2258 flags.append('inline')
2252 if v & revlog.REVLOGGENERALDELTA:
2259 if v & revlog.REVLOGGENERALDELTA:
2253 gdelta = True
2260 gdelta = True
2254 flags.append('generaldelta')
2261 flags.append('generaldelta')
2255 if not flags:
2262 if not flags:
2256 flags = ['(none)']
2263 flags = ['(none)']
2257
2264
2258 nummerges = 0
2265 nummerges = 0
2259 numfull = 0
2266 numfull = 0
2260 numprev = 0
2267 numprev = 0
2261 nump1 = 0
2268 nump1 = 0
2262 nump2 = 0
2269 nump2 = 0
2263 numother = 0
2270 numother = 0
2264 nump1prev = 0
2271 nump1prev = 0
2265 nump2prev = 0
2272 nump2prev = 0
2266 chainlengths = []
2273 chainlengths = []
2267
2274
2268 datasize = [None, 0, 0L]
2275 datasize = [None, 0, 0L]
2269 fullsize = [None, 0, 0L]
2276 fullsize = [None, 0, 0L]
2270 deltasize = [None, 0, 0L]
2277 deltasize = [None, 0, 0L]
2271
2278
2272 def addsize(size, l):
2279 def addsize(size, l):
2273 if l[0] is None or size < l[0]:
2280 if l[0] is None or size < l[0]:
2274 l[0] = size
2281 l[0] = size
2275 if size > l[1]:
2282 if size > l[1]:
2276 l[1] = size
2283 l[1] = size
2277 l[2] += size
2284 l[2] += size
2278
2285
2279 numrevs = len(r)
2286 numrevs = len(r)
2280 for rev in xrange(numrevs):
2287 for rev in xrange(numrevs):
2281 p1, p2 = r.parentrevs(rev)
2288 p1, p2 = r.parentrevs(rev)
2282 delta = r.deltaparent(rev)
2289 delta = r.deltaparent(rev)
2283 if format > 0:
2290 if format > 0:
2284 addsize(r.rawsize(rev), datasize)
2291 addsize(r.rawsize(rev), datasize)
2285 if p2 != nullrev:
2292 if p2 != nullrev:
2286 nummerges += 1
2293 nummerges += 1
2287 size = r.length(rev)
2294 size = r.length(rev)
2288 if delta == nullrev:
2295 if delta == nullrev:
2289 chainlengths.append(0)
2296 chainlengths.append(0)
2290 numfull += 1
2297 numfull += 1
2291 addsize(size, fullsize)
2298 addsize(size, fullsize)
2292 else:
2299 else:
2293 chainlengths.append(chainlengths[delta] + 1)
2300 chainlengths.append(chainlengths[delta] + 1)
2294 addsize(size, deltasize)
2301 addsize(size, deltasize)
2295 if delta == rev - 1:
2302 if delta == rev - 1:
2296 numprev += 1
2303 numprev += 1
2297 if delta == p1:
2304 if delta == p1:
2298 nump1prev += 1
2305 nump1prev += 1
2299 elif delta == p2:
2306 elif delta == p2:
2300 nump2prev += 1
2307 nump2prev += 1
2301 elif delta == p1:
2308 elif delta == p1:
2302 nump1 += 1
2309 nump1 += 1
2303 elif delta == p2:
2310 elif delta == p2:
2304 nump2 += 1
2311 nump2 += 1
2305 elif delta != nullrev:
2312 elif delta != nullrev:
2306 numother += 1
2313 numother += 1
2307
2314
2308 # Adjust size min value for empty cases
2315 # Adjust size min value for empty cases
2309 for size in (datasize, fullsize, deltasize):
2316 for size in (datasize, fullsize, deltasize):
2310 if size[0] is None:
2317 if size[0] is None:
2311 size[0] = 0
2318 size[0] = 0
2312
2319
2313 numdeltas = numrevs - numfull
2320 numdeltas = numrevs - numfull
2314 numoprev = numprev - nump1prev - nump2prev
2321 numoprev = numprev - nump1prev - nump2prev
2315 totalrawsize = datasize[2]
2322 totalrawsize = datasize[2]
2316 datasize[2] /= numrevs
2323 datasize[2] /= numrevs
2317 fulltotal = fullsize[2]
2324 fulltotal = fullsize[2]
2318 fullsize[2] /= numfull
2325 fullsize[2] /= numfull
2319 deltatotal = deltasize[2]
2326 deltatotal = deltasize[2]
2320 if numrevs - numfull > 0:
2327 if numrevs - numfull > 0:
2321 deltasize[2] /= numrevs - numfull
2328 deltasize[2] /= numrevs - numfull
2322 totalsize = fulltotal + deltatotal
2329 totalsize = fulltotal + deltatotal
2323 avgchainlen = sum(chainlengths) / numrevs
2330 avgchainlen = sum(chainlengths) / numrevs
2324 compratio = totalrawsize / totalsize
2331 compratio = totalrawsize / totalsize
2325
2332
2326 basedfmtstr = '%%%dd\n'
2333 basedfmtstr = '%%%dd\n'
2327 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2334 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2328
2335
2329 def dfmtstr(max):
2336 def dfmtstr(max):
2330 return basedfmtstr % len(str(max))
2337 return basedfmtstr % len(str(max))
2331 def pcfmtstr(max, padding=0):
2338 def pcfmtstr(max, padding=0):
2332 return basepcfmtstr % (len(str(max)), ' ' * padding)
2339 return basepcfmtstr % (len(str(max)), ' ' * padding)
2333
2340
2334 def pcfmt(value, total):
2341 def pcfmt(value, total):
2335 return (value, 100 * float(value) / total)
2342 return (value, 100 * float(value) / total)
2336
2343
2337 ui.write(('format : %d\n') % format)
2344 ui.write(('format : %d\n') % format)
2338 ui.write(('flags : %s\n') % ', '.join(flags))
2345 ui.write(('flags : %s\n') % ', '.join(flags))
2339
2346
2340 ui.write('\n')
2347 ui.write('\n')
2341 fmt = pcfmtstr(totalsize)
2348 fmt = pcfmtstr(totalsize)
2342 fmt2 = dfmtstr(totalsize)
2349 fmt2 = dfmtstr(totalsize)
2343 ui.write(('revisions : ') + fmt2 % numrevs)
2350 ui.write(('revisions : ') + fmt2 % numrevs)
2344 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2351 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2345 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2352 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2346 ui.write(('revisions : ') + fmt2 % numrevs)
2353 ui.write(('revisions : ') + fmt2 % numrevs)
2347 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2354 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2348 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2355 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2349 ui.write(('revision size : ') + fmt2 % totalsize)
2356 ui.write(('revision size : ') + fmt2 % totalsize)
2350 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2357 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2351 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2358 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2352
2359
2353 ui.write('\n')
2360 ui.write('\n')
2354 fmt = dfmtstr(max(avgchainlen, compratio))
2361 fmt = dfmtstr(max(avgchainlen, compratio))
2355 ui.write(('avg chain length : ') + fmt % avgchainlen)
2362 ui.write(('avg chain length : ') + fmt % avgchainlen)
2356 ui.write(('compression ratio : ') + fmt % compratio)
2363 ui.write(('compression ratio : ') + fmt % compratio)
2357
2364
2358 if format > 0:
2365 if format > 0:
2359 ui.write('\n')
2366 ui.write('\n')
2360 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2367 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2361 % tuple(datasize))
2368 % tuple(datasize))
2362 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2369 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2363 % tuple(fullsize))
2370 % tuple(fullsize))
2364 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2371 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2365 % tuple(deltasize))
2372 % tuple(deltasize))
2366
2373
2367 if numdeltas > 0:
2374 if numdeltas > 0:
2368 ui.write('\n')
2375 ui.write('\n')
2369 fmt = pcfmtstr(numdeltas)
2376 fmt = pcfmtstr(numdeltas)
2370 fmt2 = pcfmtstr(numdeltas, 4)
2377 fmt2 = pcfmtstr(numdeltas, 4)
2371 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2378 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2372 if numprev > 0:
2379 if numprev > 0:
2373 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2380 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2374 numprev))
2381 numprev))
2375 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2382 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2376 numprev))
2383 numprev))
2377 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2384 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2378 numprev))
2385 numprev))
2379 if gdelta:
2386 if gdelta:
2380 ui.write(('deltas against p1 : ')
2387 ui.write(('deltas against p1 : ')
2381 + fmt % pcfmt(nump1, numdeltas))
2388 + fmt % pcfmt(nump1, numdeltas))
2382 ui.write(('deltas against p2 : ')
2389 ui.write(('deltas against p2 : ')
2383 + fmt % pcfmt(nump2, numdeltas))
2390 + fmt % pcfmt(nump2, numdeltas))
2384 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2391 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2385 numdeltas))
2392 numdeltas))
2386
2393
2387 @command('debugrevspec', [], ('REVSPEC'))
2394 @command('debugrevspec', [], ('REVSPEC'))
2388 def debugrevspec(ui, repo, expr):
2395 def debugrevspec(ui, repo, expr):
2389 """parse and apply a revision specification
2396 """parse and apply a revision specification
2390
2397
2391 Use --verbose to print the parsed tree before and after aliases
2398 Use --verbose to print the parsed tree before and after aliases
2392 expansion.
2399 expansion.
2393 """
2400 """
2394 if ui.verbose:
2401 if ui.verbose:
2395 tree = revset.parse(expr)[0]
2402 tree = revset.parse(expr)[0]
2396 ui.note(revset.prettyformat(tree), "\n")
2403 ui.note(revset.prettyformat(tree), "\n")
2397 newtree = revset.findaliases(ui, tree)
2404 newtree = revset.findaliases(ui, tree)
2398 if newtree != tree:
2405 if newtree != tree:
2399 ui.note(revset.prettyformat(newtree), "\n")
2406 ui.note(revset.prettyformat(newtree), "\n")
2400 func = revset.match(ui, expr)
2407 func = revset.match(ui, expr)
2401 for c in func(repo, range(len(repo))):
2408 for c in func(repo, range(len(repo))):
2402 ui.write("%s\n" % c)
2409 ui.write("%s\n" % c)
2403
2410
2404 @command('debugsetparents', [], _('REV1 [REV2]'))
2411 @command('debugsetparents', [], _('REV1 [REV2]'))
2405 def debugsetparents(ui, repo, rev1, rev2=None):
2412 def debugsetparents(ui, repo, rev1, rev2=None):
2406 """manually set the parents of the current working directory
2413 """manually set the parents of the current working directory
2407
2414
2408 This is useful for writing repository conversion tools, but should
2415 This is useful for writing repository conversion tools, but should
2409 be used with care.
2416 be used with care.
2410
2417
2411 Returns 0 on success.
2418 Returns 0 on success.
2412 """
2419 """
2413
2420
2414 r1 = scmutil.revsingle(repo, rev1).node()
2421 r1 = scmutil.revsingle(repo, rev1).node()
2415 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2422 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2416
2423
2417 wlock = repo.wlock()
2424 wlock = repo.wlock()
2418 try:
2425 try:
2419 repo.setparents(r1, r2)
2426 repo.setparents(r1, r2)
2420 finally:
2427 finally:
2421 wlock.release()
2428 wlock.release()
2422
2429
2423 @command('debugstate',
2430 @command('debugstate',
2424 [('', 'nodates', None, _('do not display the saved mtime')),
2431 [('', 'nodates', None, _('do not display the saved mtime')),
2425 ('', 'datesort', None, _('sort by saved mtime'))],
2432 ('', 'datesort', None, _('sort by saved mtime'))],
2426 _('[OPTION]...'))
2433 _('[OPTION]...'))
2427 def debugstate(ui, repo, nodates=None, datesort=None):
2434 def debugstate(ui, repo, nodates=None, datesort=None):
2428 """show the contents of the current dirstate"""
2435 """show the contents of the current dirstate"""
2429 timestr = ""
2436 timestr = ""
2430 showdate = not nodates
2437 showdate = not nodates
2431 if datesort:
2438 if datesort:
2432 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2439 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2433 else:
2440 else:
2434 keyfunc = None # sort by filename
2441 keyfunc = None # sort by filename
2435 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2442 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2436 if showdate:
2443 if showdate:
2437 if ent[3] == -1:
2444 if ent[3] == -1:
2438 # Pad or slice to locale representation
2445 # Pad or slice to locale representation
2439 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2446 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2440 time.localtime(0)))
2447 time.localtime(0)))
2441 timestr = 'unset'
2448 timestr = 'unset'
2442 timestr = (timestr[:locale_len] +
2449 timestr = (timestr[:locale_len] +
2443 ' ' * (locale_len - len(timestr)))
2450 ' ' * (locale_len - len(timestr)))
2444 else:
2451 else:
2445 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2452 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2446 time.localtime(ent[3]))
2453 time.localtime(ent[3]))
2447 if ent[1] & 020000:
2454 if ent[1] & 020000:
2448 mode = 'lnk'
2455 mode = 'lnk'
2449 else:
2456 else:
2450 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2457 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2451 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2458 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2452 for f in repo.dirstate.copies():
2459 for f in repo.dirstate.copies():
2453 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2460 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2454
2461
2455 @command('debugsub',
2462 @command('debugsub',
2456 [('r', 'rev', '',
2463 [('r', 'rev', '',
2457 _('revision to check'), _('REV'))],
2464 _('revision to check'), _('REV'))],
2458 _('[-r REV] [REV]'))
2465 _('[-r REV] [REV]'))
2459 def debugsub(ui, repo, rev=None):
2466 def debugsub(ui, repo, rev=None):
2460 ctx = scmutil.revsingle(repo, rev, None)
2467 ctx = scmutil.revsingle(repo, rev, None)
2461 for k, v in sorted(ctx.substate.items()):
2468 for k, v in sorted(ctx.substate.items()):
2462 ui.write(('path %s\n') % k)
2469 ui.write(('path %s\n') % k)
2463 ui.write((' source %s\n') % v[0])
2470 ui.write((' source %s\n') % v[0])
2464 ui.write((' revision %s\n') % v[1])
2471 ui.write((' revision %s\n') % v[1])
2465
2472
2466 @command('debugsuccessorssets',
2473 @command('debugsuccessorssets',
2467 [],
2474 [],
2468 _('[REV]'))
2475 _('[REV]'))
2469 def debugsuccessorssets(ui, repo, *revs):
2476 def debugsuccessorssets(ui, repo, *revs):
2470 """show set of successors for revision
2477 """show set of successors for revision
2471
2478
2472 A successors set of changeset A is a consistent group of revisions that
2479 A successors set of changeset A is a consistent group of revisions that
2473 succeed A. It contains non-obsolete changesets only.
2480 succeed A. It contains non-obsolete changesets only.
2474
2481
2475 In most cases a changeset A has a single successors set containing a single
2482 In most cases a changeset A has a single successors set containing a single
2476 successor (changeset A replaced by A').
2483 successor (changeset A replaced by A').
2477
2484
2478 A changeset that is made obsolete with no successors are called "pruned".
2485 A changeset that is made obsolete with no successors are called "pruned".
2479 Such changesets have no successors sets at all.
2486 Such changesets have no successors sets at all.
2480
2487
2481 A changeset that has been "split" will have a successors set containing
2488 A changeset that has been "split" will have a successors set containing
2482 more than one successor.
2489 more than one successor.
2483
2490
2484 A changeset that has been rewritten in multiple different ways is called
2491 A changeset that has been rewritten in multiple different ways is called
2485 "divergent". Such changesets have multiple successor sets (each of which
2492 "divergent". Such changesets have multiple successor sets (each of which
2486 may also be split, i.e. have multiple successors).
2493 may also be split, i.e. have multiple successors).
2487
2494
2488 Results are displayed as follows::
2495 Results are displayed as follows::
2489
2496
2490 <rev1>
2497 <rev1>
2491 <successors-1A>
2498 <successors-1A>
2492 <rev2>
2499 <rev2>
2493 <successors-2A>
2500 <successors-2A>
2494 <successors-2B1> <successors-2B2> <successors-2B3>
2501 <successors-2B1> <successors-2B2> <successors-2B3>
2495
2502
2496 Here rev2 has two possible (i.e. divergent) successors sets. The first
2503 Here rev2 has two possible (i.e. divergent) successors sets. The first
2497 holds one element, whereas the second holds three (i.e. the changeset has
2504 holds one element, whereas the second holds three (i.e. the changeset has
2498 been split).
2505 been split).
2499 """
2506 """
2500 # passed to successorssets caching computation from one call to another
2507 # passed to successorssets caching computation from one call to another
2501 cache = {}
2508 cache = {}
2502 ctx2str = str
2509 ctx2str = str
2503 node2str = short
2510 node2str = short
2504 if ui.debug():
2511 if ui.debug():
2505 def ctx2str(ctx):
2512 def ctx2str(ctx):
2506 return ctx.hex()
2513 return ctx.hex()
2507 node2str = hex
2514 node2str = hex
2508 for rev in scmutil.revrange(repo, revs):
2515 for rev in scmutil.revrange(repo, revs):
2509 ctx = repo[rev]
2516 ctx = repo[rev]
2510 ui.write('%s\n'% ctx2str(ctx))
2517 ui.write('%s\n'% ctx2str(ctx))
2511 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2518 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2512 if succsset:
2519 if succsset:
2513 ui.write(' ')
2520 ui.write(' ')
2514 ui.write(node2str(succsset[0]))
2521 ui.write(node2str(succsset[0]))
2515 for node in succsset[1:]:
2522 for node in succsset[1:]:
2516 ui.write(' ')
2523 ui.write(' ')
2517 ui.write(node2str(node))
2524 ui.write(node2str(node))
2518 ui.write('\n')
2525 ui.write('\n')
2519
2526
2520 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2527 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2521 def debugwalk(ui, repo, *pats, **opts):
2528 def debugwalk(ui, repo, *pats, **opts):
2522 """show how files match on given patterns"""
2529 """show how files match on given patterns"""
2523 m = scmutil.match(repo[None], pats, opts)
2530 m = scmutil.match(repo[None], pats, opts)
2524 items = list(repo.walk(m))
2531 items = list(repo.walk(m))
2525 if not items:
2532 if not items:
2526 return
2533 return
2527 f = lambda fn: fn
2534 f = lambda fn: fn
2528 if ui.configbool('ui', 'slash') and os.sep != '/':
2535 if ui.configbool('ui', 'slash') and os.sep != '/':
2529 f = lambda fn: util.normpath(fn)
2536 f = lambda fn: util.normpath(fn)
2530 fmt = 'f %%-%ds %%-%ds %%s' % (
2537 fmt = 'f %%-%ds %%-%ds %%s' % (
2531 max([len(abs) for abs in items]),
2538 max([len(abs) for abs in items]),
2532 max([len(m.rel(abs)) for abs in items]))
2539 max([len(m.rel(abs)) for abs in items]))
2533 for abs in items:
2540 for abs in items:
2534 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2541 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2535 ui.write("%s\n" % line.rstrip())
2542 ui.write("%s\n" % line.rstrip())
2536
2543
2537 @command('debugwireargs',
2544 @command('debugwireargs',
2538 [('', 'three', '', 'three'),
2545 [('', 'three', '', 'three'),
2539 ('', 'four', '', 'four'),
2546 ('', 'four', '', 'four'),
2540 ('', 'five', '', 'five'),
2547 ('', 'five', '', 'five'),
2541 ] + remoteopts,
2548 ] + remoteopts,
2542 _('REPO [OPTIONS]... [ONE [TWO]]'))
2549 _('REPO [OPTIONS]... [ONE [TWO]]'))
2543 def debugwireargs(ui, repopath, *vals, **opts):
2550 def debugwireargs(ui, repopath, *vals, **opts):
2544 repo = hg.peer(ui, opts, repopath)
2551 repo = hg.peer(ui, opts, repopath)
2545 for opt in remoteopts:
2552 for opt in remoteopts:
2546 del opts[opt[1]]
2553 del opts[opt[1]]
2547 args = {}
2554 args = {}
2548 for k, v in opts.iteritems():
2555 for k, v in opts.iteritems():
2549 if v:
2556 if v:
2550 args[k] = v
2557 args[k] = v
2551 # run twice to check that we don't mess up the stream for the next command
2558 # run twice to check that we don't mess up the stream for the next command
2552 res1 = repo.debugwireargs(*vals, **args)
2559 res1 = repo.debugwireargs(*vals, **args)
2553 res2 = repo.debugwireargs(*vals, **args)
2560 res2 = repo.debugwireargs(*vals, **args)
2554 ui.write("%s\n" % res1)
2561 ui.write("%s\n" % res1)
2555 if res1 != res2:
2562 if res1 != res2:
2556 ui.warn("%s\n" % res2)
2563 ui.warn("%s\n" % res2)
2557
2564
2558 @command('^diff',
2565 @command('^diff',
2559 [('r', 'rev', [], _('revision'), _('REV')),
2566 [('r', 'rev', [], _('revision'), _('REV')),
2560 ('c', 'change', '', _('change made by revision'), _('REV'))
2567 ('c', 'change', '', _('change made by revision'), _('REV'))
2561 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2568 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2562 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2569 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2563 def diff(ui, repo, *pats, **opts):
2570 def diff(ui, repo, *pats, **opts):
2564 """diff repository (or selected files)
2571 """diff repository (or selected files)
2565
2572
2566 Show differences between revisions for the specified files.
2573 Show differences between revisions for the specified files.
2567
2574
2568 Differences between files are shown using the unified diff format.
2575 Differences between files are shown using the unified diff format.
2569
2576
2570 .. note::
2577 .. note::
2571 diff may generate unexpected results for merges, as it will
2578 diff may generate unexpected results for merges, as it will
2572 default to comparing against the working directory's first
2579 default to comparing against the working directory's first
2573 parent changeset if no revisions are specified.
2580 parent changeset if no revisions are specified.
2574
2581
2575 When two revision arguments are given, then changes are shown
2582 When two revision arguments are given, then changes are shown
2576 between those revisions. If only one revision is specified then
2583 between those revisions. If only one revision is specified then
2577 that revision is compared to the working directory, and, when no
2584 that revision is compared to the working directory, and, when no
2578 revisions are specified, the working directory files are compared
2585 revisions are specified, the working directory files are compared
2579 to its parent.
2586 to its parent.
2580
2587
2581 Alternatively you can specify -c/--change with a revision to see
2588 Alternatively you can specify -c/--change with a revision to see
2582 the changes in that changeset relative to its first parent.
2589 the changes in that changeset relative to its first parent.
2583
2590
2584 Without the -a/--text option, diff will avoid generating diffs of
2591 Without the -a/--text option, diff will avoid generating diffs of
2585 files it detects as binary. With -a, diff will generate a diff
2592 files it detects as binary. With -a, diff will generate a diff
2586 anyway, probably with undesirable results.
2593 anyway, probably with undesirable results.
2587
2594
2588 Use the -g/--git option to generate diffs in the git extended diff
2595 Use the -g/--git option to generate diffs in the git extended diff
2589 format. For more information, read :hg:`help diffs`.
2596 format. For more information, read :hg:`help diffs`.
2590
2597
2591 .. container:: verbose
2598 .. container:: verbose
2592
2599
2593 Examples:
2600 Examples:
2594
2601
2595 - compare a file in the current working directory to its parent::
2602 - compare a file in the current working directory to its parent::
2596
2603
2597 hg diff foo.c
2604 hg diff foo.c
2598
2605
2599 - compare two historical versions of a directory, with rename info::
2606 - compare two historical versions of a directory, with rename info::
2600
2607
2601 hg diff --git -r 1.0:1.2 lib/
2608 hg diff --git -r 1.0:1.2 lib/
2602
2609
2603 - get change stats relative to the last change on some date::
2610 - get change stats relative to the last change on some date::
2604
2611
2605 hg diff --stat -r "date('may 2')"
2612 hg diff --stat -r "date('may 2')"
2606
2613
2607 - diff all newly-added files that contain a keyword::
2614 - diff all newly-added files that contain a keyword::
2608
2615
2609 hg diff "set:added() and grep(GNU)"
2616 hg diff "set:added() and grep(GNU)"
2610
2617
2611 - compare a revision and its parents::
2618 - compare a revision and its parents::
2612
2619
2613 hg diff -c 9353 # compare against first parent
2620 hg diff -c 9353 # compare against first parent
2614 hg diff -r 9353^:9353 # same using revset syntax
2621 hg diff -r 9353^:9353 # same using revset syntax
2615 hg diff -r 9353^2:9353 # compare against the second parent
2622 hg diff -r 9353^2:9353 # compare against the second parent
2616
2623
2617 Returns 0 on success.
2624 Returns 0 on success.
2618 """
2625 """
2619
2626
2620 revs = opts.get('rev')
2627 revs = opts.get('rev')
2621 change = opts.get('change')
2628 change = opts.get('change')
2622 stat = opts.get('stat')
2629 stat = opts.get('stat')
2623 reverse = opts.get('reverse')
2630 reverse = opts.get('reverse')
2624
2631
2625 if revs and change:
2632 if revs and change:
2626 msg = _('cannot specify --rev and --change at the same time')
2633 msg = _('cannot specify --rev and --change at the same time')
2627 raise util.Abort(msg)
2634 raise util.Abort(msg)
2628 elif change:
2635 elif change:
2629 node2 = scmutil.revsingle(repo, change, None).node()
2636 node2 = scmutil.revsingle(repo, change, None).node()
2630 node1 = repo[node2].p1().node()
2637 node1 = repo[node2].p1().node()
2631 else:
2638 else:
2632 node1, node2 = scmutil.revpair(repo, revs)
2639 node1, node2 = scmutil.revpair(repo, revs)
2633
2640
2634 if reverse:
2641 if reverse:
2635 node1, node2 = node2, node1
2642 node1, node2 = node2, node1
2636
2643
2637 diffopts = patch.diffopts(ui, opts)
2644 diffopts = patch.diffopts(ui, opts)
2638 m = scmutil.match(repo[node2], pats, opts)
2645 m = scmutil.match(repo[node2], pats, opts)
2639 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2646 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2640 listsubrepos=opts.get('subrepos'))
2647 listsubrepos=opts.get('subrepos'))
2641
2648
2642 @command('^export',
2649 @command('^export',
2643 [('o', 'output', '',
2650 [('o', 'output', '',
2644 _('print output to file with formatted name'), _('FORMAT')),
2651 _('print output to file with formatted name'), _('FORMAT')),
2645 ('', 'switch-parent', None, _('diff against the second parent')),
2652 ('', 'switch-parent', None, _('diff against the second parent')),
2646 ('r', 'rev', [], _('revisions to export'), _('REV')),
2653 ('r', 'rev', [], _('revisions to export'), _('REV')),
2647 ] + diffopts,
2654 ] + diffopts,
2648 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2655 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2649 def export(ui, repo, *changesets, **opts):
2656 def export(ui, repo, *changesets, **opts):
2650 """dump the header and diffs for one or more changesets
2657 """dump the header and diffs for one or more changesets
2651
2658
2652 Print the changeset header and diffs for one or more revisions.
2659 Print the changeset header and diffs for one or more revisions.
2653
2660
2654 The information shown in the changeset header is: author, date,
2661 The information shown in the changeset header is: author, date,
2655 branch name (if non-default), changeset hash, parent(s) and commit
2662 branch name (if non-default), changeset hash, parent(s) and commit
2656 comment.
2663 comment.
2657
2664
2658 .. note::
2665 .. note::
2659 export may generate unexpected diff output for merge
2666 export may generate unexpected diff output for merge
2660 changesets, as it will compare the merge changeset against its
2667 changesets, as it will compare the merge changeset against its
2661 first parent only.
2668 first parent only.
2662
2669
2663 Output may be to a file, in which case the name of the file is
2670 Output may be to a file, in which case the name of the file is
2664 given using a format string. The formatting rules are as follows:
2671 given using a format string. The formatting rules are as follows:
2665
2672
2666 :``%%``: literal "%" character
2673 :``%%``: literal "%" character
2667 :``%H``: changeset hash (40 hexadecimal digits)
2674 :``%H``: changeset hash (40 hexadecimal digits)
2668 :``%N``: number of patches being generated
2675 :``%N``: number of patches being generated
2669 :``%R``: changeset revision number
2676 :``%R``: changeset revision number
2670 :``%b``: basename of the exporting repository
2677 :``%b``: basename of the exporting repository
2671 :``%h``: short-form changeset hash (12 hexadecimal digits)
2678 :``%h``: short-form changeset hash (12 hexadecimal digits)
2672 :``%m``: first line of the commit message (only alphanumeric characters)
2679 :``%m``: first line of the commit message (only alphanumeric characters)
2673 :``%n``: zero-padded sequence number, starting at 1
2680 :``%n``: zero-padded sequence number, starting at 1
2674 :``%r``: zero-padded changeset revision number
2681 :``%r``: zero-padded changeset revision number
2675
2682
2676 Without the -a/--text option, export will avoid generating diffs
2683 Without the -a/--text option, export will avoid generating diffs
2677 of files it detects as binary. With -a, export will generate a
2684 of files it detects as binary. With -a, export will generate a
2678 diff anyway, probably with undesirable results.
2685 diff anyway, probably with undesirable results.
2679
2686
2680 Use the -g/--git option to generate diffs in the git extended diff
2687 Use the -g/--git option to generate diffs in the git extended diff
2681 format. See :hg:`help diffs` for more information.
2688 format. See :hg:`help diffs` for more information.
2682
2689
2683 With the --switch-parent option, the diff will be against the
2690 With the --switch-parent option, the diff will be against the
2684 second parent. It can be useful to review a merge.
2691 second parent. It can be useful to review a merge.
2685
2692
2686 .. container:: verbose
2693 .. container:: verbose
2687
2694
2688 Examples:
2695 Examples:
2689
2696
2690 - use export and import to transplant a bugfix to the current
2697 - use export and import to transplant a bugfix to the current
2691 branch::
2698 branch::
2692
2699
2693 hg export -r 9353 | hg import -
2700 hg export -r 9353 | hg import -
2694
2701
2695 - export all the changesets between two revisions to a file with
2702 - export all the changesets between two revisions to a file with
2696 rename information::
2703 rename information::
2697
2704
2698 hg export --git -r 123:150 > changes.txt
2705 hg export --git -r 123:150 > changes.txt
2699
2706
2700 - split outgoing changes into a series of patches with
2707 - split outgoing changes into a series of patches with
2701 descriptive names::
2708 descriptive names::
2702
2709
2703 hg export -r "outgoing()" -o "%n-%m.patch"
2710 hg export -r "outgoing()" -o "%n-%m.patch"
2704
2711
2705 Returns 0 on success.
2712 Returns 0 on success.
2706 """
2713 """
2707 changesets += tuple(opts.get('rev', []))
2714 changesets += tuple(opts.get('rev', []))
2708 revs = scmutil.revrange(repo, changesets)
2715 revs = scmutil.revrange(repo, changesets)
2709 if not revs:
2716 if not revs:
2710 raise util.Abort(_("export requires at least one changeset"))
2717 raise util.Abort(_("export requires at least one changeset"))
2711 if len(revs) > 1:
2718 if len(revs) > 1:
2712 ui.note(_('exporting patches:\n'))
2719 ui.note(_('exporting patches:\n'))
2713 else:
2720 else:
2714 ui.note(_('exporting patch:\n'))
2721 ui.note(_('exporting patch:\n'))
2715 cmdutil.export(repo, revs, template=opts.get('output'),
2722 cmdutil.export(repo, revs, template=opts.get('output'),
2716 switch_parent=opts.get('switch_parent'),
2723 switch_parent=opts.get('switch_parent'),
2717 opts=patch.diffopts(ui, opts))
2724 opts=patch.diffopts(ui, opts))
2718
2725
2719 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2726 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2720 def forget(ui, repo, *pats, **opts):
2727 def forget(ui, repo, *pats, **opts):
2721 """forget the specified files on the next commit
2728 """forget the specified files on the next commit
2722
2729
2723 Mark the specified files so they will no longer be tracked
2730 Mark the specified files so they will no longer be tracked
2724 after the next commit.
2731 after the next commit.
2725
2732
2726 This only removes files from the current branch, not from the
2733 This only removes files from the current branch, not from the
2727 entire project history, and it does not delete them from the
2734 entire project history, and it does not delete them from the
2728 working directory.
2735 working directory.
2729
2736
2730 To undo a forget before the next commit, see :hg:`add`.
2737 To undo a forget before the next commit, see :hg:`add`.
2731
2738
2732 .. container:: verbose
2739 .. container:: verbose
2733
2740
2734 Examples:
2741 Examples:
2735
2742
2736 - forget newly-added binary files::
2743 - forget newly-added binary files::
2737
2744
2738 hg forget "set:added() and binary()"
2745 hg forget "set:added() and binary()"
2739
2746
2740 - forget files that would be excluded by .hgignore::
2747 - forget files that would be excluded by .hgignore::
2741
2748
2742 hg forget "set:hgignore()"
2749 hg forget "set:hgignore()"
2743
2750
2744 Returns 0 on success.
2751 Returns 0 on success.
2745 """
2752 """
2746
2753
2747 if not pats:
2754 if not pats:
2748 raise util.Abort(_('no files specified'))
2755 raise util.Abort(_('no files specified'))
2749
2756
2750 m = scmutil.match(repo[None], pats, opts)
2757 m = scmutil.match(repo[None], pats, opts)
2751 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2758 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2752 return rejected and 1 or 0
2759 return rejected and 1 or 0
2753
2760
2754 @command(
2761 @command(
2755 'graft',
2762 'graft',
2756 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2763 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2757 ('c', 'continue', False, _('resume interrupted graft')),
2764 ('c', 'continue', False, _('resume interrupted graft')),
2758 ('e', 'edit', False, _('invoke editor on commit messages')),
2765 ('e', 'edit', False, _('invoke editor on commit messages')),
2759 ('', 'log', None, _('append graft info to log message')),
2766 ('', 'log', None, _('append graft info to log message')),
2760 ('D', 'currentdate', False,
2767 ('D', 'currentdate', False,
2761 _('record the current date as commit date')),
2768 _('record the current date as commit date')),
2762 ('U', 'currentuser', False,
2769 ('U', 'currentuser', False,
2763 _('record the current user as committer'), _('DATE'))]
2770 _('record the current user as committer'), _('DATE'))]
2764 + commitopts2 + mergetoolopts + dryrunopts,
2771 + commitopts2 + mergetoolopts + dryrunopts,
2765 _('[OPTION]... [-r] REV...'))
2772 _('[OPTION]... [-r] REV...'))
2766 def graft(ui, repo, *revs, **opts):
2773 def graft(ui, repo, *revs, **opts):
2767 '''copy changes from other branches onto the current branch
2774 '''copy changes from other branches onto the current branch
2768
2775
2769 This command uses Mercurial's merge logic to copy individual
2776 This command uses Mercurial's merge logic to copy individual
2770 changes from other branches without merging branches in the
2777 changes from other branches without merging branches in the
2771 history graph. This is sometimes known as 'backporting' or
2778 history graph. This is sometimes known as 'backporting' or
2772 'cherry-picking'. By default, graft will copy user, date, and
2779 'cherry-picking'. By default, graft will copy user, date, and
2773 description from the source changesets.
2780 description from the source changesets.
2774
2781
2775 Changesets that are ancestors of the current revision, that have
2782 Changesets that are ancestors of the current revision, that have
2776 already been grafted, or that are merges will be skipped.
2783 already been grafted, or that are merges will be skipped.
2777
2784
2778 If --log is specified, log messages will have a comment appended
2785 If --log is specified, log messages will have a comment appended
2779 of the form::
2786 of the form::
2780
2787
2781 (grafted from CHANGESETHASH)
2788 (grafted from CHANGESETHASH)
2782
2789
2783 If a graft merge results in conflicts, the graft process is
2790 If a graft merge results in conflicts, the graft process is
2784 interrupted so that the current merge can be manually resolved.
2791 interrupted so that the current merge can be manually resolved.
2785 Once all conflicts are addressed, the graft process can be
2792 Once all conflicts are addressed, the graft process can be
2786 continued with the -c/--continue option.
2793 continued with the -c/--continue option.
2787
2794
2788 .. note::
2795 .. note::
2789 The -c/--continue option does not reapply earlier options.
2796 The -c/--continue option does not reapply earlier options.
2790
2797
2791 .. container:: verbose
2798 .. container:: verbose
2792
2799
2793 Examples:
2800 Examples:
2794
2801
2795 - copy a single change to the stable branch and edit its description::
2802 - copy a single change to the stable branch and edit its description::
2796
2803
2797 hg update stable
2804 hg update stable
2798 hg graft --edit 9393
2805 hg graft --edit 9393
2799
2806
2800 - graft a range of changesets with one exception, updating dates::
2807 - graft a range of changesets with one exception, updating dates::
2801
2808
2802 hg graft -D "2085::2093 and not 2091"
2809 hg graft -D "2085::2093 and not 2091"
2803
2810
2804 - continue a graft after resolving conflicts::
2811 - continue a graft after resolving conflicts::
2805
2812
2806 hg graft -c
2813 hg graft -c
2807
2814
2808 - show the source of a grafted changeset::
2815 - show the source of a grafted changeset::
2809
2816
2810 hg log --debug -r tip
2817 hg log --debug -r tip
2811
2818
2812 Returns 0 on successful completion.
2819 Returns 0 on successful completion.
2813 '''
2820 '''
2814
2821
2815 revs = list(revs)
2822 revs = list(revs)
2816 revs.extend(opts['rev'])
2823 revs.extend(opts['rev'])
2817
2824
2818 if not opts.get('user') and opts.get('currentuser'):
2825 if not opts.get('user') and opts.get('currentuser'):
2819 opts['user'] = ui.username()
2826 opts['user'] = ui.username()
2820 if not opts.get('date') and opts.get('currentdate'):
2827 if not opts.get('date') and opts.get('currentdate'):
2821 opts['date'] = "%d %d" % util.makedate()
2828 opts['date'] = "%d %d" % util.makedate()
2822
2829
2823 editor = None
2830 editor = None
2824 if opts.get('edit'):
2831 if opts.get('edit'):
2825 editor = cmdutil.commitforceeditor
2832 editor = cmdutil.commitforceeditor
2826
2833
2827 cont = False
2834 cont = False
2828 if opts['continue']:
2835 if opts['continue']:
2829 cont = True
2836 cont = True
2830 if revs:
2837 if revs:
2831 raise util.Abort(_("can't specify --continue and revisions"))
2838 raise util.Abort(_("can't specify --continue and revisions"))
2832 # read in unfinished revisions
2839 # read in unfinished revisions
2833 try:
2840 try:
2834 nodes = repo.opener.read('graftstate').splitlines()
2841 nodes = repo.opener.read('graftstate').splitlines()
2835 revs = [repo[node].rev() for node in nodes]
2842 revs = [repo[node].rev() for node in nodes]
2836 except IOError, inst:
2843 except IOError, inst:
2837 if inst.errno != errno.ENOENT:
2844 if inst.errno != errno.ENOENT:
2838 raise
2845 raise
2839 raise util.Abort(_("no graft state found, can't continue"))
2846 raise util.Abort(_("no graft state found, can't continue"))
2840 else:
2847 else:
2841 cmdutil.bailifchanged(repo)
2848 cmdutil.bailifchanged(repo)
2842 if not revs:
2849 if not revs:
2843 raise util.Abort(_('no revisions specified'))
2850 raise util.Abort(_('no revisions specified'))
2844 revs = scmutil.revrange(repo, revs)
2851 revs = scmutil.revrange(repo, revs)
2845
2852
2846 # check for merges
2853 # check for merges
2847 for rev in repo.revs('%ld and merge()', revs):
2854 for rev in repo.revs('%ld and merge()', revs):
2848 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2855 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2849 revs.remove(rev)
2856 revs.remove(rev)
2850 if not revs:
2857 if not revs:
2851 return -1
2858 return -1
2852
2859
2853 # check for ancestors of dest branch
2860 # check for ancestors of dest branch
2854 for rev in repo.revs('::. and %ld', revs):
2861 for rev in repo.revs('::. and %ld', revs):
2855 ui.warn(_('skipping ancestor revision %s\n') % rev)
2862 ui.warn(_('skipping ancestor revision %s\n') % rev)
2856 revs.remove(rev)
2863 revs.remove(rev)
2857 if not revs:
2864 if not revs:
2858 return -1
2865 return -1
2859
2866
2860 # analyze revs for earlier grafts
2867 # analyze revs for earlier grafts
2861 ids = {}
2868 ids = {}
2862 for ctx in repo.set("%ld", revs):
2869 for ctx in repo.set("%ld", revs):
2863 ids[ctx.hex()] = ctx.rev()
2870 ids[ctx.hex()] = ctx.rev()
2864 n = ctx.extra().get('source')
2871 n = ctx.extra().get('source')
2865 if n:
2872 if n:
2866 ids[n] = ctx.rev()
2873 ids[n] = ctx.rev()
2867
2874
2868 # check ancestors for earlier grafts
2875 # check ancestors for earlier grafts
2869 ui.debug('scanning for duplicate grafts\n')
2876 ui.debug('scanning for duplicate grafts\n')
2870 for ctx in repo.set("::. - ::%ld", revs):
2877 for ctx in repo.set("::. - ::%ld", revs):
2871 n = ctx.extra().get('source')
2878 n = ctx.extra().get('source')
2872 if n in ids:
2879 if n in ids:
2873 r = repo[n].rev()
2880 r = repo[n].rev()
2874 if r in revs:
2881 if r in revs:
2875 ui.warn(_('skipping already grafted revision %s\n') % r)
2882 ui.warn(_('skipping already grafted revision %s\n') % r)
2876 revs.remove(r)
2883 revs.remove(r)
2877 elif ids[n] in revs:
2884 elif ids[n] in revs:
2878 ui.warn(_('skipping already grafted revision %s '
2885 ui.warn(_('skipping already grafted revision %s '
2879 '(same origin %d)\n') % (ids[n], r))
2886 '(same origin %d)\n') % (ids[n], r))
2880 revs.remove(ids[n])
2887 revs.remove(ids[n])
2881 elif ctx.hex() in ids:
2888 elif ctx.hex() in ids:
2882 r = ids[ctx.hex()]
2889 r = ids[ctx.hex()]
2883 ui.warn(_('skipping already grafted revision %s '
2890 ui.warn(_('skipping already grafted revision %s '
2884 '(was grafted from %d)\n') % (r, ctx.rev()))
2891 '(was grafted from %d)\n') % (r, ctx.rev()))
2885 revs.remove(r)
2892 revs.remove(r)
2886 if not revs:
2893 if not revs:
2887 return -1
2894 return -1
2888
2895
2889 wlock = repo.wlock()
2896 wlock = repo.wlock()
2890 try:
2897 try:
2891 current = repo['.']
2898 current = repo['.']
2892 for pos, ctx in enumerate(repo.set("%ld", revs)):
2899 for pos, ctx in enumerate(repo.set("%ld", revs)):
2893
2900
2894 ui.status(_('grafting revision %s\n') % ctx.rev())
2901 ui.status(_('grafting revision %s\n') % ctx.rev())
2895 if opts.get('dry_run'):
2902 if opts.get('dry_run'):
2896 continue
2903 continue
2897
2904
2898 source = ctx.extra().get('source')
2905 source = ctx.extra().get('source')
2899 if not source:
2906 if not source:
2900 source = ctx.hex()
2907 source = ctx.hex()
2901 extra = {'source': source}
2908 extra = {'source': source}
2902 user = ctx.user()
2909 user = ctx.user()
2903 if opts.get('user'):
2910 if opts.get('user'):
2904 user = opts['user']
2911 user = opts['user']
2905 date = ctx.date()
2912 date = ctx.date()
2906 if opts.get('date'):
2913 if opts.get('date'):
2907 date = opts['date']
2914 date = opts['date']
2908 message = ctx.description()
2915 message = ctx.description()
2909 if opts.get('log'):
2916 if opts.get('log'):
2910 message += '\n(grafted from %s)' % ctx.hex()
2917 message += '\n(grafted from %s)' % ctx.hex()
2911
2918
2912 # we don't merge the first commit when continuing
2919 # we don't merge the first commit when continuing
2913 if not cont:
2920 if not cont:
2914 # perform the graft merge with p1(rev) as 'ancestor'
2921 # perform the graft merge with p1(rev) as 'ancestor'
2915 try:
2922 try:
2916 # ui.forcemerge is an internal variable, do not document
2923 # ui.forcemerge is an internal variable, do not document
2917 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2924 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2918 stats = mergemod.update(repo, ctx.node(), True, True, False,
2925 stats = mergemod.update(repo, ctx.node(), True, True, False,
2919 ctx.p1().node())
2926 ctx.p1().node())
2920 finally:
2927 finally:
2921 repo.ui.setconfig('ui', 'forcemerge', '')
2928 repo.ui.setconfig('ui', 'forcemerge', '')
2922 # report any conflicts
2929 # report any conflicts
2923 if stats and stats[3] > 0:
2930 if stats and stats[3] > 0:
2924 # write out state for --continue
2931 # write out state for --continue
2925 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2932 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2926 repo.opener.write('graftstate', ''.join(nodelines))
2933 repo.opener.write('graftstate', ''.join(nodelines))
2927 raise util.Abort(
2934 raise util.Abort(
2928 _("unresolved conflicts, can't continue"),
2935 _("unresolved conflicts, can't continue"),
2929 hint=_('use hg resolve and hg graft --continue'))
2936 hint=_('use hg resolve and hg graft --continue'))
2930 else:
2937 else:
2931 cont = False
2938 cont = False
2932
2939
2933 # drop the second merge parent
2940 # drop the second merge parent
2934 repo.setparents(current.node(), nullid)
2941 repo.setparents(current.node(), nullid)
2935 repo.dirstate.write()
2942 repo.dirstate.write()
2936 # fix up dirstate for copies and renames
2943 # fix up dirstate for copies and renames
2937 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2944 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2938
2945
2939 # commit
2946 # commit
2940 node = repo.commit(text=message, user=user,
2947 node = repo.commit(text=message, user=user,
2941 date=date, extra=extra, editor=editor)
2948 date=date, extra=extra, editor=editor)
2942 if node is None:
2949 if node is None:
2943 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2950 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2944 else:
2951 else:
2945 current = repo[node]
2952 current = repo[node]
2946 finally:
2953 finally:
2947 wlock.release()
2954 wlock.release()
2948
2955
2949 # remove state when we complete successfully
2956 # remove state when we complete successfully
2950 if not opts.get('dry_run'):
2957 if not opts.get('dry_run'):
2951 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2958 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2952
2959
2953 return 0
2960 return 0
2954
2961
2955 @command('grep',
2962 @command('grep',
2956 [('0', 'print0', None, _('end fields with NUL')),
2963 [('0', 'print0', None, _('end fields with NUL')),
2957 ('', 'all', None, _('print all revisions that match')),
2964 ('', 'all', None, _('print all revisions that match')),
2958 ('a', 'text', None, _('treat all files as text')),
2965 ('a', 'text', None, _('treat all files as text')),
2959 ('f', 'follow', None,
2966 ('f', 'follow', None,
2960 _('follow changeset history,'
2967 _('follow changeset history,'
2961 ' or file history across copies and renames')),
2968 ' or file history across copies and renames')),
2962 ('i', 'ignore-case', None, _('ignore case when matching')),
2969 ('i', 'ignore-case', None, _('ignore case when matching')),
2963 ('l', 'files-with-matches', None,
2970 ('l', 'files-with-matches', None,
2964 _('print only filenames and revisions that match')),
2971 _('print only filenames and revisions that match')),
2965 ('n', 'line-number', None, _('print matching line numbers')),
2972 ('n', 'line-number', None, _('print matching line numbers')),
2966 ('r', 'rev', [],
2973 ('r', 'rev', [],
2967 _('only search files changed within revision range'), _('REV')),
2974 _('only search files changed within revision range'), _('REV')),
2968 ('u', 'user', None, _('list the author (long with -v)')),
2975 ('u', 'user', None, _('list the author (long with -v)')),
2969 ('d', 'date', None, _('list the date (short with -q)')),
2976 ('d', 'date', None, _('list the date (short with -q)')),
2970 ] + walkopts,
2977 ] + walkopts,
2971 _('[OPTION]... PATTERN [FILE]...'))
2978 _('[OPTION]... PATTERN [FILE]...'))
2972 def grep(ui, repo, pattern, *pats, **opts):
2979 def grep(ui, repo, pattern, *pats, **opts):
2973 """search for a pattern in specified files and revisions
2980 """search for a pattern in specified files and revisions
2974
2981
2975 Search revisions of files for a regular expression.
2982 Search revisions of files for a regular expression.
2976
2983
2977 This command behaves differently than Unix grep. It only accepts
2984 This command behaves differently than Unix grep. It only accepts
2978 Python/Perl regexps. It searches repository history, not the
2985 Python/Perl regexps. It searches repository history, not the
2979 working directory. It always prints the revision number in which a
2986 working directory. It always prints the revision number in which a
2980 match appears.
2987 match appears.
2981
2988
2982 By default, grep only prints output for the first revision of a
2989 By default, grep only prints output for the first revision of a
2983 file in which it finds a match. To get it to print every revision
2990 file in which it finds a match. To get it to print every revision
2984 that contains a change in match status ("-" for a match that
2991 that contains a change in match status ("-" for a match that
2985 becomes a non-match, or "+" for a non-match that becomes a match),
2992 becomes a non-match, or "+" for a non-match that becomes a match),
2986 use the --all flag.
2993 use the --all flag.
2987
2994
2988 Returns 0 if a match is found, 1 otherwise.
2995 Returns 0 if a match is found, 1 otherwise.
2989 """
2996 """
2990 reflags = re.M
2997 reflags = re.M
2991 if opts.get('ignore_case'):
2998 if opts.get('ignore_case'):
2992 reflags |= re.I
2999 reflags |= re.I
2993 try:
3000 try:
2994 regexp = re.compile(pattern, reflags)
3001 regexp = re.compile(pattern, reflags)
2995 except re.error, inst:
3002 except re.error, inst:
2996 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3003 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2997 return 1
3004 return 1
2998 sep, eol = ':', '\n'
3005 sep, eol = ':', '\n'
2999 if opts.get('print0'):
3006 if opts.get('print0'):
3000 sep = eol = '\0'
3007 sep = eol = '\0'
3001
3008
3002 getfile = util.lrucachefunc(repo.file)
3009 getfile = util.lrucachefunc(repo.file)
3003
3010
3004 def matchlines(body):
3011 def matchlines(body):
3005 begin = 0
3012 begin = 0
3006 linenum = 0
3013 linenum = 0
3007 while begin < len(body):
3014 while begin < len(body):
3008 match = regexp.search(body, begin)
3015 match = regexp.search(body, begin)
3009 if not match:
3016 if not match:
3010 break
3017 break
3011 mstart, mend = match.span()
3018 mstart, mend = match.span()
3012 linenum += body.count('\n', begin, mstart) + 1
3019 linenum += body.count('\n', begin, mstart) + 1
3013 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3020 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3014 begin = body.find('\n', mend) + 1 or len(body) + 1
3021 begin = body.find('\n', mend) + 1 or len(body) + 1
3015 lend = begin - 1
3022 lend = begin - 1
3016 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3023 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3017
3024
3018 class linestate(object):
3025 class linestate(object):
3019 def __init__(self, line, linenum, colstart, colend):
3026 def __init__(self, line, linenum, colstart, colend):
3020 self.line = line
3027 self.line = line
3021 self.linenum = linenum
3028 self.linenum = linenum
3022 self.colstart = colstart
3029 self.colstart = colstart
3023 self.colend = colend
3030 self.colend = colend
3024
3031
3025 def __hash__(self):
3032 def __hash__(self):
3026 return hash((self.linenum, self.line))
3033 return hash((self.linenum, self.line))
3027
3034
3028 def __eq__(self, other):
3035 def __eq__(self, other):
3029 return self.line == other.line
3036 return self.line == other.line
3030
3037
3031 matches = {}
3038 matches = {}
3032 copies = {}
3039 copies = {}
3033 def grepbody(fn, rev, body):
3040 def grepbody(fn, rev, body):
3034 matches[rev].setdefault(fn, [])
3041 matches[rev].setdefault(fn, [])
3035 m = matches[rev][fn]
3042 m = matches[rev][fn]
3036 for lnum, cstart, cend, line in matchlines(body):
3043 for lnum, cstart, cend, line in matchlines(body):
3037 s = linestate(line, lnum, cstart, cend)
3044 s = linestate(line, lnum, cstart, cend)
3038 m.append(s)
3045 m.append(s)
3039
3046
3040 def difflinestates(a, b):
3047 def difflinestates(a, b):
3041 sm = difflib.SequenceMatcher(None, a, b)
3048 sm = difflib.SequenceMatcher(None, a, b)
3042 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3049 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3043 if tag == 'insert':
3050 if tag == 'insert':
3044 for i in xrange(blo, bhi):
3051 for i in xrange(blo, bhi):
3045 yield ('+', b[i])
3052 yield ('+', b[i])
3046 elif tag == 'delete':
3053 elif tag == 'delete':
3047 for i in xrange(alo, ahi):
3054 for i in xrange(alo, ahi):
3048 yield ('-', a[i])
3055 yield ('-', a[i])
3049 elif tag == 'replace':
3056 elif tag == 'replace':
3050 for i in xrange(alo, ahi):
3057 for i in xrange(alo, ahi):
3051 yield ('-', a[i])
3058 yield ('-', a[i])
3052 for i in xrange(blo, bhi):
3059 for i in xrange(blo, bhi):
3053 yield ('+', b[i])
3060 yield ('+', b[i])
3054
3061
3055 def display(fn, ctx, pstates, states):
3062 def display(fn, ctx, pstates, states):
3056 rev = ctx.rev()
3063 rev = ctx.rev()
3057 datefunc = ui.quiet and util.shortdate or util.datestr
3064 datefunc = ui.quiet and util.shortdate or util.datestr
3058 found = False
3065 found = False
3059 filerevmatches = {}
3066 filerevmatches = {}
3060 def binary():
3067 def binary():
3061 flog = getfile(fn)
3068 flog = getfile(fn)
3062 return util.binary(flog.read(ctx.filenode(fn)))
3069 return util.binary(flog.read(ctx.filenode(fn)))
3063
3070
3064 if opts.get('all'):
3071 if opts.get('all'):
3065 iter = difflinestates(pstates, states)
3072 iter = difflinestates(pstates, states)
3066 else:
3073 else:
3067 iter = [('', l) for l in states]
3074 iter = [('', l) for l in states]
3068 for change, l in iter:
3075 for change, l in iter:
3069 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3076 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3070 before, match, after = None, None, None
3077 before, match, after = None, None, None
3071
3078
3072 if opts.get('line_number'):
3079 if opts.get('line_number'):
3073 cols.append((str(l.linenum), 'grep.linenumber'))
3080 cols.append((str(l.linenum), 'grep.linenumber'))
3074 if opts.get('all'):
3081 if opts.get('all'):
3075 cols.append((change, 'grep.change'))
3082 cols.append((change, 'grep.change'))
3076 if opts.get('user'):
3083 if opts.get('user'):
3077 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3084 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3078 if opts.get('date'):
3085 if opts.get('date'):
3079 cols.append((datefunc(ctx.date()), 'grep.date'))
3086 cols.append((datefunc(ctx.date()), 'grep.date'))
3080 if opts.get('files_with_matches'):
3087 if opts.get('files_with_matches'):
3081 c = (fn, rev)
3088 c = (fn, rev)
3082 if c in filerevmatches:
3089 if c in filerevmatches:
3083 continue
3090 continue
3084 filerevmatches[c] = 1
3091 filerevmatches[c] = 1
3085 else:
3092 else:
3086 before = l.line[:l.colstart]
3093 before = l.line[:l.colstart]
3087 match = l.line[l.colstart:l.colend]
3094 match = l.line[l.colstart:l.colend]
3088 after = l.line[l.colend:]
3095 after = l.line[l.colend:]
3089 for col, label in cols[:-1]:
3096 for col, label in cols[:-1]:
3090 ui.write(col, label=label)
3097 ui.write(col, label=label)
3091 ui.write(sep, label='grep.sep')
3098 ui.write(sep, label='grep.sep')
3092 ui.write(cols[-1][0], label=cols[-1][1])
3099 ui.write(cols[-1][0], label=cols[-1][1])
3093 if before is not None:
3100 if before is not None:
3094 ui.write(sep, label='grep.sep')
3101 ui.write(sep, label='grep.sep')
3095 if not opts.get('text') and binary():
3102 if not opts.get('text') and binary():
3096 ui.write(" Binary file matches")
3103 ui.write(" Binary file matches")
3097 else:
3104 else:
3098 ui.write(before)
3105 ui.write(before)
3099 ui.write(match, label='grep.match')
3106 ui.write(match, label='grep.match')
3100 ui.write(after)
3107 ui.write(after)
3101 ui.write(eol)
3108 ui.write(eol)
3102 found = True
3109 found = True
3103 return found
3110 return found
3104
3111
3105 skip = {}
3112 skip = {}
3106 revfiles = {}
3113 revfiles = {}
3107 matchfn = scmutil.match(repo[None], pats, opts)
3114 matchfn = scmutil.match(repo[None], pats, opts)
3108 found = False
3115 found = False
3109 follow = opts.get('follow')
3116 follow = opts.get('follow')
3110
3117
3111 def prep(ctx, fns):
3118 def prep(ctx, fns):
3112 rev = ctx.rev()
3119 rev = ctx.rev()
3113 pctx = ctx.p1()
3120 pctx = ctx.p1()
3114 parent = pctx.rev()
3121 parent = pctx.rev()
3115 matches.setdefault(rev, {})
3122 matches.setdefault(rev, {})
3116 matches.setdefault(parent, {})
3123 matches.setdefault(parent, {})
3117 files = revfiles.setdefault(rev, [])
3124 files = revfiles.setdefault(rev, [])
3118 for fn in fns:
3125 for fn in fns:
3119 flog = getfile(fn)
3126 flog = getfile(fn)
3120 try:
3127 try:
3121 fnode = ctx.filenode(fn)
3128 fnode = ctx.filenode(fn)
3122 except error.LookupError:
3129 except error.LookupError:
3123 continue
3130 continue
3124
3131
3125 copied = flog.renamed(fnode)
3132 copied = flog.renamed(fnode)
3126 copy = follow and copied and copied[0]
3133 copy = follow and copied and copied[0]
3127 if copy:
3134 if copy:
3128 copies.setdefault(rev, {})[fn] = copy
3135 copies.setdefault(rev, {})[fn] = copy
3129 if fn in skip:
3136 if fn in skip:
3130 if copy:
3137 if copy:
3131 skip[copy] = True
3138 skip[copy] = True
3132 continue
3139 continue
3133 files.append(fn)
3140 files.append(fn)
3134
3141
3135 if fn not in matches[rev]:
3142 if fn not in matches[rev]:
3136 grepbody(fn, rev, flog.read(fnode))
3143 grepbody(fn, rev, flog.read(fnode))
3137
3144
3138 pfn = copy or fn
3145 pfn = copy or fn
3139 if pfn not in matches[parent]:
3146 if pfn not in matches[parent]:
3140 try:
3147 try:
3141 fnode = pctx.filenode(pfn)
3148 fnode = pctx.filenode(pfn)
3142 grepbody(pfn, parent, flog.read(fnode))
3149 grepbody(pfn, parent, flog.read(fnode))
3143 except error.LookupError:
3150 except error.LookupError:
3144 pass
3151 pass
3145
3152
3146 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3153 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3147 rev = ctx.rev()
3154 rev = ctx.rev()
3148 parent = ctx.p1().rev()
3155 parent = ctx.p1().rev()
3149 for fn in sorted(revfiles.get(rev, [])):
3156 for fn in sorted(revfiles.get(rev, [])):
3150 states = matches[rev][fn]
3157 states = matches[rev][fn]
3151 copy = copies.get(rev, {}).get(fn)
3158 copy = copies.get(rev, {}).get(fn)
3152 if fn in skip:
3159 if fn in skip:
3153 if copy:
3160 if copy:
3154 skip[copy] = True
3161 skip[copy] = True
3155 continue
3162 continue
3156 pstates = matches.get(parent, {}).get(copy or fn, [])
3163 pstates = matches.get(parent, {}).get(copy or fn, [])
3157 if pstates or states:
3164 if pstates or states:
3158 r = display(fn, ctx, pstates, states)
3165 r = display(fn, ctx, pstates, states)
3159 found = found or r
3166 found = found or r
3160 if r and not opts.get('all'):
3167 if r and not opts.get('all'):
3161 skip[fn] = True
3168 skip[fn] = True
3162 if copy:
3169 if copy:
3163 skip[copy] = True
3170 skip[copy] = True
3164 del matches[rev]
3171 del matches[rev]
3165 del revfiles[rev]
3172 del revfiles[rev]
3166
3173
3167 return not found
3174 return not found
3168
3175
3169 @command('heads',
3176 @command('heads',
3170 [('r', 'rev', '',
3177 [('r', 'rev', '',
3171 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3178 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3172 ('t', 'topo', False, _('show topological heads only')),
3179 ('t', 'topo', False, _('show topological heads only')),
3173 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3180 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3174 ('c', 'closed', False, _('show normal and closed branch heads')),
3181 ('c', 'closed', False, _('show normal and closed branch heads')),
3175 ] + templateopts,
3182 ] + templateopts,
3176 _('[-ct] [-r STARTREV] [REV]...'))
3183 _('[-ct] [-r STARTREV] [REV]...'))
3177 def heads(ui, repo, *branchrevs, **opts):
3184 def heads(ui, repo, *branchrevs, **opts):
3178 """show current repository heads or show branch heads
3185 """show current repository heads or show branch heads
3179
3186
3180 With no arguments, show all repository branch heads.
3187 With no arguments, show all repository branch heads.
3181
3188
3182 Repository "heads" are changesets with no child changesets. They are
3189 Repository "heads" are changesets with no child changesets. They are
3183 where development generally takes place and are the usual targets
3190 where development generally takes place and are the usual targets
3184 for update and merge operations. Branch heads are changesets that have
3191 for update and merge operations. Branch heads are changesets that have
3185 no child changeset on the same branch.
3192 no child changeset on the same branch.
3186
3193
3187 If one or more REVs are given, only branch heads on the branches
3194 If one or more REVs are given, only branch heads on the branches
3188 associated with the specified changesets are shown. This means
3195 associated with the specified changesets are shown. This means
3189 that you can use :hg:`heads foo` to see the heads on a branch
3196 that you can use :hg:`heads foo` to see the heads on a branch
3190 named ``foo``.
3197 named ``foo``.
3191
3198
3192 If -c/--closed is specified, also show branch heads marked closed
3199 If -c/--closed is specified, also show branch heads marked closed
3193 (see :hg:`commit --close-branch`).
3200 (see :hg:`commit --close-branch`).
3194
3201
3195 If STARTREV is specified, only those heads that are descendants of
3202 If STARTREV is specified, only those heads that are descendants of
3196 STARTREV will be displayed.
3203 STARTREV will be displayed.
3197
3204
3198 If -t/--topo is specified, named branch mechanics will be ignored and only
3205 If -t/--topo is specified, named branch mechanics will be ignored and only
3199 changesets without children will be shown.
3206 changesets without children will be shown.
3200
3207
3201 Returns 0 if matching heads are found, 1 if not.
3208 Returns 0 if matching heads are found, 1 if not.
3202 """
3209 """
3203
3210
3204 start = None
3211 start = None
3205 if 'rev' in opts:
3212 if 'rev' in opts:
3206 start = scmutil.revsingle(repo, opts['rev'], None).node()
3213 start = scmutil.revsingle(repo, opts['rev'], None).node()
3207
3214
3208 if opts.get('topo'):
3215 if opts.get('topo'):
3209 heads = [repo[h] for h in repo.heads(start)]
3216 heads = [repo[h] for h in repo.heads(start)]
3210 else:
3217 else:
3211 heads = []
3218 heads = []
3212 for branch in repo.branchmap():
3219 for branch in repo.branchmap():
3213 heads += repo.branchheads(branch, start, opts.get('closed'))
3220 heads += repo.branchheads(branch, start, opts.get('closed'))
3214 heads = [repo[h] for h in heads]
3221 heads = [repo[h] for h in heads]
3215
3222
3216 if branchrevs:
3223 if branchrevs:
3217 branches = set(repo[br].branch() for br in branchrevs)
3224 branches = set(repo[br].branch() for br in branchrevs)
3218 heads = [h for h in heads if h.branch() in branches]
3225 heads = [h for h in heads if h.branch() in branches]
3219
3226
3220 if opts.get('active') and branchrevs:
3227 if opts.get('active') and branchrevs:
3221 dagheads = repo.heads(start)
3228 dagheads = repo.heads(start)
3222 heads = [h for h in heads if h.node() in dagheads]
3229 heads = [h for h in heads if h.node() in dagheads]
3223
3230
3224 if branchrevs:
3231 if branchrevs:
3225 haveheads = set(h.branch() for h in heads)
3232 haveheads = set(h.branch() for h in heads)
3226 if branches - haveheads:
3233 if branches - haveheads:
3227 headless = ', '.join(b for b in branches - haveheads)
3234 headless = ', '.join(b for b in branches - haveheads)
3228 msg = _('no open branch heads found on branches %s')
3235 msg = _('no open branch heads found on branches %s')
3229 if opts.get('rev'):
3236 if opts.get('rev'):
3230 msg += _(' (started at %s)') % opts['rev']
3237 msg += _(' (started at %s)') % opts['rev']
3231 ui.warn((msg + '\n') % headless)
3238 ui.warn((msg + '\n') % headless)
3232
3239
3233 if not heads:
3240 if not heads:
3234 return 1
3241 return 1
3235
3242
3236 heads = sorted(heads, key=lambda x: -x.rev())
3243 heads = sorted(heads, key=lambda x: -x.rev())
3237 displayer = cmdutil.show_changeset(ui, repo, opts)
3244 displayer = cmdutil.show_changeset(ui, repo, opts)
3238 for ctx in heads:
3245 for ctx in heads:
3239 displayer.show(ctx)
3246 displayer.show(ctx)
3240 displayer.close()
3247 displayer.close()
3241
3248
3242 @command('help',
3249 @command('help',
3243 [('e', 'extension', None, _('show only help for extensions')),
3250 [('e', 'extension', None, _('show only help for extensions')),
3244 ('c', 'command', None, _('show only help for commands')),
3251 ('c', 'command', None, _('show only help for commands')),
3245 ('k', 'keyword', '', _('show topics matching keyword')),
3252 ('k', 'keyword', '', _('show topics matching keyword')),
3246 ],
3253 ],
3247 _('[-ec] [TOPIC]'))
3254 _('[-ec] [TOPIC]'))
3248 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3255 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3249 """show help for a given topic or a help overview
3256 """show help for a given topic or a help overview
3250
3257
3251 With no arguments, print a list of commands with short help messages.
3258 With no arguments, print a list of commands with short help messages.
3252
3259
3253 Given a topic, extension, or command name, print help for that
3260 Given a topic, extension, or command name, print help for that
3254 topic.
3261 topic.
3255
3262
3256 Returns 0 if successful.
3263 Returns 0 if successful.
3257 """
3264 """
3258
3265
3259 textwidth = min(ui.termwidth(), 80) - 2
3266 textwidth = min(ui.termwidth(), 80) - 2
3260
3267
3261 def helpcmd(name):
3268 def helpcmd(name):
3262 try:
3269 try:
3263 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3270 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3264 except error.AmbiguousCommand, inst:
3271 except error.AmbiguousCommand, inst:
3265 # py3k fix: except vars can't be used outside the scope of the
3272 # py3k fix: except vars can't be used outside the scope of the
3266 # except block, nor can be used inside a lambda. python issue4617
3273 # except block, nor can be used inside a lambda. python issue4617
3267 prefix = inst.args[0]
3274 prefix = inst.args[0]
3268 select = lambda c: c.lstrip('^').startswith(prefix)
3275 select = lambda c: c.lstrip('^').startswith(prefix)
3269 rst = helplist(select)
3276 rst = helplist(select)
3270 return rst
3277 return rst
3271
3278
3272 rst = []
3279 rst = []
3273
3280
3274 # check if it's an invalid alias and display its error if it is
3281 # check if it's an invalid alias and display its error if it is
3275 if getattr(entry[0], 'badalias', False):
3282 if getattr(entry[0], 'badalias', False):
3276 if not unknowncmd:
3283 if not unknowncmd:
3277 ui.pushbuffer()
3284 ui.pushbuffer()
3278 entry[0](ui)
3285 entry[0](ui)
3279 rst.append(ui.popbuffer())
3286 rst.append(ui.popbuffer())
3280 return rst
3287 return rst
3281
3288
3282 # synopsis
3289 # synopsis
3283 if len(entry) > 2:
3290 if len(entry) > 2:
3284 if entry[2].startswith('hg'):
3291 if entry[2].startswith('hg'):
3285 rst.append("%s\n" % entry[2])
3292 rst.append("%s\n" % entry[2])
3286 else:
3293 else:
3287 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3294 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3288 else:
3295 else:
3289 rst.append('hg %s\n' % aliases[0])
3296 rst.append('hg %s\n' % aliases[0])
3290 # aliases
3297 # aliases
3291 if full and not ui.quiet and len(aliases) > 1:
3298 if full and not ui.quiet and len(aliases) > 1:
3292 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3299 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3293 rst.append('\n')
3300 rst.append('\n')
3294
3301
3295 # description
3302 # description
3296 doc = gettext(entry[0].__doc__)
3303 doc = gettext(entry[0].__doc__)
3297 if not doc:
3304 if not doc:
3298 doc = _("(no help text available)")
3305 doc = _("(no help text available)")
3299 if util.safehasattr(entry[0], 'definition'): # aliased command
3306 if util.safehasattr(entry[0], 'definition'): # aliased command
3300 if entry[0].definition.startswith('!'): # shell alias
3307 if entry[0].definition.startswith('!'): # shell alias
3301 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3308 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3302 else:
3309 else:
3303 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3310 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3304 doc = doc.splitlines(True)
3311 doc = doc.splitlines(True)
3305 if ui.quiet or not full:
3312 if ui.quiet or not full:
3306 rst.append(doc[0])
3313 rst.append(doc[0])
3307 else:
3314 else:
3308 rst.extend(doc)
3315 rst.extend(doc)
3309 rst.append('\n')
3316 rst.append('\n')
3310
3317
3311 # check if this command shadows a non-trivial (multi-line)
3318 # check if this command shadows a non-trivial (multi-line)
3312 # extension help text
3319 # extension help text
3313 try:
3320 try:
3314 mod = extensions.find(name)
3321 mod = extensions.find(name)
3315 doc = gettext(mod.__doc__) or ''
3322 doc = gettext(mod.__doc__) or ''
3316 if '\n' in doc.strip():
3323 if '\n' in doc.strip():
3317 msg = _('use "hg help -e %s" to show help for '
3324 msg = _('use "hg help -e %s" to show help for '
3318 'the %s extension') % (name, name)
3325 'the %s extension') % (name, name)
3319 rst.append('\n%s\n' % msg)
3326 rst.append('\n%s\n' % msg)
3320 except KeyError:
3327 except KeyError:
3321 pass
3328 pass
3322
3329
3323 # options
3330 # options
3324 if not ui.quiet and entry[1]:
3331 if not ui.quiet and entry[1]:
3325 rst.append('\n%s\n\n' % _("options:"))
3332 rst.append('\n%s\n\n' % _("options:"))
3326 rst.append(help.optrst(entry[1], ui.verbose))
3333 rst.append(help.optrst(entry[1], ui.verbose))
3327
3334
3328 if ui.verbose:
3335 if ui.verbose:
3329 rst.append('\n%s\n\n' % _("global options:"))
3336 rst.append('\n%s\n\n' % _("global options:"))
3330 rst.append(help.optrst(globalopts, ui.verbose))
3337 rst.append(help.optrst(globalopts, ui.verbose))
3331
3338
3332 if not ui.verbose:
3339 if not ui.verbose:
3333 if not full:
3340 if not full:
3334 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3341 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3335 % name)
3342 % name)
3336 elif not ui.quiet:
3343 elif not ui.quiet:
3337 omitted = _('use "hg -v help %s" to show more complete'
3344 omitted = _('use "hg -v help %s" to show more complete'
3338 ' help and the global options') % name
3345 ' help and the global options') % name
3339 notomitted = _('use "hg -v help %s" to show'
3346 notomitted = _('use "hg -v help %s" to show'
3340 ' the global options') % name
3347 ' the global options') % name
3341 help.indicateomitted(rst, omitted, notomitted)
3348 help.indicateomitted(rst, omitted, notomitted)
3342
3349
3343 return rst
3350 return rst
3344
3351
3345
3352
3346 def helplist(select=None):
3353 def helplist(select=None):
3347 # list of commands
3354 # list of commands
3348 if name == "shortlist":
3355 if name == "shortlist":
3349 header = _('basic commands:\n\n')
3356 header = _('basic commands:\n\n')
3350 else:
3357 else:
3351 header = _('list of commands:\n\n')
3358 header = _('list of commands:\n\n')
3352
3359
3353 h = {}
3360 h = {}
3354 cmds = {}
3361 cmds = {}
3355 for c, e in table.iteritems():
3362 for c, e in table.iteritems():
3356 f = c.split("|", 1)[0]
3363 f = c.split("|", 1)[0]
3357 if select and not select(f):
3364 if select and not select(f):
3358 continue
3365 continue
3359 if (not select and name != 'shortlist' and
3366 if (not select and name != 'shortlist' and
3360 e[0].__module__ != __name__):
3367 e[0].__module__ != __name__):
3361 continue
3368 continue
3362 if name == "shortlist" and not f.startswith("^"):
3369 if name == "shortlist" and not f.startswith("^"):
3363 continue
3370 continue
3364 f = f.lstrip("^")
3371 f = f.lstrip("^")
3365 if not ui.debugflag and f.startswith("debug"):
3372 if not ui.debugflag and f.startswith("debug"):
3366 continue
3373 continue
3367 doc = e[0].__doc__
3374 doc = e[0].__doc__
3368 if doc and 'DEPRECATED' in doc and not ui.verbose:
3375 if doc and 'DEPRECATED' in doc and not ui.verbose:
3369 continue
3376 continue
3370 doc = gettext(doc)
3377 doc = gettext(doc)
3371 if not doc:
3378 if not doc:
3372 doc = _("(no help text available)")
3379 doc = _("(no help text available)")
3373 h[f] = doc.splitlines()[0].rstrip()
3380 h[f] = doc.splitlines()[0].rstrip()
3374 cmds[f] = c.lstrip("^")
3381 cmds[f] = c.lstrip("^")
3375
3382
3376 rst = []
3383 rst = []
3377 if not h:
3384 if not h:
3378 if not ui.quiet:
3385 if not ui.quiet:
3379 rst.append(_('no commands defined\n'))
3386 rst.append(_('no commands defined\n'))
3380 return rst
3387 return rst
3381
3388
3382 if not ui.quiet:
3389 if not ui.quiet:
3383 rst.append(header)
3390 rst.append(header)
3384 fns = sorted(h)
3391 fns = sorted(h)
3385 for f in fns:
3392 for f in fns:
3386 if ui.verbose:
3393 if ui.verbose:
3387 commands = cmds[f].replace("|",", ")
3394 commands = cmds[f].replace("|",", ")
3388 rst.append(" :%s: %s\n" % (commands, h[f]))
3395 rst.append(" :%s: %s\n" % (commands, h[f]))
3389 else:
3396 else:
3390 rst.append(' :%s: %s\n' % (f, h[f]))
3397 rst.append(' :%s: %s\n' % (f, h[f]))
3391
3398
3392 if not name:
3399 if not name:
3393 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3400 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3394 if exts:
3401 if exts:
3395 rst.append('\n')
3402 rst.append('\n')
3396 rst.extend(exts)
3403 rst.extend(exts)
3397
3404
3398 rst.append(_("\nadditional help topics:\n\n"))
3405 rst.append(_("\nadditional help topics:\n\n"))
3399 topics = []
3406 topics = []
3400 for names, header, doc in help.helptable:
3407 for names, header, doc in help.helptable:
3401 topics.append((names[0], header))
3408 topics.append((names[0], header))
3402 for t, desc in topics:
3409 for t, desc in topics:
3403 rst.append(" :%s: %s\n" % (t, desc))
3410 rst.append(" :%s: %s\n" % (t, desc))
3404
3411
3405 optlist = []
3412 optlist = []
3406 if not ui.quiet:
3413 if not ui.quiet:
3407 if ui.verbose:
3414 if ui.verbose:
3408 optlist.append((_("global options:"), globalopts))
3415 optlist.append((_("global options:"), globalopts))
3409 if name == 'shortlist':
3416 if name == 'shortlist':
3410 optlist.append((_('use "hg help" for the full list '
3417 optlist.append((_('use "hg help" for the full list '
3411 'of commands'), ()))
3418 'of commands'), ()))
3412 else:
3419 else:
3413 if name == 'shortlist':
3420 if name == 'shortlist':
3414 msg = _('use "hg help" for the full list of commands '
3421 msg = _('use "hg help" for the full list of commands '
3415 'or "hg -v" for details')
3422 'or "hg -v" for details')
3416 elif name and not full:
3423 elif name and not full:
3417 msg = _('use "hg help %s" to show the full help '
3424 msg = _('use "hg help %s" to show the full help '
3418 'text') % name
3425 'text') % name
3419 else:
3426 else:
3420 msg = _('use "hg -v help%s" to show builtin aliases and '
3427 msg = _('use "hg -v help%s" to show builtin aliases and '
3421 'global options') % (name and " " + name or "")
3428 'global options') % (name and " " + name or "")
3422 optlist.append((msg, ()))
3429 optlist.append((msg, ()))
3423
3430
3424 if optlist:
3431 if optlist:
3425 for title, options in optlist:
3432 for title, options in optlist:
3426 rst.append('\n%s\n' % title)
3433 rst.append('\n%s\n' % title)
3427 if options:
3434 if options:
3428 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3435 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3429 return rst
3436 return rst
3430
3437
3431 def helptopic(name):
3438 def helptopic(name):
3432 for names, header, doc in help.helptable:
3439 for names, header, doc in help.helptable:
3433 if name in names:
3440 if name in names:
3434 break
3441 break
3435 else:
3442 else:
3436 raise error.UnknownCommand(name)
3443 raise error.UnknownCommand(name)
3437
3444
3438 rst = ["%s\n\n" % header]
3445 rst = ["%s\n\n" % header]
3439 # description
3446 # description
3440 if not doc:
3447 if not doc:
3441 rst.append(" %s\n" % _("(no help text available)"))
3448 rst.append(" %s\n" % _("(no help text available)"))
3442 if util.safehasattr(doc, '__call__'):
3449 if util.safehasattr(doc, '__call__'):
3443 rst += [" %s\n" % l for l in doc().splitlines()]
3450 rst += [" %s\n" % l for l in doc().splitlines()]
3444
3451
3445 if not ui.verbose:
3452 if not ui.verbose:
3446 omitted = (_('use "hg help -v %s" to show more complete help') %
3453 omitted = (_('use "hg help -v %s" to show more complete help') %
3447 name)
3454 name)
3448 help.indicateomitted(rst, omitted)
3455 help.indicateomitted(rst, omitted)
3449
3456
3450 try:
3457 try:
3451 cmdutil.findcmd(name, table)
3458 cmdutil.findcmd(name, table)
3452 rst.append(_('\nuse "hg help -c %s" to see help for '
3459 rst.append(_('\nuse "hg help -c %s" to see help for '
3453 'the %s command\n') % (name, name))
3460 'the %s command\n') % (name, name))
3454 except error.UnknownCommand:
3461 except error.UnknownCommand:
3455 pass
3462 pass
3456 return rst
3463 return rst
3457
3464
3458 def helpext(name):
3465 def helpext(name):
3459 try:
3466 try:
3460 mod = extensions.find(name)
3467 mod = extensions.find(name)
3461 doc = gettext(mod.__doc__) or _('no help text available')
3468 doc = gettext(mod.__doc__) or _('no help text available')
3462 except KeyError:
3469 except KeyError:
3463 mod = None
3470 mod = None
3464 doc = extensions.disabledext(name)
3471 doc = extensions.disabledext(name)
3465 if not doc:
3472 if not doc:
3466 raise error.UnknownCommand(name)
3473 raise error.UnknownCommand(name)
3467
3474
3468 if '\n' not in doc:
3475 if '\n' not in doc:
3469 head, tail = doc, ""
3476 head, tail = doc, ""
3470 else:
3477 else:
3471 head, tail = doc.split('\n', 1)
3478 head, tail = doc.split('\n', 1)
3472 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3479 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3473 if tail:
3480 if tail:
3474 rst.extend(tail.splitlines(True))
3481 rst.extend(tail.splitlines(True))
3475 rst.append('\n')
3482 rst.append('\n')
3476
3483
3477 if not ui.verbose:
3484 if not ui.verbose:
3478 omitted = (_('use "hg help -v %s" to show more complete help') %
3485 omitted = (_('use "hg help -v %s" to show more complete help') %
3479 name)
3486 name)
3480 help.indicateomitted(rst, omitted)
3487 help.indicateomitted(rst, omitted)
3481
3488
3482 if mod:
3489 if mod:
3483 try:
3490 try:
3484 ct = mod.cmdtable
3491 ct = mod.cmdtable
3485 except AttributeError:
3492 except AttributeError:
3486 ct = {}
3493 ct = {}
3487 modcmds = set([c.split('|', 1)[0] for c in ct])
3494 modcmds = set([c.split('|', 1)[0] for c in ct])
3488 rst.extend(helplist(modcmds.__contains__))
3495 rst.extend(helplist(modcmds.__contains__))
3489 else:
3496 else:
3490 rst.append(_('use "hg help extensions" for information on enabling '
3497 rst.append(_('use "hg help extensions" for information on enabling '
3491 'extensions\n'))
3498 'extensions\n'))
3492 return rst
3499 return rst
3493
3500
3494 def helpextcmd(name):
3501 def helpextcmd(name):
3495 cmd, ext, mod = extensions.disabledcmd(ui, name,
3502 cmd, ext, mod = extensions.disabledcmd(ui, name,
3496 ui.configbool('ui', 'strict'))
3503 ui.configbool('ui', 'strict'))
3497 doc = gettext(mod.__doc__).splitlines()[0]
3504 doc = gettext(mod.__doc__).splitlines()[0]
3498
3505
3499 rst = help.listexts(_("'%s' is provided by the following "
3506 rst = help.listexts(_("'%s' is provided by the following "
3500 "extension:") % cmd, {ext: doc}, indent=4)
3507 "extension:") % cmd, {ext: doc}, indent=4)
3501 rst.append('\n')
3508 rst.append('\n')
3502 rst.append(_('use "hg help extensions" for information on enabling '
3509 rst.append(_('use "hg help extensions" for information on enabling '
3503 'extensions\n'))
3510 'extensions\n'))
3504 return rst
3511 return rst
3505
3512
3506
3513
3507 rst = []
3514 rst = []
3508 kw = opts.get('keyword')
3515 kw = opts.get('keyword')
3509 if kw:
3516 if kw:
3510 matches = help.topicmatch(kw)
3517 matches = help.topicmatch(kw)
3511 for t, title in (('topics', _('Topics')),
3518 for t, title in (('topics', _('Topics')),
3512 ('commands', _('Commands')),
3519 ('commands', _('Commands')),
3513 ('extensions', _('Extensions')),
3520 ('extensions', _('Extensions')),
3514 ('extensioncommands', _('Extension Commands'))):
3521 ('extensioncommands', _('Extension Commands'))):
3515 if matches[t]:
3522 if matches[t]:
3516 rst.append('%s:\n\n' % title)
3523 rst.append('%s:\n\n' % title)
3517 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3524 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3518 rst.append('\n')
3525 rst.append('\n')
3519 elif name and name != 'shortlist':
3526 elif name and name != 'shortlist':
3520 i = None
3527 i = None
3521 if unknowncmd:
3528 if unknowncmd:
3522 queries = (helpextcmd,)
3529 queries = (helpextcmd,)
3523 elif opts.get('extension'):
3530 elif opts.get('extension'):
3524 queries = (helpext,)
3531 queries = (helpext,)
3525 elif opts.get('command'):
3532 elif opts.get('command'):
3526 queries = (helpcmd,)
3533 queries = (helpcmd,)
3527 else:
3534 else:
3528 queries = (helptopic, helpcmd, helpext, helpextcmd)
3535 queries = (helptopic, helpcmd, helpext, helpextcmd)
3529 for f in queries:
3536 for f in queries:
3530 try:
3537 try:
3531 rst = f(name)
3538 rst = f(name)
3532 i = None
3539 i = None
3533 break
3540 break
3534 except error.UnknownCommand, inst:
3541 except error.UnknownCommand, inst:
3535 i = inst
3542 i = inst
3536 if i:
3543 if i:
3537 raise i
3544 raise i
3538 else:
3545 else:
3539 # program name
3546 # program name
3540 if not ui.quiet:
3547 if not ui.quiet:
3541 rst = [_("Mercurial Distributed SCM\n"), '\n']
3548 rst = [_("Mercurial Distributed SCM\n"), '\n']
3542 rst.extend(helplist())
3549 rst.extend(helplist())
3543
3550
3544 keep = ui.verbose and ['verbose'] or []
3551 keep = ui.verbose and ['verbose'] or []
3545 text = ''.join(rst)
3552 text = ''.join(rst)
3546 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3553 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3547 if 'verbose' in pruned:
3554 if 'verbose' in pruned:
3548 keep.append('omitted')
3555 keep.append('omitted')
3549 else:
3556 else:
3550 keep.append('notomitted')
3557 keep.append('notomitted')
3551 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3558 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3552 ui.write(formatted)
3559 ui.write(formatted)
3553
3560
3554
3561
3555 @command('identify|id',
3562 @command('identify|id',
3556 [('r', 'rev', '',
3563 [('r', 'rev', '',
3557 _('identify the specified revision'), _('REV')),
3564 _('identify the specified revision'), _('REV')),
3558 ('n', 'num', None, _('show local revision number')),
3565 ('n', 'num', None, _('show local revision number')),
3559 ('i', 'id', None, _('show global revision id')),
3566 ('i', 'id', None, _('show global revision id')),
3560 ('b', 'branch', None, _('show branch')),
3567 ('b', 'branch', None, _('show branch')),
3561 ('t', 'tags', None, _('show tags')),
3568 ('t', 'tags', None, _('show tags')),
3562 ('B', 'bookmarks', None, _('show bookmarks')),
3569 ('B', 'bookmarks', None, _('show bookmarks')),
3563 ] + remoteopts,
3570 ] + remoteopts,
3564 _('[-nibtB] [-r REV] [SOURCE]'))
3571 _('[-nibtB] [-r REV] [SOURCE]'))
3565 def identify(ui, repo, source=None, rev=None,
3572 def identify(ui, repo, source=None, rev=None,
3566 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3573 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3567 """identify the working copy or specified revision
3574 """identify the working copy or specified revision
3568
3575
3569 Print a summary identifying the repository state at REV using one or
3576 Print a summary identifying the repository state at REV using one or
3570 two parent hash identifiers, followed by a "+" if the working
3577 two parent hash identifiers, followed by a "+" if the working
3571 directory has uncommitted changes, the branch name (if not default),
3578 directory has uncommitted changes, the branch name (if not default),
3572 a list of tags, and a list of bookmarks.
3579 a list of tags, and a list of bookmarks.
3573
3580
3574 When REV is not given, print a summary of the current state of the
3581 When REV is not given, print a summary of the current state of the
3575 repository.
3582 repository.
3576
3583
3577 Specifying a path to a repository root or Mercurial bundle will
3584 Specifying a path to a repository root or Mercurial bundle will
3578 cause lookup to operate on that repository/bundle.
3585 cause lookup to operate on that repository/bundle.
3579
3586
3580 .. container:: verbose
3587 .. container:: verbose
3581
3588
3582 Examples:
3589 Examples:
3583
3590
3584 - generate a build identifier for the working directory::
3591 - generate a build identifier for the working directory::
3585
3592
3586 hg id --id > build-id.dat
3593 hg id --id > build-id.dat
3587
3594
3588 - find the revision corresponding to a tag::
3595 - find the revision corresponding to a tag::
3589
3596
3590 hg id -n -r 1.3
3597 hg id -n -r 1.3
3591
3598
3592 - check the most recent revision of a remote repository::
3599 - check the most recent revision of a remote repository::
3593
3600
3594 hg id -r tip http://selenic.com/hg/
3601 hg id -r tip http://selenic.com/hg/
3595
3602
3596 Returns 0 if successful.
3603 Returns 0 if successful.
3597 """
3604 """
3598
3605
3599 if not repo and not source:
3606 if not repo and not source:
3600 raise util.Abort(_("there is no Mercurial repository here "
3607 raise util.Abort(_("there is no Mercurial repository here "
3601 "(.hg not found)"))
3608 "(.hg not found)"))
3602
3609
3603 hexfunc = ui.debugflag and hex or short
3610 hexfunc = ui.debugflag and hex or short
3604 default = not (num or id or branch or tags or bookmarks)
3611 default = not (num or id or branch or tags or bookmarks)
3605 output = []
3612 output = []
3606 revs = []
3613 revs = []
3607
3614
3608 if source:
3615 if source:
3609 source, branches = hg.parseurl(ui.expandpath(source))
3616 source, branches = hg.parseurl(ui.expandpath(source))
3610 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3617 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3611 repo = peer.local()
3618 repo = peer.local()
3612 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3619 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3613
3620
3614 if not repo:
3621 if not repo:
3615 if num or branch or tags:
3622 if num or branch or tags:
3616 raise util.Abort(
3623 raise util.Abort(
3617 _("can't query remote revision number, branch, or tags"))
3624 _("can't query remote revision number, branch, or tags"))
3618 if not rev and revs:
3625 if not rev and revs:
3619 rev = revs[0]
3626 rev = revs[0]
3620 if not rev:
3627 if not rev:
3621 rev = "tip"
3628 rev = "tip"
3622
3629
3623 remoterev = peer.lookup(rev)
3630 remoterev = peer.lookup(rev)
3624 if default or id:
3631 if default or id:
3625 output = [hexfunc(remoterev)]
3632 output = [hexfunc(remoterev)]
3626
3633
3627 def getbms():
3634 def getbms():
3628 bms = []
3635 bms = []
3629
3636
3630 if 'bookmarks' in peer.listkeys('namespaces'):
3637 if 'bookmarks' in peer.listkeys('namespaces'):
3631 hexremoterev = hex(remoterev)
3638 hexremoterev = hex(remoterev)
3632 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3639 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3633 if bmr == hexremoterev]
3640 if bmr == hexremoterev]
3634
3641
3635 return sorted(bms)
3642 return sorted(bms)
3636
3643
3637 if bookmarks:
3644 if bookmarks:
3638 output.extend(getbms())
3645 output.extend(getbms())
3639 elif default and not ui.quiet:
3646 elif default and not ui.quiet:
3640 # multiple bookmarks for a single parent separated by '/'
3647 # multiple bookmarks for a single parent separated by '/'
3641 bm = '/'.join(getbms())
3648 bm = '/'.join(getbms())
3642 if bm:
3649 if bm:
3643 output.append(bm)
3650 output.append(bm)
3644 else:
3651 else:
3645 if not rev:
3652 if not rev:
3646 ctx = repo[None]
3653 ctx = repo[None]
3647 parents = ctx.parents()
3654 parents = ctx.parents()
3648 changed = ""
3655 changed = ""
3649 if default or id or num:
3656 if default or id or num:
3650 if (util.any(repo.status())
3657 if (util.any(repo.status())
3651 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3658 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3652 changed = '+'
3659 changed = '+'
3653 if default or id:
3660 if default or id:
3654 output = ["%s%s" %
3661 output = ["%s%s" %
3655 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3662 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3656 if num:
3663 if num:
3657 output.append("%s%s" %
3664 output.append("%s%s" %
3658 ('+'.join([str(p.rev()) for p in parents]), changed))
3665 ('+'.join([str(p.rev()) for p in parents]), changed))
3659 else:
3666 else:
3660 ctx = scmutil.revsingle(repo, rev)
3667 ctx = scmutil.revsingle(repo, rev)
3661 if default or id:
3668 if default or id:
3662 output = [hexfunc(ctx.node())]
3669 output = [hexfunc(ctx.node())]
3663 if num:
3670 if num:
3664 output.append(str(ctx.rev()))
3671 output.append(str(ctx.rev()))
3665
3672
3666 if default and not ui.quiet:
3673 if default and not ui.quiet:
3667 b = ctx.branch()
3674 b = ctx.branch()
3668 if b != 'default':
3675 if b != 'default':
3669 output.append("(%s)" % b)
3676 output.append("(%s)" % b)
3670
3677
3671 # multiple tags for a single parent separated by '/'
3678 # multiple tags for a single parent separated by '/'
3672 t = '/'.join(ctx.tags())
3679 t = '/'.join(ctx.tags())
3673 if t:
3680 if t:
3674 output.append(t)
3681 output.append(t)
3675
3682
3676 # multiple bookmarks for a single parent separated by '/'
3683 # multiple bookmarks for a single parent separated by '/'
3677 bm = '/'.join(ctx.bookmarks())
3684 bm = '/'.join(ctx.bookmarks())
3678 if bm:
3685 if bm:
3679 output.append(bm)
3686 output.append(bm)
3680 else:
3687 else:
3681 if branch:
3688 if branch:
3682 output.append(ctx.branch())
3689 output.append(ctx.branch())
3683
3690
3684 if tags:
3691 if tags:
3685 output.extend(ctx.tags())
3692 output.extend(ctx.tags())
3686
3693
3687 if bookmarks:
3694 if bookmarks:
3688 output.extend(ctx.bookmarks())
3695 output.extend(ctx.bookmarks())
3689
3696
3690 ui.write("%s\n" % ' '.join(output))
3697 ui.write("%s\n" % ' '.join(output))
3691
3698
3692 @command('import|patch',
3699 @command('import|patch',
3693 [('p', 'strip', 1,
3700 [('p', 'strip', 1,
3694 _('directory strip option for patch. This has the same '
3701 _('directory strip option for patch. This has the same '
3695 'meaning as the corresponding patch option'), _('NUM')),
3702 'meaning as the corresponding patch option'), _('NUM')),
3696 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3703 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3697 ('e', 'edit', False, _('invoke editor on commit messages')),
3704 ('e', 'edit', False, _('invoke editor on commit messages')),
3698 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3705 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3699 ('', 'no-commit', None,
3706 ('', 'no-commit', None,
3700 _("don't commit, just update the working directory")),
3707 _("don't commit, just update the working directory")),
3701 ('', 'bypass', None,
3708 ('', 'bypass', None,
3702 _("apply patch without touching the working directory")),
3709 _("apply patch without touching the working directory")),
3703 ('', 'exact', None,
3710 ('', 'exact', None,
3704 _('apply patch to the nodes from which it was generated')),
3711 _('apply patch to the nodes from which it was generated')),
3705 ('', 'import-branch', None,
3712 ('', 'import-branch', None,
3706 _('use any branch information in patch (implied by --exact)'))] +
3713 _('use any branch information in patch (implied by --exact)'))] +
3707 commitopts + commitopts2 + similarityopts,
3714 commitopts + commitopts2 + similarityopts,
3708 _('[OPTION]... PATCH...'))
3715 _('[OPTION]... PATCH...'))
3709 def import_(ui, repo, patch1=None, *patches, **opts):
3716 def import_(ui, repo, patch1=None, *patches, **opts):
3710 """import an ordered set of patches
3717 """import an ordered set of patches
3711
3718
3712 Import a list of patches and commit them individually (unless
3719 Import a list of patches and commit them individually (unless
3713 --no-commit is specified).
3720 --no-commit is specified).
3714
3721
3715 If there are outstanding changes in the working directory, import
3722 If there are outstanding changes in the working directory, import
3716 will abort unless given the -f/--force flag.
3723 will abort unless given the -f/--force flag.
3717
3724
3718 You can import a patch straight from a mail message. Even patches
3725 You can import a patch straight from a mail message. Even patches
3719 as attachments work (to use the body part, it must have type
3726 as attachments work (to use the body part, it must have type
3720 text/plain or text/x-patch). From and Subject headers of email
3727 text/plain or text/x-patch). From and Subject headers of email
3721 message are used as default committer and commit message. All
3728 message are used as default committer and commit message. All
3722 text/plain body parts before first diff are added to commit
3729 text/plain body parts before first diff are added to commit
3723 message.
3730 message.
3724
3731
3725 If the imported patch was generated by :hg:`export`, user and
3732 If the imported patch was generated by :hg:`export`, user and
3726 description from patch override values from message headers and
3733 description from patch override values from message headers and
3727 body. Values given on command line with -m/--message and -u/--user
3734 body. Values given on command line with -m/--message and -u/--user
3728 override these.
3735 override these.
3729
3736
3730 If --exact is specified, import will set the working directory to
3737 If --exact is specified, import will set the working directory to
3731 the parent of each patch before applying it, and will abort if the
3738 the parent of each patch before applying it, and will abort if the
3732 resulting changeset has a different ID than the one recorded in
3739 resulting changeset has a different ID than the one recorded in
3733 the patch. This may happen due to character set problems or other
3740 the patch. This may happen due to character set problems or other
3734 deficiencies in the text patch format.
3741 deficiencies in the text patch format.
3735
3742
3736 Use --bypass to apply and commit patches directly to the
3743 Use --bypass to apply and commit patches directly to the
3737 repository, not touching the working directory. Without --exact,
3744 repository, not touching the working directory. Without --exact,
3738 patches will be applied on top of the working directory parent
3745 patches will be applied on top of the working directory parent
3739 revision.
3746 revision.
3740
3747
3741 With -s/--similarity, hg will attempt to discover renames and
3748 With -s/--similarity, hg will attempt to discover renames and
3742 copies in the patch in the same way as :hg:`addremove`.
3749 copies in the patch in the same way as :hg:`addremove`.
3743
3750
3744 To read a patch from standard input, use "-" as the patch name. If
3751 To read a patch from standard input, use "-" as the patch name. If
3745 a URL is specified, the patch will be downloaded from it.
3752 a URL is specified, the patch will be downloaded from it.
3746 See :hg:`help dates` for a list of formats valid for -d/--date.
3753 See :hg:`help dates` for a list of formats valid for -d/--date.
3747
3754
3748 .. container:: verbose
3755 .. container:: verbose
3749
3756
3750 Examples:
3757 Examples:
3751
3758
3752 - import a traditional patch from a website and detect renames::
3759 - import a traditional patch from a website and detect renames::
3753
3760
3754 hg import -s 80 http://example.com/bugfix.patch
3761 hg import -s 80 http://example.com/bugfix.patch
3755
3762
3756 - import a changeset from an hgweb server::
3763 - import a changeset from an hgweb server::
3757
3764
3758 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3765 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3759
3766
3760 - import all the patches in an Unix-style mbox::
3767 - import all the patches in an Unix-style mbox::
3761
3768
3762 hg import incoming-patches.mbox
3769 hg import incoming-patches.mbox
3763
3770
3764 - attempt to exactly restore an exported changeset (not always
3771 - attempt to exactly restore an exported changeset (not always
3765 possible)::
3772 possible)::
3766
3773
3767 hg import --exact proposed-fix.patch
3774 hg import --exact proposed-fix.patch
3768
3775
3769 Returns 0 on success.
3776 Returns 0 on success.
3770 """
3777 """
3771
3778
3772 if not patch1:
3779 if not patch1:
3773 raise util.Abort(_('need at least one patch to import'))
3780 raise util.Abort(_('need at least one patch to import'))
3774
3781
3775 patches = (patch1,) + patches
3782 patches = (patch1,) + patches
3776
3783
3777 date = opts.get('date')
3784 date = opts.get('date')
3778 if date:
3785 if date:
3779 opts['date'] = util.parsedate(date)
3786 opts['date'] = util.parsedate(date)
3780
3787
3781 editor = cmdutil.commiteditor
3788 editor = cmdutil.commiteditor
3782 if opts.get('edit'):
3789 if opts.get('edit'):
3783 editor = cmdutil.commitforceeditor
3790 editor = cmdutil.commitforceeditor
3784
3791
3785 update = not opts.get('bypass')
3792 update = not opts.get('bypass')
3786 if not update and opts.get('no_commit'):
3793 if not update and opts.get('no_commit'):
3787 raise util.Abort(_('cannot use --no-commit with --bypass'))
3794 raise util.Abort(_('cannot use --no-commit with --bypass'))
3788 try:
3795 try:
3789 sim = float(opts.get('similarity') or 0)
3796 sim = float(opts.get('similarity') or 0)
3790 except ValueError:
3797 except ValueError:
3791 raise util.Abort(_('similarity must be a number'))
3798 raise util.Abort(_('similarity must be a number'))
3792 if sim < 0 or sim > 100:
3799 if sim < 0 or sim > 100:
3793 raise util.Abort(_('similarity must be between 0 and 100'))
3800 raise util.Abort(_('similarity must be between 0 and 100'))
3794 if sim and not update:
3801 if sim and not update:
3795 raise util.Abort(_('cannot use --similarity with --bypass'))
3802 raise util.Abort(_('cannot use --similarity with --bypass'))
3796
3803
3797 if (opts.get('exact') or not opts.get('force')) and update:
3804 if (opts.get('exact') or not opts.get('force')) and update:
3798 cmdutil.bailifchanged(repo)
3805 cmdutil.bailifchanged(repo)
3799
3806
3800 base = opts["base"]
3807 base = opts["base"]
3801 strip = opts["strip"]
3808 strip = opts["strip"]
3802 wlock = lock = tr = None
3809 wlock = lock = tr = None
3803 msgs = []
3810 msgs = []
3804
3811
3805 def checkexact(repo, n, nodeid):
3812 def checkexact(repo, n, nodeid):
3806 if opts.get('exact') and hex(n) != nodeid:
3813 if opts.get('exact') and hex(n) != nodeid:
3807 repo.rollback()
3814 repo.rollback()
3808 raise util.Abort(_('patch is damaged or loses information'))
3815 raise util.Abort(_('patch is damaged or loses information'))
3809
3816
3810 def tryone(ui, hunk, parents):
3817 def tryone(ui, hunk, parents):
3811 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3818 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3812 patch.extract(ui, hunk)
3819 patch.extract(ui, hunk)
3813
3820
3814 if not tmpname:
3821 if not tmpname:
3815 return (None, None)
3822 return (None, None)
3816 msg = _('applied to working directory')
3823 msg = _('applied to working directory')
3817
3824
3818 try:
3825 try:
3819 cmdline_message = cmdutil.logmessage(ui, opts)
3826 cmdline_message = cmdutil.logmessage(ui, opts)
3820 if cmdline_message:
3827 if cmdline_message:
3821 # pickup the cmdline msg
3828 # pickup the cmdline msg
3822 message = cmdline_message
3829 message = cmdline_message
3823 elif message:
3830 elif message:
3824 # pickup the patch msg
3831 # pickup the patch msg
3825 message = message.strip()
3832 message = message.strip()
3826 else:
3833 else:
3827 # launch the editor
3834 # launch the editor
3828 message = None
3835 message = None
3829 ui.debug('message:\n%s\n' % message)
3836 ui.debug('message:\n%s\n' % message)
3830
3837
3831 if len(parents) == 1:
3838 if len(parents) == 1:
3832 parents.append(repo[nullid])
3839 parents.append(repo[nullid])
3833 if opts.get('exact'):
3840 if opts.get('exact'):
3834 if not nodeid or not p1:
3841 if not nodeid or not p1:
3835 raise util.Abort(_('not a Mercurial patch'))
3842 raise util.Abort(_('not a Mercurial patch'))
3836 p1 = repo[p1]
3843 p1 = repo[p1]
3837 p2 = repo[p2 or nullid]
3844 p2 = repo[p2 or nullid]
3838 elif p2:
3845 elif p2:
3839 try:
3846 try:
3840 p1 = repo[p1]
3847 p1 = repo[p1]
3841 p2 = repo[p2]
3848 p2 = repo[p2]
3842 # Without any options, consider p2 only if the
3849 # Without any options, consider p2 only if the
3843 # patch is being applied on top of the recorded
3850 # patch is being applied on top of the recorded
3844 # first parent.
3851 # first parent.
3845 if p1 != parents[0]:
3852 if p1 != parents[0]:
3846 p1 = parents[0]
3853 p1 = parents[0]
3847 p2 = repo[nullid]
3854 p2 = repo[nullid]
3848 except error.RepoError:
3855 except error.RepoError:
3849 p1, p2 = parents
3856 p1, p2 = parents
3850 else:
3857 else:
3851 p1, p2 = parents
3858 p1, p2 = parents
3852
3859
3853 n = None
3860 n = None
3854 if update:
3861 if update:
3855 if p1 != parents[0]:
3862 if p1 != parents[0]:
3856 hg.clean(repo, p1.node())
3863 hg.clean(repo, p1.node())
3857 if p2 != parents[1]:
3864 if p2 != parents[1]:
3858 repo.setparents(p1.node(), p2.node())
3865 repo.setparents(p1.node(), p2.node())
3859
3866
3860 if opts.get('exact') or opts.get('import_branch'):
3867 if opts.get('exact') or opts.get('import_branch'):
3861 repo.dirstate.setbranch(branch or 'default')
3868 repo.dirstate.setbranch(branch or 'default')
3862
3869
3863 files = set()
3870 files = set()
3864 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3871 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3865 eolmode=None, similarity=sim / 100.0)
3872 eolmode=None, similarity=sim / 100.0)
3866 files = list(files)
3873 files = list(files)
3867 if opts.get('no_commit'):
3874 if opts.get('no_commit'):
3868 if message:
3875 if message:
3869 msgs.append(message)
3876 msgs.append(message)
3870 else:
3877 else:
3871 if opts.get('exact') or p2:
3878 if opts.get('exact') or p2:
3872 # If you got here, you either use --force and know what
3879 # If you got here, you either use --force and know what
3873 # you are doing or used --exact or a merge patch while
3880 # you are doing or used --exact or a merge patch while
3874 # being updated to its first parent.
3881 # being updated to its first parent.
3875 m = None
3882 m = None
3876 else:
3883 else:
3877 m = scmutil.matchfiles(repo, files or [])
3884 m = scmutil.matchfiles(repo, files or [])
3878 n = repo.commit(message, opts.get('user') or user,
3885 n = repo.commit(message, opts.get('user') or user,
3879 opts.get('date') or date, match=m,
3886 opts.get('date') or date, match=m,
3880 editor=editor)
3887 editor=editor)
3881 checkexact(repo, n, nodeid)
3888 checkexact(repo, n, nodeid)
3882 else:
3889 else:
3883 if opts.get('exact') or opts.get('import_branch'):
3890 if opts.get('exact') or opts.get('import_branch'):
3884 branch = branch or 'default'
3891 branch = branch or 'default'
3885 else:
3892 else:
3886 branch = p1.branch()
3893 branch = p1.branch()
3887 store = patch.filestore()
3894 store = patch.filestore()
3888 try:
3895 try:
3889 files = set()
3896 files = set()
3890 try:
3897 try:
3891 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3898 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3892 files, eolmode=None)
3899 files, eolmode=None)
3893 except patch.PatchError, e:
3900 except patch.PatchError, e:
3894 raise util.Abort(str(e))
3901 raise util.Abort(str(e))
3895 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3902 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3896 message,
3903 message,
3897 opts.get('user') or user,
3904 opts.get('user') or user,
3898 opts.get('date') or date,
3905 opts.get('date') or date,
3899 branch, files, store,
3906 branch, files, store,
3900 editor=cmdutil.commiteditor)
3907 editor=cmdutil.commiteditor)
3901 repo.savecommitmessage(memctx.description())
3908 repo.savecommitmessage(memctx.description())
3902 n = memctx.commit()
3909 n = memctx.commit()
3903 checkexact(repo, n, nodeid)
3910 checkexact(repo, n, nodeid)
3904 finally:
3911 finally:
3905 store.close()
3912 store.close()
3906 if n:
3913 if n:
3907 # i18n: refers to a short changeset id
3914 # i18n: refers to a short changeset id
3908 msg = _('created %s') % short(n)
3915 msg = _('created %s') % short(n)
3909 return (msg, n)
3916 return (msg, n)
3910 finally:
3917 finally:
3911 os.unlink(tmpname)
3918 os.unlink(tmpname)
3912
3919
3913 try:
3920 try:
3914 try:
3921 try:
3915 wlock = repo.wlock()
3922 wlock = repo.wlock()
3916 if not opts.get('no_commit'):
3923 if not opts.get('no_commit'):
3917 lock = repo.lock()
3924 lock = repo.lock()
3918 tr = repo.transaction('import')
3925 tr = repo.transaction('import')
3919 parents = repo.parents()
3926 parents = repo.parents()
3920 for patchurl in patches:
3927 for patchurl in patches:
3921 if patchurl == '-':
3928 if patchurl == '-':
3922 ui.status(_('applying patch from stdin\n'))
3929 ui.status(_('applying patch from stdin\n'))
3923 patchfile = ui.fin
3930 patchfile = ui.fin
3924 patchurl = 'stdin' # for error message
3931 patchurl = 'stdin' # for error message
3925 else:
3932 else:
3926 patchurl = os.path.join(base, patchurl)
3933 patchurl = os.path.join(base, patchurl)
3927 ui.status(_('applying %s\n') % patchurl)
3934 ui.status(_('applying %s\n') % patchurl)
3928 patchfile = hg.openpath(ui, patchurl)
3935 patchfile = hg.openpath(ui, patchurl)
3929
3936
3930 haspatch = False
3937 haspatch = False
3931 for hunk in patch.split(patchfile):
3938 for hunk in patch.split(patchfile):
3932 (msg, node) = tryone(ui, hunk, parents)
3939 (msg, node) = tryone(ui, hunk, parents)
3933 if msg:
3940 if msg:
3934 haspatch = True
3941 haspatch = True
3935 ui.note(msg + '\n')
3942 ui.note(msg + '\n')
3936 if update or opts.get('exact'):
3943 if update or opts.get('exact'):
3937 parents = repo.parents()
3944 parents = repo.parents()
3938 else:
3945 else:
3939 parents = [repo[node]]
3946 parents = [repo[node]]
3940
3947
3941 if not haspatch:
3948 if not haspatch:
3942 raise util.Abort(_('%s: no diffs found') % patchurl)
3949 raise util.Abort(_('%s: no diffs found') % patchurl)
3943
3950
3944 if tr:
3951 if tr:
3945 tr.close()
3952 tr.close()
3946 if msgs:
3953 if msgs:
3947 repo.savecommitmessage('\n* * *\n'.join(msgs))
3954 repo.savecommitmessage('\n* * *\n'.join(msgs))
3948 except: # re-raises
3955 except: # re-raises
3949 # wlock.release() indirectly calls dirstate.write(): since
3956 # wlock.release() indirectly calls dirstate.write(): since
3950 # we're crashing, we do not want to change the working dir
3957 # we're crashing, we do not want to change the working dir
3951 # parent after all, so make sure it writes nothing
3958 # parent after all, so make sure it writes nothing
3952 repo.dirstate.invalidate()
3959 repo.dirstate.invalidate()
3953 raise
3960 raise
3954 finally:
3961 finally:
3955 if tr:
3962 if tr:
3956 tr.release()
3963 tr.release()
3957 release(lock, wlock)
3964 release(lock, wlock)
3958
3965
3959 @command('incoming|in',
3966 @command('incoming|in',
3960 [('f', 'force', None,
3967 [('f', 'force', None,
3961 _('run even if remote repository is unrelated')),
3968 _('run even if remote repository is unrelated')),
3962 ('n', 'newest-first', None, _('show newest record first')),
3969 ('n', 'newest-first', None, _('show newest record first')),
3963 ('', 'bundle', '',
3970 ('', 'bundle', '',
3964 _('file to store the bundles into'), _('FILE')),
3971 _('file to store the bundles into'), _('FILE')),
3965 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3972 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3966 ('B', 'bookmarks', False, _("compare bookmarks")),
3973 ('B', 'bookmarks', False, _("compare bookmarks")),
3967 ('b', 'branch', [],
3974 ('b', 'branch', [],
3968 _('a specific branch you would like to pull'), _('BRANCH')),
3975 _('a specific branch you would like to pull'), _('BRANCH')),
3969 ] + logopts + remoteopts + subrepoopts,
3976 ] + logopts + remoteopts + subrepoopts,
3970 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3977 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3971 def incoming(ui, repo, source="default", **opts):
3978 def incoming(ui, repo, source="default", **opts):
3972 """show new changesets found in source
3979 """show new changesets found in source
3973
3980
3974 Show new changesets found in the specified path/URL or the default
3981 Show new changesets found in the specified path/URL or the default
3975 pull location. These are the changesets that would have been pulled
3982 pull location. These are the changesets that would have been pulled
3976 if a pull at the time you issued this command.
3983 if a pull at the time you issued this command.
3977
3984
3978 For remote repository, using --bundle avoids downloading the
3985 For remote repository, using --bundle avoids downloading the
3979 changesets twice if the incoming is followed by a pull.
3986 changesets twice if the incoming is followed by a pull.
3980
3987
3981 See pull for valid source format details.
3988 See pull for valid source format details.
3982
3989
3983 Returns 0 if there are incoming changes, 1 otherwise.
3990 Returns 0 if there are incoming changes, 1 otherwise.
3984 """
3991 """
3985 if opts.get('graph'):
3992 if opts.get('graph'):
3986 cmdutil.checkunsupportedgraphflags([], opts)
3993 cmdutil.checkunsupportedgraphflags([], opts)
3987 def display(other, chlist, displayer):
3994 def display(other, chlist, displayer):
3988 revdag = cmdutil.graphrevs(other, chlist, opts)
3995 revdag = cmdutil.graphrevs(other, chlist, opts)
3989 showparents = [ctx.node() for ctx in repo[None].parents()]
3996 showparents = [ctx.node() for ctx in repo[None].parents()]
3990 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3997 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3991 graphmod.asciiedges)
3998 graphmod.asciiedges)
3992
3999
3993 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4000 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3994 return 0
4001 return 0
3995
4002
3996 if opts.get('bundle') and opts.get('subrepos'):
4003 if opts.get('bundle') and opts.get('subrepos'):
3997 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4004 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3998
4005
3999 if opts.get('bookmarks'):
4006 if opts.get('bookmarks'):
4000 source, branches = hg.parseurl(ui.expandpath(source),
4007 source, branches = hg.parseurl(ui.expandpath(source),
4001 opts.get('branch'))
4008 opts.get('branch'))
4002 other = hg.peer(repo, opts, source)
4009 other = hg.peer(repo, opts, source)
4003 if 'bookmarks' not in other.listkeys('namespaces'):
4010 if 'bookmarks' not in other.listkeys('namespaces'):
4004 ui.warn(_("remote doesn't support bookmarks\n"))
4011 ui.warn(_("remote doesn't support bookmarks\n"))
4005 return 0
4012 return 0
4006 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4013 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4007 return bookmarks.diff(ui, repo, other)
4014 return bookmarks.diff(ui, repo, other)
4008
4015
4009 repo._subtoppath = ui.expandpath(source)
4016 repo._subtoppath = ui.expandpath(source)
4010 try:
4017 try:
4011 return hg.incoming(ui, repo, source, opts)
4018 return hg.incoming(ui, repo, source, opts)
4012 finally:
4019 finally:
4013 del repo._subtoppath
4020 del repo._subtoppath
4014
4021
4015
4022
4016 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
4023 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
4017 def init(ui, dest=".", **opts):
4024 def init(ui, dest=".", **opts):
4018 """create a new repository in the given directory
4025 """create a new repository in the given directory
4019
4026
4020 Initialize a new repository in the given directory. If the given
4027 Initialize a new repository in the given directory. If the given
4021 directory does not exist, it will be created.
4028 directory does not exist, it will be created.
4022
4029
4023 If no directory is given, the current directory is used.
4030 If no directory is given, the current directory is used.
4024
4031
4025 It is possible to specify an ``ssh://`` URL as the destination.
4032 It is possible to specify an ``ssh://`` URL as the destination.
4026 See :hg:`help urls` for more information.
4033 See :hg:`help urls` for more information.
4027
4034
4028 Returns 0 on success.
4035 Returns 0 on success.
4029 """
4036 """
4030 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4037 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4031
4038
4032 @command('locate',
4039 @command('locate',
4033 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4040 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4034 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4041 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4035 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4042 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4036 ] + walkopts,
4043 ] + walkopts,
4037 _('[OPTION]... [PATTERN]...'))
4044 _('[OPTION]... [PATTERN]...'))
4038 def locate(ui, repo, *pats, **opts):
4045 def locate(ui, repo, *pats, **opts):
4039 """locate files matching specific patterns
4046 """locate files matching specific patterns
4040
4047
4041 Print files under Mercurial control in the working directory whose
4048 Print files under Mercurial control in the working directory whose
4042 names match the given patterns.
4049 names match the given patterns.
4043
4050
4044 By default, this command searches all directories in the working
4051 By default, this command searches all directories in the working
4045 directory. To search just the current directory and its
4052 directory. To search just the current directory and its
4046 subdirectories, use "--include .".
4053 subdirectories, use "--include .".
4047
4054
4048 If no patterns are given to match, this command prints the names
4055 If no patterns are given to match, this command prints the names
4049 of all files under Mercurial control in the working directory.
4056 of all files under Mercurial control in the working directory.
4050
4057
4051 If you want to feed the output of this command into the "xargs"
4058 If you want to feed the output of this command into the "xargs"
4052 command, use the -0 option to both this command and "xargs". This
4059 command, use the -0 option to both this command and "xargs". This
4053 will avoid the problem of "xargs" treating single filenames that
4060 will avoid the problem of "xargs" treating single filenames that
4054 contain whitespace as multiple filenames.
4061 contain whitespace as multiple filenames.
4055
4062
4056 Returns 0 if a match is found, 1 otherwise.
4063 Returns 0 if a match is found, 1 otherwise.
4057 """
4064 """
4058 end = opts.get('print0') and '\0' or '\n'
4065 end = opts.get('print0') and '\0' or '\n'
4059 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4066 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4060
4067
4061 ret = 1
4068 ret = 1
4062 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4069 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4063 m.bad = lambda x, y: False
4070 m.bad = lambda x, y: False
4064 for abs in repo[rev].walk(m):
4071 for abs in repo[rev].walk(m):
4065 if not rev and abs not in repo.dirstate:
4072 if not rev and abs not in repo.dirstate:
4066 continue
4073 continue
4067 if opts.get('fullpath'):
4074 if opts.get('fullpath'):
4068 ui.write(repo.wjoin(abs), end)
4075 ui.write(repo.wjoin(abs), end)
4069 else:
4076 else:
4070 ui.write(((pats and m.rel(abs)) or abs), end)
4077 ui.write(((pats and m.rel(abs)) or abs), end)
4071 ret = 0
4078 ret = 0
4072
4079
4073 return ret
4080 return ret
4074
4081
4075 @command('^log|history',
4082 @command('^log|history',
4076 [('f', 'follow', None,
4083 [('f', 'follow', None,
4077 _('follow changeset history, or file history across copies and renames')),
4084 _('follow changeset history, or file history across copies and renames')),
4078 ('', 'follow-first', None,
4085 ('', 'follow-first', None,
4079 _('only follow the first parent of merge changesets (DEPRECATED)')),
4086 _('only follow the first parent of merge changesets (DEPRECATED)')),
4080 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4087 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4081 ('C', 'copies', None, _('show copied files')),
4088 ('C', 'copies', None, _('show copied files')),
4082 ('k', 'keyword', [],
4089 ('k', 'keyword', [],
4083 _('do case-insensitive search for a given text'), _('TEXT')),
4090 _('do case-insensitive search for a given text'), _('TEXT')),
4084 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4091 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4085 ('', 'removed', None, _('include revisions where files were removed')),
4092 ('', 'removed', None, _('include revisions where files were removed')),
4086 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4093 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4087 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4094 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4088 ('', 'only-branch', [],
4095 ('', 'only-branch', [],
4089 _('show only changesets within the given named branch (DEPRECATED)'),
4096 _('show only changesets within the given named branch (DEPRECATED)'),
4090 _('BRANCH')),
4097 _('BRANCH')),
4091 ('b', 'branch', [],
4098 ('b', 'branch', [],
4092 _('show changesets within the given named branch'), _('BRANCH')),
4099 _('show changesets within the given named branch'), _('BRANCH')),
4093 ('P', 'prune', [],
4100 ('P', 'prune', [],
4094 _('do not display revision or any of its ancestors'), _('REV')),
4101 _('do not display revision or any of its ancestors'), _('REV')),
4095 ] + logopts + walkopts,
4102 ] + logopts + walkopts,
4096 _('[OPTION]... [FILE]'))
4103 _('[OPTION]... [FILE]'))
4097 def log(ui, repo, *pats, **opts):
4104 def log(ui, repo, *pats, **opts):
4098 """show revision history of entire repository or files
4105 """show revision history of entire repository or files
4099
4106
4100 Print the revision history of the specified files or the entire
4107 Print the revision history of the specified files or the entire
4101 project.
4108 project.
4102
4109
4103 If no revision range is specified, the default is ``tip:0`` unless
4110 If no revision range is specified, the default is ``tip:0`` unless
4104 --follow is set, in which case the working directory parent is
4111 --follow is set, in which case the working directory parent is
4105 used as the starting revision.
4112 used as the starting revision.
4106
4113
4107 File history is shown without following rename or copy history of
4114 File history is shown without following rename or copy history of
4108 files. Use -f/--follow with a filename to follow history across
4115 files. Use -f/--follow with a filename to follow history across
4109 renames and copies. --follow without a filename will only show
4116 renames and copies. --follow without a filename will only show
4110 ancestors or descendants of the starting revision.
4117 ancestors or descendants of the starting revision.
4111
4118
4112 By default this command prints revision number and changeset id,
4119 By default this command prints revision number and changeset id,
4113 tags, non-trivial parents, user, date and time, and a summary for
4120 tags, non-trivial parents, user, date and time, and a summary for
4114 each commit. When the -v/--verbose switch is used, the list of
4121 each commit. When the -v/--verbose switch is used, the list of
4115 changed files and full commit message are shown.
4122 changed files and full commit message are shown.
4116
4123
4117 .. note::
4124 .. note::
4118 log -p/--patch may generate unexpected diff output for merge
4125 log -p/--patch may generate unexpected diff output for merge
4119 changesets, as it will only compare the merge changeset against
4126 changesets, as it will only compare the merge changeset against
4120 its first parent. Also, only files different from BOTH parents
4127 its first parent. Also, only files different from BOTH parents
4121 will appear in files:.
4128 will appear in files:.
4122
4129
4123 .. note::
4130 .. note::
4124 for performance reasons, log FILE may omit duplicate changes
4131 for performance reasons, log FILE may omit duplicate changes
4125 made on branches and will not show deletions. To see all
4132 made on branches and will not show deletions. To see all
4126 changes including duplicates and deletions, use the --removed
4133 changes including duplicates and deletions, use the --removed
4127 switch.
4134 switch.
4128
4135
4129 .. container:: verbose
4136 .. container:: verbose
4130
4137
4131 Some examples:
4138 Some examples:
4132
4139
4133 - changesets with full descriptions and file lists::
4140 - changesets with full descriptions and file lists::
4134
4141
4135 hg log -v
4142 hg log -v
4136
4143
4137 - changesets ancestral to the working directory::
4144 - changesets ancestral to the working directory::
4138
4145
4139 hg log -f
4146 hg log -f
4140
4147
4141 - last 10 commits on the current branch::
4148 - last 10 commits on the current branch::
4142
4149
4143 hg log -l 10 -b .
4150 hg log -l 10 -b .
4144
4151
4145 - changesets showing all modifications of a file, including removals::
4152 - changesets showing all modifications of a file, including removals::
4146
4153
4147 hg log --removed file.c
4154 hg log --removed file.c
4148
4155
4149 - all changesets that touch a directory, with diffs, excluding merges::
4156 - all changesets that touch a directory, with diffs, excluding merges::
4150
4157
4151 hg log -Mp lib/
4158 hg log -Mp lib/
4152
4159
4153 - all revision numbers that match a keyword::
4160 - all revision numbers that match a keyword::
4154
4161
4155 hg log -k bug --template "{rev}\\n"
4162 hg log -k bug --template "{rev}\\n"
4156
4163
4157 - check if a given changeset is included is a tagged release::
4164 - check if a given changeset is included is a tagged release::
4158
4165
4159 hg log -r "a21ccf and ancestor(1.9)"
4166 hg log -r "a21ccf and ancestor(1.9)"
4160
4167
4161 - find all changesets by some user in a date range::
4168 - find all changesets by some user in a date range::
4162
4169
4163 hg log -k alice -d "may 2008 to jul 2008"
4170 hg log -k alice -d "may 2008 to jul 2008"
4164
4171
4165 - summary of all changesets after the last tag::
4172 - summary of all changesets after the last tag::
4166
4173
4167 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4174 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4168
4175
4169 See :hg:`help dates` for a list of formats valid for -d/--date.
4176 See :hg:`help dates` for a list of formats valid for -d/--date.
4170
4177
4171 See :hg:`help revisions` and :hg:`help revsets` for more about
4178 See :hg:`help revisions` and :hg:`help revsets` for more about
4172 specifying revisions.
4179 specifying revisions.
4173
4180
4174 See :hg:`help templates` for more about pre-packaged styles and
4181 See :hg:`help templates` for more about pre-packaged styles and
4175 specifying custom templates.
4182 specifying custom templates.
4176
4183
4177 Returns 0 on success.
4184 Returns 0 on success.
4178 """
4185 """
4179 if opts.get('graph'):
4186 if opts.get('graph'):
4180 return cmdutil.graphlog(ui, repo, *pats, **opts)
4187 return cmdutil.graphlog(ui, repo, *pats, **opts)
4181
4188
4182 matchfn = scmutil.match(repo[None], pats, opts)
4189 matchfn = scmutil.match(repo[None], pats, opts)
4183 limit = cmdutil.loglimit(opts)
4190 limit = cmdutil.loglimit(opts)
4184 count = 0
4191 count = 0
4185
4192
4186 getrenamed, endrev = None, None
4193 getrenamed, endrev = None, None
4187 if opts.get('copies'):
4194 if opts.get('copies'):
4188 if opts.get('rev'):
4195 if opts.get('rev'):
4189 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4196 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4190 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4197 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4191
4198
4192 df = False
4199 df = False
4193 if opts.get("date"):
4200 if opts.get("date"):
4194 df = util.matchdate(opts["date"])
4201 df = util.matchdate(opts["date"])
4195
4202
4196 branches = opts.get('branch', []) + opts.get('only_branch', [])
4203 branches = opts.get('branch', []) + opts.get('only_branch', [])
4197 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4204 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4198
4205
4199 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4206 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4200 def prep(ctx, fns):
4207 def prep(ctx, fns):
4201 rev = ctx.rev()
4208 rev = ctx.rev()
4202 parents = [p for p in repo.changelog.parentrevs(rev)
4209 parents = [p for p in repo.changelog.parentrevs(rev)
4203 if p != nullrev]
4210 if p != nullrev]
4204 if opts.get('no_merges') and len(parents) == 2:
4211 if opts.get('no_merges') and len(parents) == 2:
4205 return
4212 return
4206 if opts.get('only_merges') and len(parents) != 2:
4213 if opts.get('only_merges') and len(parents) != 2:
4207 return
4214 return
4208 if opts.get('branch') and ctx.branch() not in opts['branch']:
4215 if opts.get('branch') and ctx.branch() not in opts['branch']:
4209 return
4216 return
4210 if df and not df(ctx.date()[0]):
4217 if df and not df(ctx.date()[0]):
4211 return
4218 return
4212
4219
4213 lower = encoding.lower
4220 lower = encoding.lower
4214 if opts.get('user'):
4221 if opts.get('user'):
4215 luser = lower(ctx.user())
4222 luser = lower(ctx.user())
4216 for k in [lower(x) for x in opts['user']]:
4223 for k in [lower(x) for x in opts['user']]:
4217 if (k in luser):
4224 if (k in luser):
4218 break
4225 break
4219 else:
4226 else:
4220 return
4227 return
4221 if opts.get('keyword'):
4228 if opts.get('keyword'):
4222 luser = lower(ctx.user())
4229 luser = lower(ctx.user())
4223 ldesc = lower(ctx.description())
4230 ldesc = lower(ctx.description())
4224 lfiles = lower(" ".join(ctx.files()))
4231 lfiles = lower(" ".join(ctx.files()))
4225 for k in [lower(x) for x in opts['keyword']]:
4232 for k in [lower(x) for x in opts['keyword']]:
4226 if (k in luser or k in ldesc or k in lfiles):
4233 if (k in luser or k in ldesc or k in lfiles):
4227 break
4234 break
4228 else:
4235 else:
4229 return
4236 return
4230
4237
4231 copies = None
4238 copies = None
4232 if getrenamed is not None and rev:
4239 if getrenamed is not None and rev:
4233 copies = []
4240 copies = []
4234 for fn in ctx.files():
4241 for fn in ctx.files():
4235 rename = getrenamed(fn, rev)
4242 rename = getrenamed(fn, rev)
4236 if rename:
4243 if rename:
4237 copies.append((fn, rename[0]))
4244 copies.append((fn, rename[0]))
4238
4245
4239 revmatchfn = None
4246 revmatchfn = None
4240 if opts.get('patch') or opts.get('stat'):
4247 if opts.get('patch') or opts.get('stat'):
4241 if opts.get('follow') or opts.get('follow_first'):
4248 if opts.get('follow') or opts.get('follow_first'):
4242 # note: this might be wrong when following through merges
4249 # note: this might be wrong when following through merges
4243 revmatchfn = scmutil.match(repo[None], fns, default='path')
4250 revmatchfn = scmutil.match(repo[None], fns, default='path')
4244 else:
4251 else:
4245 revmatchfn = matchfn
4252 revmatchfn = matchfn
4246
4253
4247 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4254 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4248
4255
4249 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4256 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4250 if count == limit:
4257 if count == limit:
4251 break
4258 break
4252 if displayer.flush(ctx.rev()):
4259 if displayer.flush(ctx.rev()):
4253 count += 1
4260 count += 1
4254 displayer.close()
4261 displayer.close()
4255
4262
4256 @command('manifest',
4263 @command('manifest',
4257 [('r', 'rev', '', _('revision to display'), _('REV')),
4264 [('r', 'rev', '', _('revision to display'), _('REV')),
4258 ('', 'all', False, _("list files from all revisions"))],
4265 ('', 'all', False, _("list files from all revisions"))],
4259 _('[-r REV]'))
4266 _('[-r REV]'))
4260 def manifest(ui, repo, node=None, rev=None, **opts):
4267 def manifest(ui, repo, node=None, rev=None, **opts):
4261 """output the current or given revision of the project manifest
4268 """output the current or given revision of the project manifest
4262
4269
4263 Print a list of version controlled files for the given revision.
4270 Print a list of version controlled files for the given revision.
4264 If no revision is given, the first parent of the working directory
4271 If no revision is given, the first parent of the working directory
4265 is used, or the null revision if no revision is checked out.
4272 is used, or the null revision if no revision is checked out.
4266
4273
4267 With -v, print file permissions, symlink and executable bits.
4274 With -v, print file permissions, symlink and executable bits.
4268 With --debug, print file revision hashes.
4275 With --debug, print file revision hashes.
4269
4276
4270 If option --all is specified, the list of all files from all revisions
4277 If option --all is specified, the list of all files from all revisions
4271 is printed. This includes deleted and renamed files.
4278 is printed. This includes deleted and renamed files.
4272
4279
4273 Returns 0 on success.
4280 Returns 0 on success.
4274 """
4281 """
4275
4282
4276 fm = ui.formatter('manifest', opts)
4283 fm = ui.formatter('manifest', opts)
4277
4284
4278 if opts.get('all'):
4285 if opts.get('all'):
4279 if rev or node:
4286 if rev or node:
4280 raise util.Abort(_("can't specify a revision with --all"))
4287 raise util.Abort(_("can't specify a revision with --all"))
4281
4288
4282 res = []
4289 res = []
4283 prefix = "data/"
4290 prefix = "data/"
4284 suffix = ".i"
4291 suffix = ".i"
4285 plen = len(prefix)
4292 plen = len(prefix)
4286 slen = len(suffix)
4293 slen = len(suffix)
4287 lock = repo.lock()
4294 lock = repo.lock()
4288 try:
4295 try:
4289 for fn, b, size in repo.store.datafiles():
4296 for fn, b, size in repo.store.datafiles():
4290 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4297 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4291 res.append(fn[plen:-slen])
4298 res.append(fn[plen:-slen])
4292 finally:
4299 finally:
4293 lock.release()
4300 lock.release()
4294 for f in res:
4301 for f in res:
4295 fm.startitem()
4302 fm.startitem()
4296 fm.write("path", '%s\n', f)
4303 fm.write("path", '%s\n', f)
4297 fm.end()
4304 fm.end()
4298 return
4305 return
4299
4306
4300 if rev and node:
4307 if rev and node:
4301 raise util.Abort(_("please specify just one revision"))
4308 raise util.Abort(_("please specify just one revision"))
4302
4309
4303 if not node:
4310 if not node:
4304 node = rev
4311 node = rev
4305
4312
4306 char = {'l': '@', 'x': '*', '': ''}
4313 char = {'l': '@', 'x': '*', '': ''}
4307 mode = {'l': '644', 'x': '755', '': '644'}
4314 mode = {'l': '644', 'x': '755', '': '644'}
4308 ctx = scmutil.revsingle(repo, node)
4315 ctx = scmutil.revsingle(repo, node)
4309 mf = ctx.manifest()
4316 mf = ctx.manifest()
4310 for f in ctx:
4317 for f in ctx:
4311 fm.startitem()
4318 fm.startitem()
4312 fl = ctx[f].flags()
4319 fl = ctx[f].flags()
4313 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4320 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4314 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4321 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4315 fm.write('path', '%s\n', f)
4322 fm.write('path', '%s\n', f)
4316 fm.end()
4323 fm.end()
4317
4324
4318 @command('^merge',
4325 @command('^merge',
4319 [('f', 'force', None, _('force a merge with outstanding changes')),
4326 [('f', 'force', None, _('force a merge with outstanding changes')),
4320 ('r', 'rev', '', _('revision to merge'), _('REV')),
4327 ('r', 'rev', '', _('revision to merge'), _('REV')),
4321 ('P', 'preview', None,
4328 ('P', 'preview', None,
4322 _('review revisions to merge (no merge is performed)'))
4329 _('review revisions to merge (no merge is performed)'))
4323 ] + mergetoolopts,
4330 ] + mergetoolopts,
4324 _('[-P] [-f] [[-r] REV]'))
4331 _('[-P] [-f] [[-r] REV]'))
4325 def merge(ui, repo, node=None, **opts):
4332 def merge(ui, repo, node=None, **opts):
4326 """merge working directory with another revision
4333 """merge working directory with another revision
4327
4334
4328 The current working directory is updated with all changes made in
4335 The current working directory is updated with all changes made in
4329 the requested revision since the last common predecessor revision.
4336 the requested revision since the last common predecessor revision.
4330
4337
4331 Files that changed between either parent are marked as changed for
4338 Files that changed between either parent are marked as changed for
4332 the next commit and a commit must be performed before any further
4339 the next commit and a commit must be performed before any further
4333 updates to the repository are allowed. The next commit will have
4340 updates to the repository are allowed. The next commit will have
4334 two parents.
4341 two parents.
4335
4342
4336 ``--tool`` can be used to specify the merge tool used for file
4343 ``--tool`` can be used to specify the merge tool used for file
4337 merges. It overrides the HGMERGE environment variable and your
4344 merges. It overrides the HGMERGE environment variable and your
4338 configuration files. See :hg:`help merge-tools` for options.
4345 configuration files. See :hg:`help merge-tools` for options.
4339
4346
4340 If no revision is specified, the working directory's parent is a
4347 If no revision is specified, the working directory's parent is a
4341 head revision, and the current branch contains exactly one other
4348 head revision, and the current branch contains exactly one other
4342 head, the other head is merged with by default. Otherwise, an
4349 head, the other head is merged with by default. Otherwise, an
4343 explicit revision with which to merge with must be provided.
4350 explicit revision with which to merge with must be provided.
4344
4351
4345 :hg:`resolve` must be used to resolve unresolved files.
4352 :hg:`resolve` must be used to resolve unresolved files.
4346
4353
4347 To undo an uncommitted merge, use :hg:`update --clean .` which
4354 To undo an uncommitted merge, use :hg:`update --clean .` which
4348 will check out a clean copy of the original merge parent, losing
4355 will check out a clean copy of the original merge parent, losing
4349 all changes.
4356 all changes.
4350
4357
4351 Returns 0 on success, 1 if there are unresolved files.
4358 Returns 0 on success, 1 if there are unresolved files.
4352 """
4359 """
4353
4360
4354 if opts.get('rev') and node:
4361 if opts.get('rev') and node:
4355 raise util.Abort(_("please specify just one revision"))
4362 raise util.Abort(_("please specify just one revision"))
4356 if not node:
4363 if not node:
4357 node = opts.get('rev')
4364 node = opts.get('rev')
4358
4365
4359 if node:
4366 if node:
4360 node = scmutil.revsingle(repo, node).node()
4367 node = scmutil.revsingle(repo, node).node()
4361
4368
4362 if not node and repo._bookmarkcurrent:
4369 if not node and repo._bookmarkcurrent:
4363 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4370 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4364 curhead = repo[repo._bookmarkcurrent].node()
4371 curhead = repo[repo._bookmarkcurrent].node()
4365 if len(bmheads) == 2:
4372 if len(bmheads) == 2:
4366 if curhead == bmheads[0]:
4373 if curhead == bmheads[0]:
4367 node = bmheads[1]
4374 node = bmheads[1]
4368 else:
4375 else:
4369 node = bmheads[0]
4376 node = bmheads[0]
4370 elif len(bmheads) > 2:
4377 elif len(bmheads) > 2:
4371 raise util.Abort(_("multiple matching bookmarks to merge - "
4378 raise util.Abort(_("multiple matching bookmarks to merge - "
4372 "please merge with an explicit rev or bookmark"),
4379 "please merge with an explicit rev or bookmark"),
4373 hint=_("run 'hg heads' to see all heads"))
4380 hint=_("run 'hg heads' to see all heads"))
4374 elif len(bmheads) <= 1:
4381 elif len(bmheads) <= 1:
4375 raise util.Abort(_("no matching bookmark to merge - "
4382 raise util.Abort(_("no matching bookmark to merge - "
4376 "please merge with an explicit rev or bookmark"),
4383 "please merge with an explicit rev or bookmark"),
4377 hint=_("run 'hg heads' to see all heads"))
4384 hint=_("run 'hg heads' to see all heads"))
4378
4385
4379 if not node and not repo._bookmarkcurrent:
4386 if not node and not repo._bookmarkcurrent:
4380 branch = repo[None].branch()
4387 branch = repo[None].branch()
4381 bheads = repo.branchheads(branch)
4388 bheads = repo.branchheads(branch)
4382 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4389 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4383
4390
4384 if len(nbhs) > 2:
4391 if len(nbhs) > 2:
4385 raise util.Abort(_("branch '%s' has %d heads - "
4392 raise util.Abort(_("branch '%s' has %d heads - "
4386 "please merge with an explicit rev")
4393 "please merge with an explicit rev")
4387 % (branch, len(bheads)),
4394 % (branch, len(bheads)),
4388 hint=_("run 'hg heads .' to see heads"))
4395 hint=_("run 'hg heads .' to see heads"))
4389
4396
4390 parent = repo.dirstate.p1()
4397 parent = repo.dirstate.p1()
4391 if len(nbhs) <= 1:
4398 if len(nbhs) <= 1:
4392 if len(bheads) > 1:
4399 if len(bheads) > 1:
4393 raise util.Abort(_("heads are bookmarked - "
4400 raise util.Abort(_("heads are bookmarked - "
4394 "please merge with an explicit rev"),
4401 "please merge with an explicit rev"),
4395 hint=_("run 'hg heads' to see all heads"))
4402 hint=_("run 'hg heads' to see all heads"))
4396 if len(repo.heads()) > 1:
4403 if len(repo.heads()) > 1:
4397 raise util.Abort(_("branch '%s' has one head - "
4404 raise util.Abort(_("branch '%s' has one head - "
4398 "please merge with an explicit rev")
4405 "please merge with an explicit rev")
4399 % branch,
4406 % branch,
4400 hint=_("run 'hg heads' to see all heads"))
4407 hint=_("run 'hg heads' to see all heads"))
4401 msg, hint = _('nothing to merge'), None
4408 msg, hint = _('nothing to merge'), None
4402 if parent != repo.lookup(branch):
4409 if parent != repo.lookup(branch):
4403 hint = _("use 'hg update' instead")
4410 hint = _("use 'hg update' instead")
4404 raise util.Abort(msg, hint=hint)
4411 raise util.Abort(msg, hint=hint)
4405
4412
4406 if parent not in bheads:
4413 if parent not in bheads:
4407 raise util.Abort(_('working directory not at a head revision'),
4414 raise util.Abort(_('working directory not at a head revision'),
4408 hint=_("use 'hg update' or merge with an "
4415 hint=_("use 'hg update' or merge with an "
4409 "explicit revision"))
4416 "explicit revision"))
4410 if parent == nbhs[0]:
4417 if parent == nbhs[0]:
4411 node = nbhs[-1]
4418 node = nbhs[-1]
4412 else:
4419 else:
4413 node = nbhs[0]
4420 node = nbhs[0]
4414
4421
4415 if opts.get('preview'):
4422 if opts.get('preview'):
4416 # find nodes that are ancestors of p2 but not of p1
4423 # find nodes that are ancestors of p2 but not of p1
4417 p1 = repo.lookup('.')
4424 p1 = repo.lookup('.')
4418 p2 = repo.lookup(node)
4425 p2 = repo.lookup(node)
4419 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4426 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4420
4427
4421 displayer = cmdutil.show_changeset(ui, repo, opts)
4428 displayer = cmdutil.show_changeset(ui, repo, opts)
4422 for node in nodes:
4429 for node in nodes:
4423 displayer.show(repo[node])
4430 displayer.show(repo[node])
4424 displayer.close()
4431 displayer.close()
4425 return 0
4432 return 0
4426
4433
4427 try:
4434 try:
4428 # ui.forcemerge is an internal variable, do not document
4435 # ui.forcemerge is an internal variable, do not document
4429 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4436 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4430 return hg.merge(repo, node, force=opts.get('force'))
4437 return hg.merge(repo, node, force=opts.get('force'))
4431 finally:
4438 finally:
4432 ui.setconfig('ui', 'forcemerge', '')
4439 ui.setconfig('ui', 'forcemerge', '')
4433
4440
4434 @command('outgoing|out',
4441 @command('outgoing|out',
4435 [('f', 'force', None, _('run even when the destination is unrelated')),
4442 [('f', 'force', None, _('run even when the destination is unrelated')),
4436 ('r', 'rev', [],
4443 ('r', 'rev', [],
4437 _('a changeset intended to be included in the destination'), _('REV')),
4444 _('a changeset intended to be included in the destination'), _('REV')),
4438 ('n', 'newest-first', None, _('show newest record first')),
4445 ('n', 'newest-first', None, _('show newest record first')),
4439 ('B', 'bookmarks', False, _('compare bookmarks')),
4446 ('B', 'bookmarks', False, _('compare bookmarks')),
4440 ('b', 'branch', [], _('a specific branch you would like to push'),
4447 ('b', 'branch', [], _('a specific branch you would like to push'),
4441 _('BRANCH')),
4448 _('BRANCH')),
4442 ] + logopts + remoteopts + subrepoopts,
4449 ] + logopts + remoteopts + subrepoopts,
4443 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4450 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4444 def outgoing(ui, repo, dest=None, **opts):
4451 def outgoing(ui, repo, dest=None, **opts):
4445 """show changesets not found in the destination
4452 """show changesets not found in the destination
4446
4453
4447 Show changesets not found in the specified destination repository
4454 Show changesets not found in the specified destination repository
4448 or the default push location. These are the changesets that would
4455 or the default push location. These are the changesets that would
4449 be pushed if a push was requested.
4456 be pushed if a push was requested.
4450
4457
4451 See pull for details of valid destination formats.
4458 See pull for details of valid destination formats.
4452
4459
4453 Returns 0 if there are outgoing changes, 1 otherwise.
4460 Returns 0 if there are outgoing changes, 1 otherwise.
4454 """
4461 """
4455 if opts.get('graph'):
4462 if opts.get('graph'):
4456 cmdutil.checkunsupportedgraphflags([], opts)
4463 cmdutil.checkunsupportedgraphflags([], opts)
4457 o = hg._outgoing(ui, repo, dest, opts)
4464 o = hg._outgoing(ui, repo, dest, opts)
4458 if o is None:
4465 if o is None:
4459 return
4466 return
4460
4467
4461 revdag = cmdutil.graphrevs(repo, o, opts)
4468 revdag = cmdutil.graphrevs(repo, o, opts)
4462 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4469 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4463 showparents = [ctx.node() for ctx in repo[None].parents()]
4470 showparents = [ctx.node() for ctx in repo[None].parents()]
4464 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4471 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4465 graphmod.asciiedges)
4472 graphmod.asciiedges)
4466 return 0
4473 return 0
4467
4474
4468 if opts.get('bookmarks'):
4475 if opts.get('bookmarks'):
4469 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4476 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4470 dest, branches = hg.parseurl(dest, opts.get('branch'))
4477 dest, branches = hg.parseurl(dest, opts.get('branch'))
4471 other = hg.peer(repo, opts, dest)
4478 other = hg.peer(repo, opts, dest)
4472 if 'bookmarks' not in other.listkeys('namespaces'):
4479 if 'bookmarks' not in other.listkeys('namespaces'):
4473 ui.warn(_("remote doesn't support bookmarks\n"))
4480 ui.warn(_("remote doesn't support bookmarks\n"))
4474 return 0
4481 return 0
4475 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4482 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4476 return bookmarks.diff(ui, other, repo)
4483 return bookmarks.diff(ui, other, repo)
4477
4484
4478 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4485 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4479 try:
4486 try:
4480 return hg.outgoing(ui, repo, dest, opts)
4487 return hg.outgoing(ui, repo, dest, opts)
4481 finally:
4488 finally:
4482 del repo._subtoppath
4489 del repo._subtoppath
4483
4490
4484 @command('parents',
4491 @command('parents',
4485 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4492 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4486 ] + templateopts,
4493 ] + templateopts,
4487 _('[-r REV] [FILE]'))
4494 _('[-r REV] [FILE]'))
4488 def parents(ui, repo, file_=None, **opts):
4495 def parents(ui, repo, file_=None, **opts):
4489 """show the parents of the working directory or revision
4496 """show the parents of the working directory or revision
4490
4497
4491 Print the working directory's parent revisions. If a revision is
4498 Print the working directory's parent revisions. If a revision is
4492 given via -r/--rev, the parent of that revision will be printed.
4499 given via -r/--rev, the parent of that revision will be printed.
4493 If a file argument is given, the revision in which the file was
4500 If a file argument is given, the revision in which the file was
4494 last changed (before the working directory revision or the
4501 last changed (before the working directory revision or the
4495 argument to --rev if given) is printed.
4502 argument to --rev if given) is printed.
4496
4503
4497 Returns 0 on success.
4504 Returns 0 on success.
4498 """
4505 """
4499
4506
4500 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4507 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4501
4508
4502 if file_:
4509 if file_:
4503 m = scmutil.match(ctx, (file_,), opts)
4510 m = scmutil.match(ctx, (file_,), opts)
4504 if m.anypats() or len(m.files()) != 1:
4511 if m.anypats() or len(m.files()) != 1:
4505 raise util.Abort(_('can only specify an explicit filename'))
4512 raise util.Abort(_('can only specify an explicit filename'))
4506 file_ = m.files()[0]
4513 file_ = m.files()[0]
4507 filenodes = []
4514 filenodes = []
4508 for cp in ctx.parents():
4515 for cp in ctx.parents():
4509 if not cp:
4516 if not cp:
4510 continue
4517 continue
4511 try:
4518 try:
4512 filenodes.append(cp.filenode(file_))
4519 filenodes.append(cp.filenode(file_))
4513 except error.LookupError:
4520 except error.LookupError:
4514 pass
4521 pass
4515 if not filenodes:
4522 if not filenodes:
4516 raise util.Abort(_("'%s' not found in manifest!") % file_)
4523 raise util.Abort(_("'%s' not found in manifest!") % file_)
4517 fl = repo.file(file_)
4524 fl = repo.file(file_)
4518 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4525 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4519 else:
4526 else:
4520 p = [cp.node() for cp in ctx.parents()]
4527 p = [cp.node() for cp in ctx.parents()]
4521
4528
4522 displayer = cmdutil.show_changeset(ui, repo, opts)
4529 displayer = cmdutil.show_changeset(ui, repo, opts)
4523 for n in p:
4530 for n in p:
4524 if n != nullid:
4531 if n != nullid:
4525 displayer.show(repo[n])
4532 displayer.show(repo[n])
4526 displayer.close()
4533 displayer.close()
4527
4534
4528 @command('paths', [], _('[NAME]'))
4535 @command('paths', [], _('[NAME]'))
4529 def paths(ui, repo, search=None):
4536 def paths(ui, repo, search=None):
4530 """show aliases for remote repositories
4537 """show aliases for remote repositories
4531
4538
4532 Show definition of symbolic path name NAME. If no name is given,
4539 Show definition of symbolic path name NAME. If no name is given,
4533 show definition of all available names.
4540 show definition of all available names.
4534
4541
4535 Option -q/--quiet suppresses all output when searching for NAME
4542 Option -q/--quiet suppresses all output when searching for NAME
4536 and shows only the path names when listing all definitions.
4543 and shows only the path names when listing all definitions.
4537
4544
4538 Path names are defined in the [paths] section of your
4545 Path names are defined in the [paths] section of your
4539 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4546 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4540 repository, ``.hg/hgrc`` is used, too.
4547 repository, ``.hg/hgrc`` is used, too.
4541
4548
4542 The path names ``default`` and ``default-push`` have a special
4549 The path names ``default`` and ``default-push`` have a special
4543 meaning. When performing a push or pull operation, they are used
4550 meaning. When performing a push or pull operation, they are used
4544 as fallbacks if no location is specified on the command-line.
4551 as fallbacks if no location is specified on the command-line.
4545 When ``default-push`` is set, it will be used for push and
4552 When ``default-push`` is set, it will be used for push and
4546 ``default`` will be used for pull; otherwise ``default`` is used
4553 ``default`` will be used for pull; otherwise ``default`` is used
4547 as the fallback for both. When cloning a repository, the clone
4554 as the fallback for both. When cloning a repository, the clone
4548 source is written as ``default`` in ``.hg/hgrc``. Note that
4555 source is written as ``default`` in ``.hg/hgrc``. Note that
4549 ``default`` and ``default-push`` apply to all inbound (e.g.
4556 ``default`` and ``default-push`` apply to all inbound (e.g.
4550 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4557 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4551 :hg:`bundle`) operations.
4558 :hg:`bundle`) operations.
4552
4559
4553 See :hg:`help urls` for more information.
4560 See :hg:`help urls` for more information.
4554
4561
4555 Returns 0 on success.
4562 Returns 0 on success.
4556 """
4563 """
4557 if search:
4564 if search:
4558 for name, path in ui.configitems("paths"):
4565 for name, path in ui.configitems("paths"):
4559 if name == search:
4566 if name == search:
4560 ui.status("%s\n" % util.hidepassword(path))
4567 ui.status("%s\n" % util.hidepassword(path))
4561 return
4568 return
4562 if not ui.quiet:
4569 if not ui.quiet:
4563 ui.warn(_("not found!\n"))
4570 ui.warn(_("not found!\n"))
4564 return 1
4571 return 1
4565 else:
4572 else:
4566 for name, path in ui.configitems("paths"):
4573 for name, path in ui.configitems("paths"):
4567 if ui.quiet:
4574 if ui.quiet:
4568 ui.write("%s\n" % name)
4575 ui.write("%s\n" % name)
4569 else:
4576 else:
4570 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4577 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4571
4578
4572 @command('phase',
4579 @command('phase',
4573 [('p', 'public', False, _('set changeset phase to public')),
4580 [('p', 'public', False, _('set changeset phase to public')),
4574 ('d', 'draft', False, _('set changeset phase to draft')),
4581 ('d', 'draft', False, _('set changeset phase to draft')),
4575 ('s', 'secret', False, _('set changeset phase to secret')),
4582 ('s', 'secret', False, _('set changeset phase to secret')),
4576 ('f', 'force', False, _('allow to move boundary backward')),
4583 ('f', 'force', False, _('allow to move boundary backward')),
4577 ('r', 'rev', [], _('target revision'), _('REV')),
4584 ('r', 'rev', [], _('target revision'), _('REV')),
4578 ],
4585 ],
4579 _('[-p|-d|-s] [-f] [-r] REV...'))
4586 _('[-p|-d|-s] [-f] [-r] REV...'))
4580 def phase(ui, repo, *revs, **opts):
4587 def phase(ui, repo, *revs, **opts):
4581 """set or show the current phase name
4588 """set or show the current phase name
4582
4589
4583 With no argument, show the phase name of specified revisions.
4590 With no argument, show the phase name of specified revisions.
4584
4591
4585 With one of -p/--public, -d/--draft or -s/--secret, change the
4592 With one of -p/--public, -d/--draft or -s/--secret, change the
4586 phase value of the specified revisions.
4593 phase value of the specified revisions.
4587
4594
4588 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4595 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4589 lower phase to an higher phase. Phases are ordered as follows::
4596 lower phase to an higher phase. Phases are ordered as follows::
4590
4597
4591 public < draft < secret
4598 public < draft < secret
4592
4599
4593 Return 0 on success, 1 if no phases were changed or some could not
4600 Return 0 on success, 1 if no phases were changed or some could not
4594 be changed.
4601 be changed.
4595 """
4602 """
4596 # search for a unique phase argument
4603 # search for a unique phase argument
4597 targetphase = None
4604 targetphase = None
4598 for idx, name in enumerate(phases.phasenames):
4605 for idx, name in enumerate(phases.phasenames):
4599 if opts[name]:
4606 if opts[name]:
4600 if targetphase is not None:
4607 if targetphase is not None:
4601 raise util.Abort(_('only one phase can be specified'))
4608 raise util.Abort(_('only one phase can be specified'))
4602 targetphase = idx
4609 targetphase = idx
4603
4610
4604 # look for specified revision
4611 # look for specified revision
4605 revs = list(revs)
4612 revs = list(revs)
4606 revs.extend(opts['rev'])
4613 revs.extend(opts['rev'])
4607 if not revs:
4614 if not revs:
4608 raise util.Abort(_('no revisions specified'))
4615 raise util.Abort(_('no revisions specified'))
4609
4616
4610 revs = scmutil.revrange(repo, revs)
4617 revs = scmutil.revrange(repo, revs)
4611
4618
4612 lock = None
4619 lock = None
4613 ret = 0
4620 ret = 0
4614 if targetphase is None:
4621 if targetphase is None:
4615 # display
4622 # display
4616 for r in revs:
4623 for r in revs:
4617 ctx = repo[r]
4624 ctx = repo[r]
4618 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4625 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4619 else:
4626 else:
4620 lock = repo.lock()
4627 lock = repo.lock()
4621 try:
4628 try:
4622 # set phase
4629 # set phase
4623 if not revs:
4630 if not revs:
4624 raise util.Abort(_('empty revision set'))
4631 raise util.Abort(_('empty revision set'))
4625 nodes = [repo[r].node() for r in revs]
4632 nodes = [repo[r].node() for r in revs]
4626 olddata = repo._phasecache.getphaserevs(repo)[:]
4633 olddata = repo._phasecache.getphaserevs(repo)[:]
4627 phases.advanceboundary(repo, targetphase, nodes)
4634 phases.advanceboundary(repo, targetphase, nodes)
4628 if opts['force']:
4635 if opts['force']:
4629 phases.retractboundary(repo, targetphase, nodes)
4636 phases.retractboundary(repo, targetphase, nodes)
4630 finally:
4637 finally:
4631 lock.release()
4638 lock.release()
4632 # moving revision from public to draft may hide them
4639 # moving revision from public to draft may hide them
4633 # We have to check result on an unfiltered repository
4640 # We have to check result on an unfiltered repository
4634 unfi = repo.unfiltered()
4641 unfi = repo.unfiltered()
4635 newdata = repo._phasecache.getphaserevs(unfi)
4642 newdata = repo._phasecache.getphaserevs(unfi)
4636 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4643 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4637 cl = unfi.changelog
4644 cl = unfi.changelog
4638 rejected = [n for n in nodes
4645 rejected = [n for n in nodes
4639 if newdata[cl.rev(n)] < targetphase]
4646 if newdata[cl.rev(n)] < targetphase]
4640 if rejected:
4647 if rejected:
4641 ui.warn(_('cannot move %i changesets to a more permissive '
4648 ui.warn(_('cannot move %i changesets to a more permissive '
4642 'phase, use --force\n') % len(rejected))
4649 'phase, use --force\n') % len(rejected))
4643 ret = 1
4650 ret = 1
4644 if changes:
4651 if changes:
4645 msg = _('phase changed for %i changesets\n') % changes
4652 msg = _('phase changed for %i changesets\n') % changes
4646 if ret:
4653 if ret:
4647 ui.status(msg)
4654 ui.status(msg)
4648 else:
4655 else:
4649 ui.note(msg)
4656 ui.note(msg)
4650 else:
4657 else:
4651 ui.warn(_('no phases changed\n'))
4658 ui.warn(_('no phases changed\n'))
4652 ret = 1
4659 ret = 1
4653 return ret
4660 return ret
4654
4661
4655 def postincoming(ui, repo, modheads, optupdate, checkout):
4662 def postincoming(ui, repo, modheads, optupdate, checkout):
4656 if modheads == 0:
4663 if modheads == 0:
4657 return
4664 return
4658 if optupdate:
4665 if optupdate:
4659 movemarkfrom = repo['.'].node()
4666 movemarkfrom = repo['.'].node()
4660 try:
4667 try:
4661 ret = hg.update(repo, checkout)
4668 ret = hg.update(repo, checkout)
4662 except util.Abort, inst:
4669 except util.Abort, inst:
4663 ui.warn(_("not updating: %s\n") % str(inst))
4670 ui.warn(_("not updating: %s\n") % str(inst))
4664 return 0
4671 return 0
4665 if not ret and not checkout:
4672 if not ret and not checkout:
4666 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4673 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4667 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4674 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4668 return ret
4675 return ret
4669 if modheads > 1:
4676 if modheads > 1:
4670 currentbranchheads = len(repo.branchheads())
4677 currentbranchheads = len(repo.branchheads())
4671 if currentbranchheads == modheads:
4678 if currentbranchheads == modheads:
4672 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4679 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4673 elif currentbranchheads > 1:
4680 elif currentbranchheads > 1:
4674 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4681 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4675 "merge)\n"))
4682 "merge)\n"))
4676 else:
4683 else:
4677 ui.status(_("(run 'hg heads' to see heads)\n"))
4684 ui.status(_("(run 'hg heads' to see heads)\n"))
4678 else:
4685 else:
4679 ui.status(_("(run 'hg update' to get a working copy)\n"))
4686 ui.status(_("(run 'hg update' to get a working copy)\n"))
4680
4687
4681 @command('^pull',
4688 @command('^pull',
4682 [('u', 'update', None,
4689 [('u', 'update', None,
4683 _('update to new branch head if changesets were pulled')),
4690 _('update to new branch head if changesets were pulled')),
4684 ('f', 'force', None, _('run even when remote repository is unrelated')),
4691 ('f', 'force', None, _('run even when remote repository is unrelated')),
4685 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4692 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4686 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4693 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4687 ('b', 'branch', [], _('a specific branch you would like to pull'),
4694 ('b', 'branch', [], _('a specific branch you would like to pull'),
4688 _('BRANCH')),
4695 _('BRANCH')),
4689 ] + remoteopts,
4696 ] + remoteopts,
4690 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4697 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4691 def pull(ui, repo, source="default", **opts):
4698 def pull(ui, repo, source="default", **opts):
4692 """pull changes from the specified source
4699 """pull changes from the specified source
4693
4700
4694 Pull changes from a remote repository to a local one.
4701 Pull changes from a remote repository to a local one.
4695
4702
4696 This finds all changes from the repository at the specified path
4703 This finds all changes from the repository at the specified path
4697 or URL and adds them to a local repository (the current one unless
4704 or URL and adds them to a local repository (the current one unless
4698 -R is specified). By default, this does not update the copy of the
4705 -R is specified). By default, this does not update the copy of the
4699 project in the working directory.
4706 project in the working directory.
4700
4707
4701 Use :hg:`incoming` if you want to see what would have been added
4708 Use :hg:`incoming` if you want to see what would have been added
4702 by a pull at the time you issued this command. If you then decide
4709 by a pull at the time you issued this command. If you then decide
4703 to add those changes to the repository, you should use :hg:`pull
4710 to add those changes to the repository, you should use :hg:`pull
4704 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4711 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4705
4712
4706 If SOURCE is omitted, the 'default' path will be used.
4713 If SOURCE is omitted, the 'default' path will be used.
4707 See :hg:`help urls` for more information.
4714 See :hg:`help urls` for more information.
4708
4715
4709 Returns 0 on success, 1 if an update had unresolved files.
4716 Returns 0 on success, 1 if an update had unresolved files.
4710 """
4717 """
4711 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4718 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4712 other = hg.peer(repo, opts, source)
4719 other = hg.peer(repo, opts, source)
4713 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4720 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4714 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4721 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4715
4722
4716 if opts.get('bookmark'):
4723 if opts.get('bookmark'):
4717 if not revs:
4724 if not revs:
4718 revs = []
4725 revs = []
4719 rb = other.listkeys('bookmarks')
4726 rb = other.listkeys('bookmarks')
4720 for b in opts['bookmark']:
4727 for b in opts['bookmark']:
4721 if b not in rb:
4728 if b not in rb:
4722 raise util.Abort(_('remote bookmark %s not found!') % b)
4729 raise util.Abort(_('remote bookmark %s not found!') % b)
4723 revs.append(rb[b])
4730 revs.append(rb[b])
4724
4731
4725 if revs:
4732 if revs:
4726 try:
4733 try:
4727 revs = [other.lookup(rev) for rev in revs]
4734 revs = [other.lookup(rev) for rev in revs]
4728 except error.CapabilityError:
4735 except error.CapabilityError:
4729 err = _("other repository doesn't support revision lookup, "
4736 err = _("other repository doesn't support revision lookup, "
4730 "so a rev cannot be specified.")
4737 "so a rev cannot be specified.")
4731 raise util.Abort(err)
4738 raise util.Abort(err)
4732
4739
4733 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4740 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4734 bookmarks.updatefromremote(ui, repo, other, source)
4741 bookmarks.updatefromremote(ui, repo, other, source)
4735 if checkout:
4742 if checkout:
4736 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4743 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4737 repo._subtoppath = source
4744 repo._subtoppath = source
4738 try:
4745 try:
4739 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4746 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4740
4747
4741 finally:
4748 finally:
4742 del repo._subtoppath
4749 del repo._subtoppath
4743
4750
4744 # update specified bookmarks
4751 # update specified bookmarks
4745 if opts.get('bookmark'):
4752 if opts.get('bookmark'):
4746 marks = repo._bookmarks
4753 marks = repo._bookmarks
4747 for b in opts['bookmark']:
4754 for b in opts['bookmark']:
4748 # explicit pull overrides local bookmark if any
4755 # explicit pull overrides local bookmark if any
4749 ui.status(_("importing bookmark %s\n") % b)
4756 ui.status(_("importing bookmark %s\n") % b)
4750 marks[b] = repo[rb[b]].node()
4757 marks[b] = repo[rb[b]].node()
4751 marks.write()
4758 marks.write()
4752
4759
4753 return ret
4760 return ret
4754
4761
4755 @command('^push',
4762 @command('^push',
4756 [('f', 'force', None, _('force push')),
4763 [('f', 'force', None, _('force push')),
4757 ('r', 'rev', [],
4764 ('r', 'rev', [],
4758 _('a changeset intended to be included in the destination'),
4765 _('a changeset intended to be included in the destination'),
4759 _('REV')),
4766 _('REV')),
4760 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4767 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4761 ('b', 'branch', [],
4768 ('b', 'branch', [],
4762 _('a specific branch you would like to push'), _('BRANCH')),
4769 _('a specific branch you would like to push'), _('BRANCH')),
4763 ('', 'new-branch', False, _('allow pushing a new branch')),
4770 ('', 'new-branch', False, _('allow pushing a new branch')),
4764 ] + remoteopts,
4771 ] + remoteopts,
4765 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4772 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4766 def push(ui, repo, dest=None, **opts):
4773 def push(ui, repo, dest=None, **opts):
4767 """push changes to the specified destination
4774 """push changes to the specified destination
4768
4775
4769 Push changesets from the local repository to the specified
4776 Push changesets from the local repository to the specified
4770 destination.
4777 destination.
4771
4778
4772 This operation is symmetrical to pull: it is identical to a pull
4779 This operation is symmetrical to pull: it is identical to a pull
4773 in the destination repository from the current one.
4780 in the destination repository from the current one.
4774
4781
4775 By default, push will not allow creation of new heads at the
4782 By default, push will not allow creation of new heads at the
4776 destination, since multiple heads would make it unclear which head
4783 destination, since multiple heads would make it unclear which head
4777 to use. In this situation, it is recommended to pull and merge
4784 to use. In this situation, it is recommended to pull and merge
4778 before pushing.
4785 before pushing.
4779
4786
4780 Use --new-branch if you want to allow push to create a new named
4787 Use --new-branch if you want to allow push to create a new named
4781 branch that is not present at the destination. This allows you to
4788 branch that is not present at the destination. This allows you to
4782 only create a new branch without forcing other changes.
4789 only create a new branch without forcing other changes.
4783
4790
4784 Use -f/--force to override the default behavior and push all
4791 Use -f/--force to override the default behavior and push all
4785 changesets on all branches.
4792 changesets on all branches.
4786
4793
4787 If -r/--rev is used, the specified revision and all its ancestors
4794 If -r/--rev is used, the specified revision and all its ancestors
4788 will be pushed to the remote repository.
4795 will be pushed to the remote repository.
4789
4796
4790 If -B/--bookmark is used, the specified bookmarked revision, its
4797 If -B/--bookmark is used, the specified bookmarked revision, its
4791 ancestors, and the bookmark will be pushed to the remote
4798 ancestors, and the bookmark will be pushed to the remote
4792 repository.
4799 repository.
4793
4800
4794 Please see :hg:`help urls` for important details about ``ssh://``
4801 Please see :hg:`help urls` for important details about ``ssh://``
4795 URLs. If DESTINATION is omitted, a default path will be used.
4802 URLs. If DESTINATION is omitted, a default path will be used.
4796
4803
4797 Returns 0 if push was successful, 1 if nothing to push.
4804 Returns 0 if push was successful, 1 if nothing to push.
4798 """
4805 """
4799
4806
4800 if opts.get('bookmark'):
4807 if opts.get('bookmark'):
4801 for b in opts['bookmark']:
4808 for b in opts['bookmark']:
4802 # translate -B options to -r so changesets get pushed
4809 # translate -B options to -r so changesets get pushed
4803 if b in repo._bookmarks:
4810 if b in repo._bookmarks:
4804 opts.setdefault('rev', []).append(b)
4811 opts.setdefault('rev', []).append(b)
4805 else:
4812 else:
4806 # if we try to push a deleted bookmark, translate it to null
4813 # if we try to push a deleted bookmark, translate it to null
4807 # this lets simultaneous -r, -b options continue working
4814 # this lets simultaneous -r, -b options continue working
4808 opts.setdefault('rev', []).append("null")
4815 opts.setdefault('rev', []).append("null")
4809
4816
4810 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4817 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4811 dest, branches = hg.parseurl(dest, opts.get('branch'))
4818 dest, branches = hg.parseurl(dest, opts.get('branch'))
4812 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4819 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4813 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4820 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4814 other = hg.peer(repo, opts, dest)
4821 other = hg.peer(repo, opts, dest)
4815 if revs:
4822 if revs:
4816 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4823 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4817
4824
4818 repo._subtoppath = dest
4825 repo._subtoppath = dest
4819 try:
4826 try:
4820 # push subrepos depth-first for coherent ordering
4827 # push subrepos depth-first for coherent ordering
4821 c = repo['']
4828 c = repo['']
4822 subs = c.substate # only repos that are committed
4829 subs = c.substate # only repos that are committed
4823 for s in sorted(subs):
4830 for s in sorted(subs):
4824 if c.sub(s).push(opts) == 0:
4831 if c.sub(s).push(opts) == 0:
4825 return False
4832 return False
4826 finally:
4833 finally:
4827 del repo._subtoppath
4834 del repo._subtoppath
4828 result = repo.push(other, opts.get('force'), revs=revs,
4835 result = repo.push(other, opts.get('force'), revs=revs,
4829 newbranch=opts.get('new_branch'))
4836 newbranch=opts.get('new_branch'))
4830
4837
4831 result = not result
4838 result = not result
4832
4839
4833 if opts.get('bookmark'):
4840 if opts.get('bookmark'):
4834 rb = other.listkeys('bookmarks')
4841 rb = other.listkeys('bookmarks')
4835 for b in opts['bookmark']:
4842 for b in opts['bookmark']:
4836 # explicit push overrides remote bookmark if any
4843 # explicit push overrides remote bookmark if any
4837 if b in repo._bookmarks:
4844 if b in repo._bookmarks:
4838 ui.status(_("exporting bookmark %s\n") % b)
4845 ui.status(_("exporting bookmark %s\n") % b)
4839 new = repo[b].hex()
4846 new = repo[b].hex()
4840 elif b in rb:
4847 elif b in rb:
4841 ui.status(_("deleting remote bookmark %s\n") % b)
4848 ui.status(_("deleting remote bookmark %s\n") % b)
4842 new = '' # delete
4849 new = '' # delete
4843 else:
4850 else:
4844 ui.warn(_('bookmark %s does not exist on the local '
4851 ui.warn(_('bookmark %s does not exist on the local '
4845 'or remote repository!\n') % b)
4852 'or remote repository!\n') % b)
4846 return 2
4853 return 2
4847 old = rb.get(b, '')
4854 old = rb.get(b, '')
4848 r = other.pushkey('bookmarks', b, old, new)
4855 r = other.pushkey('bookmarks', b, old, new)
4849 if not r:
4856 if not r:
4850 ui.warn(_('updating bookmark %s failed!\n') % b)
4857 ui.warn(_('updating bookmark %s failed!\n') % b)
4851 if not result:
4858 if not result:
4852 result = 2
4859 result = 2
4853
4860
4854 return result
4861 return result
4855
4862
4856 @command('recover', [])
4863 @command('recover', [])
4857 def recover(ui, repo):
4864 def recover(ui, repo):
4858 """roll back an interrupted transaction
4865 """roll back an interrupted transaction
4859
4866
4860 Recover from an interrupted commit or pull.
4867 Recover from an interrupted commit or pull.
4861
4868
4862 This command tries to fix the repository status after an
4869 This command tries to fix the repository status after an
4863 interrupted operation. It should only be necessary when Mercurial
4870 interrupted operation. It should only be necessary when Mercurial
4864 suggests it.
4871 suggests it.
4865
4872
4866 Returns 0 if successful, 1 if nothing to recover or verify fails.
4873 Returns 0 if successful, 1 if nothing to recover or verify fails.
4867 """
4874 """
4868 if repo.recover():
4875 if repo.recover():
4869 return hg.verify(repo)
4876 return hg.verify(repo)
4870 return 1
4877 return 1
4871
4878
4872 @command('^remove|rm',
4879 @command('^remove|rm',
4873 [('A', 'after', None, _('record delete for missing files')),
4880 [('A', 'after', None, _('record delete for missing files')),
4874 ('f', 'force', None,
4881 ('f', 'force', None,
4875 _('remove (and delete) file even if added or modified')),
4882 _('remove (and delete) file even if added or modified')),
4876 ] + walkopts,
4883 ] + walkopts,
4877 _('[OPTION]... FILE...'))
4884 _('[OPTION]... FILE...'))
4878 def remove(ui, repo, *pats, **opts):
4885 def remove(ui, repo, *pats, **opts):
4879 """remove the specified files on the next commit
4886 """remove the specified files on the next commit
4880
4887
4881 Schedule the indicated files for removal from the current branch.
4888 Schedule the indicated files for removal from the current branch.
4882
4889
4883 This command schedules the files to be removed at the next commit.
4890 This command schedules the files to be removed at the next commit.
4884 To undo a remove before that, see :hg:`revert`. To undo added
4891 To undo a remove before that, see :hg:`revert`. To undo added
4885 files, see :hg:`forget`.
4892 files, see :hg:`forget`.
4886
4893
4887 .. container:: verbose
4894 .. container:: verbose
4888
4895
4889 -A/--after can be used to remove only files that have already
4896 -A/--after can be used to remove only files that have already
4890 been deleted, -f/--force can be used to force deletion, and -Af
4897 been deleted, -f/--force can be used to force deletion, and -Af
4891 can be used to remove files from the next revision without
4898 can be used to remove files from the next revision without
4892 deleting them from the working directory.
4899 deleting them from the working directory.
4893
4900
4894 The following table details the behavior of remove for different
4901 The following table details the behavior of remove for different
4895 file states (columns) and option combinations (rows). The file
4902 file states (columns) and option combinations (rows). The file
4896 states are Added [A], Clean [C], Modified [M] and Missing [!]
4903 states are Added [A], Clean [C], Modified [M] and Missing [!]
4897 (as reported by :hg:`status`). The actions are Warn, Remove
4904 (as reported by :hg:`status`). The actions are Warn, Remove
4898 (from branch) and Delete (from disk):
4905 (from branch) and Delete (from disk):
4899
4906
4900 ======= == == == ==
4907 ======= == == == ==
4901 A C M !
4908 A C M !
4902 ======= == == == ==
4909 ======= == == == ==
4903 none W RD W R
4910 none W RD W R
4904 -f R RD RD R
4911 -f R RD RD R
4905 -A W W W R
4912 -A W W W R
4906 -Af R R R R
4913 -Af R R R R
4907 ======= == == == ==
4914 ======= == == == ==
4908
4915
4909 Note that remove never deletes files in Added [A] state from the
4916 Note that remove never deletes files in Added [A] state from the
4910 working directory, not even if option --force is specified.
4917 working directory, not even if option --force is specified.
4911
4918
4912 Returns 0 on success, 1 if any warnings encountered.
4919 Returns 0 on success, 1 if any warnings encountered.
4913 """
4920 """
4914
4921
4915 ret = 0
4922 ret = 0
4916 after, force = opts.get('after'), opts.get('force')
4923 after, force = opts.get('after'), opts.get('force')
4917 if not pats and not after:
4924 if not pats and not after:
4918 raise util.Abort(_('no files specified'))
4925 raise util.Abort(_('no files specified'))
4919
4926
4920 m = scmutil.match(repo[None], pats, opts)
4927 m = scmutil.match(repo[None], pats, opts)
4921 s = repo.status(match=m, clean=True)
4928 s = repo.status(match=m, clean=True)
4922 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4929 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4923
4930
4924 # warn about failure to delete explicit files/dirs
4931 # warn about failure to delete explicit files/dirs
4925 wctx = repo[None]
4932 wctx = repo[None]
4926 for f in m.files():
4933 for f in m.files():
4927 if f in repo.dirstate or f in wctx.dirs():
4934 if f in repo.dirstate or f in wctx.dirs():
4928 continue
4935 continue
4929 if os.path.exists(m.rel(f)):
4936 if os.path.exists(m.rel(f)):
4930 if os.path.isdir(m.rel(f)):
4937 if os.path.isdir(m.rel(f)):
4931 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4938 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4932 else:
4939 else:
4933 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4940 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4934 # missing files will generate a warning elsewhere
4941 # missing files will generate a warning elsewhere
4935 ret = 1
4942 ret = 1
4936
4943
4937 if force:
4944 if force:
4938 list = modified + deleted + clean + added
4945 list = modified + deleted + clean + added
4939 elif after:
4946 elif after:
4940 list = deleted
4947 list = deleted
4941 for f in modified + added + clean:
4948 for f in modified + added + clean:
4942 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4949 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4943 ret = 1
4950 ret = 1
4944 else:
4951 else:
4945 list = deleted + clean
4952 list = deleted + clean
4946 for f in modified:
4953 for f in modified:
4947 ui.warn(_('not removing %s: file is modified (use -f'
4954 ui.warn(_('not removing %s: file is modified (use -f'
4948 ' to force removal)\n') % m.rel(f))
4955 ' to force removal)\n') % m.rel(f))
4949 ret = 1
4956 ret = 1
4950 for f in added:
4957 for f in added:
4951 ui.warn(_('not removing %s: file has been marked for add'
4958 ui.warn(_('not removing %s: file has been marked for add'
4952 ' (use forget to undo)\n') % m.rel(f))
4959 ' (use forget to undo)\n') % m.rel(f))
4953 ret = 1
4960 ret = 1
4954
4961
4955 for f in sorted(list):
4962 for f in sorted(list):
4956 if ui.verbose or not m.exact(f):
4963 if ui.verbose or not m.exact(f):
4957 ui.status(_('removing %s\n') % m.rel(f))
4964 ui.status(_('removing %s\n') % m.rel(f))
4958
4965
4959 wlock = repo.wlock()
4966 wlock = repo.wlock()
4960 try:
4967 try:
4961 if not after:
4968 if not after:
4962 for f in list:
4969 for f in list:
4963 if f in added:
4970 if f in added:
4964 continue # we never unlink added files on remove
4971 continue # we never unlink added files on remove
4965 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4972 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4966 repo[None].forget(list)
4973 repo[None].forget(list)
4967 finally:
4974 finally:
4968 wlock.release()
4975 wlock.release()
4969
4976
4970 return ret
4977 return ret
4971
4978
4972 @command('rename|move|mv',
4979 @command('rename|move|mv',
4973 [('A', 'after', None, _('record a rename that has already occurred')),
4980 [('A', 'after', None, _('record a rename that has already occurred')),
4974 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4981 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4975 ] + walkopts + dryrunopts,
4982 ] + walkopts + dryrunopts,
4976 _('[OPTION]... SOURCE... DEST'))
4983 _('[OPTION]... SOURCE... DEST'))
4977 def rename(ui, repo, *pats, **opts):
4984 def rename(ui, repo, *pats, **opts):
4978 """rename files; equivalent of copy + remove
4985 """rename files; equivalent of copy + remove
4979
4986
4980 Mark dest as copies of sources; mark sources for deletion. If dest
4987 Mark dest as copies of sources; mark sources for deletion. If dest
4981 is a directory, copies are put in that directory. If dest is a
4988 is a directory, copies are put in that directory. If dest is a
4982 file, there can only be one source.
4989 file, there can only be one source.
4983
4990
4984 By default, this command copies the contents of files as they
4991 By default, this command copies the contents of files as they
4985 exist in the working directory. If invoked with -A/--after, the
4992 exist in the working directory. If invoked with -A/--after, the
4986 operation is recorded, but no copying is performed.
4993 operation is recorded, but no copying is performed.
4987
4994
4988 This command takes effect at the next commit. To undo a rename
4995 This command takes effect at the next commit. To undo a rename
4989 before that, see :hg:`revert`.
4996 before that, see :hg:`revert`.
4990
4997
4991 Returns 0 on success, 1 if errors are encountered.
4998 Returns 0 on success, 1 if errors are encountered.
4992 """
4999 """
4993 wlock = repo.wlock(False)
5000 wlock = repo.wlock(False)
4994 try:
5001 try:
4995 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5002 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4996 finally:
5003 finally:
4997 wlock.release()
5004 wlock.release()
4998
5005
4999 @command('resolve',
5006 @command('resolve',
5000 [('a', 'all', None, _('select all unresolved files')),
5007 [('a', 'all', None, _('select all unresolved files')),
5001 ('l', 'list', None, _('list state of files needing merge')),
5008 ('l', 'list', None, _('list state of files needing merge')),
5002 ('m', 'mark', None, _('mark files as resolved')),
5009 ('m', 'mark', None, _('mark files as resolved')),
5003 ('u', 'unmark', None, _('mark files as unresolved')),
5010 ('u', 'unmark', None, _('mark files as unresolved')),
5004 ('n', 'no-status', None, _('hide status prefix'))]
5011 ('n', 'no-status', None, _('hide status prefix'))]
5005 + mergetoolopts + walkopts,
5012 + mergetoolopts + walkopts,
5006 _('[OPTION]... [FILE]...'))
5013 _('[OPTION]... [FILE]...'))
5007 def resolve(ui, repo, *pats, **opts):
5014 def resolve(ui, repo, *pats, **opts):
5008 """redo merges or set/view the merge status of files
5015 """redo merges or set/view the merge status of files
5009
5016
5010 Merges with unresolved conflicts are often the result of
5017 Merges with unresolved conflicts are often the result of
5011 non-interactive merging using the ``internal:merge`` configuration
5018 non-interactive merging using the ``internal:merge`` configuration
5012 setting, or a command-line merge tool like ``diff3``. The resolve
5019 setting, or a command-line merge tool like ``diff3``. The resolve
5013 command is used to manage the files involved in a merge, after
5020 command is used to manage the files involved in a merge, after
5014 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5021 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5015 working directory must have two parents). See :hg:`help
5022 working directory must have two parents). See :hg:`help
5016 merge-tools` for information on configuring merge tools.
5023 merge-tools` for information on configuring merge tools.
5017
5024
5018 The resolve command can be used in the following ways:
5025 The resolve command can be used in the following ways:
5019
5026
5020 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5027 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5021 files, discarding any previous merge attempts. Re-merging is not
5028 files, discarding any previous merge attempts. Re-merging is not
5022 performed for files already marked as resolved. Use ``--all/-a``
5029 performed for files already marked as resolved. Use ``--all/-a``
5023 to select all unresolved files. ``--tool`` can be used to specify
5030 to select all unresolved files. ``--tool`` can be used to specify
5024 the merge tool used for the given files. It overrides the HGMERGE
5031 the merge tool used for the given files. It overrides the HGMERGE
5025 environment variable and your configuration files. Previous file
5032 environment variable and your configuration files. Previous file
5026 contents are saved with a ``.orig`` suffix.
5033 contents are saved with a ``.orig`` suffix.
5027
5034
5028 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5035 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5029 (e.g. after having manually fixed-up the files). The default is
5036 (e.g. after having manually fixed-up the files). The default is
5030 to mark all unresolved files.
5037 to mark all unresolved files.
5031
5038
5032 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5039 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5033 default is to mark all resolved files.
5040 default is to mark all resolved files.
5034
5041
5035 - :hg:`resolve -l`: list files which had or still have conflicts.
5042 - :hg:`resolve -l`: list files which had or still have conflicts.
5036 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5043 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5037
5044
5038 Note that Mercurial will not let you commit files with unresolved
5045 Note that Mercurial will not let you commit files with unresolved
5039 merge conflicts. You must use :hg:`resolve -m ...` before you can
5046 merge conflicts. You must use :hg:`resolve -m ...` before you can
5040 commit after a conflicting merge.
5047 commit after a conflicting merge.
5041
5048
5042 Returns 0 on success, 1 if any files fail a resolve attempt.
5049 Returns 0 on success, 1 if any files fail a resolve attempt.
5043 """
5050 """
5044
5051
5045 all, mark, unmark, show, nostatus = \
5052 all, mark, unmark, show, nostatus = \
5046 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5053 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5047
5054
5048 if (show and (mark or unmark)) or (mark and unmark):
5055 if (show and (mark or unmark)) or (mark and unmark):
5049 raise util.Abort(_("too many options specified"))
5056 raise util.Abort(_("too many options specified"))
5050 if pats and all:
5057 if pats and all:
5051 raise util.Abort(_("can't specify --all and patterns"))
5058 raise util.Abort(_("can't specify --all and patterns"))
5052 if not (all or pats or show or mark or unmark):
5059 if not (all or pats or show or mark or unmark):
5053 raise util.Abort(_('no files or directories specified; '
5060 raise util.Abort(_('no files or directories specified; '
5054 'use --all to remerge all files'))
5061 'use --all to remerge all files'))
5055
5062
5056 ms = mergemod.mergestate(repo)
5063 ms = mergemod.mergestate(repo)
5057 m = scmutil.match(repo[None], pats, opts)
5064 m = scmutil.match(repo[None], pats, opts)
5058 ret = 0
5065 ret = 0
5059
5066
5060 for f in ms:
5067 for f in ms:
5061 if m(f):
5068 if m(f):
5062 if show:
5069 if show:
5063 if nostatus:
5070 if nostatus:
5064 ui.write("%s\n" % f)
5071 ui.write("%s\n" % f)
5065 else:
5072 else:
5066 ui.write("%s %s\n" % (ms[f].upper(), f),
5073 ui.write("%s %s\n" % (ms[f].upper(), f),
5067 label='resolve.' +
5074 label='resolve.' +
5068 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5075 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5069 elif mark:
5076 elif mark:
5070 ms.mark(f, "r")
5077 ms.mark(f, "r")
5071 elif unmark:
5078 elif unmark:
5072 ms.mark(f, "u")
5079 ms.mark(f, "u")
5073 else:
5080 else:
5074 wctx = repo[None]
5081 wctx = repo[None]
5075 mctx = wctx.parents()[-1]
5082 mctx = wctx.parents()[-1]
5076
5083
5077 # backup pre-resolve (merge uses .orig for its own purposes)
5084 # backup pre-resolve (merge uses .orig for its own purposes)
5078 a = repo.wjoin(f)
5085 a = repo.wjoin(f)
5079 util.copyfile(a, a + ".resolve")
5086 util.copyfile(a, a + ".resolve")
5080
5087
5081 try:
5088 try:
5082 # resolve file
5089 # resolve file
5083 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5090 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5084 if ms.resolve(f, wctx, mctx):
5091 if ms.resolve(f, wctx, mctx):
5085 ret = 1
5092 ret = 1
5086 finally:
5093 finally:
5087 ui.setconfig('ui', 'forcemerge', '')
5094 ui.setconfig('ui', 'forcemerge', '')
5088 ms.commit()
5095 ms.commit()
5089
5096
5090 # replace filemerge's .orig file with our resolve file
5097 # replace filemerge's .orig file with our resolve file
5091 util.rename(a + ".resolve", a + ".orig")
5098 util.rename(a + ".resolve", a + ".orig")
5092
5099
5093 ms.commit()
5100 ms.commit()
5094 return ret
5101 return ret
5095
5102
5096 @command('revert',
5103 @command('revert',
5097 [('a', 'all', None, _('revert all changes when no arguments given')),
5104 [('a', 'all', None, _('revert all changes when no arguments given')),
5098 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5105 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5099 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5106 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5100 ('C', 'no-backup', None, _('do not save backup copies of files')),
5107 ('C', 'no-backup', None, _('do not save backup copies of files')),
5101 ] + walkopts + dryrunopts,
5108 ] + walkopts + dryrunopts,
5102 _('[OPTION]... [-r REV] [NAME]...'))
5109 _('[OPTION]... [-r REV] [NAME]...'))
5103 def revert(ui, repo, *pats, **opts):
5110 def revert(ui, repo, *pats, **opts):
5104 """restore files to their checkout state
5111 """restore files to their checkout state
5105
5112
5106 .. note::
5113 .. note::
5107
5114
5108 To check out earlier revisions, you should use :hg:`update REV`.
5115 To check out earlier revisions, you should use :hg:`update REV`.
5109 To cancel an uncommitted merge (and lose your changes), use
5116 To cancel an uncommitted merge (and lose your changes), use
5110 :hg:`update --clean .`.
5117 :hg:`update --clean .`.
5111
5118
5112 With no revision specified, revert the specified files or directories
5119 With no revision specified, revert the specified files or directories
5113 to the contents they had in the parent of the working directory.
5120 to the contents they had in the parent of the working directory.
5114 This restores the contents of files to an unmodified
5121 This restores the contents of files to an unmodified
5115 state and unschedules adds, removes, copies, and renames. If the
5122 state and unschedules adds, removes, copies, and renames. If the
5116 working directory has two parents, you must explicitly specify a
5123 working directory has two parents, you must explicitly specify a
5117 revision.
5124 revision.
5118
5125
5119 Using the -r/--rev or -d/--date options, revert the given files or
5126 Using the -r/--rev or -d/--date options, revert the given files or
5120 directories to their states as of a specific revision. Because
5127 directories to their states as of a specific revision. Because
5121 revert does not change the working directory parents, this will
5128 revert does not change the working directory parents, this will
5122 cause these files to appear modified. This can be helpful to "back
5129 cause these files to appear modified. This can be helpful to "back
5123 out" some or all of an earlier change. See :hg:`backout` for a
5130 out" some or all of an earlier change. See :hg:`backout` for a
5124 related method.
5131 related method.
5125
5132
5126 Modified files are saved with a .orig suffix before reverting.
5133 Modified files are saved with a .orig suffix before reverting.
5127 To disable these backups, use --no-backup.
5134 To disable these backups, use --no-backup.
5128
5135
5129 See :hg:`help dates` for a list of formats valid for -d/--date.
5136 See :hg:`help dates` for a list of formats valid for -d/--date.
5130
5137
5131 Returns 0 on success.
5138 Returns 0 on success.
5132 """
5139 """
5133
5140
5134 if opts.get("date"):
5141 if opts.get("date"):
5135 if opts.get("rev"):
5142 if opts.get("rev"):
5136 raise util.Abort(_("you can't specify a revision and a date"))
5143 raise util.Abort(_("you can't specify a revision and a date"))
5137 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5144 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5138
5145
5139 parent, p2 = repo.dirstate.parents()
5146 parent, p2 = repo.dirstate.parents()
5140 if not opts.get('rev') and p2 != nullid:
5147 if not opts.get('rev') and p2 != nullid:
5141 # revert after merge is a trap for new users (issue2915)
5148 # revert after merge is a trap for new users (issue2915)
5142 raise util.Abort(_('uncommitted merge with no revision specified'),
5149 raise util.Abort(_('uncommitted merge with no revision specified'),
5143 hint=_('use "hg update" or see "hg help revert"'))
5150 hint=_('use "hg update" or see "hg help revert"'))
5144
5151
5145 ctx = scmutil.revsingle(repo, opts.get('rev'))
5152 ctx = scmutil.revsingle(repo, opts.get('rev'))
5146
5153
5147 if not pats and not opts.get('all'):
5154 if not pats and not opts.get('all'):
5148 msg = _("no files or directories specified")
5155 msg = _("no files or directories specified")
5149 if p2 != nullid:
5156 if p2 != nullid:
5150 hint = _("uncommitted merge, use --all to discard all changes,"
5157 hint = _("uncommitted merge, use --all to discard all changes,"
5151 " or 'hg update -C .' to abort the merge")
5158 " or 'hg update -C .' to abort the merge")
5152 raise util.Abort(msg, hint=hint)
5159 raise util.Abort(msg, hint=hint)
5153 dirty = util.any(repo.status())
5160 dirty = util.any(repo.status())
5154 node = ctx.node()
5161 node = ctx.node()
5155 if node != parent:
5162 if node != parent:
5156 if dirty:
5163 if dirty:
5157 hint = _("uncommitted changes, use --all to discard all"
5164 hint = _("uncommitted changes, use --all to discard all"
5158 " changes, or 'hg update %s' to update") % ctx.rev()
5165 " changes, or 'hg update %s' to update") % ctx.rev()
5159 else:
5166 else:
5160 hint = _("use --all to revert all files,"
5167 hint = _("use --all to revert all files,"
5161 " or 'hg update %s' to update") % ctx.rev()
5168 " or 'hg update %s' to update") % ctx.rev()
5162 elif dirty:
5169 elif dirty:
5163 hint = _("uncommitted changes, use --all to discard all changes")
5170 hint = _("uncommitted changes, use --all to discard all changes")
5164 else:
5171 else:
5165 hint = _("use --all to revert all files")
5172 hint = _("use --all to revert all files")
5166 raise util.Abort(msg, hint=hint)
5173 raise util.Abort(msg, hint=hint)
5167
5174
5168 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5175 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5169
5176
5170 @command('rollback', dryrunopts +
5177 @command('rollback', dryrunopts +
5171 [('f', 'force', False, _('ignore safety measures'))])
5178 [('f', 'force', False, _('ignore safety measures'))])
5172 def rollback(ui, repo, **opts):
5179 def rollback(ui, repo, **opts):
5173 """roll back the last transaction (dangerous)
5180 """roll back the last transaction (dangerous)
5174
5181
5175 This command should be used with care. There is only one level of
5182 This command should be used with care. There is only one level of
5176 rollback, and there is no way to undo a rollback. It will also
5183 rollback, and there is no way to undo a rollback. It will also
5177 restore the dirstate at the time of the last transaction, losing
5184 restore the dirstate at the time of the last transaction, losing
5178 any dirstate changes since that time. This command does not alter
5185 any dirstate changes since that time. This command does not alter
5179 the working directory.
5186 the working directory.
5180
5187
5181 Transactions are used to encapsulate the effects of all commands
5188 Transactions are used to encapsulate the effects of all commands
5182 that create new changesets or propagate existing changesets into a
5189 that create new changesets or propagate existing changesets into a
5183 repository.
5190 repository.
5184
5191
5185 .. container:: verbose
5192 .. container:: verbose
5186
5193
5187 For example, the following commands are transactional, and their
5194 For example, the following commands are transactional, and their
5188 effects can be rolled back:
5195 effects can be rolled back:
5189
5196
5190 - commit
5197 - commit
5191 - import
5198 - import
5192 - pull
5199 - pull
5193 - push (with this repository as the destination)
5200 - push (with this repository as the destination)
5194 - unbundle
5201 - unbundle
5195
5202
5196 To avoid permanent data loss, rollback will refuse to rollback a
5203 To avoid permanent data loss, rollback will refuse to rollback a
5197 commit transaction if it isn't checked out. Use --force to
5204 commit transaction if it isn't checked out. Use --force to
5198 override this protection.
5205 override this protection.
5199
5206
5200 This command is not intended for use on public repositories. Once
5207 This command is not intended for use on public repositories. Once
5201 changes are visible for pull by other users, rolling a transaction
5208 changes are visible for pull by other users, rolling a transaction
5202 back locally is ineffective (someone else may already have pulled
5209 back locally is ineffective (someone else may already have pulled
5203 the changes). Furthermore, a race is possible with readers of the
5210 the changes). Furthermore, a race is possible with readers of the
5204 repository; for example an in-progress pull from the repository
5211 repository; for example an in-progress pull from the repository
5205 may fail if a rollback is performed.
5212 may fail if a rollback is performed.
5206
5213
5207 Returns 0 on success, 1 if no rollback data is available.
5214 Returns 0 on success, 1 if no rollback data is available.
5208 """
5215 """
5209 return repo.rollback(dryrun=opts.get('dry_run'),
5216 return repo.rollback(dryrun=opts.get('dry_run'),
5210 force=opts.get('force'))
5217 force=opts.get('force'))
5211
5218
5212 @command('root', [])
5219 @command('root', [])
5213 def root(ui, repo):
5220 def root(ui, repo):
5214 """print the root (top) of the current working directory
5221 """print the root (top) of the current working directory
5215
5222
5216 Print the root directory of the current repository.
5223 Print the root directory of the current repository.
5217
5224
5218 Returns 0 on success.
5225 Returns 0 on success.
5219 """
5226 """
5220 ui.write(repo.root + "\n")
5227 ui.write(repo.root + "\n")
5221
5228
5222 @command('^serve',
5229 @command('^serve',
5223 [('A', 'accesslog', '', _('name of access log file to write to'),
5230 [('A', 'accesslog', '', _('name of access log file to write to'),
5224 _('FILE')),
5231 _('FILE')),
5225 ('d', 'daemon', None, _('run server in background')),
5232 ('d', 'daemon', None, _('run server in background')),
5226 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5233 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5227 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5234 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5228 # use string type, then we can check if something was passed
5235 # use string type, then we can check if something was passed
5229 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5236 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5230 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5237 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5231 _('ADDR')),
5238 _('ADDR')),
5232 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5239 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5233 _('PREFIX')),
5240 _('PREFIX')),
5234 ('n', 'name', '',
5241 ('n', 'name', '',
5235 _('name to show in web pages (default: working directory)'), _('NAME')),
5242 _('name to show in web pages (default: working directory)'), _('NAME')),
5236 ('', 'web-conf', '',
5243 ('', 'web-conf', '',
5237 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5244 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5238 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5245 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5239 _('FILE')),
5246 _('FILE')),
5240 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5247 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5241 ('', 'stdio', None, _('for remote clients')),
5248 ('', 'stdio', None, _('for remote clients')),
5242 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5249 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5243 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5250 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5244 ('', 'style', '', _('template style to use'), _('STYLE')),
5251 ('', 'style', '', _('template style to use'), _('STYLE')),
5245 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5252 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5246 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5253 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5247 _('[OPTION]...'))
5254 _('[OPTION]...'))
5248 def serve(ui, repo, **opts):
5255 def serve(ui, repo, **opts):
5249 """start stand-alone webserver
5256 """start stand-alone webserver
5250
5257
5251 Start a local HTTP repository browser and pull server. You can use
5258 Start a local HTTP repository browser and pull server. You can use
5252 this for ad-hoc sharing and browsing of repositories. It is
5259 this for ad-hoc sharing and browsing of repositories. It is
5253 recommended to use a real web server to serve a repository for
5260 recommended to use a real web server to serve a repository for
5254 longer periods of time.
5261 longer periods of time.
5255
5262
5256 Please note that the server does not implement access control.
5263 Please note that the server does not implement access control.
5257 This means that, by default, anybody can read from the server and
5264 This means that, by default, anybody can read from the server and
5258 nobody can write to it by default. Set the ``web.allow_push``
5265 nobody can write to it by default. Set the ``web.allow_push``
5259 option to ``*`` to allow everybody to push to the server. You
5266 option to ``*`` to allow everybody to push to the server. You
5260 should use a real web server if you need to authenticate users.
5267 should use a real web server if you need to authenticate users.
5261
5268
5262 By default, the server logs accesses to stdout and errors to
5269 By default, the server logs accesses to stdout and errors to
5263 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5270 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5264 files.
5271 files.
5265
5272
5266 To have the server choose a free port number to listen on, specify
5273 To have the server choose a free port number to listen on, specify
5267 a port number of 0; in this case, the server will print the port
5274 a port number of 0; in this case, the server will print the port
5268 number it uses.
5275 number it uses.
5269
5276
5270 Returns 0 on success.
5277 Returns 0 on success.
5271 """
5278 """
5272
5279
5273 if opts["stdio"] and opts["cmdserver"]:
5280 if opts["stdio"] and opts["cmdserver"]:
5274 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5281 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5275
5282
5276 def checkrepo():
5283 def checkrepo():
5277 if repo is None:
5284 if repo is None:
5278 raise error.RepoError(_("there is no Mercurial repository here"
5285 raise error.RepoError(_("there is no Mercurial repository here"
5279 " (.hg not found)"))
5286 " (.hg not found)"))
5280
5287
5281 if opts["stdio"]:
5288 if opts["stdio"]:
5282 checkrepo()
5289 checkrepo()
5283 s = sshserver.sshserver(ui, repo)
5290 s = sshserver.sshserver(ui, repo)
5284 s.serve_forever()
5291 s.serve_forever()
5285
5292
5286 if opts["cmdserver"]:
5293 if opts["cmdserver"]:
5287 checkrepo()
5294 checkrepo()
5288 s = commandserver.server(ui, repo, opts["cmdserver"])
5295 s = commandserver.server(ui, repo, opts["cmdserver"])
5289 return s.serve()
5296 return s.serve()
5290
5297
5291 # this way we can check if something was given in the command-line
5298 # this way we can check if something was given in the command-line
5292 if opts.get('port'):
5299 if opts.get('port'):
5293 opts['port'] = util.getport(opts.get('port'))
5300 opts['port'] = util.getport(opts.get('port'))
5294
5301
5295 baseui = repo and repo.baseui or ui
5302 baseui = repo and repo.baseui or ui
5296 optlist = ("name templates style address port prefix ipv6"
5303 optlist = ("name templates style address port prefix ipv6"
5297 " accesslog errorlog certificate encoding")
5304 " accesslog errorlog certificate encoding")
5298 for o in optlist.split():
5305 for o in optlist.split():
5299 val = opts.get(o, '')
5306 val = opts.get(o, '')
5300 if val in (None, ''): # should check against default options instead
5307 if val in (None, ''): # should check against default options instead
5301 continue
5308 continue
5302 baseui.setconfig("web", o, val)
5309 baseui.setconfig("web", o, val)
5303 if repo and repo.ui != baseui:
5310 if repo and repo.ui != baseui:
5304 repo.ui.setconfig("web", o, val)
5311 repo.ui.setconfig("web", o, val)
5305
5312
5306 o = opts.get('web_conf') or opts.get('webdir_conf')
5313 o = opts.get('web_conf') or opts.get('webdir_conf')
5307 if not o:
5314 if not o:
5308 if not repo:
5315 if not repo:
5309 raise error.RepoError(_("there is no Mercurial repository"
5316 raise error.RepoError(_("there is no Mercurial repository"
5310 " here (.hg not found)"))
5317 " here (.hg not found)"))
5311 o = repo.root
5318 o = repo.root
5312
5319
5313 app = hgweb.hgweb(o, baseui=ui)
5320 app = hgweb.hgweb(o, baseui=ui)
5314
5321
5315 class service(object):
5322 class service(object):
5316 def init(self):
5323 def init(self):
5317 util.setsignalhandler()
5324 util.setsignalhandler()
5318 self.httpd = hgweb.server.create_server(ui, app)
5325 self.httpd = hgweb.server.create_server(ui, app)
5319
5326
5320 if opts['port'] and not ui.verbose:
5327 if opts['port'] and not ui.verbose:
5321 return
5328 return
5322
5329
5323 if self.httpd.prefix:
5330 if self.httpd.prefix:
5324 prefix = self.httpd.prefix.strip('/') + '/'
5331 prefix = self.httpd.prefix.strip('/') + '/'
5325 else:
5332 else:
5326 prefix = ''
5333 prefix = ''
5327
5334
5328 port = ':%d' % self.httpd.port
5335 port = ':%d' % self.httpd.port
5329 if port == ':80':
5336 if port == ':80':
5330 port = ''
5337 port = ''
5331
5338
5332 bindaddr = self.httpd.addr
5339 bindaddr = self.httpd.addr
5333 if bindaddr == '0.0.0.0':
5340 if bindaddr == '0.0.0.0':
5334 bindaddr = '*'
5341 bindaddr = '*'
5335 elif ':' in bindaddr: # IPv6
5342 elif ':' in bindaddr: # IPv6
5336 bindaddr = '[%s]' % bindaddr
5343 bindaddr = '[%s]' % bindaddr
5337
5344
5338 fqaddr = self.httpd.fqaddr
5345 fqaddr = self.httpd.fqaddr
5339 if ':' in fqaddr:
5346 if ':' in fqaddr:
5340 fqaddr = '[%s]' % fqaddr
5347 fqaddr = '[%s]' % fqaddr
5341 if opts['port']:
5348 if opts['port']:
5342 write = ui.status
5349 write = ui.status
5343 else:
5350 else:
5344 write = ui.write
5351 write = ui.write
5345 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5352 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5346 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5353 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5347
5354
5348 def run(self):
5355 def run(self):
5349 self.httpd.serve_forever()
5356 self.httpd.serve_forever()
5350
5357
5351 service = service()
5358 service = service()
5352
5359
5353 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5360 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5354
5361
5355 @command('showconfig|debugconfig',
5362 @command('showconfig|debugconfig',
5356 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5363 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5357 _('[-u] [NAME]...'))
5364 _('[-u] [NAME]...'))
5358 def showconfig(ui, repo, *values, **opts):
5365 def showconfig(ui, repo, *values, **opts):
5359 """show combined config settings from all hgrc files
5366 """show combined config settings from all hgrc files
5360
5367
5361 With no arguments, print names and values of all config items.
5368 With no arguments, print names and values of all config items.
5362
5369
5363 With one argument of the form section.name, print just the value
5370 With one argument of the form section.name, print just the value
5364 of that config item.
5371 of that config item.
5365
5372
5366 With multiple arguments, print names and values of all config
5373 With multiple arguments, print names and values of all config
5367 items with matching section names.
5374 items with matching section names.
5368
5375
5369 With --debug, the source (filename and line number) is printed
5376 With --debug, the source (filename and line number) is printed
5370 for each config item.
5377 for each config item.
5371
5378
5372 Returns 0 on success.
5379 Returns 0 on success.
5373 """
5380 """
5374
5381
5375 for f in scmutil.rcpath():
5382 for f in scmutil.rcpath():
5376 ui.debug('read config from: %s\n' % f)
5383 ui.debug('read config from: %s\n' % f)
5377 untrusted = bool(opts.get('untrusted'))
5384 untrusted = bool(opts.get('untrusted'))
5378 if values:
5385 if values:
5379 sections = [v for v in values if '.' not in v]
5386 sections = [v for v in values if '.' not in v]
5380 items = [v for v in values if '.' in v]
5387 items = [v for v in values if '.' in v]
5381 if len(items) > 1 or items and sections:
5388 if len(items) > 1 or items and sections:
5382 raise util.Abort(_('only one config item permitted'))
5389 raise util.Abort(_('only one config item permitted'))
5383 for section, name, value in ui.walkconfig(untrusted=untrusted):
5390 for section, name, value in ui.walkconfig(untrusted=untrusted):
5384 value = str(value).replace('\n', '\\n')
5391 value = str(value).replace('\n', '\\n')
5385 sectname = section + '.' + name
5392 sectname = section + '.' + name
5386 if values:
5393 if values:
5387 for v in values:
5394 for v in values:
5388 if v == section:
5395 if v == section:
5389 ui.debug('%s: ' %
5396 ui.debug('%s: ' %
5390 ui.configsource(section, name, untrusted))
5397 ui.configsource(section, name, untrusted))
5391 ui.write('%s=%s\n' % (sectname, value))
5398 ui.write('%s=%s\n' % (sectname, value))
5392 elif v == sectname:
5399 elif v == sectname:
5393 ui.debug('%s: ' %
5400 ui.debug('%s: ' %
5394 ui.configsource(section, name, untrusted))
5401 ui.configsource(section, name, untrusted))
5395 ui.write(value, '\n')
5402 ui.write(value, '\n')
5396 else:
5403 else:
5397 ui.debug('%s: ' %
5404 ui.debug('%s: ' %
5398 ui.configsource(section, name, untrusted))
5405 ui.configsource(section, name, untrusted))
5399 ui.write('%s=%s\n' % (sectname, value))
5406 ui.write('%s=%s\n' % (sectname, value))
5400
5407
5401 @command('^status|st',
5408 @command('^status|st',
5402 [('A', 'all', None, _('show status of all files')),
5409 [('A', 'all', None, _('show status of all files')),
5403 ('m', 'modified', None, _('show only modified files')),
5410 ('m', 'modified', None, _('show only modified files')),
5404 ('a', 'added', None, _('show only added files')),
5411 ('a', 'added', None, _('show only added files')),
5405 ('r', 'removed', None, _('show only removed files')),
5412 ('r', 'removed', None, _('show only removed files')),
5406 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5413 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5407 ('c', 'clean', None, _('show only files without changes')),
5414 ('c', 'clean', None, _('show only files without changes')),
5408 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5415 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5409 ('i', 'ignored', None, _('show only ignored files')),
5416 ('i', 'ignored', None, _('show only ignored files')),
5410 ('n', 'no-status', None, _('hide status prefix')),
5417 ('n', 'no-status', None, _('hide status prefix')),
5411 ('C', 'copies', None, _('show source of copied files')),
5418 ('C', 'copies', None, _('show source of copied files')),
5412 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5419 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5413 ('', 'rev', [], _('show difference from revision'), _('REV')),
5420 ('', 'rev', [], _('show difference from revision'), _('REV')),
5414 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5421 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5415 ] + walkopts + subrepoopts,
5422 ] + walkopts + subrepoopts,
5416 _('[OPTION]... [FILE]...'))
5423 _('[OPTION]... [FILE]...'))
5417 def status(ui, repo, *pats, **opts):
5424 def status(ui, repo, *pats, **opts):
5418 """show changed files in the working directory
5425 """show changed files in the working directory
5419
5426
5420 Show status of files in the repository. If names are given, only
5427 Show status of files in the repository. If names are given, only
5421 files that match are shown. Files that are clean or ignored or
5428 files that match are shown. Files that are clean or ignored or
5422 the source of a copy/move operation, are not listed unless
5429 the source of a copy/move operation, are not listed unless
5423 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5430 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5424 Unless options described with "show only ..." are given, the
5431 Unless options described with "show only ..." are given, the
5425 options -mardu are used.
5432 options -mardu are used.
5426
5433
5427 Option -q/--quiet hides untracked (unknown and ignored) files
5434 Option -q/--quiet hides untracked (unknown and ignored) files
5428 unless explicitly requested with -u/--unknown or -i/--ignored.
5435 unless explicitly requested with -u/--unknown or -i/--ignored.
5429
5436
5430 .. note::
5437 .. note::
5431 status may appear to disagree with diff if permissions have
5438 status may appear to disagree with diff if permissions have
5432 changed or a merge has occurred. The standard diff format does
5439 changed or a merge has occurred. The standard diff format does
5433 not report permission changes and diff only reports changes
5440 not report permission changes and diff only reports changes
5434 relative to one merge parent.
5441 relative to one merge parent.
5435
5442
5436 If one revision is given, it is used as the base revision.
5443 If one revision is given, it is used as the base revision.
5437 If two revisions are given, the differences between them are
5444 If two revisions are given, the differences between them are
5438 shown. The --change option can also be used as a shortcut to list
5445 shown. The --change option can also be used as a shortcut to list
5439 the changed files of a revision from its first parent.
5446 the changed files of a revision from its first parent.
5440
5447
5441 The codes used to show the status of files are::
5448 The codes used to show the status of files are::
5442
5449
5443 M = modified
5450 M = modified
5444 A = added
5451 A = added
5445 R = removed
5452 R = removed
5446 C = clean
5453 C = clean
5447 ! = missing (deleted by non-hg command, but still tracked)
5454 ! = missing (deleted by non-hg command, but still tracked)
5448 ? = not tracked
5455 ? = not tracked
5449 I = ignored
5456 I = ignored
5450 = origin of the previous file listed as A (added)
5457 = origin of the previous file listed as A (added)
5451
5458
5452 .. container:: verbose
5459 .. container:: verbose
5453
5460
5454 Examples:
5461 Examples:
5455
5462
5456 - show changes in the working directory relative to a
5463 - show changes in the working directory relative to a
5457 changeset::
5464 changeset::
5458
5465
5459 hg status --rev 9353
5466 hg status --rev 9353
5460
5467
5461 - show all changes including copies in an existing changeset::
5468 - show all changes including copies in an existing changeset::
5462
5469
5463 hg status --copies --change 9353
5470 hg status --copies --change 9353
5464
5471
5465 - get a NUL separated list of added files, suitable for xargs::
5472 - get a NUL separated list of added files, suitable for xargs::
5466
5473
5467 hg status -an0
5474 hg status -an0
5468
5475
5469 Returns 0 on success.
5476 Returns 0 on success.
5470 """
5477 """
5471
5478
5472 revs = opts.get('rev')
5479 revs = opts.get('rev')
5473 change = opts.get('change')
5480 change = opts.get('change')
5474
5481
5475 if revs and change:
5482 if revs and change:
5476 msg = _('cannot specify --rev and --change at the same time')
5483 msg = _('cannot specify --rev and --change at the same time')
5477 raise util.Abort(msg)
5484 raise util.Abort(msg)
5478 elif change:
5485 elif change:
5479 node2 = scmutil.revsingle(repo, change, None).node()
5486 node2 = scmutil.revsingle(repo, change, None).node()
5480 node1 = repo[node2].p1().node()
5487 node1 = repo[node2].p1().node()
5481 else:
5488 else:
5482 node1, node2 = scmutil.revpair(repo, revs)
5489 node1, node2 = scmutil.revpair(repo, revs)
5483
5490
5484 cwd = (pats and repo.getcwd()) or ''
5491 cwd = (pats and repo.getcwd()) or ''
5485 end = opts.get('print0') and '\0' or '\n'
5492 end = opts.get('print0') and '\0' or '\n'
5486 copy = {}
5493 copy = {}
5487 states = 'modified added removed deleted unknown ignored clean'.split()
5494 states = 'modified added removed deleted unknown ignored clean'.split()
5488 show = [k for k in states if opts.get(k)]
5495 show = [k for k in states if opts.get(k)]
5489 if opts.get('all'):
5496 if opts.get('all'):
5490 show += ui.quiet and (states[:4] + ['clean']) or states
5497 show += ui.quiet and (states[:4] + ['clean']) or states
5491 if not show:
5498 if not show:
5492 show = ui.quiet and states[:4] or states[:5]
5499 show = ui.quiet and states[:4] or states[:5]
5493
5500
5494 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5501 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5495 'ignored' in show, 'clean' in show, 'unknown' in show,
5502 'ignored' in show, 'clean' in show, 'unknown' in show,
5496 opts.get('subrepos'))
5503 opts.get('subrepos'))
5497 changestates = zip(states, 'MAR!?IC', stat)
5504 changestates = zip(states, 'MAR!?IC', stat)
5498
5505
5499 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5506 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5500 copy = copies.pathcopies(repo[node1], repo[node2])
5507 copy = copies.pathcopies(repo[node1], repo[node2])
5501
5508
5502 fm = ui.formatter('status', opts)
5509 fm = ui.formatter('status', opts)
5503 fmt = '%s' + end
5510 fmt = '%s' + end
5504 showchar = not opts.get('no_status')
5511 showchar = not opts.get('no_status')
5505
5512
5506 for state, char, files in changestates:
5513 for state, char, files in changestates:
5507 if state in show:
5514 if state in show:
5508 label = 'status.' + state
5515 label = 'status.' + state
5509 for f in files:
5516 for f in files:
5510 fm.startitem()
5517 fm.startitem()
5511 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5518 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5512 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5519 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5513 if f in copy:
5520 if f in copy:
5514 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5521 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5515 label='status.copied')
5522 label='status.copied')
5516 fm.end()
5523 fm.end()
5517
5524
5518 @command('^summary|sum',
5525 @command('^summary|sum',
5519 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5526 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5520 def summary(ui, repo, **opts):
5527 def summary(ui, repo, **opts):
5521 """summarize working directory state
5528 """summarize working directory state
5522
5529
5523 This generates a brief summary of the working directory state,
5530 This generates a brief summary of the working directory state,
5524 including parents, branch, commit status, and available updates.
5531 including parents, branch, commit status, and available updates.
5525
5532
5526 With the --remote option, this will check the default paths for
5533 With the --remote option, this will check the default paths for
5527 incoming and outgoing changes. This can be time-consuming.
5534 incoming and outgoing changes. This can be time-consuming.
5528
5535
5529 Returns 0 on success.
5536 Returns 0 on success.
5530 """
5537 """
5531
5538
5532 ctx = repo[None]
5539 ctx = repo[None]
5533 parents = ctx.parents()
5540 parents = ctx.parents()
5534 pnode = parents[0].node()
5541 pnode = parents[0].node()
5535 marks = []
5542 marks = []
5536
5543
5537 for p in parents:
5544 for p in parents:
5538 # label with log.changeset (instead of log.parent) since this
5545 # label with log.changeset (instead of log.parent) since this
5539 # shows a working directory parent *changeset*:
5546 # shows a working directory parent *changeset*:
5540 # i18n: column positioning for "hg summary"
5547 # i18n: column positioning for "hg summary"
5541 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5548 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5542 label='log.changeset changeset.%s' % p.phasestr())
5549 label='log.changeset changeset.%s' % p.phasestr())
5543 ui.write(' '.join(p.tags()), label='log.tag')
5550 ui.write(' '.join(p.tags()), label='log.tag')
5544 if p.bookmarks():
5551 if p.bookmarks():
5545 marks.extend(p.bookmarks())
5552 marks.extend(p.bookmarks())
5546 if p.rev() == -1:
5553 if p.rev() == -1:
5547 if not len(repo):
5554 if not len(repo):
5548 ui.write(_(' (empty repository)'))
5555 ui.write(_(' (empty repository)'))
5549 else:
5556 else:
5550 ui.write(_(' (no revision checked out)'))
5557 ui.write(_(' (no revision checked out)'))
5551 ui.write('\n')
5558 ui.write('\n')
5552 if p.description():
5559 if p.description():
5553 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5560 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5554 label='log.summary')
5561 label='log.summary')
5555
5562
5556 branch = ctx.branch()
5563 branch = ctx.branch()
5557 bheads = repo.branchheads(branch)
5564 bheads = repo.branchheads(branch)
5558 # i18n: column positioning for "hg summary"
5565 # i18n: column positioning for "hg summary"
5559 m = _('branch: %s\n') % branch
5566 m = _('branch: %s\n') % branch
5560 if branch != 'default':
5567 if branch != 'default':
5561 ui.write(m, label='log.branch')
5568 ui.write(m, label='log.branch')
5562 else:
5569 else:
5563 ui.status(m, label='log.branch')
5570 ui.status(m, label='log.branch')
5564
5571
5565 if marks:
5572 if marks:
5566 current = repo._bookmarkcurrent
5573 current = repo._bookmarkcurrent
5567 # i18n: column positioning for "hg summary"
5574 # i18n: column positioning for "hg summary"
5568 ui.write(_('bookmarks:'), label='log.bookmark')
5575 ui.write(_('bookmarks:'), label='log.bookmark')
5569 if current is not None:
5576 if current is not None:
5570 try:
5577 try:
5571 marks.remove(current)
5578 marks.remove(current)
5572 ui.write(' *' + current, label='bookmarks.current')
5579 ui.write(' *' + current, label='bookmarks.current')
5573 except ValueError:
5580 except ValueError:
5574 # current bookmark not in parent ctx marks
5581 # current bookmark not in parent ctx marks
5575 pass
5582 pass
5576 for m in marks:
5583 for m in marks:
5577 ui.write(' ' + m, label='log.bookmark')
5584 ui.write(' ' + m, label='log.bookmark')
5578 ui.write('\n', label='log.bookmark')
5585 ui.write('\n', label='log.bookmark')
5579
5586
5580 st = list(repo.status(unknown=True))[:6]
5587 st = list(repo.status(unknown=True))[:6]
5581
5588
5582 c = repo.dirstate.copies()
5589 c = repo.dirstate.copies()
5583 copied, renamed = [], []
5590 copied, renamed = [], []
5584 for d, s in c.iteritems():
5591 for d, s in c.iteritems():
5585 if s in st[2]:
5592 if s in st[2]:
5586 st[2].remove(s)
5593 st[2].remove(s)
5587 renamed.append(d)
5594 renamed.append(d)
5588 else:
5595 else:
5589 copied.append(d)
5596 copied.append(d)
5590 if d in st[1]:
5597 if d in st[1]:
5591 st[1].remove(d)
5598 st[1].remove(d)
5592 st.insert(3, renamed)
5599 st.insert(3, renamed)
5593 st.insert(4, copied)
5600 st.insert(4, copied)
5594
5601
5595 ms = mergemod.mergestate(repo)
5602 ms = mergemod.mergestate(repo)
5596 st.append([f for f in ms if ms[f] == 'u'])
5603 st.append([f for f in ms if ms[f] == 'u'])
5597
5604
5598 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5605 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5599 st.append(subs)
5606 st.append(subs)
5600
5607
5601 labels = [ui.label(_('%d modified'), 'status.modified'),
5608 labels = [ui.label(_('%d modified'), 'status.modified'),
5602 ui.label(_('%d added'), 'status.added'),
5609 ui.label(_('%d added'), 'status.added'),
5603 ui.label(_('%d removed'), 'status.removed'),
5610 ui.label(_('%d removed'), 'status.removed'),
5604 ui.label(_('%d renamed'), 'status.copied'),
5611 ui.label(_('%d renamed'), 'status.copied'),
5605 ui.label(_('%d copied'), 'status.copied'),
5612 ui.label(_('%d copied'), 'status.copied'),
5606 ui.label(_('%d deleted'), 'status.deleted'),
5613 ui.label(_('%d deleted'), 'status.deleted'),
5607 ui.label(_('%d unknown'), 'status.unknown'),
5614 ui.label(_('%d unknown'), 'status.unknown'),
5608 ui.label(_('%d ignored'), 'status.ignored'),
5615 ui.label(_('%d ignored'), 'status.ignored'),
5609 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5616 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5610 ui.label(_('%d subrepos'), 'status.modified')]
5617 ui.label(_('%d subrepos'), 'status.modified')]
5611 t = []
5618 t = []
5612 for s, l in zip(st, labels):
5619 for s, l in zip(st, labels):
5613 if s:
5620 if s:
5614 t.append(l % len(s))
5621 t.append(l % len(s))
5615
5622
5616 t = ', '.join(t)
5623 t = ', '.join(t)
5617 cleanworkdir = False
5624 cleanworkdir = False
5618
5625
5619 if len(parents) > 1:
5626 if len(parents) > 1:
5620 t += _(' (merge)')
5627 t += _(' (merge)')
5621 elif branch != parents[0].branch():
5628 elif branch != parents[0].branch():
5622 t += _(' (new branch)')
5629 t += _(' (new branch)')
5623 elif (parents[0].closesbranch() and
5630 elif (parents[0].closesbranch() and
5624 pnode in repo.branchheads(branch, closed=True)):
5631 pnode in repo.branchheads(branch, closed=True)):
5625 t += _(' (head closed)')
5632 t += _(' (head closed)')
5626 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5633 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5627 t += _(' (clean)')
5634 t += _(' (clean)')
5628 cleanworkdir = True
5635 cleanworkdir = True
5629 elif pnode not in bheads:
5636 elif pnode not in bheads:
5630 t += _(' (new branch head)')
5637 t += _(' (new branch head)')
5631
5638
5632 if cleanworkdir:
5639 if cleanworkdir:
5633 # i18n: column positioning for "hg summary"
5640 # i18n: column positioning for "hg summary"
5634 ui.status(_('commit: %s\n') % t.strip())
5641 ui.status(_('commit: %s\n') % t.strip())
5635 else:
5642 else:
5636 # i18n: column positioning for "hg summary"
5643 # i18n: column positioning for "hg summary"
5637 ui.write(_('commit: %s\n') % t.strip())
5644 ui.write(_('commit: %s\n') % t.strip())
5638
5645
5639 # all ancestors of branch heads - all ancestors of parent = new csets
5646 # all ancestors of branch heads - all ancestors of parent = new csets
5640 new = [0] * len(repo)
5647 new = [0] * len(repo)
5641 cl = repo.changelog
5648 cl = repo.changelog
5642 for a in [cl.rev(n) for n in bheads]:
5649 for a in [cl.rev(n) for n in bheads]:
5643 new[a] = 1
5650 new[a] = 1
5644 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5651 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5645 new[a] = 1
5652 new[a] = 1
5646 for a in [p.rev() for p in parents]:
5653 for a in [p.rev() for p in parents]:
5647 if a >= 0:
5654 if a >= 0:
5648 new[a] = 0
5655 new[a] = 0
5649 for a in cl.ancestors([p.rev() for p in parents]):
5656 for a in cl.ancestors([p.rev() for p in parents]):
5650 new[a] = 0
5657 new[a] = 0
5651 new = sum(new)
5658 new = sum(new)
5652
5659
5653 if new == 0:
5660 if new == 0:
5654 # i18n: column positioning for "hg summary"
5661 # i18n: column positioning for "hg summary"
5655 ui.status(_('update: (current)\n'))
5662 ui.status(_('update: (current)\n'))
5656 elif pnode not in bheads:
5663 elif pnode not in bheads:
5657 # i18n: column positioning for "hg summary"
5664 # i18n: column positioning for "hg summary"
5658 ui.write(_('update: %d new changesets (update)\n') % new)
5665 ui.write(_('update: %d new changesets (update)\n') % new)
5659 else:
5666 else:
5660 # i18n: column positioning for "hg summary"
5667 # i18n: column positioning for "hg summary"
5661 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5668 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5662 (new, len(bheads)))
5669 (new, len(bheads)))
5663
5670
5664 if opts.get('remote'):
5671 if opts.get('remote'):
5665 t = []
5672 t = []
5666 source, branches = hg.parseurl(ui.expandpath('default'))
5673 source, branches = hg.parseurl(ui.expandpath('default'))
5667 other = hg.peer(repo, {}, source)
5674 other = hg.peer(repo, {}, source)
5668 revs, checkout = hg.addbranchrevs(repo, other, branches,
5675 revs, checkout = hg.addbranchrevs(repo, other, branches,
5669 opts.get('rev'))
5676 opts.get('rev'))
5670 ui.debug('comparing with %s\n' % util.hidepassword(source))
5677 ui.debug('comparing with %s\n' % util.hidepassword(source))
5671 repo.ui.pushbuffer()
5678 repo.ui.pushbuffer()
5672 commoninc = discovery.findcommonincoming(repo, other)
5679 commoninc = discovery.findcommonincoming(repo, other)
5673 _common, incoming, _rheads = commoninc
5680 _common, incoming, _rheads = commoninc
5674 repo.ui.popbuffer()
5681 repo.ui.popbuffer()
5675 if incoming:
5682 if incoming:
5676 t.append(_('1 or more incoming'))
5683 t.append(_('1 or more incoming'))
5677
5684
5678 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5685 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5679 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5686 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5680 if source != dest:
5687 if source != dest:
5681 other = hg.peer(repo, {}, dest)
5688 other = hg.peer(repo, {}, dest)
5682 commoninc = None
5689 commoninc = None
5683 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5690 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5684 repo.ui.pushbuffer()
5691 repo.ui.pushbuffer()
5685 outgoing = discovery.findcommonoutgoing(repo, other,
5692 outgoing = discovery.findcommonoutgoing(repo, other,
5686 commoninc=commoninc)
5693 commoninc=commoninc)
5687 repo.ui.popbuffer()
5694 repo.ui.popbuffer()
5688 o = outgoing.missing
5695 o = outgoing.missing
5689 if o:
5696 if o:
5690 t.append(_('%d outgoing') % len(o))
5697 t.append(_('%d outgoing') % len(o))
5691 if 'bookmarks' in other.listkeys('namespaces'):
5698 if 'bookmarks' in other.listkeys('namespaces'):
5692 lmarks = repo.listkeys('bookmarks')
5699 lmarks = repo.listkeys('bookmarks')
5693 rmarks = other.listkeys('bookmarks')
5700 rmarks = other.listkeys('bookmarks')
5694 diff = set(rmarks) - set(lmarks)
5701 diff = set(rmarks) - set(lmarks)
5695 if len(diff) > 0:
5702 if len(diff) > 0:
5696 t.append(_('%d incoming bookmarks') % len(diff))
5703 t.append(_('%d incoming bookmarks') % len(diff))
5697 diff = set(lmarks) - set(rmarks)
5704 diff = set(lmarks) - set(rmarks)
5698 if len(diff) > 0:
5705 if len(diff) > 0:
5699 t.append(_('%d outgoing bookmarks') % len(diff))
5706 t.append(_('%d outgoing bookmarks') % len(diff))
5700
5707
5701 if t:
5708 if t:
5702 # i18n: column positioning for "hg summary"
5709 # i18n: column positioning for "hg summary"
5703 ui.write(_('remote: %s\n') % (', '.join(t)))
5710 ui.write(_('remote: %s\n') % (', '.join(t)))
5704 else:
5711 else:
5705 # i18n: column positioning for "hg summary"
5712 # i18n: column positioning for "hg summary"
5706 ui.status(_('remote: (synced)\n'))
5713 ui.status(_('remote: (synced)\n'))
5707
5714
5708 @command('tag',
5715 @command('tag',
5709 [('f', 'force', None, _('force tag')),
5716 [('f', 'force', None, _('force tag')),
5710 ('l', 'local', None, _('make the tag local')),
5717 ('l', 'local', None, _('make the tag local')),
5711 ('r', 'rev', '', _('revision to tag'), _('REV')),
5718 ('r', 'rev', '', _('revision to tag'), _('REV')),
5712 ('', 'remove', None, _('remove a tag')),
5719 ('', 'remove', None, _('remove a tag')),
5713 # -l/--local is already there, commitopts cannot be used
5720 # -l/--local is already there, commitopts cannot be used
5714 ('e', 'edit', None, _('edit commit message')),
5721 ('e', 'edit', None, _('edit commit message')),
5715 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5722 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5716 ] + commitopts2,
5723 ] + commitopts2,
5717 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5724 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5718 def tag(ui, repo, name1, *names, **opts):
5725 def tag(ui, repo, name1, *names, **opts):
5719 """add one or more tags for the current or given revision
5726 """add one or more tags for the current or given revision
5720
5727
5721 Name a particular revision using <name>.
5728 Name a particular revision using <name>.
5722
5729
5723 Tags are used to name particular revisions of the repository and are
5730 Tags are used to name particular revisions of the repository and are
5724 very useful to compare different revisions, to go back to significant
5731 very useful to compare different revisions, to go back to significant
5725 earlier versions or to mark branch points as releases, etc. Changing
5732 earlier versions or to mark branch points as releases, etc. Changing
5726 an existing tag is normally disallowed; use -f/--force to override.
5733 an existing tag is normally disallowed; use -f/--force to override.
5727
5734
5728 If no revision is given, the parent of the working directory is
5735 If no revision is given, the parent of the working directory is
5729 used, or tip if no revision is checked out.
5736 used, or tip if no revision is checked out.
5730
5737
5731 To facilitate version control, distribution, and merging of tags,
5738 To facilitate version control, distribution, and merging of tags,
5732 they are stored as a file named ".hgtags" which is managed similarly
5739 they are stored as a file named ".hgtags" which is managed similarly
5733 to other project files and can be hand-edited if necessary. This
5740 to other project files and can be hand-edited if necessary. This
5734 also means that tagging creates a new commit. The file
5741 also means that tagging creates a new commit. The file
5735 ".hg/localtags" is used for local tags (not shared among
5742 ".hg/localtags" is used for local tags (not shared among
5736 repositories).
5743 repositories).
5737
5744
5738 Tag commits are usually made at the head of a branch. If the parent
5745 Tag commits are usually made at the head of a branch. If the parent
5739 of the working directory is not a branch head, :hg:`tag` aborts; use
5746 of the working directory is not a branch head, :hg:`tag` aborts; use
5740 -f/--force to force the tag commit to be based on a non-head
5747 -f/--force to force the tag commit to be based on a non-head
5741 changeset.
5748 changeset.
5742
5749
5743 See :hg:`help dates` for a list of formats valid for -d/--date.
5750 See :hg:`help dates` for a list of formats valid for -d/--date.
5744
5751
5745 Since tag names have priority over branch names during revision
5752 Since tag names have priority over branch names during revision
5746 lookup, using an existing branch name as a tag name is discouraged.
5753 lookup, using an existing branch name as a tag name is discouraged.
5747
5754
5748 Returns 0 on success.
5755 Returns 0 on success.
5749 """
5756 """
5750 wlock = lock = None
5757 wlock = lock = None
5751 try:
5758 try:
5752 wlock = repo.wlock()
5759 wlock = repo.wlock()
5753 lock = repo.lock()
5760 lock = repo.lock()
5754 rev_ = "."
5761 rev_ = "."
5755 names = [t.strip() for t in (name1,) + names]
5762 names = [t.strip() for t in (name1,) + names]
5756 if len(names) != len(set(names)):
5763 if len(names) != len(set(names)):
5757 raise util.Abort(_('tag names must be unique'))
5764 raise util.Abort(_('tag names must be unique'))
5758 for n in names:
5765 for n in names:
5759 scmutil.checknewlabel(repo, n, 'tag')
5766 scmutil.checknewlabel(repo, n, 'tag')
5760 if not n:
5767 if not n:
5761 raise util.Abort(_('tag names cannot consist entirely of '
5768 raise util.Abort(_('tag names cannot consist entirely of '
5762 'whitespace'))
5769 'whitespace'))
5763 if opts.get('rev') and opts.get('remove'):
5770 if opts.get('rev') and opts.get('remove'):
5764 raise util.Abort(_("--rev and --remove are incompatible"))
5771 raise util.Abort(_("--rev and --remove are incompatible"))
5765 if opts.get('rev'):
5772 if opts.get('rev'):
5766 rev_ = opts['rev']
5773 rev_ = opts['rev']
5767 message = opts.get('message')
5774 message = opts.get('message')
5768 if opts.get('remove'):
5775 if opts.get('remove'):
5769 expectedtype = opts.get('local') and 'local' or 'global'
5776 expectedtype = opts.get('local') and 'local' or 'global'
5770 for n in names:
5777 for n in names:
5771 if not repo.tagtype(n):
5778 if not repo.tagtype(n):
5772 raise util.Abort(_("tag '%s' does not exist") % n)
5779 raise util.Abort(_("tag '%s' does not exist") % n)
5773 if repo.tagtype(n) != expectedtype:
5780 if repo.tagtype(n) != expectedtype:
5774 if expectedtype == 'global':
5781 if expectedtype == 'global':
5775 raise util.Abort(_("tag '%s' is not a global tag") % n)
5782 raise util.Abort(_("tag '%s' is not a global tag") % n)
5776 else:
5783 else:
5777 raise util.Abort(_("tag '%s' is not a local tag") % n)
5784 raise util.Abort(_("tag '%s' is not a local tag") % n)
5778 rev_ = nullid
5785 rev_ = nullid
5779 if not message:
5786 if not message:
5780 # we don't translate commit messages
5787 # we don't translate commit messages
5781 message = 'Removed tag %s' % ', '.join(names)
5788 message = 'Removed tag %s' % ', '.join(names)
5782 elif not opts.get('force'):
5789 elif not opts.get('force'):
5783 for n in names:
5790 for n in names:
5784 if n in repo.tags():
5791 if n in repo.tags():
5785 raise util.Abort(_("tag '%s' already exists "
5792 raise util.Abort(_("tag '%s' already exists "
5786 "(use -f to force)") % n)
5793 "(use -f to force)") % n)
5787 if not opts.get('local'):
5794 if not opts.get('local'):
5788 p1, p2 = repo.dirstate.parents()
5795 p1, p2 = repo.dirstate.parents()
5789 if p2 != nullid:
5796 if p2 != nullid:
5790 raise util.Abort(_('uncommitted merge'))
5797 raise util.Abort(_('uncommitted merge'))
5791 bheads = repo.branchheads()
5798 bheads = repo.branchheads()
5792 if not opts.get('force') and bheads and p1 not in bheads:
5799 if not opts.get('force') and bheads and p1 not in bheads:
5793 raise util.Abort(_('not at a branch head (use -f to force)'))
5800 raise util.Abort(_('not at a branch head (use -f to force)'))
5794 r = scmutil.revsingle(repo, rev_).node()
5801 r = scmutil.revsingle(repo, rev_).node()
5795
5802
5796 if not message:
5803 if not message:
5797 # we don't translate commit messages
5804 # we don't translate commit messages
5798 message = ('Added tag %s for changeset %s' %
5805 message = ('Added tag %s for changeset %s' %
5799 (', '.join(names), short(r)))
5806 (', '.join(names), short(r)))
5800
5807
5801 date = opts.get('date')
5808 date = opts.get('date')
5802 if date:
5809 if date:
5803 date = util.parsedate(date)
5810 date = util.parsedate(date)
5804
5811
5805 if opts.get('edit'):
5812 if opts.get('edit'):
5806 message = ui.edit(message, ui.username())
5813 message = ui.edit(message, ui.username())
5807
5814
5808 # don't allow tagging the null rev
5815 # don't allow tagging the null rev
5809 if (not opts.get('remove') and
5816 if (not opts.get('remove') and
5810 scmutil.revsingle(repo, rev_).rev() == nullrev):
5817 scmutil.revsingle(repo, rev_).rev() == nullrev):
5811 raise util.Abort(_("null revision specified"))
5818 raise util.Abort(_("null revision specified"))
5812
5819
5813 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5820 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5814 finally:
5821 finally:
5815 release(lock, wlock)
5822 release(lock, wlock)
5816
5823
5817 @command('tags', [], '')
5824 @command('tags', [], '')
5818 def tags(ui, repo, **opts):
5825 def tags(ui, repo, **opts):
5819 """list repository tags
5826 """list repository tags
5820
5827
5821 This lists both regular and local tags. When the -v/--verbose
5828 This lists both regular and local tags. When the -v/--verbose
5822 switch is used, a third column "local" is printed for local tags.
5829 switch is used, a third column "local" is printed for local tags.
5823
5830
5824 Returns 0 on success.
5831 Returns 0 on success.
5825 """
5832 """
5826
5833
5827 fm = ui.formatter('tags', opts)
5834 fm = ui.formatter('tags', opts)
5828 hexfunc = ui.debugflag and hex or short
5835 hexfunc = ui.debugflag and hex or short
5829 tagtype = ""
5836 tagtype = ""
5830
5837
5831 for t, n in reversed(repo.tagslist()):
5838 for t, n in reversed(repo.tagslist()):
5832 hn = hexfunc(n)
5839 hn = hexfunc(n)
5833 label = 'tags.normal'
5840 label = 'tags.normal'
5834 tagtype = ''
5841 tagtype = ''
5835 if repo.tagtype(t) == 'local':
5842 if repo.tagtype(t) == 'local':
5836 label = 'tags.local'
5843 label = 'tags.local'
5837 tagtype = 'local'
5844 tagtype = 'local'
5838
5845
5839 fm.startitem()
5846 fm.startitem()
5840 fm.write('tag', '%s', t, label=label)
5847 fm.write('tag', '%s', t, label=label)
5841 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5848 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5842 fm.condwrite(not ui.quiet, 'rev id', fmt,
5849 fm.condwrite(not ui.quiet, 'rev id', fmt,
5843 repo.changelog.rev(n), hn, label=label)
5850 repo.changelog.rev(n), hn, label=label)
5844 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5851 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5845 tagtype, label=label)
5852 tagtype, label=label)
5846 fm.plain('\n')
5853 fm.plain('\n')
5847 fm.end()
5854 fm.end()
5848
5855
5849 @command('tip',
5856 @command('tip',
5850 [('p', 'patch', None, _('show patch')),
5857 [('p', 'patch', None, _('show patch')),
5851 ('g', 'git', None, _('use git extended diff format')),
5858 ('g', 'git', None, _('use git extended diff format')),
5852 ] + templateopts,
5859 ] + templateopts,
5853 _('[-p] [-g]'))
5860 _('[-p] [-g]'))
5854 def tip(ui, repo, **opts):
5861 def tip(ui, repo, **opts):
5855 """show the tip revision
5862 """show the tip revision
5856
5863
5857 The tip revision (usually just called the tip) is the changeset
5864 The tip revision (usually just called the tip) is the changeset
5858 most recently added to the repository (and therefore the most
5865 most recently added to the repository (and therefore the most
5859 recently changed head).
5866 recently changed head).
5860
5867
5861 If you have just made a commit, that commit will be the tip. If
5868 If you have just made a commit, that commit will be the tip. If
5862 you have just pulled changes from another repository, the tip of
5869 you have just pulled changes from another repository, the tip of
5863 that repository becomes the current tip. The "tip" tag is special
5870 that repository becomes the current tip. The "tip" tag is special
5864 and cannot be renamed or assigned to a different changeset.
5871 and cannot be renamed or assigned to a different changeset.
5865
5872
5866 Returns 0 on success.
5873 Returns 0 on success.
5867 """
5874 """
5868 displayer = cmdutil.show_changeset(ui, repo, opts)
5875 displayer = cmdutil.show_changeset(ui, repo, opts)
5869 displayer.show(repo['tip'])
5876 displayer.show(repo['tip'])
5870 displayer.close()
5877 displayer.close()
5871
5878
5872 @command('unbundle',
5879 @command('unbundle',
5873 [('u', 'update', None,
5880 [('u', 'update', None,
5874 _('update to new branch head if changesets were unbundled'))],
5881 _('update to new branch head if changesets were unbundled'))],
5875 _('[-u] FILE...'))
5882 _('[-u] FILE...'))
5876 def unbundle(ui, repo, fname1, *fnames, **opts):
5883 def unbundle(ui, repo, fname1, *fnames, **opts):
5877 """apply one or more changegroup files
5884 """apply one or more changegroup files
5878
5885
5879 Apply one or more compressed changegroup files generated by the
5886 Apply one or more compressed changegroup files generated by the
5880 bundle command.
5887 bundle command.
5881
5888
5882 Returns 0 on success, 1 if an update has unresolved files.
5889 Returns 0 on success, 1 if an update has unresolved files.
5883 """
5890 """
5884 fnames = (fname1,) + fnames
5891 fnames = (fname1,) + fnames
5885
5892
5886 lock = repo.lock()
5893 lock = repo.lock()
5887 wc = repo['.']
5894 wc = repo['.']
5888 try:
5895 try:
5889 for fname in fnames:
5896 for fname in fnames:
5890 f = hg.openpath(ui, fname)
5897 f = hg.openpath(ui, fname)
5891 gen = changegroup.readbundle(f, fname)
5898 gen = changegroup.readbundle(f, fname)
5892 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5899 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5893 finally:
5900 finally:
5894 lock.release()
5901 lock.release()
5895 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5902 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5896 return postincoming(ui, repo, modheads, opts.get('update'), None)
5903 return postincoming(ui, repo, modheads, opts.get('update'), None)
5897
5904
5898 @command('^update|up|checkout|co',
5905 @command('^update|up|checkout|co',
5899 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5906 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5900 ('c', 'check', None,
5907 ('c', 'check', None,
5901 _('update across branches if no uncommitted changes')),
5908 _('update across branches if no uncommitted changes')),
5902 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5909 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5903 ('r', 'rev', '', _('revision'), _('REV'))],
5910 ('r', 'rev', '', _('revision'), _('REV'))],
5904 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5911 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5905 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5912 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5906 """update working directory (or switch revisions)
5913 """update working directory (or switch revisions)
5907
5914
5908 Update the repository's working directory to the specified
5915 Update the repository's working directory to the specified
5909 changeset. If no changeset is specified, update to the tip of the
5916 changeset. If no changeset is specified, update to the tip of the
5910 current named branch and move the current bookmark (see :hg:`help
5917 current named branch and move the current bookmark (see :hg:`help
5911 bookmarks`).
5918 bookmarks`).
5912
5919
5913 Update sets the working directory's parent revision to the specified
5920 Update sets the working directory's parent revision to the specified
5914 changeset (see :hg:`help parents`).
5921 changeset (see :hg:`help parents`).
5915
5922
5916 If the changeset is not a descendant or ancestor of the working
5923 If the changeset is not a descendant or ancestor of the working
5917 directory's parent, the update is aborted. With the -c/--check
5924 directory's parent, the update is aborted. With the -c/--check
5918 option, the working directory is checked for uncommitted changes; if
5925 option, the working directory is checked for uncommitted changes; if
5919 none are found, the working directory is updated to the specified
5926 none are found, the working directory is updated to the specified
5920 changeset.
5927 changeset.
5921
5928
5922 .. container:: verbose
5929 .. container:: verbose
5923
5930
5924 The following rules apply when the working directory contains
5931 The following rules apply when the working directory contains
5925 uncommitted changes:
5932 uncommitted changes:
5926
5933
5927 1. If neither -c/--check nor -C/--clean is specified, and if
5934 1. If neither -c/--check nor -C/--clean is specified, and if
5928 the requested changeset is an ancestor or descendant of
5935 the requested changeset is an ancestor or descendant of
5929 the working directory's parent, the uncommitted changes
5936 the working directory's parent, the uncommitted changes
5930 are merged into the requested changeset and the merged
5937 are merged into the requested changeset and the merged
5931 result is left uncommitted. If the requested changeset is
5938 result is left uncommitted. If the requested changeset is
5932 not an ancestor or descendant (that is, it is on another
5939 not an ancestor or descendant (that is, it is on another
5933 branch), the update is aborted and the uncommitted changes
5940 branch), the update is aborted and the uncommitted changes
5934 are preserved.
5941 are preserved.
5935
5942
5936 2. With the -c/--check option, the update is aborted and the
5943 2. With the -c/--check option, the update is aborted and the
5937 uncommitted changes are preserved.
5944 uncommitted changes are preserved.
5938
5945
5939 3. With the -C/--clean option, uncommitted changes are discarded and
5946 3. With the -C/--clean option, uncommitted changes are discarded and
5940 the working directory is updated to the requested changeset.
5947 the working directory is updated to the requested changeset.
5941
5948
5942 To cancel an uncommitted merge (and lose your changes), use
5949 To cancel an uncommitted merge (and lose your changes), use
5943 :hg:`update --clean .`.
5950 :hg:`update --clean .`.
5944
5951
5945 Use null as the changeset to remove the working directory (like
5952 Use null as the changeset to remove the working directory (like
5946 :hg:`clone -U`).
5953 :hg:`clone -U`).
5947
5954
5948 If you want to revert just one file to an older revision, use
5955 If you want to revert just one file to an older revision, use
5949 :hg:`revert [-r REV] NAME`.
5956 :hg:`revert [-r REV] NAME`.
5950
5957
5951 See :hg:`help dates` for a list of formats valid for -d/--date.
5958 See :hg:`help dates` for a list of formats valid for -d/--date.
5952
5959
5953 Returns 0 on success, 1 if there are unresolved files.
5960 Returns 0 on success, 1 if there are unresolved files.
5954 """
5961 """
5955 if rev and node:
5962 if rev and node:
5956 raise util.Abort(_("please specify just one revision"))
5963 raise util.Abort(_("please specify just one revision"))
5957
5964
5958 if rev is None or rev == '':
5965 if rev is None or rev == '':
5959 rev = node
5966 rev = node
5960
5967
5961 # with no argument, we also move the current bookmark, if any
5968 # with no argument, we also move the current bookmark, if any
5962 movemarkfrom = None
5969 movemarkfrom = None
5963 if rev is None:
5970 if rev is None:
5964 curmark = repo._bookmarkcurrent
5971 curmark = repo._bookmarkcurrent
5965 if bookmarks.iscurrent(repo):
5972 if bookmarks.iscurrent(repo):
5966 movemarkfrom = repo['.'].node()
5973 movemarkfrom = repo['.'].node()
5967 elif curmark:
5974 elif curmark:
5968 ui.status(_("updating to active bookmark %s\n") % curmark)
5975 ui.status(_("updating to active bookmark %s\n") % curmark)
5969 rev = curmark
5976 rev = curmark
5970
5977
5971 # if we defined a bookmark, we have to remember the original bookmark name
5978 # if we defined a bookmark, we have to remember the original bookmark name
5972 brev = rev
5979 brev = rev
5973 rev = scmutil.revsingle(repo, rev, rev).rev()
5980 rev = scmutil.revsingle(repo, rev, rev).rev()
5974
5981
5975 if check and clean:
5982 if check and clean:
5976 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5983 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5977
5984
5978 if date:
5985 if date:
5979 if rev is not None:
5986 if rev is not None:
5980 raise util.Abort(_("you can't specify a revision and a date"))
5987 raise util.Abort(_("you can't specify a revision and a date"))
5981 rev = cmdutil.finddate(ui, repo, date)
5988 rev = cmdutil.finddate(ui, repo, date)
5982
5989
5983 if check:
5990 if check:
5984 c = repo[None]
5991 c = repo[None]
5985 if c.dirty(merge=False, branch=False, missing=True):
5992 if c.dirty(merge=False, branch=False, missing=True):
5986 raise util.Abort(_("uncommitted local changes"))
5993 raise util.Abort(_("uncommitted local changes"))
5987 if rev is None:
5994 if rev is None:
5988 rev = repo[repo[None].branch()].rev()
5995 rev = repo[repo[None].branch()].rev()
5989 mergemod._checkunknown(repo, repo[None], repo[rev])
5996 mergemod._checkunknown(repo, repo[None], repo[rev])
5990
5997
5991 if clean:
5998 if clean:
5992 ret = hg.clean(repo, rev)
5999 ret = hg.clean(repo, rev)
5993 else:
6000 else:
5994 ret = hg.update(repo, rev)
6001 ret = hg.update(repo, rev)
5995
6002
5996 if not ret and movemarkfrom:
6003 if not ret and movemarkfrom:
5997 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6004 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5998 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6005 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5999 elif brev in repo._bookmarks:
6006 elif brev in repo._bookmarks:
6000 bookmarks.setcurrent(repo, brev)
6007 bookmarks.setcurrent(repo, brev)
6001 elif brev:
6008 elif brev:
6002 bookmarks.unsetcurrent(repo)
6009 bookmarks.unsetcurrent(repo)
6003
6010
6004 return ret
6011 return ret
6005
6012
6006 @command('verify', [])
6013 @command('verify', [])
6007 def verify(ui, repo):
6014 def verify(ui, repo):
6008 """verify the integrity of the repository
6015 """verify the integrity of the repository
6009
6016
6010 Verify the integrity of the current repository.
6017 Verify the integrity of the current repository.
6011
6018
6012 This will perform an extensive check of the repository's
6019 This will perform an extensive check of the repository's
6013 integrity, validating the hashes and checksums of each entry in
6020 integrity, validating the hashes and checksums of each entry in
6014 the changelog, manifest, and tracked files, as well as the
6021 the changelog, manifest, and tracked files, as well as the
6015 integrity of their crosslinks and indices.
6022 integrity of their crosslinks and indices.
6016
6023
6017 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6024 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6018 for more information about recovery from corruption of the
6025 for more information about recovery from corruption of the
6019 repository.
6026 repository.
6020
6027
6021 Returns 0 on success, 1 if errors are encountered.
6028 Returns 0 on success, 1 if errors are encountered.
6022 """
6029 """
6023 return hg.verify(repo)
6030 return hg.verify(repo)
6024
6031
6025 @command('version', [])
6032 @command('version', [])
6026 def version_(ui):
6033 def version_(ui):
6027 """output version and copyright information"""
6034 """output version and copyright information"""
6028 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6035 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6029 % util.version())
6036 % util.version())
6030 ui.status(_(
6037 ui.status(_(
6031 "(see http://mercurial.selenic.com for more information)\n"
6038 "(see http://mercurial.selenic.com for more information)\n"
6032 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
6039 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
6033 "This is free software; see the source for copying conditions. "
6040 "This is free software; see the source for copying conditions. "
6034 "There is NO\nwarranty; "
6041 "There is NO\nwarranty; "
6035 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6042 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6036 ))
6043 ))
6037
6044
6038 norepo = ("clone init version help debugcommands debugcomplete"
6045 norepo = ("clone init version help debugcommands debugcomplete"
6039 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
6046 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
6040 " debugknown debuggetbundle debugbundle")
6047 " debugknown debuggetbundle debugbundle")
6041 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
6048 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
6042 " debugdata debugindex debugindexdot debugrevlog")
6049 " debugdata debugindex debugindexdot debugrevlog")
6043 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
6050 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
6044 " remove resolve status debugwalk")
6051 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now