##// END OF EJS Templates
bisect: add example for limiting bisection to specified directories...
Jordi Gutiérrez Hermoso -
r17969:6c67deb3 default
parent child Browse files
Show More
@@ -1,5977 +1,5981 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 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('G', 'graph', None, _("show the revision DAG")),
101 ('G', 'graph', None, _("show the revision DAG")),
102 ] + templateopts
102 ] + templateopts
103
103
104 diffopts = [
104 diffopts = [
105 ('a', 'text', None, _('treat all files as text')),
105 ('a', 'text', None, _('treat all files as text')),
106 ('g', 'git', None, _('use git extended diff format')),
106 ('g', 'git', None, _('use git extended diff format')),
107 ('', 'nodates', None, _('omit dates from diff headers'))
107 ('', 'nodates', None, _('omit dates from diff headers'))
108 ]
108 ]
109
109
110 diffwsopts = [
110 diffwsopts = [
111 ('w', 'ignore-all-space', None,
111 ('w', 'ignore-all-space', None,
112 _('ignore white space when comparing lines')),
112 _('ignore white space when comparing lines')),
113 ('b', 'ignore-space-change', None,
113 ('b', 'ignore-space-change', None,
114 _('ignore changes in the amount of white space')),
114 _('ignore changes in the amount of white space')),
115 ('B', 'ignore-blank-lines', None,
115 ('B', 'ignore-blank-lines', None,
116 _('ignore changes whose lines are all blank')),
116 _('ignore changes whose lines are all blank')),
117 ]
117 ]
118
118
119 diffopts2 = [
119 diffopts2 = [
120 ('p', 'show-function', None, _('show which function each change is in')),
120 ('p', 'show-function', None, _('show which function each change is in')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ] + diffwsopts + [
122 ] + diffwsopts + [
123 ('U', 'unified', '',
123 ('U', 'unified', '',
124 _('number of lines of context to show'), _('NUM')),
124 _('number of lines of context to show'), _('NUM')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ]
126 ]
127
127
128 mergetoolopts = [
128 mergetoolopts = [
129 ('t', 'tool', '', _('specify merge tool')),
129 ('t', 'tool', '', _('specify merge tool')),
130 ]
130 ]
131
131
132 similarityopts = [
132 similarityopts = [
133 ('s', 'similarity', '',
133 ('s', 'similarity', '',
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 ]
135 ]
136
136
137 subrepoopts = [
137 subrepoopts = [
138 ('S', 'subrepos', None,
138 ('S', 'subrepos', None,
139 _('recurse into subrepositories'))
139 _('recurse into subrepositories'))
140 ]
140 ]
141
141
142 # Commands start here, listed alphabetically
142 # Commands start here, listed alphabetically
143
143
144 @command('^add',
144 @command('^add',
145 walkopts + subrepoopts + dryrunopts,
145 walkopts + subrepoopts + dryrunopts,
146 _('[OPTION]... [FILE]...'))
146 _('[OPTION]... [FILE]...'))
147 def add(ui, repo, *pats, **opts):
147 def add(ui, repo, *pats, **opts):
148 """add the specified files on the next commit
148 """add the specified files on the next commit
149
149
150 Schedule files to be version controlled and added to the
150 Schedule files to be version controlled and added to the
151 repository.
151 repository.
152
152
153 The files will be added to the repository at the next commit. To
153 The files will be added to the repository at the next commit. To
154 undo an add before that, see :hg:`forget`.
154 undo an add before that, see :hg:`forget`.
155
155
156 If no names are given, add all files to the repository.
156 If no names are given, add all files to the repository.
157
157
158 .. container:: verbose
158 .. container:: verbose
159
159
160 An example showing how new (unknown) files are added
160 An example showing how new (unknown) files are added
161 automatically by :hg:`add`::
161 automatically by :hg:`add`::
162
162
163 $ ls
163 $ ls
164 foo.c
164 foo.c
165 $ hg status
165 $ hg status
166 ? foo.c
166 ? foo.c
167 $ hg add
167 $ hg add
168 adding foo.c
168 adding foo.c
169 $ hg status
169 $ hg status
170 A foo.c
170 A foo.c
171
171
172 Returns 0 if all files are successfully added.
172 Returns 0 if all files are successfully added.
173 """
173 """
174
174
175 m = scmutil.match(repo[None], pats, opts)
175 m = scmutil.match(repo[None], pats, opts)
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 opts.get('subrepos'), prefix="", explicitonly=False)
177 opts.get('subrepos'), prefix="", explicitonly=False)
178 return rejected and 1 or 0
178 return rejected and 1 or 0
179
179
180 @command('addremove',
180 @command('addremove',
181 similarityopts + walkopts + dryrunopts,
181 similarityopts + walkopts + dryrunopts,
182 _('[OPTION]... [FILE]...'))
182 _('[OPTION]... [FILE]...'))
183 def addremove(ui, repo, *pats, **opts):
183 def addremove(ui, repo, *pats, **opts):
184 """add all new files, delete all missing files
184 """add all new files, delete all missing files
185
185
186 Add all new files and remove all missing files from the
186 Add all new files and remove all missing files from the
187 repository.
187 repository.
188
188
189 New files are ignored if they match any of the patterns in
189 New files are ignored if they match any of the patterns in
190 ``.hgignore``. As with add, these changes take effect at the next
190 ``.hgignore``. As with add, these changes take effect at the next
191 commit.
191 commit.
192
192
193 Use the -s/--similarity option to detect renamed files. This
193 Use the -s/--similarity option to detect renamed files. This
194 option takes a percentage between 0 (disabled) and 100 (files must
194 option takes a percentage between 0 (disabled) and 100 (files must
195 be identical) as its parameter. With a parameter greater than 0,
195 be identical) as its parameter. With a parameter greater than 0,
196 this compares every removed file with every added file and records
196 this compares every removed file with every added file and records
197 those similar enough as renames. Detecting renamed files this way
197 those similar enough as renames. Detecting renamed files this way
198 can be expensive. After using this option, :hg:`status -C` can be
198 can be expensive. After using this option, :hg:`status -C` can be
199 used to check which files were identified as moved or renamed. If
199 used to check which files were identified as moved or renamed. If
200 not specified, -s/--similarity defaults to 100 and only renames of
200 not specified, -s/--similarity defaults to 100 and only renames of
201 identical files are detected.
201 identical files are detected.
202
202
203 Returns 0 if all files are successfully added.
203 Returns 0 if all files are successfully added.
204 """
204 """
205 try:
205 try:
206 sim = float(opts.get('similarity') or 100)
206 sim = float(opts.get('similarity') or 100)
207 except ValueError:
207 except ValueError:
208 raise util.Abort(_('similarity must be a number'))
208 raise util.Abort(_('similarity must be a number'))
209 if sim < 0 or sim > 100:
209 if sim < 0 or sim > 100:
210 raise util.Abort(_('similarity must be between 0 and 100'))
210 raise util.Abort(_('similarity must be between 0 and 100'))
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212
212
213 @command('^annotate|blame',
213 @command('^annotate|blame',
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 ('', 'follow', None,
215 ('', 'follow', None,
216 _('follow copies/renames and list the filename (DEPRECATED)')),
216 _('follow copies/renames and list the filename (DEPRECATED)')),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('a', 'text', None, _('treat all files as text')),
218 ('a', 'text', None, _('treat all files as text')),
219 ('u', 'user', None, _('list the author (long with -v)')),
219 ('u', 'user', None, _('list the author (long with -v)')),
220 ('f', 'file', None, _('list the filename')),
220 ('f', 'file', None, _('list the filename')),
221 ('d', 'date', None, _('list the date (short with -q)')),
221 ('d', 'date', None, _('list the date (short with -q)')),
222 ('n', 'number', None, _('list the revision number (default)')),
222 ('n', 'number', None, _('list the revision number (default)')),
223 ('c', 'changeset', None, _('list the changeset')),
223 ('c', 'changeset', None, _('list the changeset')),
224 ('l', 'line-number', None, _('show line number at the first appearance'))
224 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ] + diffwsopts + walkopts,
225 ] + diffwsopts + walkopts,
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 def annotate(ui, repo, *pats, **opts):
227 def annotate(ui, repo, *pats, **opts):
228 """show changeset information by line for each file
228 """show changeset information by line for each file
229
229
230 List changes in files, showing the revision id responsible for
230 List changes in files, showing the revision id responsible for
231 each line
231 each line
232
232
233 This command is useful for discovering when a change was made and
233 This command is useful for discovering when a change was made and
234 by whom.
234 by whom.
235
235
236 Without the -a/--text option, annotate will avoid processing files
236 Without the -a/--text option, annotate will avoid processing files
237 it detects as binary. With -a, annotate will annotate the file
237 it detects as binary. With -a, annotate will annotate the file
238 anyway, although the results will probably be neither useful
238 anyway, although the results will probably be neither useful
239 nor desirable.
239 nor desirable.
240
240
241 Returns 0 on success.
241 Returns 0 on success.
242 """
242 """
243 if opts.get('follow'):
243 if opts.get('follow'):
244 # --follow is deprecated and now just an alias for -f/--file
244 # --follow is deprecated and now just an alias for -f/--file
245 # to mimic the behavior of Mercurial before version 1.5
245 # to mimic the behavior of Mercurial before version 1.5
246 opts['file'] = True
246 opts['file'] = True
247
247
248 datefunc = ui.quiet and util.shortdate or util.datestr
248 datefunc = ui.quiet and util.shortdate or util.datestr
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250
250
251 if not pats:
251 if not pats:
252 raise util.Abort(_('at least one filename or pattern is required'))
252 raise util.Abort(_('at least one filename or pattern is required'))
253
253
254 hexfn = ui.debugflag and hex or short
254 hexfn = ui.debugflag and hex or short
255
255
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 ('number', ' ', lambda x: str(x[0].rev())),
257 ('number', ' ', lambda x: str(x[0].rev())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('date', ' ', getdate),
259 ('date', ' ', getdate),
260 ('file', ' ', lambda x: x[0].path()),
260 ('file', ' ', lambda x: x[0].path()),
261 ('line_number', ':', lambda x: str(x[1])),
261 ('line_number', ':', lambda x: str(x[1])),
262 ]
262 ]
263
263
264 if (not opts.get('user') and not opts.get('changeset')
264 if (not opts.get('user') and not opts.get('changeset')
265 and not opts.get('date') and not opts.get('file')):
265 and not opts.get('date') and not opts.get('file')):
266 opts['number'] = True
266 opts['number'] = True
267
267
268 linenumber = opts.get('line_number') is not None
268 linenumber = opts.get('line_number') is not None
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
271
271
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274
274
275 def bad(x, y):
275 def bad(x, y):
276 raise util.Abort("%s: %s" % (x, y))
276 raise util.Abort("%s: %s" % (x, y))
277
277
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 m = scmutil.match(ctx, pats, opts)
279 m = scmutil.match(ctx, pats, opts)
280 m.bad = bad
280 m.bad = bad
281 follow = not opts.get('no_follow')
281 follow = not opts.get('no_follow')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
283 for abs in ctx.walk(m):
283 for abs in ctx.walk(m):
284 fctx = ctx[abs]
284 fctx = ctx[abs]
285 if not opts.get('text') and util.binary(fctx.data()):
285 if not opts.get('text') and util.binary(fctx.data()):
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 continue
287 continue
288
288
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 diffopts=diffopts)
290 diffopts=diffopts)
291 pieces = []
291 pieces = []
292
292
293 for f, sep in funcmap:
293 for f, sep in funcmap:
294 l = [f(n) for n, dummy in lines]
294 l = [f(n) for n, dummy in lines]
295 if l:
295 if l:
296 sized = [(x, encoding.colwidth(x)) for x in l]
296 sized = [(x, encoding.colwidth(x)) for x in l]
297 ml = max([w for x, w in sized])
297 ml = max([w for x, w in sized])
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 for x, w in sized])
299 for x, w in sized])
300
300
301 if pieces:
301 if pieces:
302 for p, l in zip(zip(*pieces), lines):
302 for p, l in zip(zip(*pieces), lines):
303 ui.write("%s: %s" % ("".join(p), l[1]))
303 ui.write("%s: %s" % ("".join(p), l[1]))
304
304
305 if lines and not lines[-1][1].endswith('\n'):
305 if lines and not lines[-1][1].endswith('\n'):
306 ui.write('\n')
306 ui.write('\n')
307
307
308 @command('archive',
308 @command('archive',
309 [('', 'no-decode', None, _('do not pass files through decoders')),
309 [('', 'no-decode', None, _('do not pass files through decoders')),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 _('PREFIX')),
311 _('PREFIX')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ] + subrepoopts + walkopts,
314 ] + subrepoopts + walkopts,
315 _('[OPTION]... DEST'))
315 _('[OPTION]... DEST'))
316 def archive(ui, repo, dest, **opts):
316 def archive(ui, repo, dest, **opts):
317 '''create an unversioned archive of a repository revision
317 '''create an unversioned archive of a repository revision
318
318
319 By default, the revision used is the parent of the working
319 By default, the revision used is the parent of the working
320 directory; use -r/--rev to specify a different revision.
320 directory; use -r/--rev to specify a different revision.
321
321
322 The archive type is automatically detected based on file
322 The archive type is automatically detected based on file
323 extension (or override using -t/--type).
323 extension (or override using -t/--type).
324
324
325 .. container:: verbose
325 .. container:: verbose
326
326
327 Examples:
327 Examples:
328
328
329 - create a zip file containing the 1.0 release::
329 - create a zip file containing the 1.0 release::
330
330
331 hg archive -r 1.0 project-1.0.zip
331 hg archive -r 1.0 project-1.0.zip
332
332
333 - create a tarball excluding .hg files::
333 - create a tarball excluding .hg files::
334
334
335 hg archive project.tar.gz -X ".hg*"
335 hg archive project.tar.gz -X ".hg*"
336
336
337 Valid types are:
337 Valid types are:
338
338
339 :``files``: a directory full of files (default)
339 :``files``: a directory full of files (default)
340 :``tar``: tar archive, uncompressed
340 :``tar``: tar archive, uncompressed
341 :``tbz2``: tar archive, compressed using bzip2
341 :``tbz2``: tar archive, compressed using bzip2
342 :``tgz``: tar archive, compressed using gzip
342 :``tgz``: tar archive, compressed using gzip
343 :``uzip``: zip archive, uncompressed
343 :``uzip``: zip archive, uncompressed
344 :``zip``: zip archive, compressed using deflate
344 :``zip``: zip archive, compressed using deflate
345
345
346 The exact name of the destination archive or directory is given
346 The exact name of the destination archive or directory is given
347 using a format string; see :hg:`help export` for details.
347 using a format string; see :hg:`help export` for details.
348
348
349 Each member added to an archive file has a directory prefix
349 Each member added to an archive file has a directory prefix
350 prepended. Use -p/--prefix to specify a format string for the
350 prepended. Use -p/--prefix to specify a format string for the
351 prefix. The default is the basename of the archive, with suffixes
351 prefix. The default is the basename of the archive, with suffixes
352 removed.
352 removed.
353
353
354 Returns 0 on success.
354 Returns 0 on success.
355 '''
355 '''
356
356
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 if not ctx:
358 if not ctx:
359 raise util.Abort(_('no working directory: please specify a revision'))
359 raise util.Abort(_('no working directory: please specify a revision'))
360 node = ctx.node()
360 node = ctx.node()
361 dest = cmdutil.makefilename(repo, dest, node)
361 dest = cmdutil.makefilename(repo, dest, node)
362 if os.path.realpath(dest) == repo.root:
362 if os.path.realpath(dest) == repo.root:
363 raise util.Abort(_('repository root cannot be destination'))
363 raise util.Abort(_('repository root cannot be destination'))
364
364
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 prefix = opts.get('prefix')
366 prefix = opts.get('prefix')
367
367
368 if dest == '-':
368 if dest == '-':
369 if kind == 'files':
369 if kind == 'files':
370 raise util.Abort(_('cannot archive plain files to stdout'))
370 raise util.Abort(_('cannot archive plain files to stdout'))
371 dest = cmdutil.makefileobj(repo, dest)
371 dest = cmdutil.makefileobj(repo, dest)
372 if not prefix:
372 if not prefix:
373 prefix = os.path.basename(repo.root) + '-%h'
373 prefix = os.path.basename(repo.root) + '-%h'
374
374
375 prefix = cmdutil.makefilename(repo, prefix, node)
375 prefix = cmdutil.makefilename(repo, prefix, node)
376 matchfn = scmutil.match(ctx, [], opts)
376 matchfn = scmutil.match(ctx, [], opts)
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 matchfn, prefix, subrepos=opts.get('subrepos'))
378 matchfn, prefix, subrepos=opts.get('subrepos'))
379
379
380 @command('backout',
380 @command('backout',
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 ('', 'parent', '',
382 ('', 'parent', '',
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 _('[OPTION]... [-r] REV'))
386 _('[OPTION]... [-r] REV'))
387 def backout(ui, repo, node=None, rev=None, **opts):
387 def backout(ui, repo, node=None, rev=None, **opts):
388 '''reverse effect of earlier changeset
388 '''reverse effect of earlier changeset
389
389
390 Prepare a new changeset with the effect of REV undone in the
390 Prepare a new changeset with the effect of REV undone in the
391 current working directory.
391 current working directory.
392
392
393 If REV is the parent of the working directory, then this new changeset
393 If REV is the parent of the working directory, then this new changeset
394 is committed automatically. Otherwise, hg needs to merge the
394 is committed automatically. Otherwise, hg needs to merge the
395 changes and the merged result is left uncommitted.
395 changes and the merged result is left uncommitted.
396
396
397 .. note::
397 .. note::
398 backout cannot be used to fix either an unwanted or
398 backout cannot be used to fix either an unwanted or
399 incorrect merge.
399 incorrect merge.
400
400
401 .. container:: verbose
401 .. container:: verbose
402
402
403 By default, the pending changeset will have one parent,
403 By default, the pending changeset will have one parent,
404 maintaining a linear history. With --merge, the pending
404 maintaining a linear history. With --merge, the pending
405 changeset will instead have two parents: the old parent of the
405 changeset will instead have two parents: the old parent of the
406 working directory and a new child of REV that simply undoes REV.
406 working directory and a new child of REV that simply undoes REV.
407
407
408 Before version 1.7, the behavior without --merge was equivalent
408 Before version 1.7, the behavior without --merge was equivalent
409 to specifying --merge followed by :hg:`update --clean .` to
409 to specifying --merge followed by :hg:`update --clean .` to
410 cancel the merge and leave the child of REV as a head to be
410 cancel the merge and leave the child of REV as a head to be
411 merged separately.
411 merged separately.
412
412
413 See :hg:`help dates` for a list of formats valid for -d/--date.
413 See :hg:`help dates` for a list of formats valid for -d/--date.
414
414
415 Returns 0 on success.
415 Returns 0 on success.
416 '''
416 '''
417 if rev and node:
417 if rev and node:
418 raise util.Abort(_("please specify just one revision"))
418 raise util.Abort(_("please specify just one revision"))
419
419
420 if not rev:
420 if not rev:
421 rev = node
421 rev = node
422
422
423 if not rev:
423 if not rev:
424 raise util.Abort(_("please specify a revision to backout"))
424 raise util.Abort(_("please specify a revision to backout"))
425
425
426 date = opts.get('date')
426 date = opts.get('date')
427 if date:
427 if date:
428 opts['date'] = util.parsedate(date)
428 opts['date'] = util.parsedate(date)
429
429
430 cmdutil.bailifchanged(repo)
430 cmdutil.bailifchanged(repo)
431 node = scmutil.revsingle(repo, rev).node()
431 node = scmutil.revsingle(repo, rev).node()
432
432
433 op1, op2 = repo.dirstate.parents()
433 op1, op2 = repo.dirstate.parents()
434 a = repo.changelog.ancestor(op1, node)
434 a = repo.changelog.ancestor(op1, node)
435 if a != node:
435 if a != node:
436 raise util.Abort(_('cannot backout change on a different branch'))
436 raise util.Abort(_('cannot backout change on a different branch'))
437
437
438 p1, p2 = repo.changelog.parents(node)
438 p1, p2 = repo.changelog.parents(node)
439 if p1 == nullid:
439 if p1 == nullid:
440 raise util.Abort(_('cannot backout a change with no parents'))
440 raise util.Abort(_('cannot backout a change with no parents'))
441 if p2 != nullid:
441 if p2 != nullid:
442 if not opts.get('parent'):
442 if not opts.get('parent'):
443 raise util.Abort(_('cannot backout a merge changeset'))
443 raise util.Abort(_('cannot backout a merge changeset'))
444 p = repo.lookup(opts['parent'])
444 p = repo.lookup(opts['parent'])
445 if p not in (p1, p2):
445 if p not in (p1, p2):
446 raise util.Abort(_('%s is not a parent of %s') %
446 raise util.Abort(_('%s is not a parent of %s') %
447 (short(p), short(node)))
447 (short(p), short(node)))
448 parent = p
448 parent = p
449 else:
449 else:
450 if opts.get('parent'):
450 if opts.get('parent'):
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 parent = p1
452 parent = p1
453
453
454 # the backout should appear on the same branch
454 # the backout should appear on the same branch
455 wlock = repo.wlock()
455 wlock = repo.wlock()
456 try:
456 try:
457 branch = repo.dirstate.branch()
457 branch = repo.dirstate.branch()
458 hg.clean(repo, node, show_stats=False)
458 hg.clean(repo, node, show_stats=False)
459 repo.dirstate.setbranch(branch)
459 repo.dirstate.setbranch(branch)
460 revert_opts = opts.copy()
460 revert_opts = opts.copy()
461 revert_opts['date'] = None
461 revert_opts['date'] = None
462 revert_opts['all'] = True
462 revert_opts['all'] = True
463 revert_opts['rev'] = hex(parent)
463 revert_opts['rev'] = hex(parent)
464 revert_opts['no_backup'] = None
464 revert_opts['no_backup'] = None
465 revert(ui, repo, **revert_opts)
465 revert(ui, repo, **revert_opts)
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 return hg.update(repo, op1)
469 return hg.update(repo, op1)
470 finally:
470 finally:
471 ui.setconfig('ui', 'forcemerge', '')
471 ui.setconfig('ui', 'forcemerge', '')
472
472
473 commit_opts = opts.copy()
473 commit_opts = opts.copy()
474 commit_opts['addremove'] = False
474 commit_opts['addremove'] = False
475 if not commit_opts['message'] and not commit_opts['logfile']:
475 if not commit_opts['message'] and not commit_opts['logfile']:
476 # we don't translate commit messages
476 # we don't translate commit messages
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
478 commit_opts['force_editor'] = True
478 commit_opts['force_editor'] = True
479 commit(ui, repo, **commit_opts)
479 commit(ui, repo, **commit_opts)
480 def nice(node):
480 def nice(node):
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
482 ui.status(_('changeset %s backs out changeset %s\n') %
482 ui.status(_('changeset %s backs out changeset %s\n') %
483 (nice(repo.changelog.tip()), nice(node)))
483 (nice(repo.changelog.tip()), nice(node)))
484 if opts.get('merge') and op1 != node:
484 if opts.get('merge') and op1 != node:
485 hg.clean(repo, op1, show_stats=False)
485 hg.clean(repo, op1, show_stats=False)
486 ui.status(_('merging with changeset %s\n')
486 ui.status(_('merging with changeset %s\n')
487 % nice(repo.changelog.tip()))
487 % nice(repo.changelog.tip()))
488 try:
488 try:
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
490 return hg.merge(repo, hex(repo.changelog.tip()))
490 return hg.merge(repo, hex(repo.changelog.tip()))
491 finally:
491 finally:
492 ui.setconfig('ui', 'forcemerge', '')
492 ui.setconfig('ui', 'forcemerge', '')
493 finally:
493 finally:
494 wlock.release()
494 wlock.release()
495 return 0
495 return 0
496
496
497 @command('bisect',
497 @command('bisect',
498 [('r', 'reset', False, _('reset bisect state')),
498 [('r', 'reset', False, _('reset bisect state')),
499 ('g', 'good', False, _('mark changeset good')),
499 ('g', 'good', False, _('mark changeset good')),
500 ('b', 'bad', False, _('mark changeset bad')),
500 ('b', 'bad', False, _('mark changeset bad')),
501 ('s', 'skip', False, _('skip testing changeset')),
501 ('s', 'skip', False, _('skip testing changeset')),
502 ('e', 'extend', False, _('extend the bisect range')),
502 ('e', 'extend', False, _('extend the bisect range')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
504 ('U', 'noupdate', False, _('do not update to target'))],
504 ('U', 'noupdate', False, _('do not update to target'))],
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
506 def bisect(ui, repo, rev=None, extra=None, command=None,
506 def bisect(ui, repo, rev=None, extra=None, command=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
508 noupdate=None):
508 noupdate=None):
509 """subdivision search of changesets
509 """subdivision search of changesets
510
510
511 This command helps to find changesets which introduce problems. To
511 This command helps to find changesets which introduce problems. To
512 use, mark the earliest changeset you know exhibits the problem as
512 use, mark the earliest changeset you know exhibits the problem as
513 bad, then mark the latest changeset which is free from the problem
513 bad, then mark the latest changeset which is free from the problem
514 as good. Bisect will update your working directory to a revision
514 as good. Bisect will update your working directory to a revision
515 for testing (unless the -U/--noupdate option is specified). Once
515 for testing (unless the -U/--noupdate option is specified). Once
516 you have performed tests, mark the working directory as good or
516 you have performed tests, mark the working directory as good or
517 bad, and bisect will either update to another candidate changeset
517 bad, and bisect will either update to another candidate changeset
518 or announce that it has found the bad revision.
518 or announce that it has found the bad revision.
519
519
520 As a shortcut, you can also use the revision argument to mark a
520 As a shortcut, you can also use the revision argument to mark a
521 revision as good or bad without checking it out first.
521 revision as good or bad without checking it out first.
522
522
523 If you supply a command, it will be used for automatic bisection.
523 If you supply a command, it will be used for automatic bisection.
524 The environment variable HG_NODE will contain the ID of the
524 The environment variable HG_NODE will contain the ID of the
525 changeset being tested. The exit status of the command will be
525 changeset being tested. The exit status of the command will be
526 used to mark revisions as good or bad: status 0 means good, 125
526 used to mark revisions as good or bad: status 0 means good, 125
527 means to skip the revision, 127 (command not found) will abort the
527 means to skip the revision, 127 (command not found) will abort the
528 bisection, and any other non-zero exit status means the revision
528 bisection, and any other non-zero exit status means the revision
529 is bad.
529 is bad.
530
530
531 .. container:: verbose
531 .. container:: verbose
532
532
533 Some examples:
533 Some examples:
534
534
535 - start a bisection with known bad revision 12, and good revision 34::
535 - start a bisection with known bad revision 12, and good revision 34::
536
536
537 hg bisect --bad 34
537 hg bisect --bad 34
538 hg bisect --good 12
538 hg bisect --good 12
539
539
540 - advance the current bisection by marking current revision as good or
540 - advance the current bisection by marking current revision as good or
541 bad::
541 bad::
542
542
543 hg bisect --good
543 hg bisect --good
544 hg bisect --bad
544 hg bisect --bad
545
545
546 - mark the current revision, or a known revision, to be skipped (e.g. if
546 - mark the current revision, or a known revision, to be skipped (e.g. if
547 that revision is not usable because of another issue)::
547 that revision is not usable because of another issue)::
548
548
549 hg bisect --skip
549 hg bisect --skip
550 hg bisect --skip 23
550 hg bisect --skip 23
551
551
552 - skip all revisions that do not touch directories ``foo`` or ``bar``
553
554 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
555
552 - forget the current bisection::
556 - forget the current bisection::
553
557
554 hg bisect --reset
558 hg bisect --reset
555
559
556 - use 'make && make tests' to automatically find the first broken
560 - use 'make && make tests' to automatically find the first broken
557 revision::
561 revision::
558
562
559 hg bisect --reset
563 hg bisect --reset
560 hg bisect --bad 34
564 hg bisect --bad 34
561 hg bisect --good 12
565 hg bisect --good 12
562 hg bisect --command 'make && make tests'
566 hg bisect --command 'make && make tests'
563
567
564 - see all changesets whose states are already known in the current
568 - see all changesets whose states are already known in the current
565 bisection::
569 bisection::
566
570
567 hg log -r "bisect(pruned)"
571 hg log -r "bisect(pruned)"
568
572
569 - see the changeset currently being bisected (especially useful
573 - see the changeset currently being bisected (especially useful
570 if running with -U/--noupdate)::
574 if running with -U/--noupdate)::
571
575
572 hg log -r "bisect(current)"
576 hg log -r "bisect(current)"
573
577
574 - see all changesets that took part in the current bisection::
578 - see all changesets that took part in the current bisection::
575
579
576 hg log -r "bisect(range)"
580 hg log -r "bisect(range)"
577
581
578 - with the graphlog extension, you can even get a nice graph::
582 - with the graphlog extension, you can even get a nice graph::
579
583
580 hg log --graph -r "bisect(range)"
584 hg log --graph -r "bisect(range)"
581
585
582 See :hg:`help revsets` for more about the `bisect()` keyword.
586 See :hg:`help revsets` for more about the `bisect()` keyword.
583
587
584 Returns 0 on success.
588 Returns 0 on success.
585 """
589 """
586 def extendbisectrange(nodes, good):
590 def extendbisectrange(nodes, good):
587 # bisect is incomplete when it ends on a merge node and
591 # bisect is incomplete when it ends on a merge node and
588 # one of the parent was not checked.
592 # one of the parent was not checked.
589 parents = repo[nodes[0]].parents()
593 parents = repo[nodes[0]].parents()
590 if len(parents) > 1:
594 if len(parents) > 1:
591 side = good and state['bad'] or state['good']
595 side = good and state['bad'] or state['good']
592 num = len(set(i.node() for i in parents) & set(side))
596 num = len(set(i.node() for i in parents) & set(side))
593 if num == 1:
597 if num == 1:
594 return parents[0].ancestor(parents[1])
598 return parents[0].ancestor(parents[1])
595 return None
599 return None
596
600
597 def print_result(nodes, good):
601 def print_result(nodes, good):
598 displayer = cmdutil.show_changeset(ui, repo, {})
602 displayer = cmdutil.show_changeset(ui, repo, {})
599 if len(nodes) == 1:
603 if len(nodes) == 1:
600 # narrowed it down to a single revision
604 # narrowed it down to a single revision
601 if good:
605 if good:
602 ui.write(_("The first good revision is:\n"))
606 ui.write(_("The first good revision is:\n"))
603 else:
607 else:
604 ui.write(_("The first bad revision is:\n"))
608 ui.write(_("The first bad revision is:\n"))
605 displayer.show(repo[nodes[0]])
609 displayer.show(repo[nodes[0]])
606 extendnode = extendbisectrange(nodes, good)
610 extendnode = extendbisectrange(nodes, good)
607 if extendnode is not None:
611 if extendnode is not None:
608 ui.write(_('Not all ancestors of this changeset have been'
612 ui.write(_('Not all ancestors of this changeset have been'
609 ' checked.\nUse bisect --extend to continue the '
613 ' checked.\nUse bisect --extend to continue the '
610 'bisection from\nthe common ancestor, %s.\n')
614 'bisection from\nthe common ancestor, %s.\n')
611 % extendnode)
615 % extendnode)
612 else:
616 else:
613 # multiple possible revisions
617 # multiple possible revisions
614 if good:
618 if good:
615 ui.write(_("Due to skipped revisions, the first "
619 ui.write(_("Due to skipped revisions, the first "
616 "good revision could be any of:\n"))
620 "good revision could be any of:\n"))
617 else:
621 else:
618 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
619 "bad revision could be any of:\n"))
623 "bad revision could be any of:\n"))
620 for n in nodes:
624 for n in nodes:
621 displayer.show(repo[n])
625 displayer.show(repo[n])
622 displayer.close()
626 displayer.close()
623
627
624 def check_state(state, interactive=True):
628 def check_state(state, interactive=True):
625 if not state['good'] or not state['bad']:
629 if not state['good'] or not state['bad']:
626 if (good or bad or skip or reset) and interactive:
630 if (good or bad or skip or reset) and interactive:
627 return
631 return
628 if not state['good']:
632 if not state['good']:
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
633 raise util.Abort(_('cannot bisect (no known good revisions)'))
630 else:
634 else:
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
635 raise util.Abort(_('cannot bisect (no known bad revisions)'))
632 return True
636 return True
633
637
634 # backward compatibility
638 # backward compatibility
635 if rev in "good bad reset init".split():
639 if rev in "good bad reset init".split():
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
640 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
637 cmd, rev, extra = rev, extra, None
641 cmd, rev, extra = rev, extra, None
638 if cmd == "good":
642 if cmd == "good":
639 good = True
643 good = True
640 elif cmd == "bad":
644 elif cmd == "bad":
641 bad = True
645 bad = True
642 else:
646 else:
643 reset = True
647 reset = True
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
648 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
645 raise util.Abort(_('incompatible arguments'))
649 raise util.Abort(_('incompatible arguments'))
646
650
647 if reset:
651 if reset:
648 p = repo.join("bisect.state")
652 p = repo.join("bisect.state")
649 if os.path.exists(p):
653 if os.path.exists(p):
650 os.unlink(p)
654 os.unlink(p)
651 return
655 return
652
656
653 state = hbisect.load_state(repo)
657 state = hbisect.load_state(repo)
654
658
655 if command:
659 if command:
656 changesets = 1
660 changesets = 1
657 try:
661 try:
658 node = state['current'][0]
662 node = state['current'][0]
659 except LookupError:
663 except LookupError:
660 if noupdate:
664 if noupdate:
661 raise util.Abort(_('current bisect revision is unknown - '
665 raise util.Abort(_('current bisect revision is unknown - '
662 'start a new bisect to fix'))
666 'start a new bisect to fix'))
663 node, p2 = repo.dirstate.parents()
667 node, p2 = repo.dirstate.parents()
664 if p2 != nullid:
668 if p2 != nullid:
665 raise util.Abort(_('current bisect revision is a merge'))
669 raise util.Abort(_('current bisect revision is a merge'))
666 try:
670 try:
667 while changesets:
671 while changesets:
668 # update state
672 # update state
669 state['current'] = [node]
673 state['current'] = [node]
670 hbisect.save_state(repo, state)
674 hbisect.save_state(repo, state)
671 status = util.system(command,
675 status = util.system(command,
672 environ={'HG_NODE': hex(node)},
676 environ={'HG_NODE': hex(node)},
673 out=ui.fout)
677 out=ui.fout)
674 if status == 125:
678 if status == 125:
675 transition = "skip"
679 transition = "skip"
676 elif status == 0:
680 elif status == 0:
677 transition = "good"
681 transition = "good"
678 # status < 0 means process was killed
682 # status < 0 means process was killed
679 elif status == 127:
683 elif status == 127:
680 raise util.Abort(_("failed to execute %s") % command)
684 raise util.Abort(_("failed to execute %s") % command)
681 elif status < 0:
685 elif status < 0:
682 raise util.Abort(_("%s killed") % command)
686 raise util.Abort(_("%s killed") % command)
683 else:
687 else:
684 transition = "bad"
688 transition = "bad"
685 ctx = scmutil.revsingle(repo, rev, node)
689 ctx = scmutil.revsingle(repo, rev, node)
686 rev = None # clear for future iterations
690 rev = None # clear for future iterations
687 state[transition].append(ctx.node())
691 state[transition].append(ctx.node())
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
692 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
689 check_state(state, interactive=False)
693 check_state(state, interactive=False)
690 # bisect
694 # bisect
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
695 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
692 # update to next check
696 # update to next check
693 node = nodes[0]
697 node = nodes[0]
694 if not noupdate:
698 if not noupdate:
695 cmdutil.bailifchanged(repo)
699 cmdutil.bailifchanged(repo)
696 hg.clean(repo, node, show_stats=False)
700 hg.clean(repo, node, show_stats=False)
697 finally:
701 finally:
698 state['current'] = [node]
702 state['current'] = [node]
699 hbisect.save_state(repo, state)
703 hbisect.save_state(repo, state)
700 print_result(nodes, good)
704 print_result(nodes, good)
701 return
705 return
702
706
703 # update state
707 # update state
704
708
705 if rev:
709 if rev:
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
710 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
707 else:
711 else:
708 nodes = [repo.lookup('.')]
712 nodes = [repo.lookup('.')]
709
713
710 if good or bad or skip:
714 if good or bad or skip:
711 if good:
715 if good:
712 state['good'] += nodes
716 state['good'] += nodes
713 elif bad:
717 elif bad:
714 state['bad'] += nodes
718 state['bad'] += nodes
715 elif skip:
719 elif skip:
716 state['skip'] += nodes
720 state['skip'] += nodes
717 hbisect.save_state(repo, state)
721 hbisect.save_state(repo, state)
718
722
719 if not check_state(state):
723 if not check_state(state):
720 return
724 return
721
725
722 # actually bisect
726 # actually bisect
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
727 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
724 if extend:
728 if extend:
725 if not changesets:
729 if not changesets:
726 extendnode = extendbisectrange(nodes, good)
730 extendnode = extendbisectrange(nodes, good)
727 if extendnode is not None:
731 if extendnode is not None:
728 ui.write(_("Extending search to changeset %d:%s\n"
732 ui.write(_("Extending search to changeset %d:%s\n"
729 % (extendnode.rev(), extendnode)))
733 % (extendnode.rev(), extendnode)))
730 state['current'] = [extendnode.node()]
734 state['current'] = [extendnode.node()]
731 hbisect.save_state(repo, state)
735 hbisect.save_state(repo, state)
732 if noupdate:
736 if noupdate:
733 return
737 return
734 cmdutil.bailifchanged(repo)
738 cmdutil.bailifchanged(repo)
735 return hg.clean(repo, extendnode.node())
739 return hg.clean(repo, extendnode.node())
736 raise util.Abort(_("nothing to extend"))
740 raise util.Abort(_("nothing to extend"))
737
741
738 if changesets == 0:
742 if changesets == 0:
739 print_result(nodes, good)
743 print_result(nodes, good)
740 else:
744 else:
741 assert len(nodes) == 1 # only a single node can be tested next
745 assert len(nodes) == 1 # only a single node can be tested next
742 node = nodes[0]
746 node = nodes[0]
743 # compute the approximate number of remaining tests
747 # compute the approximate number of remaining tests
744 tests, size = 0, 2
748 tests, size = 0, 2
745 while size <= changesets:
749 while size <= changesets:
746 tests, size = tests + 1, size * 2
750 tests, size = tests + 1, size * 2
747 rev = repo.changelog.rev(node)
751 rev = repo.changelog.rev(node)
748 ui.write(_("Testing changeset %d:%s "
752 ui.write(_("Testing changeset %d:%s "
749 "(%d changesets remaining, ~%d tests)\n")
753 "(%d changesets remaining, ~%d tests)\n")
750 % (rev, short(node), changesets, tests))
754 % (rev, short(node), changesets, tests))
751 state['current'] = [node]
755 state['current'] = [node]
752 hbisect.save_state(repo, state)
756 hbisect.save_state(repo, state)
753 if not noupdate:
757 if not noupdate:
754 cmdutil.bailifchanged(repo)
758 cmdutil.bailifchanged(repo)
755 return hg.clean(repo, node)
759 return hg.clean(repo, node)
756
760
757 @command('bookmarks',
761 @command('bookmarks',
758 [('f', 'force', False, _('force')),
762 [('f', 'force', False, _('force')),
759 ('r', 'rev', '', _('revision'), _('REV')),
763 ('r', 'rev', '', _('revision'), _('REV')),
760 ('d', 'delete', False, _('delete a given bookmark')),
764 ('d', 'delete', False, _('delete a given bookmark')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
765 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
766 ('i', 'inactive', False, _('mark a bookmark inactive'))],
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
767 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
768 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
765 rename=None, inactive=False):
769 rename=None, inactive=False):
766 '''track a line of development with movable markers
770 '''track a line of development with movable markers
767
771
768 Bookmarks are pointers to certain commits that move when committing.
772 Bookmarks are pointers to certain commits that move when committing.
769 Bookmarks are local. They can be renamed, copied and deleted. It is
773 Bookmarks are local. They can be renamed, copied and deleted. It is
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
774 possible to use :hg:`merge NAME` to merge from a given bookmark, and
771 :hg:`update NAME` to update to a given bookmark.
775 :hg:`update NAME` to update to a given bookmark.
772
776
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
777 You can use :hg:`bookmark NAME` to set a bookmark on the working
774 directory's parent revision with the given name. If you specify
778 directory's parent revision with the given name. If you specify
775 a revision using -r REV (where REV may be an existing bookmark),
779 a revision using -r REV (where REV may be an existing bookmark),
776 the bookmark is assigned to that revision.
780 the bookmark is assigned to that revision.
777
781
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
782 Bookmarks can be pushed and pulled between repositories (see :hg:`help
779 push` and :hg:`help pull`). This requires both the local and remote
783 push` and :hg:`help pull`). This requires both the local and remote
780 repositories to support bookmarks. For versions prior to 1.8, this means
784 repositories to support bookmarks. For versions prior to 1.8, this means
781 the bookmarks extension must be enabled.
785 the bookmarks extension must be enabled.
782
786
783 With -i/--inactive, the new bookmark will not be made the active
787 With -i/--inactive, the new bookmark will not be made the active
784 bookmark. If -r/--rev is given, the new bookmark will not be made
788 bookmark. If -r/--rev is given, the new bookmark will not be made
785 active even if -i/--inactive is not given. If no NAME is given, the
789 active even if -i/--inactive is not given. If no NAME is given, the
786 current active bookmark will be marked inactive.
790 current active bookmark will be marked inactive.
787 '''
791 '''
788 hexfn = ui.debugflag and hex or short
792 hexfn = ui.debugflag and hex or short
789 marks = repo._bookmarks
793 marks = repo._bookmarks
790 cur = repo.changectx('.').node()
794 cur = repo.changectx('.').node()
791
795
792 def checkformat(mark):
796 def checkformat(mark):
793 mark = mark.strip()
797 mark = mark.strip()
794 if not mark:
798 if not mark:
795 raise util.Abort(_("bookmark names cannot consist entirely of "
799 raise util.Abort(_("bookmark names cannot consist entirely of "
796 "whitespace"))
800 "whitespace"))
797 scmutil.checknewlabel(repo, mark, 'bookmark')
801 scmutil.checknewlabel(repo, mark, 'bookmark')
798 return mark
802 return mark
799
803
800 def checkconflict(repo, mark, force=False):
804 def checkconflict(repo, mark, force=False):
801 if mark in marks and not force:
805 if mark in marks and not force:
802 raise util.Abort(_("bookmark '%s' already exists "
806 raise util.Abort(_("bookmark '%s' already exists "
803 "(use -f to force)") % mark)
807 "(use -f to force)") % mark)
804 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
808 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
805 and not force):
809 and not force):
806 raise util.Abort(
810 raise util.Abort(
807 _("a bookmark cannot have the name of an existing branch"))
811 _("a bookmark cannot have the name of an existing branch"))
808
812
809 if delete and rename:
813 if delete and rename:
810 raise util.Abort(_("--delete and --rename are incompatible"))
814 raise util.Abort(_("--delete and --rename are incompatible"))
811 if delete and rev:
815 if delete and rev:
812 raise util.Abort(_("--rev is incompatible with --delete"))
816 raise util.Abort(_("--rev is incompatible with --delete"))
813 if rename and rev:
817 if rename and rev:
814 raise util.Abort(_("--rev is incompatible with --rename"))
818 raise util.Abort(_("--rev is incompatible with --rename"))
815 if mark is None and (delete or rev):
819 if mark is None and (delete or rev):
816 raise util.Abort(_("bookmark name required"))
820 raise util.Abort(_("bookmark name required"))
817
821
818 if delete:
822 if delete:
819 if mark not in marks:
823 if mark not in marks:
820 raise util.Abort(_("bookmark '%s' does not exist") % mark)
824 raise util.Abort(_("bookmark '%s' does not exist") % mark)
821 if mark == repo._bookmarkcurrent:
825 if mark == repo._bookmarkcurrent:
822 bookmarks.setcurrent(repo, None)
826 bookmarks.setcurrent(repo, None)
823 del marks[mark]
827 del marks[mark]
824 marks.write()
828 marks.write()
825
829
826 elif rename:
830 elif rename:
827 if mark is None:
831 if mark is None:
828 raise util.Abort(_("new bookmark name required"))
832 raise util.Abort(_("new bookmark name required"))
829 mark = checkformat(mark)
833 mark = checkformat(mark)
830 if rename not in marks:
834 if rename not in marks:
831 raise util.Abort(_("bookmark '%s' does not exist") % rename)
835 raise util.Abort(_("bookmark '%s' does not exist") % rename)
832 checkconflict(repo, mark, force)
836 checkconflict(repo, mark, force)
833 marks[mark] = marks[rename]
837 marks[mark] = marks[rename]
834 if repo._bookmarkcurrent == rename and not inactive:
838 if repo._bookmarkcurrent == rename and not inactive:
835 bookmarks.setcurrent(repo, mark)
839 bookmarks.setcurrent(repo, mark)
836 del marks[rename]
840 del marks[rename]
837 marks.write()
841 marks.write()
838
842
839 elif mark is not None:
843 elif mark is not None:
840 mark = checkformat(mark)
844 mark = checkformat(mark)
841 if inactive and mark == repo._bookmarkcurrent:
845 if inactive and mark == repo._bookmarkcurrent:
842 bookmarks.setcurrent(repo, None)
846 bookmarks.setcurrent(repo, None)
843 return
847 return
844 checkconflict(repo, mark, force)
848 checkconflict(repo, mark, force)
845 if rev:
849 if rev:
846 marks[mark] = scmutil.revsingle(repo, rev).node()
850 marks[mark] = scmutil.revsingle(repo, rev).node()
847 else:
851 else:
848 marks[mark] = cur
852 marks[mark] = cur
849 if not inactive and cur == marks[mark]:
853 if not inactive and cur == marks[mark]:
850 bookmarks.setcurrent(repo, mark)
854 bookmarks.setcurrent(repo, mark)
851 marks.write()
855 marks.write()
852
856
853 # Same message whether trying to deactivate the current bookmark (-i
857 # Same message whether trying to deactivate the current bookmark (-i
854 # with no NAME) or listing bookmarks
858 # with no NAME) or listing bookmarks
855 elif len(marks) == 0:
859 elif len(marks) == 0:
856 ui.status(_("no bookmarks set\n"))
860 ui.status(_("no bookmarks set\n"))
857
861
858 elif inactive:
862 elif inactive:
859 if not repo._bookmarkcurrent:
863 if not repo._bookmarkcurrent:
860 ui.status(_("no active bookmark\n"))
864 ui.status(_("no active bookmark\n"))
861 else:
865 else:
862 bookmarks.setcurrent(repo, None)
866 bookmarks.setcurrent(repo, None)
863
867
864 else: # show bookmarks
868 else: # show bookmarks
865 for bmark, n in sorted(marks.iteritems()):
869 for bmark, n in sorted(marks.iteritems()):
866 current = repo._bookmarkcurrent
870 current = repo._bookmarkcurrent
867 if bmark == current and n == cur:
871 if bmark == current and n == cur:
868 prefix, label = '*', 'bookmarks.current'
872 prefix, label = '*', 'bookmarks.current'
869 else:
873 else:
870 prefix, label = ' ', ''
874 prefix, label = ' ', ''
871
875
872 if ui.quiet:
876 if ui.quiet:
873 ui.write("%s\n" % bmark, label=label)
877 ui.write("%s\n" % bmark, label=label)
874 else:
878 else:
875 ui.write(" %s %-25s %d:%s\n" % (
879 ui.write(" %s %-25s %d:%s\n" % (
876 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
880 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
877 label=label)
881 label=label)
878
882
879 @command('branch',
883 @command('branch',
880 [('f', 'force', None,
884 [('f', 'force', None,
881 _('set branch name even if it shadows an existing branch')),
885 _('set branch name even if it shadows an existing branch')),
882 ('C', 'clean', None, _('reset branch name to parent branch name'))],
886 ('C', 'clean', None, _('reset branch name to parent branch name'))],
883 _('[-fC] [NAME]'))
887 _('[-fC] [NAME]'))
884 def branch(ui, repo, label=None, **opts):
888 def branch(ui, repo, label=None, **opts):
885 """set or show the current branch name
889 """set or show the current branch name
886
890
887 .. note::
891 .. note::
888 Branch names are permanent and global. Use :hg:`bookmark` to create a
892 Branch names are permanent and global. Use :hg:`bookmark` to create a
889 light-weight bookmark instead. See :hg:`help glossary` for more
893 light-weight bookmark instead. See :hg:`help glossary` for more
890 information about named branches and bookmarks.
894 information about named branches and bookmarks.
891
895
892 With no argument, show the current branch name. With one argument,
896 With no argument, show the current branch name. With one argument,
893 set the working directory branch name (the branch will not exist
897 set the working directory branch name (the branch will not exist
894 in the repository until the next commit). Standard practice
898 in the repository until the next commit). Standard practice
895 recommends that primary development take place on the 'default'
899 recommends that primary development take place on the 'default'
896 branch.
900 branch.
897
901
898 Unless -f/--force is specified, branch will not let you set a
902 Unless -f/--force is specified, branch will not let you set a
899 branch name that already exists, even if it's inactive.
903 branch name that already exists, even if it's inactive.
900
904
901 Use -C/--clean to reset the working directory branch to that of
905 Use -C/--clean to reset the working directory branch to that of
902 the parent of the working directory, negating a previous branch
906 the parent of the working directory, negating a previous branch
903 change.
907 change.
904
908
905 Use the command :hg:`update` to switch to an existing branch. Use
909 Use the command :hg:`update` to switch to an existing branch. Use
906 :hg:`commit --close-branch` to mark this branch as closed.
910 :hg:`commit --close-branch` to mark this branch as closed.
907
911
908 Returns 0 on success.
912 Returns 0 on success.
909 """
913 """
910 if not opts.get('clean') and not label:
914 if not opts.get('clean') and not label:
911 ui.write("%s\n" % repo.dirstate.branch())
915 ui.write("%s\n" % repo.dirstate.branch())
912 return
916 return
913
917
914 wlock = repo.wlock()
918 wlock = repo.wlock()
915 try:
919 try:
916 if opts.get('clean'):
920 if opts.get('clean'):
917 label = repo[None].p1().branch()
921 label = repo[None].p1().branch()
918 repo.dirstate.setbranch(label)
922 repo.dirstate.setbranch(label)
919 ui.status(_('reset working directory to branch %s\n') % label)
923 ui.status(_('reset working directory to branch %s\n') % label)
920 elif label:
924 elif label:
921 if not opts.get('force') and label in repo.branchmap():
925 if not opts.get('force') and label in repo.branchmap():
922 if label not in [p.branch() for p in repo.parents()]:
926 if label not in [p.branch() for p in repo.parents()]:
923 raise util.Abort(_('a branch of the same name already'
927 raise util.Abort(_('a branch of the same name already'
924 ' exists'),
928 ' exists'),
925 # i18n: "it" refers to an existing branch
929 # i18n: "it" refers to an existing branch
926 hint=_("use 'hg update' to switch to it"))
930 hint=_("use 'hg update' to switch to it"))
927 repo.dirstate.setbranch(label)
931 repo.dirstate.setbranch(label)
928 ui.status(_('marked working directory as branch %s\n') % label)
932 ui.status(_('marked working directory as branch %s\n') % label)
929 ui.status(_('(branches are permanent and global, '
933 ui.status(_('(branches are permanent and global, '
930 'did you want a bookmark?)\n'))
934 'did you want a bookmark?)\n'))
931 finally:
935 finally:
932 wlock.release()
936 wlock.release()
933
937
934 @command('branches',
938 @command('branches',
935 [('a', 'active', False, _('show only branches that have unmerged heads')),
939 [('a', 'active', False, _('show only branches that have unmerged heads')),
936 ('c', 'closed', False, _('show normal and closed branches'))],
940 ('c', 'closed', False, _('show normal and closed branches'))],
937 _('[-ac]'))
941 _('[-ac]'))
938 def branches(ui, repo, active=False, closed=False):
942 def branches(ui, repo, active=False, closed=False):
939 """list repository named branches
943 """list repository named branches
940
944
941 List the repository's named branches, indicating which ones are
945 List the repository's named branches, indicating which ones are
942 inactive. If -c/--closed is specified, also list branches which have
946 inactive. If -c/--closed is specified, also list branches which have
943 been marked closed (see :hg:`commit --close-branch`).
947 been marked closed (see :hg:`commit --close-branch`).
944
948
945 If -a/--active is specified, only show active branches. A branch
949 If -a/--active is specified, only show active branches. A branch
946 is considered active if it contains repository heads.
950 is considered active if it contains repository heads.
947
951
948 Use the command :hg:`update` to switch to an existing branch.
952 Use the command :hg:`update` to switch to an existing branch.
949
953
950 Returns 0.
954 Returns 0.
951 """
955 """
952
956
953 hexfunc = ui.debugflag and hex or short
957 hexfunc = ui.debugflag and hex or short
954
958
955 activebranches = set([repo[n].branch() for n in repo.heads()])
959 activebranches = set([repo[n].branch() for n in repo.heads()])
956 branches = []
960 branches = []
957 for tag, heads in repo.branchmap().iteritems():
961 for tag, heads in repo.branchmap().iteritems():
958 for h in reversed(heads):
962 for h in reversed(heads):
959 ctx = repo[h]
963 ctx = repo[h]
960 isopen = not ctx.closesbranch()
964 isopen = not ctx.closesbranch()
961 if isopen:
965 if isopen:
962 tip = ctx
966 tip = ctx
963 break
967 break
964 else:
968 else:
965 tip = repo[heads[-1]]
969 tip = repo[heads[-1]]
966 isactive = tag in activebranches and isopen
970 isactive = tag in activebranches and isopen
967 branches.append((tip, isactive, isopen))
971 branches.append((tip, isactive, isopen))
968 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
972 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
969 reverse=True)
973 reverse=True)
970
974
971 for ctx, isactive, isopen in branches:
975 for ctx, isactive, isopen in branches:
972 if (not active) or isactive:
976 if (not active) or isactive:
973 if isactive:
977 if isactive:
974 label = 'branches.active'
978 label = 'branches.active'
975 notice = ''
979 notice = ''
976 elif not isopen:
980 elif not isopen:
977 if not closed:
981 if not closed:
978 continue
982 continue
979 label = 'branches.closed'
983 label = 'branches.closed'
980 notice = _(' (closed)')
984 notice = _(' (closed)')
981 else:
985 else:
982 label = 'branches.inactive'
986 label = 'branches.inactive'
983 notice = _(' (inactive)')
987 notice = _(' (inactive)')
984 if ctx.branch() == repo.dirstate.branch():
988 if ctx.branch() == repo.dirstate.branch():
985 label = 'branches.current'
989 label = 'branches.current'
986 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
990 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
987 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
991 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
988 'log.changeset changeset.%s' % ctx.phasestr())
992 'log.changeset changeset.%s' % ctx.phasestr())
989 tag = ui.label(ctx.branch(), label)
993 tag = ui.label(ctx.branch(), label)
990 if ui.quiet:
994 if ui.quiet:
991 ui.write("%s\n" % tag)
995 ui.write("%s\n" % tag)
992 else:
996 else:
993 ui.write("%s %s%s\n" % (tag, rev, notice))
997 ui.write("%s %s%s\n" % (tag, rev, notice))
994
998
995 @command('bundle',
999 @command('bundle',
996 [('f', 'force', None, _('run even when the destination is unrelated')),
1000 [('f', 'force', None, _('run even when the destination is unrelated')),
997 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1001 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
998 _('REV')),
1002 _('REV')),
999 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1003 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1000 _('BRANCH')),
1004 _('BRANCH')),
1001 ('', 'base', [],
1005 ('', 'base', [],
1002 _('a base changeset assumed to be available at the destination'),
1006 _('a base changeset assumed to be available at the destination'),
1003 _('REV')),
1007 _('REV')),
1004 ('a', 'all', None, _('bundle all changesets in the repository')),
1008 ('a', 'all', None, _('bundle all changesets in the repository')),
1005 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1009 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1006 ] + remoteopts,
1010 ] + remoteopts,
1007 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1011 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1008 def bundle(ui, repo, fname, dest=None, **opts):
1012 def bundle(ui, repo, fname, dest=None, **opts):
1009 """create a changegroup file
1013 """create a changegroup file
1010
1014
1011 Generate a compressed changegroup file collecting changesets not
1015 Generate a compressed changegroup file collecting changesets not
1012 known to be in another repository.
1016 known to be in another repository.
1013
1017
1014 If you omit the destination repository, then hg assumes the
1018 If you omit the destination repository, then hg assumes the
1015 destination will have all the nodes you specify with --base
1019 destination will have all the nodes you specify with --base
1016 parameters. To create a bundle containing all changesets, use
1020 parameters. To create a bundle containing all changesets, use
1017 -a/--all (or --base null).
1021 -a/--all (or --base null).
1018
1022
1019 You can change compression method with the -t/--type option.
1023 You can change compression method with the -t/--type option.
1020 The available compression methods are: none, bzip2, and
1024 The available compression methods are: none, bzip2, and
1021 gzip (by default, bundles are compressed using bzip2).
1025 gzip (by default, bundles are compressed using bzip2).
1022
1026
1023 The bundle file can then be transferred using conventional means
1027 The bundle file can then be transferred using conventional means
1024 and applied to another repository with the unbundle or pull
1028 and applied to another repository with the unbundle or pull
1025 command. This is useful when direct push and pull are not
1029 command. This is useful when direct push and pull are not
1026 available or when exporting an entire repository is undesirable.
1030 available or when exporting an entire repository is undesirable.
1027
1031
1028 Applying bundles preserves all changeset contents including
1032 Applying bundles preserves all changeset contents including
1029 permissions, copy/rename information, and revision history.
1033 permissions, copy/rename information, and revision history.
1030
1034
1031 Returns 0 on success, 1 if no changes found.
1035 Returns 0 on success, 1 if no changes found.
1032 """
1036 """
1033 revs = None
1037 revs = None
1034 if 'rev' in opts:
1038 if 'rev' in opts:
1035 revs = scmutil.revrange(repo, opts['rev'])
1039 revs = scmutil.revrange(repo, opts['rev'])
1036
1040
1037 bundletype = opts.get('type', 'bzip2').lower()
1041 bundletype = opts.get('type', 'bzip2').lower()
1038 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1042 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1039 bundletype = btypes.get(bundletype)
1043 bundletype = btypes.get(bundletype)
1040 if bundletype not in changegroup.bundletypes:
1044 if bundletype not in changegroup.bundletypes:
1041 raise util.Abort(_('unknown bundle type specified with --type'))
1045 raise util.Abort(_('unknown bundle type specified with --type'))
1042
1046
1043 if opts.get('all'):
1047 if opts.get('all'):
1044 base = ['null']
1048 base = ['null']
1045 else:
1049 else:
1046 base = scmutil.revrange(repo, opts.get('base'))
1050 base = scmutil.revrange(repo, opts.get('base'))
1047 if base:
1051 if base:
1048 if dest:
1052 if dest:
1049 raise util.Abort(_("--base is incompatible with specifying "
1053 raise util.Abort(_("--base is incompatible with specifying "
1050 "a destination"))
1054 "a destination"))
1051 common = [repo.lookup(rev) for rev in base]
1055 common = [repo.lookup(rev) for rev in base]
1052 heads = revs and map(repo.lookup, revs) or revs
1056 heads = revs and map(repo.lookup, revs) or revs
1053 cg = repo.getbundle('bundle', heads=heads, common=common)
1057 cg = repo.getbundle('bundle', heads=heads, common=common)
1054 outgoing = None
1058 outgoing = None
1055 else:
1059 else:
1056 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1060 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1057 dest, branches = hg.parseurl(dest, opts.get('branch'))
1061 dest, branches = hg.parseurl(dest, opts.get('branch'))
1058 other = hg.peer(repo, opts, dest)
1062 other = hg.peer(repo, opts, dest)
1059 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1063 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1060 heads = revs and map(repo.lookup, revs) or revs
1064 heads = revs and map(repo.lookup, revs) or revs
1061 outgoing = discovery.findcommonoutgoing(repo, other,
1065 outgoing = discovery.findcommonoutgoing(repo, other,
1062 onlyheads=heads,
1066 onlyheads=heads,
1063 force=opts.get('force'),
1067 force=opts.get('force'),
1064 portable=True)
1068 portable=True)
1065 cg = repo.getlocalbundle('bundle', outgoing)
1069 cg = repo.getlocalbundle('bundle', outgoing)
1066 if not cg:
1070 if not cg:
1067 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1071 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1068 return 1
1072 return 1
1069
1073
1070 changegroup.writebundle(cg, fname, bundletype)
1074 changegroup.writebundle(cg, fname, bundletype)
1071
1075
1072 @command('cat',
1076 @command('cat',
1073 [('o', 'output', '',
1077 [('o', 'output', '',
1074 _('print output to file with formatted name'), _('FORMAT')),
1078 _('print output to file with formatted name'), _('FORMAT')),
1075 ('r', 'rev', '', _('print the given revision'), _('REV')),
1079 ('r', 'rev', '', _('print the given revision'), _('REV')),
1076 ('', 'decode', None, _('apply any matching decode filter')),
1080 ('', 'decode', None, _('apply any matching decode filter')),
1077 ] + walkopts,
1081 ] + walkopts,
1078 _('[OPTION]... FILE...'))
1082 _('[OPTION]... FILE...'))
1079 def cat(ui, repo, file1, *pats, **opts):
1083 def cat(ui, repo, file1, *pats, **opts):
1080 """output the current or given revision of files
1084 """output the current or given revision of files
1081
1085
1082 Print the specified files as they were at the given revision. If
1086 Print the specified files as they were at the given revision. If
1083 no revision is given, the parent of the working directory is used,
1087 no revision is given, the parent of the working directory is used,
1084 or tip if no revision is checked out.
1088 or tip if no revision is checked out.
1085
1089
1086 Output may be to a file, in which case the name of the file is
1090 Output may be to a file, in which case the name of the file is
1087 given using a format string. The formatting rules are the same as
1091 given using a format string. The formatting rules are the same as
1088 for the export command, with the following additions:
1092 for the export command, with the following additions:
1089
1093
1090 :``%s``: basename of file being printed
1094 :``%s``: basename of file being printed
1091 :``%d``: dirname of file being printed, or '.' if in repository root
1095 :``%d``: dirname of file being printed, or '.' if in repository root
1092 :``%p``: root-relative path name of file being printed
1096 :``%p``: root-relative path name of file being printed
1093
1097
1094 Returns 0 on success.
1098 Returns 0 on success.
1095 """
1099 """
1096 ctx = scmutil.revsingle(repo, opts.get('rev'))
1100 ctx = scmutil.revsingle(repo, opts.get('rev'))
1097 err = 1
1101 err = 1
1098 m = scmutil.match(ctx, (file1,) + pats, opts)
1102 m = scmutil.match(ctx, (file1,) + pats, opts)
1099 for abs in ctx.walk(m):
1103 for abs in ctx.walk(m):
1100 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1104 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1101 pathname=abs)
1105 pathname=abs)
1102 data = ctx[abs].data()
1106 data = ctx[abs].data()
1103 if opts.get('decode'):
1107 if opts.get('decode'):
1104 data = repo.wwritedata(abs, data)
1108 data = repo.wwritedata(abs, data)
1105 fp.write(data)
1109 fp.write(data)
1106 fp.close()
1110 fp.close()
1107 err = 0
1111 err = 0
1108 return err
1112 return err
1109
1113
1110 @command('^clone',
1114 @command('^clone',
1111 [('U', 'noupdate', None,
1115 [('U', 'noupdate', None,
1112 _('the clone will include an empty working copy (only a repository)')),
1116 _('the clone will include an empty working copy (only a repository)')),
1113 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1117 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1114 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1118 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1115 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1119 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1116 ('', 'pull', None, _('use pull protocol to copy metadata')),
1120 ('', 'pull', None, _('use pull protocol to copy metadata')),
1117 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1121 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1118 ] + remoteopts,
1122 ] + remoteopts,
1119 _('[OPTION]... SOURCE [DEST]'))
1123 _('[OPTION]... SOURCE [DEST]'))
1120 def clone(ui, source, dest=None, **opts):
1124 def clone(ui, source, dest=None, **opts):
1121 """make a copy of an existing repository
1125 """make a copy of an existing repository
1122
1126
1123 Create a copy of an existing repository in a new directory.
1127 Create a copy of an existing repository in a new directory.
1124
1128
1125 If no destination directory name is specified, it defaults to the
1129 If no destination directory name is specified, it defaults to the
1126 basename of the source.
1130 basename of the source.
1127
1131
1128 The location of the source is added to the new repository's
1132 The location of the source is added to the new repository's
1129 ``.hg/hgrc`` file, as the default to be used for future pulls.
1133 ``.hg/hgrc`` file, as the default to be used for future pulls.
1130
1134
1131 Only local paths and ``ssh://`` URLs are supported as
1135 Only local paths and ``ssh://`` URLs are supported as
1132 destinations. For ``ssh://`` destinations, no working directory or
1136 destinations. For ``ssh://`` destinations, no working directory or
1133 ``.hg/hgrc`` will be created on the remote side.
1137 ``.hg/hgrc`` will be created on the remote side.
1134
1138
1135 To pull only a subset of changesets, specify one or more revisions
1139 To pull only a subset of changesets, specify one or more revisions
1136 identifiers with -r/--rev or branches with -b/--branch. The
1140 identifiers with -r/--rev or branches with -b/--branch. The
1137 resulting clone will contain only the specified changesets and
1141 resulting clone will contain only the specified changesets and
1138 their ancestors. These options (or 'clone src#rev dest') imply
1142 their ancestors. These options (or 'clone src#rev dest') imply
1139 --pull, even for local source repositories. Note that specifying a
1143 --pull, even for local source repositories. Note that specifying a
1140 tag will include the tagged changeset but not the changeset
1144 tag will include the tagged changeset but not the changeset
1141 containing the tag.
1145 containing the tag.
1142
1146
1143 To check out a particular version, use -u/--update, or
1147 To check out a particular version, use -u/--update, or
1144 -U/--noupdate to create a clone with no working directory.
1148 -U/--noupdate to create a clone with no working directory.
1145
1149
1146 .. container:: verbose
1150 .. container:: verbose
1147
1151
1148 For efficiency, hardlinks are used for cloning whenever the
1152 For efficiency, hardlinks are used for cloning whenever the
1149 source and destination are on the same filesystem (note this
1153 source and destination are on the same filesystem (note this
1150 applies only to the repository data, not to the working
1154 applies only to the repository data, not to the working
1151 directory). Some filesystems, such as AFS, implement hardlinking
1155 directory). Some filesystems, such as AFS, implement hardlinking
1152 incorrectly, but do not report errors. In these cases, use the
1156 incorrectly, but do not report errors. In these cases, use the
1153 --pull option to avoid hardlinking.
1157 --pull option to avoid hardlinking.
1154
1158
1155 In some cases, you can clone repositories and the working
1159 In some cases, you can clone repositories and the working
1156 directory using full hardlinks with ::
1160 directory using full hardlinks with ::
1157
1161
1158 $ cp -al REPO REPOCLONE
1162 $ cp -al REPO REPOCLONE
1159
1163
1160 This is the fastest way to clone, but it is not always safe. The
1164 This is the fastest way to clone, but it is not always safe. The
1161 operation is not atomic (making sure REPO is not modified during
1165 operation is not atomic (making sure REPO is not modified during
1162 the operation is up to you) and you have to make sure your
1166 the operation is up to you) and you have to make sure your
1163 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1167 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1164 so). Also, this is not compatible with certain extensions that
1168 so). Also, this is not compatible with certain extensions that
1165 place their metadata under the .hg directory, such as mq.
1169 place their metadata under the .hg directory, such as mq.
1166
1170
1167 Mercurial will update the working directory to the first applicable
1171 Mercurial will update the working directory to the first applicable
1168 revision from this list:
1172 revision from this list:
1169
1173
1170 a) null if -U or the source repository has no changesets
1174 a) null if -U or the source repository has no changesets
1171 b) if -u . and the source repository is local, the first parent of
1175 b) if -u . and the source repository is local, the first parent of
1172 the source repository's working directory
1176 the source repository's working directory
1173 c) the changeset specified with -u (if a branch name, this means the
1177 c) the changeset specified with -u (if a branch name, this means the
1174 latest head of that branch)
1178 latest head of that branch)
1175 d) the changeset specified with -r
1179 d) the changeset specified with -r
1176 e) the tipmost head specified with -b
1180 e) the tipmost head specified with -b
1177 f) the tipmost head specified with the url#branch source syntax
1181 f) the tipmost head specified with the url#branch source syntax
1178 g) the tipmost head of the default branch
1182 g) the tipmost head of the default branch
1179 h) tip
1183 h) tip
1180
1184
1181 Examples:
1185 Examples:
1182
1186
1183 - clone a remote repository to a new directory named hg/::
1187 - clone a remote repository to a new directory named hg/::
1184
1188
1185 hg clone http://selenic.com/hg
1189 hg clone http://selenic.com/hg
1186
1190
1187 - create a lightweight local clone::
1191 - create a lightweight local clone::
1188
1192
1189 hg clone project/ project-feature/
1193 hg clone project/ project-feature/
1190
1194
1191 - clone from an absolute path on an ssh server (note double-slash)::
1195 - clone from an absolute path on an ssh server (note double-slash)::
1192
1196
1193 hg clone ssh://user@server//home/projects/alpha/
1197 hg clone ssh://user@server//home/projects/alpha/
1194
1198
1195 - do a high-speed clone over a LAN while checking out a
1199 - do a high-speed clone over a LAN while checking out a
1196 specified version::
1200 specified version::
1197
1201
1198 hg clone --uncompressed http://server/repo -u 1.5
1202 hg clone --uncompressed http://server/repo -u 1.5
1199
1203
1200 - create a repository without changesets after a particular revision::
1204 - create a repository without changesets after a particular revision::
1201
1205
1202 hg clone -r 04e544 experimental/ good/
1206 hg clone -r 04e544 experimental/ good/
1203
1207
1204 - clone (and track) a particular named branch::
1208 - clone (and track) a particular named branch::
1205
1209
1206 hg clone http://selenic.com/hg#stable
1210 hg clone http://selenic.com/hg#stable
1207
1211
1208 See :hg:`help urls` for details on specifying URLs.
1212 See :hg:`help urls` for details on specifying URLs.
1209
1213
1210 Returns 0 on success.
1214 Returns 0 on success.
1211 """
1215 """
1212 if opts.get('noupdate') and opts.get('updaterev'):
1216 if opts.get('noupdate') and opts.get('updaterev'):
1213 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1217 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1214
1218
1215 r = hg.clone(ui, opts, source, dest,
1219 r = hg.clone(ui, opts, source, dest,
1216 pull=opts.get('pull'),
1220 pull=opts.get('pull'),
1217 stream=opts.get('uncompressed'),
1221 stream=opts.get('uncompressed'),
1218 rev=opts.get('rev'),
1222 rev=opts.get('rev'),
1219 update=opts.get('updaterev') or not opts.get('noupdate'),
1223 update=opts.get('updaterev') or not opts.get('noupdate'),
1220 branch=opts.get('branch'))
1224 branch=opts.get('branch'))
1221
1225
1222 return r is None
1226 return r is None
1223
1227
1224 @command('^commit|ci',
1228 @command('^commit|ci',
1225 [('A', 'addremove', None,
1229 [('A', 'addremove', None,
1226 _('mark new/missing files as added/removed before committing')),
1230 _('mark new/missing files as added/removed before committing')),
1227 ('', 'close-branch', None,
1231 ('', 'close-branch', None,
1228 _('mark a branch as closed, hiding it from the branch list')),
1232 _('mark a branch as closed, hiding it from the branch list')),
1229 ('', 'amend', None, _('amend the parent of the working dir')),
1233 ('', 'amend', None, _('amend the parent of the working dir')),
1230 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1234 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1231 _('[OPTION]... [FILE]...'))
1235 _('[OPTION]... [FILE]...'))
1232 def commit(ui, repo, *pats, **opts):
1236 def commit(ui, repo, *pats, **opts):
1233 """commit the specified files or all outstanding changes
1237 """commit the specified files or all outstanding changes
1234
1238
1235 Commit changes to the given files into the repository. Unlike a
1239 Commit changes to the given files into the repository. Unlike a
1236 centralized SCM, this operation is a local operation. See
1240 centralized SCM, this operation is a local operation. See
1237 :hg:`push` for a way to actively distribute your changes.
1241 :hg:`push` for a way to actively distribute your changes.
1238
1242
1239 If a list of files is omitted, all changes reported by :hg:`status`
1243 If a list of files is omitted, all changes reported by :hg:`status`
1240 will be committed.
1244 will be committed.
1241
1245
1242 If you are committing the result of a merge, do not provide any
1246 If you are committing the result of a merge, do not provide any
1243 filenames or -I/-X filters.
1247 filenames or -I/-X filters.
1244
1248
1245 If no commit message is specified, Mercurial starts your
1249 If no commit message is specified, Mercurial starts your
1246 configured editor where you can enter a message. In case your
1250 configured editor where you can enter a message. In case your
1247 commit fails, you will find a backup of your message in
1251 commit fails, you will find a backup of your message in
1248 ``.hg/last-message.txt``.
1252 ``.hg/last-message.txt``.
1249
1253
1250 The --amend flag can be used to amend the parent of the
1254 The --amend flag can be used to amend the parent of the
1251 working directory with a new commit that contains the changes
1255 working directory with a new commit that contains the changes
1252 in the parent in addition to those currently reported by :hg:`status`,
1256 in the parent in addition to those currently reported by :hg:`status`,
1253 if there are any. The old commit is stored in a backup bundle in
1257 if there are any. The old commit is stored in a backup bundle in
1254 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1258 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1255 on how to restore it).
1259 on how to restore it).
1256
1260
1257 Message, user and date are taken from the amended commit unless
1261 Message, user and date are taken from the amended commit unless
1258 specified. When a message isn't specified on the command line,
1262 specified. When a message isn't specified on the command line,
1259 the editor will open with the message of the amended commit.
1263 the editor will open with the message of the amended commit.
1260
1264
1261 It is not possible to amend public changesets (see :hg:`help phases`)
1265 It is not possible to amend public changesets (see :hg:`help phases`)
1262 or changesets that have children.
1266 or changesets that have children.
1263
1267
1264 See :hg:`help dates` for a list of formats valid for -d/--date.
1268 See :hg:`help dates` for a list of formats valid for -d/--date.
1265
1269
1266 Returns 0 on success, 1 if nothing changed.
1270 Returns 0 on success, 1 if nothing changed.
1267 """
1271 """
1268 if opts.get('subrepos'):
1272 if opts.get('subrepos'):
1269 # Let --subrepos on the command line override config setting.
1273 # Let --subrepos on the command line override config setting.
1270 ui.setconfig('ui', 'commitsubrepos', True)
1274 ui.setconfig('ui', 'commitsubrepos', True)
1271
1275
1272 extra = {}
1276 extra = {}
1273 if opts.get('close_branch'):
1277 if opts.get('close_branch'):
1274 if repo['.'].node() not in repo.branchheads():
1278 if repo['.'].node() not in repo.branchheads():
1275 # The topo heads set is included in the branch heads set of the
1279 # The topo heads set is included in the branch heads set of the
1276 # current branch, so it's sufficient to test branchheads
1280 # current branch, so it's sufficient to test branchheads
1277 raise util.Abort(_('can only close branch heads'))
1281 raise util.Abort(_('can only close branch heads'))
1278 extra['close'] = 1
1282 extra['close'] = 1
1279
1283
1280 branch = repo[None].branch()
1284 branch = repo[None].branch()
1281 bheads = repo.branchheads(branch)
1285 bheads = repo.branchheads(branch)
1282
1286
1283 if opts.get('amend'):
1287 if opts.get('amend'):
1284 if ui.configbool('ui', 'commitsubrepos'):
1288 if ui.configbool('ui', 'commitsubrepos'):
1285 raise util.Abort(_('cannot amend recursively'))
1289 raise util.Abort(_('cannot amend recursively'))
1286
1290
1287 old = repo['.']
1291 old = repo['.']
1288 if old.phase() == phases.public:
1292 if old.phase() == phases.public:
1289 raise util.Abort(_('cannot amend public changesets'))
1293 raise util.Abort(_('cannot amend public changesets'))
1290 if len(old.parents()) > 1:
1294 if len(old.parents()) > 1:
1291 raise util.Abort(_('cannot amend merge changesets'))
1295 raise util.Abort(_('cannot amend merge changesets'))
1292 if len(repo[None].parents()) > 1:
1296 if len(repo[None].parents()) > 1:
1293 raise util.Abort(_('cannot amend while merging'))
1297 raise util.Abort(_('cannot amend while merging'))
1294 if old.children():
1298 if old.children():
1295 raise util.Abort(_('cannot amend changeset with children'))
1299 raise util.Abort(_('cannot amend changeset with children'))
1296
1300
1297 e = cmdutil.commiteditor
1301 e = cmdutil.commiteditor
1298 if opts.get('force_editor'):
1302 if opts.get('force_editor'):
1299 e = cmdutil.commitforceeditor
1303 e = cmdutil.commitforceeditor
1300
1304
1301 def commitfunc(ui, repo, message, match, opts):
1305 def commitfunc(ui, repo, message, match, opts):
1302 editor = e
1306 editor = e
1303 # message contains text from -m or -l, if it's empty,
1307 # message contains text from -m or -l, if it's empty,
1304 # open the editor with the old message
1308 # open the editor with the old message
1305 if not message:
1309 if not message:
1306 message = old.description()
1310 message = old.description()
1307 editor = cmdutil.commitforceeditor
1311 editor = cmdutil.commitforceeditor
1308 return repo.commit(message,
1312 return repo.commit(message,
1309 opts.get('user') or old.user(),
1313 opts.get('user') or old.user(),
1310 opts.get('date') or old.date(),
1314 opts.get('date') or old.date(),
1311 match,
1315 match,
1312 editor=editor,
1316 editor=editor,
1313 extra=extra)
1317 extra=extra)
1314
1318
1315 current = repo._bookmarkcurrent
1319 current = repo._bookmarkcurrent
1316 marks = old.bookmarks()
1320 marks = old.bookmarks()
1317 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1321 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1318 if node == old.node():
1322 if node == old.node():
1319 ui.status(_("nothing changed\n"))
1323 ui.status(_("nothing changed\n"))
1320 return 1
1324 return 1
1321 elif marks:
1325 elif marks:
1322 ui.debug('moving bookmarks %r from %s to %s\n' %
1326 ui.debug('moving bookmarks %r from %s to %s\n' %
1323 (marks, old.hex(), hex(node)))
1327 (marks, old.hex(), hex(node)))
1324 newmarks = repo._bookmarks
1328 newmarks = repo._bookmarks
1325 for bm in marks:
1329 for bm in marks:
1326 newmarks[bm] = node
1330 newmarks[bm] = node
1327 if bm == current:
1331 if bm == current:
1328 bookmarks.setcurrent(repo, bm)
1332 bookmarks.setcurrent(repo, bm)
1329 newmarks.write()
1333 newmarks.write()
1330 else:
1334 else:
1331 e = cmdutil.commiteditor
1335 e = cmdutil.commiteditor
1332 if opts.get('force_editor'):
1336 if opts.get('force_editor'):
1333 e = cmdutil.commitforceeditor
1337 e = cmdutil.commitforceeditor
1334
1338
1335 def commitfunc(ui, repo, message, match, opts):
1339 def commitfunc(ui, repo, message, match, opts):
1336 return repo.commit(message, opts.get('user'), opts.get('date'),
1340 return repo.commit(message, opts.get('user'), opts.get('date'),
1337 match, editor=e, extra=extra)
1341 match, editor=e, extra=extra)
1338
1342
1339 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1343 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1340
1344
1341 if not node:
1345 if not node:
1342 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1346 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1343 if stat[3]:
1347 if stat[3]:
1344 ui.status(_("nothing changed (%d missing files, see "
1348 ui.status(_("nothing changed (%d missing files, see "
1345 "'hg status')\n") % len(stat[3]))
1349 "'hg status')\n") % len(stat[3]))
1346 else:
1350 else:
1347 ui.status(_("nothing changed\n"))
1351 ui.status(_("nothing changed\n"))
1348 return 1
1352 return 1
1349
1353
1350 ctx = repo[node]
1354 ctx = repo[node]
1351 parents = ctx.parents()
1355 parents = ctx.parents()
1352
1356
1353 if (not opts.get('amend') and bheads and node not in bheads and not
1357 if (not opts.get('amend') and bheads and node not in bheads and not
1354 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1358 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1355 ui.status(_('created new head\n'))
1359 ui.status(_('created new head\n'))
1356 # The message is not printed for initial roots. For the other
1360 # The message is not printed for initial roots. For the other
1357 # changesets, it is printed in the following situations:
1361 # changesets, it is printed in the following situations:
1358 #
1362 #
1359 # Par column: for the 2 parents with ...
1363 # Par column: for the 2 parents with ...
1360 # N: null or no parent
1364 # N: null or no parent
1361 # B: parent is on another named branch
1365 # B: parent is on another named branch
1362 # C: parent is a regular non head changeset
1366 # C: parent is a regular non head changeset
1363 # H: parent was a branch head of the current branch
1367 # H: parent was a branch head of the current branch
1364 # Msg column: whether we print "created new head" message
1368 # Msg column: whether we print "created new head" message
1365 # In the following, it is assumed that there already exists some
1369 # In the following, it is assumed that there already exists some
1366 # initial branch heads of the current branch, otherwise nothing is
1370 # initial branch heads of the current branch, otherwise nothing is
1367 # printed anyway.
1371 # printed anyway.
1368 #
1372 #
1369 # Par Msg Comment
1373 # Par Msg Comment
1370 # N N y additional topo root
1374 # N N y additional topo root
1371 #
1375 #
1372 # B N y additional branch root
1376 # B N y additional branch root
1373 # C N y additional topo head
1377 # C N y additional topo head
1374 # H N n usual case
1378 # H N n usual case
1375 #
1379 #
1376 # B B y weird additional branch root
1380 # B B y weird additional branch root
1377 # C B y branch merge
1381 # C B y branch merge
1378 # H B n merge with named branch
1382 # H B n merge with named branch
1379 #
1383 #
1380 # C C y additional head from merge
1384 # C C y additional head from merge
1381 # C H n merge with a head
1385 # C H n merge with a head
1382 #
1386 #
1383 # H H n head merge: head count decreases
1387 # H H n head merge: head count decreases
1384
1388
1385 if not opts.get('close_branch'):
1389 if not opts.get('close_branch'):
1386 for r in parents:
1390 for r in parents:
1387 if r.closesbranch() and r.branch() == branch:
1391 if r.closesbranch() and r.branch() == branch:
1388 ui.status(_('reopening closed branch head %d\n') % r)
1392 ui.status(_('reopening closed branch head %d\n') % r)
1389
1393
1390 if ui.debugflag:
1394 if ui.debugflag:
1391 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1395 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1392 elif ui.verbose:
1396 elif ui.verbose:
1393 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1397 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1394
1398
1395 @command('copy|cp',
1399 @command('copy|cp',
1396 [('A', 'after', None, _('record a copy that has already occurred')),
1400 [('A', 'after', None, _('record a copy that has already occurred')),
1397 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1401 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1398 ] + walkopts + dryrunopts,
1402 ] + walkopts + dryrunopts,
1399 _('[OPTION]... [SOURCE]... DEST'))
1403 _('[OPTION]... [SOURCE]... DEST'))
1400 def copy(ui, repo, *pats, **opts):
1404 def copy(ui, repo, *pats, **opts):
1401 """mark files as copied for the next commit
1405 """mark files as copied for the next commit
1402
1406
1403 Mark dest as having copies of source files. If dest is a
1407 Mark dest as having copies of source files. If dest is a
1404 directory, copies are put in that directory. If dest is a file,
1408 directory, copies are put in that directory. If dest is a file,
1405 the source must be a single file.
1409 the source must be a single file.
1406
1410
1407 By default, this command copies the contents of files as they
1411 By default, this command copies the contents of files as they
1408 exist in the working directory. If invoked with -A/--after, the
1412 exist in the working directory. If invoked with -A/--after, the
1409 operation is recorded, but no copying is performed.
1413 operation is recorded, but no copying is performed.
1410
1414
1411 This command takes effect with the next commit. To undo a copy
1415 This command takes effect with the next commit. To undo a copy
1412 before that, see :hg:`revert`.
1416 before that, see :hg:`revert`.
1413
1417
1414 Returns 0 on success, 1 if errors are encountered.
1418 Returns 0 on success, 1 if errors are encountered.
1415 """
1419 """
1416 wlock = repo.wlock(False)
1420 wlock = repo.wlock(False)
1417 try:
1421 try:
1418 return cmdutil.copy(ui, repo, pats, opts)
1422 return cmdutil.copy(ui, repo, pats, opts)
1419 finally:
1423 finally:
1420 wlock.release()
1424 wlock.release()
1421
1425
1422 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1426 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1423 def debugancestor(ui, repo, *args):
1427 def debugancestor(ui, repo, *args):
1424 """find the ancestor revision of two revisions in a given index"""
1428 """find the ancestor revision of two revisions in a given index"""
1425 if len(args) == 3:
1429 if len(args) == 3:
1426 index, rev1, rev2 = args
1430 index, rev1, rev2 = args
1427 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1431 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1428 lookup = r.lookup
1432 lookup = r.lookup
1429 elif len(args) == 2:
1433 elif len(args) == 2:
1430 if not repo:
1434 if not repo:
1431 raise util.Abort(_("there is no Mercurial repository here "
1435 raise util.Abort(_("there is no Mercurial repository here "
1432 "(.hg not found)"))
1436 "(.hg not found)"))
1433 rev1, rev2 = args
1437 rev1, rev2 = args
1434 r = repo.changelog
1438 r = repo.changelog
1435 lookup = repo.lookup
1439 lookup = repo.lookup
1436 else:
1440 else:
1437 raise util.Abort(_('either two or three arguments required'))
1441 raise util.Abort(_('either two or three arguments required'))
1438 a = r.ancestor(lookup(rev1), lookup(rev2))
1442 a = r.ancestor(lookup(rev1), lookup(rev2))
1439 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1443 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1440
1444
1441 @command('debugbuilddag',
1445 @command('debugbuilddag',
1442 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1446 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1443 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1447 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1444 ('n', 'new-file', None, _('add new file at each rev'))],
1448 ('n', 'new-file', None, _('add new file at each rev'))],
1445 _('[OPTION]... [TEXT]'))
1449 _('[OPTION]... [TEXT]'))
1446 def debugbuilddag(ui, repo, text=None,
1450 def debugbuilddag(ui, repo, text=None,
1447 mergeable_file=False,
1451 mergeable_file=False,
1448 overwritten_file=False,
1452 overwritten_file=False,
1449 new_file=False):
1453 new_file=False):
1450 """builds a repo with a given DAG from scratch in the current empty repo
1454 """builds a repo with a given DAG from scratch in the current empty repo
1451
1455
1452 The description of the DAG is read from stdin if not given on the
1456 The description of the DAG is read from stdin if not given on the
1453 command line.
1457 command line.
1454
1458
1455 Elements:
1459 Elements:
1456
1460
1457 - "+n" is a linear run of n nodes based on the current default parent
1461 - "+n" is a linear run of n nodes based on the current default parent
1458 - "." is a single node based on the current default parent
1462 - "." is a single node based on the current default parent
1459 - "$" resets the default parent to null (implied at the start);
1463 - "$" resets the default parent to null (implied at the start);
1460 otherwise the default parent is always the last node created
1464 otherwise the default parent is always the last node created
1461 - "<p" sets the default parent to the backref p
1465 - "<p" sets the default parent to the backref p
1462 - "*p" is a fork at parent p, which is a backref
1466 - "*p" is a fork at parent p, which is a backref
1463 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1467 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1464 - "/p2" is a merge of the preceding node and p2
1468 - "/p2" is a merge of the preceding node and p2
1465 - ":tag" defines a local tag for the preceding node
1469 - ":tag" defines a local tag for the preceding node
1466 - "@branch" sets the named branch for subsequent nodes
1470 - "@branch" sets the named branch for subsequent nodes
1467 - "#...\\n" is a comment up to the end of the line
1471 - "#...\\n" is a comment up to the end of the line
1468
1472
1469 Whitespace between the above elements is ignored.
1473 Whitespace between the above elements is ignored.
1470
1474
1471 A backref is either
1475 A backref is either
1472
1476
1473 - a number n, which references the node curr-n, where curr is the current
1477 - a number n, which references the node curr-n, where curr is the current
1474 node, or
1478 node, or
1475 - the name of a local tag you placed earlier using ":tag", or
1479 - the name of a local tag you placed earlier using ":tag", or
1476 - empty to denote the default parent.
1480 - empty to denote the default parent.
1477
1481
1478 All string valued-elements are either strictly alphanumeric, or must
1482 All string valued-elements are either strictly alphanumeric, or must
1479 be enclosed in double quotes ("..."), with "\\" as escape character.
1483 be enclosed in double quotes ("..."), with "\\" as escape character.
1480 """
1484 """
1481
1485
1482 if text is None:
1486 if text is None:
1483 ui.status(_("reading DAG from stdin\n"))
1487 ui.status(_("reading DAG from stdin\n"))
1484 text = ui.fin.read()
1488 text = ui.fin.read()
1485
1489
1486 cl = repo.changelog
1490 cl = repo.changelog
1487 if len(cl) > 0:
1491 if len(cl) > 0:
1488 raise util.Abort(_('repository is not empty'))
1492 raise util.Abort(_('repository is not empty'))
1489
1493
1490 # determine number of revs in DAG
1494 # determine number of revs in DAG
1491 total = 0
1495 total = 0
1492 for type, data in dagparser.parsedag(text):
1496 for type, data in dagparser.parsedag(text):
1493 if type == 'n':
1497 if type == 'n':
1494 total += 1
1498 total += 1
1495
1499
1496 if mergeable_file:
1500 if mergeable_file:
1497 linesperrev = 2
1501 linesperrev = 2
1498 # make a file with k lines per rev
1502 # make a file with k lines per rev
1499 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1503 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1500 initialmergedlines.append("")
1504 initialmergedlines.append("")
1501
1505
1502 tags = []
1506 tags = []
1503
1507
1504 lock = tr = None
1508 lock = tr = None
1505 try:
1509 try:
1506 lock = repo.lock()
1510 lock = repo.lock()
1507 tr = repo.transaction("builddag")
1511 tr = repo.transaction("builddag")
1508
1512
1509 at = -1
1513 at = -1
1510 atbranch = 'default'
1514 atbranch = 'default'
1511 nodeids = []
1515 nodeids = []
1512 id = 0
1516 id = 0
1513 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1517 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1514 for type, data in dagparser.parsedag(text):
1518 for type, data in dagparser.parsedag(text):
1515 if type == 'n':
1519 if type == 'n':
1516 ui.note(('node %s\n' % str(data)))
1520 ui.note(('node %s\n' % str(data)))
1517 id, ps = data
1521 id, ps = data
1518
1522
1519 files = []
1523 files = []
1520 fctxs = {}
1524 fctxs = {}
1521
1525
1522 p2 = None
1526 p2 = None
1523 if mergeable_file:
1527 if mergeable_file:
1524 fn = "mf"
1528 fn = "mf"
1525 p1 = repo[ps[0]]
1529 p1 = repo[ps[0]]
1526 if len(ps) > 1:
1530 if len(ps) > 1:
1527 p2 = repo[ps[1]]
1531 p2 = repo[ps[1]]
1528 pa = p1.ancestor(p2)
1532 pa = p1.ancestor(p2)
1529 base, local, other = [x[fn].data() for x in pa, p1, p2]
1533 base, local, other = [x[fn].data() for x in pa, p1, p2]
1530 m3 = simplemerge.Merge3Text(base, local, other)
1534 m3 = simplemerge.Merge3Text(base, local, other)
1531 ml = [l.strip() for l in m3.merge_lines()]
1535 ml = [l.strip() for l in m3.merge_lines()]
1532 ml.append("")
1536 ml.append("")
1533 elif at > 0:
1537 elif at > 0:
1534 ml = p1[fn].data().split("\n")
1538 ml = p1[fn].data().split("\n")
1535 else:
1539 else:
1536 ml = initialmergedlines
1540 ml = initialmergedlines
1537 ml[id * linesperrev] += " r%i" % id
1541 ml[id * linesperrev] += " r%i" % id
1538 mergedtext = "\n".join(ml)
1542 mergedtext = "\n".join(ml)
1539 files.append(fn)
1543 files.append(fn)
1540 fctxs[fn] = context.memfilectx(fn, mergedtext)
1544 fctxs[fn] = context.memfilectx(fn, mergedtext)
1541
1545
1542 if overwritten_file:
1546 if overwritten_file:
1543 fn = "of"
1547 fn = "of"
1544 files.append(fn)
1548 files.append(fn)
1545 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1549 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1546
1550
1547 if new_file:
1551 if new_file:
1548 fn = "nf%i" % id
1552 fn = "nf%i" % id
1549 files.append(fn)
1553 files.append(fn)
1550 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1554 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1551 if len(ps) > 1:
1555 if len(ps) > 1:
1552 if not p2:
1556 if not p2:
1553 p2 = repo[ps[1]]
1557 p2 = repo[ps[1]]
1554 for fn in p2:
1558 for fn in p2:
1555 if fn.startswith("nf"):
1559 if fn.startswith("nf"):
1556 files.append(fn)
1560 files.append(fn)
1557 fctxs[fn] = p2[fn]
1561 fctxs[fn] = p2[fn]
1558
1562
1559 def fctxfn(repo, cx, path):
1563 def fctxfn(repo, cx, path):
1560 return fctxs.get(path)
1564 return fctxs.get(path)
1561
1565
1562 if len(ps) == 0 or ps[0] < 0:
1566 if len(ps) == 0 or ps[0] < 0:
1563 pars = [None, None]
1567 pars = [None, None]
1564 elif len(ps) == 1:
1568 elif len(ps) == 1:
1565 pars = [nodeids[ps[0]], None]
1569 pars = [nodeids[ps[0]], None]
1566 else:
1570 else:
1567 pars = [nodeids[p] for p in ps]
1571 pars = [nodeids[p] for p in ps]
1568 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1572 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1569 date=(id, 0),
1573 date=(id, 0),
1570 user="debugbuilddag",
1574 user="debugbuilddag",
1571 extra={'branch': atbranch})
1575 extra={'branch': atbranch})
1572 nodeid = repo.commitctx(cx)
1576 nodeid = repo.commitctx(cx)
1573 nodeids.append(nodeid)
1577 nodeids.append(nodeid)
1574 at = id
1578 at = id
1575 elif type == 'l':
1579 elif type == 'l':
1576 id, name = data
1580 id, name = data
1577 ui.note(('tag %s\n' % name))
1581 ui.note(('tag %s\n' % name))
1578 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1582 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1579 elif type == 'a':
1583 elif type == 'a':
1580 ui.note(('branch %s\n' % data))
1584 ui.note(('branch %s\n' % data))
1581 atbranch = data
1585 atbranch = data
1582 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1586 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1583 tr.close()
1587 tr.close()
1584
1588
1585 if tags:
1589 if tags:
1586 repo.opener.write("localtags", "".join(tags))
1590 repo.opener.write("localtags", "".join(tags))
1587 finally:
1591 finally:
1588 ui.progress(_('building'), None)
1592 ui.progress(_('building'), None)
1589 release(tr, lock)
1593 release(tr, lock)
1590
1594
1591 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1595 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1592 def debugbundle(ui, bundlepath, all=None, **opts):
1596 def debugbundle(ui, bundlepath, all=None, **opts):
1593 """lists the contents of a bundle"""
1597 """lists the contents of a bundle"""
1594 f = hg.openpath(ui, bundlepath)
1598 f = hg.openpath(ui, bundlepath)
1595 try:
1599 try:
1596 gen = changegroup.readbundle(f, bundlepath)
1600 gen = changegroup.readbundle(f, bundlepath)
1597 if all:
1601 if all:
1598 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1602 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1599
1603
1600 def showchunks(named):
1604 def showchunks(named):
1601 ui.write("\n%s\n" % named)
1605 ui.write("\n%s\n" % named)
1602 chain = None
1606 chain = None
1603 while True:
1607 while True:
1604 chunkdata = gen.deltachunk(chain)
1608 chunkdata = gen.deltachunk(chain)
1605 if not chunkdata:
1609 if not chunkdata:
1606 break
1610 break
1607 node = chunkdata['node']
1611 node = chunkdata['node']
1608 p1 = chunkdata['p1']
1612 p1 = chunkdata['p1']
1609 p2 = chunkdata['p2']
1613 p2 = chunkdata['p2']
1610 cs = chunkdata['cs']
1614 cs = chunkdata['cs']
1611 deltabase = chunkdata['deltabase']
1615 deltabase = chunkdata['deltabase']
1612 delta = chunkdata['delta']
1616 delta = chunkdata['delta']
1613 ui.write("%s %s %s %s %s %s\n" %
1617 ui.write("%s %s %s %s %s %s\n" %
1614 (hex(node), hex(p1), hex(p2),
1618 (hex(node), hex(p1), hex(p2),
1615 hex(cs), hex(deltabase), len(delta)))
1619 hex(cs), hex(deltabase), len(delta)))
1616 chain = node
1620 chain = node
1617
1621
1618 chunkdata = gen.changelogheader()
1622 chunkdata = gen.changelogheader()
1619 showchunks("changelog")
1623 showchunks("changelog")
1620 chunkdata = gen.manifestheader()
1624 chunkdata = gen.manifestheader()
1621 showchunks("manifest")
1625 showchunks("manifest")
1622 while True:
1626 while True:
1623 chunkdata = gen.filelogheader()
1627 chunkdata = gen.filelogheader()
1624 if not chunkdata:
1628 if not chunkdata:
1625 break
1629 break
1626 fname = chunkdata['filename']
1630 fname = chunkdata['filename']
1627 showchunks(fname)
1631 showchunks(fname)
1628 else:
1632 else:
1629 chunkdata = gen.changelogheader()
1633 chunkdata = gen.changelogheader()
1630 chain = None
1634 chain = None
1631 while True:
1635 while True:
1632 chunkdata = gen.deltachunk(chain)
1636 chunkdata = gen.deltachunk(chain)
1633 if not chunkdata:
1637 if not chunkdata:
1634 break
1638 break
1635 node = chunkdata['node']
1639 node = chunkdata['node']
1636 ui.write("%s\n" % hex(node))
1640 ui.write("%s\n" % hex(node))
1637 chain = node
1641 chain = node
1638 finally:
1642 finally:
1639 f.close()
1643 f.close()
1640
1644
1641 @command('debugcheckstate', [], '')
1645 @command('debugcheckstate', [], '')
1642 def debugcheckstate(ui, repo):
1646 def debugcheckstate(ui, repo):
1643 """validate the correctness of the current dirstate"""
1647 """validate the correctness of the current dirstate"""
1644 parent1, parent2 = repo.dirstate.parents()
1648 parent1, parent2 = repo.dirstate.parents()
1645 m1 = repo[parent1].manifest()
1649 m1 = repo[parent1].manifest()
1646 m2 = repo[parent2].manifest()
1650 m2 = repo[parent2].manifest()
1647 errors = 0
1651 errors = 0
1648 for f in repo.dirstate:
1652 for f in repo.dirstate:
1649 state = repo.dirstate[f]
1653 state = repo.dirstate[f]
1650 if state in "nr" and f not in m1:
1654 if state in "nr" and f not in m1:
1651 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1655 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1652 errors += 1
1656 errors += 1
1653 if state in "a" and f in m1:
1657 if state in "a" and f in m1:
1654 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1658 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1655 errors += 1
1659 errors += 1
1656 if state in "m" and f not in m1 and f not in m2:
1660 if state in "m" and f not in m1 and f not in m2:
1657 ui.warn(_("%s in state %s, but not in either manifest\n") %
1661 ui.warn(_("%s in state %s, but not in either manifest\n") %
1658 (f, state))
1662 (f, state))
1659 errors += 1
1663 errors += 1
1660 for f in m1:
1664 for f in m1:
1661 state = repo.dirstate[f]
1665 state = repo.dirstate[f]
1662 if state not in "nrm":
1666 if state not in "nrm":
1663 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1667 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1664 errors += 1
1668 errors += 1
1665 if errors:
1669 if errors:
1666 error = _(".hg/dirstate inconsistent with current parent's manifest")
1670 error = _(".hg/dirstate inconsistent with current parent's manifest")
1667 raise util.Abort(error)
1671 raise util.Abort(error)
1668
1672
1669 @command('debugcommands', [], _('[COMMAND]'))
1673 @command('debugcommands', [], _('[COMMAND]'))
1670 def debugcommands(ui, cmd='', *args):
1674 def debugcommands(ui, cmd='', *args):
1671 """list all available commands and options"""
1675 """list all available commands and options"""
1672 for cmd, vals in sorted(table.iteritems()):
1676 for cmd, vals in sorted(table.iteritems()):
1673 cmd = cmd.split('|')[0].strip('^')
1677 cmd = cmd.split('|')[0].strip('^')
1674 opts = ', '.join([i[1] for i in vals[1]])
1678 opts = ', '.join([i[1] for i in vals[1]])
1675 ui.write('%s: %s\n' % (cmd, opts))
1679 ui.write('%s: %s\n' % (cmd, opts))
1676
1680
1677 @command('debugcomplete',
1681 @command('debugcomplete',
1678 [('o', 'options', None, _('show the command options'))],
1682 [('o', 'options', None, _('show the command options'))],
1679 _('[-o] CMD'))
1683 _('[-o] CMD'))
1680 def debugcomplete(ui, cmd='', **opts):
1684 def debugcomplete(ui, cmd='', **opts):
1681 """returns the completion list associated with the given command"""
1685 """returns the completion list associated with the given command"""
1682
1686
1683 if opts.get('options'):
1687 if opts.get('options'):
1684 options = []
1688 options = []
1685 otables = [globalopts]
1689 otables = [globalopts]
1686 if cmd:
1690 if cmd:
1687 aliases, entry = cmdutil.findcmd(cmd, table, False)
1691 aliases, entry = cmdutil.findcmd(cmd, table, False)
1688 otables.append(entry[1])
1692 otables.append(entry[1])
1689 for t in otables:
1693 for t in otables:
1690 for o in t:
1694 for o in t:
1691 if "(DEPRECATED)" in o[3]:
1695 if "(DEPRECATED)" in o[3]:
1692 continue
1696 continue
1693 if o[0]:
1697 if o[0]:
1694 options.append('-%s' % o[0])
1698 options.append('-%s' % o[0])
1695 options.append('--%s' % o[1])
1699 options.append('--%s' % o[1])
1696 ui.write("%s\n" % "\n".join(options))
1700 ui.write("%s\n" % "\n".join(options))
1697 return
1701 return
1698
1702
1699 cmdlist = cmdutil.findpossible(cmd, table)
1703 cmdlist = cmdutil.findpossible(cmd, table)
1700 if ui.verbose:
1704 if ui.verbose:
1701 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1705 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1702 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1706 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1703
1707
1704 @command('debugdag',
1708 @command('debugdag',
1705 [('t', 'tags', None, _('use tags as labels')),
1709 [('t', 'tags', None, _('use tags as labels')),
1706 ('b', 'branches', None, _('annotate with branch names')),
1710 ('b', 'branches', None, _('annotate with branch names')),
1707 ('', 'dots', None, _('use dots for runs')),
1711 ('', 'dots', None, _('use dots for runs')),
1708 ('s', 'spaces', None, _('separate elements by spaces'))],
1712 ('s', 'spaces', None, _('separate elements by spaces'))],
1709 _('[OPTION]... [FILE [REV]...]'))
1713 _('[OPTION]... [FILE [REV]...]'))
1710 def debugdag(ui, repo, file_=None, *revs, **opts):
1714 def debugdag(ui, repo, file_=None, *revs, **opts):
1711 """format the changelog or an index DAG as a concise textual description
1715 """format the changelog or an index DAG as a concise textual description
1712
1716
1713 If you pass a revlog index, the revlog's DAG is emitted. If you list
1717 If you pass a revlog index, the revlog's DAG is emitted. If you list
1714 revision numbers, they get labeled in the output as rN.
1718 revision numbers, they get labeled in the output as rN.
1715
1719
1716 Otherwise, the changelog DAG of the current repo is emitted.
1720 Otherwise, the changelog DAG of the current repo is emitted.
1717 """
1721 """
1718 spaces = opts.get('spaces')
1722 spaces = opts.get('spaces')
1719 dots = opts.get('dots')
1723 dots = opts.get('dots')
1720 if file_:
1724 if file_:
1721 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1725 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1722 revs = set((int(r) for r in revs))
1726 revs = set((int(r) for r in revs))
1723 def events():
1727 def events():
1724 for r in rlog:
1728 for r in rlog:
1725 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1729 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1726 if p != -1)))
1730 if p != -1)))
1727 if r in revs:
1731 if r in revs:
1728 yield 'l', (r, "r%i" % r)
1732 yield 'l', (r, "r%i" % r)
1729 elif repo:
1733 elif repo:
1730 cl = repo.changelog
1734 cl = repo.changelog
1731 tags = opts.get('tags')
1735 tags = opts.get('tags')
1732 branches = opts.get('branches')
1736 branches = opts.get('branches')
1733 if tags:
1737 if tags:
1734 labels = {}
1738 labels = {}
1735 for l, n in repo.tags().items():
1739 for l, n in repo.tags().items():
1736 labels.setdefault(cl.rev(n), []).append(l)
1740 labels.setdefault(cl.rev(n), []).append(l)
1737 def events():
1741 def events():
1738 b = "default"
1742 b = "default"
1739 for r in cl:
1743 for r in cl:
1740 if branches:
1744 if branches:
1741 newb = cl.read(cl.node(r))[5]['branch']
1745 newb = cl.read(cl.node(r))[5]['branch']
1742 if newb != b:
1746 if newb != b:
1743 yield 'a', newb
1747 yield 'a', newb
1744 b = newb
1748 b = newb
1745 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1749 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1746 if p != -1)))
1750 if p != -1)))
1747 if tags:
1751 if tags:
1748 ls = labels.get(r)
1752 ls = labels.get(r)
1749 if ls:
1753 if ls:
1750 for l in ls:
1754 for l in ls:
1751 yield 'l', (r, l)
1755 yield 'l', (r, l)
1752 else:
1756 else:
1753 raise util.Abort(_('need repo for changelog dag'))
1757 raise util.Abort(_('need repo for changelog dag'))
1754
1758
1755 for line in dagparser.dagtextlines(events(),
1759 for line in dagparser.dagtextlines(events(),
1756 addspaces=spaces,
1760 addspaces=spaces,
1757 wraplabels=True,
1761 wraplabels=True,
1758 wrapannotations=True,
1762 wrapannotations=True,
1759 wrapnonlinear=dots,
1763 wrapnonlinear=dots,
1760 usedots=dots,
1764 usedots=dots,
1761 maxlinewidth=70):
1765 maxlinewidth=70):
1762 ui.write(line)
1766 ui.write(line)
1763 ui.write("\n")
1767 ui.write("\n")
1764
1768
1765 @command('debugdata',
1769 @command('debugdata',
1766 [('c', 'changelog', False, _('open changelog')),
1770 [('c', 'changelog', False, _('open changelog')),
1767 ('m', 'manifest', False, _('open manifest'))],
1771 ('m', 'manifest', False, _('open manifest'))],
1768 _('-c|-m|FILE REV'))
1772 _('-c|-m|FILE REV'))
1769 def debugdata(ui, repo, file_, rev = None, **opts):
1773 def debugdata(ui, repo, file_, rev = None, **opts):
1770 """dump the contents of a data file revision"""
1774 """dump the contents of a data file revision"""
1771 if opts.get('changelog') or opts.get('manifest'):
1775 if opts.get('changelog') or opts.get('manifest'):
1772 file_, rev = None, file_
1776 file_, rev = None, file_
1773 elif rev is None:
1777 elif rev is None:
1774 raise error.CommandError('debugdata', _('invalid arguments'))
1778 raise error.CommandError('debugdata', _('invalid arguments'))
1775 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1779 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1776 try:
1780 try:
1777 ui.write(r.revision(r.lookup(rev)))
1781 ui.write(r.revision(r.lookup(rev)))
1778 except KeyError:
1782 except KeyError:
1779 raise util.Abort(_('invalid revision identifier %s') % rev)
1783 raise util.Abort(_('invalid revision identifier %s') % rev)
1780
1784
1781 @command('debugdate',
1785 @command('debugdate',
1782 [('e', 'extended', None, _('try extended date formats'))],
1786 [('e', 'extended', None, _('try extended date formats'))],
1783 _('[-e] DATE [RANGE]'))
1787 _('[-e] DATE [RANGE]'))
1784 def debugdate(ui, date, range=None, **opts):
1788 def debugdate(ui, date, range=None, **opts):
1785 """parse and display a date"""
1789 """parse and display a date"""
1786 if opts["extended"]:
1790 if opts["extended"]:
1787 d = util.parsedate(date, util.extendeddateformats)
1791 d = util.parsedate(date, util.extendeddateformats)
1788 else:
1792 else:
1789 d = util.parsedate(date)
1793 d = util.parsedate(date)
1790 ui.write(("internal: %s %s\n") % d)
1794 ui.write(("internal: %s %s\n") % d)
1791 ui.write(("standard: %s\n") % util.datestr(d))
1795 ui.write(("standard: %s\n") % util.datestr(d))
1792 if range:
1796 if range:
1793 m = util.matchdate(range)
1797 m = util.matchdate(range)
1794 ui.write(("match: %s\n") % m(d[0]))
1798 ui.write(("match: %s\n") % m(d[0]))
1795
1799
1796 @command('debugdiscovery',
1800 @command('debugdiscovery',
1797 [('', 'old', None, _('use old-style discovery')),
1801 [('', 'old', None, _('use old-style discovery')),
1798 ('', 'nonheads', None,
1802 ('', 'nonheads', None,
1799 _('use old-style discovery with non-heads included')),
1803 _('use old-style discovery with non-heads included')),
1800 ] + remoteopts,
1804 ] + remoteopts,
1801 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1805 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1802 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1806 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1803 """runs the changeset discovery protocol in isolation"""
1807 """runs the changeset discovery protocol in isolation"""
1804 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1808 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1805 opts.get('branch'))
1809 opts.get('branch'))
1806 remote = hg.peer(repo, opts, remoteurl)
1810 remote = hg.peer(repo, opts, remoteurl)
1807 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1811 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1808
1812
1809 # make sure tests are repeatable
1813 # make sure tests are repeatable
1810 random.seed(12323)
1814 random.seed(12323)
1811
1815
1812 def doit(localheads, remoteheads, remote=remote):
1816 def doit(localheads, remoteheads, remote=remote):
1813 if opts.get('old'):
1817 if opts.get('old'):
1814 if localheads:
1818 if localheads:
1815 raise util.Abort('cannot use localheads with old style '
1819 raise util.Abort('cannot use localheads with old style '
1816 'discovery')
1820 'discovery')
1817 if not util.safehasattr(remote, 'branches'):
1821 if not util.safehasattr(remote, 'branches'):
1818 # enable in-client legacy support
1822 # enable in-client legacy support
1819 remote = localrepo.locallegacypeer(remote.local())
1823 remote = localrepo.locallegacypeer(remote.local())
1820 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1824 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1821 force=True)
1825 force=True)
1822 common = set(common)
1826 common = set(common)
1823 if not opts.get('nonheads'):
1827 if not opts.get('nonheads'):
1824 ui.write(("unpruned common: %s\n") % " ".join([short(n)
1828 ui.write(("unpruned common: %s\n") % " ".join([short(n)
1825 for n in common]))
1829 for n in common]))
1826 dag = dagutil.revlogdag(repo.changelog)
1830 dag = dagutil.revlogdag(repo.changelog)
1827 all = dag.ancestorset(dag.internalizeall(common))
1831 all = dag.ancestorset(dag.internalizeall(common))
1828 common = dag.externalizeall(dag.headsetofconnecteds(all))
1832 common = dag.externalizeall(dag.headsetofconnecteds(all))
1829 else:
1833 else:
1830 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1834 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1831 common = set(common)
1835 common = set(common)
1832 rheads = set(hds)
1836 rheads = set(hds)
1833 lheads = set(repo.heads())
1837 lheads = set(repo.heads())
1834 ui.write(("common heads: %s\n") % " ".join([short(n) for n in common]))
1838 ui.write(("common heads: %s\n") % " ".join([short(n) for n in common]))
1835 if lheads <= common:
1839 if lheads <= common:
1836 ui.write(("local is subset\n"))
1840 ui.write(("local is subset\n"))
1837 elif rheads <= common:
1841 elif rheads <= common:
1838 ui.write(("remote is subset\n"))
1842 ui.write(("remote is subset\n"))
1839
1843
1840 serverlogs = opts.get('serverlog')
1844 serverlogs = opts.get('serverlog')
1841 if serverlogs:
1845 if serverlogs:
1842 for filename in serverlogs:
1846 for filename in serverlogs:
1843 logfile = open(filename, 'r')
1847 logfile = open(filename, 'r')
1844 try:
1848 try:
1845 line = logfile.readline()
1849 line = logfile.readline()
1846 while line:
1850 while line:
1847 parts = line.strip().split(';')
1851 parts = line.strip().split(';')
1848 op = parts[1]
1852 op = parts[1]
1849 if op == 'cg':
1853 if op == 'cg':
1850 pass
1854 pass
1851 elif op == 'cgss':
1855 elif op == 'cgss':
1852 doit(parts[2].split(' '), parts[3].split(' '))
1856 doit(parts[2].split(' '), parts[3].split(' '))
1853 elif op == 'unb':
1857 elif op == 'unb':
1854 doit(parts[3].split(' '), parts[2].split(' '))
1858 doit(parts[3].split(' '), parts[2].split(' '))
1855 line = logfile.readline()
1859 line = logfile.readline()
1856 finally:
1860 finally:
1857 logfile.close()
1861 logfile.close()
1858
1862
1859 else:
1863 else:
1860 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1864 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1861 opts.get('remote_head'))
1865 opts.get('remote_head'))
1862 localrevs = opts.get('local_head')
1866 localrevs = opts.get('local_head')
1863 doit(localrevs, remoterevs)
1867 doit(localrevs, remoterevs)
1864
1868
1865 @command('debugfileset',
1869 @command('debugfileset',
1866 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1870 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1867 _('[-r REV] FILESPEC'))
1871 _('[-r REV] FILESPEC'))
1868 def debugfileset(ui, repo, expr, **opts):
1872 def debugfileset(ui, repo, expr, **opts):
1869 '''parse and apply a fileset specification'''
1873 '''parse and apply a fileset specification'''
1870 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1874 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1871 if ui.verbose:
1875 if ui.verbose:
1872 tree = fileset.parse(expr)[0]
1876 tree = fileset.parse(expr)[0]
1873 ui.note(tree, "\n")
1877 ui.note(tree, "\n")
1874
1878
1875 for f in fileset.getfileset(ctx, expr):
1879 for f in fileset.getfileset(ctx, expr):
1876 ui.write("%s\n" % f)
1880 ui.write("%s\n" % f)
1877
1881
1878 @command('debugfsinfo', [], _('[PATH]'))
1882 @command('debugfsinfo', [], _('[PATH]'))
1879 def debugfsinfo(ui, path = "."):
1883 def debugfsinfo(ui, path = "."):
1880 """show information detected about current filesystem"""
1884 """show information detected about current filesystem"""
1881 util.writefile('.debugfsinfo', '')
1885 util.writefile('.debugfsinfo', '')
1882 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1886 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1883 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1887 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1884 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1888 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1885 and 'yes' or 'no'))
1889 and 'yes' or 'no'))
1886 os.unlink('.debugfsinfo')
1890 os.unlink('.debugfsinfo')
1887
1891
1888 @command('debuggetbundle',
1892 @command('debuggetbundle',
1889 [('H', 'head', [], _('id of head node'), _('ID')),
1893 [('H', 'head', [], _('id of head node'), _('ID')),
1890 ('C', 'common', [], _('id of common node'), _('ID')),
1894 ('C', 'common', [], _('id of common node'), _('ID')),
1891 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1895 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1892 _('REPO FILE [-H|-C ID]...'))
1896 _('REPO FILE [-H|-C ID]...'))
1893 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1897 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1894 """retrieves a bundle from a repo
1898 """retrieves a bundle from a repo
1895
1899
1896 Every ID must be a full-length hex node id string. Saves the bundle to the
1900 Every ID must be a full-length hex node id string. Saves the bundle to the
1897 given file.
1901 given file.
1898 """
1902 """
1899 repo = hg.peer(ui, opts, repopath)
1903 repo = hg.peer(ui, opts, repopath)
1900 if not repo.capable('getbundle'):
1904 if not repo.capable('getbundle'):
1901 raise util.Abort("getbundle() not supported by target repository")
1905 raise util.Abort("getbundle() not supported by target repository")
1902 args = {}
1906 args = {}
1903 if common:
1907 if common:
1904 args['common'] = [bin(s) for s in common]
1908 args['common'] = [bin(s) for s in common]
1905 if head:
1909 if head:
1906 args['heads'] = [bin(s) for s in head]
1910 args['heads'] = [bin(s) for s in head]
1907 bundle = repo.getbundle('debug', **args)
1911 bundle = repo.getbundle('debug', **args)
1908
1912
1909 bundletype = opts.get('type', 'bzip2').lower()
1913 bundletype = opts.get('type', 'bzip2').lower()
1910 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1914 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1911 bundletype = btypes.get(bundletype)
1915 bundletype = btypes.get(bundletype)
1912 if bundletype not in changegroup.bundletypes:
1916 if bundletype not in changegroup.bundletypes:
1913 raise util.Abort(_('unknown bundle type specified with --type'))
1917 raise util.Abort(_('unknown bundle type specified with --type'))
1914 changegroup.writebundle(bundle, bundlepath, bundletype)
1918 changegroup.writebundle(bundle, bundlepath, bundletype)
1915
1919
1916 @command('debugignore', [], '')
1920 @command('debugignore', [], '')
1917 def debugignore(ui, repo, *values, **opts):
1921 def debugignore(ui, repo, *values, **opts):
1918 """display the combined ignore pattern"""
1922 """display the combined ignore pattern"""
1919 ignore = repo.dirstate._ignore
1923 ignore = repo.dirstate._ignore
1920 includepat = getattr(ignore, 'includepat', None)
1924 includepat = getattr(ignore, 'includepat', None)
1921 if includepat is not None:
1925 if includepat is not None:
1922 ui.write("%s\n" % includepat)
1926 ui.write("%s\n" % includepat)
1923 else:
1927 else:
1924 raise util.Abort(_("no ignore patterns found"))
1928 raise util.Abort(_("no ignore patterns found"))
1925
1929
1926 @command('debugindex',
1930 @command('debugindex',
1927 [('c', 'changelog', False, _('open changelog')),
1931 [('c', 'changelog', False, _('open changelog')),
1928 ('m', 'manifest', False, _('open manifest')),
1932 ('m', 'manifest', False, _('open manifest')),
1929 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1933 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1930 _('[-f FORMAT] -c|-m|FILE'))
1934 _('[-f FORMAT] -c|-m|FILE'))
1931 def debugindex(ui, repo, file_ = None, **opts):
1935 def debugindex(ui, repo, file_ = None, **opts):
1932 """dump the contents of an index file"""
1936 """dump the contents of an index file"""
1933 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1937 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1934 format = opts.get('format', 0)
1938 format = opts.get('format', 0)
1935 if format not in (0, 1):
1939 if format not in (0, 1):
1936 raise util.Abort(_("unknown format %d") % format)
1940 raise util.Abort(_("unknown format %d") % format)
1937
1941
1938 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1942 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1939 if generaldelta:
1943 if generaldelta:
1940 basehdr = ' delta'
1944 basehdr = ' delta'
1941 else:
1945 else:
1942 basehdr = ' base'
1946 basehdr = ' base'
1943
1947
1944 if format == 0:
1948 if format == 0:
1945 ui.write(" rev offset length " + basehdr + " linkrev"
1949 ui.write(" rev offset length " + basehdr + " linkrev"
1946 " nodeid p1 p2\n")
1950 " nodeid p1 p2\n")
1947 elif format == 1:
1951 elif format == 1:
1948 ui.write(" rev flag offset length"
1952 ui.write(" rev flag offset length"
1949 " size " + basehdr + " link p1 p2"
1953 " size " + basehdr + " link p1 p2"
1950 " nodeid\n")
1954 " nodeid\n")
1951
1955
1952 for i in r:
1956 for i in r:
1953 node = r.node(i)
1957 node = r.node(i)
1954 if generaldelta:
1958 if generaldelta:
1955 base = r.deltaparent(i)
1959 base = r.deltaparent(i)
1956 else:
1960 else:
1957 base = r.chainbase(i)
1961 base = r.chainbase(i)
1958 if format == 0:
1962 if format == 0:
1959 try:
1963 try:
1960 pp = r.parents(node)
1964 pp = r.parents(node)
1961 except Exception:
1965 except Exception:
1962 pp = [nullid, nullid]
1966 pp = [nullid, nullid]
1963 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1967 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1964 i, r.start(i), r.length(i), base, r.linkrev(i),
1968 i, r.start(i), r.length(i), base, r.linkrev(i),
1965 short(node), short(pp[0]), short(pp[1])))
1969 short(node), short(pp[0]), short(pp[1])))
1966 elif format == 1:
1970 elif format == 1:
1967 pr = r.parentrevs(i)
1971 pr = r.parentrevs(i)
1968 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1972 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1969 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1973 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1970 base, r.linkrev(i), pr[0], pr[1], short(node)))
1974 base, r.linkrev(i), pr[0], pr[1], short(node)))
1971
1975
1972 @command('debugindexdot', [], _('FILE'))
1976 @command('debugindexdot', [], _('FILE'))
1973 def debugindexdot(ui, repo, file_):
1977 def debugindexdot(ui, repo, file_):
1974 """dump an index DAG as a graphviz dot file"""
1978 """dump an index DAG as a graphviz dot file"""
1975 r = None
1979 r = None
1976 if repo:
1980 if repo:
1977 filelog = repo.file(file_)
1981 filelog = repo.file(file_)
1978 if len(filelog):
1982 if len(filelog):
1979 r = filelog
1983 r = filelog
1980 if not r:
1984 if not r:
1981 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1985 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1982 ui.write(("digraph G {\n"))
1986 ui.write(("digraph G {\n"))
1983 for i in r:
1987 for i in r:
1984 node = r.node(i)
1988 node = r.node(i)
1985 pp = r.parents(node)
1989 pp = r.parents(node)
1986 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1990 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1987 if pp[1] != nullid:
1991 if pp[1] != nullid:
1988 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1992 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1989 ui.write("}\n")
1993 ui.write("}\n")
1990
1994
1991 @command('debuginstall', [], '')
1995 @command('debuginstall', [], '')
1992 def debuginstall(ui):
1996 def debuginstall(ui):
1993 '''test Mercurial installation
1997 '''test Mercurial installation
1994
1998
1995 Returns 0 on success.
1999 Returns 0 on success.
1996 '''
2000 '''
1997
2001
1998 def writetemp(contents):
2002 def writetemp(contents):
1999 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2003 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2000 f = os.fdopen(fd, "wb")
2004 f = os.fdopen(fd, "wb")
2001 f.write(contents)
2005 f.write(contents)
2002 f.close()
2006 f.close()
2003 return name
2007 return name
2004
2008
2005 problems = 0
2009 problems = 0
2006
2010
2007 # encoding
2011 # encoding
2008 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2012 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2009 try:
2013 try:
2010 encoding.fromlocal("test")
2014 encoding.fromlocal("test")
2011 except util.Abort, inst:
2015 except util.Abort, inst:
2012 ui.write(" %s\n" % inst)
2016 ui.write(" %s\n" % inst)
2013 ui.write(_(" (check that your locale is properly set)\n"))
2017 ui.write(_(" (check that your locale is properly set)\n"))
2014 problems += 1
2018 problems += 1
2015
2019
2016 # Python lib
2020 # Python lib
2017 ui.status(_("checking Python lib (%s)...\n")
2021 ui.status(_("checking Python lib (%s)...\n")
2018 % os.path.dirname(os.__file__))
2022 % os.path.dirname(os.__file__))
2019
2023
2020 # compiled modules
2024 # compiled modules
2021 ui.status(_("checking installed modules (%s)...\n")
2025 ui.status(_("checking installed modules (%s)...\n")
2022 % os.path.dirname(__file__))
2026 % os.path.dirname(__file__))
2023 try:
2027 try:
2024 import bdiff, mpatch, base85, osutil
2028 import bdiff, mpatch, base85, osutil
2025 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2029 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2026 except Exception, inst:
2030 except Exception, inst:
2027 ui.write(" %s\n" % inst)
2031 ui.write(" %s\n" % inst)
2028 ui.write(_(" One or more extensions could not be found"))
2032 ui.write(_(" One or more extensions could not be found"))
2029 ui.write(_(" (check that you compiled the extensions)\n"))
2033 ui.write(_(" (check that you compiled the extensions)\n"))
2030 problems += 1
2034 problems += 1
2031
2035
2032 # templates
2036 # templates
2033 import templater
2037 import templater
2034 p = templater.templatepath()
2038 p = templater.templatepath()
2035 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2039 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2036 try:
2040 try:
2037 templater.templater(templater.templatepath("map-cmdline.default"))
2041 templater.templater(templater.templatepath("map-cmdline.default"))
2038 except Exception, inst:
2042 except Exception, inst:
2039 ui.write(" %s\n" % inst)
2043 ui.write(" %s\n" % inst)
2040 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2044 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2041 problems += 1
2045 problems += 1
2042
2046
2043 # editor
2047 # editor
2044 ui.status(_("checking commit editor...\n"))
2048 ui.status(_("checking commit editor...\n"))
2045 editor = ui.geteditor()
2049 editor = ui.geteditor()
2046 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2050 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2047 if not cmdpath:
2051 if not cmdpath:
2048 if editor == 'vi':
2052 if editor == 'vi':
2049 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2053 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2050 ui.write(_(" (specify a commit editor in your configuration"
2054 ui.write(_(" (specify a commit editor in your configuration"
2051 " file)\n"))
2055 " file)\n"))
2052 else:
2056 else:
2053 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2057 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2054 ui.write(_(" (specify a commit editor in your configuration"
2058 ui.write(_(" (specify a commit editor in your configuration"
2055 " file)\n"))
2059 " file)\n"))
2056 problems += 1
2060 problems += 1
2057
2061
2058 # check username
2062 # check username
2059 ui.status(_("checking username...\n"))
2063 ui.status(_("checking username...\n"))
2060 try:
2064 try:
2061 ui.username()
2065 ui.username()
2062 except util.Abort, e:
2066 except util.Abort, e:
2063 ui.write(" %s\n" % e)
2067 ui.write(" %s\n" % e)
2064 ui.write(_(" (specify a username in your configuration file)\n"))
2068 ui.write(_(" (specify a username in your configuration file)\n"))
2065 problems += 1
2069 problems += 1
2066
2070
2067 if not problems:
2071 if not problems:
2068 ui.status(_("no problems detected\n"))
2072 ui.status(_("no problems detected\n"))
2069 else:
2073 else:
2070 ui.write(_("%s problems detected,"
2074 ui.write(_("%s problems detected,"
2071 " please check your install!\n") % problems)
2075 " please check your install!\n") % problems)
2072
2076
2073 return problems
2077 return problems
2074
2078
2075 @command('debugknown', [], _('REPO ID...'))
2079 @command('debugknown', [], _('REPO ID...'))
2076 def debugknown(ui, repopath, *ids, **opts):
2080 def debugknown(ui, repopath, *ids, **opts):
2077 """test whether node ids are known to a repo
2081 """test whether node ids are known to a repo
2078
2082
2079 Every ID must be a full-length hex node id string. Returns a list of 0s
2083 Every ID must be a full-length hex node id string. Returns a list of 0s
2080 and 1s indicating unknown/known.
2084 and 1s indicating unknown/known.
2081 """
2085 """
2082 repo = hg.peer(ui, opts, repopath)
2086 repo = hg.peer(ui, opts, repopath)
2083 if not repo.capable('known'):
2087 if not repo.capable('known'):
2084 raise util.Abort("known() not supported by target repository")
2088 raise util.Abort("known() not supported by target repository")
2085 flags = repo.known([bin(s) for s in ids])
2089 flags = repo.known([bin(s) for s in ids])
2086 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2090 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2087
2091
2088 @command('debugobsolete',
2092 @command('debugobsolete',
2089 [('', 'flags', 0, _('markers flag')),
2093 [('', 'flags', 0, _('markers flag')),
2090 ] + commitopts2,
2094 ] + commitopts2,
2091 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2095 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2092 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2096 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2093 """create arbitrary obsolete marker"""
2097 """create arbitrary obsolete marker"""
2094 def parsenodeid(s):
2098 def parsenodeid(s):
2095 try:
2099 try:
2096 # We do not use revsingle/revrange functions here to accept
2100 # We do not use revsingle/revrange functions here to accept
2097 # arbitrary node identifiers, possibly not present in the
2101 # arbitrary node identifiers, possibly not present in the
2098 # local repository.
2102 # local repository.
2099 n = bin(s)
2103 n = bin(s)
2100 if len(n) != len(nullid):
2104 if len(n) != len(nullid):
2101 raise TypeError()
2105 raise TypeError()
2102 return n
2106 return n
2103 except TypeError:
2107 except TypeError:
2104 raise util.Abort('changeset references must be full hexadecimal '
2108 raise util.Abort('changeset references must be full hexadecimal '
2105 'node identifiers')
2109 'node identifiers')
2106
2110
2107 if precursor is not None:
2111 if precursor is not None:
2108 metadata = {}
2112 metadata = {}
2109 if 'date' in opts:
2113 if 'date' in opts:
2110 metadata['date'] = opts['date']
2114 metadata['date'] = opts['date']
2111 metadata['user'] = opts['user'] or ui.username()
2115 metadata['user'] = opts['user'] or ui.username()
2112 succs = tuple(parsenodeid(succ) for succ in successors)
2116 succs = tuple(parsenodeid(succ) for succ in successors)
2113 l = repo.lock()
2117 l = repo.lock()
2114 try:
2118 try:
2115 tr = repo.transaction('debugobsolete')
2119 tr = repo.transaction('debugobsolete')
2116 try:
2120 try:
2117 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2121 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2118 opts['flags'], metadata)
2122 opts['flags'], metadata)
2119 tr.close()
2123 tr.close()
2120 finally:
2124 finally:
2121 tr.release()
2125 tr.release()
2122 finally:
2126 finally:
2123 l.release()
2127 l.release()
2124 else:
2128 else:
2125 for m in obsolete.allmarkers(repo):
2129 for m in obsolete.allmarkers(repo):
2126 ui.write(hex(m.precnode()))
2130 ui.write(hex(m.precnode()))
2127 for repl in m.succnodes():
2131 for repl in m.succnodes():
2128 ui.write(' ')
2132 ui.write(' ')
2129 ui.write(hex(repl))
2133 ui.write(hex(repl))
2130 ui.write(' %X ' % m._data[2])
2134 ui.write(' %X ' % m._data[2])
2131 ui.write(m.metadata())
2135 ui.write(m.metadata())
2132 ui.write('\n')
2136 ui.write('\n')
2133
2137
2134 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2138 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2135 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2139 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2136 '''access the pushkey key/value protocol
2140 '''access the pushkey key/value protocol
2137
2141
2138 With two args, list the keys in the given namespace.
2142 With two args, list the keys in the given namespace.
2139
2143
2140 With five args, set a key to new if it currently is set to old.
2144 With five args, set a key to new if it currently is set to old.
2141 Reports success or failure.
2145 Reports success or failure.
2142 '''
2146 '''
2143
2147
2144 target = hg.peer(ui, {}, repopath)
2148 target = hg.peer(ui, {}, repopath)
2145 if keyinfo:
2149 if keyinfo:
2146 key, old, new = keyinfo
2150 key, old, new = keyinfo
2147 r = target.pushkey(namespace, key, old, new)
2151 r = target.pushkey(namespace, key, old, new)
2148 ui.status(str(r) + '\n')
2152 ui.status(str(r) + '\n')
2149 return not r
2153 return not r
2150 else:
2154 else:
2151 for k, v in target.listkeys(namespace).iteritems():
2155 for k, v in target.listkeys(namespace).iteritems():
2152 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2156 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2153 v.encode('string-escape')))
2157 v.encode('string-escape')))
2154
2158
2155 @command('debugpvec', [], _('A B'))
2159 @command('debugpvec', [], _('A B'))
2156 def debugpvec(ui, repo, a, b=None):
2160 def debugpvec(ui, repo, a, b=None):
2157 ca = scmutil.revsingle(repo, a)
2161 ca = scmutil.revsingle(repo, a)
2158 cb = scmutil.revsingle(repo, b)
2162 cb = scmutil.revsingle(repo, b)
2159 pa = pvec.ctxpvec(ca)
2163 pa = pvec.ctxpvec(ca)
2160 pb = pvec.ctxpvec(cb)
2164 pb = pvec.ctxpvec(cb)
2161 if pa == pb:
2165 if pa == pb:
2162 rel = "="
2166 rel = "="
2163 elif pa > pb:
2167 elif pa > pb:
2164 rel = ">"
2168 rel = ">"
2165 elif pa < pb:
2169 elif pa < pb:
2166 rel = "<"
2170 rel = "<"
2167 elif pa | pb:
2171 elif pa | pb:
2168 rel = "|"
2172 rel = "|"
2169 ui.write(_("a: %s\n") % pa)
2173 ui.write(_("a: %s\n") % pa)
2170 ui.write(_("b: %s\n") % pb)
2174 ui.write(_("b: %s\n") % pb)
2171 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2175 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2172 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2176 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2173 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2177 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2174 pa.distance(pb), rel))
2178 pa.distance(pb), rel))
2175
2179
2176 @command('debugrebuildstate',
2180 @command('debugrebuildstate',
2177 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2181 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2178 _('[-r REV] [REV]'))
2182 _('[-r REV] [REV]'))
2179 def debugrebuildstate(ui, repo, rev="tip"):
2183 def debugrebuildstate(ui, repo, rev="tip"):
2180 """rebuild the dirstate as it would look like for the given revision"""
2184 """rebuild the dirstate as it would look like for the given revision"""
2181 ctx = scmutil.revsingle(repo, rev)
2185 ctx = scmutil.revsingle(repo, rev)
2182 wlock = repo.wlock()
2186 wlock = repo.wlock()
2183 try:
2187 try:
2184 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2188 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2185 finally:
2189 finally:
2186 wlock.release()
2190 wlock.release()
2187
2191
2188 @command('debugrename',
2192 @command('debugrename',
2189 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2193 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2190 _('[-r REV] FILE'))
2194 _('[-r REV] FILE'))
2191 def debugrename(ui, repo, file1, *pats, **opts):
2195 def debugrename(ui, repo, file1, *pats, **opts):
2192 """dump rename information"""
2196 """dump rename information"""
2193
2197
2194 ctx = scmutil.revsingle(repo, opts.get('rev'))
2198 ctx = scmutil.revsingle(repo, opts.get('rev'))
2195 m = scmutil.match(ctx, (file1,) + pats, opts)
2199 m = scmutil.match(ctx, (file1,) + pats, opts)
2196 for abs in ctx.walk(m):
2200 for abs in ctx.walk(m):
2197 fctx = ctx[abs]
2201 fctx = ctx[abs]
2198 o = fctx.filelog().renamed(fctx.filenode())
2202 o = fctx.filelog().renamed(fctx.filenode())
2199 rel = m.rel(abs)
2203 rel = m.rel(abs)
2200 if o:
2204 if o:
2201 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2205 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2202 else:
2206 else:
2203 ui.write(_("%s not renamed\n") % rel)
2207 ui.write(_("%s not renamed\n") % rel)
2204
2208
2205 @command('debugrevlog',
2209 @command('debugrevlog',
2206 [('c', 'changelog', False, _('open changelog')),
2210 [('c', 'changelog', False, _('open changelog')),
2207 ('m', 'manifest', False, _('open manifest')),
2211 ('m', 'manifest', False, _('open manifest')),
2208 ('d', 'dump', False, _('dump index data'))],
2212 ('d', 'dump', False, _('dump index data'))],
2209 _('-c|-m|FILE'))
2213 _('-c|-m|FILE'))
2210 def debugrevlog(ui, repo, file_ = None, **opts):
2214 def debugrevlog(ui, repo, file_ = None, **opts):
2211 """show data and statistics about a revlog"""
2215 """show data and statistics about a revlog"""
2212 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2216 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2213
2217
2214 if opts.get("dump"):
2218 if opts.get("dump"):
2215 numrevs = len(r)
2219 numrevs = len(r)
2216 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2220 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2217 " rawsize totalsize compression heads\n")
2221 " rawsize totalsize compression heads\n")
2218 ts = 0
2222 ts = 0
2219 heads = set()
2223 heads = set()
2220 for rev in xrange(numrevs):
2224 for rev in xrange(numrevs):
2221 dbase = r.deltaparent(rev)
2225 dbase = r.deltaparent(rev)
2222 if dbase == -1:
2226 if dbase == -1:
2223 dbase = rev
2227 dbase = rev
2224 cbase = r.chainbase(rev)
2228 cbase = r.chainbase(rev)
2225 p1, p2 = r.parentrevs(rev)
2229 p1, p2 = r.parentrevs(rev)
2226 rs = r.rawsize(rev)
2230 rs = r.rawsize(rev)
2227 ts = ts + rs
2231 ts = ts + rs
2228 heads -= set(r.parentrevs(rev))
2232 heads -= set(r.parentrevs(rev))
2229 heads.add(rev)
2233 heads.add(rev)
2230 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2234 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2231 (rev, p1, p2, r.start(rev), r.end(rev),
2235 (rev, p1, p2, r.start(rev), r.end(rev),
2232 r.start(dbase), r.start(cbase),
2236 r.start(dbase), r.start(cbase),
2233 r.start(p1), r.start(p2),
2237 r.start(p1), r.start(p2),
2234 rs, ts, ts / r.end(rev), len(heads)))
2238 rs, ts, ts / r.end(rev), len(heads)))
2235 return 0
2239 return 0
2236
2240
2237 v = r.version
2241 v = r.version
2238 format = v & 0xFFFF
2242 format = v & 0xFFFF
2239 flags = []
2243 flags = []
2240 gdelta = False
2244 gdelta = False
2241 if v & revlog.REVLOGNGINLINEDATA:
2245 if v & revlog.REVLOGNGINLINEDATA:
2242 flags.append('inline')
2246 flags.append('inline')
2243 if v & revlog.REVLOGGENERALDELTA:
2247 if v & revlog.REVLOGGENERALDELTA:
2244 gdelta = True
2248 gdelta = True
2245 flags.append('generaldelta')
2249 flags.append('generaldelta')
2246 if not flags:
2250 if not flags:
2247 flags = ['(none)']
2251 flags = ['(none)']
2248
2252
2249 nummerges = 0
2253 nummerges = 0
2250 numfull = 0
2254 numfull = 0
2251 numprev = 0
2255 numprev = 0
2252 nump1 = 0
2256 nump1 = 0
2253 nump2 = 0
2257 nump2 = 0
2254 numother = 0
2258 numother = 0
2255 nump1prev = 0
2259 nump1prev = 0
2256 nump2prev = 0
2260 nump2prev = 0
2257 chainlengths = []
2261 chainlengths = []
2258
2262
2259 datasize = [None, 0, 0L]
2263 datasize = [None, 0, 0L]
2260 fullsize = [None, 0, 0L]
2264 fullsize = [None, 0, 0L]
2261 deltasize = [None, 0, 0L]
2265 deltasize = [None, 0, 0L]
2262
2266
2263 def addsize(size, l):
2267 def addsize(size, l):
2264 if l[0] is None or size < l[0]:
2268 if l[0] is None or size < l[0]:
2265 l[0] = size
2269 l[0] = size
2266 if size > l[1]:
2270 if size > l[1]:
2267 l[1] = size
2271 l[1] = size
2268 l[2] += size
2272 l[2] += size
2269
2273
2270 numrevs = len(r)
2274 numrevs = len(r)
2271 for rev in xrange(numrevs):
2275 for rev in xrange(numrevs):
2272 p1, p2 = r.parentrevs(rev)
2276 p1, p2 = r.parentrevs(rev)
2273 delta = r.deltaparent(rev)
2277 delta = r.deltaparent(rev)
2274 if format > 0:
2278 if format > 0:
2275 addsize(r.rawsize(rev), datasize)
2279 addsize(r.rawsize(rev), datasize)
2276 if p2 != nullrev:
2280 if p2 != nullrev:
2277 nummerges += 1
2281 nummerges += 1
2278 size = r.length(rev)
2282 size = r.length(rev)
2279 if delta == nullrev:
2283 if delta == nullrev:
2280 chainlengths.append(0)
2284 chainlengths.append(0)
2281 numfull += 1
2285 numfull += 1
2282 addsize(size, fullsize)
2286 addsize(size, fullsize)
2283 else:
2287 else:
2284 chainlengths.append(chainlengths[delta] + 1)
2288 chainlengths.append(chainlengths[delta] + 1)
2285 addsize(size, deltasize)
2289 addsize(size, deltasize)
2286 if delta == rev - 1:
2290 if delta == rev - 1:
2287 numprev += 1
2291 numprev += 1
2288 if delta == p1:
2292 if delta == p1:
2289 nump1prev += 1
2293 nump1prev += 1
2290 elif delta == p2:
2294 elif delta == p2:
2291 nump2prev += 1
2295 nump2prev += 1
2292 elif delta == p1:
2296 elif delta == p1:
2293 nump1 += 1
2297 nump1 += 1
2294 elif delta == p2:
2298 elif delta == p2:
2295 nump2 += 1
2299 nump2 += 1
2296 elif delta != nullrev:
2300 elif delta != nullrev:
2297 numother += 1
2301 numother += 1
2298
2302
2299 # Adjust size min value for empty cases
2303 # Adjust size min value for empty cases
2300 for size in (datasize, fullsize, deltasize):
2304 for size in (datasize, fullsize, deltasize):
2301 if size[0] is None:
2305 if size[0] is None:
2302 size[0] = 0
2306 size[0] = 0
2303
2307
2304 numdeltas = numrevs - numfull
2308 numdeltas = numrevs - numfull
2305 numoprev = numprev - nump1prev - nump2prev
2309 numoprev = numprev - nump1prev - nump2prev
2306 totalrawsize = datasize[2]
2310 totalrawsize = datasize[2]
2307 datasize[2] /= numrevs
2311 datasize[2] /= numrevs
2308 fulltotal = fullsize[2]
2312 fulltotal = fullsize[2]
2309 fullsize[2] /= numfull
2313 fullsize[2] /= numfull
2310 deltatotal = deltasize[2]
2314 deltatotal = deltasize[2]
2311 if numrevs - numfull > 0:
2315 if numrevs - numfull > 0:
2312 deltasize[2] /= numrevs - numfull
2316 deltasize[2] /= numrevs - numfull
2313 totalsize = fulltotal + deltatotal
2317 totalsize = fulltotal + deltatotal
2314 avgchainlen = sum(chainlengths) / numrevs
2318 avgchainlen = sum(chainlengths) / numrevs
2315 compratio = totalrawsize / totalsize
2319 compratio = totalrawsize / totalsize
2316
2320
2317 basedfmtstr = '%%%dd\n'
2321 basedfmtstr = '%%%dd\n'
2318 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2322 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2319
2323
2320 def dfmtstr(max):
2324 def dfmtstr(max):
2321 return basedfmtstr % len(str(max))
2325 return basedfmtstr % len(str(max))
2322 def pcfmtstr(max, padding=0):
2326 def pcfmtstr(max, padding=0):
2323 return basepcfmtstr % (len(str(max)), ' ' * padding)
2327 return basepcfmtstr % (len(str(max)), ' ' * padding)
2324
2328
2325 def pcfmt(value, total):
2329 def pcfmt(value, total):
2326 return (value, 100 * float(value) / total)
2330 return (value, 100 * float(value) / total)
2327
2331
2328 ui.write(('format : %d\n') % format)
2332 ui.write(('format : %d\n') % format)
2329 ui.write(('flags : %s\n') % ', '.join(flags))
2333 ui.write(('flags : %s\n') % ', '.join(flags))
2330
2334
2331 ui.write('\n')
2335 ui.write('\n')
2332 fmt = pcfmtstr(totalsize)
2336 fmt = pcfmtstr(totalsize)
2333 fmt2 = dfmtstr(totalsize)
2337 fmt2 = dfmtstr(totalsize)
2334 ui.write(('revisions : ') + fmt2 % numrevs)
2338 ui.write(('revisions : ') + fmt2 % numrevs)
2335 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2339 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2336 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2340 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2337 ui.write(('revisions : ') + fmt2 % numrevs)
2341 ui.write(('revisions : ') + fmt2 % numrevs)
2338 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2342 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2339 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2343 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2340 ui.write(('revision size : ') + fmt2 % totalsize)
2344 ui.write(('revision size : ') + fmt2 % totalsize)
2341 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2345 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2342 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2346 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2343
2347
2344 ui.write('\n')
2348 ui.write('\n')
2345 fmt = dfmtstr(max(avgchainlen, compratio))
2349 fmt = dfmtstr(max(avgchainlen, compratio))
2346 ui.write(('avg chain length : ') + fmt % avgchainlen)
2350 ui.write(('avg chain length : ') + fmt % avgchainlen)
2347 ui.write(('compression ratio : ') + fmt % compratio)
2351 ui.write(('compression ratio : ') + fmt % compratio)
2348
2352
2349 if format > 0:
2353 if format > 0:
2350 ui.write('\n')
2354 ui.write('\n')
2351 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2355 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2352 % tuple(datasize))
2356 % tuple(datasize))
2353 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2357 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2354 % tuple(fullsize))
2358 % tuple(fullsize))
2355 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2359 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2356 % tuple(deltasize))
2360 % tuple(deltasize))
2357
2361
2358 if numdeltas > 0:
2362 if numdeltas > 0:
2359 ui.write('\n')
2363 ui.write('\n')
2360 fmt = pcfmtstr(numdeltas)
2364 fmt = pcfmtstr(numdeltas)
2361 fmt2 = pcfmtstr(numdeltas, 4)
2365 fmt2 = pcfmtstr(numdeltas, 4)
2362 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2366 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2363 if numprev > 0:
2367 if numprev > 0:
2364 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2368 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2365 numprev))
2369 numprev))
2366 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2370 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2367 numprev))
2371 numprev))
2368 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2372 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2369 numprev))
2373 numprev))
2370 if gdelta:
2374 if gdelta:
2371 ui.write(('deltas against p1 : ')
2375 ui.write(('deltas against p1 : ')
2372 + fmt % pcfmt(nump1, numdeltas))
2376 + fmt % pcfmt(nump1, numdeltas))
2373 ui.write(('deltas against p2 : ')
2377 ui.write(('deltas against p2 : ')
2374 + fmt % pcfmt(nump2, numdeltas))
2378 + fmt % pcfmt(nump2, numdeltas))
2375 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2379 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2376 numdeltas))
2380 numdeltas))
2377
2381
2378 @command('debugrevspec', [], ('REVSPEC'))
2382 @command('debugrevspec', [], ('REVSPEC'))
2379 def debugrevspec(ui, repo, expr):
2383 def debugrevspec(ui, repo, expr):
2380 """parse and apply a revision specification
2384 """parse and apply a revision specification
2381
2385
2382 Use --verbose to print the parsed tree before and after aliases
2386 Use --verbose to print the parsed tree before and after aliases
2383 expansion.
2387 expansion.
2384 """
2388 """
2385 if ui.verbose:
2389 if ui.verbose:
2386 tree = revset.parse(expr)[0]
2390 tree = revset.parse(expr)[0]
2387 ui.note(revset.prettyformat(tree), "\n")
2391 ui.note(revset.prettyformat(tree), "\n")
2388 newtree = revset.findaliases(ui, tree)
2392 newtree = revset.findaliases(ui, tree)
2389 if newtree != tree:
2393 if newtree != tree:
2390 ui.note(revset.prettyformat(newtree), "\n")
2394 ui.note(revset.prettyformat(newtree), "\n")
2391 func = revset.match(ui, expr)
2395 func = revset.match(ui, expr)
2392 for c in func(repo, range(len(repo))):
2396 for c in func(repo, range(len(repo))):
2393 ui.write("%s\n" % c)
2397 ui.write("%s\n" % c)
2394
2398
2395 @command('debugsetparents', [], _('REV1 [REV2]'))
2399 @command('debugsetparents', [], _('REV1 [REV2]'))
2396 def debugsetparents(ui, repo, rev1, rev2=None):
2400 def debugsetparents(ui, repo, rev1, rev2=None):
2397 """manually set the parents of the current working directory
2401 """manually set the parents of the current working directory
2398
2402
2399 This is useful for writing repository conversion tools, but should
2403 This is useful for writing repository conversion tools, but should
2400 be used with care.
2404 be used with care.
2401
2405
2402 Returns 0 on success.
2406 Returns 0 on success.
2403 """
2407 """
2404
2408
2405 r1 = scmutil.revsingle(repo, rev1).node()
2409 r1 = scmutil.revsingle(repo, rev1).node()
2406 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2410 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2407
2411
2408 wlock = repo.wlock()
2412 wlock = repo.wlock()
2409 try:
2413 try:
2410 repo.setparents(r1, r2)
2414 repo.setparents(r1, r2)
2411 finally:
2415 finally:
2412 wlock.release()
2416 wlock.release()
2413
2417
2414 @command('debugstate',
2418 @command('debugstate',
2415 [('', 'nodates', None, _('do not display the saved mtime')),
2419 [('', 'nodates', None, _('do not display the saved mtime')),
2416 ('', 'datesort', None, _('sort by saved mtime'))],
2420 ('', 'datesort', None, _('sort by saved mtime'))],
2417 _('[OPTION]...'))
2421 _('[OPTION]...'))
2418 def debugstate(ui, repo, nodates=None, datesort=None):
2422 def debugstate(ui, repo, nodates=None, datesort=None):
2419 """show the contents of the current dirstate"""
2423 """show the contents of the current dirstate"""
2420 timestr = ""
2424 timestr = ""
2421 showdate = not nodates
2425 showdate = not nodates
2422 if datesort:
2426 if datesort:
2423 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2427 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2424 else:
2428 else:
2425 keyfunc = None # sort by filename
2429 keyfunc = None # sort by filename
2426 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2430 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2427 if showdate:
2431 if showdate:
2428 if ent[3] == -1:
2432 if ent[3] == -1:
2429 # Pad or slice to locale representation
2433 # Pad or slice to locale representation
2430 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2434 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2431 time.localtime(0)))
2435 time.localtime(0)))
2432 timestr = 'unset'
2436 timestr = 'unset'
2433 timestr = (timestr[:locale_len] +
2437 timestr = (timestr[:locale_len] +
2434 ' ' * (locale_len - len(timestr)))
2438 ' ' * (locale_len - len(timestr)))
2435 else:
2439 else:
2436 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2440 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2437 time.localtime(ent[3]))
2441 time.localtime(ent[3]))
2438 if ent[1] & 020000:
2442 if ent[1] & 020000:
2439 mode = 'lnk'
2443 mode = 'lnk'
2440 else:
2444 else:
2441 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2445 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2442 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2446 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2443 for f in repo.dirstate.copies():
2447 for f in repo.dirstate.copies():
2444 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2448 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2445
2449
2446 @command('debugsub',
2450 @command('debugsub',
2447 [('r', 'rev', '',
2451 [('r', 'rev', '',
2448 _('revision to check'), _('REV'))],
2452 _('revision to check'), _('REV'))],
2449 _('[-r REV] [REV]'))
2453 _('[-r REV] [REV]'))
2450 def debugsub(ui, repo, rev=None):
2454 def debugsub(ui, repo, rev=None):
2451 ctx = scmutil.revsingle(repo, rev, None)
2455 ctx = scmutil.revsingle(repo, rev, None)
2452 for k, v in sorted(ctx.substate.items()):
2456 for k, v in sorted(ctx.substate.items()):
2453 ui.write(('path %s\n') % k)
2457 ui.write(('path %s\n') % k)
2454 ui.write((' source %s\n') % v[0])
2458 ui.write((' source %s\n') % v[0])
2455 ui.write((' revision %s\n') % v[1])
2459 ui.write((' revision %s\n') % v[1])
2456
2460
2457 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2461 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2458 def debugwalk(ui, repo, *pats, **opts):
2462 def debugwalk(ui, repo, *pats, **opts):
2459 """show how files match on given patterns"""
2463 """show how files match on given patterns"""
2460 m = scmutil.match(repo[None], pats, opts)
2464 m = scmutil.match(repo[None], pats, opts)
2461 items = list(repo.walk(m))
2465 items = list(repo.walk(m))
2462 if not items:
2466 if not items:
2463 return
2467 return
2464 f = lambda fn: fn
2468 f = lambda fn: fn
2465 if ui.configbool('ui', 'slash') and os.sep != '/':
2469 if ui.configbool('ui', 'slash') and os.sep != '/':
2466 f = lambda fn: util.normpath(fn)
2470 f = lambda fn: util.normpath(fn)
2467 fmt = 'f %%-%ds %%-%ds %%s' % (
2471 fmt = 'f %%-%ds %%-%ds %%s' % (
2468 max([len(abs) for abs in items]),
2472 max([len(abs) for abs in items]),
2469 max([len(m.rel(abs)) for abs in items]))
2473 max([len(m.rel(abs)) for abs in items]))
2470 for abs in items:
2474 for abs in items:
2471 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2475 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2472 ui.write("%s\n" % line.rstrip())
2476 ui.write("%s\n" % line.rstrip())
2473
2477
2474 @command('debugwireargs',
2478 @command('debugwireargs',
2475 [('', 'three', '', 'three'),
2479 [('', 'three', '', 'three'),
2476 ('', 'four', '', 'four'),
2480 ('', 'four', '', 'four'),
2477 ('', 'five', '', 'five'),
2481 ('', 'five', '', 'five'),
2478 ] + remoteopts,
2482 ] + remoteopts,
2479 _('REPO [OPTIONS]... [ONE [TWO]]'))
2483 _('REPO [OPTIONS]... [ONE [TWO]]'))
2480 def debugwireargs(ui, repopath, *vals, **opts):
2484 def debugwireargs(ui, repopath, *vals, **opts):
2481 repo = hg.peer(ui, opts, repopath)
2485 repo = hg.peer(ui, opts, repopath)
2482 for opt in remoteopts:
2486 for opt in remoteopts:
2483 del opts[opt[1]]
2487 del opts[opt[1]]
2484 args = {}
2488 args = {}
2485 for k, v in opts.iteritems():
2489 for k, v in opts.iteritems():
2486 if v:
2490 if v:
2487 args[k] = v
2491 args[k] = v
2488 # run twice to check that we don't mess up the stream for the next command
2492 # run twice to check that we don't mess up the stream for the next command
2489 res1 = repo.debugwireargs(*vals, **args)
2493 res1 = repo.debugwireargs(*vals, **args)
2490 res2 = repo.debugwireargs(*vals, **args)
2494 res2 = repo.debugwireargs(*vals, **args)
2491 ui.write("%s\n" % res1)
2495 ui.write("%s\n" % res1)
2492 if res1 != res2:
2496 if res1 != res2:
2493 ui.warn("%s\n" % res2)
2497 ui.warn("%s\n" % res2)
2494
2498
2495 @command('^diff',
2499 @command('^diff',
2496 [('r', 'rev', [], _('revision'), _('REV')),
2500 [('r', 'rev', [], _('revision'), _('REV')),
2497 ('c', 'change', '', _('change made by revision'), _('REV'))
2501 ('c', 'change', '', _('change made by revision'), _('REV'))
2498 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2502 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2499 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2503 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2500 def diff(ui, repo, *pats, **opts):
2504 def diff(ui, repo, *pats, **opts):
2501 """diff repository (or selected files)
2505 """diff repository (or selected files)
2502
2506
2503 Show differences between revisions for the specified files.
2507 Show differences between revisions for the specified files.
2504
2508
2505 Differences between files are shown using the unified diff format.
2509 Differences between files are shown using the unified diff format.
2506
2510
2507 .. note::
2511 .. note::
2508 diff may generate unexpected results for merges, as it will
2512 diff may generate unexpected results for merges, as it will
2509 default to comparing against the working directory's first
2513 default to comparing against the working directory's first
2510 parent changeset if no revisions are specified.
2514 parent changeset if no revisions are specified.
2511
2515
2512 When two revision arguments are given, then changes are shown
2516 When two revision arguments are given, then changes are shown
2513 between those revisions. If only one revision is specified then
2517 between those revisions. If only one revision is specified then
2514 that revision is compared to the working directory, and, when no
2518 that revision is compared to the working directory, and, when no
2515 revisions are specified, the working directory files are compared
2519 revisions are specified, the working directory files are compared
2516 to its parent.
2520 to its parent.
2517
2521
2518 Alternatively you can specify -c/--change with a revision to see
2522 Alternatively you can specify -c/--change with a revision to see
2519 the changes in that changeset relative to its first parent.
2523 the changes in that changeset relative to its first parent.
2520
2524
2521 Without the -a/--text option, diff will avoid generating diffs of
2525 Without the -a/--text option, diff will avoid generating diffs of
2522 files it detects as binary. With -a, diff will generate a diff
2526 files it detects as binary. With -a, diff will generate a diff
2523 anyway, probably with undesirable results.
2527 anyway, probably with undesirable results.
2524
2528
2525 Use the -g/--git option to generate diffs in the git extended diff
2529 Use the -g/--git option to generate diffs in the git extended diff
2526 format. For more information, read :hg:`help diffs`.
2530 format. For more information, read :hg:`help diffs`.
2527
2531
2528 .. container:: verbose
2532 .. container:: verbose
2529
2533
2530 Examples:
2534 Examples:
2531
2535
2532 - compare a file in the current working directory to its parent::
2536 - compare a file in the current working directory to its parent::
2533
2537
2534 hg diff foo.c
2538 hg diff foo.c
2535
2539
2536 - compare two historical versions of a directory, with rename info::
2540 - compare two historical versions of a directory, with rename info::
2537
2541
2538 hg diff --git -r 1.0:1.2 lib/
2542 hg diff --git -r 1.0:1.2 lib/
2539
2543
2540 - get change stats relative to the last change on some date::
2544 - get change stats relative to the last change on some date::
2541
2545
2542 hg diff --stat -r "date('may 2')"
2546 hg diff --stat -r "date('may 2')"
2543
2547
2544 - diff all newly-added files that contain a keyword::
2548 - diff all newly-added files that contain a keyword::
2545
2549
2546 hg diff "set:added() and grep(GNU)"
2550 hg diff "set:added() and grep(GNU)"
2547
2551
2548 - compare a revision and its parents::
2552 - compare a revision and its parents::
2549
2553
2550 hg diff -c 9353 # compare against first parent
2554 hg diff -c 9353 # compare against first parent
2551 hg diff -r 9353^:9353 # same using revset syntax
2555 hg diff -r 9353^:9353 # same using revset syntax
2552 hg diff -r 9353^2:9353 # compare against the second parent
2556 hg diff -r 9353^2:9353 # compare against the second parent
2553
2557
2554 Returns 0 on success.
2558 Returns 0 on success.
2555 """
2559 """
2556
2560
2557 revs = opts.get('rev')
2561 revs = opts.get('rev')
2558 change = opts.get('change')
2562 change = opts.get('change')
2559 stat = opts.get('stat')
2563 stat = opts.get('stat')
2560 reverse = opts.get('reverse')
2564 reverse = opts.get('reverse')
2561
2565
2562 if revs and change:
2566 if revs and change:
2563 msg = _('cannot specify --rev and --change at the same time')
2567 msg = _('cannot specify --rev and --change at the same time')
2564 raise util.Abort(msg)
2568 raise util.Abort(msg)
2565 elif change:
2569 elif change:
2566 node2 = scmutil.revsingle(repo, change, None).node()
2570 node2 = scmutil.revsingle(repo, change, None).node()
2567 node1 = repo[node2].p1().node()
2571 node1 = repo[node2].p1().node()
2568 else:
2572 else:
2569 node1, node2 = scmutil.revpair(repo, revs)
2573 node1, node2 = scmutil.revpair(repo, revs)
2570
2574
2571 if reverse:
2575 if reverse:
2572 node1, node2 = node2, node1
2576 node1, node2 = node2, node1
2573
2577
2574 diffopts = patch.diffopts(ui, opts)
2578 diffopts = patch.diffopts(ui, opts)
2575 m = scmutil.match(repo[node2], pats, opts)
2579 m = scmutil.match(repo[node2], pats, opts)
2576 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2580 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2577 listsubrepos=opts.get('subrepos'))
2581 listsubrepos=opts.get('subrepos'))
2578
2582
2579 @command('^export',
2583 @command('^export',
2580 [('o', 'output', '',
2584 [('o', 'output', '',
2581 _('print output to file with formatted name'), _('FORMAT')),
2585 _('print output to file with formatted name'), _('FORMAT')),
2582 ('', 'switch-parent', None, _('diff against the second parent')),
2586 ('', 'switch-parent', None, _('diff against the second parent')),
2583 ('r', 'rev', [], _('revisions to export'), _('REV')),
2587 ('r', 'rev', [], _('revisions to export'), _('REV')),
2584 ] + diffopts,
2588 ] + diffopts,
2585 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2589 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2586 def export(ui, repo, *changesets, **opts):
2590 def export(ui, repo, *changesets, **opts):
2587 """dump the header and diffs for one or more changesets
2591 """dump the header and diffs for one or more changesets
2588
2592
2589 Print the changeset header and diffs for one or more revisions.
2593 Print the changeset header and diffs for one or more revisions.
2590
2594
2591 The information shown in the changeset header is: author, date,
2595 The information shown in the changeset header is: author, date,
2592 branch name (if non-default), changeset hash, parent(s) and commit
2596 branch name (if non-default), changeset hash, parent(s) and commit
2593 comment.
2597 comment.
2594
2598
2595 .. note::
2599 .. note::
2596 export may generate unexpected diff output for merge
2600 export may generate unexpected diff output for merge
2597 changesets, as it will compare the merge changeset against its
2601 changesets, as it will compare the merge changeset against its
2598 first parent only.
2602 first parent only.
2599
2603
2600 Output may be to a file, in which case the name of the file is
2604 Output may be to a file, in which case the name of the file is
2601 given using a format string. The formatting rules are as follows:
2605 given using a format string. The formatting rules are as follows:
2602
2606
2603 :``%%``: literal "%" character
2607 :``%%``: literal "%" character
2604 :``%H``: changeset hash (40 hexadecimal digits)
2608 :``%H``: changeset hash (40 hexadecimal digits)
2605 :``%N``: number of patches being generated
2609 :``%N``: number of patches being generated
2606 :``%R``: changeset revision number
2610 :``%R``: changeset revision number
2607 :``%b``: basename of the exporting repository
2611 :``%b``: basename of the exporting repository
2608 :``%h``: short-form changeset hash (12 hexadecimal digits)
2612 :``%h``: short-form changeset hash (12 hexadecimal digits)
2609 :``%m``: first line of the commit message (only alphanumeric characters)
2613 :``%m``: first line of the commit message (only alphanumeric characters)
2610 :``%n``: zero-padded sequence number, starting at 1
2614 :``%n``: zero-padded sequence number, starting at 1
2611 :``%r``: zero-padded changeset revision number
2615 :``%r``: zero-padded changeset revision number
2612
2616
2613 Without the -a/--text option, export will avoid generating diffs
2617 Without the -a/--text option, export will avoid generating diffs
2614 of files it detects as binary. With -a, export will generate a
2618 of files it detects as binary. With -a, export will generate a
2615 diff anyway, probably with undesirable results.
2619 diff anyway, probably with undesirable results.
2616
2620
2617 Use the -g/--git option to generate diffs in the git extended diff
2621 Use the -g/--git option to generate diffs in the git extended diff
2618 format. See :hg:`help diffs` for more information.
2622 format. See :hg:`help diffs` for more information.
2619
2623
2620 With the --switch-parent option, the diff will be against the
2624 With the --switch-parent option, the diff will be against the
2621 second parent. It can be useful to review a merge.
2625 second parent. It can be useful to review a merge.
2622
2626
2623 .. container:: verbose
2627 .. container:: verbose
2624
2628
2625 Examples:
2629 Examples:
2626
2630
2627 - use export and import to transplant a bugfix to the current
2631 - use export and import to transplant a bugfix to the current
2628 branch::
2632 branch::
2629
2633
2630 hg export -r 9353 | hg import -
2634 hg export -r 9353 | hg import -
2631
2635
2632 - export all the changesets between two revisions to a file with
2636 - export all the changesets between two revisions to a file with
2633 rename information::
2637 rename information::
2634
2638
2635 hg export --git -r 123:150 > changes.txt
2639 hg export --git -r 123:150 > changes.txt
2636
2640
2637 - split outgoing changes into a series of patches with
2641 - split outgoing changes into a series of patches with
2638 descriptive names::
2642 descriptive names::
2639
2643
2640 hg export -r "outgoing()" -o "%n-%m.patch"
2644 hg export -r "outgoing()" -o "%n-%m.patch"
2641
2645
2642 Returns 0 on success.
2646 Returns 0 on success.
2643 """
2647 """
2644 changesets += tuple(opts.get('rev', []))
2648 changesets += tuple(opts.get('rev', []))
2645 revs = scmutil.revrange(repo, changesets)
2649 revs = scmutil.revrange(repo, changesets)
2646 if not revs:
2650 if not revs:
2647 raise util.Abort(_("export requires at least one changeset"))
2651 raise util.Abort(_("export requires at least one changeset"))
2648 if len(revs) > 1:
2652 if len(revs) > 1:
2649 ui.note(_('exporting patches:\n'))
2653 ui.note(_('exporting patches:\n'))
2650 else:
2654 else:
2651 ui.note(_('exporting patch:\n'))
2655 ui.note(_('exporting patch:\n'))
2652 cmdutil.export(repo, revs, template=opts.get('output'),
2656 cmdutil.export(repo, revs, template=opts.get('output'),
2653 switch_parent=opts.get('switch_parent'),
2657 switch_parent=opts.get('switch_parent'),
2654 opts=patch.diffopts(ui, opts))
2658 opts=patch.diffopts(ui, opts))
2655
2659
2656 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2660 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2657 def forget(ui, repo, *pats, **opts):
2661 def forget(ui, repo, *pats, **opts):
2658 """forget the specified files on the next commit
2662 """forget the specified files on the next commit
2659
2663
2660 Mark the specified files so they will no longer be tracked
2664 Mark the specified files so they will no longer be tracked
2661 after the next commit.
2665 after the next commit.
2662
2666
2663 This only removes files from the current branch, not from the
2667 This only removes files from the current branch, not from the
2664 entire project history, and it does not delete them from the
2668 entire project history, and it does not delete them from the
2665 working directory.
2669 working directory.
2666
2670
2667 To undo a forget before the next commit, see :hg:`add`.
2671 To undo a forget before the next commit, see :hg:`add`.
2668
2672
2669 .. container:: verbose
2673 .. container:: verbose
2670
2674
2671 Examples:
2675 Examples:
2672
2676
2673 - forget newly-added binary files::
2677 - forget newly-added binary files::
2674
2678
2675 hg forget "set:added() and binary()"
2679 hg forget "set:added() and binary()"
2676
2680
2677 - forget files that would be excluded by .hgignore::
2681 - forget files that would be excluded by .hgignore::
2678
2682
2679 hg forget "set:hgignore()"
2683 hg forget "set:hgignore()"
2680
2684
2681 Returns 0 on success.
2685 Returns 0 on success.
2682 """
2686 """
2683
2687
2684 if not pats:
2688 if not pats:
2685 raise util.Abort(_('no files specified'))
2689 raise util.Abort(_('no files specified'))
2686
2690
2687 m = scmutil.match(repo[None], pats, opts)
2691 m = scmutil.match(repo[None], pats, opts)
2688 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2692 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2689 return rejected and 1 or 0
2693 return rejected and 1 or 0
2690
2694
2691 @command(
2695 @command(
2692 'graft',
2696 'graft',
2693 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2697 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2694 ('c', 'continue', False, _('resume interrupted graft')),
2698 ('c', 'continue', False, _('resume interrupted graft')),
2695 ('e', 'edit', False, _('invoke editor on commit messages')),
2699 ('e', 'edit', False, _('invoke editor on commit messages')),
2696 ('', 'log', None, _('append graft info to log message')),
2700 ('', 'log', None, _('append graft info to log message')),
2697 ('D', 'currentdate', False,
2701 ('D', 'currentdate', False,
2698 _('record the current date as commit date')),
2702 _('record the current date as commit date')),
2699 ('U', 'currentuser', False,
2703 ('U', 'currentuser', False,
2700 _('record the current user as committer'), _('DATE'))]
2704 _('record the current user as committer'), _('DATE'))]
2701 + commitopts2 + mergetoolopts + dryrunopts,
2705 + commitopts2 + mergetoolopts + dryrunopts,
2702 _('[OPTION]... [-r] REV...'))
2706 _('[OPTION]... [-r] REV...'))
2703 def graft(ui, repo, *revs, **opts):
2707 def graft(ui, repo, *revs, **opts):
2704 '''copy changes from other branches onto the current branch
2708 '''copy changes from other branches onto the current branch
2705
2709
2706 This command uses Mercurial's merge logic to copy individual
2710 This command uses Mercurial's merge logic to copy individual
2707 changes from other branches without merging branches in the
2711 changes from other branches without merging branches in the
2708 history graph. This is sometimes known as 'backporting' or
2712 history graph. This is sometimes known as 'backporting' or
2709 'cherry-picking'. By default, graft will copy user, date, and
2713 'cherry-picking'. By default, graft will copy user, date, and
2710 description from the source changesets.
2714 description from the source changesets.
2711
2715
2712 Changesets that are ancestors of the current revision, that have
2716 Changesets that are ancestors of the current revision, that have
2713 already been grafted, or that are merges will be skipped.
2717 already been grafted, or that are merges will be skipped.
2714
2718
2715 If --log is specified, log messages will have a comment appended
2719 If --log is specified, log messages will have a comment appended
2716 of the form::
2720 of the form::
2717
2721
2718 (grafted from CHANGESETHASH)
2722 (grafted from CHANGESETHASH)
2719
2723
2720 If a graft merge results in conflicts, the graft process is
2724 If a graft merge results in conflicts, the graft process is
2721 interrupted so that the current merge can be manually resolved.
2725 interrupted so that the current merge can be manually resolved.
2722 Once all conflicts are addressed, the graft process can be
2726 Once all conflicts are addressed, the graft process can be
2723 continued with the -c/--continue option.
2727 continued with the -c/--continue option.
2724
2728
2725 .. note::
2729 .. note::
2726 The -c/--continue option does not reapply earlier options.
2730 The -c/--continue option does not reapply earlier options.
2727
2731
2728 .. container:: verbose
2732 .. container:: verbose
2729
2733
2730 Examples:
2734 Examples:
2731
2735
2732 - copy a single change to the stable branch and edit its description::
2736 - copy a single change to the stable branch and edit its description::
2733
2737
2734 hg update stable
2738 hg update stable
2735 hg graft --edit 9393
2739 hg graft --edit 9393
2736
2740
2737 - graft a range of changesets with one exception, updating dates::
2741 - graft a range of changesets with one exception, updating dates::
2738
2742
2739 hg graft -D "2085::2093 and not 2091"
2743 hg graft -D "2085::2093 and not 2091"
2740
2744
2741 - continue a graft after resolving conflicts::
2745 - continue a graft after resolving conflicts::
2742
2746
2743 hg graft -c
2747 hg graft -c
2744
2748
2745 - show the source of a grafted changeset::
2749 - show the source of a grafted changeset::
2746
2750
2747 hg log --debug -r tip
2751 hg log --debug -r tip
2748
2752
2749 Returns 0 on successful completion.
2753 Returns 0 on successful completion.
2750 '''
2754 '''
2751
2755
2752 revs = list(revs)
2756 revs = list(revs)
2753 revs.extend(opts['rev'])
2757 revs.extend(opts['rev'])
2754
2758
2755 if not opts.get('user') and opts.get('currentuser'):
2759 if not opts.get('user') and opts.get('currentuser'):
2756 opts['user'] = ui.username()
2760 opts['user'] = ui.username()
2757 if not opts.get('date') and opts.get('currentdate'):
2761 if not opts.get('date') and opts.get('currentdate'):
2758 opts['date'] = "%d %d" % util.makedate()
2762 opts['date'] = "%d %d" % util.makedate()
2759
2763
2760 editor = None
2764 editor = None
2761 if opts.get('edit'):
2765 if opts.get('edit'):
2762 editor = cmdutil.commitforceeditor
2766 editor = cmdutil.commitforceeditor
2763
2767
2764 cont = False
2768 cont = False
2765 if opts['continue']:
2769 if opts['continue']:
2766 cont = True
2770 cont = True
2767 if revs:
2771 if revs:
2768 raise util.Abort(_("can't specify --continue and revisions"))
2772 raise util.Abort(_("can't specify --continue and revisions"))
2769 # read in unfinished revisions
2773 # read in unfinished revisions
2770 try:
2774 try:
2771 nodes = repo.opener.read('graftstate').splitlines()
2775 nodes = repo.opener.read('graftstate').splitlines()
2772 revs = [repo[node].rev() for node in nodes]
2776 revs = [repo[node].rev() for node in nodes]
2773 except IOError, inst:
2777 except IOError, inst:
2774 if inst.errno != errno.ENOENT:
2778 if inst.errno != errno.ENOENT:
2775 raise
2779 raise
2776 raise util.Abort(_("no graft state found, can't continue"))
2780 raise util.Abort(_("no graft state found, can't continue"))
2777 else:
2781 else:
2778 cmdutil.bailifchanged(repo)
2782 cmdutil.bailifchanged(repo)
2779 if not revs:
2783 if not revs:
2780 raise util.Abort(_('no revisions specified'))
2784 raise util.Abort(_('no revisions specified'))
2781 revs = scmutil.revrange(repo, revs)
2785 revs = scmutil.revrange(repo, revs)
2782
2786
2783 # check for merges
2787 # check for merges
2784 for rev in repo.revs('%ld and merge()', revs):
2788 for rev in repo.revs('%ld and merge()', revs):
2785 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2789 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2786 revs.remove(rev)
2790 revs.remove(rev)
2787 if not revs:
2791 if not revs:
2788 return -1
2792 return -1
2789
2793
2790 # check for ancestors of dest branch
2794 # check for ancestors of dest branch
2791 for rev in repo.revs('::. and %ld', revs):
2795 for rev in repo.revs('::. and %ld', revs):
2792 ui.warn(_('skipping ancestor revision %s\n') % rev)
2796 ui.warn(_('skipping ancestor revision %s\n') % rev)
2793 revs.remove(rev)
2797 revs.remove(rev)
2794 if not revs:
2798 if not revs:
2795 return -1
2799 return -1
2796
2800
2797 # analyze revs for earlier grafts
2801 # analyze revs for earlier grafts
2798 ids = {}
2802 ids = {}
2799 for ctx in repo.set("%ld", revs):
2803 for ctx in repo.set("%ld", revs):
2800 ids[ctx.hex()] = ctx.rev()
2804 ids[ctx.hex()] = ctx.rev()
2801 n = ctx.extra().get('source')
2805 n = ctx.extra().get('source')
2802 if n:
2806 if n:
2803 ids[n] = ctx.rev()
2807 ids[n] = ctx.rev()
2804
2808
2805 # check ancestors for earlier grafts
2809 # check ancestors for earlier grafts
2806 ui.debug('scanning for duplicate grafts\n')
2810 ui.debug('scanning for duplicate grafts\n')
2807 for ctx in repo.set("::. - ::%ld", revs):
2811 for ctx in repo.set("::. - ::%ld", revs):
2808 n = ctx.extra().get('source')
2812 n = ctx.extra().get('source')
2809 if n in ids:
2813 if n in ids:
2810 r = repo[n].rev()
2814 r = repo[n].rev()
2811 if r in revs:
2815 if r in revs:
2812 ui.warn(_('skipping already grafted revision %s\n') % r)
2816 ui.warn(_('skipping already grafted revision %s\n') % r)
2813 revs.remove(r)
2817 revs.remove(r)
2814 elif ids[n] in revs:
2818 elif ids[n] in revs:
2815 ui.warn(_('skipping already grafted revision %s '
2819 ui.warn(_('skipping already grafted revision %s '
2816 '(same origin %d)\n') % (ids[n], r))
2820 '(same origin %d)\n') % (ids[n], r))
2817 revs.remove(ids[n])
2821 revs.remove(ids[n])
2818 elif ctx.hex() in ids:
2822 elif ctx.hex() in ids:
2819 r = ids[ctx.hex()]
2823 r = ids[ctx.hex()]
2820 ui.warn(_('skipping already grafted revision %s '
2824 ui.warn(_('skipping already grafted revision %s '
2821 '(was grafted from %d)\n') % (r, ctx.rev()))
2825 '(was grafted from %d)\n') % (r, ctx.rev()))
2822 revs.remove(r)
2826 revs.remove(r)
2823 if not revs:
2827 if not revs:
2824 return -1
2828 return -1
2825
2829
2826 wlock = repo.wlock()
2830 wlock = repo.wlock()
2827 try:
2831 try:
2828 for pos, ctx in enumerate(repo.set("%ld", revs)):
2832 for pos, ctx in enumerate(repo.set("%ld", revs)):
2829 current = repo['.']
2833 current = repo['.']
2830
2834
2831 ui.status(_('grafting revision %s\n') % ctx.rev())
2835 ui.status(_('grafting revision %s\n') % ctx.rev())
2832 if opts.get('dry_run'):
2836 if opts.get('dry_run'):
2833 continue
2837 continue
2834
2838
2835 # we don't merge the first commit when continuing
2839 # we don't merge the first commit when continuing
2836 if not cont:
2840 if not cont:
2837 # perform the graft merge with p1(rev) as 'ancestor'
2841 # perform the graft merge with p1(rev) as 'ancestor'
2838 try:
2842 try:
2839 # ui.forcemerge is an internal variable, do not document
2843 # ui.forcemerge is an internal variable, do not document
2840 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2844 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2841 stats = mergemod.update(repo, ctx.node(), True, True, False,
2845 stats = mergemod.update(repo, ctx.node(), True, True, False,
2842 ctx.p1().node())
2846 ctx.p1().node())
2843 finally:
2847 finally:
2844 repo.ui.setconfig('ui', 'forcemerge', '')
2848 repo.ui.setconfig('ui', 'forcemerge', '')
2845 # report any conflicts
2849 # report any conflicts
2846 if stats and stats[3] > 0:
2850 if stats and stats[3] > 0:
2847 # write out state for --continue
2851 # write out state for --continue
2848 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2852 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2849 repo.opener.write('graftstate', ''.join(nodelines))
2853 repo.opener.write('graftstate', ''.join(nodelines))
2850 raise util.Abort(
2854 raise util.Abort(
2851 _("unresolved conflicts, can't continue"),
2855 _("unresolved conflicts, can't continue"),
2852 hint=_('use hg resolve and hg graft --continue'))
2856 hint=_('use hg resolve and hg graft --continue'))
2853 else:
2857 else:
2854 cont = False
2858 cont = False
2855
2859
2856 # drop the second merge parent
2860 # drop the second merge parent
2857 repo.setparents(current.node(), nullid)
2861 repo.setparents(current.node(), nullid)
2858 repo.dirstate.write()
2862 repo.dirstate.write()
2859 # fix up dirstate for copies and renames
2863 # fix up dirstate for copies and renames
2860 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2864 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2861
2865
2862 # commit
2866 # commit
2863 source = ctx.extra().get('source')
2867 source = ctx.extra().get('source')
2864 if not source:
2868 if not source:
2865 source = ctx.hex()
2869 source = ctx.hex()
2866 extra = {'source': source}
2870 extra = {'source': source}
2867 user = ctx.user()
2871 user = ctx.user()
2868 if opts.get('user'):
2872 if opts.get('user'):
2869 user = opts['user']
2873 user = opts['user']
2870 date = ctx.date()
2874 date = ctx.date()
2871 if opts.get('date'):
2875 if opts.get('date'):
2872 date = opts['date']
2876 date = opts['date']
2873 message = ctx.description()
2877 message = ctx.description()
2874 if opts.get('log'):
2878 if opts.get('log'):
2875 message += '\n(grafted from %s)' % ctx.hex()
2879 message += '\n(grafted from %s)' % ctx.hex()
2876 node = repo.commit(text=message, user=user,
2880 node = repo.commit(text=message, user=user,
2877 date=date, extra=extra, editor=editor)
2881 date=date, extra=extra, editor=editor)
2878 if node is None:
2882 if node is None:
2879 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2883 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2880 finally:
2884 finally:
2881 wlock.release()
2885 wlock.release()
2882
2886
2883 # remove state when we complete successfully
2887 # remove state when we complete successfully
2884 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2888 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2885 util.unlinkpath(repo.join('graftstate'))
2889 util.unlinkpath(repo.join('graftstate'))
2886
2890
2887 return 0
2891 return 0
2888
2892
2889 @command('grep',
2893 @command('grep',
2890 [('0', 'print0', None, _('end fields with NUL')),
2894 [('0', 'print0', None, _('end fields with NUL')),
2891 ('', 'all', None, _('print all revisions that match')),
2895 ('', 'all', None, _('print all revisions that match')),
2892 ('a', 'text', None, _('treat all files as text')),
2896 ('a', 'text', None, _('treat all files as text')),
2893 ('f', 'follow', None,
2897 ('f', 'follow', None,
2894 _('follow changeset history,'
2898 _('follow changeset history,'
2895 ' or file history across copies and renames')),
2899 ' or file history across copies and renames')),
2896 ('i', 'ignore-case', None, _('ignore case when matching')),
2900 ('i', 'ignore-case', None, _('ignore case when matching')),
2897 ('l', 'files-with-matches', None,
2901 ('l', 'files-with-matches', None,
2898 _('print only filenames and revisions that match')),
2902 _('print only filenames and revisions that match')),
2899 ('n', 'line-number', None, _('print matching line numbers')),
2903 ('n', 'line-number', None, _('print matching line numbers')),
2900 ('r', 'rev', [],
2904 ('r', 'rev', [],
2901 _('only search files changed within revision range'), _('REV')),
2905 _('only search files changed within revision range'), _('REV')),
2902 ('u', 'user', None, _('list the author (long with -v)')),
2906 ('u', 'user', None, _('list the author (long with -v)')),
2903 ('d', 'date', None, _('list the date (short with -q)')),
2907 ('d', 'date', None, _('list the date (short with -q)')),
2904 ] + walkopts,
2908 ] + walkopts,
2905 _('[OPTION]... PATTERN [FILE]...'))
2909 _('[OPTION]... PATTERN [FILE]...'))
2906 def grep(ui, repo, pattern, *pats, **opts):
2910 def grep(ui, repo, pattern, *pats, **opts):
2907 """search for a pattern in specified files and revisions
2911 """search for a pattern in specified files and revisions
2908
2912
2909 Search revisions of files for a regular expression.
2913 Search revisions of files for a regular expression.
2910
2914
2911 This command behaves differently than Unix grep. It only accepts
2915 This command behaves differently than Unix grep. It only accepts
2912 Python/Perl regexps. It searches repository history, not the
2916 Python/Perl regexps. It searches repository history, not the
2913 working directory. It always prints the revision number in which a
2917 working directory. It always prints the revision number in which a
2914 match appears.
2918 match appears.
2915
2919
2916 By default, grep only prints output for the first revision of a
2920 By default, grep only prints output for the first revision of a
2917 file in which it finds a match. To get it to print every revision
2921 file in which it finds a match. To get it to print every revision
2918 that contains a change in match status ("-" for a match that
2922 that contains a change in match status ("-" for a match that
2919 becomes a non-match, or "+" for a non-match that becomes a match),
2923 becomes a non-match, or "+" for a non-match that becomes a match),
2920 use the --all flag.
2924 use the --all flag.
2921
2925
2922 Returns 0 if a match is found, 1 otherwise.
2926 Returns 0 if a match is found, 1 otherwise.
2923 """
2927 """
2924 reflags = re.M
2928 reflags = re.M
2925 if opts.get('ignore_case'):
2929 if opts.get('ignore_case'):
2926 reflags |= re.I
2930 reflags |= re.I
2927 try:
2931 try:
2928 regexp = re.compile(pattern, reflags)
2932 regexp = re.compile(pattern, reflags)
2929 except re.error, inst:
2933 except re.error, inst:
2930 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2934 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2931 return 1
2935 return 1
2932 sep, eol = ':', '\n'
2936 sep, eol = ':', '\n'
2933 if opts.get('print0'):
2937 if opts.get('print0'):
2934 sep = eol = '\0'
2938 sep = eol = '\0'
2935
2939
2936 getfile = util.lrucachefunc(repo.file)
2940 getfile = util.lrucachefunc(repo.file)
2937
2941
2938 def matchlines(body):
2942 def matchlines(body):
2939 begin = 0
2943 begin = 0
2940 linenum = 0
2944 linenum = 0
2941 while begin < len(body):
2945 while begin < len(body):
2942 match = regexp.search(body, begin)
2946 match = regexp.search(body, begin)
2943 if not match:
2947 if not match:
2944 break
2948 break
2945 mstart, mend = match.span()
2949 mstart, mend = match.span()
2946 linenum += body.count('\n', begin, mstart) + 1
2950 linenum += body.count('\n', begin, mstart) + 1
2947 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2951 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2948 begin = body.find('\n', mend) + 1 or len(body) + 1
2952 begin = body.find('\n', mend) + 1 or len(body) + 1
2949 lend = begin - 1
2953 lend = begin - 1
2950 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2954 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2951
2955
2952 class linestate(object):
2956 class linestate(object):
2953 def __init__(self, line, linenum, colstart, colend):
2957 def __init__(self, line, linenum, colstart, colend):
2954 self.line = line
2958 self.line = line
2955 self.linenum = linenum
2959 self.linenum = linenum
2956 self.colstart = colstart
2960 self.colstart = colstart
2957 self.colend = colend
2961 self.colend = colend
2958
2962
2959 def __hash__(self):
2963 def __hash__(self):
2960 return hash((self.linenum, self.line))
2964 return hash((self.linenum, self.line))
2961
2965
2962 def __eq__(self, other):
2966 def __eq__(self, other):
2963 return self.line == other.line
2967 return self.line == other.line
2964
2968
2965 matches = {}
2969 matches = {}
2966 copies = {}
2970 copies = {}
2967 def grepbody(fn, rev, body):
2971 def grepbody(fn, rev, body):
2968 matches[rev].setdefault(fn, [])
2972 matches[rev].setdefault(fn, [])
2969 m = matches[rev][fn]
2973 m = matches[rev][fn]
2970 for lnum, cstart, cend, line in matchlines(body):
2974 for lnum, cstart, cend, line in matchlines(body):
2971 s = linestate(line, lnum, cstart, cend)
2975 s = linestate(line, lnum, cstart, cend)
2972 m.append(s)
2976 m.append(s)
2973
2977
2974 def difflinestates(a, b):
2978 def difflinestates(a, b):
2975 sm = difflib.SequenceMatcher(None, a, b)
2979 sm = difflib.SequenceMatcher(None, a, b)
2976 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2980 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2977 if tag == 'insert':
2981 if tag == 'insert':
2978 for i in xrange(blo, bhi):
2982 for i in xrange(blo, bhi):
2979 yield ('+', b[i])
2983 yield ('+', b[i])
2980 elif tag == 'delete':
2984 elif tag == 'delete':
2981 for i in xrange(alo, ahi):
2985 for i in xrange(alo, ahi):
2982 yield ('-', a[i])
2986 yield ('-', a[i])
2983 elif tag == 'replace':
2987 elif tag == 'replace':
2984 for i in xrange(alo, ahi):
2988 for i in xrange(alo, ahi):
2985 yield ('-', a[i])
2989 yield ('-', a[i])
2986 for i in xrange(blo, bhi):
2990 for i in xrange(blo, bhi):
2987 yield ('+', b[i])
2991 yield ('+', b[i])
2988
2992
2989 def display(fn, ctx, pstates, states):
2993 def display(fn, ctx, pstates, states):
2990 rev = ctx.rev()
2994 rev = ctx.rev()
2991 datefunc = ui.quiet and util.shortdate or util.datestr
2995 datefunc = ui.quiet and util.shortdate or util.datestr
2992 found = False
2996 found = False
2993 filerevmatches = {}
2997 filerevmatches = {}
2994 def binary():
2998 def binary():
2995 flog = getfile(fn)
2999 flog = getfile(fn)
2996 return util.binary(flog.read(ctx.filenode(fn)))
3000 return util.binary(flog.read(ctx.filenode(fn)))
2997
3001
2998 if opts.get('all'):
3002 if opts.get('all'):
2999 iter = difflinestates(pstates, states)
3003 iter = difflinestates(pstates, states)
3000 else:
3004 else:
3001 iter = [('', l) for l in states]
3005 iter = [('', l) for l in states]
3002 for change, l in iter:
3006 for change, l in iter:
3003 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3007 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3004 before, match, after = None, None, None
3008 before, match, after = None, None, None
3005
3009
3006 if opts.get('line_number'):
3010 if opts.get('line_number'):
3007 cols.append((str(l.linenum), 'grep.linenumber'))
3011 cols.append((str(l.linenum), 'grep.linenumber'))
3008 if opts.get('all'):
3012 if opts.get('all'):
3009 cols.append((change, 'grep.change'))
3013 cols.append((change, 'grep.change'))
3010 if opts.get('user'):
3014 if opts.get('user'):
3011 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3015 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3012 if opts.get('date'):
3016 if opts.get('date'):
3013 cols.append((datefunc(ctx.date()), 'grep.date'))
3017 cols.append((datefunc(ctx.date()), 'grep.date'))
3014 if opts.get('files_with_matches'):
3018 if opts.get('files_with_matches'):
3015 c = (fn, rev)
3019 c = (fn, rev)
3016 if c in filerevmatches:
3020 if c in filerevmatches:
3017 continue
3021 continue
3018 filerevmatches[c] = 1
3022 filerevmatches[c] = 1
3019 else:
3023 else:
3020 before = l.line[:l.colstart]
3024 before = l.line[:l.colstart]
3021 match = l.line[l.colstart:l.colend]
3025 match = l.line[l.colstart:l.colend]
3022 after = l.line[l.colend:]
3026 after = l.line[l.colend:]
3023 for col, label in cols[:-1]:
3027 for col, label in cols[:-1]:
3024 ui.write(col, label=label)
3028 ui.write(col, label=label)
3025 ui.write(sep, label='grep.sep')
3029 ui.write(sep, label='grep.sep')
3026 ui.write(cols[-1][0], label=cols[-1][1])
3030 ui.write(cols[-1][0], label=cols[-1][1])
3027 if before is not None:
3031 if before is not None:
3028 ui.write(sep, label='grep.sep')
3032 ui.write(sep, label='grep.sep')
3029 if not opts.get('text') and binary():
3033 if not opts.get('text') and binary():
3030 ui.write(" Binary file matches")
3034 ui.write(" Binary file matches")
3031 else:
3035 else:
3032 ui.write(before)
3036 ui.write(before)
3033 ui.write(match, label='grep.match')
3037 ui.write(match, label='grep.match')
3034 ui.write(after)
3038 ui.write(after)
3035 ui.write(eol)
3039 ui.write(eol)
3036 found = True
3040 found = True
3037 return found
3041 return found
3038
3042
3039 skip = {}
3043 skip = {}
3040 revfiles = {}
3044 revfiles = {}
3041 matchfn = scmutil.match(repo[None], pats, opts)
3045 matchfn = scmutil.match(repo[None], pats, opts)
3042 found = False
3046 found = False
3043 follow = opts.get('follow')
3047 follow = opts.get('follow')
3044
3048
3045 def prep(ctx, fns):
3049 def prep(ctx, fns):
3046 rev = ctx.rev()
3050 rev = ctx.rev()
3047 pctx = ctx.p1()
3051 pctx = ctx.p1()
3048 parent = pctx.rev()
3052 parent = pctx.rev()
3049 matches.setdefault(rev, {})
3053 matches.setdefault(rev, {})
3050 matches.setdefault(parent, {})
3054 matches.setdefault(parent, {})
3051 files = revfiles.setdefault(rev, [])
3055 files = revfiles.setdefault(rev, [])
3052 for fn in fns:
3056 for fn in fns:
3053 flog = getfile(fn)
3057 flog = getfile(fn)
3054 try:
3058 try:
3055 fnode = ctx.filenode(fn)
3059 fnode = ctx.filenode(fn)
3056 except error.LookupError:
3060 except error.LookupError:
3057 continue
3061 continue
3058
3062
3059 copied = flog.renamed(fnode)
3063 copied = flog.renamed(fnode)
3060 copy = follow and copied and copied[0]
3064 copy = follow and copied and copied[0]
3061 if copy:
3065 if copy:
3062 copies.setdefault(rev, {})[fn] = copy
3066 copies.setdefault(rev, {})[fn] = copy
3063 if fn in skip:
3067 if fn in skip:
3064 if copy:
3068 if copy:
3065 skip[copy] = True
3069 skip[copy] = True
3066 continue
3070 continue
3067 files.append(fn)
3071 files.append(fn)
3068
3072
3069 if fn not in matches[rev]:
3073 if fn not in matches[rev]:
3070 grepbody(fn, rev, flog.read(fnode))
3074 grepbody(fn, rev, flog.read(fnode))
3071
3075
3072 pfn = copy or fn
3076 pfn = copy or fn
3073 if pfn not in matches[parent]:
3077 if pfn not in matches[parent]:
3074 try:
3078 try:
3075 fnode = pctx.filenode(pfn)
3079 fnode = pctx.filenode(pfn)
3076 grepbody(pfn, parent, flog.read(fnode))
3080 grepbody(pfn, parent, flog.read(fnode))
3077 except error.LookupError:
3081 except error.LookupError:
3078 pass
3082 pass
3079
3083
3080 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3084 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3081 rev = ctx.rev()
3085 rev = ctx.rev()
3082 parent = ctx.p1().rev()
3086 parent = ctx.p1().rev()
3083 for fn in sorted(revfiles.get(rev, [])):
3087 for fn in sorted(revfiles.get(rev, [])):
3084 states = matches[rev][fn]
3088 states = matches[rev][fn]
3085 copy = copies.get(rev, {}).get(fn)
3089 copy = copies.get(rev, {}).get(fn)
3086 if fn in skip:
3090 if fn in skip:
3087 if copy:
3091 if copy:
3088 skip[copy] = True
3092 skip[copy] = True
3089 continue
3093 continue
3090 pstates = matches.get(parent, {}).get(copy or fn, [])
3094 pstates = matches.get(parent, {}).get(copy or fn, [])
3091 if pstates or states:
3095 if pstates or states:
3092 r = display(fn, ctx, pstates, states)
3096 r = display(fn, ctx, pstates, states)
3093 found = found or r
3097 found = found or r
3094 if r and not opts.get('all'):
3098 if r and not opts.get('all'):
3095 skip[fn] = True
3099 skip[fn] = True
3096 if copy:
3100 if copy:
3097 skip[copy] = True
3101 skip[copy] = True
3098 del matches[rev]
3102 del matches[rev]
3099 del revfiles[rev]
3103 del revfiles[rev]
3100
3104
3101 return not found
3105 return not found
3102
3106
3103 @command('heads',
3107 @command('heads',
3104 [('r', 'rev', '',
3108 [('r', 'rev', '',
3105 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3109 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3106 ('t', 'topo', False, _('show topological heads only')),
3110 ('t', 'topo', False, _('show topological heads only')),
3107 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3111 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3108 ('c', 'closed', False, _('show normal and closed branch heads')),
3112 ('c', 'closed', False, _('show normal and closed branch heads')),
3109 ] + templateopts,
3113 ] + templateopts,
3110 _('[-ct] [-r STARTREV] [REV]...'))
3114 _('[-ct] [-r STARTREV] [REV]...'))
3111 def heads(ui, repo, *branchrevs, **opts):
3115 def heads(ui, repo, *branchrevs, **opts):
3112 """show current repository heads or show branch heads
3116 """show current repository heads or show branch heads
3113
3117
3114 With no arguments, show all repository branch heads.
3118 With no arguments, show all repository branch heads.
3115
3119
3116 Repository "heads" are changesets with no child changesets. They are
3120 Repository "heads" are changesets with no child changesets. They are
3117 where development generally takes place and are the usual targets
3121 where development generally takes place and are the usual targets
3118 for update and merge operations. Branch heads are changesets that have
3122 for update and merge operations. Branch heads are changesets that have
3119 no child changeset on the same branch.
3123 no child changeset on the same branch.
3120
3124
3121 If one or more REVs are given, only branch heads on the branches
3125 If one or more REVs are given, only branch heads on the branches
3122 associated with the specified changesets are shown. This means
3126 associated with the specified changesets are shown. This means
3123 that you can use :hg:`heads foo` to see the heads on a branch
3127 that you can use :hg:`heads foo` to see the heads on a branch
3124 named ``foo``.
3128 named ``foo``.
3125
3129
3126 If -c/--closed is specified, also show branch heads marked closed
3130 If -c/--closed is specified, also show branch heads marked closed
3127 (see :hg:`commit --close-branch`).
3131 (see :hg:`commit --close-branch`).
3128
3132
3129 If STARTREV is specified, only those heads that are descendants of
3133 If STARTREV is specified, only those heads that are descendants of
3130 STARTREV will be displayed.
3134 STARTREV will be displayed.
3131
3135
3132 If -t/--topo is specified, named branch mechanics will be ignored and only
3136 If -t/--topo is specified, named branch mechanics will be ignored and only
3133 changesets without children will be shown.
3137 changesets without children will be shown.
3134
3138
3135 Returns 0 if matching heads are found, 1 if not.
3139 Returns 0 if matching heads are found, 1 if not.
3136 """
3140 """
3137
3141
3138 start = None
3142 start = None
3139 if 'rev' in opts:
3143 if 'rev' in opts:
3140 start = scmutil.revsingle(repo, opts['rev'], None).node()
3144 start = scmutil.revsingle(repo, opts['rev'], None).node()
3141
3145
3142 if opts.get('topo'):
3146 if opts.get('topo'):
3143 heads = [repo[h] for h in repo.heads(start)]
3147 heads = [repo[h] for h in repo.heads(start)]
3144 else:
3148 else:
3145 heads = []
3149 heads = []
3146 for branch in repo.branchmap():
3150 for branch in repo.branchmap():
3147 heads += repo.branchheads(branch, start, opts.get('closed'))
3151 heads += repo.branchheads(branch, start, opts.get('closed'))
3148 heads = [repo[h] for h in heads]
3152 heads = [repo[h] for h in heads]
3149
3153
3150 if branchrevs:
3154 if branchrevs:
3151 branches = set(repo[br].branch() for br in branchrevs)
3155 branches = set(repo[br].branch() for br in branchrevs)
3152 heads = [h for h in heads if h.branch() in branches]
3156 heads = [h for h in heads if h.branch() in branches]
3153
3157
3154 if opts.get('active') and branchrevs:
3158 if opts.get('active') and branchrevs:
3155 dagheads = repo.heads(start)
3159 dagheads = repo.heads(start)
3156 heads = [h for h in heads if h.node() in dagheads]
3160 heads = [h for h in heads if h.node() in dagheads]
3157
3161
3158 if branchrevs:
3162 if branchrevs:
3159 haveheads = set(h.branch() for h in heads)
3163 haveheads = set(h.branch() for h in heads)
3160 if branches - haveheads:
3164 if branches - haveheads:
3161 headless = ', '.join(b for b in branches - haveheads)
3165 headless = ', '.join(b for b in branches - haveheads)
3162 msg = _('no open branch heads found on branches %s')
3166 msg = _('no open branch heads found on branches %s')
3163 if opts.get('rev'):
3167 if opts.get('rev'):
3164 msg += _(' (started at %s)') % opts['rev']
3168 msg += _(' (started at %s)') % opts['rev']
3165 ui.warn((msg + '\n') % headless)
3169 ui.warn((msg + '\n') % headless)
3166
3170
3167 if not heads:
3171 if not heads:
3168 return 1
3172 return 1
3169
3173
3170 heads = sorted(heads, key=lambda x: -x.rev())
3174 heads = sorted(heads, key=lambda x: -x.rev())
3171 displayer = cmdutil.show_changeset(ui, repo, opts)
3175 displayer = cmdutil.show_changeset(ui, repo, opts)
3172 for ctx in heads:
3176 for ctx in heads:
3173 displayer.show(ctx)
3177 displayer.show(ctx)
3174 displayer.close()
3178 displayer.close()
3175
3179
3176 @command('help',
3180 @command('help',
3177 [('e', 'extension', None, _('show only help for extensions')),
3181 [('e', 'extension', None, _('show only help for extensions')),
3178 ('c', 'command', None, _('show only help for commands')),
3182 ('c', 'command', None, _('show only help for commands')),
3179 ('k', 'keyword', '', _('show topics matching keyword')),
3183 ('k', 'keyword', '', _('show topics matching keyword')),
3180 ],
3184 ],
3181 _('[-ec] [TOPIC]'))
3185 _('[-ec] [TOPIC]'))
3182 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3186 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3183 """show help for a given topic or a help overview
3187 """show help for a given topic or a help overview
3184
3188
3185 With no arguments, print a list of commands with short help messages.
3189 With no arguments, print a list of commands with short help messages.
3186
3190
3187 Given a topic, extension, or command name, print help for that
3191 Given a topic, extension, or command name, print help for that
3188 topic.
3192 topic.
3189
3193
3190 Returns 0 if successful.
3194 Returns 0 if successful.
3191 """
3195 """
3192
3196
3193 textwidth = min(ui.termwidth(), 80) - 2
3197 textwidth = min(ui.termwidth(), 80) - 2
3194
3198
3195 def helpcmd(name):
3199 def helpcmd(name):
3196 try:
3200 try:
3197 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3201 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3198 except error.AmbiguousCommand, inst:
3202 except error.AmbiguousCommand, inst:
3199 # py3k fix: except vars can't be used outside the scope of the
3203 # py3k fix: except vars can't be used outside the scope of the
3200 # except block, nor can be used inside a lambda. python issue4617
3204 # except block, nor can be used inside a lambda. python issue4617
3201 prefix = inst.args[0]
3205 prefix = inst.args[0]
3202 select = lambda c: c.lstrip('^').startswith(prefix)
3206 select = lambda c: c.lstrip('^').startswith(prefix)
3203 rst = helplist(select)
3207 rst = helplist(select)
3204 return rst
3208 return rst
3205
3209
3206 rst = []
3210 rst = []
3207
3211
3208 # check if it's an invalid alias and display its error if it is
3212 # check if it's an invalid alias and display its error if it is
3209 if getattr(entry[0], 'badalias', False):
3213 if getattr(entry[0], 'badalias', False):
3210 if not unknowncmd:
3214 if not unknowncmd:
3211 ui.pushbuffer()
3215 ui.pushbuffer()
3212 entry[0](ui)
3216 entry[0](ui)
3213 rst.append(ui.popbuffer())
3217 rst.append(ui.popbuffer())
3214 return rst
3218 return rst
3215
3219
3216 # synopsis
3220 # synopsis
3217 if len(entry) > 2:
3221 if len(entry) > 2:
3218 if entry[2].startswith('hg'):
3222 if entry[2].startswith('hg'):
3219 rst.append("%s\n" % entry[2])
3223 rst.append("%s\n" % entry[2])
3220 else:
3224 else:
3221 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3225 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3222 else:
3226 else:
3223 rst.append('hg %s\n' % aliases[0])
3227 rst.append('hg %s\n' % aliases[0])
3224 # aliases
3228 # aliases
3225 if full and not ui.quiet and len(aliases) > 1:
3229 if full and not ui.quiet and len(aliases) > 1:
3226 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3230 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3227 rst.append('\n')
3231 rst.append('\n')
3228
3232
3229 # description
3233 # description
3230 doc = gettext(entry[0].__doc__)
3234 doc = gettext(entry[0].__doc__)
3231 if not doc:
3235 if not doc:
3232 doc = _("(no help text available)")
3236 doc = _("(no help text available)")
3233 if util.safehasattr(entry[0], 'definition'): # aliased command
3237 if util.safehasattr(entry[0], 'definition'): # aliased command
3234 if entry[0].definition.startswith('!'): # shell alias
3238 if entry[0].definition.startswith('!'): # shell alias
3235 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3239 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3236 else:
3240 else:
3237 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3241 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3238 doc = doc.splitlines(True)
3242 doc = doc.splitlines(True)
3239 if ui.quiet or not full:
3243 if ui.quiet or not full:
3240 rst.append(doc[0])
3244 rst.append(doc[0])
3241 else:
3245 else:
3242 rst.extend(doc)
3246 rst.extend(doc)
3243 rst.append('\n')
3247 rst.append('\n')
3244
3248
3245 # check if this command shadows a non-trivial (multi-line)
3249 # check if this command shadows a non-trivial (multi-line)
3246 # extension help text
3250 # extension help text
3247 try:
3251 try:
3248 mod = extensions.find(name)
3252 mod = extensions.find(name)
3249 doc = gettext(mod.__doc__) or ''
3253 doc = gettext(mod.__doc__) or ''
3250 if '\n' in doc.strip():
3254 if '\n' in doc.strip():
3251 msg = _('use "hg help -e %s" to show help for '
3255 msg = _('use "hg help -e %s" to show help for '
3252 'the %s extension') % (name, name)
3256 'the %s extension') % (name, name)
3253 rst.append('\n%s\n' % msg)
3257 rst.append('\n%s\n' % msg)
3254 except KeyError:
3258 except KeyError:
3255 pass
3259 pass
3256
3260
3257 # options
3261 # options
3258 if not ui.quiet and entry[1]:
3262 if not ui.quiet and entry[1]:
3259 rst.append('\n%s\n\n' % _("options:"))
3263 rst.append('\n%s\n\n' % _("options:"))
3260 rst.append(help.optrst(entry[1], ui.verbose))
3264 rst.append(help.optrst(entry[1], ui.verbose))
3261
3265
3262 if ui.verbose:
3266 if ui.verbose:
3263 rst.append('\n%s\n\n' % _("global options:"))
3267 rst.append('\n%s\n\n' % _("global options:"))
3264 rst.append(help.optrst(globalopts, ui.verbose))
3268 rst.append(help.optrst(globalopts, ui.verbose))
3265
3269
3266 if not ui.verbose:
3270 if not ui.verbose:
3267 if not full:
3271 if not full:
3268 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3272 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3269 % name)
3273 % name)
3270 elif not ui.quiet:
3274 elif not ui.quiet:
3271 omitted = _('use "hg -v help %s" to show more complete'
3275 omitted = _('use "hg -v help %s" to show more complete'
3272 ' help and the global options') % name
3276 ' help and the global options') % name
3273 notomitted = _('use "hg -v help %s" to show'
3277 notomitted = _('use "hg -v help %s" to show'
3274 ' the global options') % name
3278 ' the global options') % name
3275 help.indicateomitted(rst, omitted, notomitted)
3279 help.indicateomitted(rst, omitted, notomitted)
3276
3280
3277 return rst
3281 return rst
3278
3282
3279
3283
3280 def helplist(select=None):
3284 def helplist(select=None):
3281 # list of commands
3285 # list of commands
3282 if name == "shortlist":
3286 if name == "shortlist":
3283 header = _('basic commands:\n\n')
3287 header = _('basic commands:\n\n')
3284 else:
3288 else:
3285 header = _('list of commands:\n\n')
3289 header = _('list of commands:\n\n')
3286
3290
3287 h = {}
3291 h = {}
3288 cmds = {}
3292 cmds = {}
3289 for c, e in table.iteritems():
3293 for c, e in table.iteritems():
3290 f = c.split("|", 1)[0]
3294 f = c.split("|", 1)[0]
3291 if select and not select(f):
3295 if select and not select(f):
3292 continue
3296 continue
3293 if (not select and name != 'shortlist' and
3297 if (not select and name != 'shortlist' and
3294 e[0].__module__ != __name__):
3298 e[0].__module__ != __name__):
3295 continue
3299 continue
3296 if name == "shortlist" and not f.startswith("^"):
3300 if name == "shortlist" and not f.startswith("^"):
3297 continue
3301 continue
3298 f = f.lstrip("^")
3302 f = f.lstrip("^")
3299 if not ui.debugflag and f.startswith("debug"):
3303 if not ui.debugflag and f.startswith("debug"):
3300 continue
3304 continue
3301 doc = e[0].__doc__
3305 doc = e[0].__doc__
3302 if doc and 'DEPRECATED' in doc and not ui.verbose:
3306 if doc and 'DEPRECATED' in doc and not ui.verbose:
3303 continue
3307 continue
3304 doc = gettext(doc)
3308 doc = gettext(doc)
3305 if not doc:
3309 if not doc:
3306 doc = _("(no help text available)")
3310 doc = _("(no help text available)")
3307 h[f] = doc.splitlines()[0].rstrip()
3311 h[f] = doc.splitlines()[0].rstrip()
3308 cmds[f] = c.lstrip("^")
3312 cmds[f] = c.lstrip("^")
3309
3313
3310 rst = []
3314 rst = []
3311 if not h:
3315 if not h:
3312 if not ui.quiet:
3316 if not ui.quiet:
3313 rst.append(_('no commands defined\n'))
3317 rst.append(_('no commands defined\n'))
3314 return rst
3318 return rst
3315
3319
3316 if not ui.quiet:
3320 if not ui.quiet:
3317 rst.append(header)
3321 rst.append(header)
3318 fns = sorted(h)
3322 fns = sorted(h)
3319 for f in fns:
3323 for f in fns:
3320 if ui.verbose:
3324 if ui.verbose:
3321 commands = cmds[f].replace("|",", ")
3325 commands = cmds[f].replace("|",", ")
3322 rst.append(" :%s: %s\n" % (commands, h[f]))
3326 rst.append(" :%s: %s\n" % (commands, h[f]))
3323 else:
3327 else:
3324 rst.append(' :%s: %s\n' % (f, h[f]))
3328 rst.append(' :%s: %s\n' % (f, h[f]))
3325
3329
3326 if not name:
3330 if not name:
3327 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3331 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3328 if exts:
3332 if exts:
3329 rst.append('\n')
3333 rst.append('\n')
3330 rst.extend(exts)
3334 rst.extend(exts)
3331
3335
3332 rst.append(_("\nadditional help topics:\n\n"))
3336 rst.append(_("\nadditional help topics:\n\n"))
3333 topics = []
3337 topics = []
3334 for names, header, doc in help.helptable:
3338 for names, header, doc in help.helptable:
3335 topics.append((names[0], header))
3339 topics.append((names[0], header))
3336 for t, desc in topics:
3340 for t, desc in topics:
3337 rst.append(" :%s: %s\n" % (t, desc))
3341 rst.append(" :%s: %s\n" % (t, desc))
3338
3342
3339 optlist = []
3343 optlist = []
3340 if not ui.quiet:
3344 if not ui.quiet:
3341 if ui.verbose:
3345 if ui.verbose:
3342 optlist.append((_("global options:"), globalopts))
3346 optlist.append((_("global options:"), globalopts))
3343 if name == 'shortlist':
3347 if name == 'shortlist':
3344 optlist.append((_('use "hg help" for the full list '
3348 optlist.append((_('use "hg help" for the full list '
3345 'of commands'), ()))
3349 'of commands'), ()))
3346 else:
3350 else:
3347 if name == 'shortlist':
3351 if name == 'shortlist':
3348 msg = _('use "hg help" for the full list of commands '
3352 msg = _('use "hg help" for the full list of commands '
3349 'or "hg -v" for details')
3353 'or "hg -v" for details')
3350 elif name and not full:
3354 elif name and not full:
3351 msg = _('use "hg help %s" to show the full help '
3355 msg = _('use "hg help %s" to show the full help '
3352 'text') % name
3356 'text') % name
3353 else:
3357 else:
3354 msg = _('use "hg -v help%s" to show builtin aliases and '
3358 msg = _('use "hg -v help%s" to show builtin aliases and '
3355 'global options') % (name and " " + name or "")
3359 'global options') % (name and " " + name or "")
3356 optlist.append((msg, ()))
3360 optlist.append((msg, ()))
3357
3361
3358 if optlist:
3362 if optlist:
3359 for title, options in optlist:
3363 for title, options in optlist:
3360 rst.append('\n%s\n' % title)
3364 rst.append('\n%s\n' % title)
3361 if options:
3365 if options:
3362 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3366 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3363 return rst
3367 return rst
3364
3368
3365 def helptopic(name):
3369 def helptopic(name):
3366 for names, header, doc in help.helptable:
3370 for names, header, doc in help.helptable:
3367 if name in names:
3371 if name in names:
3368 break
3372 break
3369 else:
3373 else:
3370 raise error.UnknownCommand(name)
3374 raise error.UnknownCommand(name)
3371
3375
3372 rst = ["%s\n\n" % header]
3376 rst = ["%s\n\n" % header]
3373 # description
3377 # description
3374 if not doc:
3378 if not doc:
3375 rst.append(" %s\n" % _("(no help text available)"))
3379 rst.append(" %s\n" % _("(no help text available)"))
3376 if util.safehasattr(doc, '__call__'):
3380 if util.safehasattr(doc, '__call__'):
3377 rst += [" %s\n" % l for l in doc().splitlines()]
3381 rst += [" %s\n" % l for l in doc().splitlines()]
3378
3382
3379 if not ui.verbose:
3383 if not ui.verbose:
3380 omitted = (_('use "hg help -v %s" to show more complete help') %
3384 omitted = (_('use "hg help -v %s" to show more complete help') %
3381 name)
3385 name)
3382 help.indicateomitted(rst, omitted)
3386 help.indicateomitted(rst, omitted)
3383
3387
3384 try:
3388 try:
3385 cmdutil.findcmd(name, table)
3389 cmdutil.findcmd(name, table)
3386 rst.append(_('\nuse "hg help -c %s" to see help for '
3390 rst.append(_('\nuse "hg help -c %s" to see help for '
3387 'the %s command\n') % (name, name))
3391 'the %s command\n') % (name, name))
3388 except error.UnknownCommand:
3392 except error.UnknownCommand:
3389 pass
3393 pass
3390 return rst
3394 return rst
3391
3395
3392 def helpext(name):
3396 def helpext(name):
3393 try:
3397 try:
3394 mod = extensions.find(name)
3398 mod = extensions.find(name)
3395 doc = gettext(mod.__doc__) or _('no help text available')
3399 doc = gettext(mod.__doc__) or _('no help text available')
3396 except KeyError:
3400 except KeyError:
3397 mod = None
3401 mod = None
3398 doc = extensions.disabledext(name)
3402 doc = extensions.disabledext(name)
3399 if not doc:
3403 if not doc:
3400 raise error.UnknownCommand(name)
3404 raise error.UnknownCommand(name)
3401
3405
3402 if '\n' not in doc:
3406 if '\n' not in doc:
3403 head, tail = doc, ""
3407 head, tail = doc, ""
3404 else:
3408 else:
3405 head, tail = doc.split('\n', 1)
3409 head, tail = doc.split('\n', 1)
3406 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3410 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3407 if tail:
3411 if tail:
3408 rst.extend(tail.splitlines(True))
3412 rst.extend(tail.splitlines(True))
3409 rst.append('\n')
3413 rst.append('\n')
3410
3414
3411 if not ui.verbose:
3415 if not ui.verbose:
3412 omitted = (_('use "hg help -v %s" to show more complete help') %
3416 omitted = (_('use "hg help -v %s" to show more complete help') %
3413 name)
3417 name)
3414 help.indicateomitted(rst, omitted)
3418 help.indicateomitted(rst, omitted)
3415
3419
3416 if mod:
3420 if mod:
3417 try:
3421 try:
3418 ct = mod.cmdtable
3422 ct = mod.cmdtable
3419 except AttributeError:
3423 except AttributeError:
3420 ct = {}
3424 ct = {}
3421 modcmds = set([c.split('|', 1)[0] for c in ct])
3425 modcmds = set([c.split('|', 1)[0] for c in ct])
3422 rst.extend(helplist(modcmds.__contains__))
3426 rst.extend(helplist(modcmds.__contains__))
3423 else:
3427 else:
3424 rst.append(_('use "hg help extensions" for information on enabling '
3428 rst.append(_('use "hg help extensions" for information on enabling '
3425 'extensions\n'))
3429 'extensions\n'))
3426 return rst
3430 return rst
3427
3431
3428 def helpextcmd(name):
3432 def helpextcmd(name):
3429 cmd, ext, mod = extensions.disabledcmd(ui, name,
3433 cmd, ext, mod = extensions.disabledcmd(ui, name,
3430 ui.configbool('ui', 'strict'))
3434 ui.configbool('ui', 'strict'))
3431 doc = gettext(mod.__doc__).splitlines()[0]
3435 doc = gettext(mod.__doc__).splitlines()[0]
3432
3436
3433 rst = help.listexts(_("'%s' is provided by the following "
3437 rst = help.listexts(_("'%s' is provided by the following "
3434 "extension:") % cmd, {ext: doc}, indent=4)
3438 "extension:") % cmd, {ext: doc}, indent=4)
3435 rst.append('\n')
3439 rst.append('\n')
3436 rst.append(_('use "hg help extensions" for information on enabling '
3440 rst.append(_('use "hg help extensions" for information on enabling '
3437 'extensions\n'))
3441 'extensions\n'))
3438 return rst
3442 return rst
3439
3443
3440
3444
3441 rst = []
3445 rst = []
3442 kw = opts.get('keyword')
3446 kw = opts.get('keyword')
3443 if kw:
3447 if kw:
3444 matches = help.topicmatch(kw)
3448 matches = help.topicmatch(kw)
3445 for t, title in (('topics', _('Topics')),
3449 for t, title in (('topics', _('Topics')),
3446 ('commands', _('Commands')),
3450 ('commands', _('Commands')),
3447 ('extensions', _('Extensions')),
3451 ('extensions', _('Extensions')),
3448 ('extensioncommands', _('Extension Commands'))):
3452 ('extensioncommands', _('Extension Commands'))):
3449 if matches[t]:
3453 if matches[t]:
3450 rst.append('%s:\n\n' % title)
3454 rst.append('%s:\n\n' % title)
3451 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3455 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3452 rst.append('\n')
3456 rst.append('\n')
3453 elif name and name != 'shortlist':
3457 elif name and name != 'shortlist':
3454 i = None
3458 i = None
3455 if unknowncmd:
3459 if unknowncmd:
3456 queries = (helpextcmd,)
3460 queries = (helpextcmd,)
3457 elif opts.get('extension'):
3461 elif opts.get('extension'):
3458 queries = (helpext,)
3462 queries = (helpext,)
3459 elif opts.get('command'):
3463 elif opts.get('command'):
3460 queries = (helpcmd,)
3464 queries = (helpcmd,)
3461 else:
3465 else:
3462 queries = (helptopic, helpcmd, helpext, helpextcmd)
3466 queries = (helptopic, helpcmd, helpext, helpextcmd)
3463 for f in queries:
3467 for f in queries:
3464 try:
3468 try:
3465 rst = f(name)
3469 rst = f(name)
3466 i = None
3470 i = None
3467 break
3471 break
3468 except error.UnknownCommand, inst:
3472 except error.UnknownCommand, inst:
3469 i = inst
3473 i = inst
3470 if i:
3474 if i:
3471 raise i
3475 raise i
3472 else:
3476 else:
3473 # program name
3477 # program name
3474 if not ui.quiet:
3478 if not ui.quiet:
3475 rst = [_("Mercurial Distributed SCM\n"), '\n']
3479 rst = [_("Mercurial Distributed SCM\n"), '\n']
3476 rst.extend(helplist())
3480 rst.extend(helplist())
3477
3481
3478 keep = ui.verbose and ['verbose'] or []
3482 keep = ui.verbose and ['verbose'] or []
3479 text = ''.join(rst)
3483 text = ''.join(rst)
3480 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3484 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3481 if 'verbose' in pruned:
3485 if 'verbose' in pruned:
3482 keep.append('omitted')
3486 keep.append('omitted')
3483 else:
3487 else:
3484 keep.append('notomitted')
3488 keep.append('notomitted')
3485 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3489 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3486 ui.write(formatted)
3490 ui.write(formatted)
3487
3491
3488
3492
3489 @command('identify|id',
3493 @command('identify|id',
3490 [('r', 'rev', '',
3494 [('r', 'rev', '',
3491 _('identify the specified revision'), _('REV')),
3495 _('identify the specified revision'), _('REV')),
3492 ('n', 'num', None, _('show local revision number')),
3496 ('n', 'num', None, _('show local revision number')),
3493 ('i', 'id', None, _('show global revision id')),
3497 ('i', 'id', None, _('show global revision id')),
3494 ('b', 'branch', None, _('show branch')),
3498 ('b', 'branch', None, _('show branch')),
3495 ('t', 'tags', None, _('show tags')),
3499 ('t', 'tags', None, _('show tags')),
3496 ('B', 'bookmarks', None, _('show bookmarks')),
3500 ('B', 'bookmarks', None, _('show bookmarks')),
3497 ] + remoteopts,
3501 ] + remoteopts,
3498 _('[-nibtB] [-r REV] [SOURCE]'))
3502 _('[-nibtB] [-r REV] [SOURCE]'))
3499 def identify(ui, repo, source=None, rev=None,
3503 def identify(ui, repo, source=None, rev=None,
3500 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3504 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3501 """identify the working copy or specified revision
3505 """identify the working copy or specified revision
3502
3506
3503 Print a summary identifying the repository state at REV using one or
3507 Print a summary identifying the repository state at REV using one or
3504 two parent hash identifiers, followed by a "+" if the working
3508 two parent hash identifiers, followed by a "+" if the working
3505 directory has uncommitted changes, the branch name (if not default),
3509 directory has uncommitted changes, the branch name (if not default),
3506 a list of tags, and a list of bookmarks.
3510 a list of tags, and a list of bookmarks.
3507
3511
3508 When REV is not given, print a summary of the current state of the
3512 When REV is not given, print a summary of the current state of the
3509 repository.
3513 repository.
3510
3514
3511 Specifying a path to a repository root or Mercurial bundle will
3515 Specifying a path to a repository root or Mercurial bundle will
3512 cause lookup to operate on that repository/bundle.
3516 cause lookup to operate on that repository/bundle.
3513
3517
3514 .. container:: verbose
3518 .. container:: verbose
3515
3519
3516 Examples:
3520 Examples:
3517
3521
3518 - generate a build identifier for the working directory::
3522 - generate a build identifier for the working directory::
3519
3523
3520 hg id --id > build-id.dat
3524 hg id --id > build-id.dat
3521
3525
3522 - find the revision corresponding to a tag::
3526 - find the revision corresponding to a tag::
3523
3527
3524 hg id -n -r 1.3
3528 hg id -n -r 1.3
3525
3529
3526 - check the most recent revision of a remote repository::
3530 - check the most recent revision of a remote repository::
3527
3531
3528 hg id -r tip http://selenic.com/hg/
3532 hg id -r tip http://selenic.com/hg/
3529
3533
3530 Returns 0 if successful.
3534 Returns 0 if successful.
3531 """
3535 """
3532
3536
3533 if not repo and not source:
3537 if not repo and not source:
3534 raise util.Abort(_("there is no Mercurial repository here "
3538 raise util.Abort(_("there is no Mercurial repository here "
3535 "(.hg not found)"))
3539 "(.hg not found)"))
3536
3540
3537 hexfunc = ui.debugflag and hex or short
3541 hexfunc = ui.debugflag and hex or short
3538 default = not (num or id or branch or tags or bookmarks)
3542 default = not (num or id or branch or tags or bookmarks)
3539 output = []
3543 output = []
3540 revs = []
3544 revs = []
3541
3545
3542 if source:
3546 if source:
3543 source, branches = hg.parseurl(ui.expandpath(source))
3547 source, branches = hg.parseurl(ui.expandpath(source))
3544 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3548 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3545 repo = peer.local()
3549 repo = peer.local()
3546 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3550 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3547
3551
3548 if not repo:
3552 if not repo:
3549 if num or branch or tags:
3553 if num or branch or tags:
3550 raise util.Abort(
3554 raise util.Abort(
3551 _("can't query remote revision number, branch, or tags"))
3555 _("can't query remote revision number, branch, or tags"))
3552 if not rev and revs:
3556 if not rev and revs:
3553 rev = revs[0]
3557 rev = revs[0]
3554 if not rev:
3558 if not rev:
3555 rev = "tip"
3559 rev = "tip"
3556
3560
3557 remoterev = peer.lookup(rev)
3561 remoterev = peer.lookup(rev)
3558 if default or id:
3562 if default or id:
3559 output = [hexfunc(remoterev)]
3563 output = [hexfunc(remoterev)]
3560
3564
3561 def getbms():
3565 def getbms():
3562 bms = []
3566 bms = []
3563
3567
3564 if 'bookmarks' in peer.listkeys('namespaces'):
3568 if 'bookmarks' in peer.listkeys('namespaces'):
3565 hexremoterev = hex(remoterev)
3569 hexremoterev = hex(remoterev)
3566 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3570 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3567 if bmr == hexremoterev]
3571 if bmr == hexremoterev]
3568
3572
3569 return bms
3573 return bms
3570
3574
3571 if bookmarks:
3575 if bookmarks:
3572 output.extend(getbms())
3576 output.extend(getbms())
3573 elif default and not ui.quiet:
3577 elif default and not ui.quiet:
3574 # multiple bookmarks for a single parent separated by '/'
3578 # multiple bookmarks for a single parent separated by '/'
3575 bm = '/'.join(getbms())
3579 bm = '/'.join(getbms())
3576 if bm:
3580 if bm:
3577 output.append(bm)
3581 output.append(bm)
3578 else:
3582 else:
3579 if not rev:
3583 if not rev:
3580 ctx = repo[None]
3584 ctx = repo[None]
3581 parents = ctx.parents()
3585 parents = ctx.parents()
3582 changed = ""
3586 changed = ""
3583 if default or id or num:
3587 if default or id or num:
3584 if (util.any(repo.status())
3588 if (util.any(repo.status())
3585 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3589 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3586 changed = '+'
3590 changed = '+'
3587 if default or id:
3591 if default or id:
3588 output = ["%s%s" %
3592 output = ["%s%s" %
3589 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3593 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3590 if num:
3594 if num:
3591 output.append("%s%s" %
3595 output.append("%s%s" %
3592 ('+'.join([str(p.rev()) for p in parents]), changed))
3596 ('+'.join([str(p.rev()) for p in parents]), changed))
3593 else:
3597 else:
3594 ctx = scmutil.revsingle(repo, rev)
3598 ctx = scmutil.revsingle(repo, rev)
3595 if default or id:
3599 if default or id:
3596 output = [hexfunc(ctx.node())]
3600 output = [hexfunc(ctx.node())]
3597 if num:
3601 if num:
3598 output.append(str(ctx.rev()))
3602 output.append(str(ctx.rev()))
3599
3603
3600 if default and not ui.quiet:
3604 if default and not ui.quiet:
3601 b = ctx.branch()
3605 b = ctx.branch()
3602 if b != 'default':
3606 if b != 'default':
3603 output.append("(%s)" % b)
3607 output.append("(%s)" % b)
3604
3608
3605 # multiple tags for a single parent separated by '/'
3609 # multiple tags for a single parent separated by '/'
3606 t = '/'.join(ctx.tags())
3610 t = '/'.join(ctx.tags())
3607 if t:
3611 if t:
3608 output.append(t)
3612 output.append(t)
3609
3613
3610 # multiple bookmarks for a single parent separated by '/'
3614 # multiple bookmarks for a single parent separated by '/'
3611 bm = '/'.join(ctx.bookmarks())
3615 bm = '/'.join(ctx.bookmarks())
3612 if bm:
3616 if bm:
3613 output.append(bm)
3617 output.append(bm)
3614 else:
3618 else:
3615 if branch:
3619 if branch:
3616 output.append(ctx.branch())
3620 output.append(ctx.branch())
3617
3621
3618 if tags:
3622 if tags:
3619 output.extend(ctx.tags())
3623 output.extend(ctx.tags())
3620
3624
3621 if bookmarks:
3625 if bookmarks:
3622 output.extend(ctx.bookmarks())
3626 output.extend(ctx.bookmarks())
3623
3627
3624 ui.write("%s\n" % ' '.join(output))
3628 ui.write("%s\n" % ' '.join(output))
3625
3629
3626 @command('import|patch',
3630 @command('import|patch',
3627 [('p', 'strip', 1,
3631 [('p', 'strip', 1,
3628 _('directory strip option for patch. This has the same '
3632 _('directory strip option for patch. This has the same '
3629 'meaning as the corresponding patch option'), _('NUM')),
3633 'meaning as the corresponding patch option'), _('NUM')),
3630 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3634 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3631 ('e', 'edit', False, _('invoke editor on commit messages')),
3635 ('e', 'edit', False, _('invoke editor on commit messages')),
3632 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3636 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3633 ('', 'no-commit', None,
3637 ('', 'no-commit', None,
3634 _("don't commit, just update the working directory")),
3638 _("don't commit, just update the working directory")),
3635 ('', 'bypass', None,
3639 ('', 'bypass', None,
3636 _("apply patch without touching the working directory")),
3640 _("apply patch without touching the working directory")),
3637 ('', 'exact', None,
3641 ('', 'exact', None,
3638 _('apply patch to the nodes from which it was generated')),
3642 _('apply patch to the nodes from which it was generated')),
3639 ('', 'import-branch', None,
3643 ('', 'import-branch', None,
3640 _('use any branch information in patch (implied by --exact)'))] +
3644 _('use any branch information in patch (implied by --exact)'))] +
3641 commitopts + commitopts2 + similarityopts,
3645 commitopts + commitopts2 + similarityopts,
3642 _('[OPTION]... PATCH...'))
3646 _('[OPTION]... PATCH...'))
3643 def import_(ui, repo, patch1=None, *patches, **opts):
3647 def import_(ui, repo, patch1=None, *patches, **opts):
3644 """import an ordered set of patches
3648 """import an ordered set of patches
3645
3649
3646 Import a list of patches and commit them individually (unless
3650 Import a list of patches and commit them individually (unless
3647 --no-commit is specified).
3651 --no-commit is specified).
3648
3652
3649 If there are outstanding changes in the working directory, import
3653 If there are outstanding changes in the working directory, import
3650 will abort unless given the -f/--force flag.
3654 will abort unless given the -f/--force flag.
3651
3655
3652 You can import a patch straight from a mail message. Even patches
3656 You can import a patch straight from a mail message. Even patches
3653 as attachments work (to use the body part, it must have type
3657 as attachments work (to use the body part, it must have type
3654 text/plain or text/x-patch). From and Subject headers of email
3658 text/plain or text/x-patch). From and Subject headers of email
3655 message are used as default committer and commit message. All
3659 message are used as default committer and commit message. All
3656 text/plain body parts before first diff are added to commit
3660 text/plain body parts before first diff are added to commit
3657 message.
3661 message.
3658
3662
3659 If the imported patch was generated by :hg:`export`, user and
3663 If the imported patch was generated by :hg:`export`, user and
3660 description from patch override values from message headers and
3664 description from patch override values from message headers and
3661 body. Values given on command line with -m/--message and -u/--user
3665 body. Values given on command line with -m/--message and -u/--user
3662 override these.
3666 override these.
3663
3667
3664 If --exact is specified, import will set the working directory to
3668 If --exact is specified, import will set the working directory to
3665 the parent of each patch before applying it, and will abort if the
3669 the parent of each patch before applying it, and will abort if the
3666 resulting changeset has a different ID than the one recorded in
3670 resulting changeset has a different ID than the one recorded in
3667 the patch. This may happen due to character set problems or other
3671 the patch. This may happen due to character set problems or other
3668 deficiencies in the text patch format.
3672 deficiencies in the text patch format.
3669
3673
3670 Use --bypass to apply and commit patches directly to the
3674 Use --bypass to apply and commit patches directly to the
3671 repository, not touching the working directory. Without --exact,
3675 repository, not touching the working directory. Without --exact,
3672 patches will be applied on top of the working directory parent
3676 patches will be applied on top of the working directory parent
3673 revision.
3677 revision.
3674
3678
3675 With -s/--similarity, hg will attempt to discover renames and
3679 With -s/--similarity, hg will attempt to discover renames and
3676 copies in the patch in the same way as :hg:`addremove`.
3680 copies in the patch in the same way as :hg:`addremove`.
3677
3681
3678 To read a patch from standard input, use "-" as the patch name. If
3682 To read a patch from standard input, use "-" as the patch name. If
3679 a URL is specified, the patch will be downloaded from it.
3683 a URL is specified, the patch will be downloaded from it.
3680 See :hg:`help dates` for a list of formats valid for -d/--date.
3684 See :hg:`help dates` for a list of formats valid for -d/--date.
3681
3685
3682 .. container:: verbose
3686 .. container:: verbose
3683
3687
3684 Examples:
3688 Examples:
3685
3689
3686 - import a traditional patch from a website and detect renames::
3690 - import a traditional patch from a website and detect renames::
3687
3691
3688 hg import -s 80 http://example.com/bugfix.patch
3692 hg import -s 80 http://example.com/bugfix.patch
3689
3693
3690 - import a changeset from an hgweb server::
3694 - import a changeset from an hgweb server::
3691
3695
3692 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3696 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3693
3697
3694 - import all the patches in an Unix-style mbox::
3698 - import all the patches in an Unix-style mbox::
3695
3699
3696 hg import incoming-patches.mbox
3700 hg import incoming-patches.mbox
3697
3701
3698 - attempt to exactly restore an exported changeset (not always
3702 - attempt to exactly restore an exported changeset (not always
3699 possible)::
3703 possible)::
3700
3704
3701 hg import --exact proposed-fix.patch
3705 hg import --exact proposed-fix.patch
3702
3706
3703 Returns 0 on success.
3707 Returns 0 on success.
3704 """
3708 """
3705
3709
3706 if not patch1:
3710 if not patch1:
3707 raise util.Abort(_('need at least one patch to import'))
3711 raise util.Abort(_('need at least one patch to import'))
3708
3712
3709 patches = (patch1,) + patches
3713 patches = (patch1,) + patches
3710
3714
3711 date = opts.get('date')
3715 date = opts.get('date')
3712 if date:
3716 if date:
3713 opts['date'] = util.parsedate(date)
3717 opts['date'] = util.parsedate(date)
3714
3718
3715 editor = cmdutil.commiteditor
3719 editor = cmdutil.commiteditor
3716 if opts.get('edit'):
3720 if opts.get('edit'):
3717 editor = cmdutil.commitforceeditor
3721 editor = cmdutil.commitforceeditor
3718
3722
3719 update = not opts.get('bypass')
3723 update = not opts.get('bypass')
3720 if not update and opts.get('no_commit'):
3724 if not update and opts.get('no_commit'):
3721 raise util.Abort(_('cannot use --no-commit with --bypass'))
3725 raise util.Abort(_('cannot use --no-commit with --bypass'))
3722 try:
3726 try:
3723 sim = float(opts.get('similarity') or 0)
3727 sim = float(opts.get('similarity') or 0)
3724 except ValueError:
3728 except ValueError:
3725 raise util.Abort(_('similarity must be a number'))
3729 raise util.Abort(_('similarity must be a number'))
3726 if sim < 0 or sim > 100:
3730 if sim < 0 or sim > 100:
3727 raise util.Abort(_('similarity must be between 0 and 100'))
3731 raise util.Abort(_('similarity must be between 0 and 100'))
3728 if sim and not update:
3732 if sim and not update:
3729 raise util.Abort(_('cannot use --similarity with --bypass'))
3733 raise util.Abort(_('cannot use --similarity with --bypass'))
3730
3734
3731 if (opts.get('exact') or not opts.get('force')) and update:
3735 if (opts.get('exact') or not opts.get('force')) and update:
3732 cmdutil.bailifchanged(repo)
3736 cmdutil.bailifchanged(repo)
3733
3737
3734 base = opts["base"]
3738 base = opts["base"]
3735 strip = opts["strip"]
3739 strip = opts["strip"]
3736 wlock = lock = tr = None
3740 wlock = lock = tr = None
3737 msgs = []
3741 msgs = []
3738
3742
3739 def checkexact(repo, n, nodeid):
3743 def checkexact(repo, n, nodeid):
3740 if opts.get('exact') and hex(n) != nodeid:
3744 if opts.get('exact') and hex(n) != nodeid:
3741 repo.rollback()
3745 repo.rollback()
3742 raise util.Abort(_('patch is damaged or loses information'))
3746 raise util.Abort(_('patch is damaged or loses information'))
3743
3747
3744 def tryone(ui, hunk, parents):
3748 def tryone(ui, hunk, parents):
3745 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3749 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3746 patch.extract(ui, hunk)
3750 patch.extract(ui, hunk)
3747
3751
3748 if not tmpname:
3752 if not tmpname:
3749 return (None, None)
3753 return (None, None)
3750 msg = _('applied to working directory')
3754 msg = _('applied to working directory')
3751
3755
3752 try:
3756 try:
3753 cmdline_message = cmdutil.logmessage(ui, opts)
3757 cmdline_message = cmdutil.logmessage(ui, opts)
3754 if cmdline_message:
3758 if cmdline_message:
3755 # pickup the cmdline msg
3759 # pickup the cmdline msg
3756 message = cmdline_message
3760 message = cmdline_message
3757 elif message:
3761 elif message:
3758 # pickup the patch msg
3762 # pickup the patch msg
3759 message = message.strip()
3763 message = message.strip()
3760 else:
3764 else:
3761 # launch the editor
3765 # launch the editor
3762 message = None
3766 message = None
3763 ui.debug('message:\n%s\n' % message)
3767 ui.debug('message:\n%s\n' % message)
3764
3768
3765 if len(parents) == 1:
3769 if len(parents) == 1:
3766 parents.append(repo[nullid])
3770 parents.append(repo[nullid])
3767 if opts.get('exact'):
3771 if opts.get('exact'):
3768 if not nodeid or not p1:
3772 if not nodeid or not p1:
3769 raise util.Abort(_('not a Mercurial patch'))
3773 raise util.Abort(_('not a Mercurial patch'))
3770 p1 = repo[p1]
3774 p1 = repo[p1]
3771 p2 = repo[p2 or nullid]
3775 p2 = repo[p2 or nullid]
3772 elif p2:
3776 elif p2:
3773 try:
3777 try:
3774 p1 = repo[p1]
3778 p1 = repo[p1]
3775 p2 = repo[p2]
3779 p2 = repo[p2]
3776 # Without any options, consider p2 only if the
3780 # Without any options, consider p2 only if the
3777 # patch is being applied on top of the recorded
3781 # patch is being applied on top of the recorded
3778 # first parent.
3782 # first parent.
3779 if p1 != parents[0]:
3783 if p1 != parents[0]:
3780 p1 = parents[0]
3784 p1 = parents[0]
3781 p2 = repo[nullid]
3785 p2 = repo[nullid]
3782 except error.RepoError:
3786 except error.RepoError:
3783 p1, p2 = parents
3787 p1, p2 = parents
3784 else:
3788 else:
3785 p1, p2 = parents
3789 p1, p2 = parents
3786
3790
3787 n = None
3791 n = None
3788 if update:
3792 if update:
3789 if p1 != parents[0]:
3793 if p1 != parents[0]:
3790 hg.clean(repo, p1.node())
3794 hg.clean(repo, p1.node())
3791 if p2 != parents[1]:
3795 if p2 != parents[1]:
3792 repo.setparents(p1.node(), p2.node())
3796 repo.setparents(p1.node(), p2.node())
3793
3797
3794 if opts.get('exact') or opts.get('import_branch'):
3798 if opts.get('exact') or opts.get('import_branch'):
3795 repo.dirstate.setbranch(branch or 'default')
3799 repo.dirstate.setbranch(branch or 'default')
3796
3800
3797 files = set()
3801 files = set()
3798 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3802 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3799 eolmode=None, similarity=sim / 100.0)
3803 eolmode=None, similarity=sim / 100.0)
3800 files = list(files)
3804 files = list(files)
3801 if opts.get('no_commit'):
3805 if opts.get('no_commit'):
3802 if message:
3806 if message:
3803 msgs.append(message)
3807 msgs.append(message)
3804 else:
3808 else:
3805 if opts.get('exact') or p2:
3809 if opts.get('exact') or p2:
3806 # If you got here, you either use --force and know what
3810 # If you got here, you either use --force and know what
3807 # you are doing or used --exact or a merge patch while
3811 # you are doing or used --exact or a merge patch while
3808 # being updated to its first parent.
3812 # being updated to its first parent.
3809 m = None
3813 m = None
3810 else:
3814 else:
3811 m = scmutil.matchfiles(repo, files or [])
3815 m = scmutil.matchfiles(repo, files or [])
3812 n = repo.commit(message, opts.get('user') or user,
3816 n = repo.commit(message, opts.get('user') or user,
3813 opts.get('date') or date, match=m,
3817 opts.get('date') or date, match=m,
3814 editor=editor)
3818 editor=editor)
3815 checkexact(repo, n, nodeid)
3819 checkexact(repo, n, nodeid)
3816 else:
3820 else:
3817 if opts.get('exact') or opts.get('import_branch'):
3821 if opts.get('exact') or opts.get('import_branch'):
3818 branch = branch or 'default'
3822 branch = branch or 'default'
3819 else:
3823 else:
3820 branch = p1.branch()
3824 branch = p1.branch()
3821 store = patch.filestore()
3825 store = patch.filestore()
3822 try:
3826 try:
3823 files = set()
3827 files = set()
3824 try:
3828 try:
3825 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3829 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3826 files, eolmode=None)
3830 files, eolmode=None)
3827 except patch.PatchError, e:
3831 except patch.PatchError, e:
3828 raise util.Abort(str(e))
3832 raise util.Abort(str(e))
3829 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3833 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3830 message,
3834 message,
3831 opts.get('user') or user,
3835 opts.get('user') or user,
3832 opts.get('date') or date,
3836 opts.get('date') or date,
3833 branch, files, store,
3837 branch, files, store,
3834 editor=cmdutil.commiteditor)
3838 editor=cmdutil.commiteditor)
3835 repo.savecommitmessage(memctx.description())
3839 repo.savecommitmessage(memctx.description())
3836 n = memctx.commit()
3840 n = memctx.commit()
3837 checkexact(repo, n, nodeid)
3841 checkexact(repo, n, nodeid)
3838 finally:
3842 finally:
3839 store.close()
3843 store.close()
3840 if n:
3844 if n:
3841 # i18n: refers to a short changeset id
3845 # i18n: refers to a short changeset id
3842 msg = _('created %s') % short(n)
3846 msg = _('created %s') % short(n)
3843 return (msg, n)
3847 return (msg, n)
3844 finally:
3848 finally:
3845 os.unlink(tmpname)
3849 os.unlink(tmpname)
3846
3850
3847 try:
3851 try:
3848 try:
3852 try:
3849 wlock = repo.wlock()
3853 wlock = repo.wlock()
3850 if not opts.get('no_commit'):
3854 if not opts.get('no_commit'):
3851 lock = repo.lock()
3855 lock = repo.lock()
3852 tr = repo.transaction('import')
3856 tr = repo.transaction('import')
3853 parents = repo.parents()
3857 parents = repo.parents()
3854 for patchurl in patches:
3858 for patchurl in patches:
3855 if patchurl == '-':
3859 if patchurl == '-':
3856 ui.status(_('applying patch from stdin\n'))
3860 ui.status(_('applying patch from stdin\n'))
3857 patchfile = ui.fin
3861 patchfile = ui.fin
3858 patchurl = 'stdin' # for error message
3862 patchurl = 'stdin' # for error message
3859 else:
3863 else:
3860 patchurl = os.path.join(base, patchurl)
3864 patchurl = os.path.join(base, patchurl)
3861 ui.status(_('applying %s\n') % patchurl)
3865 ui.status(_('applying %s\n') % patchurl)
3862 patchfile = hg.openpath(ui, patchurl)
3866 patchfile = hg.openpath(ui, patchurl)
3863
3867
3864 haspatch = False
3868 haspatch = False
3865 for hunk in patch.split(patchfile):
3869 for hunk in patch.split(patchfile):
3866 (msg, node) = tryone(ui, hunk, parents)
3870 (msg, node) = tryone(ui, hunk, parents)
3867 if msg:
3871 if msg:
3868 haspatch = True
3872 haspatch = True
3869 ui.note(msg + '\n')
3873 ui.note(msg + '\n')
3870 if update or opts.get('exact'):
3874 if update or opts.get('exact'):
3871 parents = repo.parents()
3875 parents = repo.parents()
3872 else:
3876 else:
3873 parents = [repo[node]]
3877 parents = [repo[node]]
3874
3878
3875 if not haspatch:
3879 if not haspatch:
3876 raise util.Abort(_('%s: no diffs found') % patchurl)
3880 raise util.Abort(_('%s: no diffs found') % patchurl)
3877
3881
3878 if tr:
3882 if tr:
3879 tr.close()
3883 tr.close()
3880 if msgs:
3884 if msgs:
3881 repo.savecommitmessage('\n* * *\n'.join(msgs))
3885 repo.savecommitmessage('\n* * *\n'.join(msgs))
3882 except: # re-raises
3886 except: # re-raises
3883 # wlock.release() indirectly calls dirstate.write(): since
3887 # wlock.release() indirectly calls dirstate.write(): since
3884 # we're crashing, we do not want to change the working dir
3888 # we're crashing, we do not want to change the working dir
3885 # parent after all, so make sure it writes nothing
3889 # parent after all, so make sure it writes nothing
3886 repo.dirstate.invalidate()
3890 repo.dirstate.invalidate()
3887 raise
3891 raise
3888 finally:
3892 finally:
3889 if tr:
3893 if tr:
3890 tr.release()
3894 tr.release()
3891 release(lock, wlock)
3895 release(lock, wlock)
3892
3896
3893 @command('incoming|in',
3897 @command('incoming|in',
3894 [('f', 'force', None,
3898 [('f', 'force', None,
3895 _('run even if remote repository is unrelated')),
3899 _('run even if remote repository is unrelated')),
3896 ('n', 'newest-first', None, _('show newest record first')),
3900 ('n', 'newest-first', None, _('show newest record first')),
3897 ('', 'bundle', '',
3901 ('', 'bundle', '',
3898 _('file to store the bundles into'), _('FILE')),
3902 _('file to store the bundles into'), _('FILE')),
3899 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3903 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3900 ('B', 'bookmarks', False, _("compare bookmarks")),
3904 ('B', 'bookmarks', False, _("compare bookmarks")),
3901 ('b', 'branch', [],
3905 ('b', 'branch', [],
3902 _('a specific branch you would like to pull'), _('BRANCH')),
3906 _('a specific branch you would like to pull'), _('BRANCH')),
3903 ] + logopts + remoteopts + subrepoopts,
3907 ] + logopts + remoteopts + subrepoopts,
3904 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3908 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3905 def incoming(ui, repo, source="default", **opts):
3909 def incoming(ui, repo, source="default", **opts):
3906 """show new changesets found in source
3910 """show new changesets found in source
3907
3911
3908 Show new changesets found in the specified path/URL or the default
3912 Show new changesets found in the specified path/URL or the default
3909 pull location. These are the changesets that would have been pulled
3913 pull location. These are the changesets that would have been pulled
3910 if a pull at the time you issued this command.
3914 if a pull at the time you issued this command.
3911
3915
3912 For remote repository, using --bundle avoids downloading the
3916 For remote repository, using --bundle avoids downloading the
3913 changesets twice if the incoming is followed by a pull.
3917 changesets twice if the incoming is followed by a pull.
3914
3918
3915 See pull for valid source format details.
3919 See pull for valid source format details.
3916
3920
3917 Returns 0 if there are incoming changes, 1 otherwise.
3921 Returns 0 if there are incoming changes, 1 otherwise.
3918 """
3922 """
3919 if opts.get('graph'):
3923 if opts.get('graph'):
3920 cmdutil.checkunsupportedgraphflags([], opts)
3924 cmdutil.checkunsupportedgraphflags([], opts)
3921 def display(other, chlist, displayer):
3925 def display(other, chlist, displayer):
3922 revdag = cmdutil.graphrevs(other, chlist, opts)
3926 revdag = cmdutil.graphrevs(other, chlist, opts)
3923 showparents = [ctx.node() for ctx in repo[None].parents()]
3927 showparents = [ctx.node() for ctx in repo[None].parents()]
3924 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3928 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3925 graphmod.asciiedges)
3929 graphmod.asciiedges)
3926
3930
3927 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3931 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3928 return 0
3932 return 0
3929
3933
3930 if opts.get('bundle') and opts.get('subrepos'):
3934 if opts.get('bundle') and opts.get('subrepos'):
3931 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3935 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3932
3936
3933 if opts.get('bookmarks'):
3937 if opts.get('bookmarks'):
3934 source, branches = hg.parseurl(ui.expandpath(source),
3938 source, branches = hg.parseurl(ui.expandpath(source),
3935 opts.get('branch'))
3939 opts.get('branch'))
3936 other = hg.peer(repo, opts, source)
3940 other = hg.peer(repo, opts, source)
3937 if 'bookmarks' not in other.listkeys('namespaces'):
3941 if 'bookmarks' not in other.listkeys('namespaces'):
3938 ui.warn(_("remote doesn't support bookmarks\n"))
3942 ui.warn(_("remote doesn't support bookmarks\n"))
3939 return 0
3943 return 0
3940 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3944 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3941 return bookmarks.diff(ui, repo, other)
3945 return bookmarks.diff(ui, repo, other)
3942
3946
3943 repo._subtoppath = ui.expandpath(source)
3947 repo._subtoppath = ui.expandpath(source)
3944 try:
3948 try:
3945 return hg.incoming(ui, repo, source, opts)
3949 return hg.incoming(ui, repo, source, opts)
3946 finally:
3950 finally:
3947 del repo._subtoppath
3951 del repo._subtoppath
3948
3952
3949
3953
3950 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3954 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3951 def init(ui, dest=".", **opts):
3955 def init(ui, dest=".", **opts):
3952 """create a new repository in the given directory
3956 """create a new repository in the given directory
3953
3957
3954 Initialize a new repository in the given directory. If the given
3958 Initialize a new repository in the given directory. If the given
3955 directory does not exist, it will be created.
3959 directory does not exist, it will be created.
3956
3960
3957 If no directory is given, the current directory is used.
3961 If no directory is given, the current directory is used.
3958
3962
3959 It is possible to specify an ``ssh://`` URL as the destination.
3963 It is possible to specify an ``ssh://`` URL as the destination.
3960 See :hg:`help urls` for more information.
3964 See :hg:`help urls` for more information.
3961
3965
3962 Returns 0 on success.
3966 Returns 0 on success.
3963 """
3967 """
3964 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3968 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3965
3969
3966 @command('locate',
3970 @command('locate',
3967 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3971 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3968 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3972 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3969 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3973 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3970 ] + walkopts,
3974 ] + walkopts,
3971 _('[OPTION]... [PATTERN]...'))
3975 _('[OPTION]... [PATTERN]...'))
3972 def locate(ui, repo, *pats, **opts):
3976 def locate(ui, repo, *pats, **opts):
3973 """locate files matching specific patterns
3977 """locate files matching specific patterns
3974
3978
3975 Print files under Mercurial control in the working directory whose
3979 Print files under Mercurial control in the working directory whose
3976 names match the given patterns.
3980 names match the given patterns.
3977
3981
3978 By default, this command searches all directories in the working
3982 By default, this command searches all directories in the working
3979 directory. To search just the current directory and its
3983 directory. To search just the current directory and its
3980 subdirectories, use "--include .".
3984 subdirectories, use "--include .".
3981
3985
3982 If no patterns are given to match, this command prints the names
3986 If no patterns are given to match, this command prints the names
3983 of all files under Mercurial control in the working directory.
3987 of all files under Mercurial control in the working directory.
3984
3988
3985 If you want to feed the output of this command into the "xargs"
3989 If you want to feed the output of this command into the "xargs"
3986 command, use the -0 option to both this command and "xargs". This
3990 command, use the -0 option to both this command and "xargs". This
3987 will avoid the problem of "xargs" treating single filenames that
3991 will avoid the problem of "xargs" treating single filenames that
3988 contain whitespace as multiple filenames.
3992 contain whitespace as multiple filenames.
3989
3993
3990 Returns 0 if a match is found, 1 otherwise.
3994 Returns 0 if a match is found, 1 otherwise.
3991 """
3995 """
3992 end = opts.get('print0') and '\0' or '\n'
3996 end = opts.get('print0') and '\0' or '\n'
3993 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3997 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3994
3998
3995 ret = 1
3999 ret = 1
3996 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4000 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3997 m.bad = lambda x, y: False
4001 m.bad = lambda x, y: False
3998 for abs in repo[rev].walk(m):
4002 for abs in repo[rev].walk(m):
3999 if not rev and abs not in repo.dirstate:
4003 if not rev and abs not in repo.dirstate:
4000 continue
4004 continue
4001 if opts.get('fullpath'):
4005 if opts.get('fullpath'):
4002 ui.write(repo.wjoin(abs), end)
4006 ui.write(repo.wjoin(abs), end)
4003 else:
4007 else:
4004 ui.write(((pats and m.rel(abs)) or abs), end)
4008 ui.write(((pats and m.rel(abs)) or abs), end)
4005 ret = 0
4009 ret = 0
4006
4010
4007 return ret
4011 return ret
4008
4012
4009 @command('^log|history',
4013 @command('^log|history',
4010 [('f', 'follow', None,
4014 [('f', 'follow', None,
4011 _('follow changeset history, or file history across copies and renames')),
4015 _('follow changeset history, or file history across copies and renames')),
4012 ('', 'follow-first', None,
4016 ('', 'follow-first', None,
4013 _('only follow the first parent of merge changesets (DEPRECATED)')),
4017 _('only follow the first parent of merge changesets (DEPRECATED)')),
4014 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4018 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4015 ('C', 'copies', None, _('show copied files')),
4019 ('C', 'copies', None, _('show copied files')),
4016 ('k', 'keyword', [],
4020 ('k', 'keyword', [],
4017 _('do case-insensitive search for a given text'), _('TEXT')),
4021 _('do case-insensitive search for a given text'), _('TEXT')),
4018 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4022 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4019 ('', 'removed', None, _('include revisions where files were removed')),
4023 ('', 'removed', None, _('include revisions where files were removed')),
4020 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4024 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4021 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4025 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4022 ('', 'only-branch', [],
4026 ('', 'only-branch', [],
4023 _('show only changesets within the given named branch (DEPRECATED)'),
4027 _('show only changesets within the given named branch (DEPRECATED)'),
4024 _('BRANCH')),
4028 _('BRANCH')),
4025 ('b', 'branch', [],
4029 ('b', 'branch', [],
4026 _('show changesets within the given named branch'), _('BRANCH')),
4030 _('show changesets within the given named branch'), _('BRANCH')),
4027 ('P', 'prune', [],
4031 ('P', 'prune', [],
4028 _('do not display revision or any of its ancestors'), _('REV')),
4032 _('do not display revision or any of its ancestors'), _('REV')),
4029 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
4033 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
4030 ] + logopts + walkopts,
4034 ] + logopts + walkopts,
4031 _('[OPTION]... [FILE]'))
4035 _('[OPTION]... [FILE]'))
4032 def log(ui, repo, *pats, **opts):
4036 def log(ui, repo, *pats, **opts):
4033 """show revision history of entire repository or files
4037 """show revision history of entire repository or files
4034
4038
4035 Print the revision history of the specified files or the entire
4039 Print the revision history of the specified files or the entire
4036 project.
4040 project.
4037
4041
4038 If no revision range is specified, the default is ``tip:0`` unless
4042 If no revision range is specified, the default is ``tip:0`` unless
4039 --follow is set, in which case the working directory parent is
4043 --follow is set, in which case the working directory parent is
4040 used as the starting revision.
4044 used as the starting revision.
4041
4045
4042 File history is shown without following rename or copy history of
4046 File history is shown without following rename or copy history of
4043 files. Use -f/--follow with a filename to follow history across
4047 files. Use -f/--follow with a filename to follow history across
4044 renames and copies. --follow without a filename will only show
4048 renames and copies. --follow without a filename will only show
4045 ancestors or descendants of the starting revision.
4049 ancestors or descendants of the starting revision.
4046
4050
4047 By default this command prints revision number and changeset id,
4051 By default this command prints revision number and changeset id,
4048 tags, non-trivial parents, user, date and time, and a summary for
4052 tags, non-trivial parents, user, date and time, and a summary for
4049 each commit. When the -v/--verbose switch is used, the list of
4053 each commit. When the -v/--verbose switch is used, the list of
4050 changed files and full commit message are shown.
4054 changed files and full commit message are shown.
4051
4055
4052 .. note::
4056 .. note::
4053 log -p/--patch may generate unexpected diff output for merge
4057 log -p/--patch may generate unexpected diff output for merge
4054 changesets, as it will only compare the merge changeset against
4058 changesets, as it will only compare the merge changeset against
4055 its first parent. Also, only files different from BOTH parents
4059 its first parent. Also, only files different from BOTH parents
4056 will appear in files:.
4060 will appear in files:.
4057
4061
4058 .. note::
4062 .. note::
4059 for performance reasons, log FILE may omit duplicate changes
4063 for performance reasons, log FILE may omit duplicate changes
4060 made on branches and will not show deletions. To see all
4064 made on branches and will not show deletions. To see all
4061 changes including duplicates and deletions, use the --removed
4065 changes including duplicates and deletions, use the --removed
4062 switch.
4066 switch.
4063
4067
4064 .. container:: verbose
4068 .. container:: verbose
4065
4069
4066 Some examples:
4070 Some examples:
4067
4071
4068 - changesets with full descriptions and file lists::
4072 - changesets with full descriptions and file lists::
4069
4073
4070 hg log -v
4074 hg log -v
4071
4075
4072 - changesets ancestral to the working directory::
4076 - changesets ancestral to the working directory::
4073
4077
4074 hg log -f
4078 hg log -f
4075
4079
4076 - last 10 commits on the current branch::
4080 - last 10 commits on the current branch::
4077
4081
4078 hg log -l 10 -b .
4082 hg log -l 10 -b .
4079
4083
4080 - changesets showing all modifications of a file, including removals::
4084 - changesets showing all modifications of a file, including removals::
4081
4085
4082 hg log --removed file.c
4086 hg log --removed file.c
4083
4087
4084 - all changesets that touch a directory, with diffs, excluding merges::
4088 - all changesets that touch a directory, with diffs, excluding merges::
4085
4089
4086 hg log -Mp lib/
4090 hg log -Mp lib/
4087
4091
4088 - all revision numbers that match a keyword::
4092 - all revision numbers that match a keyword::
4089
4093
4090 hg log -k bug --template "{rev}\\n"
4094 hg log -k bug --template "{rev}\\n"
4091
4095
4092 - check if a given changeset is included is a tagged release::
4096 - check if a given changeset is included is a tagged release::
4093
4097
4094 hg log -r "a21ccf and ancestor(1.9)"
4098 hg log -r "a21ccf and ancestor(1.9)"
4095
4099
4096 - find all changesets by some user in a date range::
4100 - find all changesets by some user in a date range::
4097
4101
4098 hg log -k alice -d "may 2008 to jul 2008"
4102 hg log -k alice -d "may 2008 to jul 2008"
4099
4103
4100 - summary of all changesets after the last tag::
4104 - summary of all changesets after the last tag::
4101
4105
4102 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4106 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4103
4107
4104 See :hg:`help dates` for a list of formats valid for -d/--date.
4108 See :hg:`help dates` for a list of formats valid for -d/--date.
4105
4109
4106 See :hg:`help revisions` and :hg:`help revsets` for more about
4110 See :hg:`help revisions` and :hg:`help revsets` for more about
4107 specifying revisions.
4111 specifying revisions.
4108
4112
4109 See :hg:`help templates` for more about pre-packaged styles and
4113 See :hg:`help templates` for more about pre-packaged styles and
4110 specifying custom templates.
4114 specifying custom templates.
4111
4115
4112 Returns 0 on success.
4116 Returns 0 on success.
4113 """
4117 """
4114 if opts.get('graph'):
4118 if opts.get('graph'):
4115 return cmdutil.graphlog(ui, repo, *pats, **opts)
4119 return cmdutil.graphlog(ui, repo, *pats, **opts)
4116
4120
4117 matchfn = scmutil.match(repo[None], pats, opts)
4121 matchfn = scmutil.match(repo[None], pats, opts)
4118 limit = cmdutil.loglimit(opts)
4122 limit = cmdutil.loglimit(opts)
4119 count = 0
4123 count = 0
4120
4124
4121 getrenamed, endrev = None, None
4125 getrenamed, endrev = None, None
4122 if opts.get('copies'):
4126 if opts.get('copies'):
4123 if opts.get('rev'):
4127 if opts.get('rev'):
4124 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4128 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4125 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4129 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4126
4130
4127 df = False
4131 df = False
4128 if opts.get("date"):
4132 if opts.get("date"):
4129 df = util.matchdate(opts["date"])
4133 df = util.matchdate(opts["date"])
4130
4134
4131 branches = opts.get('branch', []) + opts.get('only_branch', [])
4135 branches = opts.get('branch', []) + opts.get('only_branch', [])
4132 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4136 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4133
4137
4134 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4138 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4135 def prep(ctx, fns):
4139 def prep(ctx, fns):
4136 rev = ctx.rev()
4140 rev = ctx.rev()
4137 parents = [p for p in repo.changelog.parentrevs(rev)
4141 parents = [p for p in repo.changelog.parentrevs(rev)
4138 if p != nullrev]
4142 if p != nullrev]
4139 if opts.get('no_merges') and len(parents) == 2:
4143 if opts.get('no_merges') and len(parents) == 2:
4140 return
4144 return
4141 if opts.get('only_merges') and len(parents) != 2:
4145 if opts.get('only_merges') and len(parents) != 2:
4142 return
4146 return
4143 if opts.get('branch') and ctx.branch() not in opts['branch']:
4147 if opts.get('branch') and ctx.branch() not in opts['branch']:
4144 return
4148 return
4145 if not opts.get('hidden') and ctx.hidden():
4149 if not opts.get('hidden') and ctx.hidden():
4146 return
4150 return
4147 if df and not df(ctx.date()[0]):
4151 if df and not df(ctx.date()[0]):
4148 return
4152 return
4149
4153
4150 lower = encoding.lower
4154 lower = encoding.lower
4151 if opts.get('user'):
4155 if opts.get('user'):
4152 luser = lower(ctx.user())
4156 luser = lower(ctx.user())
4153 for k in [lower(x) for x in opts['user']]:
4157 for k in [lower(x) for x in opts['user']]:
4154 if (k in luser):
4158 if (k in luser):
4155 break
4159 break
4156 else:
4160 else:
4157 return
4161 return
4158 if opts.get('keyword'):
4162 if opts.get('keyword'):
4159 luser = lower(ctx.user())
4163 luser = lower(ctx.user())
4160 ldesc = lower(ctx.description())
4164 ldesc = lower(ctx.description())
4161 lfiles = lower(" ".join(ctx.files()))
4165 lfiles = lower(" ".join(ctx.files()))
4162 for k in [lower(x) for x in opts['keyword']]:
4166 for k in [lower(x) for x in opts['keyword']]:
4163 if (k in luser or k in ldesc or k in lfiles):
4167 if (k in luser or k in ldesc or k in lfiles):
4164 break
4168 break
4165 else:
4169 else:
4166 return
4170 return
4167
4171
4168 copies = None
4172 copies = None
4169 if getrenamed is not None and rev:
4173 if getrenamed is not None and rev:
4170 copies = []
4174 copies = []
4171 for fn in ctx.files():
4175 for fn in ctx.files():
4172 rename = getrenamed(fn, rev)
4176 rename = getrenamed(fn, rev)
4173 if rename:
4177 if rename:
4174 copies.append((fn, rename[0]))
4178 copies.append((fn, rename[0]))
4175
4179
4176 revmatchfn = None
4180 revmatchfn = None
4177 if opts.get('patch') or opts.get('stat'):
4181 if opts.get('patch') or opts.get('stat'):
4178 if opts.get('follow') or opts.get('follow_first'):
4182 if opts.get('follow') or opts.get('follow_first'):
4179 # note: this might be wrong when following through merges
4183 # note: this might be wrong when following through merges
4180 revmatchfn = scmutil.match(repo[None], fns, default='path')
4184 revmatchfn = scmutil.match(repo[None], fns, default='path')
4181 else:
4185 else:
4182 revmatchfn = matchfn
4186 revmatchfn = matchfn
4183
4187
4184 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4188 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4185
4189
4186 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4190 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4187 if count == limit:
4191 if count == limit:
4188 break
4192 break
4189 if displayer.flush(ctx.rev()):
4193 if displayer.flush(ctx.rev()):
4190 count += 1
4194 count += 1
4191 displayer.close()
4195 displayer.close()
4192
4196
4193 @command('manifest',
4197 @command('manifest',
4194 [('r', 'rev', '', _('revision to display'), _('REV')),
4198 [('r', 'rev', '', _('revision to display'), _('REV')),
4195 ('', 'all', False, _("list files from all revisions"))],
4199 ('', 'all', False, _("list files from all revisions"))],
4196 _('[-r REV]'))
4200 _('[-r REV]'))
4197 def manifest(ui, repo, node=None, rev=None, **opts):
4201 def manifest(ui, repo, node=None, rev=None, **opts):
4198 """output the current or given revision of the project manifest
4202 """output the current or given revision of the project manifest
4199
4203
4200 Print a list of version controlled files for the given revision.
4204 Print a list of version controlled files for the given revision.
4201 If no revision is given, the first parent of the working directory
4205 If no revision is given, the first parent of the working directory
4202 is used, or the null revision if no revision is checked out.
4206 is used, or the null revision if no revision is checked out.
4203
4207
4204 With -v, print file permissions, symlink and executable bits.
4208 With -v, print file permissions, symlink and executable bits.
4205 With --debug, print file revision hashes.
4209 With --debug, print file revision hashes.
4206
4210
4207 If option --all is specified, the list of all files from all revisions
4211 If option --all is specified, the list of all files from all revisions
4208 is printed. This includes deleted and renamed files.
4212 is printed. This includes deleted and renamed files.
4209
4213
4210 Returns 0 on success.
4214 Returns 0 on success.
4211 """
4215 """
4212
4216
4213 fm = ui.formatter('manifest', opts)
4217 fm = ui.formatter('manifest', opts)
4214
4218
4215 if opts.get('all'):
4219 if opts.get('all'):
4216 if rev or node:
4220 if rev or node:
4217 raise util.Abort(_("can't specify a revision with --all"))
4221 raise util.Abort(_("can't specify a revision with --all"))
4218
4222
4219 res = []
4223 res = []
4220 prefix = "data/"
4224 prefix = "data/"
4221 suffix = ".i"
4225 suffix = ".i"
4222 plen = len(prefix)
4226 plen = len(prefix)
4223 slen = len(suffix)
4227 slen = len(suffix)
4224 lock = repo.lock()
4228 lock = repo.lock()
4225 try:
4229 try:
4226 for fn, b, size in repo.store.datafiles():
4230 for fn, b, size in repo.store.datafiles():
4227 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4231 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4228 res.append(fn[plen:-slen])
4232 res.append(fn[plen:-slen])
4229 finally:
4233 finally:
4230 lock.release()
4234 lock.release()
4231 for f in res:
4235 for f in res:
4232 fm.startitem()
4236 fm.startitem()
4233 fm.write("path", '%s\n', f)
4237 fm.write("path", '%s\n', f)
4234 fm.end()
4238 fm.end()
4235 return
4239 return
4236
4240
4237 if rev and node:
4241 if rev and node:
4238 raise util.Abort(_("please specify just one revision"))
4242 raise util.Abort(_("please specify just one revision"))
4239
4243
4240 if not node:
4244 if not node:
4241 node = rev
4245 node = rev
4242
4246
4243 char = {'l': '@', 'x': '*', '': ''}
4247 char = {'l': '@', 'x': '*', '': ''}
4244 mode = {'l': '644', 'x': '755', '': '644'}
4248 mode = {'l': '644', 'x': '755', '': '644'}
4245 ctx = scmutil.revsingle(repo, node)
4249 ctx = scmutil.revsingle(repo, node)
4246 mf = ctx.manifest()
4250 mf = ctx.manifest()
4247 for f in ctx:
4251 for f in ctx:
4248 fm.startitem()
4252 fm.startitem()
4249 fl = ctx[f].flags()
4253 fl = ctx[f].flags()
4250 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4254 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4251 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4255 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4252 fm.write('path', '%s\n', f)
4256 fm.write('path', '%s\n', f)
4253 fm.end()
4257 fm.end()
4254
4258
4255 @command('^merge',
4259 @command('^merge',
4256 [('f', 'force', None, _('force a merge with outstanding changes')),
4260 [('f', 'force', None, _('force a merge with outstanding changes')),
4257 ('r', 'rev', '', _('revision to merge'), _('REV')),
4261 ('r', 'rev', '', _('revision to merge'), _('REV')),
4258 ('P', 'preview', None,
4262 ('P', 'preview', None,
4259 _('review revisions to merge (no merge is performed)'))
4263 _('review revisions to merge (no merge is performed)'))
4260 ] + mergetoolopts,
4264 ] + mergetoolopts,
4261 _('[-P] [-f] [[-r] REV]'))
4265 _('[-P] [-f] [[-r] REV]'))
4262 def merge(ui, repo, node=None, **opts):
4266 def merge(ui, repo, node=None, **opts):
4263 """merge working directory with another revision
4267 """merge working directory with another revision
4264
4268
4265 The current working directory is updated with all changes made in
4269 The current working directory is updated with all changes made in
4266 the requested revision since the last common predecessor revision.
4270 the requested revision since the last common predecessor revision.
4267
4271
4268 Files that changed between either parent are marked as changed for
4272 Files that changed between either parent are marked as changed for
4269 the next commit and a commit must be performed before any further
4273 the next commit and a commit must be performed before any further
4270 updates to the repository are allowed. The next commit will have
4274 updates to the repository are allowed. The next commit will have
4271 two parents.
4275 two parents.
4272
4276
4273 ``--tool`` can be used to specify the merge tool used for file
4277 ``--tool`` can be used to specify the merge tool used for file
4274 merges. It overrides the HGMERGE environment variable and your
4278 merges. It overrides the HGMERGE environment variable and your
4275 configuration files. See :hg:`help merge-tools` for options.
4279 configuration files. See :hg:`help merge-tools` for options.
4276
4280
4277 If no revision is specified, the working directory's parent is a
4281 If no revision is specified, the working directory's parent is a
4278 head revision, and the current branch contains exactly one other
4282 head revision, and the current branch contains exactly one other
4279 head, the other head is merged with by default. Otherwise, an
4283 head, the other head is merged with by default. Otherwise, an
4280 explicit revision with which to merge with must be provided.
4284 explicit revision with which to merge with must be provided.
4281
4285
4282 :hg:`resolve` must be used to resolve unresolved files.
4286 :hg:`resolve` must be used to resolve unresolved files.
4283
4287
4284 To undo an uncommitted merge, use :hg:`update --clean .` which
4288 To undo an uncommitted merge, use :hg:`update --clean .` which
4285 will check out a clean copy of the original merge parent, losing
4289 will check out a clean copy of the original merge parent, losing
4286 all changes.
4290 all changes.
4287
4291
4288 Returns 0 on success, 1 if there are unresolved files.
4292 Returns 0 on success, 1 if there are unresolved files.
4289 """
4293 """
4290
4294
4291 if opts.get('rev') and node:
4295 if opts.get('rev') and node:
4292 raise util.Abort(_("please specify just one revision"))
4296 raise util.Abort(_("please specify just one revision"))
4293 if not node:
4297 if not node:
4294 node = opts.get('rev')
4298 node = opts.get('rev')
4295
4299
4296 if node:
4300 if node:
4297 node = scmutil.revsingle(repo, node).node()
4301 node = scmutil.revsingle(repo, node).node()
4298
4302
4299 if not node and repo._bookmarkcurrent:
4303 if not node and repo._bookmarkcurrent:
4300 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4304 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4301 curhead = repo[repo._bookmarkcurrent]
4305 curhead = repo[repo._bookmarkcurrent]
4302 if len(bmheads) == 2:
4306 if len(bmheads) == 2:
4303 if curhead == bmheads[0]:
4307 if curhead == bmheads[0]:
4304 node = bmheads[1]
4308 node = bmheads[1]
4305 else:
4309 else:
4306 node = bmheads[0]
4310 node = bmheads[0]
4307 elif len(bmheads) > 2:
4311 elif len(bmheads) > 2:
4308 raise util.Abort(_("multiple matching bookmarks to merge - "
4312 raise util.Abort(_("multiple matching bookmarks to merge - "
4309 "please merge with an explicit rev or bookmark"),
4313 "please merge with an explicit rev or bookmark"),
4310 hint=_("run 'hg heads' to see all heads"))
4314 hint=_("run 'hg heads' to see all heads"))
4311 elif len(bmheads) <= 1:
4315 elif len(bmheads) <= 1:
4312 raise util.Abort(_("no matching bookmark to merge - "
4316 raise util.Abort(_("no matching bookmark to merge - "
4313 "please merge with an explicit rev or bookmark"),
4317 "please merge with an explicit rev or bookmark"),
4314 hint=_("run 'hg heads' to see all heads"))
4318 hint=_("run 'hg heads' to see all heads"))
4315
4319
4316 if not node and not repo._bookmarkcurrent:
4320 if not node and not repo._bookmarkcurrent:
4317 branch = repo[None].branch()
4321 branch = repo[None].branch()
4318 bheads = repo.branchheads(branch)
4322 bheads = repo.branchheads(branch)
4319 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4323 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4320
4324
4321 if len(nbhs) > 2:
4325 if len(nbhs) > 2:
4322 raise util.Abort(_("branch '%s' has %d heads - "
4326 raise util.Abort(_("branch '%s' has %d heads - "
4323 "please merge with an explicit rev")
4327 "please merge with an explicit rev")
4324 % (branch, len(bheads)),
4328 % (branch, len(bheads)),
4325 hint=_("run 'hg heads .' to see heads"))
4329 hint=_("run 'hg heads .' to see heads"))
4326
4330
4327 parent = repo.dirstate.p1()
4331 parent = repo.dirstate.p1()
4328 if len(nbhs) <= 1:
4332 if len(nbhs) <= 1:
4329 if len(bheads) > 1:
4333 if len(bheads) > 1:
4330 raise util.Abort(_("heads are bookmarked - "
4334 raise util.Abort(_("heads are bookmarked - "
4331 "please merge with an explicit rev"),
4335 "please merge with an explicit rev"),
4332 hint=_("run 'hg heads' to see all heads"))
4336 hint=_("run 'hg heads' to see all heads"))
4333 if len(repo.heads()) > 1:
4337 if len(repo.heads()) > 1:
4334 raise util.Abort(_("branch '%s' has one head - "
4338 raise util.Abort(_("branch '%s' has one head - "
4335 "please merge with an explicit rev")
4339 "please merge with an explicit rev")
4336 % branch,
4340 % branch,
4337 hint=_("run 'hg heads' to see all heads"))
4341 hint=_("run 'hg heads' to see all heads"))
4338 msg, hint = _('nothing to merge'), None
4342 msg, hint = _('nothing to merge'), None
4339 if parent != repo.lookup(branch):
4343 if parent != repo.lookup(branch):
4340 hint = _("use 'hg update' instead")
4344 hint = _("use 'hg update' instead")
4341 raise util.Abort(msg, hint=hint)
4345 raise util.Abort(msg, hint=hint)
4342
4346
4343 if parent not in bheads:
4347 if parent not in bheads:
4344 raise util.Abort(_('working directory not at a head revision'),
4348 raise util.Abort(_('working directory not at a head revision'),
4345 hint=_("use 'hg update' or merge with an "
4349 hint=_("use 'hg update' or merge with an "
4346 "explicit revision"))
4350 "explicit revision"))
4347 if parent == nbhs[0]:
4351 if parent == nbhs[0]:
4348 node = nbhs[-1]
4352 node = nbhs[-1]
4349 else:
4353 else:
4350 node = nbhs[0]
4354 node = nbhs[0]
4351
4355
4352 if opts.get('preview'):
4356 if opts.get('preview'):
4353 # find nodes that are ancestors of p2 but not of p1
4357 # find nodes that are ancestors of p2 but not of p1
4354 p1 = repo.lookup('.')
4358 p1 = repo.lookup('.')
4355 p2 = repo.lookup(node)
4359 p2 = repo.lookup(node)
4356 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4360 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4357
4361
4358 displayer = cmdutil.show_changeset(ui, repo, opts)
4362 displayer = cmdutil.show_changeset(ui, repo, opts)
4359 for node in nodes:
4363 for node in nodes:
4360 displayer.show(repo[node])
4364 displayer.show(repo[node])
4361 displayer.close()
4365 displayer.close()
4362 return 0
4366 return 0
4363
4367
4364 try:
4368 try:
4365 # ui.forcemerge is an internal variable, do not document
4369 # ui.forcemerge is an internal variable, do not document
4366 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4370 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4367 return hg.merge(repo, node, force=opts.get('force'))
4371 return hg.merge(repo, node, force=opts.get('force'))
4368 finally:
4372 finally:
4369 ui.setconfig('ui', 'forcemerge', '')
4373 ui.setconfig('ui', 'forcemerge', '')
4370
4374
4371 @command('outgoing|out',
4375 @command('outgoing|out',
4372 [('f', 'force', None, _('run even when the destination is unrelated')),
4376 [('f', 'force', None, _('run even when the destination is unrelated')),
4373 ('r', 'rev', [],
4377 ('r', 'rev', [],
4374 _('a changeset intended to be included in the destination'), _('REV')),
4378 _('a changeset intended to be included in the destination'), _('REV')),
4375 ('n', 'newest-first', None, _('show newest record first')),
4379 ('n', 'newest-first', None, _('show newest record first')),
4376 ('B', 'bookmarks', False, _('compare bookmarks')),
4380 ('B', 'bookmarks', False, _('compare bookmarks')),
4377 ('b', 'branch', [], _('a specific branch you would like to push'),
4381 ('b', 'branch', [], _('a specific branch you would like to push'),
4378 _('BRANCH')),
4382 _('BRANCH')),
4379 ] + logopts + remoteopts + subrepoopts,
4383 ] + logopts + remoteopts + subrepoopts,
4380 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4384 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4381 def outgoing(ui, repo, dest=None, **opts):
4385 def outgoing(ui, repo, dest=None, **opts):
4382 """show changesets not found in the destination
4386 """show changesets not found in the destination
4383
4387
4384 Show changesets not found in the specified destination repository
4388 Show changesets not found in the specified destination repository
4385 or the default push location. These are the changesets that would
4389 or the default push location. These are the changesets that would
4386 be pushed if a push was requested.
4390 be pushed if a push was requested.
4387
4391
4388 See pull for details of valid destination formats.
4392 See pull for details of valid destination formats.
4389
4393
4390 Returns 0 if there are outgoing changes, 1 otherwise.
4394 Returns 0 if there are outgoing changes, 1 otherwise.
4391 """
4395 """
4392 if opts.get('graph'):
4396 if opts.get('graph'):
4393 cmdutil.checkunsupportedgraphflags([], opts)
4397 cmdutil.checkunsupportedgraphflags([], opts)
4394 o = hg._outgoing(ui, repo, dest, opts)
4398 o = hg._outgoing(ui, repo, dest, opts)
4395 if o is None:
4399 if o is None:
4396 return
4400 return
4397
4401
4398 revdag = cmdutil.graphrevs(repo, o, opts)
4402 revdag = cmdutil.graphrevs(repo, o, opts)
4399 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4403 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4400 showparents = [ctx.node() for ctx in repo[None].parents()]
4404 showparents = [ctx.node() for ctx in repo[None].parents()]
4401 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4405 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4402 graphmod.asciiedges)
4406 graphmod.asciiedges)
4403 return 0
4407 return 0
4404
4408
4405 if opts.get('bookmarks'):
4409 if opts.get('bookmarks'):
4406 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4410 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4407 dest, branches = hg.parseurl(dest, opts.get('branch'))
4411 dest, branches = hg.parseurl(dest, opts.get('branch'))
4408 other = hg.peer(repo, opts, dest)
4412 other = hg.peer(repo, opts, dest)
4409 if 'bookmarks' not in other.listkeys('namespaces'):
4413 if 'bookmarks' not in other.listkeys('namespaces'):
4410 ui.warn(_("remote doesn't support bookmarks\n"))
4414 ui.warn(_("remote doesn't support bookmarks\n"))
4411 return 0
4415 return 0
4412 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4416 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4413 return bookmarks.diff(ui, other, repo)
4417 return bookmarks.diff(ui, other, repo)
4414
4418
4415 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4419 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4416 try:
4420 try:
4417 return hg.outgoing(ui, repo, dest, opts)
4421 return hg.outgoing(ui, repo, dest, opts)
4418 finally:
4422 finally:
4419 del repo._subtoppath
4423 del repo._subtoppath
4420
4424
4421 @command('parents',
4425 @command('parents',
4422 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4426 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4423 ] + templateopts,
4427 ] + templateopts,
4424 _('[-r REV] [FILE]'))
4428 _('[-r REV] [FILE]'))
4425 def parents(ui, repo, file_=None, **opts):
4429 def parents(ui, repo, file_=None, **opts):
4426 """show the parents of the working directory or revision
4430 """show the parents of the working directory or revision
4427
4431
4428 Print the working directory's parent revisions. If a revision is
4432 Print the working directory's parent revisions. If a revision is
4429 given via -r/--rev, the parent of that revision will be printed.
4433 given via -r/--rev, the parent of that revision will be printed.
4430 If a file argument is given, the revision in which the file was
4434 If a file argument is given, the revision in which the file was
4431 last changed (before the working directory revision or the
4435 last changed (before the working directory revision or the
4432 argument to --rev if given) is printed.
4436 argument to --rev if given) is printed.
4433
4437
4434 Returns 0 on success.
4438 Returns 0 on success.
4435 """
4439 """
4436
4440
4437 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4441 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4438
4442
4439 if file_:
4443 if file_:
4440 m = scmutil.match(ctx, (file_,), opts)
4444 m = scmutil.match(ctx, (file_,), opts)
4441 if m.anypats() or len(m.files()) != 1:
4445 if m.anypats() or len(m.files()) != 1:
4442 raise util.Abort(_('can only specify an explicit filename'))
4446 raise util.Abort(_('can only specify an explicit filename'))
4443 file_ = m.files()[0]
4447 file_ = m.files()[0]
4444 filenodes = []
4448 filenodes = []
4445 for cp in ctx.parents():
4449 for cp in ctx.parents():
4446 if not cp:
4450 if not cp:
4447 continue
4451 continue
4448 try:
4452 try:
4449 filenodes.append(cp.filenode(file_))
4453 filenodes.append(cp.filenode(file_))
4450 except error.LookupError:
4454 except error.LookupError:
4451 pass
4455 pass
4452 if not filenodes:
4456 if not filenodes:
4453 raise util.Abort(_("'%s' not found in manifest!") % file_)
4457 raise util.Abort(_("'%s' not found in manifest!") % file_)
4454 fl = repo.file(file_)
4458 fl = repo.file(file_)
4455 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4459 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4456 else:
4460 else:
4457 p = [cp.node() for cp in ctx.parents()]
4461 p = [cp.node() for cp in ctx.parents()]
4458
4462
4459 displayer = cmdutil.show_changeset(ui, repo, opts)
4463 displayer = cmdutil.show_changeset(ui, repo, opts)
4460 for n in p:
4464 for n in p:
4461 if n != nullid:
4465 if n != nullid:
4462 displayer.show(repo[n])
4466 displayer.show(repo[n])
4463 displayer.close()
4467 displayer.close()
4464
4468
4465 @command('paths', [], _('[NAME]'))
4469 @command('paths', [], _('[NAME]'))
4466 def paths(ui, repo, search=None):
4470 def paths(ui, repo, search=None):
4467 """show aliases for remote repositories
4471 """show aliases for remote repositories
4468
4472
4469 Show definition of symbolic path name NAME. If no name is given,
4473 Show definition of symbolic path name NAME. If no name is given,
4470 show definition of all available names.
4474 show definition of all available names.
4471
4475
4472 Option -q/--quiet suppresses all output when searching for NAME
4476 Option -q/--quiet suppresses all output when searching for NAME
4473 and shows only the path names when listing all definitions.
4477 and shows only the path names when listing all definitions.
4474
4478
4475 Path names are defined in the [paths] section of your
4479 Path names are defined in the [paths] section of your
4476 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4480 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4477 repository, ``.hg/hgrc`` is used, too.
4481 repository, ``.hg/hgrc`` is used, too.
4478
4482
4479 The path names ``default`` and ``default-push`` have a special
4483 The path names ``default`` and ``default-push`` have a special
4480 meaning. When performing a push or pull operation, they are used
4484 meaning. When performing a push or pull operation, they are used
4481 as fallbacks if no location is specified on the command-line.
4485 as fallbacks if no location is specified on the command-line.
4482 When ``default-push`` is set, it will be used for push and
4486 When ``default-push`` is set, it will be used for push and
4483 ``default`` will be used for pull; otherwise ``default`` is used
4487 ``default`` will be used for pull; otherwise ``default`` is used
4484 as the fallback for both. When cloning a repository, the clone
4488 as the fallback for both. When cloning a repository, the clone
4485 source is written as ``default`` in ``.hg/hgrc``. Note that
4489 source is written as ``default`` in ``.hg/hgrc``. Note that
4486 ``default`` and ``default-push`` apply to all inbound (e.g.
4490 ``default`` and ``default-push`` apply to all inbound (e.g.
4487 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4491 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4488 :hg:`bundle`) operations.
4492 :hg:`bundle`) operations.
4489
4493
4490 See :hg:`help urls` for more information.
4494 See :hg:`help urls` for more information.
4491
4495
4492 Returns 0 on success.
4496 Returns 0 on success.
4493 """
4497 """
4494 if search:
4498 if search:
4495 for name, path in ui.configitems("paths"):
4499 for name, path in ui.configitems("paths"):
4496 if name == search:
4500 if name == search:
4497 ui.status("%s\n" % util.hidepassword(path))
4501 ui.status("%s\n" % util.hidepassword(path))
4498 return
4502 return
4499 if not ui.quiet:
4503 if not ui.quiet:
4500 ui.warn(_("not found!\n"))
4504 ui.warn(_("not found!\n"))
4501 return 1
4505 return 1
4502 else:
4506 else:
4503 for name, path in ui.configitems("paths"):
4507 for name, path in ui.configitems("paths"):
4504 if ui.quiet:
4508 if ui.quiet:
4505 ui.write("%s\n" % name)
4509 ui.write("%s\n" % name)
4506 else:
4510 else:
4507 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4511 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4508
4512
4509 @command('^phase',
4513 @command('^phase',
4510 [('p', 'public', False, _('set changeset phase to public')),
4514 [('p', 'public', False, _('set changeset phase to public')),
4511 ('d', 'draft', False, _('set changeset phase to draft')),
4515 ('d', 'draft', False, _('set changeset phase to draft')),
4512 ('s', 'secret', False, _('set changeset phase to secret')),
4516 ('s', 'secret', False, _('set changeset phase to secret')),
4513 ('f', 'force', False, _('allow to move boundary backward')),
4517 ('f', 'force', False, _('allow to move boundary backward')),
4514 ('r', 'rev', [], _('target revision'), _('REV')),
4518 ('r', 'rev', [], _('target revision'), _('REV')),
4515 ],
4519 ],
4516 _('[-p|-d|-s] [-f] [-r] REV...'))
4520 _('[-p|-d|-s] [-f] [-r] REV...'))
4517 def phase(ui, repo, *revs, **opts):
4521 def phase(ui, repo, *revs, **opts):
4518 """set or show the current phase name
4522 """set or show the current phase name
4519
4523
4520 With no argument, show the phase name of specified revisions.
4524 With no argument, show the phase name of specified revisions.
4521
4525
4522 With one of -p/--public, -d/--draft or -s/--secret, change the
4526 With one of -p/--public, -d/--draft or -s/--secret, change the
4523 phase value of the specified revisions.
4527 phase value of the specified revisions.
4524
4528
4525 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4529 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4526 lower phase to an higher phase. Phases are ordered as follows::
4530 lower phase to an higher phase. Phases are ordered as follows::
4527
4531
4528 public < draft < secret
4532 public < draft < secret
4529
4533
4530 Return 0 on success, 1 if no phases were changed or some could not
4534 Return 0 on success, 1 if no phases were changed or some could not
4531 be changed.
4535 be changed.
4532 """
4536 """
4533 # search for a unique phase argument
4537 # search for a unique phase argument
4534 targetphase = None
4538 targetphase = None
4535 for idx, name in enumerate(phases.phasenames):
4539 for idx, name in enumerate(phases.phasenames):
4536 if opts[name]:
4540 if opts[name]:
4537 if targetphase is not None:
4541 if targetphase is not None:
4538 raise util.Abort(_('only one phase can be specified'))
4542 raise util.Abort(_('only one phase can be specified'))
4539 targetphase = idx
4543 targetphase = idx
4540
4544
4541 # look for specified revision
4545 # look for specified revision
4542 revs = list(revs)
4546 revs = list(revs)
4543 revs.extend(opts['rev'])
4547 revs.extend(opts['rev'])
4544 if not revs:
4548 if not revs:
4545 raise util.Abort(_('no revisions specified'))
4549 raise util.Abort(_('no revisions specified'))
4546
4550
4547 revs = scmutil.revrange(repo, revs)
4551 revs = scmutil.revrange(repo, revs)
4548
4552
4549 lock = None
4553 lock = None
4550 ret = 0
4554 ret = 0
4551 if targetphase is None:
4555 if targetphase is None:
4552 # display
4556 # display
4553 for r in revs:
4557 for r in revs:
4554 ctx = repo[r]
4558 ctx = repo[r]
4555 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4559 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4556 else:
4560 else:
4557 lock = repo.lock()
4561 lock = repo.lock()
4558 try:
4562 try:
4559 # set phase
4563 # set phase
4560 if not revs:
4564 if not revs:
4561 raise util.Abort(_('empty revision set'))
4565 raise util.Abort(_('empty revision set'))
4562 nodes = [repo[r].node() for r in revs]
4566 nodes = [repo[r].node() for r in revs]
4563 olddata = repo._phasecache.getphaserevs(repo)[:]
4567 olddata = repo._phasecache.getphaserevs(repo)[:]
4564 phases.advanceboundary(repo, targetphase, nodes)
4568 phases.advanceboundary(repo, targetphase, nodes)
4565 if opts['force']:
4569 if opts['force']:
4566 phases.retractboundary(repo, targetphase, nodes)
4570 phases.retractboundary(repo, targetphase, nodes)
4567 finally:
4571 finally:
4568 lock.release()
4572 lock.release()
4569 newdata = repo._phasecache.getphaserevs(repo)
4573 newdata = repo._phasecache.getphaserevs(repo)
4570 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4574 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4571 rejected = [n for n in nodes
4575 rejected = [n for n in nodes
4572 if newdata[repo[n].rev()] < targetphase]
4576 if newdata[repo[n].rev()] < targetphase]
4573 if rejected:
4577 if rejected:
4574 ui.warn(_('cannot move %i changesets to a more permissive '
4578 ui.warn(_('cannot move %i changesets to a more permissive '
4575 'phase, use --force\n') % len(rejected))
4579 'phase, use --force\n') % len(rejected))
4576 ret = 1
4580 ret = 1
4577 if changes:
4581 if changes:
4578 msg = _('phase changed for %i changesets\n') % changes
4582 msg = _('phase changed for %i changesets\n') % changes
4579 if ret:
4583 if ret:
4580 ui.status(msg)
4584 ui.status(msg)
4581 else:
4585 else:
4582 ui.note(msg)
4586 ui.note(msg)
4583 else:
4587 else:
4584 ui.warn(_('no phases changed\n'))
4588 ui.warn(_('no phases changed\n'))
4585 ret = 1
4589 ret = 1
4586 return ret
4590 return ret
4587
4591
4588 def postincoming(ui, repo, modheads, optupdate, checkout):
4592 def postincoming(ui, repo, modheads, optupdate, checkout):
4589 if modheads == 0:
4593 if modheads == 0:
4590 return
4594 return
4591 if optupdate:
4595 if optupdate:
4592 movemarkfrom = repo['.'].node()
4596 movemarkfrom = repo['.'].node()
4593 try:
4597 try:
4594 ret = hg.update(repo, checkout)
4598 ret = hg.update(repo, checkout)
4595 except util.Abort, inst:
4599 except util.Abort, inst:
4596 ui.warn(_("not updating: %s\n") % str(inst))
4600 ui.warn(_("not updating: %s\n") % str(inst))
4597 return 0
4601 return 0
4598 if not ret and not checkout:
4602 if not ret and not checkout:
4599 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4603 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4600 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4604 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4601 return ret
4605 return ret
4602 if modheads > 1:
4606 if modheads > 1:
4603 currentbranchheads = len(repo.branchheads())
4607 currentbranchheads = len(repo.branchheads())
4604 if currentbranchheads == modheads:
4608 if currentbranchheads == modheads:
4605 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4609 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4606 elif currentbranchheads > 1:
4610 elif currentbranchheads > 1:
4607 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4611 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4608 "merge)\n"))
4612 "merge)\n"))
4609 else:
4613 else:
4610 ui.status(_("(run 'hg heads' to see heads)\n"))
4614 ui.status(_("(run 'hg heads' to see heads)\n"))
4611 else:
4615 else:
4612 ui.status(_("(run 'hg update' to get a working copy)\n"))
4616 ui.status(_("(run 'hg update' to get a working copy)\n"))
4613
4617
4614 @command('^pull',
4618 @command('^pull',
4615 [('u', 'update', None,
4619 [('u', 'update', None,
4616 _('update to new branch head if changesets were pulled')),
4620 _('update to new branch head if changesets were pulled')),
4617 ('f', 'force', None, _('run even when remote repository is unrelated')),
4621 ('f', 'force', None, _('run even when remote repository is unrelated')),
4618 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4622 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4619 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4623 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4620 ('b', 'branch', [], _('a specific branch you would like to pull'),
4624 ('b', 'branch', [], _('a specific branch you would like to pull'),
4621 _('BRANCH')),
4625 _('BRANCH')),
4622 ] + remoteopts,
4626 ] + remoteopts,
4623 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4627 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4624 def pull(ui, repo, source="default", **opts):
4628 def pull(ui, repo, source="default", **opts):
4625 """pull changes from the specified source
4629 """pull changes from the specified source
4626
4630
4627 Pull changes from a remote repository to a local one.
4631 Pull changes from a remote repository to a local one.
4628
4632
4629 This finds all changes from the repository at the specified path
4633 This finds all changes from the repository at the specified path
4630 or URL and adds them to a local repository (the current one unless
4634 or URL and adds them to a local repository (the current one unless
4631 -R is specified). By default, this does not update the copy of the
4635 -R is specified). By default, this does not update the copy of the
4632 project in the working directory.
4636 project in the working directory.
4633
4637
4634 Use :hg:`incoming` if you want to see what would have been added
4638 Use :hg:`incoming` if you want to see what would have been added
4635 by a pull at the time you issued this command. If you then decide
4639 by a pull at the time you issued this command. If you then decide
4636 to add those changes to the repository, you should use :hg:`pull
4640 to add those changes to the repository, you should use :hg:`pull
4637 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4641 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4638
4642
4639 If SOURCE is omitted, the 'default' path will be used.
4643 If SOURCE is omitted, the 'default' path will be used.
4640 See :hg:`help urls` for more information.
4644 See :hg:`help urls` for more information.
4641
4645
4642 Returns 0 on success, 1 if an update had unresolved files.
4646 Returns 0 on success, 1 if an update had unresolved files.
4643 """
4647 """
4644 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4648 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4645 other = hg.peer(repo, opts, source)
4649 other = hg.peer(repo, opts, source)
4646 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4650 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4647 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4651 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4648
4652
4649 if opts.get('bookmark'):
4653 if opts.get('bookmark'):
4650 if not revs:
4654 if not revs:
4651 revs = []
4655 revs = []
4652 rb = other.listkeys('bookmarks')
4656 rb = other.listkeys('bookmarks')
4653 for b in opts['bookmark']:
4657 for b in opts['bookmark']:
4654 if b not in rb:
4658 if b not in rb:
4655 raise util.Abort(_('remote bookmark %s not found!') % b)
4659 raise util.Abort(_('remote bookmark %s not found!') % b)
4656 revs.append(rb[b])
4660 revs.append(rb[b])
4657
4661
4658 if revs:
4662 if revs:
4659 try:
4663 try:
4660 revs = [other.lookup(rev) for rev in revs]
4664 revs = [other.lookup(rev) for rev in revs]
4661 except error.CapabilityError:
4665 except error.CapabilityError:
4662 err = _("other repository doesn't support revision lookup, "
4666 err = _("other repository doesn't support revision lookup, "
4663 "so a rev cannot be specified.")
4667 "so a rev cannot be specified.")
4664 raise util.Abort(err)
4668 raise util.Abort(err)
4665
4669
4666 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4670 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4667 bookmarks.updatefromremote(ui, repo, other, source)
4671 bookmarks.updatefromremote(ui, repo, other, source)
4668 if checkout:
4672 if checkout:
4669 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4673 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4670 repo._subtoppath = source
4674 repo._subtoppath = source
4671 try:
4675 try:
4672 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4676 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4673
4677
4674 finally:
4678 finally:
4675 del repo._subtoppath
4679 del repo._subtoppath
4676
4680
4677 # update specified bookmarks
4681 # update specified bookmarks
4678 if opts.get('bookmark'):
4682 if opts.get('bookmark'):
4679 marks = repo._bookmarks
4683 marks = repo._bookmarks
4680 for b in opts['bookmark']:
4684 for b in opts['bookmark']:
4681 # explicit pull overrides local bookmark if any
4685 # explicit pull overrides local bookmark if any
4682 ui.status(_("importing bookmark %s\n") % b)
4686 ui.status(_("importing bookmark %s\n") % b)
4683 marks[b] = repo[rb[b]].node()
4687 marks[b] = repo[rb[b]].node()
4684 marks.write()
4688 marks.write()
4685
4689
4686 return ret
4690 return ret
4687
4691
4688 @command('^push',
4692 @command('^push',
4689 [('f', 'force', None, _('force push')),
4693 [('f', 'force', None, _('force push')),
4690 ('r', 'rev', [],
4694 ('r', 'rev', [],
4691 _('a changeset intended to be included in the destination'),
4695 _('a changeset intended to be included in the destination'),
4692 _('REV')),
4696 _('REV')),
4693 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4697 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4694 ('b', 'branch', [],
4698 ('b', 'branch', [],
4695 _('a specific branch you would like to push'), _('BRANCH')),
4699 _('a specific branch you would like to push'), _('BRANCH')),
4696 ('', 'new-branch', False, _('allow pushing a new branch')),
4700 ('', 'new-branch', False, _('allow pushing a new branch')),
4697 ] + remoteopts,
4701 ] + remoteopts,
4698 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4702 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4699 def push(ui, repo, dest=None, **opts):
4703 def push(ui, repo, dest=None, **opts):
4700 """push changes to the specified destination
4704 """push changes to the specified destination
4701
4705
4702 Push changesets from the local repository to the specified
4706 Push changesets from the local repository to the specified
4703 destination.
4707 destination.
4704
4708
4705 This operation is symmetrical to pull: it is identical to a pull
4709 This operation is symmetrical to pull: it is identical to a pull
4706 in the destination repository from the current one.
4710 in the destination repository from the current one.
4707
4711
4708 By default, push will not allow creation of new heads at the
4712 By default, push will not allow creation of new heads at the
4709 destination, since multiple heads would make it unclear which head
4713 destination, since multiple heads would make it unclear which head
4710 to use. In this situation, it is recommended to pull and merge
4714 to use. In this situation, it is recommended to pull and merge
4711 before pushing.
4715 before pushing.
4712
4716
4713 Use --new-branch if you want to allow push to create a new named
4717 Use --new-branch if you want to allow push to create a new named
4714 branch that is not present at the destination. This allows you to
4718 branch that is not present at the destination. This allows you to
4715 only create a new branch without forcing other changes.
4719 only create a new branch without forcing other changes.
4716
4720
4717 Use -f/--force to override the default behavior and push all
4721 Use -f/--force to override the default behavior and push all
4718 changesets on all branches.
4722 changesets on all branches.
4719
4723
4720 If -r/--rev is used, the specified revision and all its ancestors
4724 If -r/--rev is used, the specified revision and all its ancestors
4721 will be pushed to the remote repository.
4725 will be pushed to the remote repository.
4722
4726
4723 If -B/--bookmark is used, the specified bookmarked revision, its
4727 If -B/--bookmark is used, the specified bookmarked revision, its
4724 ancestors, and the bookmark will be pushed to the remote
4728 ancestors, and the bookmark will be pushed to the remote
4725 repository.
4729 repository.
4726
4730
4727 Please see :hg:`help urls` for important details about ``ssh://``
4731 Please see :hg:`help urls` for important details about ``ssh://``
4728 URLs. If DESTINATION is omitted, a default path will be used.
4732 URLs. If DESTINATION is omitted, a default path will be used.
4729
4733
4730 Returns 0 if push was successful, 1 if nothing to push.
4734 Returns 0 if push was successful, 1 if nothing to push.
4731 """
4735 """
4732
4736
4733 if opts.get('bookmark'):
4737 if opts.get('bookmark'):
4734 for b in opts['bookmark']:
4738 for b in opts['bookmark']:
4735 # translate -B options to -r so changesets get pushed
4739 # translate -B options to -r so changesets get pushed
4736 if b in repo._bookmarks:
4740 if b in repo._bookmarks:
4737 opts.setdefault('rev', []).append(b)
4741 opts.setdefault('rev', []).append(b)
4738 else:
4742 else:
4739 # if we try to push a deleted bookmark, translate it to null
4743 # if we try to push a deleted bookmark, translate it to null
4740 # this lets simultaneous -r, -b options continue working
4744 # this lets simultaneous -r, -b options continue working
4741 opts.setdefault('rev', []).append("null")
4745 opts.setdefault('rev', []).append("null")
4742
4746
4743 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4747 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4744 dest, branches = hg.parseurl(dest, opts.get('branch'))
4748 dest, branches = hg.parseurl(dest, opts.get('branch'))
4745 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4749 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4746 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4750 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4747 other = hg.peer(repo, opts, dest)
4751 other = hg.peer(repo, opts, dest)
4748 if revs:
4752 if revs:
4749 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4753 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4750
4754
4751 repo._subtoppath = dest
4755 repo._subtoppath = dest
4752 try:
4756 try:
4753 # push subrepos depth-first for coherent ordering
4757 # push subrepos depth-first for coherent ordering
4754 c = repo['']
4758 c = repo['']
4755 subs = c.substate # only repos that are committed
4759 subs = c.substate # only repos that are committed
4756 for s in sorted(subs):
4760 for s in sorted(subs):
4757 if c.sub(s).push(opts) == 0:
4761 if c.sub(s).push(opts) == 0:
4758 return False
4762 return False
4759 finally:
4763 finally:
4760 del repo._subtoppath
4764 del repo._subtoppath
4761 result = repo.push(other, opts.get('force'), revs=revs,
4765 result = repo.push(other, opts.get('force'), revs=revs,
4762 newbranch=opts.get('new_branch'))
4766 newbranch=opts.get('new_branch'))
4763
4767
4764 result = not result
4768 result = not result
4765
4769
4766 if opts.get('bookmark'):
4770 if opts.get('bookmark'):
4767 rb = other.listkeys('bookmarks')
4771 rb = other.listkeys('bookmarks')
4768 for b in opts['bookmark']:
4772 for b in opts['bookmark']:
4769 # explicit push overrides remote bookmark if any
4773 # explicit push overrides remote bookmark if any
4770 if b in repo._bookmarks:
4774 if b in repo._bookmarks:
4771 ui.status(_("exporting bookmark %s\n") % b)
4775 ui.status(_("exporting bookmark %s\n") % b)
4772 new = repo[b].hex()
4776 new = repo[b].hex()
4773 elif b in rb:
4777 elif b in rb:
4774 ui.status(_("deleting remote bookmark %s\n") % b)
4778 ui.status(_("deleting remote bookmark %s\n") % b)
4775 new = '' # delete
4779 new = '' # delete
4776 else:
4780 else:
4777 ui.warn(_('bookmark %s does not exist on the local '
4781 ui.warn(_('bookmark %s does not exist on the local '
4778 'or remote repository!\n') % b)
4782 'or remote repository!\n') % b)
4779 return 2
4783 return 2
4780 old = rb.get(b, '')
4784 old = rb.get(b, '')
4781 r = other.pushkey('bookmarks', b, old, new)
4785 r = other.pushkey('bookmarks', b, old, new)
4782 if not r:
4786 if not r:
4783 ui.warn(_('updating bookmark %s failed!\n') % b)
4787 ui.warn(_('updating bookmark %s failed!\n') % b)
4784 if not result:
4788 if not result:
4785 result = 2
4789 result = 2
4786
4790
4787 return result
4791 return result
4788
4792
4789 @command('recover', [])
4793 @command('recover', [])
4790 def recover(ui, repo):
4794 def recover(ui, repo):
4791 """roll back an interrupted transaction
4795 """roll back an interrupted transaction
4792
4796
4793 Recover from an interrupted commit or pull.
4797 Recover from an interrupted commit or pull.
4794
4798
4795 This command tries to fix the repository status after an
4799 This command tries to fix the repository status after an
4796 interrupted operation. It should only be necessary when Mercurial
4800 interrupted operation. It should only be necessary when Mercurial
4797 suggests it.
4801 suggests it.
4798
4802
4799 Returns 0 if successful, 1 if nothing to recover or verify fails.
4803 Returns 0 if successful, 1 if nothing to recover or verify fails.
4800 """
4804 """
4801 if repo.recover():
4805 if repo.recover():
4802 return hg.verify(repo)
4806 return hg.verify(repo)
4803 return 1
4807 return 1
4804
4808
4805 @command('^remove|rm',
4809 @command('^remove|rm',
4806 [('A', 'after', None, _('record delete for missing files')),
4810 [('A', 'after', None, _('record delete for missing files')),
4807 ('f', 'force', None,
4811 ('f', 'force', None,
4808 _('remove (and delete) file even if added or modified')),
4812 _('remove (and delete) file even if added or modified')),
4809 ] + walkopts,
4813 ] + walkopts,
4810 _('[OPTION]... FILE...'))
4814 _('[OPTION]... FILE...'))
4811 def remove(ui, repo, *pats, **opts):
4815 def remove(ui, repo, *pats, **opts):
4812 """remove the specified files on the next commit
4816 """remove the specified files on the next commit
4813
4817
4814 Schedule the indicated files for removal from the current branch.
4818 Schedule the indicated files for removal from the current branch.
4815
4819
4816 This command schedules the files to be removed at the next commit.
4820 This command schedules the files to be removed at the next commit.
4817 To undo a remove before that, see :hg:`revert`. To undo added
4821 To undo a remove before that, see :hg:`revert`. To undo added
4818 files, see :hg:`forget`.
4822 files, see :hg:`forget`.
4819
4823
4820 .. container:: verbose
4824 .. container:: verbose
4821
4825
4822 -A/--after can be used to remove only files that have already
4826 -A/--after can be used to remove only files that have already
4823 been deleted, -f/--force can be used to force deletion, and -Af
4827 been deleted, -f/--force can be used to force deletion, and -Af
4824 can be used to remove files from the next revision without
4828 can be used to remove files from the next revision without
4825 deleting them from the working directory.
4829 deleting them from the working directory.
4826
4830
4827 The following table details the behavior of remove for different
4831 The following table details the behavior of remove for different
4828 file states (columns) and option combinations (rows). The file
4832 file states (columns) and option combinations (rows). The file
4829 states are Added [A], Clean [C], Modified [M] and Missing [!]
4833 states are Added [A], Clean [C], Modified [M] and Missing [!]
4830 (as reported by :hg:`status`). The actions are Warn, Remove
4834 (as reported by :hg:`status`). The actions are Warn, Remove
4831 (from branch) and Delete (from disk):
4835 (from branch) and Delete (from disk):
4832
4836
4833 ======= == == == ==
4837 ======= == == == ==
4834 A C M !
4838 A C M !
4835 ======= == == == ==
4839 ======= == == == ==
4836 none W RD W R
4840 none W RD W R
4837 -f R RD RD R
4841 -f R RD RD R
4838 -A W W W R
4842 -A W W W R
4839 -Af R R R R
4843 -Af R R R R
4840 ======= == == == ==
4844 ======= == == == ==
4841
4845
4842 Note that remove never deletes files in Added [A] state from the
4846 Note that remove never deletes files in Added [A] state from the
4843 working directory, not even if option --force is specified.
4847 working directory, not even if option --force is specified.
4844
4848
4845 Returns 0 on success, 1 if any warnings encountered.
4849 Returns 0 on success, 1 if any warnings encountered.
4846 """
4850 """
4847
4851
4848 ret = 0
4852 ret = 0
4849 after, force = opts.get('after'), opts.get('force')
4853 after, force = opts.get('after'), opts.get('force')
4850 if not pats and not after:
4854 if not pats and not after:
4851 raise util.Abort(_('no files specified'))
4855 raise util.Abort(_('no files specified'))
4852
4856
4853 m = scmutil.match(repo[None], pats, opts)
4857 m = scmutil.match(repo[None], pats, opts)
4854 s = repo.status(match=m, clean=True)
4858 s = repo.status(match=m, clean=True)
4855 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4859 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4856
4860
4857 # warn about failure to delete explicit files/dirs
4861 # warn about failure to delete explicit files/dirs
4858 wctx = repo[None]
4862 wctx = repo[None]
4859 for f in m.files():
4863 for f in m.files():
4860 if f in repo.dirstate or f in wctx.dirs():
4864 if f in repo.dirstate or f in wctx.dirs():
4861 continue
4865 continue
4862 if os.path.exists(m.rel(f)):
4866 if os.path.exists(m.rel(f)):
4863 if os.path.isdir(m.rel(f)):
4867 if os.path.isdir(m.rel(f)):
4864 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4868 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4865 else:
4869 else:
4866 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4870 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4867 # missing files will generate a warning elsewhere
4871 # missing files will generate a warning elsewhere
4868 ret = 1
4872 ret = 1
4869
4873
4870 if force:
4874 if force:
4871 list = modified + deleted + clean + added
4875 list = modified + deleted + clean + added
4872 elif after:
4876 elif after:
4873 list = deleted
4877 list = deleted
4874 for f in modified + added + clean:
4878 for f in modified + added + clean:
4875 ui.warn(_('not removing %s: file still exists (use -f'
4879 ui.warn(_('not removing %s: file still exists (use -f'
4876 ' to force removal)\n') % m.rel(f))
4880 ' to force removal)\n') % m.rel(f))
4877 ret = 1
4881 ret = 1
4878 else:
4882 else:
4879 list = deleted + clean
4883 list = deleted + clean
4880 for f in modified:
4884 for f in modified:
4881 ui.warn(_('not removing %s: file is modified (use -f'
4885 ui.warn(_('not removing %s: file is modified (use -f'
4882 ' to force removal)\n') % m.rel(f))
4886 ' to force removal)\n') % m.rel(f))
4883 ret = 1
4887 ret = 1
4884 for f in added:
4888 for f in added:
4885 ui.warn(_('not removing %s: file has been marked for add'
4889 ui.warn(_('not removing %s: file has been marked for add'
4886 ' (use forget to undo)\n') % m.rel(f))
4890 ' (use forget to undo)\n') % m.rel(f))
4887 ret = 1
4891 ret = 1
4888
4892
4889 for f in sorted(list):
4893 for f in sorted(list):
4890 if ui.verbose or not m.exact(f):
4894 if ui.verbose or not m.exact(f):
4891 ui.status(_('removing %s\n') % m.rel(f))
4895 ui.status(_('removing %s\n') % m.rel(f))
4892
4896
4893 wlock = repo.wlock()
4897 wlock = repo.wlock()
4894 try:
4898 try:
4895 if not after:
4899 if not after:
4896 for f in list:
4900 for f in list:
4897 if f in added:
4901 if f in added:
4898 continue # we never unlink added files on remove
4902 continue # we never unlink added files on remove
4899 try:
4903 try:
4900 util.unlinkpath(repo.wjoin(f))
4904 util.unlinkpath(repo.wjoin(f))
4901 except OSError, inst:
4905 except OSError, inst:
4902 if inst.errno != errno.ENOENT:
4906 if inst.errno != errno.ENOENT:
4903 raise
4907 raise
4904 repo[None].forget(list)
4908 repo[None].forget(list)
4905 finally:
4909 finally:
4906 wlock.release()
4910 wlock.release()
4907
4911
4908 return ret
4912 return ret
4909
4913
4910 @command('rename|move|mv',
4914 @command('rename|move|mv',
4911 [('A', 'after', None, _('record a rename that has already occurred')),
4915 [('A', 'after', None, _('record a rename that has already occurred')),
4912 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4916 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4913 ] + walkopts + dryrunopts,
4917 ] + walkopts + dryrunopts,
4914 _('[OPTION]... SOURCE... DEST'))
4918 _('[OPTION]... SOURCE... DEST'))
4915 def rename(ui, repo, *pats, **opts):
4919 def rename(ui, repo, *pats, **opts):
4916 """rename files; equivalent of copy + remove
4920 """rename files; equivalent of copy + remove
4917
4921
4918 Mark dest as copies of sources; mark sources for deletion. If dest
4922 Mark dest as copies of sources; mark sources for deletion. If dest
4919 is a directory, copies are put in that directory. If dest is a
4923 is a directory, copies are put in that directory. If dest is a
4920 file, there can only be one source.
4924 file, there can only be one source.
4921
4925
4922 By default, this command copies the contents of files as they
4926 By default, this command copies the contents of files as they
4923 exist in the working directory. If invoked with -A/--after, the
4927 exist in the working directory. If invoked with -A/--after, the
4924 operation is recorded, but no copying is performed.
4928 operation is recorded, but no copying is performed.
4925
4929
4926 This command takes effect at the next commit. To undo a rename
4930 This command takes effect at the next commit. To undo a rename
4927 before that, see :hg:`revert`.
4931 before that, see :hg:`revert`.
4928
4932
4929 Returns 0 on success, 1 if errors are encountered.
4933 Returns 0 on success, 1 if errors are encountered.
4930 """
4934 """
4931 wlock = repo.wlock(False)
4935 wlock = repo.wlock(False)
4932 try:
4936 try:
4933 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4937 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4934 finally:
4938 finally:
4935 wlock.release()
4939 wlock.release()
4936
4940
4937 @command('resolve',
4941 @command('resolve',
4938 [('a', 'all', None, _('select all unresolved files')),
4942 [('a', 'all', None, _('select all unresolved files')),
4939 ('l', 'list', None, _('list state of files needing merge')),
4943 ('l', 'list', None, _('list state of files needing merge')),
4940 ('m', 'mark', None, _('mark files as resolved')),
4944 ('m', 'mark', None, _('mark files as resolved')),
4941 ('u', 'unmark', None, _('mark files as unresolved')),
4945 ('u', 'unmark', None, _('mark files as unresolved')),
4942 ('n', 'no-status', None, _('hide status prefix'))]
4946 ('n', 'no-status', None, _('hide status prefix'))]
4943 + mergetoolopts + walkopts,
4947 + mergetoolopts + walkopts,
4944 _('[OPTION]... [FILE]...'))
4948 _('[OPTION]... [FILE]...'))
4945 def resolve(ui, repo, *pats, **opts):
4949 def resolve(ui, repo, *pats, **opts):
4946 """redo merges or set/view the merge status of files
4950 """redo merges or set/view the merge status of files
4947
4951
4948 Merges with unresolved conflicts are often the result of
4952 Merges with unresolved conflicts are often the result of
4949 non-interactive merging using the ``internal:merge`` configuration
4953 non-interactive merging using the ``internal:merge`` configuration
4950 setting, or a command-line merge tool like ``diff3``. The resolve
4954 setting, or a command-line merge tool like ``diff3``. The resolve
4951 command is used to manage the files involved in a merge, after
4955 command is used to manage the files involved in a merge, after
4952 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4956 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4953 working directory must have two parents). See :hg:`help
4957 working directory must have two parents). See :hg:`help
4954 merge-tools` for information on configuring merge tools.
4958 merge-tools` for information on configuring merge tools.
4955
4959
4956 The resolve command can be used in the following ways:
4960 The resolve command can be used in the following ways:
4957
4961
4958 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4962 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4959 files, discarding any previous merge attempts. Re-merging is not
4963 files, discarding any previous merge attempts. Re-merging is not
4960 performed for files already marked as resolved. Use ``--all/-a``
4964 performed for files already marked as resolved. Use ``--all/-a``
4961 to select all unresolved files. ``--tool`` can be used to specify
4965 to select all unresolved files. ``--tool`` can be used to specify
4962 the merge tool used for the given files. It overrides the HGMERGE
4966 the merge tool used for the given files. It overrides the HGMERGE
4963 environment variable and your configuration files. Previous file
4967 environment variable and your configuration files. Previous file
4964 contents are saved with a ``.orig`` suffix.
4968 contents are saved with a ``.orig`` suffix.
4965
4969
4966 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4970 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4967 (e.g. after having manually fixed-up the files). The default is
4971 (e.g. after having manually fixed-up the files). The default is
4968 to mark all unresolved files.
4972 to mark all unresolved files.
4969
4973
4970 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4974 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4971 default is to mark all resolved files.
4975 default is to mark all resolved files.
4972
4976
4973 - :hg:`resolve -l`: list files which had or still have conflicts.
4977 - :hg:`resolve -l`: list files which had or still have conflicts.
4974 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4978 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4975
4979
4976 Note that Mercurial will not let you commit files with unresolved
4980 Note that Mercurial will not let you commit files with unresolved
4977 merge conflicts. You must use :hg:`resolve -m ...` before you can
4981 merge conflicts. You must use :hg:`resolve -m ...` before you can
4978 commit after a conflicting merge.
4982 commit after a conflicting merge.
4979
4983
4980 Returns 0 on success, 1 if any files fail a resolve attempt.
4984 Returns 0 on success, 1 if any files fail a resolve attempt.
4981 """
4985 """
4982
4986
4983 all, mark, unmark, show, nostatus = \
4987 all, mark, unmark, show, nostatus = \
4984 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4988 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4985
4989
4986 if (show and (mark or unmark)) or (mark and unmark):
4990 if (show and (mark or unmark)) or (mark and unmark):
4987 raise util.Abort(_("too many options specified"))
4991 raise util.Abort(_("too many options specified"))
4988 if pats and all:
4992 if pats and all:
4989 raise util.Abort(_("can't specify --all and patterns"))
4993 raise util.Abort(_("can't specify --all and patterns"))
4990 if not (all or pats or show or mark or unmark):
4994 if not (all or pats or show or mark or unmark):
4991 raise util.Abort(_('no files or directories specified; '
4995 raise util.Abort(_('no files or directories specified; '
4992 'use --all to remerge all files'))
4996 'use --all to remerge all files'))
4993
4997
4994 ms = mergemod.mergestate(repo)
4998 ms = mergemod.mergestate(repo)
4995 m = scmutil.match(repo[None], pats, opts)
4999 m = scmutil.match(repo[None], pats, opts)
4996 ret = 0
5000 ret = 0
4997
5001
4998 for f in ms:
5002 for f in ms:
4999 if m(f):
5003 if m(f):
5000 if show:
5004 if show:
5001 if nostatus:
5005 if nostatus:
5002 ui.write("%s\n" % f)
5006 ui.write("%s\n" % f)
5003 else:
5007 else:
5004 ui.write("%s %s\n" % (ms[f].upper(), f),
5008 ui.write("%s %s\n" % (ms[f].upper(), f),
5005 label='resolve.' +
5009 label='resolve.' +
5006 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5010 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5007 elif mark:
5011 elif mark:
5008 ms.mark(f, "r")
5012 ms.mark(f, "r")
5009 elif unmark:
5013 elif unmark:
5010 ms.mark(f, "u")
5014 ms.mark(f, "u")
5011 else:
5015 else:
5012 wctx = repo[None]
5016 wctx = repo[None]
5013 mctx = wctx.parents()[-1]
5017 mctx = wctx.parents()[-1]
5014
5018
5015 # backup pre-resolve (merge uses .orig for its own purposes)
5019 # backup pre-resolve (merge uses .orig for its own purposes)
5016 a = repo.wjoin(f)
5020 a = repo.wjoin(f)
5017 util.copyfile(a, a + ".resolve")
5021 util.copyfile(a, a + ".resolve")
5018
5022
5019 try:
5023 try:
5020 # resolve file
5024 # resolve file
5021 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5025 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5022 if ms.resolve(f, wctx, mctx):
5026 if ms.resolve(f, wctx, mctx):
5023 ret = 1
5027 ret = 1
5024 finally:
5028 finally:
5025 ui.setconfig('ui', 'forcemerge', '')
5029 ui.setconfig('ui', 'forcemerge', '')
5026 ms.commit()
5030 ms.commit()
5027
5031
5028 # replace filemerge's .orig file with our resolve file
5032 # replace filemerge's .orig file with our resolve file
5029 util.rename(a + ".resolve", a + ".orig")
5033 util.rename(a + ".resolve", a + ".orig")
5030
5034
5031 ms.commit()
5035 ms.commit()
5032 return ret
5036 return ret
5033
5037
5034 @command('revert',
5038 @command('revert',
5035 [('a', 'all', None, _('revert all changes when no arguments given')),
5039 [('a', 'all', None, _('revert all changes when no arguments given')),
5036 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5040 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5037 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5041 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5038 ('C', 'no-backup', None, _('do not save backup copies of files')),
5042 ('C', 'no-backup', None, _('do not save backup copies of files')),
5039 ] + walkopts + dryrunopts,
5043 ] + walkopts + dryrunopts,
5040 _('[OPTION]... [-r REV] [NAME]...'))
5044 _('[OPTION]... [-r REV] [NAME]...'))
5041 def revert(ui, repo, *pats, **opts):
5045 def revert(ui, repo, *pats, **opts):
5042 """restore files to their checkout state
5046 """restore files to their checkout state
5043
5047
5044 .. note::
5048 .. note::
5045
5049
5046 To check out earlier revisions, you should use :hg:`update REV`.
5050 To check out earlier revisions, you should use :hg:`update REV`.
5047 To cancel an uncommitted merge (and lose your changes), use
5051 To cancel an uncommitted merge (and lose your changes), use
5048 :hg:`update --clean .`.
5052 :hg:`update --clean .`.
5049
5053
5050 With no revision specified, revert the specified files or directories
5054 With no revision specified, revert the specified files or directories
5051 to the contents they had in the parent of the working directory.
5055 to the contents they had in the parent of the working directory.
5052 This restores the contents of files to an unmodified
5056 This restores the contents of files to an unmodified
5053 state and unschedules adds, removes, copies, and renames. If the
5057 state and unschedules adds, removes, copies, and renames. If the
5054 working directory has two parents, you must explicitly specify a
5058 working directory has two parents, you must explicitly specify a
5055 revision.
5059 revision.
5056
5060
5057 Using the -r/--rev or -d/--date options, revert the given files or
5061 Using the -r/--rev or -d/--date options, revert the given files or
5058 directories to their states as of a specific revision. Because
5062 directories to their states as of a specific revision. Because
5059 revert does not change the working directory parents, this will
5063 revert does not change the working directory parents, this will
5060 cause these files to appear modified. This can be helpful to "back
5064 cause these files to appear modified. This can be helpful to "back
5061 out" some or all of an earlier change. See :hg:`backout` for a
5065 out" some or all of an earlier change. See :hg:`backout` for a
5062 related method.
5066 related method.
5063
5067
5064 Modified files are saved with a .orig suffix before reverting.
5068 Modified files are saved with a .orig suffix before reverting.
5065 To disable these backups, use --no-backup.
5069 To disable these backups, use --no-backup.
5066
5070
5067 See :hg:`help dates` for a list of formats valid for -d/--date.
5071 See :hg:`help dates` for a list of formats valid for -d/--date.
5068
5072
5069 Returns 0 on success.
5073 Returns 0 on success.
5070 """
5074 """
5071
5075
5072 if opts.get("date"):
5076 if opts.get("date"):
5073 if opts.get("rev"):
5077 if opts.get("rev"):
5074 raise util.Abort(_("you can't specify a revision and a date"))
5078 raise util.Abort(_("you can't specify a revision and a date"))
5075 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5079 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5076
5080
5077 parent, p2 = repo.dirstate.parents()
5081 parent, p2 = repo.dirstate.parents()
5078 if not opts.get('rev') and p2 != nullid:
5082 if not opts.get('rev') and p2 != nullid:
5079 # revert after merge is a trap for new users (issue2915)
5083 # revert after merge is a trap for new users (issue2915)
5080 raise util.Abort(_('uncommitted merge with no revision specified'),
5084 raise util.Abort(_('uncommitted merge with no revision specified'),
5081 hint=_('use "hg update" or see "hg help revert"'))
5085 hint=_('use "hg update" or see "hg help revert"'))
5082
5086
5083 ctx = scmutil.revsingle(repo, opts.get('rev'))
5087 ctx = scmutil.revsingle(repo, opts.get('rev'))
5084
5088
5085 if not pats and not opts.get('all'):
5089 if not pats and not opts.get('all'):
5086 msg = _("no files or directories specified")
5090 msg = _("no files or directories specified")
5087 if p2 != nullid:
5091 if p2 != nullid:
5088 hint = _("uncommitted merge, use --all to discard all changes,"
5092 hint = _("uncommitted merge, use --all to discard all changes,"
5089 " or 'hg update -C .' to abort the merge")
5093 " or 'hg update -C .' to abort the merge")
5090 raise util.Abort(msg, hint=hint)
5094 raise util.Abort(msg, hint=hint)
5091 dirty = util.any(repo.status())
5095 dirty = util.any(repo.status())
5092 node = ctx.node()
5096 node = ctx.node()
5093 if node != parent:
5097 if node != parent:
5094 if dirty:
5098 if dirty:
5095 hint = _("uncommitted changes, use --all to discard all"
5099 hint = _("uncommitted changes, use --all to discard all"
5096 " changes, or 'hg update %s' to update") % ctx.rev()
5100 " changes, or 'hg update %s' to update") % ctx.rev()
5097 else:
5101 else:
5098 hint = _("use --all to revert all files,"
5102 hint = _("use --all to revert all files,"
5099 " or 'hg update %s' to update") % ctx.rev()
5103 " or 'hg update %s' to update") % ctx.rev()
5100 elif dirty:
5104 elif dirty:
5101 hint = _("uncommitted changes, use --all to discard all changes")
5105 hint = _("uncommitted changes, use --all to discard all changes")
5102 else:
5106 else:
5103 hint = _("use --all to revert all files")
5107 hint = _("use --all to revert all files")
5104 raise util.Abort(msg, hint=hint)
5108 raise util.Abort(msg, hint=hint)
5105
5109
5106 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5110 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5107
5111
5108 @command('rollback', dryrunopts +
5112 @command('rollback', dryrunopts +
5109 [('f', 'force', False, _('ignore safety measures'))])
5113 [('f', 'force', False, _('ignore safety measures'))])
5110 def rollback(ui, repo, **opts):
5114 def rollback(ui, repo, **opts):
5111 """roll back the last transaction (dangerous)
5115 """roll back the last transaction (dangerous)
5112
5116
5113 This command should be used with care. There is only one level of
5117 This command should be used with care. There is only one level of
5114 rollback, and there is no way to undo a rollback. It will also
5118 rollback, and there is no way to undo a rollback. It will also
5115 restore the dirstate at the time of the last transaction, losing
5119 restore the dirstate at the time of the last transaction, losing
5116 any dirstate changes since that time. This command does not alter
5120 any dirstate changes since that time. This command does not alter
5117 the working directory.
5121 the working directory.
5118
5122
5119 Transactions are used to encapsulate the effects of all commands
5123 Transactions are used to encapsulate the effects of all commands
5120 that create new changesets or propagate existing changesets into a
5124 that create new changesets or propagate existing changesets into a
5121 repository.
5125 repository.
5122
5126
5123 .. container:: verbose
5127 .. container:: verbose
5124
5128
5125 For example, the following commands are transactional, and their
5129 For example, the following commands are transactional, and their
5126 effects can be rolled back:
5130 effects can be rolled back:
5127
5131
5128 - commit
5132 - commit
5129 - import
5133 - import
5130 - pull
5134 - pull
5131 - push (with this repository as the destination)
5135 - push (with this repository as the destination)
5132 - unbundle
5136 - unbundle
5133
5137
5134 To avoid permanent data loss, rollback will refuse to rollback a
5138 To avoid permanent data loss, rollback will refuse to rollback a
5135 commit transaction if it isn't checked out. Use --force to
5139 commit transaction if it isn't checked out. Use --force to
5136 override this protection.
5140 override this protection.
5137
5141
5138 This command is not intended for use on public repositories. Once
5142 This command is not intended for use on public repositories. Once
5139 changes are visible for pull by other users, rolling a transaction
5143 changes are visible for pull by other users, rolling a transaction
5140 back locally is ineffective (someone else may already have pulled
5144 back locally is ineffective (someone else may already have pulled
5141 the changes). Furthermore, a race is possible with readers of the
5145 the changes). Furthermore, a race is possible with readers of the
5142 repository; for example an in-progress pull from the repository
5146 repository; for example an in-progress pull from the repository
5143 may fail if a rollback is performed.
5147 may fail if a rollback is performed.
5144
5148
5145 Returns 0 on success, 1 if no rollback data is available.
5149 Returns 0 on success, 1 if no rollback data is available.
5146 """
5150 """
5147 return repo.rollback(dryrun=opts.get('dry_run'),
5151 return repo.rollback(dryrun=opts.get('dry_run'),
5148 force=opts.get('force'))
5152 force=opts.get('force'))
5149
5153
5150 @command('root', [])
5154 @command('root', [])
5151 def root(ui, repo):
5155 def root(ui, repo):
5152 """print the root (top) of the current working directory
5156 """print the root (top) of the current working directory
5153
5157
5154 Print the root directory of the current repository.
5158 Print the root directory of the current repository.
5155
5159
5156 Returns 0 on success.
5160 Returns 0 on success.
5157 """
5161 """
5158 ui.write(repo.root + "\n")
5162 ui.write(repo.root + "\n")
5159
5163
5160 @command('^serve',
5164 @command('^serve',
5161 [('A', 'accesslog', '', _('name of access log file to write to'),
5165 [('A', 'accesslog', '', _('name of access log file to write to'),
5162 _('FILE')),
5166 _('FILE')),
5163 ('d', 'daemon', None, _('run server in background')),
5167 ('d', 'daemon', None, _('run server in background')),
5164 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5168 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5165 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5169 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5166 # use string type, then we can check if something was passed
5170 # use string type, then we can check if something was passed
5167 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5171 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5168 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5172 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5169 _('ADDR')),
5173 _('ADDR')),
5170 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5174 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5171 _('PREFIX')),
5175 _('PREFIX')),
5172 ('n', 'name', '',
5176 ('n', 'name', '',
5173 _('name to show in web pages (default: working directory)'), _('NAME')),
5177 _('name to show in web pages (default: working directory)'), _('NAME')),
5174 ('', 'web-conf', '',
5178 ('', 'web-conf', '',
5175 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5179 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5176 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5180 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5177 _('FILE')),
5181 _('FILE')),
5178 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5182 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5179 ('', 'stdio', None, _('for remote clients')),
5183 ('', 'stdio', None, _('for remote clients')),
5180 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5184 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5181 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5185 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5182 ('', 'style', '', _('template style to use'), _('STYLE')),
5186 ('', 'style', '', _('template style to use'), _('STYLE')),
5183 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5187 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5184 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5188 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5185 _('[OPTION]...'))
5189 _('[OPTION]...'))
5186 def serve(ui, repo, **opts):
5190 def serve(ui, repo, **opts):
5187 """start stand-alone webserver
5191 """start stand-alone webserver
5188
5192
5189 Start a local HTTP repository browser and pull server. You can use
5193 Start a local HTTP repository browser and pull server. You can use
5190 this for ad-hoc sharing and browsing of repositories. It is
5194 this for ad-hoc sharing and browsing of repositories. It is
5191 recommended to use a real web server to serve a repository for
5195 recommended to use a real web server to serve a repository for
5192 longer periods of time.
5196 longer periods of time.
5193
5197
5194 Please note that the server does not implement access control.
5198 Please note that the server does not implement access control.
5195 This means that, by default, anybody can read from the server and
5199 This means that, by default, anybody can read from the server and
5196 nobody can write to it by default. Set the ``web.allow_push``
5200 nobody can write to it by default. Set the ``web.allow_push``
5197 option to ``*`` to allow everybody to push to the server. You
5201 option to ``*`` to allow everybody to push to the server. You
5198 should use a real web server if you need to authenticate users.
5202 should use a real web server if you need to authenticate users.
5199
5203
5200 By default, the server logs accesses to stdout and errors to
5204 By default, the server logs accesses to stdout and errors to
5201 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5205 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5202 files.
5206 files.
5203
5207
5204 To have the server choose a free port number to listen on, specify
5208 To have the server choose a free port number to listen on, specify
5205 a port number of 0; in this case, the server will print the port
5209 a port number of 0; in this case, the server will print the port
5206 number it uses.
5210 number it uses.
5207
5211
5208 Returns 0 on success.
5212 Returns 0 on success.
5209 """
5213 """
5210
5214
5211 if opts["stdio"] and opts["cmdserver"]:
5215 if opts["stdio"] and opts["cmdserver"]:
5212 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5216 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5213
5217
5214 def checkrepo():
5218 def checkrepo():
5215 if repo is None:
5219 if repo is None:
5216 raise error.RepoError(_("there is no Mercurial repository here"
5220 raise error.RepoError(_("there is no Mercurial repository here"
5217 " (.hg not found)"))
5221 " (.hg not found)"))
5218
5222
5219 if opts["stdio"]:
5223 if opts["stdio"]:
5220 checkrepo()
5224 checkrepo()
5221 s = sshserver.sshserver(ui, repo)
5225 s = sshserver.sshserver(ui, repo)
5222 s.serve_forever()
5226 s.serve_forever()
5223
5227
5224 if opts["cmdserver"]:
5228 if opts["cmdserver"]:
5225 checkrepo()
5229 checkrepo()
5226 s = commandserver.server(ui, repo, opts["cmdserver"])
5230 s = commandserver.server(ui, repo, opts["cmdserver"])
5227 return s.serve()
5231 return s.serve()
5228
5232
5229 # this way we can check if something was given in the command-line
5233 # this way we can check if something was given in the command-line
5230 if opts.get('port'):
5234 if opts.get('port'):
5231 opts['port'] = util.getport(opts.get('port'))
5235 opts['port'] = util.getport(opts.get('port'))
5232
5236
5233 baseui = repo and repo.baseui or ui
5237 baseui = repo and repo.baseui or ui
5234 optlist = ("name templates style address port prefix ipv6"
5238 optlist = ("name templates style address port prefix ipv6"
5235 " accesslog errorlog certificate encoding")
5239 " accesslog errorlog certificate encoding")
5236 for o in optlist.split():
5240 for o in optlist.split():
5237 val = opts.get(o, '')
5241 val = opts.get(o, '')
5238 if val in (None, ''): # should check against default options instead
5242 if val in (None, ''): # should check against default options instead
5239 continue
5243 continue
5240 baseui.setconfig("web", o, val)
5244 baseui.setconfig("web", o, val)
5241 if repo and repo.ui != baseui:
5245 if repo and repo.ui != baseui:
5242 repo.ui.setconfig("web", o, val)
5246 repo.ui.setconfig("web", o, val)
5243
5247
5244 o = opts.get('web_conf') or opts.get('webdir_conf')
5248 o = opts.get('web_conf') or opts.get('webdir_conf')
5245 if not o:
5249 if not o:
5246 if not repo:
5250 if not repo:
5247 raise error.RepoError(_("there is no Mercurial repository"
5251 raise error.RepoError(_("there is no Mercurial repository"
5248 " here (.hg not found)"))
5252 " here (.hg not found)"))
5249 o = repo.root
5253 o = repo.root
5250
5254
5251 app = hgweb.hgweb(o, baseui=ui)
5255 app = hgweb.hgweb(o, baseui=ui)
5252
5256
5253 class service(object):
5257 class service(object):
5254 def init(self):
5258 def init(self):
5255 util.setsignalhandler()
5259 util.setsignalhandler()
5256 self.httpd = hgweb.server.create_server(ui, app)
5260 self.httpd = hgweb.server.create_server(ui, app)
5257
5261
5258 if opts['port'] and not ui.verbose:
5262 if opts['port'] and not ui.verbose:
5259 return
5263 return
5260
5264
5261 if self.httpd.prefix:
5265 if self.httpd.prefix:
5262 prefix = self.httpd.prefix.strip('/') + '/'
5266 prefix = self.httpd.prefix.strip('/') + '/'
5263 else:
5267 else:
5264 prefix = ''
5268 prefix = ''
5265
5269
5266 port = ':%d' % self.httpd.port
5270 port = ':%d' % self.httpd.port
5267 if port == ':80':
5271 if port == ':80':
5268 port = ''
5272 port = ''
5269
5273
5270 bindaddr = self.httpd.addr
5274 bindaddr = self.httpd.addr
5271 if bindaddr == '0.0.0.0':
5275 if bindaddr == '0.0.0.0':
5272 bindaddr = '*'
5276 bindaddr = '*'
5273 elif ':' in bindaddr: # IPv6
5277 elif ':' in bindaddr: # IPv6
5274 bindaddr = '[%s]' % bindaddr
5278 bindaddr = '[%s]' % bindaddr
5275
5279
5276 fqaddr = self.httpd.fqaddr
5280 fqaddr = self.httpd.fqaddr
5277 if ':' in fqaddr:
5281 if ':' in fqaddr:
5278 fqaddr = '[%s]' % fqaddr
5282 fqaddr = '[%s]' % fqaddr
5279 if opts['port']:
5283 if opts['port']:
5280 write = ui.status
5284 write = ui.status
5281 else:
5285 else:
5282 write = ui.write
5286 write = ui.write
5283 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5287 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5284 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5288 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5285
5289
5286 def run(self):
5290 def run(self):
5287 self.httpd.serve_forever()
5291 self.httpd.serve_forever()
5288
5292
5289 service = service()
5293 service = service()
5290
5294
5291 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5295 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5292
5296
5293 @command('showconfig|debugconfig',
5297 @command('showconfig|debugconfig',
5294 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5298 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5295 _('[-u] [NAME]...'))
5299 _('[-u] [NAME]...'))
5296 def showconfig(ui, repo, *values, **opts):
5300 def showconfig(ui, repo, *values, **opts):
5297 """show combined config settings from all hgrc files
5301 """show combined config settings from all hgrc files
5298
5302
5299 With no arguments, print names and values of all config items.
5303 With no arguments, print names and values of all config items.
5300
5304
5301 With one argument of the form section.name, print just the value
5305 With one argument of the form section.name, print just the value
5302 of that config item.
5306 of that config item.
5303
5307
5304 With multiple arguments, print names and values of all config
5308 With multiple arguments, print names and values of all config
5305 items with matching section names.
5309 items with matching section names.
5306
5310
5307 With --debug, the source (filename and line number) is printed
5311 With --debug, the source (filename and line number) is printed
5308 for each config item.
5312 for each config item.
5309
5313
5310 Returns 0 on success.
5314 Returns 0 on success.
5311 """
5315 """
5312
5316
5313 for f in scmutil.rcpath():
5317 for f in scmutil.rcpath():
5314 ui.debug('read config from: %s\n' % f)
5318 ui.debug('read config from: %s\n' % f)
5315 untrusted = bool(opts.get('untrusted'))
5319 untrusted = bool(opts.get('untrusted'))
5316 if values:
5320 if values:
5317 sections = [v for v in values if '.' not in v]
5321 sections = [v for v in values if '.' not in v]
5318 items = [v for v in values if '.' in v]
5322 items = [v for v in values if '.' in v]
5319 if len(items) > 1 or items and sections:
5323 if len(items) > 1 or items and sections:
5320 raise util.Abort(_('only one config item permitted'))
5324 raise util.Abort(_('only one config item permitted'))
5321 for section, name, value in ui.walkconfig(untrusted=untrusted):
5325 for section, name, value in ui.walkconfig(untrusted=untrusted):
5322 value = str(value).replace('\n', '\\n')
5326 value = str(value).replace('\n', '\\n')
5323 sectname = section + '.' + name
5327 sectname = section + '.' + name
5324 if values:
5328 if values:
5325 for v in values:
5329 for v in values:
5326 if v == section:
5330 if v == section:
5327 ui.debug('%s: ' %
5331 ui.debug('%s: ' %
5328 ui.configsource(section, name, untrusted))
5332 ui.configsource(section, name, untrusted))
5329 ui.write('%s=%s\n' % (sectname, value))
5333 ui.write('%s=%s\n' % (sectname, value))
5330 elif v == sectname:
5334 elif v == sectname:
5331 ui.debug('%s: ' %
5335 ui.debug('%s: ' %
5332 ui.configsource(section, name, untrusted))
5336 ui.configsource(section, name, untrusted))
5333 ui.write(value, '\n')
5337 ui.write(value, '\n')
5334 else:
5338 else:
5335 ui.debug('%s: ' %
5339 ui.debug('%s: ' %
5336 ui.configsource(section, name, untrusted))
5340 ui.configsource(section, name, untrusted))
5337 ui.write('%s=%s\n' % (sectname, value))
5341 ui.write('%s=%s\n' % (sectname, value))
5338
5342
5339 @command('^status|st',
5343 @command('^status|st',
5340 [('A', 'all', None, _('show status of all files')),
5344 [('A', 'all', None, _('show status of all files')),
5341 ('m', 'modified', None, _('show only modified files')),
5345 ('m', 'modified', None, _('show only modified files')),
5342 ('a', 'added', None, _('show only added files')),
5346 ('a', 'added', None, _('show only added files')),
5343 ('r', 'removed', None, _('show only removed files')),
5347 ('r', 'removed', None, _('show only removed files')),
5344 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5348 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5345 ('c', 'clean', None, _('show only files without changes')),
5349 ('c', 'clean', None, _('show only files without changes')),
5346 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5350 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5347 ('i', 'ignored', None, _('show only ignored files')),
5351 ('i', 'ignored', None, _('show only ignored files')),
5348 ('n', 'no-status', None, _('hide status prefix')),
5352 ('n', 'no-status', None, _('hide status prefix')),
5349 ('C', 'copies', None, _('show source of copied files')),
5353 ('C', 'copies', None, _('show source of copied files')),
5350 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5354 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5351 ('', 'rev', [], _('show difference from revision'), _('REV')),
5355 ('', 'rev', [], _('show difference from revision'), _('REV')),
5352 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5356 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5353 ] + walkopts + subrepoopts,
5357 ] + walkopts + subrepoopts,
5354 _('[OPTION]... [FILE]...'))
5358 _('[OPTION]... [FILE]...'))
5355 def status(ui, repo, *pats, **opts):
5359 def status(ui, repo, *pats, **opts):
5356 """show changed files in the working directory
5360 """show changed files in the working directory
5357
5361
5358 Show status of files in the repository. If names are given, only
5362 Show status of files in the repository. If names are given, only
5359 files that match are shown. Files that are clean or ignored or
5363 files that match are shown. Files that are clean or ignored or
5360 the source of a copy/move operation, are not listed unless
5364 the source of a copy/move operation, are not listed unless
5361 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5365 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5362 Unless options described with "show only ..." are given, the
5366 Unless options described with "show only ..." are given, the
5363 options -mardu are used.
5367 options -mardu are used.
5364
5368
5365 Option -q/--quiet hides untracked (unknown and ignored) files
5369 Option -q/--quiet hides untracked (unknown and ignored) files
5366 unless explicitly requested with -u/--unknown or -i/--ignored.
5370 unless explicitly requested with -u/--unknown or -i/--ignored.
5367
5371
5368 .. note::
5372 .. note::
5369 status may appear to disagree with diff if permissions have
5373 status may appear to disagree with diff if permissions have
5370 changed or a merge has occurred. The standard diff format does
5374 changed or a merge has occurred. The standard diff format does
5371 not report permission changes and diff only reports changes
5375 not report permission changes and diff only reports changes
5372 relative to one merge parent.
5376 relative to one merge parent.
5373
5377
5374 If one revision is given, it is used as the base revision.
5378 If one revision is given, it is used as the base revision.
5375 If two revisions are given, the differences between them are
5379 If two revisions are given, the differences between them are
5376 shown. The --change option can also be used as a shortcut to list
5380 shown. The --change option can also be used as a shortcut to list
5377 the changed files of a revision from its first parent.
5381 the changed files of a revision from its first parent.
5378
5382
5379 The codes used to show the status of files are::
5383 The codes used to show the status of files are::
5380
5384
5381 M = modified
5385 M = modified
5382 A = added
5386 A = added
5383 R = removed
5387 R = removed
5384 C = clean
5388 C = clean
5385 ! = missing (deleted by non-hg command, but still tracked)
5389 ! = missing (deleted by non-hg command, but still tracked)
5386 ? = not tracked
5390 ? = not tracked
5387 I = ignored
5391 I = ignored
5388 = origin of the previous file listed as A (added)
5392 = origin of the previous file listed as A (added)
5389
5393
5390 .. container:: verbose
5394 .. container:: verbose
5391
5395
5392 Examples:
5396 Examples:
5393
5397
5394 - show changes in the working directory relative to a
5398 - show changes in the working directory relative to a
5395 changeset::
5399 changeset::
5396
5400
5397 hg status --rev 9353
5401 hg status --rev 9353
5398
5402
5399 - show all changes including copies in an existing changeset::
5403 - show all changes including copies in an existing changeset::
5400
5404
5401 hg status --copies --change 9353
5405 hg status --copies --change 9353
5402
5406
5403 - get a NUL separated list of added files, suitable for xargs::
5407 - get a NUL separated list of added files, suitable for xargs::
5404
5408
5405 hg status -an0
5409 hg status -an0
5406
5410
5407 Returns 0 on success.
5411 Returns 0 on success.
5408 """
5412 """
5409
5413
5410 revs = opts.get('rev')
5414 revs = opts.get('rev')
5411 change = opts.get('change')
5415 change = opts.get('change')
5412
5416
5413 if revs and change:
5417 if revs and change:
5414 msg = _('cannot specify --rev and --change at the same time')
5418 msg = _('cannot specify --rev and --change at the same time')
5415 raise util.Abort(msg)
5419 raise util.Abort(msg)
5416 elif change:
5420 elif change:
5417 node2 = scmutil.revsingle(repo, change, None).node()
5421 node2 = scmutil.revsingle(repo, change, None).node()
5418 node1 = repo[node2].p1().node()
5422 node1 = repo[node2].p1().node()
5419 else:
5423 else:
5420 node1, node2 = scmutil.revpair(repo, revs)
5424 node1, node2 = scmutil.revpair(repo, revs)
5421
5425
5422 cwd = (pats and repo.getcwd()) or ''
5426 cwd = (pats and repo.getcwd()) or ''
5423 end = opts.get('print0') and '\0' or '\n'
5427 end = opts.get('print0') and '\0' or '\n'
5424 copy = {}
5428 copy = {}
5425 states = 'modified added removed deleted unknown ignored clean'.split()
5429 states = 'modified added removed deleted unknown ignored clean'.split()
5426 show = [k for k in states if opts.get(k)]
5430 show = [k for k in states if opts.get(k)]
5427 if opts.get('all'):
5431 if opts.get('all'):
5428 show += ui.quiet and (states[:4] + ['clean']) or states
5432 show += ui.quiet and (states[:4] + ['clean']) or states
5429 if not show:
5433 if not show:
5430 show = ui.quiet and states[:4] or states[:5]
5434 show = ui.quiet and states[:4] or states[:5]
5431
5435
5432 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5436 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5433 'ignored' in show, 'clean' in show, 'unknown' in show,
5437 'ignored' in show, 'clean' in show, 'unknown' in show,
5434 opts.get('subrepos'))
5438 opts.get('subrepos'))
5435 changestates = zip(states, 'MAR!?IC', stat)
5439 changestates = zip(states, 'MAR!?IC', stat)
5436
5440
5437 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5441 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5438 copy = copies.pathcopies(repo[node1], repo[node2])
5442 copy = copies.pathcopies(repo[node1], repo[node2])
5439
5443
5440 fm = ui.formatter('status', opts)
5444 fm = ui.formatter('status', opts)
5441 fmt = '%s' + end
5445 fmt = '%s' + end
5442 showchar = not opts.get('no_status')
5446 showchar = not opts.get('no_status')
5443
5447
5444 for state, char, files in changestates:
5448 for state, char, files in changestates:
5445 if state in show:
5449 if state in show:
5446 label = 'status.' + state
5450 label = 'status.' + state
5447 for f in files:
5451 for f in files:
5448 fm.startitem()
5452 fm.startitem()
5449 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5453 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5450 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5454 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5451 if f in copy:
5455 if f in copy:
5452 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5456 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5453 label='status.copied')
5457 label='status.copied')
5454 fm.end()
5458 fm.end()
5455
5459
5456 @command('^summary|sum',
5460 @command('^summary|sum',
5457 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5461 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5458 def summary(ui, repo, **opts):
5462 def summary(ui, repo, **opts):
5459 """summarize working directory state
5463 """summarize working directory state
5460
5464
5461 This generates a brief summary of the working directory state,
5465 This generates a brief summary of the working directory state,
5462 including parents, branch, commit status, and available updates.
5466 including parents, branch, commit status, and available updates.
5463
5467
5464 With the --remote option, this will check the default paths for
5468 With the --remote option, this will check the default paths for
5465 incoming and outgoing changes. This can be time-consuming.
5469 incoming and outgoing changes. This can be time-consuming.
5466
5470
5467 Returns 0 on success.
5471 Returns 0 on success.
5468 """
5472 """
5469
5473
5470 ctx = repo[None]
5474 ctx = repo[None]
5471 parents = ctx.parents()
5475 parents = ctx.parents()
5472 pnode = parents[0].node()
5476 pnode = parents[0].node()
5473 marks = []
5477 marks = []
5474
5478
5475 for p in parents:
5479 for p in parents:
5476 # label with log.changeset (instead of log.parent) since this
5480 # label with log.changeset (instead of log.parent) since this
5477 # shows a working directory parent *changeset*:
5481 # shows a working directory parent *changeset*:
5478 # i18n: column positioning for "hg summary"
5482 # i18n: column positioning for "hg summary"
5479 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5483 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5480 label='log.changeset changeset.%s' % p.phasestr())
5484 label='log.changeset changeset.%s' % p.phasestr())
5481 ui.write(' '.join(p.tags()), label='log.tag')
5485 ui.write(' '.join(p.tags()), label='log.tag')
5482 if p.bookmarks():
5486 if p.bookmarks():
5483 marks.extend(p.bookmarks())
5487 marks.extend(p.bookmarks())
5484 if p.rev() == -1:
5488 if p.rev() == -1:
5485 if not len(repo):
5489 if not len(repo):
5486 ui.write(_(' (empty repository)'))
5490 ui.write(_(' (empty repository)'))
5487 else:
5491 else:
5488 ui.write(_(' (no revision checked out)'))
5492 ui.write(_(' (no revision checked out)'))
5489 ui.write('\n')
5493 ui.write('\n')
5490 if p.description():
5494 if p.description():
5491 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5495 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5492 label='log.summary')
5496 label='log.summary')
5493
5497
5494 branch = ctx.branch()
5498 branch = ctx.branch()
5495 bheads = repo.branchheads(branch)
5499 bheads = repo.branchheads(branch)
5496 # i18n: column positioning for "hg summary"
5500 # i18n: column positioning for "hg summary"
5497 m = _('branch: %s\n') % branch
5501 m = _('branch: %s\n') % branch
5498 if branch != 'default':
5502 if branch != 'default':
5499 ui.write(m, label='log.branch')
5503 ui.write(m, label='log.branch')
5500 else:
5504 else:
5501 ui.status(m, label='log.branch')
5505 ui.status(m, label='log.branch')
5502
5506
5503 if marks:
5507 if marks:
5504 current = repo._bookmarkcurrent
5508 current = repo._bookmarkcurrent
5505 # i18n: column positioning for "hg summary"
5509 # i18n: column positioning for "hg summary"
5506 ui.write(_('bookmarks:'), label='log.bookmark')
5510 ui.write(_('bookmarks:'), label='log.bookmark')
5507 if current is not None:
5511 if current is not None:
5508 try:
5512 try:
5509 marks.remove(current)
5513 marks.remove(current)
5510 ui.write(' *' + current, label='bookmarks.current')
5514 ui.write(' *' + current, label='bookmarks.current')
5511 except ValueError:
5515 except ValueError:
5512 # current bookmark not in parent ctx marks
5516 # current bookmark not in parent ctx marks
5513 pass
5517 pass
5514 for m in marks:
5518 for m in marks:
5515 ui.write(' ' + m, label='log.bookmark')
5519 ui.write(' ' + m, label='log.bookmark')
5516 ui.write('\n', label='log.bookmark')
5520 ui.write('\n', label='log.bookmark')
5517
5521
5518 st = list(repo.status(unknown=True))[:6]
5522 st = list(repo.status(unknown=True))[:6]
5519
5523
5520 c = repo.dirstate.copies()
5524 c = repo.dirstate.copies()
5521 copied, renamed = [], []
5525 copied, renamed = [], []
5522 for d, s in c.iteritems():
5526 for d, s in c.iteritems():
5523 if s in st[2]:
5527 if s in st[2]:
5524 st[2].remove(s)
5528 st[2].remove(s)
5525 renamed.append(d)
5529 renamed.append(d)
5526 else:
5530 else:
5527 copied.append(d)
5531 copied.append(d)
5528 if d in st[1]:
5532 if d in st[1]:
5529 st[1].remove(d)
5533 st[1].remove(d)
5530 st.insert(3, renamed)
5534 st.insert(3, renamed)
5531 st.insert(4, copied)
5535 st.insert(4, copied)
5532
5536
5533 ms = mergemod.mergestate(repo)
5537 ms = mergemod.mergestate(repo)
5534 st.append([f for f in ms if ms[f] == 'u'])
5538 st.append([f for f in ms if ms[f] == 'u'])
5535
5539
5536 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5540 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5537 st.append(subs)
5541 st.append(subs)
5538
5542
5539 labels = [ui.label(_('%d modified'), 'status.modified'),
5543 labels = [ui.label(_('%d modified'), 'status.modified'),
5540 ui.label(_('%d added'), 'status.added'),
5544 ui.label(_('%d added'), 'status.added'),
5541 ui.label(_('%d removed'), 'status.removed'),
5545 ui.label(_('%d removed'), 'status.removed'),
5542 ui.label(_('%d renamed'), 'status.copied'),
5546 ui.label(_('%d renamed'), 'status.copied'),
5543 ui.label(_('%d copied'), 'status.copied'),
5547 ui.label(_('%d copied'), 'status.copied'),
5544 ui.label(_('%d deleted'), 'status.deleted'),
5548 ui.label(_('%d deleted'), 'status.deleted'),
5545 ui.label(_('%d unknown'), 'status.unknown'),
5549 ui.label(_('%d unknown'), 'status.unknown'),
5546 ui.label(_('%d ignored'), 'status.ignored'),
5550 ui.label(_('%d ignored'), 'status.ignored'),
5547 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5551 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5548 ui.label(_('%d subrepos'), 'status.modified')]
5552 ui.label(_('%d subrepos'), 'status.modified')]
5549 t = []
5553 t = []
5550 for s, l in zip(st, labels):
5554 for s, l in zip(st, labels):
5551 if s:
5555 if s:
5552 t.append(l % len(s))
5556 t.append(l % len(s))
5553
5557
5554 t = ', '.join(t)
5558 t = ', '.join(t)
5555 cleanworkdir = False
5559 cleanworkdir = False
5556
5560
5557 if len(parents) > 1:
5561 if len(parents) > 1:
5558 t += _(' (merge)')
5562 t += _(' (merge)')
5559 elif branch != parents[0].branch():
5563 elif branch != parents[0].branch():
5560 t += _(' (new branch)')
5564 t += _(' (new branch)')
5561 elif (parents[0].closesbranch() and
5565 elif (parents[0].closesbranch() and
5562 pnode in repo.branchheads(branch, closed=True)):
5566 pnode in repo.branchheads(branch, closed=True)):
5563 t += _(' (head closed)')
5567 t += _(' (head closed)')
5564 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5568 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5565 t += _(' (clean)')
5569 t += _(' (clean)')
5566 cleanworkdir = True
5570 cleanworkdir = True
5567 elif pnode not in bheads:
5571 elif pnode not in bheads:
5568 t += _(' (new branch head)')
5572 t += _(' (new branch head)')
5569
5573
5570 if cleanworkdir:
5574 if cleanworkdir:
5571 # i18n: column positioning for "hg summary"
5575 # i18n: column positioning for "hg summary"
5572 ui.status(_('commit: %s\n') % t.strip())
5576 ui.status(_('commit: %s\n') % t.strip())
5573 else:
5577 else:
5574 # i18n: column positioning for "hg summary"
5578 # i18n: column positioning for "hg summary"
5575 ui.write(_('commit: %s\n') % t.strip())
5579 ui.write(_('commit: %s\n') % t.strip())
5576
5580
5577 # all ancestors of branch heads - all ancestors of parent = new csets
5581 # all ancestors of branch heads - all ancestors of parent = new csets
5578 new = [0] * len(repo)
5582 new = [0] * len(repo)
5579 cl = repo.changelog
5583 cl = repo.changelog
5580 for a in [cl.rev(n) for n in bheads]:
5584 for a in [cl.rev(n) for n in bheads]:
5581 new[a] = 1
5585 new[a] = 1
5582 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5586 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5583 new[a] = 1
5587 new[a] = 1
5584 for a in [p.rev() for p in parents]:
5588 for a in [p.rev() for p in parents]:
5585 if a >= 0:
5589 if a >= 0:
5586 new[a] = 0
5590 new[a] = 0
5587 for a in cl.ancestors([p.rev() for p in parents]):
5591 for a in cl.ancestors([p.rev() for p in parents]):
5588 new[a] = 0
5592 new[a] = 0
5589 new = sum(new)
5593 new = sum(new)
5590
5594
5591 if new == 0:
5595 if new == 0:
5592 # i18n: column positioning for "hg summary"
5596 # i18n: column positioning for "hg summary"
5593 ui.status(_('update: (current)\n'))
5597 ui.status(_('update: (current)\n'))
5594 elif pnode not in bheads:
5598 elif pnode not in bheads:
5595 # i18n: column positioning for "hg summary"
5599 # i18n: column positioning for "hg summary"
5596 ui.write(_('update: %d new changesets (update)\n') % new)
5600 ui.write(_('update: %d new changesets (update)\n') % new)
5597 else:
5601 else:
5598 # i18n: column positioning for "hg summary"
5602 # i18n: column positioning for "hg summary"
5599 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5603 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5600 (new, len(bheads)))
5604 (new, len(bheads)))
5601
5605
5602 if opts.get('remote'):
5606 if opts.get('remote'):
5603 t = []
5607 t = []
5604 source, branches = hg.parseurl(ui.expandpath('default'))
5608 source, branches = hg.parseurl(ui.expandpath('default'))
5605 other = hg.peer(repo, {}, source)
5609 other = hg.peer(repo, {}, source)
5606 revs, checkout = hg.addbranchrevs(repo, other, branches,
5610 revs, checkout = hg.addbranchrevs(repo, other, branches,
5607 opts.get('rev'))
5611 opts.get('rev'))
5608 ui.debug('comparing with %s\n' % util.hidepassword(source))
5612 ui.debug('comparing with %s\n' % util.hidepassword(source))
5609 repo.ui.pushbuffer()
5613 repo.ui.pushbuffer()
5610 commoninc = discovery.findcommonincoming(repo, other)
5614 commoninc = discovery.findcommonincoming(repo, other)
5611 _common, incoming, _rheads = commoninc
5615 _common, incoming, _rheads = commoninc
5612 repo.ui.popbuffer()
5616 repo.ui.popbuffer()
5613 if incoming:
5617 if incoming:
5614 t.append(_('1 or more incoming'))
5618 t.append(_('1 or more incoming'))
5615
5619
5616 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5620 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5617 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5621 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5618 if source != dest:
5622 if source != dest:
5619 other = hg.peer(repo, {}, dest)
5623 other = hg.peer(repo, {}, dest)
5620 commoninc = None
5624 commoninc = None
5621 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5625 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5622 repo.ui.pushbuffer()
5626 repo.ui.pushbuffer()
5623 outgoing = discovery.findcommonoutgoing(repo, other,
5627 outgoing = discovery.findcommonoutgoing(repo, other,
5624 commoninc=commoninc)
5628 commoninc=commoninc)
5625 repo.ui.popbuffer()
5629 repo.ui.popbuffer()
5626 o = outgoing.missing
5630 o = outgoing.missing
5627 if o:
5631 if o:
5628 t.append(_('%d outgoing') % len(o))
5632 t.append(_('%d outgoing') % len(o))
5629 if 'bookmarks' in other.listkeys('namespaces'):
5633 if 'bookmarks' in other.listkeys('namespaces'):
5630 lmarks = repo.listkeys('bookmarks')
5634 lmarks = repo.listkeys('bookmarks')
5631 rmarks = other.listkeys('bookmarks')
5635 rmarks = other.listkeys('bookmarks')
5632 diff = set(rmarks) - set(lmarks)
5636 diff = set(rmarks) - set(lmarks)
5633 if len(diff) > 0:
5637 if len(diff) > 0:
5634 t.append(_('%d incoming bookmarks') % len(diff))
5638 t.append(_('%d incoming bookmarks') % len(diff))
5635 diff = set(lmarks) - set(rmarks)
5639 diff = set(lmarks) - set(rmarks)
5636 if len(diff) > 0:
5640 if len(diff) > 0:
5637 t.append(_('%d outgoing bookmarks') % len(diff))
5641 t.append(_('%d outgoing bookmarks') % len(diff))
5638
5642
5639 if t:
5643 if t:
5640 # i18n: column positioning for "hg summary"
5644 # i18n: column positioning for "hg summary"
5641 ui.write(_('remote: %s\n') % (', '.join(t)))
5645 ui.write(_('remote: %s\n') % (', '.join(t)))
5642 else:
5646 else:
5643 # i18n: column positioning for "hg summary"
5647 # i18n: column positioning for "hg summary"
5644 ui.status(_('remote: (synced)\n'))
5648 ui.status(_('remote: (synced)\n'))
5645
5649
5646 @command('tag',
5650 @command('tag',
5647 [('f', 'force', None, _('force tag')),
5651 [('f', 'force', None, _('force tag')),
5648 ('l', 'local', None, _('make the tag local')),
5652 ('l', 'local', None, _('make the tag local')),
5649 ('r', 'rev', '', _('revision to tag'), _('REV')),
5653 ('r', 'rev', '', _('revision to tag'), _('REV')),
5650 ('', 'remove', None, _('remove a tag')),
5654 ('', 'remove', None, _('remove a tag')),
5651 # -l/--local is already there, commitopts cannot be used
5655 # -l/--local is already there, commitopts cannot be used
5652 ('e', 'edit', None, _('edit commit message')),
5656 ('e', 'edit', None, _('edit commit message')),
5653 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5657 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5654 ] + commitopts2,
5658 ] + commitopts2,
5655 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5659 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5656 def tag(ui, repo, name1, *names, **opts):
5660 def tag(ui, repo, name1, *names, **opts):
5657 """add one or more tags for the current or given revision
5661 """add one or more tags for the current or given revision
5658
5662
5659 Name a particular revision using <name>.
5663 Name a particular revision using <name>.
5660
5664
5661 Tags are used to name particular revisions of the repository and are
5665 Tags are used to name particular revisions of the repository and are
5662 very useful to compare different revisions, to go back to significant
5666 very useful to compare different revisions, to go back to significant
5663 earlier versions or to mark branch points as releases, etc. Changing
5667 earlier versions or to mark branch points as releases, etc. Changing
5664 an existing tag is normally disallowed; use -f/--force to override.
5668 an existing tag is normally disallowed; use -f/--force to override.
5665
5669
5666 If no revision is given, the parent of the working directory is
5670 If no revision is given, the parent of the working directory is
5667 used, or tip if no revision is checked out.
5671 used, or tip if no revision is checked out.
5668
5672
5669 To facilitate version control, distribution, and merging of tags,
5673 To facilitate version control, distribution, and merging of tags,
5670 they are stored as a file named ".hgtags" which is managed similarly
5674 they are stored as a file named ".hgtags" which is managed similarly
5671 to other project files and can be hand-edited if necessary. This
5675 to other project files and can be hand-edited if necessary. This
5672 also means that tagging creates a new commit. The file
5676 also means that tagging creates a new commit. The file
5673 ".hg/localtags" is used for local tags (not shared among
5677 ".hg/localtags" is used for local tags (not shared among
5674 repositories).
5678 repositories).
5675
5679
5676 Tag commits are usually made at the head of a branch. If the parent
5680 Tag commits are usually made at the head of a branch. If the parent
5677 of the working directory is not a branch head, :hg:`tag` aborts; use
5681 of the working directory is not a branch head, :hg:`tag` aborts; use
5678 -f/--force to force the tag commit to be based on a non-head
5682 -f/--force to force the tag commit to be based on a non-head
5679 changeset.
5683 changeset.
5680
5684
5681 See :hg:`help dates` for a list of formats valid for -d/--date.
5685 See :hg:`help dates` for a list of formats valid for -d/--date.
5682
5686
5683 Since tag names have priority over branch names during revision
5687 Since tag names have priority over branch names during revision
5684 lookup, using an existing branch name as a tag name is discouraged.
5688 lookup, using an existing branch name as a tag name is discouraged.
5685
5689
5686 Returns 0 on success.
5690 Returns 0 on success.
5687 """
5691 """
5688 wlock = lock = None
5692 wlock = lock = None
5689 try:
5693 try:
5690 wlock = repo.wlock()
5694 wlock = repo.wlock()
5691 lock = repo.lock()
5695 lock = repo.lock()
5692 rev_ = "."
5696 rev_ = "."
5693 names = [t.strip() for t in (name1,) + names]
5697 names = [t.strip() for t in (name1,) + names]
5694 if len(names) != len(set(names)):
5698 if len(names) != len(set(names)):
5695 raise util.Abort(_('tag names must be unique'))
5699 raise util.Abort(_('tag names must be unique'))
5696 for n in names:
5700 for n in names:
5697 scmutil.checknewlabel(repo, n, 'tag')
5701 scmutil.checknewlabel(repo, n, 'tag')
5698 if not n:
5702 if not n:
5699 raise util.Abort(_('tag names cannot consist entirely of '
5703 raise util.Abort(_('tag names cannot consist entirely of '
5700 'whitespace'))
5704 'whitespace'))
5701 if opts.get('rev') and opts.get('remove'):
5705 if opts.get('rev') and opts.get('remove'):
5702 raise util.Abort(_("--rev and --remove are incompatible"))
5706 raise util.Abort(_("--rev and --remove are incompatible"))
5703 if opts.get('rev'):
5707 if opts.get('rev'):
5704 rev_ = opts['rev']
5708 rev_ = opts['rev']
5705 message = opts.get('message')
5709 message = opts.get('message')
5706 if opts.get('remove'):
5710 if opts.get('remove'):
5707 expectedtype = opts.get('local') and 'local' or 'global'
5711 expectedtype = opts.get('local') and 'local' or 'global'
5708 for n in names:
5712 for n in names:
5709 if not repo.tagtype(n):
5713 if not repo.tagtype(n):
5710 raise util.Abort(_("tag '%s' does not exist") % n)
5714 raise util.Abort(_("tag '%s' does not exist") % n)
5711 if repo.tagtype(n) != expectedtype:
5715 if repo.tagtype(n) != expectedtype:
5712 if expectedtype == 'global':
5716 if expectedtype == 'global':
5713 raise util.Abort(_("tag '%s' is not a global tag") % n)
5717 raise util.Abort(_("tag '%s' is not a global tag") % n)
5714 else:
5718 else:
5715 raise util.Abort(_("tag '%s' is not a local tag") % n)
5719 raise util.Abort(_("tag '%s' is not a local tag") % n)
5716 rev_ = nullid
5720 rev_ = nullid
5717 if not message:
5721 if not message:
5718 # we don't translate commit messages
5722 # we don't translate commit messages
5719 message = 'Removed tag %s' % ', '.join(names)
5723 message = 'Removed tag %s' % ', '.join(names)
5720 elif not opts.get('force'):
5724 elif not opts.get('force'):
5721 for n in names:
5725 for n in names:
5722 if n in repo.tags():
5726 if n in repo.tags():
5723 raise util.Abort(_("tag '%s' already exists "
5727 raise util.Abort(_("tag '%s' already exists "
5724 "(use -f to force)") % n)
5728 "(use -f to force)") % n)
5725 if not opts.get('local'):
5729 if not opts.get('local'):
5726 p1, p2 = repo.dirstate.parents()
5730 p1, p2 = repo.dirstate.parents()
5727 if p2 != nullid:
5731 if p2 != nullid:
5728 raise util.Abort(_('uncommitted merge'))
5732 raise util.Abort(_('uncommitted merge'))
5729 bheads = repo.branchheads()
5733 bheads = repo.branchheads()
5730 if not opts.get('force') and bheads and p1 not in bheads:
5734 if not opts.get('force') and bheads and p1 not in bheads:
5731 raise util.Abort(_('not at a branch head (use -f to force)'))
5735 raise util.Abort(_('not at a branch head (use -f to force)'))
5732 r = scmutil.revsingle(repo, rev_).node()
5736 r = scmutil.revsingle(repo, rev_).node()
5733
5737
5734 if not message:
5738 if not message:
5735 # we don't translate commit messages
5739 # we don't translate commit messages
5736 message = ('Added tag %s for changeset %s' %
5740 message = ('Added tag %s for changeset %s' %
5737 (', '.join(names), short(r)))
5741 (', '.join(names), short(r)))
5738
5742
5739 date = opts.get('date')
5743 date = opts.get('date')
5740 if date:
5744 if date:
5741 date = util.parsedate(date)
5745 date = util.parsedate(date)
5742
5746
5743 if opts.get('edit'):
5747 if opts.get('edit'):
5744 message = ui.edit(message, ui.username())
5748 message = ui.edit(message, ui.username())
5745
5749
5746 # don't allow tagging the null rev
5750 # don't allow tagging the null rev
5747 if (not opts.get('remove') and
5751 if (not opts.get('remove') and
5748 scmutil.revsingle(repo, rev_).rev() == nullrev):
5752 scmutil.revsingle(repo, rev_).rev() == nullrev):
5749 raise util.Abort(_("null revision specified"))
5753 raise util.Abort(_("null revision specified"))
5750
5754
5751 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5755 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5752 finally:
5756 finally:
5753 release(lock, wlock)
5757 release(lock, wlock)
5754
5758
5755 @command('tags', [], '')
5759 @command('tags', [], '')
5756 def tags(ui, repo, **opts):
5760 def tags(ui, repo, **opts):
5757 """list repository tags
5761 """list repository tags
5758
5762
5759 This lists both regular and local tags. When the -v/--verbose
5763 This lists both regular and local tags. When the -v/--verbose
5760 switch is used, a third column "local" is printed for local tags.
5764 switch is used, a third column "local" is printed for local tags.
5761
5765
5762 Returns 0 on success.
5766 Returns 0 on success.
5763 """
5767 """
5764
5768
5765 fm = ui.formatter('tags', opts)
5769 fm = ui.formatter('tags', opts)
5766 hexfunc = ui.debugflag and hex or short
5770 hexfunc = ui.debugflag and hex or short
5767 tagtype = ""
5771 tagtype = ""
5768
5772
5769 for t, n in reversed(repo.tagslist()):
5773 for t, n in reversed(repo.tagslist()):
5770 hn = hexfunc(n)
5774 hn = hexfunc(n)
5771 label = 'tags.normal'
5775 label = 'tags.normal'
5772 tagtype = ''
5776 tagtype = ''
5773 if repo.tagtype(t) == 'local':
5777 if repo.tagtype(t) == 'local':
5774 label = 'tags.local'
5778 label = 'tags.local'
5775 tagtype = 'local'
5779 tagtype = 'local'
5776
5780
5777 fm.startitem()
5781 fm.startitem()
5778 fm.write('tag', '%s', t, label=label)
5782 fm.write('tag', '%s', t, label=label)
5779 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5783 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5780 fm.condwrite(not ui.quiet, 'rev id', fmt,
5784 fm.condwrite(not ui.quiet, 'rev id', fmt,
5781 repo.changelog.rev(n), hn, label=label)
5785 repo.changelog.rev(n), hn, label=label)
5782 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5786 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5783 tagtype, label=label)
5787 tagtype, label=label)
5784 fm.plain('\n')
5788 fm.plain('\n')
5785 fm.end()
5789 fm.end()
5786
5790
5787 @command('tip',
5791 @command('tip',
5788 [('p', 'patch', None, _('show patch')),
5792 [('p', 'patch', None, _('show patch')),
5789 ('g', 'git', None, _('use git extended diff format')),
5793 ('g', 'git', None, _('use git extended diff format')),
5790 ] + templateopts,
5794 ] + templateopts,
5791 _('[-p] [-g]'))
5795 _('[-p] [-g]'))
5792 def tip(ui, repo, **opts):
5796 def tip(ui, repo, **opts):
5793 """show the tip revision
5797 """show the tip revision
5794
5798
5795 The tip revision (usually just called the tip) is the changeset
5799 The tip revision (usually just called the tip) is the changeset
5796 most recently added to the repository (and therefore the most
5800 most recently added to the repository (and therefore the most
5797 recently changed head).
5801 recently changed head).
5798
5802
5799 If you have just made a commit, that commit will be the tip. If
5803 If you have just made a commit, that commit will be the tip. If
5800 you have just pulled changes from another repository, the tip of
5804 you have just pulled changes from another repository, the tip of
5801 that repository becomes the current tip. The "tip" tag is special
5805 that repository becomes the current tip. The "tip" tag is special
5802 and cannot be renamed or assigned to a different changeset.
5806 and cannot be renamed or assigned to a different changeset.
5803
5807
5804 Returns 0 on success.
5808 Returns 0 on success.
5805 """
5809 """
5806 displayer = cmdutil.show_changeset(ui, repo, opts)
5810 displayer = cmdutil.show_changeset(ui, repo, opts)
5807 displayer.show(repo[len(repo) - 1])
5811 displayer.show(repo[len(repo) - 1])
5808 displayer.close()
5812 displayer.close()
5809
5813
5810 @command('unbundle',
5814 @command('unbundle',
5811 [('u', 'update', None,
5815 [('u', 'update', None,
5812 _('update to new branch head if changesets were unbundled'))],
5816 _('update to new branch head if changesets were unbundled'))],
5813 _('[-u] FILE...'))
5817 _('[-u] FILE...'))
5814 def unbundle(ui, repo, fname1, *fnames, **opts):
5818 def unbundle(ui, repo, fname1, *fnames, **opts):
5815 """apply one or more changegroup files
5819 """apply one or more changegroup files
5816
5820
5817 Apply one or more compressed changegroup files generated by the
5821 Apply one or more compressed changegroup files generated by the
5818 bundle command.
5822 bundle command.
5819
5823
5820 Returns 0 on success, 1 if an update has unresolved files.
5824 Returns 0 on success, 1 if an update has unresolved files.
5821 """
5825 """
5822 fnames = (fname1,) + fnames
5826 fnames = (fname1,) + fnames
5823
5827
5824 lock = repo.lock()
5828 lock = repo.lock()
5825 wc = repo['.']
5829 wc = repo['.']
5826 try:
5830 try:
5827 for fname in fnames:
5831 for fname in fnames:
5828 f = hg.openpath(ui, fname)
5832 f = hg.openpath(ui, fname)
5829 gen = changegroup.readbundle(f, fname)
5833 gen = changegroup.readbundle(f, fname)
5830 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5834 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5831 finally:
5835 finally:
5832 lock.release()
5836 lock.release()
5833 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5837 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5834 return postincoming(ui, repo, modheads, opts.get('update'), None)
5838 return postincoming(ui, repo, modheads, opts.get('update'), None)
5835
5839
5836 @command('^update|up|checkout|co',
5840 @command('^update|up|checkout|co',
5837 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5841 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5838 ('c', 'check', None,
5842 ('c', 'check', None,
5839 _('update across branches if no uncommitted changes')),
5843 _('update across branches if no uncommitted changes')),
5840 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5844 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5841 ('r', 'rev', '', _('revision'), _('REV'))],
5845 ('r', 'rev', '', _('revision'), _('REV'))],
5842 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5846 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5843 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5847 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5844 """update working directory (or switch revisions)
5848 """update working directory (or switch revisions)
5845
5849
5846 Update the repository's working directory to the specified
5850 Update the repository's working directory to the specified
5847 changeset. If no changeset is specified, update to the tip of the
5851 changeset. If no changeset is specified, update to the tip of the
5848 current named branch and move the current bookmark (see :hg:`help
5852 current named branch and move the current bookmark (see :hg:`help
5849 bookmarks`).
5853 bookmarks`).
5850
5854
5851 Update sets the working directory's parent revision to the specified
5855 Update sets the working directory's parent revision to the specified
5852 changeset (see :hg:`help parents`).
5856 changeset (see :hg:`help parents`).
5853
5857
5854 If the changeset is not a descendant or ancestor of the working
5858 If the changeset is not a descendant or ancestor of the working
5855 directory's parent, the update is aborted. With the -c/--check
5859 directory's parent, the update is aborted. With the -c/--check
5856 option, the working directory is checked for uncommitted changes; if
5860 option, the working directory is checked for uncommitted changes; if
5857 none are found, the working directory is updated to the specified
5861 none are found, the working directory is updated to the specified
5858 changeset.
5862 changeset.
5859
5863
5860 .. container:: verbose
5864 .. container:: verbose
5861
5865
5862 The following rules apply when the working directory contains
5866 The following rules apply when the working directory contains
5863 uncommitted changes:
5867 uncommitted changes:
5864
5868
5865 1. If neither -c/--check nor -C/--clean is specified, and if
5869 1. If neither -c/--check nor -C/--clean is specified, and if
5866 the requested changeset is an ancestor or descendant of
5870 the requested changeset is an ancestor or descendant of
5867 the working directory's parent, the uncommitted changes
5871 the working directory's parent, the uncommitted changes
5868 are merged into the requested changeset and the merged
5872 are merged into the requested changeset and the merged
5869 result is left uncommitted. If the requested changeset is
5873 result is left uncommitted. If the requested changeset is
5870 not an ancestor or descendant (that is, it is on another
5874 not an ancestor or descendant (that is, it is on another
5871 branch), the update is aborted and the uncommitted changes
5875 branch), the update is aborted and the uncommitted changes
5872 are preserved.
5876 are preserved.
5873
5877
5874 2. With the -c/--check option, the update is aborted and the
5878 2. With the -c/--check option, the update is aborted and the
5875 uncommitted changes are preserved.
5879 uncommitted changes are preserved.
5876
5880
5877 3. With the -C/--clean option, uncommitted changes are discarded and
5881 3. With the -C/--clean option, uncommitted changes are discarded and
5878 the working directory is updated to the requested changeset.
5882 the working directory is updated to the requested changeset.
5879
5883
5880 To cancel an uncommitted merge (and lose your changes), use
5884 To cancel an uncommitted merge (and lose your changes), use
5881 :hg:`update --clean .`.
5885 :hg:`update --clean .`.
5882
5886
5883 Use null as the changeset to remove the working directory (like
5887 Use null as the changeset to remove the working directory (like
5884 :hg:`clone -U`).
5888 :hg:`clone -U`).
5885
5889
5886 If you want to revert just one file to an older revision, use
5890 If you want to revert just one file to an older revision, use
5887 :hg:`revert [-r REV] NAME`.
5891 :hg:`revert [-r REV] NAME`.
5888
5892
5889 See :hg:`help dates` for a list of formats valid for -d/--date.
5893 See :hg:`help dates` for a list of formats valid for -d/--date.
5890
5894
5891 Returns 0 on success, 1 if there are unresolved files.
5895 Returns 0 on success, 1 if there are unresolved files.
5892 """
5896 """
5893 if rev and node:
5897 if rev and node:
5894 raise util.Abort(_("please specify just one revision"))
5898 raise util.Abort(_("please specify just one revision"))
5895
5899
5896 if rev is None or rev == '':
5900 if rev is None or rev == '':
5897 rev = node
5901 rev = node
5898
5902
5899 # with no argument, we also move the current bookmark, if any
5903 # with no argument, we also move the current bookmark, if any
5900 movemarkfrom = None
5904 movemarkfrom = None
5901 if rev is None:
5905 if rev is None:
5902 movemarkfrom = repo['.'].node()
5906 movemarkfrom = repo['.'].node()
5903
5907
5904 # if we defined a bookmark, we have to remember the original bookmark name
5908 # if we defined a bookmark, we have to remember the original bookmark name
5905 brev = rev
5909 brev = rev
5906 rev = scmutil.revsingle(repo, rev, rev).rev()
5910 rev = scmutil.revsingle(repo, rev, rev).rev()
5907
5911
5908 if check and clean:
5912 if check and clean:
5909 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5913 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5910
5914
5911 if date:
5915 if date:
5912 if rev is not None:
5916 if rev is not None:
5913 raise util.Abort(_("you can't specify a revision and a date"))
5917 raise util.Abort(_("you can't specify a revision and a date"))
5914 rev = cmdutil.finddate(ui, repo, date)
5918 rev = cmdutil.finddate(ui, repo, date)
5915
5919
5916 if check:
5920 if check:
5917 c = repo[None]
5921 c = repo[None]
5918 if c.dirty(merge=False, branch=False, missing=True):
5922 if c.dirty(merge=False, branch=False, missing=True):
5919 raise util.Abort(_("uncommitted local changes"))
5923 raise util.Abort(_("uncommitted local changes"))
5920 if rev is None:
5924 if rev is None:
5921 rev = repo[repo[None].branch()].rev()
5925 rev = repo[repo[None].branch()].rev()
5922 mergemod._checkunknown(repo, repo[None], repo[rev])
5926 mergemod._checkunknown(repo, repo[None], repo[rev])
5923
5927
5924 if clean:
5928 if clean:
5925 ret = hg.clean(repo, rev)
5929 ret = hg.clean(repo, rev)
5926 else:
5930 else:
5927 ret = hg.update(repo, rev)
5931 ret = hg.update(repo, rev)
5928
5932
5929 if not ret and movemarkfrom:
5933 if not ret and movemarkfrom:
5930 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5934 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5931 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5935 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5932 elif brev in repo._bookmarks:
5936 elif brev in repo._bookmarks:
5933 bookmarks.setcurrent(repo, brev)
5937 bookmarks.setcurrent(repo, brev)
5934 elif brev:
5938 elif brev:
5935 bookmarks.unsetcurrent(repo)
5939 bookmarks.unsetcurrent(repo)
5936
5940
5937 return ret
5941 return ret
5938
5942
5939 @command('verify', [])
5943 @command('verify', [])
5940 def verify(ui, repo):
5944 def verify(ui, repo):
5941 """verify the integrity of the repository
5945 """verify the integrity of the repository
5942
5946
5943 Verify the integrity of the current repository.
5947 Verify the integrity of the current repository.
5944
5948
5945 This will perform an extensive check of the repository's
5949 This will perform an extensive check of the repository's
5946 integrity, validating the hashes and checksums of each entry in
5950 integrity, validating the hashes and checksums of each entry in
5947 the changelog, manifest, and tracked files, as well as the
5951 the changelog, manifest, and tracked files, as well as the
5948 integrity of their crosslinks and indices.
5952 integrity of their crosslinks and indices.
5949
5953
5950 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5954 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5951 for more information about recovery from corruption of the
5955 for more information about recovery from corruption of the
5952 repository.
5956 repository.
5953
5957
5954 Returns 0 on success, 1 if errors are encountered.
5958 Returns 0 on success, 1 if errors are encountered.
5955 """
5959 """
5956 return hg.verify(repo)
5960 return hg.verify(repo)
5957
5961
5958 @command('version', [])
5962 @command('version', [])
5959 def version_(ui):
5963 def version_(ui):
5960 """output version and copyright information"""
5964 """output version and copyright information"""
5961 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5965 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5962 % util.version())
5966 % util.version())
5963 ui.status(_(
5967 ui.status(_(
5964 "(see http://mercurial.selenic.com for more information)\n"
5968 "(see http://mercurial.selenic.com for more information)\n"
5965 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5969 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5966 "This is free software; see the source for copying conditions. "
5970 "This is free software; see the source for copying conditions. "
5967 "There is NO\nwarranty; "
5971 "There is NO\nwarranty; "
5968 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5972 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5969 ))
5973 ))
5970
5974
5971 norepo = ("clone init version help debugcommands debugcomplete"
5975 norepo = ("clone init version help debugcommands debugcomplete"
5972 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5976 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5973 " debugknown debuggetbundle debugbundle")
5977 " debugknown debuggetbundle debugbundle")
5974 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5978 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5975 " debugdata debugindex debugindexdot debugrevlog")
5979 " debugdata debugindex debugindexdot debugrevlog")
5976 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5980 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5977 " remove resolve status debugwalk")
5981 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now