##// END OF EJS Templates
tag: lock before tagging
Mads Kiilerich -
r15877:afd45993 default
parent child Browse files
Show More
@@ -1,5759 +1,5765 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import match as matchmod
16 import match as matchmod
17 import merge as mergemod
17 import merge as mergemod
18 import minirst, revset, fileset
18 import minirst, revset, fileset
19 import dagparser, context, simplemerge
19 import dagparser, context, simplemerge
20 import random, setdiscovery, treediscovery, dagutil
20 import random, setdiscovery, treediscovery, dagutil
21 import phases
21 import phases
22
22
23 table = {}
23 table = {}
24
24
25 command = cmdutil.command(table)
25 command = cmdutil.command(table)
26
26
27 # common command options
27 # common command options
28
28
29 globalopts = [
29 globalopts = [
30 ('R', 'repository', '',
30 ('R', 'repository', '',
31 _('repository root directory or name of overlay bundle file'),
31 _('repository root directory or name of overlay bundle file'),
32 _('REPO')),
32 _('REPO')),
33 ('', 'cwd', '',
33 ('', 'cwd', '',
34 _('change working directory'), _('DIR')),
34 _('change working directory'), _('DIR')),
35 ('y', 'noninteractive', None,
35 ('y', 'noninteractive', None,
36 _('do not prompt, automatically pick the first choice for all prompts')),
36 _('do not prompt, automatically pick the first choice for all prompts')),
37 ('q', 'quiet', None, _('suppress output')),
37 ('q', 'quiet', None, _('suppress output')),
38 ('v', 'verbose', None, _('enable additional output')),
38 ('v', 'verbose', None, _('enable additional output')),
39 ('', 'config', [],
39 ('', 'config', [],
40 _('set/override config option (use \'section.name=value\')'),
40 _('set/override config option (use \'section.name=value\')'),
41 _('CONFIG')),
41 _('CONFIG')),
42 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debugger', None, _('start debugger')),
43 ('', 'debugger', None, _('start debugger')),
44 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 _('ENCODE')),
45 _('ENCODE')),
46 ('', 'encodingmode', encoding.encodingmode,
46 ('', 'encodingmode', encoding.encodingmode,
47 _('set the charset encoding mode'), _('MODE')),
47 _('set the charset encoding mode'), _('MODE')),
48 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'time', None, _('time how long the command takes')),
49 ('', 'time', None, _('time how long the command takes')),
50 ('', 'profile', None, _('print command execution profile')),
50 ('', 'profile', None, _('print command execution profile')),
51 ('', 'version', None, _('output version information and exit')),
51 ('', 'version', None, _('output version information and exit')),
52 ('h', 'help', None, _('display help and exit')),
52 ('h', 'help', None, _('display help and exit')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ] + 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="")
177 opts.get('subrepos'), prefix="")
178 return rejected and 1 or 0
178 return rejected and 1 or 0
179
179
180 @command('addremove',
180 @command('addremove',
181 similarityopts + walkopts + dryrunopts,
181 similarityopts + walkopts + dryrunopts,
182 _('[OPTION]... [FILE]...'))
182 _('[OPTION]... [FILE]...'))
183 def addremove(ui, repo, *pats, **opts):
183 def addremove(ui, repo, *pats, **opts):
184 """add all new files, delete all missing files
184 """add all new files, delete all missing files
185
185
186 Add all new files and remove all missing files from the
186 Add all new files and remove all missing files from the
187 repository.
187 repository.
188
188
189 New files are ignored if they match any of the patterns in
189 New files are ignored if they match any of the patterns in
190 ``.hgignore``. As with add, these changes take effect at the next
190 ``.hgignore``. As with add, these changes take effect at the next
191 commit.
191 commit.
192
192
193 Use the -s/--similarity option to detect renamed files. With a
193 Use the -s/--similarity option to detect renamed files. With a
194 parameter greater than 0, this compares every removed file with
194 parameter greater than 0, this compares every removed file with
195 every added file and records those similar enough as renames. This
195 every added file and records those similar enough as renames. This
196 option takes a percentage between 0 (disabled) and 100 (files must
196 option takes a percentage between 0 (disabled) and 100 (files must
197 be identical) as its parameter. Detecting renamed files this way
197 be identical) as its parameter. Detecting renamed files this way
198 can be expensive. After using this option, :hg:`status -C` can be
198 can be expensive. After using this option, :hg:`status -C` can be
199 used to check which files were identified as moved or renamed.
199 used to check which files were identified as moved or renamed.
200
200
201 Returns 0 if all files are successfully added.
201 Returns 0 if all files are successfully added.
202 """
202 """
203 try:
203 try:
204 sim = float(opts.get('similarity') or 100)
204 sim = float(opts.get('similarity') or 100)
205 except ValueError:
205 except ValueError:
206 raise util.Abort(_('similarity must be a number'))
206 raise util.Abort(_('similarity must be a number'))
207 if sim < 0 or sim > 100:
207 if sim < 0 or sim > 100:
208 raise util.Abort(_('similarity must be between 0 and 100'))
208 raise util.Abort(_('similarity must be between 0 and 100'))
209 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
209 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
210
210
211 @command('^annotate|blame',
211 @command('^annotate|blame',
212 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
212 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
213 ('', 'follow', None,
213 ('', 'follow', None,
214 _('follow copies/renames and list the filename (DEPRECATED)')),
214 _('follow copies/renames and list the filename (DEPRECATED)')),
215 ('', 'no-follow', None, _("don't follow copies and renames")),
215 ('', 'no-follow', None, _("don't follow copies and renames")),
216 ('a', 'text', None, _('treat all files as text')),
216 ('a', 'text', None, _('treat all files as text')),
217 ('u', 'user', None, _('list the author (long with -v)')),
217 ('u', 'user', None, _('list the author (long with -v)')),
218 ('f', 'file', None, _('list the filename')),
218 ('f', 'file', None, _('list the filename')),
219 ('d', 'date', None, _('list the date (short with -q)')),
219 ('d', 'date', None, _('list the date (short with -q)')),
220 ('n', 'number', None, _('list the revision number (default)')),
220 ('n', 'number', None, _('list the revision number (default)')),
221 ('c', 'changeset', None, _('list the changeset')),
221 ('c', 'changeset', None, _('list the changeset')),
222 ('l', 'line-number', None, _('show line number at the first appearance'))
222 ('l', 'line-number', None, _('show line number at the first appearance'))
223 ] + diffwsopts + walkopts,
223 ] + diffwsopts + walkopts,
224 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
224 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
225 def annotate(ui, repo, *pats, **opts):
225 def annotate(ui, repo, *pats, **opts):
226 """show changeset information by line for each file
226 """show changeset information by line for each file
227
227
228 List changes in files, showing the revision id responsible for
228 List changes in files, showing the revision id responsible for
229 each line
229 each line
230
230
231 This command is useful for discovering when a change was made and
231 This command is useful for discovering when a change was made and
232 by whom.
232 by whom.
233
233
234 Without the -a/--text option, annotate will avoid processing files
234 Without the -a/--text option, annotate will avoid processing files
235 it detects as binary. With -a, annotate will annotate the file
235 it detects as binary. With -a, annotate will annotate the file
236 anyway, although the results will probably be neither useful
236 anyway, although the results will probably be neither useful
237 nor desirable.
237 nor desirable.
238
238
239 Returns 0 on success.
239 Returns 0 on success.
240 """
240 """
241 if opts.get('follow'):
241 if opts.get('follow'):
242 # --follow is deprecated and now just an alias for -f/--file
242 # --follow is deprecated and now just an alias for -f/--file
243 # to mimic the behavior of Mercurial before version 1.5
243 # to mimic the behavior of Mercurial before version 1.5
244 opts['file'] = True
244 opts['file'] = True
245
245
246 datefunc = ui.quiet and util.shortdate or util.datestr
246 datefunc = ui.quiet and util.shortdate or util.datestr
247 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
247 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
248
248
249 if not pats:
249 if not pats:
250 raise util.Abort(_('at least one filename or pattern is required'))
250 raise util.Abort(_('at least one filename or pattern is required'))
251
251
252 hexfn = ui.debugflag and hex or short
252 hexfn = ui.debugflag and hex or short
253
253
254 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
254 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
255 ('number', ' ', lambda x: str(x[0].rev())),
255 ('number', ' ', lambda x: str(x[0].rev())),
256 ('changeset', ' ', lambda x: hexfn(x[0].node())),
256 ('changeset', ' ', lambda x: hexfn(x[0].node())),
257 ('date', ' ', getdate),
257 ('date', ' ', getdate),
258 ('file', ' ', lambda x: x[0].path()),
258 ('file', ' ', lambda x: x[0].path()),
259 ('line_number', ':', lambda x: str(x[1])),
259 ('line_number', ':', lambda x: str(x[1])),
260 ]
260 ]
261
261
262 if (not opts.get('user') and not opts.get('changeset')
262 if (not opts.get('user') and not opts.get('changeset')
263 and not opts.get('date') and not opts.get('file')):
263 and not opts.get('date') and not opts.get('file')):
264 opts['number'] = True
264 opts['number'] = True
265
265
266 linenumber = opts.get('line_number') is not None
266 linenumber = opts.get('line_number') is not None
267 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
267 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
268 raise util.Abort(_('at least one of -n/-c is required for -l'))
268 raise util.Abort(_('at least one of -n/-c is required for -l'))
269
269
270 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
270 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
271 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
271 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
272
272
273 def bad(x, y):
273 def bad(x, y):
274 raise util.Abort("%s: %s" % (x, y))
274 raise util.Abort("%s: %s" % (x, y))
275
275
276 ctx = scmutil.revsingle(repo, opts.get('rev'))
276 ctx = scmutil.revsingle(repo, opts.get('rev'))
277 m = scmutil.match(ctx, pats, opts)
277 m = scmutil.match(ctx, pats, opts)
278 m.bad = bad
278 m.bad = bad
279 follow = not opts.get('no_follow')
279 follow = not opts.get('no_follow')
280 diffopts = patch.diffopts(ui, opts, section='annotate')
280 diffopts = patch.diffopts(ui, opts, section='annotate')
281 for abs in ctx.walk(m):
281 for abs in ctx.walk(m):
282 fctx = ctx[abs]
282 fctx = ctx[abs]
283 if not opts.get('text') and util.binary(fctx.data()):
283 if not opts.get('text') and util.binary(fctx.data()):
284 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
284 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
285 continue
285 continue
286
286
287 lines = fctx.annotate(follow=follow, linenumber=linenumber,
287 lines = fctx.annotate(follow=follow, linenumber=linenumber,
288 diffopts=diffopts)
288 diffopts=diffopts)
289 pieces = []
289 pieces = []
290
290
291 for f, sep in funcmap:
291 for f, sep in funcmap:
292 l = [f(n) for n, dummy in lines]
292 l = [f(n) for n, dummy in lines]
293 if l:
293 if l:
294 sized = [(x, encoding.colwidth(x)) for x in l]
294 sized = [(x, encoding.colwidth(x)) for x in l]
295 ml = max([w for x, w in sized])
295 ml = max([w for x, w in sized])
296 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
296 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
297 for x, w in sized])
297 for x, w in sized])
298
298
299 if pieces:
299 if pieces:
300 for p, l in zip(zip(*pieces), lines):
300 for p, l in zip(zip(*pieces), lines):
301 ui.write("%s: %s" % ("".join(p), l[1]))
301 ui.write("%s: %s" % ("".join(p), l[1]))
302
302
303 if lines and not lines[-1][1].endswith('\n'):
303 if lines and not lines[-1][1].endswith('\n'):
304 ui.write('\n')
304 ui.write('\n')
305
305
306 @command('archive',
306 @command('archive',
307 [('', 'no-decode', None, _('do not pass files through decoders')),
307 [('', 'no-decode', None, _('do not pass files through decoders')),
308 ('p', 'prefix', '', _('directory prefix for files in archive'),
308 ('p', 'prefix', '', _('directory prefix for files in archive'),
309 _('PREFIX')),
309 _('PREFIX')),
310 ('r', 'rev', '', _('revision to distribute'), _('REV')),
310 ('r', 'rev', '', _('revision to distribute'), _('REV')),
311 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
311 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
312 ] + subrepoopts + walkopts,
312 ] + subrepoopts + walkopts,
313 _('[OPTION]... DEST'))
313 _('[OPTION]... DEST'))
314 def archive(ui, repo, dest, **opts):
314 def archive(ui, repo, dest, **opts):
315 '''create an unversioned archive of a repository revision
315 '''create an unversioned archive of a repository revision
316
316
317 By default, the revision used is the parent of the working
317 By default, the revision used is the parent of the working
318 directory; use -r/--rev to specify a different revision.
318 directory; use -r/--rev to specify a different revision.
319
319
320 The archive type is automatically detected based on file
320 The archive type is automatically detected based on file
321 extension (or override using -t/--type).
321 extension (or override using -t/--type).
322
322
323 .. container:: verbose
323 .. container:: verbose
324
324
325 Examples:
325 Examples:
326
326
327 - create a zip file containing the 1.0 release::
327 - create a zip file containing the 1.0 release::
328
328
329 hg archive -r 1.0 project-1.0.zip
329 hg archive -r 1.0 project-1.0.zip
330
330
331 - create a tarball excluding .hg files::
331 - create a tarball excluding .hg files::
332
332
333 hg archive project.tar.gz -X ".hg*"
333 hg archive project.tar.gz -X ".hg*"
334
334
335 Valid types are:
335 Valid types are:
336
336
337 :``files``: a directory full of files (default)
337 :``files``: a directory full of files (default)
338 :``tar``: tar archive, uncompressed
338 :``tar``: tar archive, uncompressed
339 :``tbz2``: tar archive, compressed using bzip2
339 :``tbz2``: tar archive, compressed using bzip2
340 :``tgz``: tar archive, compressed using gzip
340 :``tgz``: tar archive, compressed using gzip
341 :``uzip``: zip archive, uncompressed
341 :``uzip``: zip archive, uncompressed
342 :``zip``: zip archive, compressed using deflate
342 :``zip``: zip archive, compressed using deflate
343
343
344 The exact name of the destination archive or directory is given
344 The exact name of the destination archive or directory is given
345 using a format string; see :hg:`help export` for details.
345 using a format string; see :hg:`help export` for details.
346
346
347 Each member added to an archive file has a directory prefix
347 Each member added to an archive file has a directory prefix
348 prepended. Use -p/--prefix to specify a format string for the
348 prepended. Use -p/--prefix to specify a format string for the
349 prefix. The default is the basename of the archive, with suffixes
349 prefix. The default is the basename of the archive, with suffixes
350 removed.
350 removed.
351
351
352 Returns 0 on success.
352 Returns 0 on success.
353 '''
353 '''
354
354
355 ctx = scmutil.revsingle(repo, opts.get('rev'))
355 ctx = scmutil.revsingle(repo, opts.get('rev'))
356 if not ctx:
356 if not ctx:
357 raise util.Abort(_('no working directory: please specify a revision'))
357 raise util.Abort(_('no working directory: please specify a revision'))
358 node = ctx.node()
358 node = ctx.node()
359 dest = cmdutil.makefilename(repo, dest, node)
359 dest = cmdutil.makefilename(repo, dest, node)
360 if os.path.realpath(dest) == repo.root:
360 if os.path.realpath(dest) == repo.root:
361 raise util.Abort(_('repository root cannot be destination'))
361 raise util.Abort(_('repository root cannot be destination'))
362
362
363 kind = opts.get('type') or archival.guesskind(dest) or 'files'
363 kind = opts.get('type') or archival.guesskind(dest) or 'files'
364 prefix = opts.get('prefix')
364 prefix = opts.get('prefix')
365
365
366 if dest == '-':
366 if dest == '-':
367 if kind == 'files':
367 if kind == 'files':
368 raise util.Abort(_('cannot archive plain files to stdout'))
368 raise util.Abort(_('cannot archive plain files to stdout'))
369 dest = cmdutil.makefileobj(repo, dest)
369 dest = cmdutil.makefileobj(repo, dest)
370 if not prefix:
370 if not prefix:
371 prefix = os.path.basename(repo.root) + '-%h'
371 prefix = os.path.basename(repo.root) + '-%h'
372
372
373 prefix = cmdutil.makefilename(repo, prefix, node)
373 prefix = cmdutil.makefilename(repo, prefix, node)
374 matchfn = scmutil.match(ctx, [], opts)
374 matchfn = scmutil.match(ctx, [], opts)
375 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
375 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
376 matchfn, prefix, subrepos=opts.get('subrepos'))
376 matchfn, prefix, subrepos=opts.get('subrepos'))
377
377
378 @command('backout',
378 @command('backout',
379 [('', 'merge', None, _('merge with old dirstate parent after backout')),
379 [('', 'merge', None, _('merge with old dirstate parent after backout')),
380 ('', 'parent', '',
380 ('', 'parent', '',
381 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
381 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
382 ('r', 'rev', '', _('revision to backout'), _('REV')),
382 ('r', 'rev', '', _('revision to backout'), _('REV')),
383 ] + mergetoolopts + walkopts + commitopts + commitopts2,
383 ] + mergetoolopts + walkopts + commitopts + commitopts2,
384 _('[OPTION]... [-r] REV'))
384 _('[OPTION]... [-r] REV'))
385 def backout(ui, repo, node=None, rev=None, **opts):
385 def backout(ui, repo, node=None, rev=None, **opts):
386 '''reverse effect of earlier changeset
386 '''reverse effect of earlier changeset
387
387
388 Prepare a new changeset with the effect of REV undone in the
388 Prepare a new changeset with the effect of REV undone in the
389 current working directory.
389 current working directory.
390
390
391 If REV is the parent of the working directory, then this new changeset
391 If REV is the parent of the working directory, then this new changeset
392 is committed automatically. Otherwise, hg needs to merge the
392 is committed automatically. Otherwise, hg needs to merge the
393 changes and the merged result is left uncommitted.
393 changes and the merged result is left uncommitted.
394
394
395 .. note::
395 .. note::
396 backout cannot be used to fix either an unwanted or
396 backout cannot be used to fix either an unwanted or
397 incorrect merge.
397 incorrect merge.
398
398
399 .. container:: verbose
399 .. container:: verbose
400
400
401 By default, the pending changeset will have one parent,
401 By default, the pending changeset will have one parent,
402 maintaining a linear history. With --merge, the pending
402 maintaining a linear history. With --merge, the pending
403 changeset will instead have two parents: the old parent of the
403 changeset will instead have two parents: the old parent of the
404 working directory and a new child of REV that simply undoes REV.
404 working directory and a new child of REV that simply undoes REV.
405
405
406 Before version 1.7, the behavior without --merge was equivalent
406 Before version 1.7, the behavior without --merge was equivalent
407 to specifying --merge followed by :hg:`update --clean .` to
407 to specifying --merge followed by :hg:`update --clean .` to
408 cancel the merge and leave the child of REV as a head to be
408 cancel the merge and leave the child of REV as a head to be
409 merged separately.
409 merged separately.
410
410
411 See :hg:`help dates` for a list of formats valid for -d/--date.
411 See :hg:`help dates` for a list of formats valid for -d/--date.
412
412
413 Returns 0 on success.
413 Returns 0 on success.
414 '''
414 '''
415 if rev and node:
415 if rev and node:
416 raise util.Abort(_("please specify just one revision"))
416 raise util.Abort(_("please specify just one revision"))
417
417
418 if not rev:
418 if not rev:
419 rev = node
419 rev = node
420
420
421 if not rev:
421 if not rev:
422 raise util.Abort(_("please specify a revision to backout"))
422 raise util.Abort(_("please specify a revision to backout"))
423
423
424 date = opts.get('date')
424 date = opts.get('date')
425 if date:
425 if date:
426 opts['date'] = util.parsedate(date)
426 opts['date'] = util.parsedate(date)
427
427
428 cmdutil.bailifchanged(repo)
428 cmdutil.bailifchanged(repo)
429 node = scmutil.revsingle(repo, rev).node()
429 node = scmutil.revsingle(repo, rev).node()
430
430
431 op1, op2 = repo.dirstate.parents()
431 op1, op2 = repo.dirstate.parents()
432 a = repo.changelog.ancestor(op1, node)
432 a = repo.changelog.ancestor(op1, node)
433 if a != node:
433 if a != node:
434 raise util.Abort(_('cannot backout change on a different branch'))
434 raise util.Abort(_('cannot backout change on a different branch'))
435
435
436 p1, p2 = repo.changelog.parents(node)
436 p1, p2 = repo.changelog.parents(node)
437 if p1 == nullid:
437 if p1 == nullid:
438 raise util.Abort(_('cannot backout a change with no parents'))
438 raise util.Abort(_('cannot backout a change with no parents'))
439 if p2 != nullid:
439 if p2 != nullid:
440 if not opts.get('parent'):
440 if not opts.get('parent'):
441 raise util.Abort(_('cannot backout a merge changeset'))
441 raise util.Abort(_('cannot backout a merge changeset'))
442 p = repo.lookup(opts['parent'])
442 p = repo.lookup(opts['parent'])
443 if p not in (p1, p2):
443 if p not in (p1, p2):
444 raise util.Abort(_('%s is not a parent of %s') %
444 raise util.Abort(_('%s is not a parent of %s') %
445 (short(p), short(node)))
445 (short(p), short(node)))
446 parent = p
446 parent = p
447 else:
447 else:
448 if opts.get('parent'):
448 if opts.get('parent'):
449 raise util.Abort(_('cannot use --parent on non-merge changeset'))
449 raise util.Abort(_('cannot use --parent on non-merge changeset'))
450 parent = p1
450 parent = p1
451
451
452 # the backout should appear on the same branch
452 # the backout should appear on the same branch
453 branch = repo.dirstate.branch()
453 branch = repo.dirstate.branch()
454 hg.clean(repo, node, show_stats=False)
454 hg.clean(repo, node, show_stats=False)
455 repo.dirstate.setbranch(branch)
455 repo.dirstate.setbranch(branch)
456 revert_opts = opts.copy()
456 revert_opts = opts.copy()
457 revert_opts['date'] = None
457 revert_opts['date'] = None
458 revert_opts['all'] = True
458 revert_opts['all'] = True
459 revert_opts['rev'] = hex(parent)
459 revert_opts['rev'] = hex(parent)
460 revert_opts['no_backup'] = None
460 revert_opts['no_backup'] = None
461 revert(ui, repo, **revert_opts)
461 revert(ui, repo, **revert_opts)
462 if not opts.get('merge') and op1 != node:
462 if not opts.get('merge') and op1 != node:
463 try:
463 try:
464 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
464 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
465 return hg.update(repo, op1)
465 return hg.update(repo, op1)
466 finally:
466 finally:
467 ui.setconfig('ui', 'forcemerge', '')
467 ui.setconfig('ui', 'forcemerge', '')
468
468
469 commit_opts = opts.copy()
469 commit_opts = opts.copy()
470 commit_opts['addremove'] = False
470 commit_opts['addremove'] = False
471 if not commit_opts['message'] and not commit_opts['logfile']:
471 if not commit_opts['message'] and not commit_opts['logfile']:
472 # we don't translate commit messages
472 # we don't translate commit messages
473 commit_opts['message'] = "Backed out changeset %s" % short(node)
473 commit_opts['message'] = "Backed out changeset %s" % short(node)
474 commit_opts['force_editor'] = True
474 commit_opts['force_editor'] = True
475 commit(ui, repo, **commit_opts)
475 commit(ui, repo, **commit_opts)
476 def nice(node):
476 def nice(node):
477 return '%d:%s' % (repo.changelog.rev(node), short(node))
477 return '%d:%s' % (repo.changelog.rev(node), short(node))
478 ui.status(_('changeset %s backs out changeset %s\n') %
478 ui.status(_('changeset %s backs out changeset %s\n') %
479 (nice(repo.changelog.tip()), nice(node)))
479 (nice(repo.changelog.tip()), nice(node)))
480 if opts.get('merge') and op1 != node:
480 if opts.get('merge') and op1 != node:
481 hg.clean(repo, op1, show_stats=False)
481 hg.clean(repo, op1, show_stats=False)
482 ui.status(_('merging with changeset %s\n')
482 ui.status(_('merging with changeset %s\n')
483 % nice(repo.changelog.tip()))
483 % nice(repo.changelog.tip()))
484 try:
484 try:
485 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
485 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
486 return hg.merge(repo, hex(repo.changelog.tip()))
486 return hg.merge(repo, hex(repo.changelog.tip()))
487 finally:
487 finally:
488 ui.setconfig('ui', 'forcemerge', '')
488 ui.setconfig('ui', 'forcemerge', '')
489 return 0
489 return 0
490
490
491 @command('bisect',
491 @command('bisect',
492 [('r', 'reset', False, _('reset bisect state')),
492 [('r', 'reset', False, _('reset bisect state')),
493 ('g', 'good', False, _('mark changeset good')),
493 ('g', 'good', False, _('mark changeset good')),
494 ('b', 'bad', False, _('mark changeset bad')),
494 ('b', 'bad', False, _('mark changeset bad')),
495 ('s', 'skip', False, _('skip testing changeset')),
495 ('s', 'skip', False, _('skip testing changeset')),
496 ('e', 'extend', False, _('extend the bisect range')),
496 ('e', 'extend', False, _('extend the bisect range')),
497 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
497 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
498 ('U', 'noupdate', False, _('do not update to target'))],
498 ('U', 'noupdate', False, _('do not update to target'))],
499 _("[-gbsr] [-U] [-c CMD] [REV]"))
499 _("[-gbsr] [-U] [-c CMD] [REV]"))
500 def bisect(ui, repo, rev=None, extra=None, command=None,
500 def bisect(ui, repo, rev=None, extra=None, command=None,
501 reset=None, good=None, bad=None, skip=None, extend=None,
501 reset=None, good=None, bad=None, skip=None, extend=None,
502 noupdate=None):
502 noupdate=None):
503 """subdivision search of changesets
503 """subdivision search of changesets
504
504
505 This command helps to find changesets which introduce problems. To
505 This command helps to find changesets which introduce problems. To
506 use, mark the earliest changeset you know exhibits the problem as
506 use, mark the earliest changeset you know exhibits the problem as
507 bad, then mark the latest changeset which is free from the problem
507 bad, then mark the latest changeset which is free from the problem
508 as good. Bisect will update your working directory to a revision
508 as good. Bisect will update your working directory to a revision
509 for testing (unless the -U/--noupdate option is specified). Once
509 for testing (unless the -U/--noupdate option is specified). Once
510 you have performed tests, mark the working directory as good or
510 you have performed tests, mark the working directory as good or
511 bad, and bisect will either update to another candidate changeset
511 bad, and bisect will either update to another candidate changeset
512 or announce that it has found the bad revision.
512 or announce that it has found the bad revision.
513
513
514 As a shortcut, you can also use the revision argument to mark a
514 As a shortcut, you can also use the revision argument to mark a
515 revision as good or bad without checking it out first.
515 revision as good or bad without checking it out first.
516
516
517 If you supply a command, it will be used for automatic bisection.
517 If you supply a command, it will be used for automatic bisection.
518 Its exit status will be used to mark revisions as good or bad:
518 Its exit status will be used to mark revisions as good or bad:
519 status 0 means good, 125 means to skip the revision, 127
519 status 0 means good, 125 means to skip the revision, 127
520 (command not found) will abort the bisection, and any other
520 (command not found) will abort the bisection, and any other
521 non-zero exit status means the revision is bad.
521 non-zero exit status means the revision is bad.
522
522
523 .. container:: verbose
523 .. container:: verbose
524
524
525 Some examples:
525 Some examples:
526
526
527 - start a bisection with known bad revision 12, and good revision 34::
527 - start a bisection with known bad revision 12, and good revision 34::
528
528
529 hg bisect --bad 34
529 hg bisect --bad 34
530 hg bisect --good 12
530 hg bisect --good 12
531
531
532 - advance the current bisection by marking current revision as good or
532 - advance the current bisection by marking current revision as good or
533 bad::
533 bad::
534
534
535 hg bisect --good
535 hg bisect --good
536 hg bisect --bad
536 hg bisect --bad
537
537
538 - mark the current revision, or a known revision, to be skipped (eg. if
538 - mark the current revision, or a known revision, to be skipped (eg. if
539 that revision is not usable because of another issue)::
539 that revision is not usable because of another issue)::
540
540
541 hg bisect --skip
541 hg bisect --skip
542 hg bisect --skip 23
542 hg bisect --skip 23
543
543
544 - forget the current bisection::
544 - forget the current bisection::
545
545
546 hg bisect --reset
546 hg bisect --reset
547
547
548 - use 'make && make tests' to automatically find the first broken
548 - use 'make && make tests' to automatically find the first broken
549 revision::
549 revision::
550
550
551 hg bisect --reset
551 hg bisect --reset
552 hg bisect --bad 34
552 hg bisect --bad 34
553 hg bisect --good 12
553 hg bisect --good 12
554 hg bisect --command 'make && make tests'
554 hg bisect --command 'make && make tests'
555
555
556 - see all changesets whose states are already known in the current
556 - see all changesets whose states are already known in the current
557 bisection::
557 bisection::
558
558
559 hg log -r "bisect(pruned)"
559 hg log -r "bisect(pruned)"
560
560
561 - see all changesets that took part in the current bisection::
561 - see all changesets that took part in the current bisection::
562
562
563 hg log -r "bisect(range)"
563 hg log -r "bisect(range)"
564
564
565 - with the graphlog extension, you can even get a nice graph::
565 - with the graphlog extension, you can even get a nice graph::
566
566
567 hg log --graph -r "bisect(range)"
567 hg log --graph -r "bisect(range)"
568
568
569 See :hg:`help revsets` for more about the `bisect()` keyword.
569 See :hg:`help revsets` for more about the `bisect()` keyword.
570
570
571 Returns 0 on success.
571 Returns 0 on success.
572 """
572 """
573 def extendbisectrange(nodes, good):
573 def extendbisectrange(nodes, good):
574 # bisect is incomplete when it ends on a merge node and
574 # bisect is incomplete when it ends on a merge node and
575 # one of the parent was not checked.
575 # one of the parent was not checked.
576 parents = repo[nodes[0]].parents()
576 parents = repo[nodes[0]].parents()
577 if len(parents) > 1:
577 if len(parents) > 1:
578 side = good and state['bad'] or state['good']
578 side = good and state['bad'] or state['good']
579 num = len(set(i.node() for i in parents) & set(side))
579 num = len(set(i.node() for i in parents) & set(side))
580 if num == 1:
580 if num == 1:
581 return parents[0].ancestor(parents[1])
581 return parents[0].ancestor(parents[1])
582 return None
582 return None
583
583
584 def print_result(nodes, good):
584 def print_result(nodes, good):
585 displayer = cmdutil.show_changeset(ui, repo, {})
585 displayer = cmdutil.show_changeset(ui, repo, {})
586 if len(nodes) == 1:
586 if len(nodes) == 1:
587 # narrowed it down to a single revision
587 # narrowed it down to a single revision
588 if good:
588 if good:
589 ui.write(_("The first good revision is:\n"))
589 ui.write(_("The first good revision is:\n"))
590 else:
590 else:
591 ui.write(_("The first bad revision is:\n"))
591 ui.write(_("The first bad revision is:\n"))
592 displayer.show(repo[nodes[0]])
592 displayer.show(repo[nodes[0]])
593 extendnode = extendbisectrange(nodes, good)
593 extendnode = extendbisectrange(nodes, good)
594 if extendnode is not None:
594 if extendnode is not None:
595 ui.write(_('Not all ancestors of this changeset have been'
595 ui.write(_('Not all ancestors of this changeset have been'
596 ' checked.\nUse bisect --extend to continue the '
596 ' checked.\nUse bisect --extend to continue the '
597 'bisection from\nthe common ancestor, %s.\n')
597 'bisection from\nthe common ancestor, %s.\n')
598 % extendnode)
598 % extendnode)
599 else:
599 else:
600 # multiple possible revisions
600 # multiple possible revisions
601 if good:
601 if good:
602 ui.write(_("Due to skipped revisions, the first "
602 ui.write(_("Due to skipped revisions, the first "
603 "good revision could be any of:\n"))
603 "good revision could be any of:\n"))
604 else:
604 else:
605 ui.write(_("Due to skipped revisions, the first "
605 ui.write(_("Due to skipped revisions, the first "
606 "bad revision could be any of:\n"))
606 "bad revision could be any of:\n"))
607 for n in nodes:
607 for n in nodes:
608 displayer.show(repo[n])
608 displayer.show(repo[n])
609 displayer.close()
609 displayer.close()
610
610
611 def check_state(state, interactive=True):
611 def check_state(state, interactive=True):
612 if not state['good'] or not state['bad']:
612 if not state['good'] or not state['bad']:
613 if (good or bad or skip or reset) and interactive:
613 if (good or bad or skip or reset) and interactive:
614 return
614 return
615 if not state['good']:
615 if not state['good']:
616 raise util.Abort(_('cannot bisect (no known good revisions)'))
616 raise util.Abort(_('cannot bisect (no known good revisions)'))
617 else:
617 else:
618 raise util.Abort(_('cannot bisect (no known bad revisions)'))
618 raise util.Abort(_('cannot bisect (no known bad revisions)'))
619 return True
619 return True
620
620
621 # backward compatibility
621 # backward compatibility
622 if rev in "good bad reset init".split():
622 if rev in "good bad reset init".split():
623 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
623 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
624 cmd, rev, extra = rev, extra, None
624 cmd, rev, extra = rev, extra, None
625 if cmd == "good":
625 if cmd == "good":
626 good = True
626 good = True
627 elif cmd == "bad":
627 elif cmd == "bad":
628 bad = True
628 bad = True
629 else:
629 else:
630 reset = True
630 reset = True
631 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
631 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
632 raise util.Abort(_('incompatible arguments'))
632 raise util.Abort(_('incompatible arguments'))
633
633
634 if reset:
634 if reset:
635 p = repo.join("bisect.state")
635 p = repo.join("bisect.state")
636 if os.path.exists(p):
636 if os.path.exists(p):
637 os.unlink(p)
637 os.unlink(p)
638 return
638 return
639
639
640 state = hbisect.load_state(repo)
640 state = hbisect.load_state(repo)
641
641
642 if command:
642 if command:
643 changesets = 1
643 changesets = 1
644 try:
644 try:
645 while changesets:
645 while changesets:
646 # update state
646 # update state
647 status = util.system(command, out=ui.fout)
647 status = util.system(command, out=ui.fout)
648 if status == 125:
648 if status == 125:
649 transition = "skip"
649 transition = "skip"
650 elif status == 0:
650 elif status == 0:
651 transition = "good"
651 transition = "good"
652 # status < 0 means process was killed
652 # status < 0 means process was killed
653 elif status == 127:
653 elif status == 127:
654 raise util.Abort(_("failed to execute %s") % command)
654 raise util.Abort(_("failed to execute %s") % command)
655 elif status < 0:
655 elif status < 0:
656 raise util.Abort(_("%s killed") % command)
656 raise util.Abort(_("%s killed") % command)
657 else:
657 else:
658 transition = "bad"
658 transition = "bad"
659 ctx = scmutil.revsingle(repo, rev)
659 ctx = scmutil.revsingle(repo, rev)
660 rev = None # clear for future iterations
660 rev = None # clear for future iterations
661 state[transition].append(ctx.node())
661 state[transition].append(ctx.node())
662 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
662 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
663 check_state(state, interactive=False)
663 check_state(state, interactive=False)
664 # bisect
664 # bisect
665 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
665 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
666 # update to next check
666 # update to next check
667 cmdutil.bailifchanged(repo)
667 cmdutil.bailifchanged(repo)
668 hg.clean(repo, nodes[0], show_stats=False)
668 hg.clean(repo, nodes[0], show_stats=False)
669 finally:
669 finally:
670 hbisect.save_state(repo, state)
670 hbisect.save_state(repo, state)
671 print_result(nodes, good)
671 print_result(nodes, good)
672 return
672 return
673
673
674 # update state
674 # update state
675
675
676 if rev:
676 if rev:
677 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
677 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
678 else:
678 else:
679 nodes = [repo.lookup('.')]
679 nodes = [repo.lookup('.')]
680
680
681 if good or bad or skip:
681 if good or bad or skip:
682 if good:
682 if good:
683 state['good'] += nodes
683 state['good'] += nodes
684 elif bad:
684 elif bad:
685 state['bad'] += nodes
685 state['bad'] += nodes
686 elif skip:
686 elif skip:
687 state['skip'] += nodes
687 state['skip'] += nodes
688 hbisect.save_state(repo, state)
688 hbisect.save_state(repo, state)
689
689
690 if not check_state(state):
690 if not check_state(state):
691 return
691 return
692
692
693 # actually bisect
693 # actually bisect
694 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
694 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
695 if extend:
695 if extend:
696 if not changesets:
696 if not changesets:
697 extendnode = extendbisectrange(nodes, good)
697 extendnode = extendbisectrange(nodes, good)
698 if extendnode is not None:
698 if extendnode is not None:
699 ui.write(_("Extending search to changeset %d:%s\n"
699 ui.write(_("Extending search to changeset %d:%s\n"
700 % (extendnode.rev(), extendnode)))
700 % (extendnode.rev(), extendnode)))
701 if noupdate:
701 if noupdate:
702 return
702 return
703 cmdutil.bailifchanged(repo)
703 cmdutil.bailifchanged(repo)
704 return hg.clean(repo, extendnode.node())
704 return hg.clean(repo, extendnode.node())
705 raise util.Abort(_("nothing to extend"))
705 raise util.Abort(_("nothing to extend"))
706
706
707 if changesets == 0:
707 if changesets == 0:
708 print_result(nodes, good)
708 print_result(nodes, good)
709 else:
709 else:
710 assert len(nodes) == 1 # only a single node can be tested next
710 assert len(nodes) == 1 # only a single node can be tested next
711 node = nodes[0]
711 node = nodes[0]
712 # compute the approximate number of remaining tests
712 # compute the approximate number of remaining tests
713 tests, size = 0, 2
713 tests, size = 0, 2
714 while size <= changesets:
714 while size <= changesets:
715 tests, size = tests + 1, size * 2
715 tests, size = tests + 1, size * 2
716 rev = repo.changelog.rev(node)
716 rev = repo.changelog.rev(node)
717 ui.write(_("Testing changeset %d:%s "
717 ui.write(_("Testing changeset %d:%s "
718 "(%d changesets remaining, ~%d tests)\n")
718 "(%d changesets remaining, ~%d tests)\n")
719 % (rev, short(node), changesets, tests))
719 % (rev, short(node), changesets, tests))
720 if not noupdate:
720 if not noupdate:
721 cmdutil.bailifchanged(repo)
721 cmdutil.bailifchanged(repo)
722 return hg.clean(repo, node)
722 return hg.clean(repo, node)
723
723
724 @command('bookmarks',
724 @command('bookmarks',
725 [('f', 'force', False, _('force')),
725 [('f', 'force', False, _('force')),
726 ('r', 'rev', '', _('revision'), _('REV')),
726 ('r', 'rev', '', _('revision'), _('REV')),
727 ('d', 'delete', False, _('delete a given bookmark')),
727 ('d', 'delete', False, _('delete a given bookmark')),
728 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
728 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
729 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
729 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
730 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
730 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
731 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
731 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
732 rename=None, inactive=False):
732 rename=None, inactive=False):
733 '''track a line of development with movable markers
733 '''track a line of development with movable markers
734
734
735 Bookmarks are pointers to certain commits that move when committing.
735 Bookmarks are pointers to certain commits that move when committing.
736 Bookmarks are local. They can be renamed, copied and deleted. It is
736 Bookmarks are local. They can be renamed, copied and deleted. It is
737 possible to use :hg:`merge NAME` to merge from a given bookmark, and
737 possible to use :hg:`merge NAME` to merge from a given bookmark, and
738 :hg:`update NAME` to update to a given bookmark.
738 :hg:`update NAME` to update to a given bookmark.
739
739
740 You can use :hg:`bookmark NAME` to set a bookmark on the working
740 You can use :hg:`bookmark NAME` to set a bookmark on the working
741 directory's parent revision with the given name. If you specify
741 directory's parent revision with the given name. If you specify
742 a revision using -r REV (where REV may be an existing bookmark),
742 a revision using -r REV (where REV may be an existing bookmark),
743 the bookmark is assigned to that revision.
743 the bookmark is assigned to that revision.
744
744
745 Bookmarks can be pushed and pulled between repositories (see :hg:`help
745 Bookmarks can be pushed and pulled between repositories (see :hg:`help
746 push` and :hg:`help pull`). This requires both the local and remote
746 push` and :hg:`help pull`). This requires both the local and remote
747 repositories to support bookmarks. For versions prior to 1.8, this means
747 repositories to support bookmarks. For versions prior to 1.8, this means
748 the bookmarks extension must be enabled.
748 the bookmarks extension must be enabled.
749 '''
749 '''
750 hexfn = ui.debugflag and hex or short
750 hexfn = ui.debugflag and hex or short
751 marks = repo._bookmarks
751 marks = repo._bookmarks
752 cur = repo.changectx('.').node()
752 cur = repo.changectx('.').node()
753
753
754 if delete:
754 if delete:
755 if mark is None:
755 if mark is None:
756 raise util.Abort(_("bookmark name required"))
756 raise util.Abort(_("bookmark name required"))
757 if mark not in marks:
757 if mark not in marks:
758 raise util.Abort(_("bookmark '%s' does not exist") % mark)
758 raise util.Abort(_("bookmark '%s' does not exist") % mark)
759 if mark == repo._bookmarkcurrent:
759 if mark == repo._bookmarkcurrent:
760 bookmarks.setcurrent(repo, None)
760 bookmarks.setcurrent(repo, None)
761 del marks[mark]
761 del marks[mark]
762 bookmarks.write(repo)
762 bookmarks.write(repo)
763 return
763 return
764
764
765 if rename:
765 if rename:
766 if rename not in marks:
766 if rename not in marks:
767 raise util.Abort(_("bookmark '%s' does not exist") % rename)
767 raise util.Abort(_("bookmark '%s' does not exist") % rename)
768 if mark in marks and not force:
768 if mark in marks and not force:
769 raise util.Abort(_("bookmark '%s' already exists "
769 raise util.Abort(_("bookmark '%s' already exists "
770 "(use -f to force)") % mark)
770 "(use -f to force)") % mark)
771 if mark is None:
771 if mark is None:
772 raise util.Abort(_("new bookmark name required"))
772 raise util.Abort(_("new bookmark name required"))
773 marks[mark] = marks[rename]
773 marks[mark] = marks[rename]
774 if repo._bookmarkcurrent == rename and not inactive:
774 if repo._bookmarkcurrent == rename and not inactive:
775 bookmarks.setcurrent(repo, mark)
775 bookmarks.setcurrent(repo, mark)
776 del marks[rename]
776 del marks[rename]
777 bookmarks.write(repo)
777 bookmarks.write(repo)
778 return
778 return
779
779
780 if mark is not None:
780 if mark is not None:
781 if "\n" in mark:
781 if "\n" in mark:
782 raise util.Abort(_("bookmark name cannot contain newlines"))
782 raise util.Abort(_("bookmark name cannot contain newlines"))
783 mark = mark.strip()
783 mark = mark.strip()
784 if not mark:
784 if not mark:
785 raise util.Abort(_("bookmark names cannot consist entirely of "
785 raise util.Abort(_("bookmark names cannot consist entirely of "
786 "whitespace"))
786 "whitespace"))
787 if inactive and mark == repo._bookmarkcurrent:
787 if inactive and mark == repo._bookmarkcurrent:
788 bookmarks.setcurrent(repo, None)
788 bookmarks.setcurrent(repo, None)
789 return
789 return
790 if mark in marks and not force:
790 if mark in marks and not force:
791 raise util.Abort(_("bookmark '%s' already exists "
791 raise util.Abort(_("bookmark '%s' already exists "
792 "(use -f to force)") % mark)
792 "(use -f to force)") % mark)
793 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
793 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
794 and not force):
794 and not force):
795 raise util.Abort(
795 raise util.Abort(
796 _("a bookmark cannot have the name of an existing branch"))
796 _("a bookmark cannot have the name of an existing branch"))
797 if rev:
797 if rev:
798 marks[mark] = repo.lookup(rev)
798 marks[mark] = repo.lookup(rev)
799 else:
799 else:
800 marks[mark] = cur
800 marks[mark] = cur
801 if not inactive and cur == marks[mark]:
801 if not inactive and cur == marks[mark]:
802 bookmarks.setcurrent(repo, mark)
802 bookmarks.setcurrent(repo, mark)
803 bookmarks.write(repo)
803 bookmarks.write(repo)
804 return
804 return
805
805
806 if mark is None:
806 if mark is None:
807 if rev:
807 if rev:
808 raise util.Abort(_("bookmark name required"))
808 raise util.Abort(_("bookmark name required"))
809 if len(marks) == 0:
809 if len(marks) == 0:
810 ui.status(_("no bookmarks set\n"))
810 ui.status(_("no bookmarks set\n"))
811 else:
811 else:
812 for bmark, n in sorted(marks.iteritems()):
812 for bmark, n in sorted(marks.iteritems()):
813 current = repo._bookmarkcurrent
813 current = repo._bookmarkcurrent
814 if bmark == current and n == cur:
814 if bmark == current and n == cur:
815 prefix, label = '*', 'bookmarks.current'
815 prefix, label = '*', 'bookmarks.current'
816 else:
816 else:
817 prefix, label = ' ', ''
817 prefix, label = ' ', ''
818
818
819 if ui.quiet:
819 if ui.quiet:
820 ui.write("%s\n" % bmark, label=label)
820 ui.write("%s\n" % bmark, label=label)
821 else:
821 else:
822 ui.write(" %s %-25s %d:%s\n" % (
822 ui.write(" %s %-25s %d:%s\n" % (
823 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
823 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
824 label=label)
824 label=label)
825 return
825 return
826
826
827 @command('branch',
827 @command('branch',
828 [('f', 'force', None,
828 [('f', 'force', None,
829 _('set branch name even if it shadows an existing branch')),
829 _('set branch name even if it shadows an existing branch')),
830 ('C', 'clean', None, _('reset branch name to parent branch name'))],
830 ('C', 'clean', None, _('reset branch name to parent branch name'))],
831 _('[-fC] [NAME]'))
831 _('[-fC] [NAME]'))
832 def branch(ui, repo, label=None, **opts):
832 def branch(ui, repo, label=None, **opts):
833 """set or show the current branch name
833 """set or show the current branch name
834
834
835 .. note::
835 .. note::
836 Branch names are permanent and global. Use :hg:`bookmark` to create a
836 Branch names are permanent and global. Use :hg:`bookmark` to create a
837 light-weight bookmark instead. See :hg:`help glossary` for more
837 light-weight bookmark instead. See :hg:`help glossary` for more
838 information about named branches and bookmarks.
838 information about named branches and bookmarks.
839
839
840 With no argument, show the current branch name. With one argument,
840 With no argument, show the current branch name. With one argument,
841 set the working directory branch name (the branch will not exist
841 set the working directory branch name (the branch will not exist
842 in the repository until the next commit). Standard practice
842 in the repository until the next commit). Standard practice
843 recommends that primary development take place on the 'default'
843 recommends that primary development take place on the 'default'
844 branch.
844 branch.
845
845
846 Unless -f/--force is specified, branch will not let you set a
846 Unless -f/--force is specified, branch will not let you set a
847 branch name that already exists, even if it's inactive.
847 branch name that already exists, even if it's inactive.
848
848
849 Use -C/--clean to reset the working directory branch to that of
849 Use -C/--clean to reset the working directory branch to that of
850 the parent of the working directory, negating a previous branch
850 the parent of the working directory, negating a previous branch
851 change.
851 change.
852
852
853 Use the command :hg:`update` to switch to an existing branch. Use
853 Use the command :hg:`update` to switch to an existing branch. Use
854 :hg:`commit --close-branch` to mark this branch as closed.
854 :hg:`commit --close-branch` to mark this branch as closed.
855
855
856 Returns 0 on success.
856 Returns 0 on success.
857 """
857 """
858
858
859 if opts.get('clean'):
859 if opts.get('clean'):
860 label = repo[None].p1().branch()
860 label = repo[None].p1().branch()
861 repo.dirstate.setbranch(label)
861 repo.dirstate.setbranch(label)
862 ui.status(_('reset working directory to branch %s\n') % label)
862 ui.status(_('reset working directory to branch %s\n') % label)
863 elif label:
863 elif label:
864 if not opts.get('force') and label in repo.branchtags():
864 if not opts.get('force') and label in repo.branchtags():
865 if label not in [p.branch() for p in repo.parents()]:
865 if label not in [p.branch() for p in repo.parents()]:
866 raise util.Abort(_('a branch of the same name already exists'),
866 raise util.Abort(_('a branch of the same name already exists'),
867 # i18n: "it" refers to an existing branch
867 # i18n: "it" refers to an existing branch
868 hint=_("use 'hg update' to switch to it"))
868 hint=_("use 'hg update' to switch to it"))
869 repo.dirstate.setbranch(label)
869 repo.dirstate.setbranch(label)
870 ui.status(_('marked working directory as branch %s\n') % label)
870 ui.status(_('marked working directory as branch %s\n') % label)
871 ui.status(_('(branches are permanent and global, '
871 ui.status(_('(branches are permanent and global, '
872 'did you want a bookmark?)\n'))
872 'did you want a bookmark?)\n'))
873 else:
873 else:
874 ui.write("%s\n" % repo.dirstate.branch())
874 ui.write("%s\n" % repo.dirstate.branch())
875
875
876 @command('branches',
876 @command('branches',
877 [('a', 'active', False, _('show only branches that have unmerged heads')),
877 [('a', 'active', False, _('show only branches that have unmerged heads')),
878 ('c', 'closed', False, _('show normal and closed branches'))],
878 ('c', 'closed', False, _('show normal and closed branches'))],
879 _('[-ac]'))
879 _('[-ac]'))
880 def branches(ui, repo, active=False, closed=False):
880 def branches(ui, repo, active=False, closed=False):
881 """list repository named branches
881 """list repository named branches
882
882
883 List the repository's named branches, indicating which ones are
883 List the repository's named branches, indicating which ones are
884 inactive. If -c/--closed is specified, also list branches which have
884 inactive. If -c/--closed is specified, also list branches which have
885 been marked closed (see :hg:`commit --close-branch`).
885 been marked closed (see :hg:`commit --close-branch`).
886
886
887 If -a/--active is specified, only show active branches. A branch
887 If -a/--active is specified, only show active branches. A branch
888 is considered active if it contains repository heads.
888 is considered active if it contains repository heads.
889
889
890 Use the command :hg:`update` to switch to an existing branch.
890 Use the command :hg:`update` to switch to an existing branch.
891
891
892 Returns 0.
892 Returns 0.
893 """
893 """
894
894
895 hexfunc = ui.debugflag and hex or short
895 hexfunc = ui.debugflag and hex or short
896 activebranches = [repo[n].branch() for n in repo.heads()]
896 activebranches = [repo[n].branch() for n in repo.heads()]
897 def testactive(tag, node):
897 def testactive(tag, node):
898 realhead = tag in activebranches
898 realhead = tag in activebranches
899 open = node in repo.branchheads(tag, closed=False)
899 open = node in repo.branchheads(tag, closed=False)
900 return realhead and open
900 return realhead and open
901 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
901 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
902 for tag, node in repo.branchtags().items()],
902 for tag, node in repo.branchtags().items()],
903 reverse=True)
903 reverse=True)
904
904
905 for isactive, node, tag in branches:
905 for isactive, node, tag in branches:
906 if (not active) or isactive:
906 if (not active) or isactive:
907 if ui.quiet:
907 if ui.quiet:
908 ui.write("%s\n" % tag)
908 ui.write("%s\n" % tag)
909 else:
909 else:
910 hn = repo.lookup(node)
910 hn = repo.lookup(node)
911 if isactive:
911 if isactive:
912 label = 'branches.active'
912 label = 'branches.active'
913 notice = ''
913 notice = ''
914 elif hn not in repo.branchheads(tag, closed=False):
914 elif hn not in repo.branchheads(tag, closed=False):
915 if not closed:
915 if not closed:
916 continue
916 continue
917 label = 'branches.closed'
917 label = 'branches.closed'
918 notice = _(' (closed)')
918 notice = _(' (closed)')
919 else:
919 else:
920 label = 'branches.inactive'
920 label = 'branches.inactive'
921 notice = _(' (inactive)')
921 notice = _(' (inactive)')
922 if tag == repo.dirstate.branch():
922 if tag == repo.dirstate.branch():
923 label = 'branches.current'
923 label = 'branches.current'
924 rev = str(node).rjust(31 - encoding.colwidth(tag))
924 rev = str(node).rjust(31 - encoding.colwidth(tag))
925 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
925 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
926 tag = ui.label(tag, label)
926 tag = ui.label(tag, label)
927 ui.write("%s %s%s\n" % (tag, rev, notice))
927 ui.write("%s %s%s\n" % (tag, rev, notice))
928
928
929 @command('bundle',
929 @command('bundle',
930 [('f', 'force', None, _('run even when the destination is unrelated')),
930 [('f', 'force', None, _('run even when the destination is unrelated')),
931 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
931 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
932 _('REV')),
932 _('REV')),
933 ('b', 'branch', [], _('a specific branch you would like to bundle'),
933 ('b', 'branch', [], _('a specific branch you would like to bundle'),
934 _('BRANCH')),
934 _('BRANCH')),
935 ('', 'base', [],
935 ('', 'base', [],
936 _('a base changeset assumed to be available at the destination'),
936 _('a base changeset assumed to be available at the destination'),
937 _('REV')),
937 _('REV')),
938 ('a', 'all', None, _('bundle all changesets in the repository')),
938 ('a', 'all', None, _('bundle all changesets in the repository')),
939 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
939 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
940 ] + remoteopts,
940 ] + remoteopts,
941 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
941 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
942 def bundle(ui, repo, fname, dest=None, **opts):
942 def bundle(ui, repo, fname, dest=None, **opts):
943 """create a changegroup file
943 """create a changegroup file
944
944
945 Generate a compressed changegroup file collecting changesets not
945 Generate a compressed changegroup file collecting changesets not
946 known to be in another repository.
946 known to be in another repository.
947
947
948 If you omit the destination repository, then hg assumes the
948 If you omit the destination repository, then hg assumes the
949 destination will have all the nodes you specify with --base
949 destination will have all the nodes you specify with --base
950 parameters. To create a bundle containing all changesets, use
950 parameters. To create a bundle containing all changesets, use
951 -a/--all (or --base null).
951 -a/--all (or --base null).
952
952
953 You can change compression method with the -t/--type option.
953 You can change compression method with the -t/--type option.
954 The available compression methods are: none, bzip2, and
954 The available compression methods are: none, bzip2, and
955 gzip (by default, bundles are compressed using bzip2).
955 gzip (by default, bundles are compressed using bzip2).
956
956
957 The bundle file can then be transferred using conventional means
957 The bundle file can then be transferred using conventional means
958 and applied to another repository with the unbundle or pull
958 and applied to another repository with the unbundle or pull
959 command. This is useful when direct push and pull are not
959 command. This is useful when direct push and pull are not
960 available or when exporting an entire repository is undesirable.
960 available or when exporting an entire repository is undesirable.
961
961
962 Applying bundles preserves all changeset contents including
962 Applying bundles preserves all changeset contents including
963 permissions, copy/rename information, and revision history.
963 permissions, copy/rename information, and revision history.
964
964
965 Returns 0 on success, 1 if no changes found.
965 Returns 0 on success, 1 if no changes found.
966 """
966 """
967 revs = None
967 revs = None
968 if 'rev' in opts:
968 if 'rev' in opts:
969 revs = scmutil.revrange(repo, opts['rev'])
969 revs = scmutil.revrange(repo, opts['rev'])
970
970
971 if opts.get('all'):
971 if opts.get('all'):
972 base = ['null']
972 base = ['null']
973 else:
973 else:
974 base = scmutil.revrange(repo, opts.get('base'))
974 base = scmutil.revrange(repo, opts.get('base'))
975 if base:
975 if base:
976 if dest:
976 if dest:
977 raise util.Abort(_("--base is incompatible with specifying "
977 raise util.Abort(_("--base is incompatible with specifying "
978 "a destination"))
978 "a destination"))
979 common = [repo.lookup(rev) for rev in base]
979 common = [repo.lookup(rev) for rev in base]
980 heads = revs and map(repo.lookup, revs) or revs
980 heads = revs and map(repo.lookup, revs) or revs
981 cg = repo.getbundle('bundle', heads=heads, common=common)
981 cg = repo.getbundle('bundle', heads=heads, common=common)
982 else:
982 else:
983 dest = ui.expandpath(dest or 'default-push', dest or 'default')
983 dest = ui.expandpath(dest or 'default-push', dest or 'default')
984 dest, branches = hg.parseurl(dest, opts.get('branch'))
984 dest, branches = hg.parseurl(dest, opts.get('branch'))
985 other = hg.peer(repo, opts, dest)
985 other = hg.peer(repo, opts, dest)
986 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
986 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
987 heads = revs and map(repo.lookup, revs) or revs
987 heads = revs and map(repo.lookup, revs) or revs
988 outgoing = discovery.findcommonoutgoing(repo, other,
988 outgoing = discovery.findcommonoutgoing(repo, other,
989 onlyheads=heads,
989 onlyheads=heads,
990 force=opts.get('force'))
990 force=opts.get('force'))
991 cg = repo.getlocalbundle('bundle', outgoing)
991 cg = repo.getlocalbundle('bundle', outgoing)
992 if not cg:
992 if not cg:
993 ui.status(_("no changes found\n"))
993 ui.status(_("no changes found\n"))
994 return 1
994 return 1
995
995
996 bundletype = opts.get('type', 'bzip2').lower()
996 bundletype = opts.get('type', 'bzip2').lower()
997 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
997 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
998 bundletype = btypes.get(bundletype)
998 bundletype = btypes.get(bundletype)
999 if bundletype not in changegroup.bundletypes:
999 if bundletype not in changegroup.bundletypes:
1000 raise util.Abort(_('unknown bundle type specified with --type'))
1000 raise util.Abort(_('unknown bundle type specified with --type'))
1001
1001
1002 changegroup.writebundle(cg, fname, bundletype)
1002 changegroup.writebundle(cg, fname, bundletype)
1003
1003
1004 @command('cat',
1004 @command('cat',
1005 [('o', 'output', '',
1005 [('o', 'output', '',
1006 _('print output to file with formatted name'), _('FORMAT')),
1006 _('print output to file with formatted name'), _('FORMAT')),
1007 ('r', 'rev', '', _('print the given revision'), _('REV')),
1007 ('r', 'rev', '', _('print the given revision'), _('REV')),
1008 ('', 'decode', None, _('apply any matching decode filter')),
1008 ('', 'decode', None, _('apply any matching decode filter')),
1009 ] + walkopts,
1009 ] + walkopts,
1010 _('[OPTION]... FILE...'))
1010 _('[OPTION]... FILE...'))
1011 def cat(ui, repo, file1, *pats, **opts):
1011 def cat(ui, repo, file1, *pats, **opts):
1012 """output the current or given revision of files
1012 """output the current or given revision of files
1013
1013
1014 Print the specified files as they were at the given revision. If
1014 Print the specified files as they were at the given revision. If
1015 no revision is given, the parent of the working directory is used,
1015 no revision is given, the parent of the working directory is used,
1016 or tip if no revision is checked out.
1016 or tip if no revision is checked out.
1017
1017
1018 Output may be to a file, in which case the name of the file is
1018 Output may be to a file, in which case the name of the file is
1019 given using a format string. The formatting rules are the same as
1019 given using a format string. The formatting rules are the same as
1020 for the export command, with the following additions:
1020 for the export command, with the following additions:
1021
1021
1022 :``%s``: basename of file being printed
1022 :``%s``: basename of file being printed
1023 :``%d``: dirname of file being printed, or '.' if in repository root
1023 :``%d``: dirname of file being printed, or '.' if in repository root
1024 :``%p``: root-relative path name of file being printed
1024 :``%p``: root-relative path name of file being printed
1025
1025
1026 Returns 0 on success.
1026 Returns 0 on success.
1027 """
1027 """
1028 ctx = scmutil.revsingle(repo, opts.get('rev'))
1028 ctx = scmutil.revsingle(repo, opts.get('rev'))
1029 err = 1
1029 err = 1
1030 m = scmutil.match(ctx, (file1,) + pats, opts)
1030 m = scmutil.match(ctx, (file1,) + pats, opts)
1031 for abs in ctx.walk(m):
1031 for abs in ctx.walk(m):
1032 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1032 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1033 pathname=abs)
1033 pathname=abs)
1034 data = ctx[abs].data()
1034 data = ctx[abs].data()
1035 if opts.get('decode'):
1035 if opts.get('decode'):
1036 data = repo.wwritedata(abs, data)
1036 data = repo.wwritedata(abs, data)
1037 fp.write(data)
1037 fp.write(data)
1038 fp.close()
1038 fp.close()
1039 err = 0
1039 err = 0
1040 return err
1040 return err
1041
1041
1042 @command('^clone',
1042 @command('^clone',
1043 [('U', 'noupdate', None,
1043 [('U', 'noupdate', None,
1044 _('the clone will include an empty working copy (only a repository)')),
1044 _('the clone will include an empty working copy (only a repository)')),
1045 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1045 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1046 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1046 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1047 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1047 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1048 ('', 'pull', None, _('use pull protocol to copy metadata')),
1048 ('', 'pull', None, _('use pull protocol to copy metadata')),
1049 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1049 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1050 ] + remoteopts,
1050 ] + remoteopts,
1051 _('[OPTION]... SOURCE [DEST]'))
1051 _('[OPTION]... SOURCE [DEST]'))
1052 def clone(ui, source, dest=None, **opts):
1052 def clone(ui, source, dest=None, **opts):
1053 """make a copy of an existing repository
1053 """make a copy of an existing repository
1054
1054
1055 Create a copy of an existing repository in a new directory.
1055 Create a copy of an existing repository in a new directory.
1056
1056
1057 If no destination directory name is specified, it defaults to the
1057 If no destination directory name is specified, it defaults to the
1058 basename of the source.
1058 basename of the source.
1059
1059
1060 The location of the source is added to the new repository's
1060 The location of the source is added to the new repository's
1061 ``.hg/hgrc`` file, as the default to be used for future pulls.
1061 ``.hg/hgrc`` file, as the default to be used for future pulls.
1062
1062
1063 Only local paths and ``ssh://`` URLs are supported as
1063 Only local paths and ``ssh://`` URLs are supported as
1064 destinations. For ``ssh://`` destinations, no working directory or
1064 destinations. For ``ssh://`` destinations, no working directory or
1065 ``.hg/hgrc`` will be created on the remote side.
1065 ``.hg/hgrc`` will be created on the remote side.
1066
1066
1067 To pull only a subset of changesets, specify one or more revisions
1067 To pull only a subset of changesets, specify one or more revisions
1068 identifiers with -r/--rev or branches with -b/--branch. The
1068 identifiers with -r/--rev or branches with -b/--branch. The
1069 resulting clone will contain only the specified changesets and
1069 resulting clone will contain only the specified changesets and
1070 their ancestors. These options (or 'clone src#rev dest') imply
1070 their ancestors. These options (or 'clone src#rev dest') imply
1071 --pull, even for local source repositories. Note that specifying a
1071 --pull, even for local source repositories. Note that specifying a
1072 tag will include the tagged changeset but not the changeset
1072 tag will include the tagged changeset but not the changeset
1073 containing the tag.
1073 containing the tag.
1074
1074
1075 To check out a particular version, use -u/--update, or
1075 To check out a particular version, use -u/--update, or
1076 -U/--noupdate to create a clone with no working directory.
1076 -U/--noupdate to create a clone with no working directory.
1077
1077
1078 .. container:: verbose
1078 .. container:: verbose
1079
1079
1080 For efficiency, hardlinks are used for cloning whenever the
1080 For efficiency, hardlinks are used for cloning whenever the
1081 source and destination are on the same filesystem (note this
1081 source and destination are on the same filesystem (note this
1082 applies only to the repository data, not to the working
1082 applies only to the repository data, not to the working
1083 directory). Some filesystems, such as AFS, implement hardlinking
1083 directory). Some filesystems, such as AFS, implement hardlinking
1084 incorrectly, but do not report errors. In these cases, use the
1084 incorrectly, but do not report errors. In these cases, use the
1085 --pull option to avoid hardlinking.
1085 --pull option to avoid hardlinking.
1086
1086
1087 In some cases, you can clone repositories and the working
1087 In some cases, you can clone repositories and the working
1088 directory using full hardlinks with ::
1088 directory using full hardlinks with ::
1089
1089
1090 $ cp -al REPO REPOCLONE
1090 $ cp -al REPO REPOCLONE
1091
1091
1092 This is the fastest way to clone, but it is not always safe. The
1092 This is the fastest way to clone, but it is not always safe. The
1093 operation is not atomic (making sure REPO is not modified during
1093 operation is not atomic (making sure REPO is not modified during
1094 the operation is up to you) and you have to make sure your
1094 the operation is up to you) and you have to make sure your
1095 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1095 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1096 so). Also, this is not compatible with certain extensions that
1096 so). Also, this is not compatible with certain extensions that
1097 place their metadata under the .hg directory, such as mq.
1097 place their metadata under the .hg directory, such as mq.
1098
1098
1099 Mercurial will update the working directory to the first applicable
1099 Mercurial will update the working directory to the first applicable
1100 revision from this list:
1100 revision from this list:
1101
1101
1102 a) null if -U or the source repository has no changesets
1102 a) null if -U or the source repository has no changesets
1103 b) if -u . and the source repository is local, the first parent of
1103 b) if -u . and the source repository is local, the first parent of
1104 the source repository's working directory
1104 the source repository's working directory
1105 c) the changeset specified with -u (if a branch name, this means the
1105 c) the changeset specified with -u (if a branch name, this means the
1106 latest head of that branch)
1106 latest head of that branch)
1107 d) the changeset specified with -r
1107 d) the changeset specified with -r
1108 e) the tipmost head specified with -b
1108 e) the tipmost head specified with -b
1109 f) the tipmost head specified with the url#branch source syntax
1109 f) the tipmost head specified with the url#branch source syntax
1110 g) the tipmost head of the default branch
1110 g) the tipmost head of the default branch
1111 h) tip
1111 h) tip
1112
1112
1113 Examples:
1113 Examples:
1114
1114
1115 - clone a remote repository to a new directory named hg/::
1115 - clone a remote repository to a new directory named hg/::
1116
1116
1117 hg clone http://selenic.com/hg
1117 hg clone http://selenic.com/hg
1118
1118
1119 - create a lightweight local clone::
1119 - create a lightweight local clone::
1120
1120
1121 hg clone project/ project-feature/
1121 hg clone project/ project-feature/
1122
1122
1123 - clone from an absolute path on an ssh server (note double-slash)::
1123 - clone from an absolute path on an ssh server (note double-slash)::
1124
1124
1125 hg clone ssh://user@server//home/projects/alpha/
1125 hg clone ssh://user@server//home/projects/alpha/
1126
1126
1127 - do a high-speed clone over a LAN while checking out a
1127 - do a high-speed clone over a LAN while checking out a
1128 specified version::
1128 specified version::
1129
1129
1130 hg clone --uncompressed http://server/repo -u 1.5
1130 hg clone --uncompressed http://server/repo -u 1.5
1131
1131
1132 - create a repository without changesets after a particular revision::
1132 - create a repository without changesets after a particular revision::
1133
1133
1134 hg clone -r 04e544 experimental/ good/
1134 hg clone -r 04e544 experimental/ good/
1135
1135
1136 - clone (and track) a particular named branch::
1136 - clone (and track) a particular named branch::
1137
1137
1138 hg clone http://selenic.com/hg#stable
1138 hg clone http://selenic.com/hg#stable
1139
1139
1140 See :hg:`help urls` for details on specifying URLs.
1140 See :hg:`help urls` for details on specifying URLs.
1141
1141
1142 Returns 0 on success.
1142 Returns 0 on success.
1143 """
1143 """
1144 if opts.get('noupdate') and opts.get('updaterev'):
1144 if opts.get('noupdate') and opts.get('updaterev'):
1145 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1145 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1146
1146
1147 r = hg.clone(ui, opts, source, dest,
1147 r = hg.clone(ui, opts, source, dest,
1148 pull=opts.get('pull'),
1148 pull=opts.get('pull'),
1149 stream=opts.get('uncompressed'),
1149 stream=opts.get('uncompressed'),
1150 rev=opts.get('rev'),
1150 rev=opts.get('rev'),
1151 update=opts.get('updaterev') or not opts.get('noupdate'),
1151 update=opts.get('updaterev') or not opts.get('noupdate'),
1152 branch=opts.get('branch'))
1152 branch=opts.get('branch'))
1153
1153
1154 return r is None
1154 return r is None
1155
1155
1156 @command('^commit|ci',
1156 @command('^commit|ci',
1157 [('A', 'addremove', None,
1157 [('A', 'addremove', None,
1158 _('mark new/missing files as added/removed before committing')),
1158 _('mark new/missing files as added/removed before committing')),
1159 ('', 'close-branch', None,
1159 ('', 'close-branch', None,
1160 _('mark a branch as closed, hiding it from the branch list')),
1160 _('mark a branch as closed, hiding it from the branch list')),
1161 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1161 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1162 _('[OPTION]... [FILE]...'))
1162 _('[OPTION]... [FILE]...'))
1163 def commit(ui, repo, *pats, **opts):
1163 def commit(ui, repo, *pats, **opts):
1164 """commit the specified files or all outstanding changes
1164 """commit the specified files or all outstanding changes
1165
1165
1166 Commit changes to the given files into the repository. Unlike a
1166 Commit changes to the given files into the repository. Unlike a
1167 centralized SCM, this operation is a local operation. See
1167 centralized SCM, this operation is a local operation. See
1168 :hg:`push` for a way to actively distribute your changes.
1168 :hg:`push` for a way to actively distribute your changes.
1169
1169
1170 If a list of files is omitted, all changes reported by :hg:`status`
1170 If a list of files is omitted, all changes reported by :hg:`status`
1171 will be committed.
1171 will be committed.
1172
1172
1173 If you are committing the result of a merge, do not provide any
1173 If you are committing the result of a merge, do not provide any
1174 filenames or -I/-X filters.
1174 filenames or -I/-X filters.
1175
1175
1176 If no commit message is specified, Mercurial starts your
1176 If no commit message is specified, Mercurial starts your
1177 configured editor where you can enter a message. In case your
1177 configured editor where you can enter a message. In case your
1178 commit fails, you will find a backup of your message in
1178 commit fails, you will find a backup of your message in
1179 ``.hg/last-message.txt``.
1179 ``.hg/last-message.txt``.
1180
1180
1181 See :hg:`help dates` for a list of formats valid for -d/--date.
1181 See :hg:`help dates` for a list of formats valid for -d/--date.
1182
1182
1183 Returns 0 on success, 1 if nothing changed.
1183 Returns 0 on success, 1 if nothing changed.
1184 """
1184 """
1185 if opts.get('subrepos'):
1185 if opts.get('subrepos'):
1186 # Let --subrepos on the command line overide config setting.
1186 # Let --subrepos on the command line overide config setting.
1187 ui.setconfig('ui', 'commitsubrepos', True)
1187 ui.setconfig('ui', 'commitsubrepos', True)
1188
1188
1189 extra = {}
1189 extra = {}
1190 if opts.get('close_branch'):
1190 if opts.get('close_branch'):
1191 if repo['.'].node() not in repo.branchheads():
1191 if repo['.'].node() not in repo.branchheads():
1192 # The topo heads set is included in the branch heads set of the
1192 # The topo heads set is included in the branch heads set of the
1193 # current branch, so it's sufficient to test branchheads
1193 # current branch, so it's sufficient to test branchheads
1194 raise util.Abort(_('can only close branch heads'))
1194 raise util.Abort(_('can only close branch heads'))
1195 extra['close'] = 1
1195 extra['close'] = 1
1196 e = cmdutil.commiteditor
1196 e = cmdutil.commiteditor
1197 if opts.get('force_editor'):
1197 if opts.get('force_editor'):
1198 e = cmdutil.commitforceeditor
1198 e = cmdutil.commitforceeditor
1199
1199
1200 def commitfunc(ui, repo, message, match, opts):
1200 def commitfunc(ui, repo, message, match, opts):
1201 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1201 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1202 editor=e, extra=extra)
1202 editor=e, extra=extra)
1203
1203
1204 branch = repo[None].branch()
1204 branch = repo[None].branch()
1205 bheads = repo.branchheads(branch)
1205 bheads = repo.branchheads(branch)
1206
1206
1207 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1207 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1208 if not node:
1208 if not node:
1209 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1209 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1210 if stat[3]:
1210 if stat[3]:
1211 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1211 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1212 % len(stat[3]))
1212 % len(stat[3]))
1213 else:
1213 else:
1214 ui.status(_("nothing changed\n"))
1214 ui.status(_("nothing changed\n"))
1215 return 1
1215 return 1
1216
1216
1217 ctx = repo[node]
1217 ctx = repo[node]
1218 parents = ctx.parents()
1218 parents = ctx.parents()
1219
1219
1220 if (bheads and node not in bheads and not
1220 if (bheads and node not in bheads and not
1221 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1221 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1222 ui.status(_('created new head\n'))
1222 ui.status(_('created new head\n'))
1223 # The message is not printed for initial roots. For the other
1223 # The message is not printed for initial roots. For the other
1224 # changesets, it is printed in the following situations:
1224 # changesets, it is printed in the following situations:
1225 #
1225 #
1226 # Par column: for the 2 parents with ...
1226 # Par column: for the 2 parents with ...
1227 # N: null or no parent
1227 # N: null or no parent
1228 # B: parent is on another named branch
1228 # B: parent is on another named branch
1229 # C: parent is a regular non head changeset
1229 # C: parent is a regular non head changeset
1230 # H: parent was a branch head of the current branch
1230 # H: parent was a branch head of the current branch
1231 # Msg column: whether we print "created new head" message
1231 # Msg column: whether we print "created new head" message
1232 # In the following, it is assumed that there already exists some
1232 # In the following, it is assumed that there already exists some
1233 # initial branch heads of the current branch, otherwise nothing is
1233 # initial branch heads of the current branch, otherwise nothing is
1234 # printed anyway.
1234 # printed anyway.
1235 #
1235 #
1236 # Par Msg Comment
1236 # Par Msg Comment
1237 # NN y additional topo root
1237 # NN y additional topo root
1238 #
1238 #
1239 # BN y additional branch root
1239 # BN y additional branch root
1240 # CN y additional topo head
1240 # CN y additional topo head
1241 # HN n usual case
1241 # HN n usual case
1242 #
1242 #
1243 # BB y weird additional branch root
1243 # BB y weird additional branch root
1244 # CB y branch merge
1244 # CB y branch merge
1245 # HB n merge with named branch
1245 # HB n merge with named branch
1246 #
1246 #
1247 # CC y additional head from merge
1247 # CC y additional head from merge
1248 # CH n merge with a head
1248 # CH n merge with a head
1249 #
1249 #
1250 # HH n head merge: head count decreases
1250 # HH n head merge: head count decreases
1251
1251
1252 if not opts.get('close_branch'):
1252 if not opts.get('close_branch'):
1253 for r in parents:
1253 for r in parents:
1254 if r.extra().get('close') and r.branch() == branch:
1254 if r.extra().get('close') and r.branch() == branch:
1255 ui.status(_('reopening closed branch head %d\n') % r)
1255 ui.status(_('reopening closed branch head %d\n') % r)
1256
1256
1257 if ui.debugflag:
1257 if ui.debugflag:
1258 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1258 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1259 elif ui.verbose:
1259 elif ui.verbose:
1260 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1260 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1261
1261
1262 @command('copy|cp',
1262 @command('copy|cp',
1263 [('A', 'after', None, _('record a copy that has already occurred')),
1263 [('A', 'after', None, _('record a copy that has already occurred')),
1264 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1264 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1265 ] + walkopts + dryrunopts,
1265 ] + walkopts + dryrunopts,
1266 _('[OPTION]... [SOURCE]... DEST'))
1266 _('[OPTION]... [SOURCE]... DEST'))
1267 def copy(ui, repo, *pats, **opts):
1267 def copy(ui, repo, *pats, **opts):
1268 """mark files as copied for the next commit
1268 """mark files as copied for the next commit
1269
1269
1270 Mark dest as having copies of source files. If dest is a
1270 Mark dest as having copies of source files. If dest is a
1271 directory, copies are put in that directory. If dest is a file,
1271 directory, copies are put in that directory. If dest is a file,
1272 the source must be a single file.
1272 the source must be a single file.
1273
1273
1274 By default, this command copies the contents of files as they
1274 By default, this command copies the contents of files as they
1275 exist in the working directory. If invoked with -A/--after, the
1275 exist in the working directory. If invoked with -A/--after, the
1276 operation is recorded, but no copying is performed.
1276 operation is recorded, but no copying is performed.
1277
1277
1278 This command takes effect with the next commit. To undo a copy
1278 This command takes effect with the next commit. To undo a copy
1279 before that, see :hg:`revert`.
1279 before that, see :hg:`revert`.
1280
1280
1281 Returns 0 on success, 1 if errors are encountered.
1281 Returns 0 on success, 1 if errors are encountered.
1282 """
1282 """
1283 wlock = repo.wlock(False)
1283 wlock = repo.wlock(False)
1284 try:
1284 try:
1285 return cmdutil.copy(ui, repo, pats, opts)
1285 return cmdutil.copy(ui, repo, pats, opts)
1286 finally:
1286 finally:
1287 wlock.release()
1287 wlock.release()
1288
1288
1289 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1289 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1290 def debugancestor(ui, repo, *args):
1290 def debugancestor(ui, repo, *args):
1291 """find the ancestor revision of two revisions in a given index"""
1291 """find the ancestor revision of two revisions in a given index"""
1292 if len(args) == 3:
1292 if len(args) == 3:
1293 index, rev1, rev2 = args
1293 index, rev1, rev2 = args
1294 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1294 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1295 lookup = r.lookup
1295 lookup = r.lookup
1296 elif len(args) == 2:
1296 elif len(args) == 2:
1297 if not repo:
1297 if not repo:
1298 raise util.Abort(_("there is no Mercurial repository here "
1298 raise util.Abort(_("there is no Mercurial repository here "
1299 "(.hg not found)"))
1299 "(.hg not found)"))
1300 rev1, rev2 = args
1300 rev1, rev2 = args
1301 r = repo.changelog
1301 r = repo.changelog
1302 lookup = repo.lookup
1302 lookup = repo.lookup
1303 else:
1303 else:
1304 raise util.Abort(_('either two or three arguments required'))
1304 raise util.Abort(_('either two or three arguments required'))
1305 a = r.ancestor(lookup(rev1), lookup(rev2))
1305 a = r.ancestor(lookup(rev1), lookup(rev2))
1306 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1306 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1307
1307
1308 @command('debugbuilddag',
1308 @command('debugbuilddag',
1309 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1309 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1310 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1310 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1311 ('n', 'new-file', None, _('add new file at each rev'))],
1311 ('n', 'new-file', None, _('add new file at each rev'))],
1312 _('[OPTION]... [TEXT]'))
1312 _('[OPTION]... [TEXT]'))
1313 def debugbuilddag(ui, repo, text=None,
1313 def debugbuilddag(ui, repo, text=None,
1314 mergeable_file=False,
1314 mergeable_file=False,
1315 overwritten_file=False,
1315 overwritten_file=False,
1316 new_file=False):
1316 new_file=False):
1317 """builds a repo with a given DAG from scratch in the current empty repo
1317 """builds a repo with a given DAG from scratch in the current empty repo
1318
1318
1319 The description of the DAG is read from stdin if not given on the
1319 The description of the DAG is read from stdin if not given on the
1320 command line.
1320 command line.
1321
1321
1322 Elements:
1322 Elements:
1323
1323
1324 - "+n" is a linear run of n nodes based on the current default parent
1324 - "+n" is a linear run of n nodes based on the current default parent
1325 - "." is a single node based on the current default parent
1325 - "." is a single node based on the current default parent
1326 - "$" resets the default parent to null (implied at the start);
1326 - "$" resets the default parent to null (implied at the start);
1327 otherwise the default parent is always the last node created
1327 otherwise the default parent is always the last node created
1328 - "<p" sets the default parent to the backref p
1328 - "<p" sets the default parent to the backref p
1329 - "*p" is a fork at parent p, which is a backref
1329 - "*p" is a fork at parent p, which is a backref
1330 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1330 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1331 - "/p2" is a merge of the preceding node and p2
1331 - "/p2" is a merge of the preceding node and p2
1332 - ":tag" defines a local tag for the preceding node
1332 - ":tag" defines a local tag for the preceding node
1333 - "@branch" sets the named branch for subsequent nodes
1333 - "@branch" sets the named branch for subsequent nodes
1334 - "#...\\n" is a comment up to the end of the line
1334 - "#...\\n" is a comment up to the end of the line
1335
1335
1336 Whitespace between the above elements is ignored.
1336 Whitespace between the above elements is ignored.
1337
1337
1338 A backref is either
1338 A backref is either
1339
1339
1340 - a number n, which references the node curr-n, where curr is the current
1340 - a number n, which references the node curr-n, where curr is the current
1341 node, or
1341 node, or
1342 - the name of a local tag you placed earlier using ":tag", or
1342 - the name of a local tag you placed earlier using ":tag", or
1343 - empty to denote the default parent.
1343 - empty to denote the default parent.
1344
1344
1345 All string valued-elements are either strictly alphanumeric, or must
1345 All string valued-elements are either strictly alphanumeric, or must
1346 be enclosed in double quotes ("..."), with "\\" as escape character.
1346 be enclosed in double quotes ("..."), with "\\" as escape character.
1347 """
1347 """
1348
1348
1349 if text is None:
1349 if text is None:
1350 ui.status(_("reading DAG from stdin\n"))
1350 ui.status(_("reading DAG from stdin\n"))
1351 text = ui.fin.read()
1351 text = ui.fin.read()
1352
1352
1353 cl = repo.changelog
1353 cl = repo.changelog
1354 if len(cl) > 0:
1354 if len(cl) > 0:
1355 raise util.Abort(_('repository is not empty'))
1355 raise util.Abort(_('repository is not empty'))
1356
1356
1357 # determine number of revs in DAG
1357 # determine number of revs in DAG
1358 total = 0
1358 total = 0
1359 for type, data in dagparser.parsedag(text):
1359 for type, data in dagparser.parsedag(text):
1360 if type == 'n':
1360 if type == 'n':
1361 total += 1
1361 total += 1
1362
1362
1363 if mergeable_file:
1363 if mergeable_file:
1364 linesperrev = 2
1364 linesperrev = 2
1365 # make a file with k lines per rev
1365 # make a file with k lines per rev
1366 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1366 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1367 initialmergedlines.append("")
1367 initialmergedlines.append("")
1368
1368
1369 tags = []
1369 tags = []
1370
1370
1371 lock = tr = None
1371 lock = tr = None
1372 try:
1372 try:
1373 lock = repo.lock()
1373 lock = repo.lock()
1374 tr = repo.transaction("builddag")
1374 tr = repo.transaction("builddag")
1375
1375
1376 at = -1
1376 at = -1
1377 atbranch = 'default'
1377 atbranch = 'default'
1378 nodeids = []
1378 nodeids = []
1379 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1379 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1380 for type, data in dagparser.parsedag(text):
1380 for type, data in dagparser.parsedag(text):
1381 if type == 'n':
1381 if type == 'n':
1382 ui.note('node %s\n' % str(data))
1382 ui.note('node %s\n' % str(data))
1383 id, ps = data
1383 id, ps = data
1384
1384
1385 files = []
1385 files = []
1386 fctxs = {}
1386 fctxs = {}
1387
1387
1388 p2 = None
1388 p2 = None
1389 if mergeable_file:
1389 if mergeable_file:
1390 fn = "mf"
1390 fn = "mf"
1391 p1 = repo[ps[0]]
1391 p1 = repo[ps[0]]
1392 if len(ps) > 1:
1392 if len(ps) > 1:
1393 p2 = repo[ps[1]]
1393 p2 = repo[ps[1]]
1394 pa = p1.ancestor(p2)
1394 pa = p1.ancestor(p2)
1395 base, local, other = [x[fn].data() for x in pa, p1, p2]
1395 base, local, other = [x[fn].data() for x in pa, p1, p2]
1396 m3 = simplemerge.Merge3Text(base, local, other)
1396 m3 = simplemerge.Merge3Text(base, local, other)
1397 ml = [l.strip() for l in m3.merge_lines()]
1397 ml = [l.strip() for l in m3.merge_lines()]
1398 ml.append("")
1398 ml.append("")
1399 elif at > 0:
1399 elif at > 0:
1400 ml = p1[fn].data().split("\n")
1400 ml = p1[fn].data().split("\n")
1401 else:
1401 else:
1402 ml = initialmergedlines
1402 ml = initialmergedlines
1403 ml[id * linesperrev] += " r%i" % id
1403 ml[id * linesperrev] += " r%i" % id
1404 mergedtext = "\n".join(ml)
1404 mergedtext = "\n".join(ml)
1405 files.append(fn)
1405 files.append(fn)
1406 fctxs[fn] = context.memfilectx(fn, mergedtext)
1406 fctxs[fn] = context.memfilectx(fn, mergedtext)
1407
1407
1408 if overwritten_file:
1408 if overwritten_file:
1409 fn = "of"
1409 fn = "of"
1410 files.append(fn)
1410 files.append(fn)
1411 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1411 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1412
1412
1413 if new_file:
1413 if new_file:
1414 fn = "nf%i" % id
1414 fn = "nf%i" % id
1415 files.append(fn)
1415 files.append(fn)
1416 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1416 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1417 if len(ps) > 1:
1417 if len(ps) > 1:
1418 if not p2:
1418 if not p2:
1419 p2 = repo[ps[1]]
1419 p2 = repo[ps[1]]
1420 for fn in p2:
1420 for fn in p2:
1421 if fn.startswith("nf"):
1421 if fn.startswith("nf"):
1422 files.append(fn)
1422 files.append(fn)
1423 fctxs[fn] = p2[fn]
1423 fctxs[fn] = p2[fn]
1424
1424
1425 def fctxfn(repo, cx, path):
1425 def fctxfn(repo, cx, path):
1426 return fctxs.get(path)
1426 return fctxs.get(path)
1427
1427
1428 if len(ps) == 0 or ps[0] < 0:
1428 if len(ps) == 0 or ps[0] < 0:
1429 pars = [None, None]
1429 pars = [None, None]
1430 elif len(ps) == 1:
1430 elif len(ps) == 1:
1431 pars = [nodeids[ps[0]], None]
1431 pars = [nodeids[ps[0]], None]
1432 else:
1432 else:
1433 pars = [nodeids[p] for p in ps]
1433 pars = [nodeids[p] for p in ps]
1434 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1434 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1435 date=(id, 0),
1435 date=(id, 0),
1436 user="debugbuilddag",
1436 user="debugbuilddag",
1437 extra={'branch': atbranch})
1437 extra={'branch': atbranch})
1438 nodeid = repo.commitctx(cx)
1438 nodeid = repo.commitctx(cx)
1439 nodeids.append(nodeid)
1439 nodeids.append(nodeid)
1440 at = id
1440 at = id
1441 elif type == 'l':
1441 elif type == 'l':
1442 id, name = data
1442 id, name = data
1443 ui.note('tag %s\n' % name)
1443 ui.note('tag %s\n' % name)
1444 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1444 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1445 elif type == 'a':
1445 elif type == 'a':
1446 ui.note('branch %s\n' % data)
1446 ui.note('branch %s\n' % data)
1447 atbranch = data
1447 atbranch = data
1448 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1448 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1449 tr.close()
1449 tr.close()
1450
1450
1451 if tags:
1451 if tags:
1452 repo.opener.write("localtags", "".join(tags))
1452 repo.opener.write("localtags", "".join(tags))
1453 finally:
1453 finally:
1454 ui.progress(_('building'), None)
1454 ui.progress(_('building'), None)
1455 release(tr, lock)
1455 release(tr, lock)
1456
1456
1457 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1457 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1458 def debugbundle(ui, bundlepath, all=None, **opts):
1458 def debugbundle(ui, bundlepath, all=None, **opts):
1459 """lists the contents of a bundle"""
1459 """lists the contents of a bundle"""
1460 f = url.open(ui, bundlepath)
1460 f = url.open(ui, bundlepath)
1461 try:
1461 try:
1462 gen = changegroup.readbundle(f, bundlepath)
1462 gen = changegroup.readbundle(f, bundlepath)
1463 if all:
1463 if all:
1464 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1464 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1465
1465
1466 def showchunks(named):
1466 def showchunks(named):
1467 ui.write("\n%s\n" % named)
1467 ui.write("\n%s\n" % named)
1468 chain = None
1468 chain = None
1469 while True:
1469 while True:
1470 chunkdata = gen.deltachunk(chain)
1470 chunkdata = gen.deltachunk(chain)
1471 if not chunkdata:
1471 if not chunkdata:
1472 break
1472 break
1473 node = chunkdata['node']
1473 node = chunkdata['node']
1474 p1 = chunkdata['p1']
1474 p1 = chunkdata['p1']
1475 p2 = chunkdata['p2']
1475 p2 = chunkdata['p2']
1476 cs = chunkdata['cs']
1476 cs = chunkdata['cs']
1477 deltabase = chunkdata['deltabase']
1477 deltabase = chunkdata['deltabase']
1478 delta = chunkdata['delta']
1478 delta = chunkdata['delta']
1479 ui.write("%s %s %s %s %s %s\n" %
1479 ui.write("%s %s %s %s %s %s\n" %
1480 (hex(node), hex(p1), hex(p2),
1480 (hex(node), hex(p1), hex(p2),
1481 hex(cs), hex(deltabase), len(delta)))
1481 hex(cs), hex(deltabase), len(delta)))
1482 chain = node
1482 chain = node
1483
1483
1484 chunkdata = gen.changelogheader()
1484 chunkdata = gen.changelogheader()
1485 showchunks("changelog")
1485 showchunks("changelog")
1486 chunkdata = gen.manifestheader()
1486 chunkdata = gen.manifestheader()
1487 showchunks("manifest")
1487 showchunks("manifest")
1488 while True:
1488 while True:
1489 chunkdata = gen.filelogheader()
1489 chunkdata = gen.filelogheader()
1490 if not chunkdata:
1490 if not chunkdata:
1491 break
1491 break
1492 fname = chunkdata['filename']
1492 fname = chunkdata['filename']
1493 showchunks(fname)
1493 showchunks(fname)
1494 else:
1494 else:
1495 chunkdata = gen.changelogheader()
1495 chunkdata = gen.changelogheader()
1496 chain = None
1496 chain = None
1497 while True:
1497 while True:
1498 chunkdata = gen.deltachunk(chain)
1498 chunkdata = gen.deltachunk(chain)
1499 if not chunkdata:
1499 if not chunkdata:
1500 break
1500 break
1501 node = chunkdata['node']
1501 node = chunkdata['node']
1502 ui.write("%s\n" % hex(node))
1502 ui.write("%s\n" % hex(node))
1503 chain = node
1503 chain = node
1504 finally:
1504 finally:
1505 f.close()
1505 f.close()
1506
1506
1507 @command('debugcheckstate', [], '')
1507 @command('debugcheckstate', [], '')
1508 def debugcheckstate(ui, repo):
1508 def debugcheckstate(ui, repo):
1509 """validate the correctness of the current dirstate"""
1509 """validate the correctness of the current dirstate"""
1510 parent1, parent2 = repo.dirstate.parents()
1510 parent1, parent2 = repo.dirstate.parents()
1511 m1 = repo[parent1].manifest()
1511 m1 = repo[parent1].manifest()
1512 m2 = repo[parent2].manifest()
1512 m2 = repo[parent2].manifest()
1513 errors = 0
1513 errors = 0
1514 for f in repo.dirstate:
1514 for f in repo.dirstate:
1515 state = repo.dirstate[f]
1515 state = repo.dirstate[f]
1516 if state in "nr" and f not in m1:
1516 if state in "nr" and f not in m1:
1517 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1517 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1518 errors += 1
1518 errors += 1
1519 if state in "a" and f in m1:
1519 if state in "a" and f in m1:
1520 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1520 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1521 errors += 1
1521 errors += 1
1522 if state in "m" and f not in m1 and f not in m2:
1522 if state in "m" and f not in m1 and f not in m2:
1523 ui.warn(_("%s in state %s, but not in either manifest\n") %
1523 ui.warn(_("%s in state %s, but not in either manifest\n") %
1524 (f, state))
1524 (f, state))
1525 errors += 1
1525 errors += 1
1526 for f in m1:
1526 for f in m1:
1527 state = repo.dirstate[f]
1527 state = repo.dirstate[f]
1528 if state not in "nrm":
1528 if state not in "nrm":
1529 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1529 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1530 errors += 1
1530 errors += 1
1531 if errors:
1531 if errors:
1532 error = _(".hg/dirstate inconsistent with current parent's manifest")
1532 error = _(".hg/dirstate inconsistent with current parent's manifest")
1533 raise util.Abort(error)
1533 raise util.Abort(error)
1534
1534
1535 @command('debugcommands', [], _('[COMMAND]'))
1535 @command('debugcommands', [], _('[COMMAND]'))
1536 def debugcommands(ui, cmd='', *args):
1536 def debugcommands(ui, cmd='', *args):
1537 """list all available commands and options"""
1537 """list all available commands and options"""
1538 for cmd, vals in sorted(table.iteritems()):
1538 for cmd, vals in sorted(table.iteritems()):
1539 cmd = cmd.split('|')[0].strip('^')
1539 cmd = cmd.split('|')[0].strip('^')
1540 opts = ', '.join([i[1] for i in vals[1]])
1540 opts = ', '.join([i[1] for i in vals[1]])
1541 ui.write('%s: %s\n' % (cmd, opts))
1541 ui.write('%s: %s\n' % (cmd, opts))
1542
1542
1543 @command('debugcomplete',
1543 @command('debugcomplete',
1544 [('o', 'options', None, _('show the command options'))],
1544 [('o', 'options', None, _('show the command options'))],
1545 _('[-o] CMD'))
1545 _('[-o] CMD'))
1546 def debugcomplete(ui, cmd='', **opts):
1546 def debugcomplete(ui, cmd='', **opts):
1547 """returns the completion list associated with the given command"""
1547 """returns the completion list associated with the given command"""
1548
1548
1549 if opts.get('options'):
1549 if opts.get('options'):
1550 options = []
1550 options = []
1551 otables = [globalopts]
1551 otables = [globalopts]
1552 if cmd:
1552 if cmd:
1553 aliases, entry = cmdutil.findcmd(cmd, table, False)
1553 aliases, entry = cmdutil.findcmd(cmd, table, False)
1554 otables.append(entry[1])
1554 otables.append(entry[1])
1555 for t in otables:
1555 for t in otables:
1556 for o in t:
1556 for o in t:
1557 if "(DEPRECATED)" in o[3]:
1557 if "(DEPRECATED)" in o[3]:
1558 continue
1558 continue
1559 if o[0]:
1559 if o[0]:
1560 options.append('-%s' % o[0])
1560 options.append('-%s' % o[0])
1561 options.append('--%s' % o[1])
1561 options.append('--%s' % o[1])
1562 ui.write("%s\n" % "\n".join(options))
1562 ui.write("%s\n" % "\n".join(options))
1563 return
1563 return
1564
1564
1565 cmdlist = cmdutil.findpossible(cmd, table)
1565 cmdlist = cmdutil.findpossible(cmd, table)
1566 if ui.verbose:
1566 if ui.verbose:
1567 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1567 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1568 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1568 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1569
1569
1570 @command('debugdag',
1570 @command('debugdag',
1571 [('t', 'tags', None, _('use tags as labels')),
1571 [('t', 'tags', None, _('use tags as labels')),
1572 ('b', 'branches', None, _('annotate with branch names')),
1572 ('b', 'branches', None, _('annotate with branch names')),
1573 ('', 'dots', None, _('use dots for runs')),
1573 ('', 'dots', None, _('use dots for runs')),
1574 ('s', 'spaces', None, _('separate elements by spaces'))],
1574 ('s', 'spaces', None, _('separate elements by spaces'))],
1575 _('[OPTION]... [FILE [REV]...]'))
1575 _('[OPTION]... [FILE [REV]...]'))
1576 def debugdag(ui, repo, file_=None, *revs, **opts):
1576 def debugdag(ui, repo, file_=None, *revs, **opts):
1577 """format the changelog or an index DAG as a concise textual description
1577 """format the changelog or an index DAG as a concise textual description
1578
1578
1579 If you pass a revlog index, the revlog's DAG is emitted. If you list
1579 If you pass a revlog index, the revlog's DAG is emitted. If you list
1580 revision numbers, they get labelled in the output as rN.
1580 revision numbers, they get labelled in the output as rN.
1581
1581
1582 Otherwise, the changelog DAG of the current repo is emitted.
1582 Otherwise, the changelog DAG of the current repo is emitted.
1583 """
1583 """
1584 spaces = opts.get('spaces')
1584 spaces = opts.get('spaces')
1585 dots = opts.get('dots')
1585 dots = opts.get('dots')
1586 if file_:
1586 if file_:
1587 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1587 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1588 revs = set((int(r) for r in revs))
1588 revs = set((int(r) for r in revs))
1589 def events():
1589 def events():
1590 for r in rlog:
1590 for r in rlog:
1591 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1591 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1592 if r in revs:
1592 if r in revs:
1593 yield 'l', (r, "r%i" % r)
1593 yield 'l', (r, "r%i" % r)
1594 elif repo:
1594 elif repo:
1595 cl = repo.changelog
1595 cl = repo.changelog
1596 tags = opts.get('tags')
1596 tags = opts.get('tags')
1597 branches = opts.get('branches')
1597 branches = opts.get('branches')
1598 if tags:
1598 if tags:
1599 labels = {}
1599 labels = {}
1600 for l, n in repo.tags().items():
1600 for l, n in repo.tags().items():
1601 labels.setdefault(cl.rev(n), []).append(l)
1601 labels.setdefault(cl.rev(n), []).append(l)
1602 def events():
1602 def events():
1603 b = "default"
1603 b = "default"
1604 for r in cl:
1604 for r in cl:
1605 if branches:
1605 if branches:
1606 newb = cl.read(cl.node(r))[5]['branch']
1606 newb = cl.read(cl.node(r))[5]['branch']
1607 if newb != b:
1607 if newb != b:
1608 yield 'a', newb
1608 yield 'a', newb
1609 b = newb
1609 b = newb
1610 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1610 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1611 if tags:
1611 if tags:
1612 ls = labels.get(r)
1612 ls = labels.get(r)
1613 if ls:
1613 if ls:
1614 for l in ls:
1614 for l in ls:
1615 yield 'l', (r, l)
1615 yield 'l', (r, l)
1616 else:
1616 else:
1617 raise util.Abort(_('need repo for changelog dag'))
1617 raise util.Abort(_('need repo for changelog dag'))
1618
1618
1619 for line in dagparser.dagtextlines(events(),
1619 for line in dagparser.dagtextlines(events(),
1620 addspaces=spaces,
1620 addspaces=spaces,
1621 wraplabels=True,
1621 wraplabels=True,
1622 wrapannotations=True,
1622 wrapannotations=True,
1623 wrapnonlinear=dots,
1623 wrapnonlinear=dots,
1624 usedots=dots,
1624 usedots=dots,
1625 maxlinewidth=70):
1625 maxlinewidth=70):
1626 ui.write(line)
1626 ui.write(line)
1627 ui.write("\n")
1627 ui.write("\n")
1628
1628
1629 @command('debugdata',
1629 @command('debugdata',
1630 [('c', 'changelog', False, _('open changelog')),
1630 [('c', 'changelog', False, _('open changelog')),
1631 ('m', 'manifest', False, _('open manifest'))],
1631 ('m', 'manifest', False, _('open manifest'))],
1632 _('-c|-m|FILE REV'))
1632 _('-c|-m|FILE REV'))
1633 def debugdata(ui, repo, file_, rev = None, **opts):
1633 def debugdata(ui, repo, file_, rev = None, **opts):
1634 """dump the contents of a data file revision"""
1634 """dump the contents of a data file revision"""
1635 if opts.get('changelog') or opts.get('manifest'):
1635 if opts.get('changelog') or opts.get('manifest'):
1636 file_, rev = None, file_
1636 file_, rev = None, file_
1637 elif rev is None:
1637 elif rev is None:
1638 raise error.CommandError('debugdata', _('invalid arguments'))
1638 raise error.CommandError('debugdata', _('invalid arguments'))
1639 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1639 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1640 try:
1640 try:
1641 ui.write(r.revision(r.lookup(rev)))
1641 ui.write(r.revision(r.lookup(rev)))
1642 except KeyError:
1642 except KeyError:
1643 raise util.Abort(_('invalid revision identifier %s') % rev)
1643 raise util.Abort(_('invalid revision identifier %s') % rev)
1644
1644
1645 @command('debugdate',
1645 @command('debugdate',
1646 [('e', 'extended', None, _('try extended date formats'))],
1646 [('e', 'extended', None, _('try extended date formats'))],
1647 _('[-e] DATE [RANGE]'))
1647 _('[-e] DATE [RANGE]'))
1648 def debugdate(ui, date, range=None, **opts):
1648 def debugdate(ui, date, range=None, **opts):
1649 """parse and display a date"""
1649 """parse and display a date"""
1650 if opts["extended"]:
1650 if opts["extended"]:
1651 d = util.parsedate(date, util.extendeddateformats)
1651 d = util.parsedate(date, util.extendeddateformats)
1652 else:
1652 else:
1653 d = util.parsedate(date)
1653 d = util.parsedate(date)
1654 ui.write("internal: %s %s\n" % d)
1654 ui.write("internal: %s %s\n" % d)
1655 ui.write("standard: %s\n" % util.datestr(d))
1655 ui.write("standard: %s\n" % util.datestr(d))
1656 if range:
1656 if range:
1657 m = util.matchdate(range)
1657 m = util.matchdate(range)
1658 ui.write("match: %s\n" % m(d[0]))
1658 ui.write("match: %s\n" % m(d[0]))
1659
1659
1660 @command('debugdiscovery',
1660 @command('debugdiscovery',
1661 [('', 'old', None, _('use old-style discovery')),
1661 [('', 'old', None, _('use old-style discovery')),
1662 ('', 'nonheads', None,
1662 ('', 'nonheads', None,
1663 _('use old-style discovery with non-heads included')),
1663 _('use old-style discovery with non-heads included')),
1664 ] + remoteopts,
1664 ] + remoteopts,
1665 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1665 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1666 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1666 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1667 """runs the changeset discovery protocol in isolation"""
1667 """runs the changeset discovery protocol in isolation"""
1668 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1668 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1669 remote = hg.peer(repo, opts, remoteurl)
1669 remote = hg.peer(repo, opts, remoteurl)
1670 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1670 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1671
1671
1672 # make sure tests are repeatable
1672 # make sure tests are repeatable
1673 random.seed(12323)
1673 random.seed(12323)
1674
1674
1675 def doit(localheads, remoteheads):
1675 def doit(localheads, remoteheads):
1676 if opts.get('old'):
1676 if opts.get('old'):
1677 if localheads:
1677 if localheads:
1678 raise util.Abort('cannot use localheads with old style discovery')
1678 raise util.Abort('cannot use localheads with old style discovery')
1679 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1679 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1680 force=True)
1680 force=True)
1681 common = set(common)
1681 common = set(common)
1682 if not opts.get('nonheads'):
1682 if not opts.get('nonheads'):
1683 ui.write("unpruned common: %s\n" % " ".join([short(n)
1683 ui.write("unpruned common: %s\n" % " ".join([short(n)
1684 for n in common]))
1684 for n in common]))
1685 dag = dagutil.revlogdag(repo.changelog)
1685 dag = dagutil.revlogdag(repo.changelog)
1686 all = dag.ancestorset(dag.internalizeall(common))
1686 all = dag.ancestorset(dag.internalizeall(common))
1687 common = dag.externalizeall(dag.headsetofconnecteds(all))
1687 common = dag.externalizeall(dag.headsetofconnecteds(all))
1688 else:
1688 else:
1689 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1689 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1690 common = set(common)
1690 common = set(common)
1691 rheads = set(hds)
1691 rheads = set(hds)
1692 lheads = set(repo.heads())
1692 lheads = set(repo.heads())
1693 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1693 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1694 if lheads <= common:
1694 if lheads <= common:
1695 ui.write("local is subset\n")
1695 ui.write("local is subset\n")
1696 elif rheads <= common:
1696 elif rheads <= common:
1697 ui.write("remote is subset\n")
1697 ui.write("remote is subset\n")
1698
1698
1699 serverlogs = opts.get('serverlog')
1699 serverlogs = opts.get('serverlog')
1700 if serverlogs:
1700 if serverlogs:
1701 for filename in serverlogs:
1701 for filename in serverlogs:
1702 logfile = open(filename, 'r')
1702 logfile = open(filename, 'r')
1703 try:
1703 try:
1704 line = logfile.readline()
1704 line = logfile.readline()
1705 while line:
1705 while line:
1706 parts = line.strip().split(';')
1706 parts = line.strip().split(';')
1707 op = parts[1]
1707 op = parts[1]
1708 if op == 'cg':
1708 if op == 'cg':
1709 pass
1709 pass
1710 elif op == 'cgss':
1710 elif op == 'cgss':
1711 doit(parts[2].split(' '), parts[3].split(' '))
1711 doit(parts[2].split(' '), parts[3].split(' '))
1712 elif op == 'unb':
1712 elif op == 'unb':
1713 doit(parts[3].split(' '), parts[2].split(' '))
1713 doit(parts[3].split(' '), parts[2].split(' '))
1714 line = logfile.readline()
1714 line = logfile.readline()
1715 finally:
1715 finally:
1716 logfile.close()
1716 logfile.close()
1717
1717
1718 else:
1718 else:
1719 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1719 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1720 opts.get('remote_head'))
1720 opts.get('remote_head'))
1721 localrevs = opts.get('local_head')
1721 localrevs = opts.get('local_head')
1722 doit(localrevs, remoterevs)
1722 doit(localrevs, remoterevs)
1723
1723
1724 @command('debugfileset', [], ('REVSPEC'))
1724 @command('debugfileset', [], ('REVSPEC'))
1725 def debugfileset(ui, repo, expr):
1725 def debugfileset(ui, repo, expr):
1726 '''parse and apply a fileset specification'''
1726 '''parse and apply a fileset specification'''
1727 if ui.verbose:
1727 if ui.verbose:
1728 tree = fileset.parse(expr)[0]
1728 tree = fileset.parse(expr)[0]
1729 ui.note(tree, "\n")
1729 ui.note(tree, "\n")
1730
1730
1731 for f in fileset.getfileset(repo[None], expr):
1731 for f in fileset.getfileset(repo[None], expr):
1732 ui.write("%s\n" % f)
1732 ui.write("%s\n" % f)
1733
1733
1734 @command('debugfsinfo', [], _('[PATH]'))
1734 @command('debugfsinfo', [], _('[PATH]'))
1735 def debugfsinfo(ui, path = "."):
1735 def debugfsinfo(ui, path = "."):
1736 """show information detected about current filesystem"""
1736 """show information detected about current filesystem"""
1737 util.writefile('.debugfsinfo', '')
1737 util.writefile('.debugfsinfo', '')
1738 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1738 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1739 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1739 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1740 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1740 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1741 and 'yes' or 'no'))
1741 and 'yes' or 'no'))
1742 os.unlink('.debugfsinfo')
1742 os.unlink('.debugfsinfo')
1743
1743
1744 @command('debuggetbundle',
1744 @command('debuggetbundle',
1745 [('H', 'head', [], _('id of head node'), _('ID')),
1745 [('H', 'head', [], _('id of head node'), _('ID')),
1746 ('C', 'common', [], _('id of common node'), _('ID')),
1746 ('C', 'common', [], _('id of common node'), _('ID')),
1747 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1747 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1748 _('REPO FILE [-H|-C ID]...'))
1748 _('REPO FILE [-H|-C ID]...'))
1749 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1749 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1750 """retrieves a bundle from a repo
1750 """retrieves a bundle from a repo
1751
1751
1752 Every ID must be a full-length hex node id string. Saves the bundle to the
1752 Every ID must be a full-length hex node id string. Saves the bundle to the
1753 given file.
1753 given file.
1754 """
1754 """
1755 repo = hg.peer(ui, opts, repopath)
1755 repo = hg.peer(ui, opts, repopath)
1756 if not repo.capable('getbundle'):
1756 if not repo.capable('getbundle'):
1757 raise util.Abort("getbundle() not supported by target repository")
1757 raise util.Abort("getbundle() not supported by target repository")
1758 args = {}
1758 args = {}
1759 if common:
1759 if common:
1760 args['common'] = [bin(s) for s in common]
1760 args['common'] = [bin(s) for s in common]
1761 if head:
1761 if head:
1762 args['heads'] = [bin(s) for s in head]
1762 args['heads'] = [bin(s) for s in head]
1763 bundle = repo.getbundle('debug', **args)
1763 bundle = repo.getbundle('debug', **args)
1764
1764
1765 bundletype = opts.get('type', 'bzip2').lower()
1765 bundletype = opts.get('type', 'bzip2').lower()
1766 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1766 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1767 bundletype = btypes.get(bundletype)
1767 bundletype = btypes.get(bundletype)
1768 if bundletype not in changegroup.bundletypes:
1768 if bundletype not in changegroup.bundletypes:
1769 raise util.Abort(_('unknown bundle type specified with --type'))
1769 raise util.Abort(_('unknown bundle type specified with --type'))
1770 changegroup.writebundle(bundle, bundlepath, bundletype)
1770 changegroup.writebundle(bundle, bundlepath, bundletype)
1771
1771
1772 @command('debugignore', [], '')
1772 @command('debugignore', [], '')
1773 def debugignore(ui, repo, *values, **opts):
1773 def debugignore(ui, repo, *values, **opts):
1774 """display the combined ignore pattern"""
1774 """display the combined ignore pattern"""
1775 ignore = repo.dirstate._ignore
1775 ignore = repo.dirstate._ignore
1776 includepat = getattr(ignore, 'includepat', None)
1776 includepat = getattr(ignore, 'includepat', None)
1777 if includepat is not None:
1777 if includepat is not None:
1778 ui.write("%s\n" % includepat)
1778 ui.write("%s\n" % includepat)
1779 else:
1779 else:
1780 raise util.Abort(_("no ignore patterns found"))
1780 raise util.Abort(_("no ignore patterns found"))
1781
1781
1782 @command('debugindex',
1782 @command('debugindex',
1783 [('c', 'changelog', False, _('open changelog')),
1783 [('c', 'changelog', False, _('open changelog')),
1784 ('m', 'manifest', False, _('open manifest')),
1784 ('m', 'manifest', False, _('open manifest')),
1785 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1785 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1786 _('[-f FORMAT] -c|-m|FILE'))
1786 _('[-f FORMAT] -c|-m|FILE'))
1787 def debugindex(ui, repo, file_ = None, **opts):
1787 def debugindex(ui, repo, file_ = None, **opts):
1788 """dump the contents of an index file"""
1788 """dump the contents of an index file"""
1789 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1789 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1790 format = opts.get('format', 0)
1790 format = opts.get('format', 0)
1791 if format not in (0, 1):
1791 if format not in (0, 1):
1792 raise util.Abort(_("unknown format %d") % format)
1792 raise util.Abort(_("unknown format %d") % format)
1793
1793
1794 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1794 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1795 if generaldelta:
1795 if generaldelta:
1796 basehdr = ' delta'
1796 basehdr = ' delta'
1797 else:
1797 else:
1798 basehdr = ' base'
1798 basehdr = ' base'
1799
1799
1800 if format == 0:
1800 if format == 0:
1801 ui.write(" rev offset length " + basehdr + " linkrev"
1801 ui.write(" rev offset length " + basehdr + " linkrev"
1802 " nodeid p1 p2\n")
1802 " nodeid p1 p2\n")
1803 elif format == 1:
1803 elif format == 1:
1804 ui.write(" rev flag offset length"
1804 ui.write(" rev flag offset length"
1805 " size " + basehdr + " link p1 p2 nodeid\n")
1805 " size " + basehdr + " link p1 p2 nodeid\n")
1806
1806
1807 for i in r:
1807 for i in r:
1808 node = r.node(i)
1808 node = r.node(i)
1809 if generaldelta:
1809 if generaldelta:
1810 base = r.deltaparent(i)
1810 base = r.deltaparent(i)
1811 else:
1811 else:
1812 base = r.chainbase(i)
1812 base = r.chainbase(i)
1813 if format == 0:
1813 if format == 0:
1814 try:
1814 try:
1815 pp = r.parents(node)
1815 pp = r.parents(node)
1816 except:
1816 except:
1817 pp = [nullid, nullid]
1817 pp = [nullid, nullid]
1818 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1818 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1819 i, r.start(i), r.length(i), base, r.linkrev(i),
1819 i, r.start(i), r.length(i), base, r.linkrev(i),
1820 short(node), short(pp[0]), short(pp[1])))
1820 short(node), short(pp[0]), short(pp[1])))
1821 elif format == 1:
1821 elif format == 1:
1822 pr = r.parentrevs(i)
1822 pr = r.parentrevs(i)
1823 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1823 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1824 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1824 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1825 base, r.linkrev(i), pr[0], pr[1], short(node)))
1825 base, r.linkrev(i), pr[0], pr[1], short(node)))
1826
1826
1827 @command('debugindexdot', [], _('FILE'))
1827 @command('debugindexdot', [], _('FILE'))
1828 def debugindexdot(ui, repo, file_):
1828 def debugindexdot(ui, repo, file_):
1829 """dump an index DAG as a graphviz dot file"""
1829 """dump an index DAG as a graphviz dot file"""
1830 r = None
1830 r = None
1831 if repo:
1831 if repo:
1832 filelog = repo.file(file_)
1832 filelog = repo.file(file_)
1833 if len(filelog):
1833 if len(filelog):
1834 r = filelog
1834 r = filelog
1835 if not r:
1835 if not r:
1836 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1836 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1837 ui.write("digraph G {\n")
1837 ui.write("digraph G {\n")
1838 for i in r:
1838 for i in r:
1839 node = r.node(i)
1839 node = r.node(i)
1840 pp = r.parents(node)
1840 pp = r.parents(node)
1841 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1841 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1842 if pp[1] != nullid:
1842 if pp[1] != nullid:
1843 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1843 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1844 ui.write("}\n")
1844 ui.write("}\n")
1845
1845
1846 @command('debuginstall', [], '')
1846 @command('debuginstall', [], '')
1847 def debuginstall(ui):
1847 def debuginstall(ui):
1848 '''test Mercurial installation
1848 '''test Mercurial installation
1849
1849
1850 Returns 0 on success.
1850 Returns 0 on success.
1851 '''
1851 '''
1852
1852
1853 def writetemp(contents):
1853 def writetemp(contents):
1854 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1854 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1855 f = os.fdopen(fd, "wb")
1855 f = os.fdopen(fd, "wb")
1856 f.write(contents)
1856 f.write(contents)
1857 f.close()
1857 f.close()
1858 return name
1858 return name
1859
1859
1860 problems = 0
1860 problems = 0
1861
1861
1862 # encoding
1862 # encoding
1863 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1863 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1864 try:
1864 try:
1865 encoding.fromlocal("test")
1865 encoding.fromlocal("test")
1866 except util.Abort, inst:
1866 except util.Abort, inst:
1867 ui.write(" %s\n" % inst)
1867 ui.write(" %s\n" % inst)
1868 ui.write(_(" (check that your locale is properly set)\n"))
1868 ui.write(_(" (check that your locale is properly set)\n"))
1869 problems += 1
1869 problems += 1
1870
1870
1871 # compiled modules
1871 # compiled modules
1872 ui.status(_("Checking installed modules (%s)...\n")
1872 ui.status(_("Checking installed modules (%s)...\n")
1873 % os.path.dirname(__file__))
1873 % os.path.dirname(__file__))
1874 try:
1874 try:
1875 import bdiff, mpatch, base85, osutil
1875 import bdiff, mpatch, base85, osutil
1876 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1876 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1877 except Exception, inst:
1877 except Exception, inst:
1878 ui.write(" %s\n" % inst)
1878 ui.write(" %s\n" % inst)
1879 ui.write(_(" One or more extensions could not be found"))
1879 ui.write(_(" One or more extensions could not be found"))
1880 ui.write(_(" (check that you compiled the extensions)\n"))
1880 ui.write(_(" (check that you compiled the extensions)\n"))
1881 problems += 1
1881 problems += 1
1882
1882
1883 # templates
1883 # templates
1884 import templater
1884 import templater
1885 p = templater.templatepath()
1885 p = templater.templatepath()
1886 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1886 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1887 try:
1887 try:
1888 templater.templater(templater.templatepath("map-cmdline.default"))
1888 templater.templater(templater.templatepath("map-cmdline.default"))
1889 except Exception, inst:
1889 except Exception, inst:
1890 ui.write(" %s\n" % inst)
1890 ui.write(" %s\n" % inst)
1891 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1891 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1892 problems += 1
1892 problems += 1
1893
1893
1894 # editor
1894 # editor
1895 ui.status(_("Checking commit editor...\n"))
1895 ui.status(_("Checking commit editor...\n"))
1896 editor = ui.geteditor()
1896 editor = ui.geteditor()
1897 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1897 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1898 if not cmdpath:
1898 if not cmdpath:
1899 if editor == 'vi':
1899 if editor == 'vi':
1900 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1900 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1901 ui.write(_(" (specify a commit editor in your configuration"
1901 ui.write(_(" (specify a commit editor in your configuration"
1902 " file)\n"))
1902 " file)\n"))
1903 else:
1903 else:
1904 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1904 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1905 ui.write(_(" (specify a commit editor in your configuration"
1905 ui.write(_(" (specify a commit editor in your configuration"
1906 " file)\n"))
1906 " file)\n"))
1907 problems += 1
1907 problems += 1
1908
1908
1909 # check username
1909 # check username
1910 ui.status(_("Checking username...\n"))
1910 ui.status(_("Checking username...\n"))
1911 try:
1911 try:
1912 ui.username()
1912 ui.username()
1913 except util.Abort, e:
1913 except util.Abort, e:
1914 ui.write(" %s\n" % e)
1914 ui.write(" %s\n" % e)
1915 ui.write(_(" (specify a username in your configuration file)\n"))
1915 ui.write(_(" (specify a username in your configuration file)\n"))
1916 problems += 1
1916 problems += 1
1917
1917
1918 if not problems:
1918 if not problems:
1919 ui.status(_("No problems detected\n"))
1919 ui.status(_("No problems detected\n"))
1920 else:
1920 else:
1921 ui.write(_("%s problems detected,"
1921 ui.write(_("%s problems detected,"
1922 " please check your install!\n") % problems)
1922 " please check your install!\n") % problems)
1923
1923
1924 return problems
1924 return problems
1925
1925
1926 @command('debugknown', [], _('REPO ID...'))
1926 @command('debugknown', [], _('REPO ID...'))
1927 def debugknown(ui, repopath, *ids, **opts):
1927 def debugknown(ui, repopath, *ids, **opts):
1928 """test whether node ids are known to a repo
1928 """test whether node ids are known to a repo
1929
1929
1930 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1930 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1931 indicating unknown/known.
1931 indicating unknown/known.
1932 """
1932 """
1933 repo = hg.peer(ui, opts, repopath)
1933 repo = hg.peer(ui, opts, repopath)
1934 if not repo.capable('known'):
1934 if not repo.capable('known'):
1935 raise util.Abort("known() not supported by target repository")
1935 raise util.Abort("known() not supported by target repository")
1936 flags = repo.known([bin(s) for s in ids])
1936 flags = repo.known([bin(s) for s in ids])
1937 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1937 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1938
1938
1939 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1939 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1940 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1940 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1941 '''access the pushkey key/value protocol
1941 '''access the pushkey key/value protocol
1942
1942
1943 With two args, list the keys in the given namespace.
1943 With two args, list the keys in the given namespace.
1944
1944
1945 With five args, set a key to new if it currently is set to old.
1945 With five args, set a key to new if it currently is set to old.
1946 Reports success or failure.
1946 Reports success or failure.
1947 '''
1947 '''
1948
1948
1949 target = hg.peer(ui, {}, repopath)
1949 target = hg.peer(ui, {}, repopath)
1950 if keyinfo:
1950 if keyinfo:
1951 key, old, new = keyinfo
1951 key, old, new = keyinfo
1952 r = target.pushkey(namespace, key, old, new)
1952 r = target.pushkey(namespace, key, old, new)
1953 ui.status(str(r) + '\n')
1953 ui.status(str(r) + '\n')
1954 return not r
1954 return not r
1955 else:
1955 else:
1956 for k, v in target.listkeys(namespace).iteritems():
1956 for k, v in target.listkeys(namespace).iteritems():
1957 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1957 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1958 v.encode('string-escape')))
1958 v.encode('string-escape')))
1959
1959
1960 @command('debugrebuildstate',
1960 @command('debugrebuildstate',
1961 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1961 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1962 _('[-r REV] [REV]'))
1962 _('[-r REV] [REV]'))
1963 def debugrebuildstate(ui, repo, rev="tip"):
1963 def debugrebuildstate(ui, repo, rev="tip"):
1964 """rebuild the dirstate as it would look like for the given revision"""
1964 """rebuild the dirstate as it would look like for the given revision"""
1965 ctx = scmutil.revsingle(repo, rev)
1965 ctx = scmutil.revsingle(repo, rev)
1966 wlock = repo.wlock()
1966 wlock = repo.wlock()
1967 try:
1967 try:
1968 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1968 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1969 finally:
1969 finally:
1970 wlock.release()
1970 wlock.release()
1971
1971
1972 @command('debugrename',
1972 @command('debugrename',
1973 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1973 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1974 _('[-r REV] FILE'))
1974 _('[-r REV] FILE'))
1975 def debugrename(ui, repo, file1, *pats, **opts):
1975 def debugrename(ui, repo, file1, *pats, **opts):
1976 """dump rename information"""
1976 """dump rename information"""
1977
1977
1978 ctx = scmutil.revsingle(repo, opts.get('rev'))
1978 ctx = scmutil.revsingle(repo, opts.get('rev'))
1979 m = scmutil.match(ctx, (file1,) + pats, opts)
1979 m = scmutil.match(ctx, (file1,) + pats, opts)
1980 for abs in ctx.walk(m):
1980 for abs in ctx.walk(m):
1981 fctx = ctx[abs]
1981 fctx = ctx[abs]
1982 o = fctx.filelog().renamed(fctx.filenode())
1982 o = fctx.filelog().renamed(fctx.filenode())
1983 rel = m.rel(abs)
1983 rel = m.rel(abs)
1984 if o:
1984 if o:
1985 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1985 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1986 else:
1986 else:
1987 ui.write(_("%s not renamed\n") % rel)
1987 ui.write(_("%s not renamed\n") % rel)
1988
1988
1989 @command('debugrevlog',
1989 @command('debugrevlog',
1990 [('c', 'changelog', False, _('open changelog')),
1990 [('c', 'changelog', False, _('open changelog')),
1991 ('m', 'manifest', False, _('open manifest')),
1991 ('m', 'manifest', False, _('open manifest')),
1992 ('d', 'dump', False, _('dump index data'))],
1992 ('d', 'dump', False, _('dump index data'))],
1993 _('-c|-m|FILE'))
1993 _('-c|-m|FILE'))
1994 def debugrevlog(ui, repo, file_ = None, **opts):
1994 def debugrevlog(ui, repo, file_ = None, **opts):
1995 """show data and statistics about a revlog"""
1995 """show data and statistics about a revlog"""
1996 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1996 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1997
1997
1998 if opts.get("dump"):
1998 if opts.get("dump"):
1999 numrevs = len(r)
1999 numrevs = len(r)
2000 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2000 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2001 " rawsize totalsize compression heads\n")
2001 " rawsize totalsize compression heads\n")
2002 ts = 0
2002 ts = 0
2003 heads = set()
2003 heads = set()
2004 for rev in xrange(numrevs):
2004 for rev in xrange(numrevs):
2005 dbase = r.deltaparent(rev)
2005 dbase = r.deltaparent(rev)
2006 if dbase == -1:
2006 if dbase == -1:
2007 dbase = rev
2007 dbase = rev
2008 cbase = r.chainbase(rev)
2008 cbase = r.chainbase(rev)
2009 p1, p2 = r.parentrevs(rev)
2009 p1, p2 = r.parentrevs(rev)
2010 rs = r.rawsize(rev)
2010 rs = r.rawsize(rev)
2011 ts = ts + rs
2011 ts = ts + rs
2012 heads -= set(r.parentrevs(rev))
2012 heads -= set(r.parentrevs(rev))
2013 heads.add(rev)
2013 heads.add(rev)
2014 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2014 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2015 (rev, p1, p2, r.start(rev), r.end(rev),
2015 (rev, p1, p2, r.start(rev), r.end(rev),
2016 r.start(dbase), r.start(cbase),
2016 r.start(dbase), r.start(cbase),
2017 r.start(p1), r.start(p2),
2017 r.start(p1), r.start(p2),
2018 rs, ts, ts / r.end(rev), len(heads)))
2018 rs, ts, ts / r.end(rev), len(heads)))
2019 return 0
2019 return 0
2020
2020
2021 v = r.version
2021 v = r.version
2022 format = v & 0xFFFF
2022 format = v & 0xFFFF
2023 flags = []
2023 flags = []
2024 gdelta = False
2024 gdelta = False
2025 if v & revlog.REVLOGNGINLINEDATA:
2025 if v & revlog.REVLOGNGINLINEDATA:
2026 flags.append('inline')
2026 flags.append('inline')
2027 if v & revlog.REVLOGGENERALDELTA:
2027 if v & revlog.REVLOGGENERALDELTA:
2028 gdelta = True
2028 gdelta = True
2029 flags.append('generaldelta')
2029 flags.append('generaldelta')
2030 if not flags:
2030 if not flags:
2031 flags = ['(none)']
2031 flags = ['(none)']
2032
2032
2033 nummerges = 0
2033 nummerges = 0
2034 numfull = 0
2034 numfull = 0
2035 numprev = 0
2035 numprev = 0
2036 nump1 = 0
2036 nump1 = 0
2037 nump2 = 0
2037 nump2 = 0
2038 numother = 0
2038 numother = 0
2039 nump1prev = 0
2039 nump1prev = 0
2040 nump2prev = 0
2040 nump2prev = 0
2041 chainlengths = []
2041 chainlengths = []
2042
2042
2043 datasize = [None, 0, 0L]
2043 datasize = [None, 0, 0L]
2044 fullsize = [None, 0, 0L]
2044 fullsize = [None, 0, 0L]
2045 deltasize = [None, 0, 0L]
2045 deltasize = [None, 0, 0L]
2046
2046
2047 def addsize(size, l):
2047 def addsize(size, l):
2048 if l[0] is None or size < l[0]:
2048 if l[0] is None or size < l[0]:
2049 l[0] = size
2049 l[0] = size
2050 if size > l[1]:
2050 if size > l[1]:
2051 l[1] = size
2051 l[1] = size
2052 l[2] += size
2052 l[2] += size
2053
2053
2054 numrevs = len(r)
2054 numrevs = len(r)
2055 for rev in xrange(numrevs):
2055 for rev in xrange(numrevs):
2056 p1, p2 = r.parentrevs(rev)
2056 p1, p2 = r.parentrevs(rev)
2057 delta = r.deltaparent(rev)
2057 delta = r.deltaparent(rev)
2058 if format > 0:
2058 if format > 0:
2059 addsize(r.rawsize(rev), datasize)
2059 addsize(r.rawsize(rev), datasize)
2060 if p2 != nullrev:
2060 if p2 != nullrev:
2061 nummerges += 1
2061 nummerges += 1
2062 size = r.length(rev)
2062 size = r.length(rev)
2063 if delta == nullrev:
2063 if delta == nullrev:
2064 chainlengths.append(0)
2064 chainlengths.append(0)
2065 numfull += 1
2065 numfull += 1
2066 addsize(size, fullsize)
2066 addsize(size, fullsize)
2067 else:
2067 else:
2068 chainlengths.append(chainlengths[delta] + 1)
2068 chainlengths.append(chainlengths[delta] + 1)
2069 addsize(size, deltasize)
2069 addsize(size, deltasize)
2070 if delta == rev - 1:
2070 if delta == rev - 1:
2071 numprev += 1
2071 numprev += 1
2072 if delta == p1:
2072 if delta == p1:
2073 nump1prev += 1
2073 nump1prev += 1
2074 elif delta == p2:
2074 elif delta == p2:
2075 nump2prev += 1
2075 nump2prev += 1
2076 elif delta == p1:
2076 elif delta == p1:
2077 nump1 += 1
2077 nump1 += 1
2078 elif delta == p2:
2078 elif delta == p2:
2079 nump2 += 1
2079 nump2 += 1
2080 elif delta != nullrev:
2080 elif delta != nullrev:
2081 numother += 1
2081 numother += 1
2082
2082
2083 numdeltas = numrevs - numfull
2083 numdeltas = numrevs - numfull
2084 numoprev = numprev - nump1prev - nump2prev
2084 numoprev = numprev - nump1prev - nump2prev
2085 totalrawsize = datasize[2]
2085 totalrawsize = datasize[2]
2086 datasize[2] /= numrevs
2086 datasize[2] /= numrevs
2087 fulltotal = fullsize[2]
2087 fulltotal = fullsize[2]
2088 fullsize[2] /= numfull
2088 fullsize[2] /= numfull
2089 deltatotal = deltasize[2]
2089 deltatotal = deltasize[2]
2090 deltasize[2] /= numrevs - numfull
2090 deltasize[2] /= numrevs - numfull
2091 totalsize = fulltotal + deltatotal
2091 totalsize = fulltotal + deltatotal
2092 avgchainlen = sum(chainlengths) / numrevs
2092 avgchainlen = sum(chainlengths) / numrevs
2093 compratio = totalrawsize / totalsize
2093 compratio = totalrawsize / totalsize
2094
2094
2095 basedfmtstr = '%%%dd\n'
2095 basedfmtstr = '%%%dd\n'
2096 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2096 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2097
2097
2098 def dfmtstr(max):
2098 def dfmtstr(max):
2099 return basedfmtstr % len(str(max))
2099 return basedfmtstr % len(str(max))
2100 def pcfmtstr(max, padding=0):
2100 def pcfmtstr(max, padding=0):
2101 return basepcfmtstr % (len(str(max)), ' ' * padding)
2101 return basepcfmtstr % (len(str(max)), ' ' * padding)
2102
2102
2103 def pcfmt(value, total):
2103 def pcfmt(value, total):
2104 return (value, 100 * float(value) / total)
2104 return (value, 100 * float(value) / total)
2105
2105
2106 ui.write('format : %d\n' % format)
2106 ui.write('format : %d\n' % format)
2107 ui.write('flags : %s\n' % ', '.join(flags))
2107 ui.write('flags : %s\n' % ', '.join(flags))
2108
2108
2109 ui.write('\n')
2109 ui.write('\n')
2110 fmt = pcfmtstr(totalsize)
2110 fmt = pcfmtstr(totalsize)
2111 fmt2 = dfmtstr(totalsize)
2111 fmt2 = dfmtstr(totalsize)
2112 ui.write('revisions : ' + fmt2 % numrevs)
2112 ui.write('revisions : ' + fmt2 % numrevs)
2113 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2113 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2114 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2114 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2115 ui.write('revisions : ' + fmt2 % numrevs)
2115 ui.write('revisions : ' + fmt2 % numrevs)
2116 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2116 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2117 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2117 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2118 ui.write('revision size : ' + fmt2 % totalsize)
2118 ui.write('revision size : ' + fmt2 % totalsize)
2119 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2119 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2120 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2120 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2121
2121
2122 ui.write('\n')
2122 ui.write('\n')
2123 fmt = dfmtstr(max(avgchainlen, compratio))
2123 fmt = dfmtstr(max(avgchainlen, compratio))
2124 ui.write('avg chain length : ' + fmt % avgchainlen)
2124 ui.write('avg chain length : ' + fmt % avgchainlen)
2125 ui.write('compression ratio : ' + fmt % compratio)
2125 ui.write('compression ratio : ' + fmt % compratio)
2126
2126
2127 if format > 0:
2127 if format > 0:
2128 ui.write('\n')
2128 ui.write('\n')
2129 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2129 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2130 % tuple(datasize))
2130 % tuple(datasize))
2131 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2131 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2132 % tuple(fullsize))
2132 % tuple(fullsize))
2133 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2133 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2134 % tuple(deltasize))
2134 % tuple(deltasize))
2135
2135
2136 if numdeltas > 0:
2136 if numdeltas > 0:
2137 ui.write('\n')
2137 ui.write('\n')
2138 fmt = pcfmtstr(numdeltas)
2138 fmt = pcfmtstr(numdeltas)
2139 fmt2 = pcfmtstr(numdeltas, 4)
2139 fmt2 = pcfmtstr(numdeltas, 4)
2140 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2140 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2141 if numprev > 0:
2141 if numprev > 0:
2142 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2142 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2143 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2143 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2144 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2144 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2145 if gdelta:
2145 if gdelta:
2146 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2146 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2147 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2147 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2148 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2148 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2149
2149
2150 @command('debugrevspec', [], ('REVSPEC'))
2150 @command('debugrevspec', [], ('REVSPEC'))
2151 def debugrevspec(ui, repo, expr):
2151 def debugrevspec(ui, repo, expr):
2152 '''parse and apply a revision specification'''
2152 '''parse and apply a revision specification'''
2153 if ui.verbose:
2153 if ui.verbose:
2154 tree = revset.parse(expr)[0]
2154 tree = revset.parse(expr)[0]
2155 ui.note(tree, "\n")
2155 ui.note(tree, "\n")
2156 newtree = revset.findaliases(ui, tree)
2156 newtree = revset.findaliases(ui, tree)
2157 if newtree != tree:
2157 if newtree != tree:
2158 ui.note(newtree, "\n")
2158 ui.note(newtree, "\n")
2159 func = revset.match(ui, expr)
2159 func = revset.match(ui, expr)
2160 for c in func(repo, range(len(repo))):
2160 for c in func(repo, range(len(repo))):
2161 ui.write("%s\n" % c)
2161 ui.write("%s\n" % c)
2162
2162
2163 @command('debugsetparents', [], _('REV1 [REV2]'))
2163 @command('debugsetparents', [], _('REV1 [REV2]'))
2164 def debugsetparents(ui, repo, rev1, rev2=None):
2164 def debugsetparents(ui, repo, rev1, rev2=None):
2165 """manually set the parents of the current working directory
2165 """manually set the parents of the current working directory
2166
2166
2167 This is useful for writing repository conversion tools, but should
2167 This is useful for writing repository conversion tools, but should
2168 be used with care.
2168 be used with care.
2169
2169
2170 Returns 0 on success.
2170 Returns 0 on success.
2171 """
2171 """
2172
2172
2173 r1 = scmutil.revsingle(repo, rev1).node()
2173 r1 = scmutil.revsingle(repo, rev1).node()
2174 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2174 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2175
2175
2176 wlock = repo.wlock()
2176 wlock = repo.wlock()
2177 try:
2177 try:
2178 repo.dirstate.setparents(r1, r2)
2178 repo.dirstate.setparents(r1, r2)
2179 finally:
2179 finally:
2180 wlock.release()
2180 wlock.release()
2181
2181
2182 @command('debugstate',
2182 @command('debugstate',
2183 [('', 'nodates', None, _('do not display the saved mtime')),
2183 [('', 'nodates', None, _('do not display the saved mtime')),
2184 ('', 'datesort', None, _('sort by saved mtime'))],
2184 ('', 'datesort', None, _('sort by saved mtime'))],
2185 _('[OPTION]...'))
2185 _('[OPTION]...'))
2186 def debugstate(ui, repo, nodates=None, datesort=None):
2186 def debugstate(ui, repo, nodates=None, datesort=None):
2187 """show the contents of the current dirstate"""
2187 """show the contents of the current dirstate"""
2188 timestr = ""
2188 timestr = ""
2189 showdate = not nodates
2189 showdate = not nodates
2190 if datesort:
2190 if datesort:
2191 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2191 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2192 else:
2192 else:
2193 keyfunc = None # sort by filename
2193 keyfunc = None # sort by filename
2194 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2194 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2195 if showdate:
2195 if showdate:
2196 if ent[3] == -1:
2196 if ent[3] == -1:
2197 # Pad or slice to locale representation
2197 # Pad or slice to locale representation
2198 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2198 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2199 time.localtime(0)))
2199 time.localtime(0)))
2200 timestr = 'unset'
2200 timestr = 'unset'
2201 timestr = (timestr[:locale_len] +
2201 timestr = (timestr[:locale_len] +
2202 ' ' * (locale_len - len(timestr)))
2202 ' ' * (locale_len - len(timestr)))
2203 else:
2203 else:
2204 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2204 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2205 time.localtime(ent[3]))
2205 time.localtime(ent[3]))
2206 if ent[1] & 020000:
2206 if ent[1] & 020000:
2207 mode = 'lnk'
2207 mode = 'lnk'
2208 else:
2208 else:
2209 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2209 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2210 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2210 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2211 for f in repo.dirstate.copies():
2211 for f in repo.dirstate.copies():
2212 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2212 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2213
2213
2214 @command('debugsub',
2214 @command('debugsub',
2215 [('r', 'rev', '',
2215 [('r', 'rev', '',
2216 _('revision to check'), _('REV'))],
2216 _('revision to check'), _('REV'))],
2217 _('[-r REV] [REV]'))
2217 _('[-r REV] [REV]'))
2218 def debugsub(ui, repo, rev=None):
2218 def debugsub(ui, repo, rev=None):
2219 ctx = scmutil.revsingle(repo, rev, None)
2219 ctx = scmutil.revsingle(repo, rev, None)
2220 for k, v in sorted(ctx.substate.items()):
2220 for k, v in sorted(ctx.substate.items()):
2221 ui.write('path %s\n' % k)
2221 ui.write('path %s\n' % k)
2222 ui.write(' source %s\n' % v[0])
2222 ui.write(' source %s\n' % v[0])
2223 ui.write(' revision %s\n' % v[1])
2223 ui.write(' revision %s\n' % v[1])
2224
2224
2225 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2225 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2226 def debugwalk(ui, repo, *pats, **opts):
2226 def debugwalk(ui, repo, *pats, **opts):
2227 """show how files match on given patterns"""
2227 """show how files match on given patterns"""
2228 m = scmutil.match(repo[None], pats, opts)
2228 m = scmutil.match(repo[None], pats, opts)
2229 items = list(repo.walk(m))
2229 items = list(repo.walk(m))
2230 if not items:
2230 if not items:
2231 return
2231 return
2232 fmt = 'f %%-%ds %%-%ds %%s' % (
2232 fmt = 'f %%-%ds %%-%ds %%s' % (
2233 max([len(abs) for abs in items]),
2233 max([len(abs) for abs in items]),
2234 max([len(m.rel(abs)) for abs in items]))
2234 max([len(m.rel(abs)) for abs in items]))
2235 for abs in items:
2235 for abs in items:
2236 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2236 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2237 ui.write("%s\n" % line.rstrip())
2237 ui.write("%s\n" % line.rstrip())
2238
2238
2239 @command('debugwireargs',
2239 @command('debugwireargs',
2240 [('', 'three', '', 'three'),
2240 [('', 'three', '', 'three'),
2241 ('', 'four', '', 'four'),
2241 ('', 'four', '', 'four'),
2242 ('', 'five', '', 'five'),
2242 ('', 'five', '', 'five'),
2243 ] + remoteopts,
2243 ] + remoteopts,
2244 _('REPO [OPTIONS]... [ONE [TWO]]'))
2244 _('REPO [OPTIONS]... [ONE [TWO]]'))
2245 def debugwireargs(ui, repopath, *vals, **opts):
2245 def debugwireargs(ui, repopath, *vals, **opts):
2246 repo = hg.peer(ui, opts, repopath)
2246 repo = hg.peer(ui, opts, repopath)
2247 for opt in remoteopts:
2247 for opt in remoteopts:
2248 del opts[opt[1]]
2248 del opts[opt[1]]
2249 args = {}
2249 args = {}
2250 for k, v in opts.iteritems():
2250 for k, v in opts.iteritems():
2251 if v:
2251 if v:
2252 args[k] = v
2252 args[k] = v
2253 # run twice to check that we don't mess up the stream for the next command
2253 # run twice to check that we don't mess up the stream for the next command
2254 res1 = repo.debugwireargs(*vals, **args)
2254 res1 = repo.debugwireargs(*vals, **args)
2255 res2 = repo.debugwireargs(*vals, **args)
2255 res2 = repo.debugwireargs(*vals, **args)
2256 ui.write("%s\n" % res1)
2256 ui.write("%s\n" % res1)
2257 if res1 != res2:
2257 if res1 != res2:
2258 ui.warn("%s\n" % res2)
2258 ui.warn("%s\n" % res2)
2259
2259
2260 @command('^diff',
2260 @command('^diff',
2261 [('r', 'rev', [], _('revision'), _('REV')),
2261 [('r', 'rev', [], _('revision'), _('REV')),
2262 ('c', 'change', '', _('change made by revision'), _('REV'))
2262 ('c', 'change', '', _('change made by revision'), _('REV'))
2263 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2263 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2264 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2264 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2265 def diff(ui, repo, *pats, **opts):
2265 def diff(ui, repo, *pats, **opts):
2266 """diff repository (or selected files)
2266 """diff repository (or selected files)
2267
2267
2268 Show differences between revisions for the specified files.
2268 Show differences between revisions for the specified files.
2269
2269
2270 Differences between files are shown using the unified diff format.
2270 Differences between files are shown using the unified diff format.
2271
2271
2272 .. note::
2272 .. note::
2273 diff may generate unexpected results for merges, as it will
2273 diff may generate unexpected results for merges, as it will
2274 default to comparing against the working directory's first
2274 default to comparing against the working directory's first
2275 parent changeset if no revisions are specified.
2275 parent changeset if no revisions are specified.
2276
2276
2277 When two revision arguments are given, then changes are shown
2277 When two revision arguments are given, then changes are shown
2278 between those revisions. If only one revision is specified then
2278 between those revisions. If only one revision is specified then
2279 that revision is compared to the working directory, and, when no
2279 that revision is compared to the working directory, and, when no
2280 revisions are specified, the working directory files are compared
2280 revisions are specified, the working directory files are compared
2281 to its parent.
2281 to its parent.
2282
2282
2283 Alternatively you can specify -c/--change with a revision to see
2283 Alternatively you can specify -c/--change with a revision to see
2284 the changes in that changeset relative to its first parent.
2284 the changes in that changeset relative to its first parent.
2285
2285
2286 Without the -a/--text option, diff will avoid generating diffs of
2286 Without the -a/--text option, diff will avoid generating diffs of
2287 files it detects as binary. With -a, diff will generate a diff
2287 files it detects as binary. With -a, diff will generate a diff
2288 anyway, probably with undesirable results.
2288 anyway, probably with undesirable results.
2289
2289
2290 Use the -g/--git option to generate diffs in the git extended diff
2290 Use the -g/--git option to generate diffs in the git extended diff
2291 format. For more information, read :hg:`help diffs`.
2291 format. For more information, read :hg:`help diffs`.
2292
2292
2293 .. container:: verbose
2293 .. container:: verbose
2294
2294
2295 Examples:
2295 Examples:
2296
2296
2297 - compare a file in the current working directory to its parent::
2297 - compare a file in the current working directory to its parent::
2298
2298
2299 hg diff foo.c
2299 hg diff foo.c
2300
2300
2301 - compare two historical versions of a directory, with rename info::
2301 - compare two historical versions of a directory, with rename info::
2302
2302
2303 hg diff --git -r 1.0:1.2 lib/
2303 hg diff --git -r 1.0:1.2 lib/
2304
2304
2305 - get change stats relative to the last change on some date::
2305 - get change stats relative to the last change on some date::
2306
2306
2307 hg diff --stat -r "date('may 2')"
2307 hg diff --stat -r "date('may 2')"
2308
2308
2309 - diff all newly-added files that contain a keyword::
2309 - diff all newly-added files that contain a keyword::
2310
2310
2311 hg diff "set:added() and grep(GNU)"
2311 hg diff "set:added() and grep(GNU)"
2312
2312
2313 - compare a revision and its parents::
2313 - compare a revision and its parents::
2314
2314
2315 hg diff -c 9353 # compare against first parent
2315 hg diff -c 9353 # compare against first parent
2316 hg diff -r 9353^:9353 # same using revset syntax
2316 hg diff -r 9353^:9353 # same using revset syntax
2317 hg diff -r 9353^2:9353 # compare against the second parent
2317 hg diff -r 9353^2:9353 # compare against the second parent
2318
2318
2319 Returns 0 on success.
2319 Returns 0 on success.
2320 """
2320 """
2321
2321
2322 revs = opts.get('rev')
2322 revs = opts.get('rev')
2323 change = opts.get('change')
2323 change = opts.get('change')
2324 stat = opts.get('stat')
2324 stat = opts.get('stat')
2325 reverse = opts.get('reverse')
2325 reverse = opts.get('reverse')
2326
2326
2327 if revs and change:
2327 if revs and change:
2328 msg = _('cannot specify --rev and --change at the same time')
2328 msg = _('cannot specify --rev and --change at the same time')
2329 raise util.Abort(msg)
2329 raise util.Abort(msg)
2330 elif change:
2330 elif change:
2331 node2 = scmutil.revsingle(repo, change, None).node()
2331 node2 = scmutil.revsingle(repo, change, None).node()
2332 node1 = repo[node2].p1().node()
2332 node1 = repo[node2].p1().node()
2333 else:
2333 else:
2334 node1, node2 = scmutil.revpair(repo, revs)
2334 node1, node2 = scmutil.revpair(repo, revs)
2335
2335
2336 if reverse:
2336 if reverse:
2337 node1, node2 = node2, node1
2337 node1, node2 = node2, node1
2338
2338
2339 diffopts = patch.diffopts(ui, opts)
2339 diffopts = patch.diffopts(ui, opts)
2340 m = scmutil.match(repo[node2], pats, opts)
2340 m = scmutil.match(repo[node2], pats, opts)
2341 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2341 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2342 listsubrepos=opts.get('subrepos'))
2342 listsubrepos=opts.get('subrepos'))
2343
2343
2344 @command('^export',
2344 @command('^export',
2345 [('o', 'output', '',
2345 [('o', 'output', '',
2346 _('print output to file with formatted name'), _('FORMAT')),
2346 _('print output to file with formatted name'), _('FORMAT')),
2347 ('', 'switch-parent', None, _('diff against the second parent')),
2347 ('', 'switch-parent', None, _('diff against the second parent')),
2348 ('r', 'rev', [], _('revisions to export'), _('REV')),
2348 ('r', 'rev', [], _('revisions to export'), _('REV')),
2349 ] + diffopts,
2349 ] + diffopts,
2350 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2350 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2351 def export(ui, repo, *changesets, **opts):
2351 def export(ui, repo, *changesets, **opts):
2352 """dump the header and diffs for one or more changesets
2352 """dump the header and diffs for one or more changesets
2353
2353
2354 Print the changeset header and diffs for one or more revisions.
2354 Print the changeset header and diffs for one or more revisions.
2355
2355
2356 The information shown in the changeset header is: author, date,
2356 The information shown in the changeset header is: author, date,
2357 branch name (if non-default), changeset hash, parent(s) and commit
2357 branch name (if non-default), changeset hash, parent(s) and commit
2358 comment.
2358 comment.
2359
2359
2360 .. note::
2360 .. note::
2361 export may generate unexpected diff output for merge
2361 export may generate unexpected diff output for merge
2362 changesets, as it will compare the merge changeset against its
2362 changesets, as it will compare the merge changeset against its
2363 first parent only.
2363 first parent only.
2364
2364
2365 Output may be to a file, in which case the name of the file is
2365 Output may be to a file, in which case the name of the file is
2366 given using a format string. The formatting rules are as follows:
2366 given using a format string. The formatting rules are as follows:
2367
2367
2368 :``%%``: literal "%" character
2368 :``%%``: literal "%" character
2369 :``%H``: changeset hash (40 hexadecimal digits)
2369 :``%H``: changeset hash (40 hexadecimal digits)
2370 :``%N``: number of patches being generated
2370 :``%N``: number of patches being generated
2371 :``%R``: changeset revision number
2371 :``%R``: changeset revision number
2372 :``%b``: basename of the exporting repository
2372 :``%b``: basename of the exporting repository
2373 :``%h``: short-form changeset hash (12 hexadecimal digits)
2373 :``%h``: short-form changeset hash (12 hexadecimal digits)
2374 :``%m``: first line of the commit message (only alphanumeric characters)
2374 :``%m``: first line of the commit message (only alphanumeric characters)
2375 :``%n``: zero-padded sequence number, starting at 1
2375 :``%n``: zero-padded sequence number, starting at 1
2376 :``%r``: zero-padded changeset revision number
2376 :``%r``: zero-padded changeset revision number
2377
2377
2378 Without the -a/--text option, export will avoid generating diffs
2378 Without the -a/--text option, export will avoid generating diffs
2379 of files it detects as binary. With -a, export will generate a
2379 of files it detects as binary. With -a, export will generate a
2380 diff anyway, probably with undesirable results.
2380 diff anyway, probably with undesirable results.
2381
2381
2382 Use the -g/--git option to generate diffs in the git extended diff
2382 Use the -g/--git option to generate diffs in the git extended diff
2383 format. See :hg:`help diffs` for more information.
2383 format. See :hg:`help diffs` for more information.
2384
2384
2385 With the --switch-parent option, the diff will be against the
2385 With the --switch-parent option, the diff will be against the
2386 second parent. It can be useful to review a merge.
2386 second parent. It can be useful to review a merge.
2387
2387
2388 .. container:: verbose
2388 .. container:: verbose
2389
2389
2390 Examples:
2390 Examples:
2391
2391
2392 - use export and import to transplant a bugfix to the current
2392 - use export and import to transplant a bugfix to the current
2393 branch::
2393 branch::
2394
2394
2395 hg export -r 9353 | hg import -
2395 hg export -r 9353 | hg import -
2396
2396
2397 - export all the changesets between two revisions to a file with
2397 - export all the changesets between two revisions to a file with
2398 rename information::
2398 rename information::
2399
2399
2400 hg export --git -r 123:150 > changes.txt
2400 hg export --git -r 123:150 > changes.txt
2401
2401
2402 - split outgoing changes into a series of patches with
2402 - split outgoing changes into a series of patches with
2403 descriptive names::
2403 descriptive names::
2404
2404
2405 hg export -r "outgoing()" -o "%n-%m.patch"
2405 hg export -r "outgoing()" -o "%n-%m.patch"
2406
2406
2407 Returns 0 on success.
2407 Returns 0 on success.
2408 """
2408 """
2409 changesets += tuple(opts.get('rev', []))
2409 changesets += tuple(opts.get('rev', []))
2410 if not changesets:
2410 if not changesets:
2411 raise util.Abort(_("export requires at least one changeset"))
2411 raise util.Abort(_("export requires at least one changeset"))
2412 revs = scmutil.revrange(repo, changesets)
2412 revs = scmutil.revrange(repo, changesets)
2413 if len(revs) > 1:
2413 if len(revs) > 1:
2414 ui.note(_('exporting patches:\n'))
2414 ui.note(_('exporting patches:\n'))
2415 else:
2415 else:
2416 ui.note(_('exporting patch:\n'))
2416 ui.note(_('exporting patch:\n'))
2417 cmdutil.export(repo, revs, template=opts.get('output'),
2417 cmdutil.export(repo, revs, template=opts.get('output'),
2418 switch_parent=opts.get('switch_parent'),
2418 switch_parent=opts.get('switch_parent'),
2419 opts=patch.diffopts(ui, opts))
2419 opts=patch.diffopts(ui, opts))
2420
2420
2421 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2421 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2422 def forget(ui, repo, *pats, **opts):
2422 def forget(ui, repo, *pats, **opts):
2423 """forget the specified files on the next commit
2423 """forget the specified files on the next commit
2424
2424
2425 Mark the specified files so they will no longer be tracked
2425 Mark the specified files so they will no longer be tracked
2426 after the next commit.
2426 after the next commit.
2427
2427
2428 This only removes files from the current branch, not from the
2428 This only removes files from the current branch, not from the
2429 entire project history, and it does not delete them from the
2429 entire project history, and it does not delete them from the
2430 working directory.
2430 working directory.
2431
2431
2432 To undo a forget before the next commit, see :hg:`add`.
2432 To undo a forget before the next commit, see :hg:`add`.
2433
2433
2434 .. container:: verbose
2434 .. container:: verbose
2435
2435
2436 Examples:
2436 Examples:
2437
2437
2438 - forget newly-added binary files::
2438 - forget newly-added binary files::
2439
2439
2440 hg forget "set:added() and binary()"
2440 hg forget "set:added() and binary()"
2441
2441
2442 - forget files that would be excluded by .hgignore::
2442 - forget files that would be excluded by .hgignore::
2443
2443
2444 hg forget "set:hgignore()"
2444 hg forget "set:hgignore()"
2445
2445
2446 Returns 0 on success.
2446 Returns 0 on success.
2447 """
2447 """
2448
2448
2449 if not pats:
2449 if not pats:
2450 raise util.Abort(_('no files specified'))
2450 raise util.Abort(_('no files specified'))
2451
2451
2452 wctx = repo[None]
2452 wctx = repo[None]
2453 m = scmutil.match(wctx, pats, opts)
2453 m = scmutil.match(wctx, pats, opts)
2454 s = repo.status(match=m, clean=True)
2454 s = repo.status(match=m, clean=True)
2455 forget = sorted(s[0] + s[1] + s[3] + s[6])
2455 forget = sorted(s[0] + s[1] + s[3] + s[6])
2456 subforget = {}
2456 subforget = {}
2457 errs = 0
2457 errs = 0
2458
2458
2459 for subpath in wctx.substate:
2459 for subpath in wctx.substate:
2460 sub = wctx.sub(subpath)
2460 sub = wctx.sub(subpath)
2461 try:
2461 try:
2462 submatch = matchmod.narrowmatcher(subpath, m)
2462 submatch = matchmod.narrowmatcher(subpath, m)
2463 for fsub in sub.walk(submatch):
2463 for fsub in sub.walk(submatch):
2464 if submatch.exact(fsub):
2464 if submatch.exact(fsub):
2465 subforget[subpath + '/' + fsub] = (fsub, sub)
2465 subforget[subpath + '/' + fsub] = (fsub, sub)
2466 except error.LookupError:
2466 except error.LookupError:
2467 ui.status(_("skipping missing subrepository: %s\n") % subpath)
2467 ui.status(_("skipping missing subrepository: %s\n") % subpath)
2468
2468
2469 for f in m.files():
2469 for f in m.files():
2470 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2470 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2471 if f not in subforget:
2471 if f not in subforget:
2472 if os.path.exists(m.rel(f)):
2472 if os.path.exists(m.rel(f)):
2473 ui.warn(_('not removing %s: file is already untracked\n')
2473 ui.warn(_('not removing %s: file is already untracked\n')
2474 % m.rel(f))
2474 % m.rel(f))
2475 errs = 1
2475 errs = 1
2476
2476
2477 for f in forget:
2477 for f in forget:
2478 if ui.verbose or not m.exact(f):
2478 if ui.verbose or not m.exact(f):
2479 ui.status(_('removing %s\n') % m.rel(f))
2479 ui.status(_('removing %s\n') % m.rel(f))
2480
2480
2481 if ui.verbose:
2481 if ui.verbose:
2482 for f in sorted(subforget.keys()):
2482 for f in sorted(subforget.keys()):
2483 ui.status(_('removing %s\n') % m.rel(f))
2483 ui.status(_('removing %s\n') % m.rel(f))
2484
2484
2485 wctx.forget(forget)
2485 wctx.forget(forget)
2486
2486
2487 for f in sorted(subforget.keys()):
2487 for f in sorted(subforget.keys()):
2488 fsub, sub = subforget[f]
2488 fsub, sub = subforget[f]
2489 sub.forget([fsub])
2489 sub.forget([fsub])
2490
2490
2491 return errs
2491 return errs
2492
2492
2493 @command(
2493 @command(
2494 'graft',
2494 'graft',
2495 [('c', 'continue', False, _('resume interrupted graft')),
2495 [('c', 'continue', False, _('resume interrupted graft')),
2496 ('e', 'edit', False, _('invoke editor on commit messages')),
2496 ('e', 'edit', False, _('invoke editor on commit messages')),
2497 ('D', 'currentdate', False,
2497 ('D', 'currentdate', False,
2498 _('record the current date as commit date')),
2498 _('record the current date as commit date')),
2499 ('U', 'currentuser', False,
2499 ('U', 'currentuser', False,
2500 _('record the current user as committer'), _('DATE'))]
2500 _('record the current user as committer'), _('DATE'))]
2501 + commitopts2 + mergetoolopts,
2501 + commitopts2 + mergetoolopts,
2502 _('[OPTION]... REVISION...'))
2502 _('[OPTION]... REVISION...'))
2503 def graft(ui, repo, *revs, **opts):
2503 def graft(ui, repo, *revs, **opts):
2504 '''copy changes from other branches onto the current branch
2504 '''copy changes from other branches onto the current branch
2505
2505
2506 This command uses Mercurial's merge logic to copy individual
2506 This command uses Mercurial's merge logic to copy individual
2507 changes from other branches without merging branches in the
2507 changes from other branches without merging branches in the
2508 history graph. This is sometimes known as 'backporting' or
2508 history graph. This is sometimes known as 'backporting' or
2509 'cherry-picking'. By default, graft will copy user, date, and
2509 'cherry-picking'. By default, graft will copy user, date, and
2510 description from the source changesets.
2510 description from the source changesets.
2511
2511
2512 Changesets that are ancestors of the current revision, that have
2512 Changesets that are ancestors of the current revision, that have
2513 already been grafted, or that are merges will be skipped.
2513 already been grafted, or that are merges will be skipped.
2514
2514
2515 If a graft merge results in conflicts, the graft process is
2515 If a graft merge results in conflicts, the graft process is
2516 interrupted so that the current merge can be manually resolved.
2516 interrupted so that the current merge can be manually resolved.
2517 Once all conflicts are addressed, the graft process can be
2517 Once all conflicts are addressed, the graft process can be
2518 continued with the -c/--continue option.
2518 continued with the -c/--continue option.
2519
2519
2520 .. note::
2520 .. note::
2521 The -c/--continue option does not reapply earlier options.
2521 The -c/--continue option does not reapply earlier options.
2522
2522
2523 .. container:: verbose
2523 .. container:: verbose
2524
2524
2525 Examples:
2525 Examples:
2526
2526
2527 - copy a single change to the stable branch and edit its description::
2527 - copy a single change to the stable branch and edit its description::
2528
2528
2529 hg update stable
2529 hg update stable
2530 hg graft --edit 9393
2530 hg graft --edit 9393
2531
2531
2532 - graft a range of changesets with one exception, updating dates::
2532 - graft a range of changesets with one exception, updating dates::
2533
2533
2534 hg graft -D "2085::2093 and not 2091"
2534 hg graft -D "2085::2093 and not 2091"
2535
2535
2536 - continue a graft after resolving conflicts::
2536 - continue a graft after resolving conflicts::
2537
2537
2538 hg graft -c
2538 hg graft -c
2539
2539
2540 - show the source of a grafted changeset::
2540 - show the source of a grafted changeset::
2541
2541
2542 hg log --debug -r tip
2542 hg log --debug -r tip
2543
2543
2544 Returns 0 on successful completion.
2544 Returns 0 on successful completion.
2545 '''
2545 '''
2546
2546
2547 if not opts.get('user') and opts.get('currentuser'):
2547 if not opts.get('user') and opts.get('currentuser'):
2548 opts['user'] = ui.username()
2548 opts['user'] = ui.username()
2549 if not opts.get('date') and opts.get('currentdate'):
2549 if not opts.get('date') and opts.get('currentdate'):
2550 opts['date'] = "%d %d" % util.makedate()
2550 opts['date'] = "%d %d" % util.makedate()
2551
2551
2552 editor = None
2552 editor = None
2553 if opts.get('edit'):
2553 if opts.get('edit'):
2554 editor = cmdutil.commitforceeditor
2554 editor = cmdutil.commitforceeditor
2555
2555
2556 cont = False
2556 cont = False
2557 if opts['continue']:
2557 if opts['continue']:
2558 cont = True
2558 cont = True
2559 if revs:
2559 if revs:
2560 raise util.Abort(_("can't specify --continue and revisions"))
2560 raise util.Abort(_("can't specify --continue and revisions"))
2561 # read in unfinished revisions
2561 # read in unfinished revisions
2562 try:
2562 try:
2563 nodes = repo.opener.read('graftstate').splitlines()
2563 nodes = repo.opener.read('graftstate').splitlines()
2564 revs = [repo[node].rev() for node in nodes]
2564 revs = [repo[node].rev() for node in nodes]
2565 except IOError, inst:
2565 except IOError, inst:
2566 if inst.errno != errno.ENOENT:
2566 if inst.errno != errno.ENOENT:
2567 raise
2567 raise
2568 raise util.Abort(_("no graft state found, can't continue"))
2568 raise util.Abort(_("no graft state found, can't continue"))
2569 else:
2569 else:
2570 cmdutil.bailifchanged(repo)
2570 cmdutil.bailifchanged(repo)
2571 if not revs:
2571 if not revs:
2572 raise util.Abort(_('no revisions specified'))
2572 raise util.Abort(_('no revisions specified'))
2573 revs = scmutil.revrange(repo, revs)
2573 revs = scmutil.revrange(repo, revs)
2574
2574
2575 # check for merges
2575 # check for merges
2576 for rev in repo.revs('%ld and merge()', revs):
2576 for rev in repo.revs('%ld and merge()', revs):
2577 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2577 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2578 revs.remove(rev)
2578 revs.remove(rev)
2579 if not revs:
2579 if not revs:
2580 return -1
2580 return -1
2581
2581
2582 # check for ancestors of dest branch
2582 # check for ancestors of dest branch
2583 for rev in repo.revs('::. and %ld', revs):
2583 for rev in repo.revs('::. and %ld', revs):
2584 ui.warn(_('skipping ancestor revision %s\n') % rev)
2584 ui.warn(_('skipping ancestor revision %s\n') % rev)
2585 revs.remove(rev)
2585 revs.remove(rev)
2586 if not revs:
2586 if not revs:
2587 return -1
2587 return -1
2588
2588
2589 # analyze revs for earlier grafts
2589 # analyze revs for earlier grafts
2590 ids = {}
2590 ids = {}
2591 for ctx in repo.set("%ld", revs):
2591 for ctx in repo.set("%ld", revs):
2592 ids[ctx.hex()] = ctx.rev()
2592 ids[ctx.hex()] = ctx.rev()
2593 n = ctx.extra().get('source')
2593 n = ctx.extra().get('source')
2594 if n:
2594 if n:
2595 ids[n] = ctx.rev()
2595 ids[n] = ctx.rev()
2596
2596
2597 # check ancestors for earlier grafts
2597 # check ancestors for earlier grafts
2598 ui.debug('scanning for duplicate grafts\n')
2598 ui.debug('scanning for duplicate grafts\n')
2599 for ctx in repo.set("::. - ::%ld", revs):
2599 for ctx in repo.set("::. - ::%ld", revs):
2600 n = ctx.extra().get('source')
2600 n = ctx.extra().get('source')
2601 if n in ids:
2601 if n in ids:
2602 r = repo[n].rev()
2602 r = repo[n].rev()
2603 if r in revs:
2603 if r in revs:
2604 ui.warn(_('skipping already grafted revision %s\n') % r)
2604 ui.warn(_('skipping already grafted revision %s\n') % r)
2605 revs.remove(r)
2605 revs.remove(r)
2606 elif ids[n] in revs:
2606 elif ids[n] in revs:
2607 ui.warn(_('skipping already grafted revision %s '
2607 ui.warn(_('skipping already grafted revision %s '
2608 '(same origin %d)\n') % (ids[n], r))
2608 '(same origin %d)\n') % (ids[n], r))
2609 revs.remove(ids[n])
2609 revs.remove(ids[n])
2610 elif ctx.hex() in ids:
2610 elif ctx.hex() in ids:
2611 r = ids[ctx.hex()]
2611 r = ids[ctx.hex()]
2612 ui.warn(_('skipping already grafted revision %s '
2612 ui.warn(_('skipping already grafted revision %s '
2613 '(was grafted from %d)\n') % (r, ctx.rev()))
2613 '(was grafted from %d)\n') % (r, ctx.rev()))
2614 revs.remove(r)
2614 revs.remove(r)
2615 if not revs:
2615 if not revs:
2616 return -1
2616 return -1
2617
2617
2618 for pos, ctx in enumerate(repo.set("%ld", revs)):
2618 for pos, ctx in enumerate(repo.set("%ld", revs)):
2619 current = repo['.']
2619 current = repo['.']
2620 ui.status(_('grafting revision %s\n') % ctx.rev())
2620 ui.status(_('grafting revision %s\n') % ctx.rev())
2621
2621
2622 # we don't merge the first commit when continuing
2622 # we don't merge the first commit when continuing
2623 if not cont:
2623 if not cont:
2624 # perform the graft merge with p1(rev) as 'ancestor'
2624 # perform the graft merge with p1(rev) as 'ancestor'
2625 try:
2625 try:
2626 # ui.forcemerge is an internal variable, do not document
2626 # ui.forcemerge is an internal variable, do not document
2627 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2627 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2628 stats = mergemod.update(repo, ctx.node(), True, True, False,
2628 stats = mergemod.update(repo, ctx.node(), True, True, False,
2629 ctx.p1().node())
2629 ctx.p1().node())
2630 finally:
2630 finally:
2631 ui.setconfig('ui', 'forcemerge', '')
2631 ui.setconfig('ui', 'forcemerge', '')
2632 # drop the second merge parent
2632 # drop the second merge parent
2633 repo.dirstate.setparents(current.node(), nullid)
2633 repo.dirstate.setparents(current.node(), nullid)
2634 repo.dirstate.write()
2634 repo.dirstate.write()
2635 # fix up dirstate for copies and renames
2635 # fix up dirstate for copies and renames
2636 cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
2636 cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
2637 # report any conflicts
2637 # report any conflicts
2638 if stats and stats[3] > 0:
2638 if stats and stats[3] > 0:
2639 # write out state for --continue
2639 # write out state for --continue
2640 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2640 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2641 repo.opener.write('graftstate', ''.join(nodelines))
2641 repo.opener.write('graftstate', ''.join(nodelines))
2642 raise util.Abort(
2642 raise util.Abort(
2643 _("unresolved conflicts, can't continue"),
2643 _("unresolved conflicts, can't continue"),
2644 hint=_('use hg resolve and hg graft --continue'))
2644 hint=_('use hg resolve and hg graft --continue'))
2645 else:
2645 else:
2646 cont = False
2646 cont = False
2647
2647
2648 # commit
2648 # commit
2649 source = ctx.extra().get('source')
2649 source = ctx.extra().get('source')
2650 if not source:
2650 if not source:
2651 source = ctx.hex()
2651 source = ctx.hex()
2652 extra = {'source': source}
2652 extra = {'source': source}
2653 user = ctx.user()
2653 user = ctx.user()
2654 if opts.get('user'):
2654 if opts.get('user'):
2655 user = opts['user']
2655 user = opts['user']
2656 date = ctx.date()
2656 date = ctx.date()
2657 if opts.get('date'):
2657 if opts.get('date'):
2658 date = opts['date']
2658 date = opts['date']
2659 repo.commit(text=ctx.description(), user=user,
2659 repo.commit(text=ctx.description(), user=user,
2660 date=date, extra=extra, editor=editor)
2660 date=date, extra=extra, editor=editor)
2661
2661
2662 # remove state when we complete successfully
2662 # remove state when we complete successfully
2663 if os.path.exists(repo.join('graftstate')):
2663 if os.path.exists(repo.join('graftstate')):
2664 util.unlinkpath(repo.join('graftstate'))
2664 util.unlinkpath(repo.join('graftstate'))
2665
2665
2666 return 0
2666 return 0
2667
2667
2668 @command('grep',
2668 @command('grep',
2669 [('0', 'print0', None, _('end fields with NUL')),
2669 [('0', 'print0', None, _('end fields with NUL')),
2670 ('', 'all', None, _('print all revisions that match')),
2670 ('', 'all', None, _('print all revisions that match')),
2671 ('a', 'text', None, _('treat all files as text')),
2671 ('a', 'text', None, _('treat all files as text')),
2672 ('f', 'follow', None,
2672 ('f', 'follow', None,
2673 _('follow changeset history,'
2673 _('follow changeset history,'
2674 ' or file history across copies and renames')),
2674 ' or file history across copies and renames')),
2675 ('i', 'ignore-case', None, _('ignore case when matching')),
2675 ('i', 'ignore-case', None, _('ignore case when matching')),
2676 ('l', 'files-with-matches', None,
2676 ('l', 'files-with-matches', None,
2677 _('print only filenames and revisions that match')),
2677 _('print only filenames and revisions that match')),
2678 ('n', 'line-number', None, _('print matching line numbers')),
2678 ('n', 'line-number', None, _('print matching line numbers')),
2679 ('r', 'rev', [],
2679 ('r', 'rev', [],
2680 _('only search files changed within revision range'), _('REV')),
2680 _('only search files changed within revision range'), _('REV')),
2681 ('u', 'user', None, _('list the author (long with -v)')),
2681 ('u', 'user', None, _('list the author (long with -v)')),
2682 ('d', 'date', None, _('list the date (short with -q)')),
2682 ('d', 'date', None, _('list the date (short with -q)')),
2683 ] + walkopts,
2683 ] + walkopts,
2684 _('[OPTION]... PATTERN [FILE]...'))
2684 _('[OPTION]... PATTERN [FILE]...'))
2685 def grep(ui, repo, pattern, *pats, **opts):
2685 def grep(ui, repo, pattern, *pats, **opts):
2686 """search for a pattern in specified files and revisions
2686 """search for a pattern in specified files and revisions
2687
2687
2688 Search revisions of files for a regular expression.
2688 Search revisions of files for a regular expression.
2689
2689
2690 This command behaves differently than Unix grep. It only accepts
2690 This command behaves differently than Unix grep. It only accepts
2691 Python/Perl regexps. It searches repository history, not the
2691 Python/Perl regexps. It searches repository history, not the
2692 working directory. It always prints the revision number in which a
2692 working directory. It always prints the revision number in which a
2693 match appears.
2693 match appears.
2694
2694
2695 By default, grep only prints output for the first revision of a
2695 By default, grep only prints output for the first revision of a
2696 file in which it finds a match. To get it to print every revision
2696 file in which it finds a match. To get it to print every revision
2697 that contains a change in match status ("-" for a match that
2697 that contains a change in match status ("-" for a match that
2698 becomes a non-match, or "+" for a non-match that becomes a match),
2698 becomes a non-match, or "+" for a non-match that becomes a match),
2699 use the --all flag.
2699 use the --all flag.
2700
2700
2701 Returns 0 if a match is found, 1 otherwise.
2701 Returns 0 if a match is found, 1 otherwise.
2702 """
2702 """
2703 reflags = re.M
2703 reflags = re.M
2704 if opts.get('ignore_case'):
2704 if opts.get('ignore_case'):
2705 reflags |= re.I
2705 reflags |= re.I
2706 try:
2706 try:
2707 regexp = re.compile(pattern, reflags)
2707 regexp = re.compile(pattern, reflags)
2708 except re.error, inst:
2708 except re.error, inst:
2709 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2709 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2710 return 1
2710 return 1
2711 sep, eol = ':', '\n'
2711 sep, eol = ':', '\n'
2712 if opts.get('print0'):
2712 if opts.get('print0'):
2713 sep = eol = '\0'
2713 sep = eol = '\0'
2714
2714
2715 getfile = util.lrucachefunc(repo.file)
2715 getfile = util.lrucachefunc(repo.file)
2716
2716
2717 def matchlines(body):
2717 def matchlines(body):
2718 begin = 0
2718 begin = 0
2719 linenum = 0
2719 linenum = 0
2720 while True:
2720 while True:
2721 match = regexp.search(body, begin)
2721 match = regexp.search(body, begin)
2722 if not match:
2722 if not match:
2723 break
2723 break
2724 mstart, mend = match.span()
2724 mstart, mend = match.span()
2725 linenum += body.count('\n', begin, mstart) + 1
2725 linenum += body.count('\n', begin, mstart) + 1
2726 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2726 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2727 begin = body.find('\n', mend) + 1 or len(body) + 1
2727 begin = body.find('\n', mend) + 1 or len(body) + 1
2728 lend = begin - 1
2728 lend = begin - 1
2729 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2729 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2730
2730
2731 class linestate(object):
2731 class linestate(object):
2732 def __init__(self, line, linenum, colstart, colend):
2732 def __init__(self, line, linenum, colstart, colend):
2733 self.line = line
2733 self.line = line
2734 self.linenum = linenum
2734 self.linenum = linenum
2735 self.colstart = colstart
2735 self.colstart = colstart
2736 self.colend = colend
2736 self.colend = colend
2737
2737
2738 def __hash__(self):
2738 def __hash__(self):
2739 return hash((self.linenum, self.line))
2739 return hash((self.linenum, self.line))
2740
2740
2741 def __eq__(self, other):
2741 def __eq__(self, other):
2742 return self.line == other.line
2742 return self.line == other.line
2743
2743
2744 matches = {}
2744 matches = {}
2745 copies = {}
2745 copies = {}
2746 def grepbody(fn, rev, body):
2746 def grepbody(fn, rev, body):
2747 matches[rev].setdefault(fn, [])
2747 matches[rev].setdefault(fn, [])
2748 m = matches[rev][fn]
2748 m = matches[rev][fn]
2749 for lnum, cstart, cend, line in matchlines(body):
2749 for lnum, cstart, cend, line in matchlines(body):
2750 s = linestate(line, lnum, cstart, cend)
2750 s = linestate(line, lnum, cstart, cend)
2751 m.append(s)
2751 m.append(s)
2752
2752
2753 def difflinestates(a, b):
2753 def difflinestates(a, b):
2754 sm = difflib.SequenceMatcher(None, a, b)
2754 sm = difflib.SequenceMatcher(None, a, b)
2755 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2755 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2756 if tag == 'insert':
2756 if tag == 'insert':
2757 for i in xrange(blo, bhi):
2757 for i in xrange(blo, bhi):
2758 yield ('+', b[i])
2758 yield ('+', b[i])
2759 elif tag == 'delete':
2759 elif tag == 'delete':
2760 for i in xrange(alo, ahi):
2760 for i in xrange(alo, ahi):
2761 yield ('-', a[i])
2761 yield ('-', a[i])
2762 elif tag == 'replace':
2762 elif tag == 'replace':
2763 for i in xrange(alo, ahi):
2763 for i in xrange(alo, ahi):
2764 yield ('-', a[i])
2764 yield ('-', a[i])
2765 for i in xrange(blo, bhi):
2765 for i in xrange(blo, bhi):
2766 yield ('+', b[i])
2766 yield ('+', b[i])
2767
2767
2768 def display(fn, ctx, pstates, states):
2768 def display(fn, ctx, pstates, states):
2769 rev = ctx.rev()
2769 rev = ctx.rev()
2770 datefunc = ui.quiet and util.shortdate or util.datestr
2770 datefunc = ui.quiet and util.shortdate or util.datestr
2771 found = False
2771 found = False
2772 filerevmatches = {}
2772 filerevmatches = {}
2773 def binary():
2773 def binary():
2774 flog = getfile(fn)
2774 flog = getfile(fn)
2775 return util.binary(flog.read(ctx.filenode(fn)))
2775 return util.binary(flog.read(ctx.filenode(fn)))
2776
2776
2777 if opts.get('all'):
2777 if opts.get('all'):
2778 iter = difflinestates(pstates, states)
2778 iter = difflinestates(pstates, states)
2779 else:
2779 else:
2780 iter = [('', l) for l in states]
2780 iter = [('', l) for l in states]
2781 for change, l in iter:
2781 for change, l in iter:
2782 cols = [fn, str(rev)]
2782 cols = [fn, str(rev)]
2783 before, match, after = None, None, None
2783 before, match, after = None, None, None
2784 if opts.get('line_number'):
2784 if opts.get('line_number'):
2785 cols.append(str(l.linenum))
2785 cols.append(str(l.linenum))
2786 if opts.get('all'):
2786 if opts.get('all'):
2787 cols.append(change)
2787 cols.append(change)
2788 if opts.get('user'):
2788 if opts.get('user'):
2789 cols.append(ui.shortuser(ctx.user()))
2789 cols.append(ui.shortuser(ctx.user()))
2790 if opts.get('date'):
2790 if opts.get('date'):
2791 cols.append(datefunc(ctx.date()))
2791 cols.append(datefunc(ctx.date()))
2792 if opts.get('files_with_matches'):
2792 if opts.get('files_with_matches'):
2793 c = (fn, rev)
2793 c = (fn, rev)
2794 if c in filerevmatches:
2794 if c in filerevmatches:
2795 continue
2795 continue
2796 filerevmatches[c] = 1
2796 filerevmatches[c] = 1
2797 else:
2797 else:
2798 before = l.line[:l.colstart]
2798 before = l.line[:l.colstart]
2799 match = l.line[l.colstart:l.colend]
2799 match = l.line[l.colstart:l.colend]
2800 after = l.line[l.colend:]
2800 after = l.line[l.colend:]
2801 ui.write(sep.join(cols))
2801 ui.write(sep.join(cols))
2802 if before is not None:
2802 if before is not None:
2803 if not opts.get('text') and binary():
2803 if not opts.get('text') and binary():
2804 ui.write(sep + " Binary file matches")
2804 ui.write(sep + " Binary file matches")
2805 else:
2805 else:
2806 ui.write(sep + before)
2806 ui.write(sep + before)
2807 ui.write(match, label='grep.match')
2807 ui.write(match, label='grep.match')
2808 ui.write(after)
2808 ui.write(after)
2809 ui.write(eol)
2809 ui.write(eol)
2810 found = True
2810 found = True
2811 return found
2811 return found
2812
2812
2813 skip = {}
2813 skip = {}
2814 revfiles = {}
2814 revfiles = {}
2815 matchfn = scmutil.match(repo[None], pats, opts)
2815 matchfn = scmutil.match(repo[None], pats, opts)
2816 found = False
2816 found = False
2817 follow = opts.get('follow')
2817 follow = opts.get('follow')
2818
2818
2819 def prep(ctx, fns):
2819 def prep(ctx, fns):
2820 rev = ctx.rev()
2820 rev = ctx.rev()
2821 pctx = ctx.p1()
2821 pctx = ctx.p1()
2822 parent = pctx.rev()
2822 parent = pctx.rev()
2823 matches.setdefault(rev, {})
2823 matches.setdefault(rev, {})
2824 matches.setdefault(parent, {})
2824 matches.setdefault(parent, {})
2825 files = revfiles.setdefault(rev, [])
2825 files = revfiles.setdefault(rev, [])
2826 for fn in fns:
2826 for fn in fns:
2827 flog = getfile(fn)
2827 flog = getfile(fn)
2828 try:
2828 try:
2829 fnode = ctx.filenode(fn)
2829 fnode = ctx.filenode(fn)
2830 except error.LookupError:
2830 except error.LookupError:
2831 continue
2831 continue
2832
2832
2833 copied = flog.renamed(fnode)
2833 copied = flog.renamed(fnode)
2834 copy = follow and copied and copied[0]
2834 copy = follow and copied and copied[0]
2835 if copy:
2835 if copy:
2836 copies.setdefault(rev, {})[fn] = copy
2836 copies.setdefault(rev, {})[fn] = copy
2837 if fn in skip:
2837 if fn in skip:
2838 if copy:
2838 if copy:
2839 skip[copy] = True
2839 skip[copy] = True
2840 continue
2840 continue
2841 files.append(fn)
2841 files.append(fn)
2842
2842
2843 if fn not in matches[rev]:
2843 if fn not in matches[rev]:
2844 grepbody(fn, rev, flog.read(fnode))
2844 grepbody(fn, rev, flog.read(fnode))
2845
2845
2846 pfn = copy or fn
2846 pfn = copy or fn
2847 if pfn not in matches[parent]:
2847 if pfn not in matches[parent]:
2848 try:
2848 try:
2849 fnode = pctx.filenode(pfn)
2849 fnode = pctx.filenode(pfn)
2850 grepbody(pfn, parent, flog.read(fnode))
2850 grepbody(pfn, parent, flog.read(fnode))
2851 except error.LookupError:
2851 except error.LookupError:
2852 pass
2852 pass
2853
2853
2854 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2854 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2855 rev = ctx.rev()
2855 rev = ctx.rev()
2856 parent = ctx.p1().rev()
2856 parent = ctx.p1().rev()
2857 for fn in sorted(revfiles.get(rev, [])):
2857 for fn in sorted(revfiles.get(rev, [])):
2858 states = matches[rev][fn]
2858 states = matches[rev][fn]
2859 copy = copies.get(rev, {}).get(fn)
2859 copy = copies.get(rev, {}).get(fn)
2860 if fn in skip:
2860 if fn in skip:
2861 if copy:
2861 if copy:
2862 skip[copy] = True
2862 skip[copy] = True
2863 continue
2863 continue
2864 pstates = matches.get(parent, {}).get(copy or fn, [])
2864 pstates = matches.get(parent, {}).get(copy or fn, [])
2865 if pstates or states:
2865 if pstates or states:
2866 r = display(fn, ctx, pstates, states)
2866 r = display(fn, ctx, pstates, states)
2867 found = found or r
2867 found = found or r
2868 if r and not opts.get('all'):
2868 if r and not opts.get('all'):
2869 skip[fn] = True
2869 skip[fn] = True
2870 if copy:
2870 if copy:
2871 skip[copy] = True
2871 skip[copy] = True
2872 del matches[rev]
2872 del matches[rev]
2873 del revfiles[rev]
2873 del revfiles[rev]
2874
2874
2875 return not found
2875 return not found
2876
2876
2877 @command('heads',
2877 @command('heads',
2878 [('r', 'rev', '',
2878 [('r', 'rev', '',
2879 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2879 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2880 ('t', 'topo', False, _('show topological heads only')),
2880 ('t', 'topo', False, _('show topological heads only')),
2881 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2881 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2882 ('c', 'closed', False, _('show normal and closed branch heads')),
2882 ('c', 'closed', False, _('show normal and closed branch heads')),
2883 ] + templateopts,
2883 ] + templateopts,
2884 _('[-ac] [-r STARTREV] [REV]...'))
2884 _('[-ac] [-r STARTREV] [REV]...'))
2885 def heads(ui, repo, *branchrevs, **opts):
2885 def heads(ui, repo, *branchrevs, **opts):
2886 """show current repository heads or show branch heads
2886 """show current repository heads or show branch heads
2887
2887
2888 With no arguments, show all repository branch heads.
2888 With no arguments, show all repository branch heads.
2889
2889
2890 Repository "heads" are changesets with no child changesets. They are
2890 Repository "heads" are changesets with no child changesets. They are
2891 where development generally takes place and are the usual targets
2891 where development generally takes place and are the usual targets
2892 for update and merge operations. Branch heads are changesets that have
2892 for update and merge operations. Branch heads are changesets that have
2893 no child changeset on the same branch.
2893 no child changeset on the same branch.
2894
2894
2895 If one or more REVs are given, only branch heads on the branches
2895 If one or more REVs are given, only branch heads on the branches
2896 associated with the specified changesets are shown. This means
2896 associated with the specified changesets are shown. This means
2897 that you can use :hg:`heads foo` to see the heads on a branch
2897 that you can use :hg:`heads foo` to see the heads on a branch
2898 named ``foo``.
2898 named ``foo``.
2899
2899
2900 If -c/--closed is specified, also show branch heads marked closed
2900 If -c/--closed is specified, also show branch heads marked closed
2901 (see :hg:`commit --close-branch`).
2901 (see :hg:`commit --close-branch`).
2902
2902
2903 If STARTREV is specified, only those heads that are descendants of
2903 If STARTREV is specified, only those heads that are descendants of
2904 STARTREV will be displayed.
2904 STARTREV will be displayed.
2905
2905
2906 If -t/--topo is specified, named branch mechanics will be ignored and only
2906 If -t/--topo is specified, named branch mechanics will be ignored and only
2907 changesets without children will be shown.
2907 changesets without children will be shown.
2908
2908
2909 Returns 0 if matching heads are found, 1 if not.
2909 Returns 0 if matching heads are found, 1 if not.
2910 """
2910 """
2911
2911
2912 start = None
2912 start = None
2913 if 'rev' in opts:
2913 if 'rev' in opts:
2914 start = scmutil.revsingle(repo, opts['rev'], None).node()
2914 start = scmutil.revsingle(repo, opts['rev'], None).node()
2915
2915
2916 if opts.get('topo'):
2916 if opts.get('topo'):
2917 heads = [repo[h] for h in repo.heads(start)]
2917 heads = [repo[h] for h in repo.heads(start)]
2918 else:
2918 else:
2919 heads = []
2919 heads = []
2920 for branch in repo.branchmap():
2920 for branch in repo.branchmap():
2921 heads += repo.branchheads(branch, start, opts.get('closed'))
2921 heads += repo.branchheads(branch, start, opts.get('closed'))
2922 heads = [repo[h] for h in heads]
2922 heads = [repo[h] for h in heads]
2923
2923
2924 if branchrevs:
2924 if branchrevs:
2925 branches = set(repo[br].branch() for br in branchrevs)
2925 branches = set(repo[br].branch() for br in branchrevs)
2926 heads = [h for h in heads if h.branch() in branches]
2926 heads = [h for h in heads if h.branch() in branches]
2927
2927
2928 if opts.get('active') and branchrevs:
2928 if opts.get('active') and branchrevs:
2929 dagheads = repo.heads(start)
2929 dagheads = repo.heads(start)
2930 heads = [h for h in heads if h.node() in dagheads]
2930 heads = [h for h in heads if h.node() in dagheads]
2931
2931
2932 if branchrevs:
2932 if branchrevs:
2933 haveheads = set(h.branch() for h in heads)
2933 haveheads = set(h.branch() for h in heads)
2934 if branches - haveheads:
2934 if branches - haveheads:
2935 headless = ', '.join(b for b in branches - haveheads)
2935 headless = ', '.join(b for b in branches - haveheads)
2936 msg = _('no open branch heads found on branches %s')
2936 msg = _('no open branch heads found on branches %s')
2937 if opts.get('rev'):
2937 if opts.get('rev'):
2938 msg += _(' (started at %s)' % opts['rev'])
2938 msg += _(' (started at %s)' % opts['rev'])
2939 ui.warn((msg + '\n') % headless)
2939 ui.warn((msg + '\n') % headless)
2940
2940
2941 if not heads:
2941 if not heads:
2942 return 1
2942 return 1
2943
2943
2944 heads = sorted(heads, key=lambda x: -x.rev())
2944 heads = sorted(heads, key=lambda x: -x.rev())
2945 displayer = cmdutil.show_changeset(ui, repo, opts)
2945 displayer = cmdutil.show_changeset(ui, repo, opts)
2946 for ctx in heads:
2946 for ctx in heads:
2947 displayer.show(ctx)
2947 displayer.show(ctx)
2948 displayer.close()
2948 displayer.close()
2949
2949
2950 @command('help',
2950 @command('help',
2951 [('e', 'extension', None, _('show only help for extensions')),
2951 [('e', 'extension', None, _('show only help for extensions')),
2952 ('c', 'command', None, _('show only help for commands'))],
2952 ('c', 'command', None, _('show only help for commands'))],
2953 _('[-ec] [TOPIC]'))
2953 _('[-ec] [TOPIC]'))
2954 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2954 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2955 """show help for a given topic or a help overview
2955 """show help for a given topic or a help overview
2956
2956
2957 With no arguments, print a list of commands with short help messages.
2957 With no arguments, print a list of commands with short help messages.
2958
2958
2959 Given a topic, extension, or command name, print help for that
2959 Given a topic, extension, or command name, print help for that
2960 topic.
2960 topic.
2961
2961
2962 Returns 0 if successful.
2962 Returns 0 if successful.
2963 """
2963 """
2964
2964
2965 textwidth = min(ui.termwidth(), 80) - 2
2965 textwidth = min(ui.termwidth(), 80) - 2
2966
2966
2967 def optrst(options):
2967 def optrst(options):
2968 data = []
2968 data = []
2969 multioccur = False
2969 multioccur = False
2970 for option in options:
2970 for option in options:
2971 if len(option) == 5:
2971 if len(option) == 5:
2972 shortopt, longopt, default, desc, optlabel = option
2972 shortopt, longopt, default, desc, optlabel = option
2973 else:
2973 else:
2974 shortopt, longopt, default, desc = option
2974 shortopt, longopt, default, desc = option
2975 optlabel = _("VALUE") # default label
2975 optlabel = _("VALUE") # default label
2976
2976
2977 if _("DEPRECATED") in desc and not ui.verbose:
2977 if _("DEPRECATED") in desc and not ui.verbose:
2978 continue
2978 continue
2979
2979
2980 so = ''
2980 so = ''
2981 if shortopt:
2981 if shortopt:
2982 so = '-' + shortopt
2982 so = '-' + shortopt
2983 lo = '--' + longopt
2983 lo = '--' + longopt
2984 if default:
2984 if default:
2985 desc += _(" (default: %s)") % default
2985 desc += _(" (default: %s)") % default
2986
2986
2987 if isinstance(default, list):
2987 if isinstance(default, list):
2988 lo += " %s [+]" % optlabel
2988 lo += " %s [+]" % optlabel
2989 multioccur = True
2989 multioccur = True
2990 elif (default is not None) and not isinstance(default, bool):
2990 elif (default is not None) and not isinstance(default, bool):
2991 lo += " %s" % optlabel
2991 lo += " %s" % optlabel
2992
2992
2993 data.append((so, lo, desc))
2993 data.append((so, lo, desc))
2994
2994
2995 rst = minirst.maketable(data, 1)
2995 rst = minirst.maketable(data, 1)
2996
2996
2997 if multioccur:
2997 if multioccur:
2998 rst += _("\n[+] marked option can be specified multiple times\n")
2998 rst += _("\n[+] marked option can be specified multiple times\n")
2999
2999
3000 return rst
3000 return rst
3001
3001
3002 # list all option lists
3002 # list all option lists
3003 def opttext(optlist, width):
3003 def opttext(optlist, width):
3004 rst = ''
3004 rst = ''
3005 if not optlist:
3005 if not optlist:
3006 return ''
3006 return ''
3007
3007
3008 for title, options in optlist:
3008 for title, options in optlist:
3009 rst += '\n%s\n' % title
3009 rst += '\n%s\n' % title
3010 if options:
3010 if options:
3011 rst += "\n"
3011 rst += "\n"
3012 rst += optrst(options)
3012 rst += optrst(options)
3013 rst += '\n'
3013 rst += '\n'
3014
3014
3015 return '\n' + minirst.format(rst, width)
3015 return '\n' + minirst.format(rst, width)
3016
3016
3017 def addglobalopts(optlist, aliases):
3017 def addglobalopts(optlist, aliases):
3018 if ui.quiet:
3018 if ui.quiet:
3019 return []
3019 return []
3020
3020
3021 if ui.verbose:
3021 if ui.verbose:
3022 optlist.append((_("global options:"), globalopts))
3022 optlist.append((_("global options:"), globalopts))
3023 if name == 'shortlist':
3023 if name == 'shortlist':
3024 optlist.append((_('use "hg help" for the full list '
3024 optlist.append((_('use "hg help" for the full list '
3025 'of commands'), ()))
3025 'of commands'), ()))
3026 else:
3026 else:
3027 if name == 'shortlist':
3027 if name == 'shortlist':
3028 msg = _('use "hg help" for the full list of commands '
3028 msg = _('use "hg help" for the full list of commands '
3029 'or "hg -v" for details')
3029 'or "hg -v" for details')
3030 elif name and not full:
3030 elif name and not full:
3031 msg = _('use "hg help %s" to show the full help text' % name)
3031 msg = _('use "hg help %s" to show the full help text' % name)
3032 elif aliases:
3032 elif aliases:
3033 msg = _('use "hg -v help%s" to show builtin aliases and '
3033 msg = _('use "hg -v help%s" to show builtin aliases and '
3034 'global options') % (name and " " + name or "")
3034 'global options') % (name and " " + name or "")
3035 else:
3035 else:
3036 msg = _('use "hg -v help %s" to show more info') % name
3036 msg = _('use "hg -v help %s" to show more info') % name
3037 optlist.append((msg, ()))
3037 optlist.append((msg, ()))
3038
3038
3039 def helpcmd(name):
3039 def helpcmd(name):
3040 try:
3040 try:
3041 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3041 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3042 except error.AmbiguousCommand, inst:
3042 except error.AmbiguousCommand, inst:
3043 # py3k fix: except vars can't be used outside the scope of the
3043 # py3k fix: except vars can't be used outside the scope of the
3044 # except block, nor can be used inside a lambda. python issue4617
3044 # except block, nor can be used inside a lambda. python issue4617
3045 prefix = inst.args[0]
3045 prefix = inst.args[0]
3046 select = lambda c: c.lstrip('^').startswith(prefix)
3046 select = lambda c: c.lstrip('^').startswith(prefix)
3047 helplist(select)
3047 helplist(select)
3048 return
3048 return
3049
3049
3050 # check if it's an invalid alias and display its error if it is
3050 # check if it's an invalid alias and display its error if it is
3051 if getattr(entry[0], 'badalias', False):
3051 if getattr(entry[0], 'badalias', False):
3052 if not unknowncmd:
3052 if not unknowncmd:
3053 entry[0](ui)
3053 entry[0](ui)
3054 return
3054 return
3055
3055
3056 rst = ""
3056 rst = ""
3057
3057
3058 # synopsis
3058 # synopsis
3059 if len(entry) > 2:
3059 if len(entry) > 2:
3060 if entry[2].startswith('hg'):
3060 if entry[2].startswith('hg'):
3061 rst += "%s\n" % entry[2]
3061 rst += "%s\n" % entry[2]
3062 else:
3062 else:
3063 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3063 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3064 else:
3064 else:
3065 rst += 'hg %s\n' % aliases[0]
3065 rst += 'hg %s\n' % aliases[0]
3066
3066
3067 # aliases
3067 # aliases
3068 if full and not ui.quiet and len(aliases) > 1:
3068 if full and not ui.quiet and len(aliases) > 1:
3069 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3069 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3070
3070
3071 # description
3071 # description
3072 doc = gettext(entry[0].__doc__)
3072 doc = gettext(entry[0].__doc__)
3073 if not doc:
3073 if not doc:
3074 doc = _("(no help text available)")
3074 doc = _("(no help text available)")
3075 if util.safehasattr(entry[0], 'definition'): # aliased command
3075 if util.safehasattr(entry[0], 'definition'): # aliased command
3076 if entry[0].definition.startswith('!'): # shell alias
3076 if entry[0].definition.startswith('!'): # shell alias
3077 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3077 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3078 else:
3078 else:
3079 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3079 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3080 if ui.quiet or not full:
3080 if ui.quiet or not full:
3081 doc = doc.splitlines()[0]
3081 doc = doc.splitlines()[0]
3082 rst += "\n" + doc + "\n"
3082 rst += "\n" + doc + "\n"
3083
3083
3084 # check if this command shadows a non-trivial (multi-line)
3084 # check if this command shadows a non-trivial (multi-line)
3085 # extension help text
3085 # extension help text
3086 try:
3086 try:
3087 mod = extensions.find(name)
3087 mod = extensions.find(name)
3088 doc = gettext(mod.__doc__) or ''
3088 doc = gettext(mod.__doc__) or ''
3089 if '\n' in doc.strip():
3089 if '\n' in doc.strip():
3090 msg = _('use "hg help -e %s" to show help for '
3090 msg = _('use "hg help -e %s" to show help for '
3091 'the %s extension') % (name, name)
3091 'the %s extension') % (name, name)
3092 rst += '\n%s\n' % msg
3092 rst += '\n%s\n' % msg
3093 except KeyError:
3093 except KeyError:
3094 pass
3094 pass
3095
3095
3096 # options
3096 # options
3097 if not ui.quiet and entry[1]:
3097 if not ui.quiet and entry[1]:
3098 rst += '\noptions:\n\n'
3098 rst += '\noptions:\n\n'
3099 rst += optrst(entry[1])
3099 rst += optrst(entry[1])
3100
3100
3101 if ui.verbose:
3101 if ui.verbose:
3102 rst += '\nglobal options:\n\n'
3102 rst += '\nglobal options:\n\n'
3103 rst += optrst(globalopts)
3103 rst += optrst(globalopts)
3104
3104
3105 keep = ui.verbose and ['verbose'] or []
3105 keep = ui.verbose and ['verbose'] or []
3106 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3106 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3107 ui.write(formatted)
3107 ui.write(formatted)
3108
3108
3109 if not ui.verbose:
3109 if not ui.verbose:
3110 if not full:
3110 if not full:
3111 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3111 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3112 % name)
3112 % name)
3113 elif not ui.quiet:
3113 elif not ui.quiet:
3114 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3114 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3115
3115
3116
3116
3117 def helplist(select=None):
3117 def helplist(select=None):
3118 # list of commands
3118 # list of commands
3119 if name == "shortlist":
3119 if name == "shortlist":
3120 header = _('basic commands:\n\n')
3120 header = _('basic commands:\n\n')
3121 else:
3121 else:
3122 header = _('list of commands:\n\n')
3122 header = _('list of commands:\n\n')
3123
3123
3124 h = {}
3124 h = {}
3125 cmds = {}
3125 cmds = {}
3126 for c, e in table.iteritems():
3126 for c, e in table.iteritems():
3127 f = c.split("|", 1)[0]
3127 f = c.split("|", 1)[0]
3128 if select and not select(f):
3128 if select and not select(f):
3129 continue
3129 continue
3130 if (not select and name != 'shortlist' and
3130 if (not select and name != 'shortlist' and
3131 e[0].__module__ != __name__):
3131 e[0].__module__ != __name__):
3132 continue
3132 continue
3133 if name == "shortlist" and not f.startswith("^"):
3133 if name == "shortlist" and not f.startswith("^"):
3134 continue
3134 continue
3135 f = f.lstrip("^")
3135 f = f.lstrip("^")
3136 if not ui.debugflag and f.startswith("debug"):
3136 if not ui.debugflag and f.startswith("debug"):
3137 continue
3137 continue
3138 doc = e[0].__doc__
3138 doc = e[0].__doc__
3139 if doc and 'DEPRECATED' in doc and not ui.verbose:
3139 if doc and 'DEPRECATED' in doc and not ui.verbose:
3140 continue
3140 continue
3141 doc = gettext(doc)
3141 doc = gettext(doc)
3142 if not doc:
3142 if not doc:
3143 doc = _("(no help text available)")
3143 doc = _("(no help text available)")
3144 h[f] = doc.splitlines()[0].rstrip()
3144 h[f] = doc.splitlines()[0].rstrip()
3145 cmds[f] = c.lstrip("^")
3145 cmds[f] = c.lstrip("^")
3146
3146
3147 if not h:
3147 if not h:
3148 ui.status(_('no commands defined\n'))
3148 ui.status(_('no commands defined\n'))
3149 return
3149 return
3150
3150
3151 ui.status(header)
3151 ui.status(header)
3152 fns = sorted(h)
3152 fns = sorted(h)
3153 m = max(map(len, fns))
3153 m = max(map(len, fns))
3154 for f in fns:
3154 for f in fns:
3155 if ui.verbose:
3155 if ui.verbose:
3156 commands = cmds[f].replace("|",", ")
3156 commands = cmds[f].replace("|",", ")
3157 ui.write(" %s:\n %s\n"%(commands, h[f]))
3157 ui.write(" %s:\n %s\n"%(commands, h[f]))
3158 else:
3158 else:
3159 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3159 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3160 initindent=' %-*s ' % (m, f),
3160 initindent=' %-*s ' % (m, f),
3161 hangindent=' ' * (m + 4))))
3161 hangindent=' ' * (m + 4))))
3162
3162
3163 if not name:
3163 if not name:
3164 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3164 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3165 if text:
3165 if text:
3166 ui.write("\n%s" % minirst.format(text, textwidth))
3166 ui.write("\n%s" % minirst.format(text, textwidth))
3167
3167
3168 ui.write(_("\nadditional help topics:\n\n"))
3168 ui.write(_("\nadditional help topics:\n\n"))
3169 topics = []
3169 topics = []
3170 for names, header, doc in help.helptable:
3170 for names, header, doc in help.helptable:
3171 topics.append((sorted(names, key=len, reverse=True)[0], header))
3171 topics.append((sorted(names, key=len, reverse=True)[0], header))
3172 topics_len = max([len(s[0]) for s in topics])
3172 topics_len = max([len(s[0]) for s in topics])
3173 for t, desc in topics:
3173 for t, desc in topics:
3174 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3174 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3175
3175
3176 optlist = []
3176 optlist = []
3177 addglobalopts(optlist, True)
3177 addglobalopts(optlist, True)
3178 ui.write(opttext(optlist, textwidth))
3178 ui.write(opttext(optlist, textwidth))
3179
3179
3180 def helptopic(name):
3180 def helptopic(name):
3181 for names, header, doc in help.helptable:
3181 for names, header, doc in help.helptable:
3182 if name in names:
3182 if name in names:
3183 break
3183 break
3184 else:
3184 else:
3185 raise error.UnknownCommand(name)
3185 raise error.UnknownCommand(name)
3186
3186
3187 # description
3187 # description
3188 if not doc:
3188 if not doc:
3189 doc = _("(no help text available)")
3189 doc = _("(no help text available)")
3190 if util.safehasattr(doc, '__call__'):
3190 if util.safehasattr(doc, '__call__'):
3191 doc = doc()
3191 doc = doc()
3192
3192
3193 ui.write("%s\n\n" % header)
3193 ui.write("%s\n\n" % header)
3194 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3194 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3195 try:
3195 try:
3196 cmdutil.findcmd(name, table)
3196 cmdutil.findcmd(name, table)
3197 ui.write(_('\nuse "hg help -c %s" to see help for '
3197 ui.write(_('\nuse "hg help -c %s" to see help for '
3198 'the %s command\n') % (name, name))
3198 'the %s command\n') % (name, name))
3199 except error.UnknownCommand:
3199 except error.UnknownCommand:
3200 pass
3200 pass
3201
3201
3202 def helpext(name):
3202 def helpext(name):
3203 try:
3203 try:
3204 mod = extensions.find(name)
3204 mod = extensions.find(name)
3205 doc = gettext(mod.__doc__) or _('no help text available')
3205 doc = gettext(mod.__doc__) or _('no help text available')
3206 except KeyError:
3206 except KeyError:
3207 mod = None
3207 mod = None
3208 doc = extensions.disabledext(name)
3208 doc = extensions.disabledext(name)
3209 if not doc:
3209 if not doc:
3210 raise error.UnknownCommand(name)
3210 raise error.UnknownCommand(name)
3211
3211
3212 if '\n' not in doc:
3212 if '\n' not in doc:
3213 head, tail = doc, ""
3213 head, tail = doc, ""
3214 else:
3214 else:
3215 head, tail = doc.split('\n', 1)
3215 head, tail = doc.split('\n', 1)
3216 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3216 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3217 if tail:
3217 if tail:
3218 ui.write(minirst.format(tail, textwidth))
3218 ui.write(minirst.format(tail, textwidth))
3219 ui.status('\n')
3219 ui.status('\n')
3220
3220
3221 if mod:
3221 if mod:
3222 try:
3222 try:
3223 ct = mod.cmdtable
3223 ct = mod.cmdtable
3224 except AttributeError:
3224 except AttributeError:
3225 ct = {}
3225 ct = {}
3226 modcmds = set([c.split('|', 1)[0] for c in ct])
3226 modcmds = set([c.split('|', 1)[0] for c in ct])
3227 helplist(modcmds.__contains__)
3227 helplist(modcmds.__contains__)
3228 else:
3228 else:
3229 ui.write(_('use "hg help extensions" for information on enabling '
3229 ui.write(_('use "hg help extensions" for information on enabling '
3230 'extensions\n'))
3230 'extensions\n'))
3231
3231
3232 def helpextcmd(name):
3232 def helpextcmd(name):
3233 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3233 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3234 doc = gettext(mod.__doc__).splitlines()[0]
3234 doc = gettext(mod.__doc__).splitlines()[0]
3235
3235
3236 msg = help.listexts(_("'%s' is provided by the following "
3236 msg = help.listexts(_("'%s' is provided by the following "
3237 "extension:") % cmd, {ext: doc}, indent=4)
3237 "extension:") % cmd, {ext: doc}, indent=4)
3238 ui.write(minirst.format(msg, textwidth))
3238 ui.write(minirst.format(msg, textwidth))
3239 ui.write('\n')
3239 ui.write('\n')
3240 ui.write(_('use "hg help extensions" for information on enabling '
3240 ui.write(_('use "hg help extensions" for information on enabling '
3241 'extensions\n'))
3241 'extensions\n'))
3242
3242
3243 if name and name != 'shortlist':
3243 if name and name != 'shortlist':
3244 i = None
3244 i = None
3245 if unknowncmd:
3245 if unknowncmd:
3246 queries = (helpextcmd,)
3246 queries = (helpextcmd,)
3247 elif opts.get('extension'):
3247 elif opts.get('extension'):
3248 queries = (helpext,)
3248 queries = (helpext,)
3249 elif opts.get('command'):
3249 elif opts.get('command'):
3250 queries = (helpcmd,)
3250 queries = (helpcmd,)
3251 else:
3251 else:
3252 queries = (helptopic, helpcmd, helpext, helpextcmd)
3252 queries = (helptopic, helpcmd, helpext, helpextcmd)
3253 for f in queries:
3253 for f in queries:
3254 try:
3254 try:
3255 f(name)
3255 f(name)
3256 i = None
3256 i = None
3257 break
3257 break
3258 except error.UnknownCommand, inst:
3258 except error.UnknownCommand, inst:
3259 i = inst
3259 i = inst
3260 if i:
3260 if i:
3261 raise i
3261 raise i
3262 else:
3262 else:
3263 # program name
3263 # program name
3264 ui.status(_("Mercurial Distributed SCM\n"))
3264 ui.status(_("Mercurial Distributed SCM\n"))
3265 ui.status('\n')
3265 ui.status('\n')
3266 helplist()
3266 helplist()
3267
3267
3268
3268
3269 @command('identify|id',
3269 @command('identify|id',
3270 [('r', 'rev', '',
3270 [('r', 'rev', '',
3271 _('identify the specified revision'), _('REV')),
3271 _('identify the specified revision'), _('REV')),
3272 ('n', 'num', None, _('show local revision number')),
3272 ('n', 'num', None, _('show local revision number')),
3273 ('i', 'id', None, _('show global revision id')),
3273 ('i', 'id', None, _('show global revision id')),
3274 ('b', 'branch', None, _('show branch')),
3274 ('b', 'branch', None, _('show branch')),
3275 ('t', 'tags', None, _('show tags')),
3275 ('t', 'tags', None, _('show tags')),
3276 ('B', 'bookmarks', None, _('show bookmarks')),
3276 ('B', 'bookmarks', None, _('show bookmarks')),
3277 ] + remoteopts,
3277 ] + remoteopts,
3278 _('[-nibtB] [-r REV] [SOURCE]'))
3278 _('[-nibtB] [-r REV] [SOURCE]'))
3279 def identify(ui, repo, source=None, rev=None,
3279 def identify(ui, repo, source=None, rev=None,
3280 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3280 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3281 """identify the working copy or specified revision
3281 """identify the working copy or specified revision
3282
3282
3283 Print a summary identifying the repository state at REV using one or
3283 Print a summary identifying the repository state at REV using one or
3284 two parent hash identifiers, followed by a "+" if the working
3284 two parent hash identifiers, followed by a "+" if the working
3285 directory has uncommitted changes, the branch name (if not default),
3285 directory has uncommitted changes, the branch name (if not default),
3286 a list of tags, and a list of bookmarks.
3286 a list of tags, and a list of bookmarks.
3287
3287
3288 When REV is not given, print a summary of the current state of the
3288 When REV is not given, print a summary of the current state of the
3289 repository.
3289 repository.
3290
3290
3291 Specifying a path to a repository root or Mercurial bundle will
3291 Specifying a path to a repository root or Mercurial bundle will
3292 cause lookup to operate on that repository/bundle.
3292 cause lookup to operate on that repository/bundle.
3293
3293
3294 .. container:: verbose
3294 .. container:: verbose
3295
3295
3296 Examples:
3296 Examples:
3297
3297
3298 - generate a build identifier for the working directory::
3298 - generate a build identifier for the working directory::
3299
3299
3300 hg id --id > build-id.dat
3300 hg id --id > build-id.dat
3301
3301
3302 - find the revision corresponding to a tag::
3302 - find the revision corresponding to a tag::
3303
3303
3304 hg id -n -r 1.3
3304 hg id -n -r 1.3
3305
3305
3306 - check the most recent revision of a remote repository::
3306 - check the most recent revision of a remote repository::
3307
3307
3308 hg id -r tip http://selenic.com/hg/
3308 hg id -r tip http://selenic.com/hg/
3309
3309
3310 Returns 0 if successful.
3310 Returns 0 if successful.
3311 """
3311 """
3312
3312
3313 if not repo and not source:
3313 if not repo and not source:
3314 raise util.Abort(_("there is no Mercurial repository here "
3314 raise util.Abort(_("there is no Mercurial repository here "
3315 "(.hg not found)"))
3315 "(.hg not found)"))
3316
3316
3317 hexfunc = ui.debugflag and hex or short
3317 hexfunc = ui.debugflag and hex or short
3318 default = not (num or id or branch or tags or bookmarks)
3318 default = not (num or id or branch or tags or bookmarks)
3319 output = []
3319 output = []
3320 revs = []
3320 revs = []
3321
3321
3322 if source:
3322 if source:
3323 source, branches = hg.parseurl(ui.expandpath(source))
3323 source, branches = hg.parseurl(ui.expandpath(source))
3324 repo = hg.peer(ui, opts, source)
3324 repo = hg.peer(ui, opts, source)
3325 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3325 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3326
3326
3327 if not repo.local():
3327 if not repo.local():
3328 if num or branch or tags:
3328 if num or branch or tags:
3329 raise util.Abort(
3329 raise util.Abort(
3330 _("can't query remote revision number, branch, or tags"))
3330 _("can't query remote revision number, branch, or tags"))
3331 if not rev and revs:
3331 if not rev and revs:
3332 rev = revs[0]
3332 rev = revs[0]
3333 if not rev:
3333 if not rev:
3334 rev = "tip"
3334 rev = "tip"
3335
3335
3336 remoterev = repo.lookup(rev)
3336 remoterev = repo.lookup(rev)
3337 if default or id:
3337 if default or id:
3338 output = [hexfunc(remoterev)]
3338 output = [hexfunc(remoterev)]
3339
3339
3340 def getbms():
3340 def getbms():
3341 bms = []
3341 bms = []
3342
3342
3343 if 'bookmarks' in repo.listkeys('namespaces'):
3343 if 'bookmarks' in repo.listkeys('namespaces'):
3344 hexremoterev = hex(remoterev)
3344 hexremoterev = hex(remoterev)
3345 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3345 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3346 if bmr == hexremoterev]
3346 if bmr == hexremoterev]
3347
3347
3348 return bms
3348 return bms
3349
3349
3350 if bookmarks:
3350 if bookmarks:
3351 output.extend(getbms())
3351 output.extend(getbms())
3352 elif default and not ui.quiet:
3352 elif default and not ui.quiet:
3353 # multiple bookmarks for a single parent separated by '/'
3353 # multiple bookmarks for a single parent separated by '/'
3354 bm = '/'.join(getbms())
3354 bm = '/'.join(getbms())
3355 if bm:
3355 if bm:
3356 output.append(bm)
3356 output.append(bm)
3357 else:
3357 else:
3358 if not rev:
3358 if not rev:
3359 ctx = repo[None]
3359 ctx = repo[None]
3360 parents = ctx.parents()
3360 parents = ctx.parents()
3361 changed = ""
3361 changed = ""
3362 if default or id or num:
3362 if default or id or num:
3363 changed = util.any(repo.status()) and "+" or ""
3363 changed = util.any(repo.status()) and "+" or ""
3364 if default or id:
3364 if default or id:
3365 output = ["%s%s" %
3365 output = ["%s%s" %
3366 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3366 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3367 if num:
3367 if num:
3368 output.append("%s%s" %
3368 output.append("%s%s" %
3369 ('+'.join([str(p.rev()) for p in parents]), changed))
3369 ('+'.join([str(p.rev()) for p in parents]), changed))
3370 else:
3370 else:
3371 ctx = scmutil.revsingle(repo, rev)
3371 ctx = scmutil.revsingle(repo, rev)
3372 if default or id:
3372 if default or id:
3373 output = [hexfunc(ctx.node())]
3373 output = [hexfunc(ctx.node())]
3374 if num:
3374 if num:
3375 output.append(str(ctx.rev()))
3375 output.append(str(ctx.rev()))
3376
3376
3377 if default and not ui.quiet:
3377 if default and not ui.quiet:
3378 b = ctx.branch()
3378 b = ctx.branch()
3379 if b != 'default':
3379 if b != 'default':
3380 output.append("(%s)" % b)
3380 output.append("(%s)" % b)
3381
3381
3382 # multiple tags for a single parent separated by '/'
3382 # multiple tags for a single parent separated by '/'
3383 t = '/'.join(ctx.tags())
3383 t = '/'.join(ctx.tags())
3384 if t:
3384 if t:
3385 output.append(t)
3385 output.append(t)
3386
3386
3387 # multiple bookmarks for a single parent separated by '/'
3387 # multiple bookmarks for a single parent separated by '/'
3388 bm = '/'.join(ctx.bookmarks())
3388 bm = '/'.join(ctx.bookmarks())
3389 if bm:
3389 if bm:
3390 output.append(bm)
3390 output.append(bm)
3391 else:
3391 else:
3392 if branch:
3392 if branch:
3393 output.append(ctx.branch())
3393 output.append(ctx.branch())
3394
3394
3395 if tags:
3395 if tags:
3396 output.extend(ctx.tags())
3396 output.extend(ctx.tags())
3397
3397
3398 if bookmarks:
3398 if bookmarks:
3399 output.extend(ctx.bookmarks())
3399 output.extend(ctx.bookmarks())
3400
3400
3401 ui.write("%s\n" % ' '.join(output))
3401 ui.write("%s\n" % ' '.join(output))
3402
3402
3403 @command('import|patch',
3403 @command('import|patch',
3404 [('p', 'strip', 1,
3404 [('p', 'strip', 1,
3405 _('directory strip option for patch. This has the same '
3405 _('directory strip option for patch. This has the same '
3406 'meaning as the corresponding patch option'), _('NUM')),
3406 'meaning as the corresponding patch option'), _('NUM')),
3407 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3407 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3408 ('e', 'edit', False, _('invoke editor on commit messages')),
3408 ('e', 'edit', False, _('invoke editor on commit messages')),
3409 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3409 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3410 ('', 'no-commit', None,
3410 ('', 'no-commit', None,
3411 _("don't commit, just update the working directory")),
3411 _("don't commit, just update the working directory")),
3412 ('', 'bypass', None,
3412 ('', 'bypass', None,
3413 _("apply patch without touching the working directory")),
3413 _("apply patch without touching the working directory")),
3414 ('', 'exact', None,
3414 ('', 'exact', None,
3415 _('apply patch to the nodes from which it was generated')),
3415 _('apply patch to the nodes from which it was generated')),
3416 ('', 'import-branch', None,
3416 ('', 'import-branch', None,
3417 _('use any branch information in patch (implied by --exact)'))] +
3417 _('use any branch information in patch (implied by --exact)'))] +
3418 commitopts + commitopts2 + similarityopts,
3418 commitopts + commitopts2 + similarityopts,
3419 _('[OPTION]... PATCH...'))
3419 _('[OPTION]... PATCH...'))
3420 def import_(ui, repo, patch1=None, *patches, **opts):
3420 def import_(ui, repo, patch1=None, *patches, **opts):
3421 """import an ordered set of patches
3421 """import an ordered set of patches
3422
3422
3423 Import a list of patches and commit them individually (unless
3423 Import a list of patches and commit them individually (unless
3424 --no-commit is specified).
3424 --no-commit is specified).
3425
3425
3426 If there are outstanding changes in the working directory, import
3426 If there are outstanding changes in the working directory, import
3427 will abort unless given the -f/--force flag.
3427 will abort unless given the -f/--force flag.
3428
3428
3429 You can import a patch straight from a mail message. Even patches
3429 You can import a patch straight from a mail message. Even patches
3430 as attachments work (to use the body part, it must have type
3430 as attachments work (to use the body part, it must have type
3431 text/plain or text/x-patch). From and Subject headers of email
3431 text/plain or text/x-patch). From and Subject headers of email
3432 message are used as default committer and commit message. All
3432 message are used as default committer and commit message. All
3433 text/plain body parts before first diff are added to commit
3433 text/plain body parts before first diff are added to commit
3434 message.
3434 message.
3435
3435
3436 If the imported patch was generated by :hg:`export`, user and
3436 If the imported patch was generated by :hg:`export`, user and
3437 description from patch override values from message headers and
3437 description from patch override values from message headers and
3438 body. Values given on command line with -m/--message and -u/--user
3438 body. Values given on command line with -m/--message and -u/--user
3439 override these.
3439 override these.
3440
3440
3441 If --exact is specified, import will set the working directory to
3441 If --exact is specified, import will set the working directory to
3442 the parent of each patch before applying it, and will abort if the
3442 the parent of each patch before applying it, and will abort if the
3443 resulting changeset has a different ID than the one recorded in
3443 resulting changeset has a different ID than the one recorded in
3444 the patch. This may happen due to character set problems or other
3444 the patch. This may happen due to character set problems or other
3445 deficiencies in the text patch format.
3445 deficiencies in the text patch format.
3446
3446
3447 Use --bypass to apply and commit patches directly to the
3447 Use --bypass to apply and commit patches directly to the
3448 repository, not touching the working directory. Without --exact,
3448 repository, not touching the working directory. Without --exact,
3449 patches will be applied on top of the working directory parent
3449 patches will be applied on top of the working directory parent
3450 revision.
3450 revision.
3451
3451
3452 With -s/--similarity, hg will attempt to discover renames and
3452 With -s/--similarity, hg will attempt to discover renames and
3453 copies in the patch in the same way as :hg:`addremove`.
3453 copies in the patch in the same way as :hg:`addremove`.
3454
3454
3455 To read a patch from standard input, use "-" as the patch name. If
3455 To read a patch from standard input, use "-" as the patch name. If
3456 a URL is specified, the patch will be downloaded from it.
3456 a URL is specified, the patch will be downloaded from it.
3457 See :hg:`help dates` for a list of formats valid for -d/--date.
3457 See :hg:`help dates` for a list of formats valid for -d/--date.
3458
3458
3459 .. container:: verbose
3459 .. container:: verbose
3460
3460
3461 Examples:
3461 Examples:
3462
3462
3463 - import a traditional patch from a website and detect renames::
3463 - import a traditional patch from a website and detect renames::
3464
3464
3465 hg import -s 80 http://example.com/bugfix.patch
3465 hg import -s 80 http://example.com/bugfix.patch
3466
3466
3467 - import a changeset from an hgweb server::
3467 - import a changeset from an hgweb server::
3468
3468
3469 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3469 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3470
3470
3471 - import all the patches in an Unix-style mbox::
3471 - import all the patches in an Unix-style mbox::
3472
3472
3473 hg import incoming-patches.mbox
3473 hg import incoming-patches.mbox
3474
3474
3475 - attempt to exactly restore an exported changeset (not always
3475 - attempt to exactly restore an exported changeset (not always
3476 possible)::
3476 possible)::
3477
3477
3478 hg import --exact proposed-fix.patch
3478 hg import --exact proposed-fix.patch
3479
3479
3480 Returns 0 on success.
3480 Returns 0 on success.
3481 """
3481 """
3482
3482
3483 if not patch1:
3483 if not patch1:
3484 raise util.Abort(_('need at least one patch to import'))
3484 raise util.Abort(_('need at least one patch to import'))
3485
3485
3486 patches = (patch1,) + patches
3486 patches = (patch1,) + patches
3487
3487
3488 date = opts.get('date')
3488 date = opts.get('date')
3489 if date:
3489 if date:
3490 opts['date'] = util.parsedate(date)
3490 opts['date'] = util.parsedate(date)
3491
3491
3492 editor = cmdutil.commiteditor
3492 editor = cmdutil.commiteditor
3493 if opts.get('edit'):
3493 if opts.get('edit'):
3494 editor = cmdutil.commitforceeditor
3494 editor = cmdutil.commitforceeditor
3495
3495
3496 update = not opts.get('bypass')
3496 update = not opts.get('bypass')
3497 if not update and opts.get('no_commit'):
3497 if not update and opts.get('no_commit'):
3498 raise util.Abort(_('cannot use --no-commit with --bypass'))
3498 raise util.Abort(_('cannot use --no-commit with --bypass'))
3499 try:
3499 try:
3500 sim = float(opts.get('similarity') or 0)
3500 sim = float(opts.get('similarity') or 0)
3501 except ValueError:
3501 except ValueError:
3502 raise util.Abort(_('similarity must be a number'))
3502 raise util.Abort(_('similarity must be a number'))
3503 if sim < 0 or sim > 100:
3503 if sim < 0 or sim > 100:
3504 raise util.Abort(_('similarity must be between 0 and 100'))
3504 raise util.Abort(_('similarity must be between 0 and 100'))
3505 if sim and not update:
3505 if sim and not update:
3506 raise util.Abort(_('cannot use --similarity with --bypass'))
3506 raise util.Abort(_('cannot use --similarity with --bypass'))
3507
3507
3508 if (opts.get('exact') or not opts.get('force')) and update:
3508 if (opts.get('exact') or not opts.get('force')) and update:
3509 cmdutil.bailifchanged(repo)
3509 cmdutil.bailifchanged(repo)
3510
3510
3511 base = opts["base"]
3511 base = opts["base"]
3512 strip = opts["strip"]
3512 strip = opts["strip"]
3513 wlock = lock = tr = None
3513 wlock = lock = tr = None
3514 msgs = []
3514 msgs = []
3515
3515
3516 def checkexact(repo, n, nodeid):
3516 def checkexact(repo, n, nodeid):
3517 if opts.get('exact') and hex(n) != nodeid:
3517 if opts.get('exact') and hex(n) != nodeid:
3518 repo.rollback()
3518 repo.rollback()
3519 raise util.Abort(_('patch is damaged or loses information'))
3519 raise util.Abort(_('patch is damaged or loses information'))
3520
3520
3521 def tryone(ui, hunk, parents):
3521 def tryone(ui, hunk, parents):
3522 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3522 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3523 patch.extract(ui, hunk)
3523 patch.extract(ui, hunk)
3524
3524
3525 if not tmpname:
3525 if not tmpname:
3526 return (None, None)
3526 return (None, None)
3527 msg = _('applied to working directory')
3527 msg = _('applied to working directory')
3528
3528
3529 try:
3529 try:
3530 cmdline_message = cmdutil.logmessage(ui, opts)
3530 cmdline_message = cmdutil.logmessage(ui, opts)
3531 if cmdline_message:
3531 if cmdline_message:
3532 # pickup the cmdline msg
3532 # pickup the cmdline msg
3533 message = cmdline_message
3533 message = cmdline_message
3534 elif message:
3534 elif message:
3535 # pickup the patch msg
3535 # pickup the patch msg
3536 message = message.strip()
3536 message = message.strip()
3537 else:
3537 else:
3538 # launch the editor
3538 # launch the editor
3539 message = None
3539 message = None
3540 ui.debug('message:\n%s\n' % message)
3540 ui.debug('message:\n%s\n' % message)
3541
3541
3542 if len(parents) == 1:
3542 if len(parents) == 1:
3543 parents.append(repo[nullid])
3543 parents.append(repo[nullid])
3544 if opts.get('exact'):
3544 if opts.get('exact'):
3545 if not nodeid or not p1:
3545 if not nodeid or not p1:
3546 raise util.Abort(_('not a Mercurial patch'))
3546 raise util.Abort(_('not a Mercurial patch'))
3547 p1 = repo[p1]
3547 p1 = repo[p1]
3548 p2 = repo[p2 or nullid]
3548 p2 = repo[p2 or nullid]
3549 elif p2:
3549 elif p2:
3550 try:
3550 try:
3551 p1 = repo[p1]
3551 p1 = repo[p1]
3552 p2 = repo[p2]
3552 p2 = repo[p2]
3553 # Without any options, consider p2 only if the
3553 # Without any options, consider p2 only if the
3554 # patch is being applied on top of the recorded
3554 # patch is being applied on top of the recorded
3555 # first parent.
3555 # first parent.
3556 if p1 != parents[0]:
3556 if p1 != parents[0]:
3557 p1 = parents[0]
3557 p1 = parents[0]
3558 p2 = repo[nullid]
3558 p2 = repo[nullid]
3559 except error.RepoError:
3559 except error.RepoError:
3560 p1, p2 = parents
3560 p1, p2 = parents
3561 else:
3561 else:
3562 p1, p2 = parents
3562 p1, p2 = parents
3563
3563
3564 n = None
3564 n = None
3565 if update:
3565 if update:
3566 if p1 != parents[0]:
3566 if p1 != parents[0]:
3567 hg.clean(repo, p1.node())
3567 hg.clean(repo, p1.node())
3568 if p2 != parents[1]:
3568 if p2 != parents[1]:
3569 repo.dirstate.setparents(p1.node(), p2.node())
3569 repo.dirstate.setparents(p1.node(), p2.node())
3570
3570
3571 if opts.get('exact') or opts.get('import_branch'):
3571 if opts.get('exact') or opts.get('import_branch'):
3572 repo.dirstate.setbranch(branch or 'default')
3572 repo.dirstate.setbranch(branch or 'default')
3573
3573
3574 files = set()
3574 files = set()
3575 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3575 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3576 eolmode=None, similarity=sim / 100.0)
3576 eolmode=None, similarity=sim / 100.0)
3577 files = list(files)
3577 files = list(files)
3578 if opts.get('no_commit'):
3578 if opts.get('no_commit'):
3579 if message:
3579 if message:
3580 msgs.append(message)
3580 msgs.append(message)
3581 else:
3581 else:
3582 if opts.get('exact') or p2:
3582 if opts.get('exact') or p2:
3583 # If you got here, you either use --force and know what
3583 # If you got here, you either use --force and know what
3584 # you are doing or used --exact or a merge patch while
3584 # you are doing or used --exact or a merge patch while
3585 # being updated to its first parent.
3585 # being updated to its first parent.
3586 m = None
3586 m = None
3587 else:
3587 else:
3588 m = scmutil.matchfiles(repo, files or [])
3588 m = scmutil.matchfiles(repo, files or [])
3589 n = repo.commit(message, opts.get('user') or user,
3589 n = repo.commit(message, opts.get('user') or user,
3590 opts.get('date') or date, match=m,
3590 opts.get('date') or date, match=m,
3591 editor=editor)
3591 editor=editor)
3592 checkexact(repo, n, nodeid)
3592 checkexact(repo, n, nodeid)
3593 else:
3593 else:
3594 if opts.get('exact') or opts.get('import_branch'):
3594 if opts.get('exact') or opts.get('import_branch'):
3595 branch = branch or 'default'
3595 branch = branch or 'default'
3596 else:
3596 else:
3597 branch = p1.branch()
3597 branch = p1.branch()
3598 store = patch.filestore()
3598 store = patch.filestore()
3599 try:
3599 try:
3600 files = set()
3600 files = set()
3601 try:
3601 try:
3602 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3602 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3603 files, eolmode=None)
3603 files, eolmode=None)
3604 except patch.PatchError, e:
3604 except patch.PatchError, e:
3605 raise util.Abort(str(e))
3605 raise util.Abort(str(e))
3606 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3606 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3607 message,
3607 message,
3608 opts.get('user') or user,
3608 opts.get('user') or user,
3609 opts.get('date') or date,
3609 opts.get('date') or date,
3610 branch, files, store,
3610 branch, files, store,
3611 editor=cmdutil.commiteditor)
3611 editor=cmdutil.commiteditor)
3612 repo.savecommitmessage(memctx.description())
3612 repo.savecommitmessage(memctx.description())
3613 n = memctx.commit()
3613 n = memctx.commit()
3614 checkexact(repo, n, nodeid)
3614 checkexact(repo, n, nodeid)
3615 finally:
3615 finally:
3616 store.close()
3616 store.close()
3617 if n:
3617 if n:
3618 # i18n: refers to a short changeset id
3618 # i18n: refers to a short changeset id
3619 msg = _('created %s') % short(n)
3619 msg = _('created %s') % short(n)
3620 return (msg, n)
3620 return (msg, n)
3621 finally:
3621 finally:
3622 os.unlink(tmpname)
3622 os.unlink(tmpname)
3623
3623
3624 try:
3624 try:
3625 try:
3625 try:
3626 wlock = repo.wlock()
3626 wlock = repo.wlock()
3627 lock = repo.lock()
3627 lock = repo.lock()
3628 tr = repo.transaction('import')
3628 tr = repo.transaction('import')
3629 parents = repo.parents()
3629 parents = repo.parents()
3630 for patchurl in patches:
3630 for patchurl in patches:
3631 if patchurl == '-':
3631 if patchurl == '-':
3632 ui.status(_('applying patch from stdin\n'))
3632 ui.status(_('applying patch from stdin\n'))
3633 patchfile = ui.fin
3633 patchfile = ui.fin
3634 patchurl = 'stdin' # for error message
3634 patchurl = 'stdin' # for error message
3635 else:
3635 else:
3636 patchurl = os.path.join(base, patchurl)
3636 patchurl = os.path.join(base, patchurl)
3637 ui.status(_('applying %s\n') % patchurl)
3637 ui.status(_('applying %s\n') % patchurl)
3638 patchfile = url.open(ui, patchurl)
3638 patchfile = url.open(ui, patchurl)
3639
3639
3640 haspatch = False
3640 haspatch = False
3641 for hunk in patch.split(patchfile):
3641 for hunk in patch.split(patchfile):
3642 (msg, node) = tryone(ui, hunk, parents)
3642 (msg, node) = tryone(ui, hunk, parents)
3643 if msg:
3643 if msg:
3644 haspatch = True
3644 haspatch = True
3645 ui.note(msg + '\n')
3645 ui.note(msg + '\n')
3646 if update or opts.get('exact'):
3646 if update or opts.get('exact'):
3647 parents = repo.parents()
3647 parents = repo.parents()
3648 else:
3648 else:
3649 parents = [repo[node]]
3649 parents = [repo[node]]
3650
3650
3651 if not haspatch:
3651 if not haspatch:
3652 raise util.Abort(_('%s: no diffs found') % patchurl)
3652 raise util.Abort(_('%s: no diffs found') % patchurl)
3653
3653
3654 tr.close()
3654 tr.close()
3655 if msgs:
3655 if msgs:
3656 repo.savecommitmessage('\n* * *\n'.join(msgs))
3656 repo.savecommitmessage('\n* * *\n'.join(msgs))
3657 except:
3657 except:
3658 # wlock.release() indirectly calls dirstate.write(): since
3658 # wlock.release() indirectly calls dirstate.write(): since
3659 # we're crashing, we do not want to change the working dir
3659 # we're crashing, we do not want to change the working dir
3660 # parent after all, so make sure it writes nothing
3660 # parent after all, so make sure it writes nothing
3661 repo.dirstate.invalidate()
3661 repo.dirstate.invalidate()
3662 raise
3662 raise
3663 finally:
3663 finally:
3664 if tr:
3664 if tr:
3665 tr.release()
3665 tr.release()
3666 release(lock, wlock)
3666 release(lock, wlock)
3667
3667
3668 @command('incoming|in',
3668 @command('incoming|in',
3669 [('f', 'force', None,
3669 [('f', 'force', None,
3670 _('run even if remote repository is unrelated')),
3670 _('run even if remote repository is unrelated')),
3671 ('n', 'newest-first', None, _('show newest record first')),
3671 ('n', 'newest-first', None, _('show newest record first')),
3672 ('', 'bundle', '',
3672 ('', 'bundle', '',
3673 _('file to store the bundles into'), _('FILE')),
3673 _('file to store the bundles into'), _('FILE')),
3674 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3674 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3675 ('B', 'bookmarks', False, _("compare bookmarks")),
3675 ('B', 'bookmarks', False, _("compare bookmarks")),
3676 ('b', 'branch', [],
3676 ('b', 'branch', [],
3677 _('a specific branch you would like to pull'), _('BRANCH')),
3677 _('a specific branch you would like to pull'), _('BRANCH')),
3678 ] + logopts + remoteopts + subrepoopts,
3678 ] + logopts + remoteopts + subrepoopts,
3679 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3679 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3680 def incoming(ui, repo, source="default", **opts):
3680 def incoming(ui, repo, source="default", **opts):
3681 """show new changesets found in source
3681 """show new changesets found in source
3682
3682
3683 Show new changesets found in the specified path/URL or the default
3683 Show new changesets found in the specified path/URL or the default
3684 pull location. These are the changesets that would have been pulled
3684 pull location. These are the changesets that would have been pulled
3685 if a pull at the time you issued this command.
3685 if a pull at the time you issued this command.
3686
3686
3687 For remote repository, using --bundle avoids downloading the
3687 For remote repository, using --bundle avoids downloading the
3688 changesets twice if the incoming is followed by a pull.
3688 changesets twice if the incoming is followed by a pull.
3689
3689
3690 See pull for valid source format details.
3690 See pull for valid source format details.
3691
3691
3692 Returns 0 if there are incoming changes, 1 otherwise.
3692 Returns 0 if there are incoming changes, 1 otherwise.
3693 """
3693 """
3694 if opts.get('bundle') and opts.get('subrepos'):
3694 if opts.get('bundle') and opts.get('subrepos'):
3695 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3695 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3696
3696
3697 if opts.get('bookmarks'):
3697 if opts.get('bookmarks'):
3698 source, branches = hg.parseurl(ui.expandpath(source),
3698 source, branches = hg.parseurl(ui.expandpath(source),
3699 opts.get('branch'))
3699 opts.get('branch'))
3700 other = hg.peer(repo, opts, source)
3700 other = hg.peer(repo, opts, source)
3701 if 'bookmarks' not in other.listkeys('namespaces'):
3701 if 'bookmarks' not in other.listkeys('namespaces'):
3702 ui.warn(_("remote doesn't support bookmarks\n"))
3702 ui.warn(_("remote doesn't support bookmarks\n"))
3703 return 0
3703 return 0
3704 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3704 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3705 return bookmarks.diff(ui, repo, other)
3705 return bookmarks.diff(ui, repo, other)
3706
3706
3707 repo._subtoppath = ui.expandpath(source)
3707 repo._subtoppath = ui.expandpath(source)
3708 try:
3708 try:
3709 return hg.incoming(ui, repo, source, opts)
3709 return hg.incoming(ui, repo, source, opts)
3710 finally:
3710 finally:
3711 del repo._subtoppath
3711 del repo._subtoppath
3712
3712
3713
3713
3714 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3714 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3715 def init(ui, dest=".", **opts):
3715 def init(ui, dest=".", **opts):
3716 """create a new repository in the given directory
3716 """create a new repository in the given directory
3717
3717
3718 Initialize a new repository in the given directory. If the given
3718 Initialize a new repository in the given directory. If the given
3719 directory does not exist, it will be created.
3719 directory does not exist, it will be created.
3720
3720
3721 If no directory is given, the current directory is used.
3721 If no directory is given, the current directory is used.
3722
3722
3723 It is possible to specify an ``ssh://`` URL as the destination.
3723 It is possible to specify an ``ssh://`` URL as the destination.
3724 See :hg:`help urls` for more information.
3724 See :hg:`help urls` for more information.
3725
3725
3726 Returns 0 on success.
3726 Returns 0 on success.
3727 """
3727 """
3728 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3728 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3729
3729
3730 @command('locate',
3730 @command('locate',
3731 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3731 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3732 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3732 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3733 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3733 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3734 ] + walkopts,
3734 ] + walkopts,
3735 _('[OPTION]... [PATTERN]...'))
3735 _('[OPTION]... [PATTERN]...'))
3736 def locate(ui, repo, *pats, **opts):
3736 def locate(ui, repo, *pats, **opts):
3737 """locate files matching specific patterns
3737 """locate files matching specific patterns
3738
3738
3739 Print files under Mercurial control in the working directory whose
3739 Print files under Mercurial control in the working directory whose
3740 names match the given patterns.
3740 names match the given patterns.
3741
3741
3742 By default, this command searches all directories in the working
3742 By default, this command searches all directories in the working
3743 directory. To search just the current directory and its
3743 directory. To search just the current directory and its
3744 subdirectories, use "--include .".
3744 subdirectories, use "--include .".
3745
3745
3746 If no patterns are given to match, this command prints the names
3746 If no patterns are given to match, this command prints the names
3747 of all files under Mercurial control in the working directory.
3747 of all files under Mercurial control in the working directory.
3748
3748
3749 If you want to feed the output of this command into the "xargs"
3749 If you want to feed the output of this command into the "xargs"
3750 command, use the -0 option to both this command and "xargs". This
3750 command, use the -0 option to both this command and "xargs". This
3751 will avoid the problem of "xargs" treating single filenames that
3751 will avoid the problem of "xargs" treating single filenames that
3752 contain whitespace as multiple filenames.
3752 contain whitespace as multiple filenames.
3753
3753
3754 Returns 0 if a match is found, 1 otherwise.
3754 Returns 0 if a match is found, 1 otherwise.
3755 """
3755 """
3756 end = opts.get('print0') and '\0' or '\n'
3756 end = opts.get('print0') and '\0' or '\n'
3757 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3757 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3758
3758
3759 ret = 1
3759 ret = 1
3760 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3760 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3761 m.bad = lambda x, y: False
3761 m.bad = lambda x, y: False
3762 for abs in repo[rev].walk(m):
3762 for abs in repo[rev].walk(m):
3763 if not rev and abs not in repo.dirstate:
3763 if not rev and abs not in repo.dirstate:
3764 continue
3764 continue
3765 if opts.get('fullpath'):
3765 if opts.get('fullpath'):
3766 ui.write(repo.wjoin(abs), end)
3766 ui.write(repo.wjoin(abs), end)
3767 else:
3767 else:
3768 ui.write(((pats and m.rel(abs)) or abs), end)
3768 ui.write(((pats and m.rel(abs)) or abs), end)
3769 ret = 0
3769 ret = 0
3770
3770
3771 return ret
3771 return ret
3772
3772
3773 @command('^log|history',
3773 @command('^log|history',
3774 [('f', 'follow', None,
3774 [('f', 'follow', None,
3775 _('follow changeset history, or file history across copies and renames')),
3775 _('follow changeset history, or file history across copies and renames')),
3776 ('', 'follow-first', None,
3776 ('', 'follow-first', None,
3777 _('only follow the first parent of merge changesets (DEPRECATED)')),
3777 _('only follow the first parent of merge changesets (DEPRECATED)')),
3778 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3778 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3779 ('C', 'copies', None, _('show copied files')),
3779 ('C', 'copies', None, _('show copied files')),
3780 ('k', 'keyword', [],
3780 ('k', 'keyword', [],
3781 _('do case-insensitive search for a given text'), _('TEXT')),
3781 _('do case-insensitive search for a given text'), _('TEXT')),
3782 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3782 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3783 ('', 'removed', None, _('include revisions where files were removed')),
3783 ('', 'removed', None, _('include revisions where files were removed')),
3784 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3784 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3785 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3785 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3786 ('', 'only-branch', [],
3786 ('', 'only-branch', [],
3787 _('show only changesets within the given named branch (DEPRECATED)'),
3787 _('show only changesets within the given named branch (DEPRECATED)'),
3788 _('BRANCH')),
3788 _('BRANCH')),
3789 ('b', 'branch', [],
3789 ('b', 'branch', [],
3790 _('show changesets within the given named branch'), _('BRANCH')),
3790 _('show changesets within the given named branch'), _('BRANCH')),
3791 ('P', 'prune', [],
3791 ('P', 'prune', [],
3792 _('do not display revision or any of its ancestors'), _('REV')),
3792 _('do not display revision or any of its ancestors'), _('REV')),
3793 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3793 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3794 ] + logopts + walkopts,
3794 ] + logopts + walkopts,
3795 _('[OPTION]... [FILE]'))
3795 _('[OPTION]... [FILE]'))
3796 def log(ui, repo, *pats, **opts):
3796 def log(ui, repo, *pats, **opts):
3797 """show revision history of entire repository or files
3797 """show revision history of entire repository or files
3798
3798
3799 Print the revision history of the specified files or the entire
3799 Print the revision history of the specified files or the entire
3800 project.
3800 project.
3801
3801
3802 If no revision range is specified, the default is ``tip:0`` unless
3802 If no revision range is specified, the default is ``tip:0`` unless
3803 --follow is set, in which case the working directory parent is
3803 --follow is set, in which case the working directory parent is
3804 used as the starting revision.
3804 used as the starting revision.
3805
3805
3806 File history is shown without following rename or copy history of
3806 File history is shown without following rename or copy history of
3807 files. Use -f/--follow with a filename to follow history across
3807 files. Use -f/--follow with a filename to follow history across
3808 renames and copies. --follow without a filename will only show
3808 renames and copies. --follow without a filename will only show
3809 ancestors or descendants of the starting revision.
3809 ancestors or descendants of the starting revision.
3810
3810
3811 By default this command prints revision number and changeset id,
3811 By default this command prints revision number and changeset id,
3812 tags, non-trivial parents, user, date and time, and a summary for
3812 tags, non-trivial parents, user, date and time, and a summary for
3813 each commit. When the -v/--verbose switch is used, the list of
3813 each commit. When the -v/--verbose switch is used, the list of
3814 changed files and full commit message are shown.
3814 changed files and full commit message are shown.
3815
3815
3816 .. note::
3816 .. note::
3817 log -p/--patch may generate unexpected diff output for merge
3817 log -p/--patch may generate unexpected diff output for merge
3818 changesets, as it will only compare the merge changeset against
3818 changesets, as it will only compare the merge changeset against
3819 its first parent. Also, only files different from BOTH parents
3819 its first parent. Also, only files different from BOTH parents
3820 will appear in files:.
3820 will appear in files:.
3821
3821
3822 .. note::
3822 .. note::
3823 for performance reasons, log FILE may omit duplicate changes
3823 for performance reasons, log FILE may omit duplicate changes
3824 made on branches and will not show deletions. To see all
3824 made on branches and will not show deletions. To see all
3825 changes including duplicates and deletions, use the --removed
3825 changes including duplicates and deletions, use the --removed
3826 switch.
3826 switch.
3827
3827
3828 .. container:: verbose
3828 .. container:: verbose
3829
3829
3830 Some examples:
3830 Some examples:
3831
3831
3832 - changesets with full descriptions and file lists::
3832 - changesets with full descriptions and file lists::
3833
3833
3834 hg log -v
3834 hg log -v
3835
3835
3836 - changesets ancestral to the working directory::
3836 - changesets ancestral to the working directory::
3837
3837
3838 hg log -f
3838 hg log -f
3839
3839
3840 - last 10 commits on the current branch::
3840 - last 10 commits on the current branch::
3841
3841
3842 hg log -l 10 -b .
3842 hg log -l 10 -b .
3843
3843
3844 - changesets showing all modifications of a file, including removals::
3844 - changesets showing all modifications of a file, including removals::
3845
3845
3846 hg log --removed file.c
3846 hg log --removed file.c
3847
3847
3848 - all changesets that touch a directory, with diffs, excluding merges::
3848 - all changesets that touch a directory, with diffs, excluding merges::
3849
3849
3850 hg log -Mp lib/
3850 hg log -Mp lib/
3851
3851
3852 - all revision numbers that match a keyword::
3852 - all revision numbers that match a keyword::
3853
3853
3854 hg log -k bug --template "{rev}\\n"
3854 hg log -k bug --template "{rev}\\n"
3855
3855
3856 - check if a given changeset is included is a tagged release::
3856 - check if a given changeset is included is a tagged release::
3857
3857
3858 hg log -r "a21ccf and ancestor(1.9)"
3858 hg log -r "a21ccf and ancestor(1.9)"
3859
3859
3860 - find all changesets by some user in a date range::
3860 - find all changesets by some user in a date range::
3861
3861
3862 hg log -k alice -d "may 2008 to jul 2008"
3862 hg log -k alice -d "may 2008 to jul 2008"
3863
3863
3864 - summary of all changesets after the last tag::
3864 - summary of all changesets after the last tag::
3865
3865
3866 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3866 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3867
3867
3868 See :hg:`help dates` for a list of formats valid for -d/--date.
3868 See :hg:`help dates` for a list of formats valid for -d/--date.
3869
3869
3870 See :hg:`help revisions` and :hg:`help revsets` for more about
3870 See :hg:`help revisions` and :hg:`help revsets` for more about
3871 specifying revisions.
3871 specifying revisions.
3872
3872
3873 Returns 0 on success.
3873 Returns 0 on success.
3874 """
3874 """
3875
3875
3876 matchfn = scmutil.match(repo[None], pats, opts)
3876 matchfn = scmutil.match(repo[None], pats, opts)
3877 limit = cmdutil.loglimit(opts)
3877 limit = cmdutil.loglimit(opts)
3878 count = 0
3878 count = 0
3879
3879
3880 endrev = None
3880 endrev = None
3881 if opts.get('copies') and opts.get('rev'):
3881 if opts.get('copies') and opts.get('rev'):
3882 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3882 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3883
3883
3884 df = False
3884 df = False
3885 if opts["date"]:
3885 if opts["date"]:
3886 df = util.matchdate(opts["date"])
3886 df = util.matchdate(opts["date"])
3887
3887
3888 branches = opts.get('branch', []) + opts.get('only_branch', [])
3888 branches = opts.get('branch', []) + opts.get('only_branch', [])
3889 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3889 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3890
3890
3891 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3891 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3892 def prep(ctx, fns):
3892 def prep(ctx, fns):
3893 rev = ctx.rev()
3893 rev = ctx.rev()
3894 parents = [p for p in repo.changelog.parentrevs(rev)
3894 parents = [p for p in repo.changelog.parentrevs(rev)
3895 if p != nullrev]
3895 if p != nullrev]
3896 if opts.get('no_merges') and len(parents) == 2:
3896 if opts.get('no_merges') and len(parents) == 2:
3897 return
3897 return
3898 if opts.get('only_merges') and len(parents) != 2:
3898 if opts.get('only_merges') and len(parents) != 2:
3899 return
3899 return
3900 if opts.get('branch') and ctx.branch() not in opts['branch']:
3900 if opts.get('branch') and ctx.branch() not in opts['branch']:
3901 return
3901 return
3902 if not opts.get('hidden') and ctx.hidden():
3902 if not opts.get('hidden') and ctx.hidden():
3903 return
3903 return
3904 if df and not df(ctx.date()[0]):
3904 if df and not df(ctx.date()[0]):
3905 return
3905 return
3906
3906
3907 lower = encoding.lower
3907 lower = encoding.lower
3908 if opts.get('user'):
3908 if opts.get('user'):
3909 luser = lower(ctx.user())
3909 luser = lower(ctx.user())
3910 for k in [lower(x) for x in opts['user']]:
3910 for k in [lower(x) for x in opts['user']]:
3911 if (k in luser):
3911 if (k in luser):
3912 break
3912 break
3913 else:
3913 else:
3914 return
3914 return
3915 if opts.get('keyword'):
3915 if opts.get('keyword'):
3916 luser = lower(ctx.user())
3916 luser = lower(ctx.user())
3917 ldesc = lower(ctx.description())
3917 ldesc = lower(ctx.description())
3918 lfiles = lower(" ".join(ctx.files()))
3918 lfiles = lower(" ".join(ctx.files()))
3919 for k in [lower(x) for x in opts['keyword']]:
3919 for k in [lower(x) for x in opts['keyword']]:
3920 if (k in luser or k in ldesc or k in lfiles):
3920 if (k in luser or k in ldesc or k in lfiles):
3921 break
3921 break
3922 else:
3922 else:
3923 return
3923 return
3924
3924
3925 copies = None
3925 copies = None
3926 if opts.get('copies') and rev:
3926 if opts.get('copies') and rev:
3927 copies = []
3927 copies = []
3928 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3928 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3929 for fn in ctx.files():
3929 for fn in ctx.files():
3930 rename = getrenamed(fn, rev)
3930 rename = getrenamed(fn, rev)
3931 if rename:
3931 if rename:
3932 copies.append((fn, rename[0]))
3932 copies.append((fn, rename[0]))
3933
3933
3934 revmatchfn = None
3934 revmatchfn = None
3935 if opts.get('patch') or opts.get('stat'):
3935 if opts.get('patch') or opts.get('stat'):
3936 if opts.get('follow') or opts.get('follow_first'):
3936 if opts.get('follow') or opts.get('follow_first'):
3937 # note: this might be wrong when following through merges
3937 # note: this might be wrong when following through merges
3938 revmatchfn = scmutil.match(repo[None], fns, default='path')
3938 revmatchfn = scmutil.match(repo[None], fns, default='path')
3939 else:
3939 else:
3940 revmatchfn = matchfn
3940 revmatchfn = matchfn
3941
3941
3942 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3942 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3943
3943
3944 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3944 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3945 if count == limit:
3945 if count == limit:
3946 break
3946 break
3947 if displayer.flush(ctx.rev()):
3947 if displayer.flush(ctx.rev()):
3948 count += 1
3948 count += 1
3949 displayer.close()
3949 displayer.close()
3950
3950
3951 @command('manifest',
3951 @command('manifest',
3952 [('r', 'rev', '', _('revision to display'), _('REV')),
3952 [('r', 'rev', '', _('revision to display'), _('REV')),
3953 ('', 'all', False, _("list files from all revisions"))],
3953 ('', 'all', False, _("list files from all revisions"))],
3954 _('[-r REV]'))
3954 _('[-r REV]'))
3955 def manifest(ui, repo, node=None, rev=None, **opts):
3955 def manifest(ui, repo, node=None, rev=None, **opts):
3956 """output the current or given revision of the project manifest
3956 """output the current or given revision of the project manifest
3957
3957
3958 Print a list of version controlled files for the given revision.
3958 Print a list of version controlled files for the given revision.
3959 If no revision is given, the first parent of the working directory
3959 If no revision is given, the first parent of the working directory
3960 is used, or the null revision if no revision is checked out.
3960 is used, or the null revision if no revision is checked out.
3961
3961
3962 With -v, print file permissions, symlink and executable bits.
3962 With -v, print file permissions, symlink and executable bits.
3963 With --debug, print file revision hashes.
3963 With --debug, print file revision hashes.
3964
3964
3965 If option --all is specified, the list of all files from all revisions
3965 If option --all is specified, the list of all files from all revisions
3966 is printed. This includes deleted and renamed files.
3966 is printed. This includes deleted and renamed files.
3967
3967
3968 Returns 0 on success.
3968 Returns 0 on success.
3969 """
3969 """
3970 if opts.get('all'):
3970 if opts.get('all'):
3971 if rev or node:
3971 if rev or node:
3972 raise util.Abort(_("can't specify a revision with --all"))
3972 raise util.Abort(_("can't specify a revision with --all"))
3973
3973
3974 res = []
3974 res = []
3975 prefix = "data/"
3975 prefix = "data/"
3976 suffix = ".i"
3976 suffix = ".i"
3977 plen = len(prefix)
3977 plen = len(prefix)
3978 slen = len(suffix)
3978 slen = len(suffix)
3979 lock = repo.lock()
3979 lock = repo.lock()
3980 try:
3980 try:
3981 for fn, b, size in repo.store.datafiles():
3981 for fn, b, size in repo.store.datafiles():
3982 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3982 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3983 res.append(fn[plen:-slen])
3983 res.append(fn[plen:-slen])
3984 finally:
3984 finally:
3985 lock.release()
3985 lock.release()
3986 for f in sorted(res):
3986 for f in sorted(res):
3987 ui.write("%s\n" % f)
3987 ui.write("%s\n" % f)
3988 return
3988 return
3989
3989
3990 if rev and node:
3990 if rev and node:
3991 raise util.Abort(_("please specify just one revision"))
3991 raise util.Abort(_("please specify just one revision"))
3992
3992
3993 if not node:
3993 if not node:
3994 node = rev
3994 node = rev
3995
3995
3996 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3996 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3997 ctx = scmutil.revsingle(repo, node)
3997 ctx = scmutil.revsingle(repo, node)
3998 for f in ctx:
3998 for f in ctx:
3999 if ui.debugflag:
3999 if ui.debugflag:
4000 ui.write("%40s " % hex(ctx.manifest()[f]))
4000 ui.write("%40s " % hex(ctx.manifest()[f]))
4001 if ui.verbose:
4001 if ui.verbose:
4002 ui.write(decor[ctx.flags(f)])
4002 ui.write(decor[ctx.flags(f)])
4003 ui.write("%s\n" % f)
4003 ui.write("%s\n" % f)
4004
4004
4005 @command('^merge',
4005 @command('^merge',
4006 [('f', 'force', None, _('force a merge with outstanding changes')),
4006 [('f', 'force', None, _('force a merge with outstanding changes')),
4007 ('r', 'rev', '', _('revision to merge'), _('REV')),
4007 ('r', 'rev', '', _('revision to merge'), _('REV')),
4008 ('P', 'preview', None,
4008 ('P', 'preview', None,
4009 _('review revisions to merge (no merge is performed)'))
4009 _('review revisions to merge (no merge is performed)'))
4010 ] + mergetoolopts,
4010 ] + mergetoolopts,
4011 _('[-P] [-f] [[-r] REV]'))
4011 _('[-P] [-f] [[-r] REV]'))
4012 def merge(ui, repo, node=None, **opts):
4012 def merge(ui, repo, node=None, **opts):
4013 """merge working directory with another revision
4013 """merge working directory with another revision
4014
4014
4015 The current working directory is updated with all changes made in
4015 The current working directory is updated with all changes made in
4016 the requested revision since the last common predecessor revision.
4016 the requested revision since the last common predecessor revision.
4017
4017
4018 Files that changed between either parent are marked as changed for
4018 Files that changed between either parent are marked as changed for
4019 the next commit and a commit must be performed before any further
4019 the next commit and a commit must be performed before any further
4020 updates to the repository are allowed. The next commit will have
4020 updates to the repository are allowed. The next commit will have
4021 two parents.
4021 two parents.
4022
4022
4023 ``--tool`` can be used to specify the merge tool used for file
4023 ``--tool`` can be used to specify the merge tool used for file
4024 merges. It overrides the HGMERGE environment variable and your
4024 merges. It overrides the HGMERGE environment variable and your
4025 configuration files. See :hg:`help merge-tools` for options.
4025 configuration files. See :hg:`help merge-tools` for options.
4026
4026
4027 If no revision is specified, the working directory's parent is a
4027 If no revision is specified, the working directory's parent is a
4028 head revision, and the current branch contains exactly one other
4028 head revision, and the current branch contains exactly one other
4029 head, the other head is merged with by default. Otherwise, an
4029 head, the other head is merged with by default. Otherwise, an
4030 explicit revision with which to merge with must be provided.
4030 explicit revision with which to merge with must be provided.
4031
4031
4032 :hg:`resolve` must be used to resolve unresolved files.
4032 :hg:`resolve` must be used to resolve unresolved files.
4033
4033
4034 To undo an uncommitted merge, use :hg:`update --clean .` which
4034 To undo an uncommitted merge, use :hg:`update --clean .` which
4035 will check out a clean copy of the original merge parent, losing
4035 will check out a clean copy of the original merge parent, losing
4036 all changes.
4036 all changes.
4037
4037
4038 Returns 0 on success, 1 if there are unresolved files.
4038 Returns 0 on success, 1 if there are unresolved files.
4039 """
4039 """
4040
4040
4041 if opts.get('rev') and node:
4041 if opts.get('rev') and node:
4042 raise util.Abort(_("please specify just one revision"))
4042 raise util.Abort(_("please specify just one revision"))
4043 if not node:
4043 if not node:
4044 node = opts.get('rev')
4044 node = opts.get('rev')
4045
4045
4046 if not node:
4046 if not node:
4047 branch = repo[None].branch()
4047 branch = repo[None].branch()
4048 bheads = repo.branchheads(branch)
4048 bheads = repo.branchheads(branch)
4049 if len(bheads) > 2:
4049 if len(bheads) > 2:
4050 raise util.Abort(_("branch '%s' has %d heads - "
4050 raise util.Abort(_("branch '%s' has %d heads - "
4051 "please merge with an explicit rev")
4051 "please merge with an explicit rev")
4052 % (branch, len(bheads)),
4052 % (branch, len(bheads)),
4053 hint=_("run 'hg heads .' to see heads"))
4053 hint=_("run 'hg heads .' to see heads"))
4054
4054
4055 parent = repo.dirstate.p1()
4055 parent = repo.dirstate.p1()
4056 if len(bheads) == 1:
4056 if len(bheads) == 1:
4057 if len(repo.heads()) > 1:
4057 if len(repo.heads()) > 1:
4058 raise util.Abort(_("branch '%s' has one head - "
4058 raise util.Abort(_("branch '%s' has one head - "
4059 "please merge with an explicit rev")
4059 "please merge with an explicit rev")
4060 % branch,
4060 % branch,
4061 hint=_("run 'hg heads' to see all heads"))
4061 hint=_("run 'hg heads' to see all heads"))
4062 msg, hint = _('nothing to merge'), None
4062 msg, hint = _('nothing to merge'), None
4063 if parent != repo.lookup(branch):
4063 if parent != repo.lookup(branch):
4064 hint = _("use 'hg update' instead")
4064 hint = _("use 'hg update' instead")
4065 raise util.Abort(msg, hint=hint)
4065 raise util.Abort(msg, hint=hint)
4066
4066
4067 if parent not in bheads:
4067 if parent not in bheads:
4068 raise util.Abort(_('working directory not at a head revision'),
4068 raise util.Abort(_('working directory not at a head revision'),
4069 hint=_("use 'hg update' or merge with an "
4069 hint=_("use 'hg update' or merge with an "
4070 "explicit revision"))
4070 "explicit revision"))
4071 node = parent == bheads[0] and bheads[-1] or bheads[0]
4071 node = parent == bheads[0] and bheads[-1] or bheads[0]
4072 else:
4072 else:
4073 node = scmutil.revsingle(repo, node).node()
4073 node = scmutil.revsingle(repo, node).node()
4074
4074
4075 if opts.get('preview'):
4075 if opts.get('preview'):
4076 # find nodes that are ancestors of p2 but not of p1
4076 # find nodes that are ancestors of p2 but not of p1
4077 p1 = repo.lookup('.')
4077 p1 = repo.lookup('.')
4078 p2 = repo.lookup(node)
4078 p2 = repo.lookup(node)
4079 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4079 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4080
4080
4081 displayer = cmdutil.show_changeset(ui, repo, opts)
4081 displayer = cmdutil.show_changeset(ui, repo, opts)
4082 for node in nodes:
4082 for node in nodes:
4083 displayer.show(repo[node])
4083 displayer.show(repo[node])
4084 displayer.close()
4084 displayer.close()
4085 return 0
4085 return 0
4086
4086
4087 try:
4087 try:
4088 # ui.forcemerge is an internal variable, do not document
4088 # ui.forcemerge is an internal variable, do not document
4089 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4089 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4090 return hg.merge(repo, node, force=opts.get('force'))
4090 return hg.merge(repo, node, force=opts.get('force'))
4091 finally:
4091 finally:
4092 ui.setconfig('ui', 'forcemerge', '')
4092 ui.setconfig('ui', 'forcemerge', '')
4093
4093
4094 @command('outgoing|out',
4094 @command('outgoing|out',
4095 [('f', 'force', None, _('run even when the destination is unrelated')),
4095 [('f', 'force', None, _('run even when the destination is unrelated')),
4096 ('r', 'rev', [],
4096 ('r', 'rev', [],
4097 _('a changeset intended to be included in the destination'), _('REV')),
4097 _('a changeset intended to be included in the destination'), _('REV')),
4098 ('n', 'newest-first', None, _('show newest record first')),
4098 ('n', 'newest-first', None, _('show newest record first')),
4099 ('B', 'bookmarks', False, _('compare bookmarks')),
4099 ('B', 'bookmarks', False, _('compare bookmarks')),
4100 ('b', 'branch', [], _('a specific branch you would like to push'),
4100 ('b', 'branch', [], _('a specific branch you would like to push'),
4101 _('BRANCH')),
4101 _('BRANCH')),
4102 ] + logopts + remoteopts + subrepoopts,
4102 ] + logopts + remoteopts + subrepoopts,
4103 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4103 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4104 def outgoing(ui, repo, dest=None, **opts):
4104 def outgoing(ui, repo, dest=None, **opts):
4105 """show changesets not found in the destination
4105 """show changesets not found in the destination
4106
4106
4107 Show changesets not found in the specified destination repository
4107 Show changesets not found in the specified destination repository
4108 or the default push location. These are the changesets that would
4108 or the default push location. These are the changesets that would
4109 be pushed if a push was requested.
4109 be pushed if a push was requested.
4110
4110
4111 See pull for details of valid destination formats.
4111 See pull for details of valid destination formats.
4112
4112
4113 Returns 0 if there are outgoing changes, 1 otherwise.
4113 Returns 0 if there are outgoing changes, 1 otherwise.
4114 """
4114 """
4115
4115
4116 if opts.get('bookmarks'):
4116 if opts.get('bookmarks'):
4117 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4117 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4118 dest, branches = hg.parseurl(dest, opts.get('branch'))
4118 dest, branches = hg.parseurl(dest, opts.get('branch'))
4119 other = hg.peer(repo, opts, dest)
4119 other = hg.peer(repo, opts, dest)
4120 if 'bookmarks' not in other.listkeys('namespaces'):
4120 if 'bookmarks' not in other.listkeys('namespaces'):
4121 ui.warn(_("remote doesn't support bookmarks\n"))
4121 ui.warn(_("remote doesn't support bookmarks\n"))
4122 return 0
4122 return 0
4123 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4123 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4124 return bookmarks.diff(ui, other, repo)
4124 return bookmarks.diff(ui, other, repo)
4125
4125
4126 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4126 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4127 try:
4127 try:
4128 return hg.outgoing(ui, repo, dest, opts)
4128 return hg.outgoing(ui, repo, dest, opts)
4129 finally:
4129 finally:
4130 del repo._subtoppath
4130 del repo._subtoppath
4131
4131
4132 @command('parents',
4132 @command('parents',
4133 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4133 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4134 ] + templateopts,
4134 ] + templateopts,
4135 _('[-r REV] [FILE]'))
4135 _('[-r REV] [FILE]'))
4136 def parents(ui, repo, file_=None, **opts):
4136 def parents(ui, repo, file_=None, **opts):
4137 """show the parents of the working directory or revision
4137 """show the parents of the working directory or revision
4138
4138
4139 Print the working directory's parent revisions. If a revision is
4139 Print the working directory's parent revisions. If a revision is
4140 given via -r/--rev, the parent of that revision will be printed.
4140 given via -r/--rev, the parent of that revision will be printed.
4141 If a file argument is given, the revision in which the file was
4141 If a file argument is given, the revision in which the file was
4142 last changed (before the working directory revision or the
4142 last changed (before the working directory revision or the
4143 argument to --rev if given) is printed.
4143 argument to --rev if given) is printed.
4144
4144
4145 Returns 0 on success.
4145 Returns 0 on success.
4146 """
4146 """
4147
4147
4148 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4148 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4149
4149
4150 if file_:
4150 if file_:
4151 m = scmutil.match(ctx, (file_,), opts)
4151 m = scmutil.match(ctx, (file_,), opts)
4152 if m.anypats() or len(m.files()) != 1:
4152 if m.anypats() or len(m.files()) != 1:
4153 raise util.Abort(_('can only specify an explicit filename'))
4153 raise util.Abort(_('can only specify an explicit filename'))
4154 file_ = m.files()[0]
4154 file_ = m.files()[0]
4155 filenodes = []
4155 filenodes = []
4156 for cp in ctx.parents():
4156 for cp in ctx.parents():
4157 if not cp:
4157 if not cp:
4158 continue
4158 continue
4159 try:
4159 try:
4160 filenodes.append(cp.filenode(file_))
4160 filenodes.append(cp.filenode(file_))
4161 except error.LookupError:
4161 except error.LookupError:
4162 pass
4162 pass
4163 if not filenodes:
4163 if not filenodes:
4164 raise util.Abort(_("'%s' not found in manifest!") % file_)
4164 raise util.Abort(_("'%s' not found in manifest!") % file_)
4165 fl = repo.file(file_)
4165 fl = repo.file(file_)
4166 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4166 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4167 else:
4167 else:
4168 p = [cp.node() for cp in ctx.parents()]
4168 p = [cp.node() for cp in ctx.parents()]
4169
4169
4170 displayer = cmdutil.show_changeset(ui, repo, opts)
4170 displayer = cmdutil.show_changeset(ui, repo, opts)
4171 for n in p:
4171 for n in p:
4172 if n != nullid:
4172 if n != nullid:
4173 displayer.show(repo[n])
4173 displayer.show(repo[n])
4174 displayer.close()
4174 displayer.close()
4175
4175
4176 @command('paths', [], _('[NAME]'))
4176 @command('paths', [], _('[NAME]'))
4177 def paths(ui, repo, search=None):
4177 def paths(ui, repo, search=None):
4178 """show aliases for remote repositories
4178 """show aliases for remote repositories
4179
4179
4180 Show definition of symbolic path name NAME. If no name is given,
4180 Show definition of symbolic path name NAME. If no name is given,
4181 show definition of all available names.
4181 show definition of all available names.
4182
4182
4183 Option -q/--quiet suppresses all output when searching for NAME
4183 Option -q/--quiet suppresses all output when searching for NAME
4184 and shows only the path names when listing all definitions.
4184 and shows only the path names when listing all definitions.
4185
4185
4186 Path names are defined in the [paths] section of your
4186 Path names are defined in the [paths] section of your
4187 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4187 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4188 repository, ``.hg/hgrc`` is used, too.
4188 repository, ``.hg/hgrc`` is used, too.
4189
4189
4190 The path names ``default`` and ``default-push`` have a special
4190 The path names ``default`` and ``default-push`` have a special
4191 meaning. When performing a push or pull operation, they are used
4191 meaning. When performing a push or pull operation, they are used
4192 as fallbacks if no location is specified on the command-line.
4192 as fallbacks if no location is specified on the command-line.
4193 When ``default-push`` is set, it will be used for push and
4193 When ``default-push`` is set, it will be used for push and
4194 ``default`` will be used for pull; otherwise ``default`` is used
4194 ``default`` will be used for pull; otherwise ``default`` is used
4195 as the fallback for both. When cloning a repository, the clone
4195 as the fallback for both. When cloning a repository, the clone
4196 source is written as ``default`` in ``.hg/hgrc``. Note that
4196 source is written as ``default`` in ``.hg/hgrc``. Note that
4197 ``default`` and ``default-push`` apply to all inbound (e.g.
4197 ``default`` and ``default-push`` apply to all inbound (e.g.
4198 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4198 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4199 :hg:`bundle`) operations.
4199 :hg:`bundle`) operations.
4200
4200
4201 See :hg:`help urls` for more information.
4201 See :hg:`help urls` for more information.
4202
4202
4203 Returns 0 on success.
4203 Returns 0 on success.
4204 """
4204 """
4205 if search:
4205 if search:
4206 for name, path in ui.configitems("paths"):
4206 for name, path in ui.configitems("paths"):
4207 if name == search:
4207 if name == search:
4208 ui.status("%s\n" % util.hidepassword(path))
4208 ui.status("%s\n" % util.hidepassword(path))
4209 return
4209 return
4210 if not ui.quiet:
4210 if not ui.quiet:
4211 ui.warn(_("not found!\n"))
4211 ui.warn(_("not found!\n"))
4212 return 1
4212 return 1
4213 else:
4213 else:
4214 for name, path in ui.configitems("paths"):
4214 for name, path in ui.configitems("paths"):
4215 if ui.quiet:
4215 if ui.quiet:
4216 ui.write("%s\n" % name)
4216 ui.write("%s\n" % name)
4217 else:
4217 else:
4218 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4218 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4219
4219
4220 @command('^phase',
4220 @command('^phase',
4221 [('p', 'public', False, _('set changeset phase to public')),
4221 [('p', 'public', False, _('set changeset phase to public')),
4222 ('d', 'draft', False, _('set changeset phase to draft')),
4222 ('d', 'draft', False, _('set changeset phase to draft')),
4223 ('s', 'secret', False, _('set changeset phase to secret')),
4223 ('s', 'secret', False, _('set changeset phase to secret')),
4224 ('f', 'force', False, _('allow to move boundary backward')),
4224 ('f', 'force', False, _('allow to move boundary backward')),
4225 ('r', 'rev', [], _('target revision'), _('REV')),
4225 ('r', 'rev', [], _('target revision'), _('REV')),
4226 ],
4226 ],
4227 _('[-p|-d|-s] [-f] [-r] REV...'))
4227 _('[-p|-d|-s] [-f] [-r] REV...'))
4228 def phase(ui, repo, *revs, **opts):
4228 def phase(ui, repo, *revs, **opts):
4229 """set or show the current phase name
4229 """set or show the current phase name
4230
4230
4231 With no argument, show the phase name of specified revisions.
4231 With no argument, show the phase name of specified revisions.
4232
4232
4233 With one of -p/--public, -d/--draft or -s/--secret, change the
4233 With one of -p/--public, -d/--draft or -s/--secret, change the
4234 phase value of the specified revisions.
4234 phase value of the specified revisions.
4235
4235
4236 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4236 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4237 lower phase to an higher phase. Phases are ordered as follows::
4237 lower phase to an higher phase. Phases are ordered as follows::
4238
4238
4239 public < draft < secret
4239 public < draft < secret
4240 """
4240 """
4241 # search for a unique phase argument
4241 # search for a unique phase argument
4242 targetphase = None
4242 targetphase = None
4243 for idx, name in enumerate(phases.phasenames):
4243 for idx, name in enumerate(phases.phasenames):
4244 if opts[name]:
4244 if opts[name]:
4245 if targetphase is not None:
4245 if targetphase is not None:
4246 raise util.Abort(_('only one phase can be specified'))
4246 raise util.Abort(_('only one phase can be specified'))
4247 targetphase = idx
4247 targetphase = idx
4248
4248
4249 # look for specified revision
4249 # look for specified revision
4250 revs = list(revs)
4250 revs = list(revs)
4251 revs.extend(opts['rev'])
4251 revs.extend(opts['rev'])
4252 if not revs:
4252 if not revs:
4253 raise util.Abort(_('no revisions specified!'))
4253 raise util.Abort(_('no revisions specified!'))
4254
4254
4255 lock = None
4255 lock = None
4256 if targetphase is None:
4256 if targetphase is None:
4257 # display
4257 # display
4258 for ctx in repo.set('%lr', revs):
4258 for ctx in repo.set('%lr', revs):
4259 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4259 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4260 else:
4260 else:
4261 lock = repo.lock()
4261 lock = repo.lock()
4262 try:
4262 try:
4263 # set phase
4263 # set phase
4264 nodes = [ctx.node() for ctx in repo.set('%lr', revs)]
4264 nodes = [ctx.node() for ctx in repo.set('%lr', revs)]
4265 if not nodes:
4265 if not nodes:
4266 raise util.Abort(_('empty revision set'))
4266 raise util.Abort(_('empty revision set'))
4267 phases.advanceboundary(repo, targetphase, nodes)
4267 phases.advanceboundary(repo, targetphase, nodes)
4268 if opts['force']:
4268 if opts['force']:
4269 phases.retractboundary(repo, targetphase, nodes)
4269 phases.retractboundary(repo, targetphase, nodes)
4270 finally:
4270 finally:
4271 lock.release()
4271 lock.release()
4272
4272
4273 def postincoming(ui, repo, modheads, optupdate, checkout):
4273 def postincoming(ui, repo, modheads, optupdate, checkout):
4274 if modheads == 0:
4274 if modheads == 0:
4275 return
4275 return
4276 if optupdate:
4276 if optupdate:
4277 try:
4277 try:
4278 return hg.update(repo, checkout)
4278 return hg.update(repo, checkout)
4279 except util.Abort, inst:
4279 except util.Abort, inst:
4280 ui.warn(_("not updating: %s\n" % str(inst)))
4280 ui.warn(_("not updating: %s\n" % str(inst)))
4281 return 0
4281 return 0
4282 if modheads > 1:
4282 if modheads > 1:
4283 currentbranchheads = len(repo.branchheads())
4283 currentbranchheads = len(repo.branchheads())
4284 if currentbranchheads == modheads:
4284 if currentbranchheads == modheads:
4285 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4285 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4286 elif currentbranchheads > 1:
4286 elif currentbranchheads > 1:
4287 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4287 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4288 else:
4288 else:
4289 ui.status(_("(run 'hg heads' to see heads)\n"))
4289 ui.status(_("(run 'hg heads' to see heads)\n"))
4290 else:
4290 else:
4291 ui.status(_("(run 'hg update' to get a working copy)\n"))
4291 ui.status(_("(run 'hg update' to get a working copy)\n"))
4292
4292
4293 @command('^pull',
4293 @command('^pull',
4294 [('u', 'update', None,
4294 [('u', 'update', None,
4295 _('update to new branch head if changesets were pulled')),
4295 _('update to new branch head if changesets were pulled')),
4296 ('f', 'force', None, _('run even when remote repository is unrelated')),
4296 ('f', 'force', None, _('run even when remote repository is unrelated')),
4297 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4297 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4298 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4298 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4299 ('b', 'branch', [], _('a specific branch you would like to pull'),
4299 ('b', 'branch', [], _('a specific branch you would like to pull'),
4300 _('BRANCH')),
4300 _('BRANCH')),
4301 ] + remoteopts,
4301 ] + remoteopts,
4302 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4302 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4303 def pull(ui, repo, source="default", **opts):
4303 def pull(ui, repo, source="default", **opts):
4304 """pull changes from the specified source
4304 """pull changes from the specified source
4305
4305
4306 Pull changes from a remote repository to a local one.
4306 Pull changes from a remote repository to a local one.
4307
4307
4308 This finds all changes from the repository at the specified path
4308 This finds all changes from the repository at the specified path
4309 or URL and adds them to a local repository (the current one unless
4309 or URL and adds them to a local repository (the current one unless
4310 -R is specified). By default, this does not update the copy of the
4310 -R is specified). By default, this does not update the copy of the
4311 project in the working directory.
4311 project in the working directory.
4312
4312
4313 Use :hg:`incoming` if you want to see what would have been added
4313 Use :hg:`incoming` if you want to see what would have been added
4314 by a pull at the time you issued this command. If you then decide
4314 by a pull at the time you issued this command. If you then decide
4315 to add those changes to the repository, you should use :hg:`pull
4315 to add those changes to the repository, you should use :hg:`pull
4316 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4316 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4317
4317
4318 If SOURCE is omitted, the 'default' path will be used.
4318 If SOURCE is omitted, the 'default' path will be used.
4319 See :hg:`help urls` for more information.
4319 See :hg:`help urls` for more information.
4320
4320
4321 Returns 0 on success, 1 if an update had unresolved files.
4321 Returns 0 on success, 1 if an update had unresolved files.
4322 """
4322 """
4323 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4323 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4324 other = hg.peer(repo, opts, source)
4324 other = hg.peer(repo, opts, source)
4325 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4325 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4326 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4326 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4327
4327
4328 if opts.get('bookmark'):
4328 if opts.get('bookmark'):
4329 if not revs:
4329 if not revs:
4330 revs = []
4330 revs = []
4331 rb = other.listkeys('bookmarks')
4331 rb = other.listkeys('bookmarks')
4332 for b in opts['bookmark']:
4332 for b in opts['bookmark']:
4333 if b not in rb:
4333 if b not in rb:
4334 raise util.Abort(_('remote bookmark %s not found!') % b)
4334 raise util.Abort(_('remote bookmark %s not found!') % b)
4335 revs.append(rb[b])
4335 revs.append(rb[b])
4336
4336
4337 if revs:
4337 if revs:
4338 try:
4338 try:
4339 revs = [other.lookup(rev) for rev in revs]
4339 revs = [other.lookup(rev) for rev in revs]
4340 except error.CapabilityError:
4340 except error.CapabilityError:
4341 err = _("other repository doesn't support revision lookup, "
4341 err = _("other repository doesn't support revision lookup, "
4342 "so a rev cannot be specified.")
4342 "so a rev cannot be specified.")
4343 raise util.Abort(err)
4343 raise util.Abort(err)
4344
4344
4345 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4345 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4346 bookmarks.updatefromremote(ui, repo, other, source)
4346 bookmarks.updatefromremote(ui, repo, other, source)
4347 if checkout:
4347 if checkout:
4348 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4348 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4349 repo._subtoppath = source
4349 repo._subtoppath = source
4350 try:
4350 try:
4351 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4351 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4352
4352
4353 finally:
4353 finally:
4354 del repo._subtoppath
4354 del repo._subtoppath
4355
4355
4356 # update specified bookmarks
4356 # update specified bookmarks
4357 if opts.get('bookmark'):
4357 if opts.get('bookmark'):
4358 for b in opts['bookmark']:
4358 for b in opts['bookmark']:
4359 # explicit pull overrides local bookmark if any
4359 # explicit pull overrides local bookmark if any
4360 ui.status(_("importing bookmark %s\n") % b)
4360 ui.status(_("importing bookmark %s\n") % b)
4361 repo._bookmarks[b] = repo[rb[b]].node()
4361 repo._bookmarks[b] = repo[rb[b]].node()
4362 bookmarks.write(repo)
4362 bookmarks.write(repo)
4363
4363
4364 return ret
4364 return ret
4365
4365
4366 @command('^push',
4366 @command('^push',
4367 [('f', 'force', None, _('force push')),
4367 [('f', 'force', None, _('force push')),
4368 ('r', 'rev', [],
4368 ('r', 'rev', [],
4369 _('a changeset intended to be included in the destination'),
4369 _('a changeset intended to be included in the destination'),
4370 _('REV')),
4370 _('REV')),
4371 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4371 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4372 ('b', 'branch', [],
4372 ('b', 'branch', [],
4373 _('a specific branch you would like to push'), _('BRANCH')),
4373 _('a specific branch you would like to push'), _('BRANCH')),
4374 ('', 'new-branch', False, _('allow pushing a new branch')),
4374 ('', 'new-branch', False, _('allow pushing a new branch')),
4375 ] + remoteopts,
4375 ] + remoteopts,
4376 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4376 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4377 def push(ui, repo, dest=None, **opts):
4377 def push(ui, repo, dest=None, **opts):
4378 """push changes to the specified destination
4378 """push changes to the specified destination
4379
4379
4380 Push changesets from the local repository to the specified
4380 Push changesets from the local repository to the specified
4381 destination.
4381 destination.
4382
4382
4383 This operation is symmetrical to pull: it is identical to a pull
4383 This operation is symmetrical to pull: it is identical to a pull
4384 in the destination repository from the current one.
4384 in the destination repository from the current one.
4385
4385
4386 By default, push will not allow creation of new heads at the
4386 By default, push will not allow creation of new heads at the
4387 destination, since multiple heads would make it unclear which head
4387 destination, since multiple heads would make it unclear which head
4388 to use. In this situation, it is recommended to pull and merge
4388 to use. In this situation, it is recommended to pull and merge
4389 before pushing.
4389 before pushing.
4390
4390
4391 Use --new-branch if you want to allow push to create a new named
4391 Use --new-branch if you want to allow push to create a new named
4392 branch that is not present at the destination. This allows you to
4392 branch that is not present at the destination. This allows you to
4393 only create a new branch without forcing other changes.
4393 only create a new branch without forcing other changes.
4394
4394
4395 Use -f/--force to override the default behavior and push all
4395 Use -f/--force to override the default behavior and push all
4396 changesets on all branches.
4396 changesets on all branches.
4397
4397
4398 If -r/--rev is used, the specified revision and all its ancestors
4398 If -r/--rev is used, the specified revision and all its ancestors
4399 will be pushed to the remote repository.
4399 will be pushed to the remote repository.
4400
4400
4401 Please see :hg:`help urls` for important details about ``ssh://``
4401 Please see :hg:`help urls` for important details about ``ssh://``
4402 URLs. If DESTINATION is omitted, a default path will be used.
4402 URLs. If DESTINATION is omitted, a default path will be used.
4403
4403
4404 Returns 0 if push was successful, 1 if nothing to push.
4404 Returns 0 if push was successful, 1 if nothing to push.
4405 """
4405 """
4406
4406
4407 if opts.get('bookmark'):
4407 if opts.get('bookmark'):
4408 for b in opts['bookmark']:
4408 for b in opts['bookmark']:
4409 # translate -B options to -r so changesets get pushed
4409 # translate -B options to -r so changesets get pushed
4410 if b in repo._bookmarks:
4410 if b in repo._bookmarks:
4411 opts.setdefault('rev', []).append(b)
4411 opts.setdefault('rev', []).append(b)
4412 else:
4412 else:
4413 # if we try to push a deleted bookmark, translate it to null
4413 # if we try to push a deleted bookmark, translate it to null
4414 # this lets simultaneous -r, -b options continue working
4414 # this lets simultaneous -r, -b options continue working
4415 opts.setdefault('rev', []).append("null")
4415 opts.setdefault('rev', []).append("null")
4416
4416
4417 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4417 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4418 dest, branches = hg.parseurl(dest, opts.get('branch'))
4418 dest, branches = hg.parseurl(dest, opts.get('branch'))
4419 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4419 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4420 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4420 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4421 other = hg.peer(repo, opts, dest)
4421 other = hg.peer(repo, opts, dest)
4422 if revs:
4422 if revs:
4423 revs = [repo.lookup(rev) for rev in revs]
4423 revs = [repo.lookup(rev) for rev in revs]
4424
4424
4425 repo._subtoppath = dest
4425 repo._subtoppath = dest
4426 try:
4426 try:
4427 # push subrepos depth-first for coherent ordering
4427 # push subrepos depth-first for coherent ordering
4428 c = repo['']
4428 c = repo['']
4429 subs = c.substate # only repos that are committed
4429 subs = c.substate # only repos that are committed
4430 for s in sorted(subs):
4430 for s in sorted(subs):
4431 if not c.sub(s).push(opts):
4431 if not c.sub(s).push(opts):
4432 return False
4432 return False
4433 finally:
4433 finally:
4434 del repo._subtoppath
4434 del repo._subtoppath
4435 result = repo.push(other, opts.get('force'), revs=revs,
4435 result = repo.push(other, opts.get('force'), revs=revs,
4436 newbranch=opts.get('new_branch'))
4436 newbranch=opts.get('new_branch'))
4437
4437
4438 result = (result == 0)
4438 result = (result == 0)
4439
4439
4440 if opts.get('bookmark'):
4440 if opts.get('bookmark'):
4441 rb = other.listkeys('bookmarks')
4441 rb = other.listkeys('bookmarks')
4442 for b in opts['bookmark']:
4442 for b in opts['bookmark']:
4443 # explicit push overrides remote bookmark if any
4443 # explicit push overrides remote bookmark if any
4444 if b in repo._bookmarks:
4444 if b in repo._bookmarks:
4445 ui.status(_("exporting bookmark %s\n") % b)
4445 ui.status(_("exporting bookmark %s\n") % b)
4446 new = repo[b].hex()
4446 new = repo[b].hex()
4447 elif b in rb:
4447 elif b in rb:
4448 ui.status(_("deleting remote bookmark %s\n") % b)
4448 ui.status(_("deleting remote bookmark %s\n") % b)
4449 new = '' # delete
4449 new = '' # delete
4450 else:
4450 else:
4451 ui.warn(_('bookmark %s does not exist on the local '
4451 ui.warn(_('bookmark %s does not exist on the local '
4452 'or remote repository!\n') % b)
4452 'or remote repository!\n') % b)
4453 return 2
4453 return 2
4454 old = rb.get(b, '')
4454 old = rb.get(b, '')
4455 r = other.pushkey('bookmarks', b, old, new)
4455 r = other.pushkey('bookmarks', b, old, new)
4456 if not r:
4456 if not r:
4457 ui.warn(_('updating bookmark %s failed!\n') % b)
4457 ui.warn(_('updating bookmark %s failed!\n') % b)
4458 if not result:
4458 if not result:
4459 result = 2
4459 result = 2
4460
4460
4461 return result
4461 return result
4462
4462
4463 @command('recover', [])
4463 @command('recover', [])
4464 def recover(ui, repo):
4464 def recover(ui, repo):
4465 """roll back an interrupted transaction
4465 """roll back an interrupted transaction
4466
4466
4467 Recover from an interrupted commit or pull.
4467 Recover from an interrupted commit or pull.
4468
4468
4469 This command tries to fix the repository status after an
4469 This command tries to fix the repository status after an
4470 interrupted operation. It should only be necessary when Mercurial
4470 interrupted operation. It should only be necessary when Mercurial
4471 suggests it.
4471 suggests it.
4472
4472
4473 Returns 0 if successful, 1 if nothing to recover or verify fails.
4473 Returns 0 if successful, 1 if nothing to recover or verify fails.
4474 """
4474 """
4475 if repo.recover():
4475 if repo.recover():
4476 return hg.verify(repo)
4476 return hg.verify(repo)
4477 return 1
4477 return 1
4478
4478
4479 @command('^remove|rm',
4479 @command('^remove|rm',
4480 [('A', 'after', None, _('record delete for missing files')),
4480 [('A', 'after', None, _('record delete for missing files')),
4481 ('f', 'force', None,
4481 ('f', 'force', None,
4482 _('remove (and delete) file even if added or modified')),
4482 _('remove (and delete) file even if added or modified')),
4483 ] + walkopts,
4483 ] + walkopts,
4484 _('[OPTION]... FILE...'))
4484 _('[OPTION]... FILE...'))
4485 def remove(ui, repo, *pats, **opts):
4485 def remove(ui, repo, *pats, **opts):
4486 """remove the specified files on the next commit
4486 """remove the specified files on the next commit
4487
4487
4488 Schedule the indicated files for removal from the current branch.
4488 Schedule the indicated files for removal from the current branch.
4489
4489
4490 This command schedules the files to be removed at the next commit.
4490 This command schedules the files to be removed at the next commit.
4491 To undo a remove before that, see :hg:`revert`. To undo added
4491 To undo a remove before that, see :hg:`revert`. To undo added
4492 files, see :hg:`forget`.
4492 files, see :hg:`forget`.
4493
4493
4494 .. container:: verbose
4494 .. container:: verbose
4495
4495
4496 -A/--after can be used to remove only files that have already
4496 -A/--after can be used to remove only files that have already
4497 been deleted, -f/--force can be used to force deletion, and -Af
4497 been deleted, -f/--force can be used to force deletion, and -Af
4498 can be used to remove files from the next revision without
4498 can be used to remove files from the next revision without
4499 deleting them from the working directory.
4499 deleting them from the working directory.
4500
4500
4501 The following table details the behavior of remove for different
4501 The following table details the behavior of remove for different
4502 file states (columns) and option combinations (rows). The file
4502 file states (columns) and option combinations (rows). The file
4503 states are Added [A], Clean [C], Modified [M] and Missing [!]
4503 states are Added [A], Clean [C], Modified [M] and Missing [!]
4504 (as reported by :hg:`status`). The actions are Warn, Remove
4504 (as reported by :hg:`status`). The actions are Warn, Remove
4505 (from branch) and Delete (from disk):
4505 (from branch) and Delete (from disk):
4506
4506
4507 ======= == == == ==
4507 ======= == == == ==
4508 A C M !
4508 A C M !
4509 ======= == == == ==
4509 ======= == == == ==
4510 none W RD W R
4510 none W RD W R
4511 -f R RD RD R
4511 -f R RD RD R
4512 -A W W W R
4512 -A W W W R
4513 -Af R R R R
4513 -Af R R R R
4514 ======= == == == ==
4514 ======= == == == ==
4515
4515
4516 Note that remove never deletes files in Added [A] state from the
4516 Note that remove never deletes files in Added [A] state from the
4517 working directory, not even if option --force is specified.
4517 working directory, not even if option --force is specified.
4518
4518
4519 Returns 0 on success, 1 if any warnings encountered.
4519 Returns 0 on success, 1 if any warnings encountered.
4520 """
4520 """
4521
4521
4522 ret = 0
4522 ret = 0
4523 after, force = opts.get('after'), opts.get('force')
4523 after, force = opts.get('after'), opts.get('force')
4524 if not pats and not after:
4524 if not pats and not after:
4525 raise util.Abort(_('no files specified'))
4525 raise util.Abort(_('no files specified'))
4526
4526
4527 m = scmutil.match(repo[None], pats, opts)
4527 m = scmutil.match(repo[None], pats, opts)
4528 s = repo.status(match=m, clean=True)
4528 s = repo.status(match=m, clean=True)
4529 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4529 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4530
4530
4531 for f in m.files():
4531 for f in m.files():
4532 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4532 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4533 if os.path.exists(m.rel(f)):
4533 if os.path.exists(m.rel(f)):
4534 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4534 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4535 ret = 1
4535 ret = 1
4536
4536
4537 if force:
4537 if force:
4538 list = modified + deleted + clean + added
4538 list = modified + deleted + clean + added
4539 elif after:
4539 elif after:
4540 list = deleted
4540 list = deleted
4541 for f in modified + added + clean:
4541 for f in modified + added + clean:
4542 ui.warn(_('not removing %s: file still exists (use -f'
4542 ui.warn(_('not removing %s: file still exists (use -f'
4543 ' to force removal)\n') % m.rel(f))
4543 ' to force removal)\n') % m.rel(f))
4544 ret = 1
4544 ret = 1
4545 else:
4545 else:
4546 list = deleted + clean
4546 list = deleted + clean
4547 for f in modified:
4547 for f in modified:
4548 ui.warn(_('not removing %s: file is modified (use -f'
4548 ui.warn(_('not removing %s: file is modified (use -f'
4549 ' to force removal)\n') % m.rel(f))
4549 ' to force removal)\n') % m.rel(f))
4550 ret = 1
4550 ret = 1
4551 for f in added:
4551 for f in added:
4552 ui.warn(_('not removing %s: file has been marked for add'
4552 ui.warn(_('not removing %s: file has been marked for add'
4553 ' (use forget to undo)\n') % m.rel(f))
4553 ' (use forget to undo)\n') % m.rel(f))
4554 ret = 1
4554 ret = 1
4555
4555
4556 for f in sorted(list):
4556 for f in sorted(list):
4557 if ui.verbose or not m.exact(f):
4557 if ui.verbose or not m.exact(f):
4558 ui.status(_('removing %s\n') % m.rel(f))
4558 ui.status(_('removing %s\n') % m.rel(f))
4559
4559
4560 wlock = repo.wlock()
4560 wlock = repo.wlock()
4561 try:
4561 try:
4562 if not after:
4562 if not after:
4563 for f in list:
4563 for f in list:
4564 if f in added:
4564 if f in added:
4565 continue # we never unlink added files on remove
4565 continue # we never unlink added files on remove
4566 try:
4566 try:
4567 util.unlinkpath(repo.wjoin(f))
4567 util.unlinkpath(repo.wjoin(f))
4568 except OSError, inst:
4568 except OSError, inst:
4569 if inst.errno != errno.ENOENT:
4569 if inst.errno != errno.ENOENT:
4570 raise
4570 raise
4571 repo[None].forget(list)
4571 repo[None].forget(list)
4572 finally:
4572 finally:
4573 wlock.release()
4573 wlock.release()
4574
4574
4575 return ret
4575 return ret
4576
4576
4577 @command('rename|move|mv',
4577 @command('rename|move|mv',
4578 [('A', 'after', None, _('record a rename that has already occurred')),
4578 [('A', 'after', None, _('record a rename that has already occurred')),
4579 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4579 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4580 ] + walkopts + dryrunopts,
4580 ] + walkopts + dryrunopts,
4581 _('[OPTION]... SOURCE... DEST'))
4581 _('[OPTION]... SOURCE... DEST'))
4582 def rename(ui, repo, *pats, **opts):
4582 def rename(ui, repo, *pats, **opts):
4583 """rename files; equivalent of copy + remove
4583 """rename files; equivalent of copy + remove
4584
4584
4585 Mark dest as copies of sources; mark sources for deletion. If dest
4585 Mark dest as copies of sources; mark sources for deletion. If dest
4586 is a directory, copies are put in that directory. If dest is a
4586 is a directory, copies are put in that directory. If dest is a
4587 file, there can only be one source.
4587 file, there can only be one source.
4588
4588
4589 By default, this command copies the contents of files as they
4589 By default, this command copies the contents of files as they
4590 exist in the working directory. If invoked with -A/--after, the
4590 exist in the working directory. If invoked with -A/--after, the
4591 operation is recorded, but no copying is performed.
4591 operation is recorded, but no copying is performed.
4592
4592
4593 This command takes effect at the next commit. To undo a rename
4593 This command takes effect at the next commit. To undo a rename
4594 before that, see :hg:`revert`.
4594 before that, see :hg:`revert`.
4595
4595
4596 Returns 0 on success, 1 if errors are encountered.
4596 Returns 0 on success, 1 if errors are encountered.
4597 """
4597 """
4598 wlock = repo.wlock(False)
4598 wlock = repo.wlock(False)
4599 try:
4599 try:
4600 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4600 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4601 finally:
4601 finally:
4602 wlock.release()
4602 wlock.release()
4603
4603
4604 @command('resolve',
4604 @command('resolve',
4605 [('a', 'all', None, _('select all unresolved files')),
4605 [('a', 'all', None, _('select all unresolved files')),
4606 ('l', 'list', None, _('list state of files needing merge')),
4606 ('l', 'list', None, _('list state of files needing merge')),
4607 ('m', 'mark', None, _('mark files as resolved')),
4607 ('m', 'mark', None, _('mark files as resolved')),
4608 ('u', 'unmark', None, _('mark files as unresolved')),
4608 ('u', 'unmark', None, _('mark files as unresolved')),
4609 ('n', 'no-status', None, _('hide status prefix'))]
4609 ('n', 'no-status', None, _('hide status prefix'))]
4610 + mergetoolopts + walkopts,
4610 + mergetoolopts + walkopts,
4611 _('[OPTION]... [FILE]...'))
4611 _('[OPTION]... [FILE]...'))
4612 def resolve(ui, repo, *pats, **opts):
4612 def resolve(ui, repo, *pats, **opts):
4613 """redo merges or set/view the merge status of files
4613 """redo merges or set/view the merge status of files
4614
4614
4615 Merges with unresolved conflicts are often the result of
4615 Merges with unresolved conflicts are often the result of
4616 non-interactive merging using the ``internal:merge`` configuration
4616 non-interactive merging using the ``internal:merge`` configuration
4617 setting, or a command-line merge tool like ``diff3``. The resolve
4617 setting, or a command-line merge tool like ``diff3``. The resolve
4618 command is used to manage the files involved in a merge, after
4618 command is used to manage the files involved in a merge, after
4619 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4619 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4620 working directory must have two parents).
4620 working directory must have two parents).
4621
4621
4622 The resolve command can be used in the following ways:
4622 The resolve command can be used in the following ways:
4623
4623
4624 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4624 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4625 files, discarding any previous merge attempts. Re-merging is not
4625 files, discarding any previous merge attempts. Re-merging is not
4626 performed for files already marked as resolved. Use ``--all/-a``
4626 performed for files already marked as resolved. Use ``--all/-a``
4627 to select all unresolved files. ``--tool`` can be used to specify
4627 to select all unresolved files. ``--tool`` can be used to specify
4628 the merge tool used for the given files. It overrides the HGMERGE
4628 the merge tool used for the given files. It overrides the HGMERGE
4629 environment variable and your configuration files. Previous file
4629 environment variable and your configuration files. Previous file
4630 contents are saved with a ``.orig`` suffix.
4630 contents are saved with a ``.orig`` suffix.
4631
4631
4632 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4632 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4633 (e.g. after having manually fixed-up the files). The default is
4633 (e.g. after having manually fixed-up the files). The default is
4634 to mark all unresolved files.
4634 to mark all unresolved files.
4635
4635
4636 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4636 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4637 default is to mark all resolved files.
4637 default is to mark all resolved files.
4638
4638
4639 - :hg:`resolve -l`: list files which had or still have conflicts.
4639 - :hg:`resolve -l`: list files which had or still have conflicts.
4640 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4640 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4641
4641
4642 Note that Mercurial will not let you commit files with unresolved
4642 Note that Mercurial will not let you commit files with unresolved
4643 merge conflicts. You must use :hg:`resolve -m ...` before you can
4643 merge conflicts. You must use :hg:`resolve -m ...` before you can
4644 commit after a conflicting merge.
4644 commit after a conflicting merge.
4645
4645
4646 Returns 0 on success, 1 if any files fail a resolve attempt.
4646 Returns 0 on success, 1 if any files fail a resolve attempt.
4647 """
4647 """
4648
4648
4649 all, mark, unmark, show, nostatus = \
4649 all, mark, unmark, show, nostatus = \
4650 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4650 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4651
4651
4652 if (show and (mark or unmark)) or (mark and unmark):
4652 if (show and (mark or unmark)) or (mark and unmark):
4653 raise util.Abort(_("too many options specified"))
4653 raise util.Abort(_("too many options specified"))
4654 if pats and all:
4654 if pats and all:
4655 raise util.Abort(_("can't specify --all and patterns"))
4655 raise util.Abort(_("can't specify --all and patterns"))
4656 if not (all or pats or show or mark or unmark):
4656 if not (all or pats or show or mark or unmark):
4657 raise util.Abort(_('no files or directories specified; '
4657 raise util.Abort(_('no files or directories specified; '
4658 'use --all to remerge all files'))
4658 'use --all to remerge all files'))
4659
4659
4660 ms = mergemod.mergestate(repo)
4660 ms = mergemod.mergestate(repo)
4661 m = scmutil.match(repo[None], pats, opts)
4661 m = scmutil.match(repo[None], pats, opts)
4662 ret = 0
4662 ret = 0
4663
4663
4664 for f in ms:
4664 for f in ms:
4665 if m(f):
4665 if m(f):
4666 if show:
4666 if show:
4667 if nostatus:
4667 if nostatus:
4668 ui.write("%s\n" % f)
4668 ui.write("%s\n" % f)
4669 else:
4669 else:
4670 ui.write("%s %s\n" % (ms[f].upper(), f),
4670 ui.write("%s %s\n" % (ms[f].upper(), f),
4671 label='resolve.' +
4671 label='resolve.' +
4672 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4672 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4673 elif mark:
4673 elif mark:
4674 ms.mark(f, "r")
4674 ms.mark(f, "r")
4675 elif unmark:
4675 elif unmark:
4676 ms.mark(f, "u")
4676 ms.mark(f, "u")
4677 else:
4677 else:
4678 wctx = repo[None]
4678 wctx = repo[None]
4679 mctx = wctx.parents()[-1]
4679 mctx = wctx.parents()[-1]
4680
4680
4681 # backup pre-resolve (merge uses .orig for its own purposes)
4681 # backup pre-resolve (merge uses .orig for its own purposes)
4682 a = repo.wjoin(f)
4682 a = repo.wjoin(f)
4683 util.copyfile(a, a + ".resolve")
4683 util.copyfile(a, a + ".resolve")
4684
4684
4685 try:
4685 try:
4686 # resolve file
4686 # resolve file
4687 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4687 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4688 if ms.resolve(f, wctx, mctx):
4688 if ms.resolve(f, wctx, mctx):
4689 ret = 1
4689 ret = 1
4690 finally:
4690 finally:
4691 ui.setconfig('ui', 'forcemerge', '')
4691 ui.setconfig('ui', 'forcemerge', '')
4692
4692
4693 # replace filemerge's .orig file with our resolve file
4693 # replace filemerge's .orig file with our resolve file
4694 util.rename(a + ".resolve", a + ".orig")
4694 util.rename(a + ".resolve", a + ".orig")
4695
4695
4696 ms.commit()
4696 ms.commit()
4697 return ret
4697 return ret
4698
4698
4699 @command('revert',
4699 @command('revert',
4700 [('a', 'all', None, _('revert all changes when no arguments given')),
4700 [('a', 'all', None, _('revert all changes when no arguments given')),
4701 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4701 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4702 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4702 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4703 ('C', 'no-backup', None, _('do not save backup copies of files')),
4703 ('C', 'no-backup', None, _('do not save backup copies of files')),
4704 ] + walkopts + dryrunopts,
4704 ] + walkopts + dryrunopts,
4705 _('[OPTION]... [-r REV] [NAME]...'))
4705 _('[OPTION]... [-r REV] [NAME]...'))
4706 def revert(ui, repo, *pats, **opts):
4706 def revert(ui, repo, *pats, **opts):
4707 """restore files to their checkout state
4707 """restore files to their checkout state
4708
4708
4709 .. note::
4709 .. note::
4710 To check out earlier revisions, you should use :hg:`update REV`.
4710 To check out earlier revisions, you should use :hg:`update REV`.
4711 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4711 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4712
4712
4713 With no revision specified, revert the specified files or directories
4713 With no revision specified, revert the specified files or directories
4714 to the contents they had in the parent of the working directory.
4714 to the contents they had in the parent of the working directory.
4715 This restores the contents of files to an unmodified
4715 This restores the contents of files to an unmodified
4716 state and unschedules adds, removes, copies, and renames. If the
4716 state and unschedules adds, removes, copies, and renames. If the
4717 working directory has two parents, you must explicitly specify a
4717 working directory has two parents, you must explicitly specify a
4718 revision.
4718 revision.
4719
4719
4720 Using the -r/--rev or -d/--date options, revert the given files or
4720 Using the -r/--rev or -d/--date options, revert the given files or
4721 directories to their states as of a specific revision. Because
4721 directories to their states as of a specific revision. Because
4722 revert does not change the working directory parents, this will
4722 revert does not change the working directory parents, this will
4723 cause these files to appear modified. This can be helpful to "back
4723 cause these files to appear modified. This can be helpful to "back
4724 out" some or all of an earlier change. See :hg:`backout` for a
4724 out" some or all of an earlier change. See :hg:`backout` for a
4725 related method.
4725 related method.
4726
4726
4727 Modified files are saved with a .orig suffix before reverting.
4727 Modified files are saved with a .orig suffix before reverting.
4728 To disable these backups, use --no-backup.
4728 To disable these backups, use --no-backup.
4729
4729
4730 See :hg:`help dates` for a list of formats valid for -d/--date.
4730 See :hg:`help dates` for a list of formats valid for -d/--date.
4731
4731
4732 Returns 0 on success.
4732 Returns 0 on success.
4733 """
4733 """
4734
4734
4735 if opts.get("date"):
4735 if opts.get("date"):
4736 if opts.get("rev"):
4736 if opts.get("rev"):
4737 raise util.Abort(_("you can't specify a revision and a date"))
4737 raise util.Abort(_("you can't specify a revision and a date"))
4738 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4738 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4739
4739
4740 parent, p2 = repo.dirstate.parents()
4740 parent, p2 = repo.dirstate.parents()
4741 if not opts.get('rev') and p2 != nullid:
4741 if not opts.get('rev') and p2 != nullid:
4742 # revert after merge is a trap for new users (issue2915)
4742 # revert after merge is a trap for new users (issue2915)
4743 raise util.Abort(_('uncommitted merge with no revision specified'),
4743 raise util.Abort(_('uncommitted merge with no revision specified'),
4744 hint=_('use "hg update" or see "hg help revert"'))
4744 hint=_('use "hg update" or see "hg help revert"'))
4745
4745
4746 ctx = scmutil.revsingle(repo, opts.get('rev'))
4746 ctx = scmutil.revsingle(repo, opts.get('rev'))
4747 node = ctx.node()
4747 node = ctx.node()
4748
4748
4749 if not pats and not opts.get('all'):
4749 if not pats and not opts.get('all'):
4750 msg = _("no files or directories specified")
4750 msg = _("no files or directories specified")
4751 if p2 != nullid:
4751 if p2 != nullid:
4752 hint = _("uncommitted merge, use --all to discard all changes,"
4752 hint = _("uncommitted merge, use --all to discard all changes,"
4753 " or 'hg update -C .' to abort the merge")
4753 " or 'hg update -C .' to abort the merge")
4754 raise util.Abort(msg, hint=hint)
4754 raise util.Abort(msg, hint=hint)
4755 dirty = util.any(repo.status())
4755 dirty = util.any(repo.status())
4756 if node != parent:
4756 if node != parent:
4757 if dirty:
4757 if dirty:
4758 hint = _("uncommitted changes, use --all to discard all"
4758 hint = _("uncommitted changes, use --all to discard all"
4759 " changes, or 'hg update %s' to update") % ctx.rev()
4759 " changes, or 'hg update %s' to update") % ctx.rev()
4760 else:
4760 else:
4761 hint = _("use --all to revert all files,"
4761 hint = _("use --all to revert all files,"
4762 " or 'hg update %s' to update") % ctx.rev()
4762 " or 'hg update %s' to update") % ctx.rev()
4763 elif dirty:
4763 elif dirty:
4764 hint = _("uncommitted changes, use --all to discard all changes")
4764 hint = _("uncommitted changes, use --all to discard all changes")
4765 else:
4765 else:
4766 hint = _("use --all to revert all files")
4766 hint = _("use --all to revert all files")
4767 raise util.Abort(msg, hint=hint)
4767 raise util.Abort(msg, hint=hint)
4768
4768
4769 mf = ctx.manifest()
4769 mf = ctx.manifest()
4770 if node == parent:
4770 if node == parent:
4771 pmf = mf
4771 pmf = mf
4772 else:
4772 else:
4773 pmf = None
4773 pmf = None
4774
4774
4775 # need all matching names in dirstate and manifest of target rev,
4775 # need all matching names in dirstate and manifest of target rev,
4776 # so have to walk both. do not print errors if files exist in one
4776 # so have to walk both. do not print errors if files exist in one
4777 # but not other.
4777 # but not other.
4778
4778
4779 names = {}
4779 names = {}
4780
4780
4781 wlock = repo.wlock()
4781 wlock = repo.wlock()
4782 try:
4782 try:
4783 # walk dirstate.
4783 # walk dirstate.
4784
4784
4785 m = scmutil.match(repo[None], pats, opts)
4785 m = scmutil.match(repo[None], pats, opts)
4786 m.bad = lambda x, y: False
4786 m.bad = lambda x, y: False
4787 for abs in repo.walk(m):
4787 for abs in repo.walk(m):
4788 names[abs] = m.rel(abs), m.exact(abs)
4788 names[abs] = m.rel(abs), m.exact(abs)
4789
4789
4790 # walk target manifest.
4790 # walk target manifest.
4791
4791
4792 def badfn(path, msg):
4792 def badfn(path, msg):
4793 if path in names:
4793 if path in names:
4794 return
4794 return
4795 if path in repo[node].substate:
4795 if path in repo[node].substate:
4796 ui.warn("%s: %s\n" % (m.rel(path),
4796 ui.warn("%s: %s\n" % (m.rel(path),
4797 'reverting subrepos is unsupported'))
4797 'reverting subrepos is unsupported'))
4798 return
4798 return
4799 path_ = path + '/'
4799 path_ = path + '/'
4800 for f in names:
4800 for f in names:
4801 if f.startswith(path_):
4801 if f.startswith(path_):
4802 return
4802 return
4803 ui.warn("%s: %s\n" % (m.rel(path), msg))
4803 ui.warn("%s: %s\n" % (m.rel(path), msg))
4804
4804
4805 m = scmutil.match(repo[node], pats, opts)
4805 m = scmutil.match(repo[node], pats, opts)
4806 m.bad = badfn
4806 m.bad = badfn
4807 for abs in repo[node].walk(m):
4807 for abs in repo[node].walk(m):
4808 if abs not in names:
4808 if abs not in names:
4809 names[abs] = m.rel(abs), m.exact(abs)
4809 names[abs] = m.rel(abs), m.exact(abs)
4810
4810
4811 m = scmutil.matchfiles(repo, names)
4811 m = scmutil.matchfiles(repo, names)
4812 changes = repo.status(match=m)[:4]
4812 changes = repo.status(match=m)[:4]
4813 modified, added, removed, deleted = map(set, changes)
4813 modified, added, removed, deleted = map(set, changes)
4814
4814
4815 # if f is a rename, also revert the source
4815 # if f is a rename, also revert the source
4816 cwd = repo.getcwd()
4816 cwd = repo.getcwd()
4817 for f in added:
4817 for f in added:
4818 src = repo.dirstate.copied(f)
4818 src = repo.dirstate.copied(f)
4819 if src and src not in names and repo.dirstate[src] == 'r':
4819 if src and src not in names and repo.dirstate[src] == 'r':
4820 removed.add(src)
4820 removed.add(src)
4821 names[src] = (repo.pathto(src, cwd), True)
4821 names[src] = (repo.pathto(src, cwd), True)
4822
4822
4823 def removeforget(abs):
4823 def removeforget(abs):
4824 if repo.dirstate[abs] == 'a':
4824 if repo.dirstate[abs] == 'a':
4825 return _('forgetting %s\n')
4825 return _('forgetting %s\n')
4826 return _('removing %s\n')
4826 return _('removing %s\n')
4827
4827
4828 revert = ([], _('reverting %s\n'))
4828 revert = ([], _('reverting %s\n'))
4829 add = ([], _('adding %s\n'))
4829 add = ([], _('adding %s\n'))
4830 remove = ([], removeforget)
4830 remove = ([], removeforget)
4831 undelete = ([], _('undeleting %s\n'))
4831 undelete = ([], _('undeleting %s\n'))
4832
4832
4833 disptable = (
4833 disptable = (
4834 # dispatch table:
4834 # dispatch table:
4835 # file state
4835 # file state
4836 # action if in target manifest
4836 # action if in target manifest
4837 # action if not in target manifest
4837 # action if not in target manifest
4838 # make backup if in target manifest
4838 # make backup if in target manifest
4839 # make backup if not in target manifest
4839 # make backup if not in target manifest
4840 (modified, revert, remove, True, True),
4840 (modified, revert, remove, True, True),
4841 (added, revert, remove, True, False),
4841 (added, revert, remove, True, False),
4842 (removed, undelete, None, False, False),
4842 (removed, undelete, None, False, False),
4843 (deleted, revert, remove, False, False),
4843 (deleted, revert, remove, False, False),
4844 )
4844 )
4845
4845
4846 for abs, (rel, exact) in sorted(names.items()):
4846 for abs, (rel, exact) in sorted(names.items()):
4847 mfentry = mf.get(abs)
4847 mfentry = mf.get(abs)
4848 target = repo.wjoin(abs)
4848 target = repo.wjoin(abs)
4849 def handle(xlist, dobackup):
4849 def handle(xlist, dobackup):
4850 xlist[0].append(abs)
4850 xlist[0].append(abs)
4851 if (dobackup and not opts.get('no_backup') and
4851 if (dobackup and not opts.get('no_backup') and
4852 os.path.lexists(target)):
4852 os.path.lexists(target)):
4853 bakname = "%s.orig" % rel
4853 bakname = "%s.orig" % rel
4854 ui.note(_('saving current version of %s as %s\n') %
4854 ui.note(_('saving current version of %s as %s\n') %
4855 (rel, bakname))
4855 (rel, bakname))
4856 if not opts.get('dry_run'):
4856 if not opts.get('dry_run'):
4857 util.rename(target, bakname)
4857 util.rename(target, bakname)
4858 if ui.verbose or not exact:
4858 if ui.verbose or not exact:
4859 msg = xlist[1]
4859 msg = xlist[1]
4860 if not isinstance(msg, basestring):
4860 if not isinstance(msg, basestring):
4861 msg = msg(abs)
4861 msg = msg(abs)
4862 ui.status(msg % rel)
4862 ui.status(msg % rel)
4863 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4863 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4864 if abs not in table:
4864 if abs not in table:
4865 continue
4865 continue
4866 # file has changed in dirstate
4866 # file has changed in dirstate
4867 if mfentry:
4867 if mfentry:
4868 handle(hitlist, backuphit)
4868 handle(hitlist, backuphit)
4869 elif misslist is not None:
4869 elif misslist is not None:
4870 handle(misslist, backupmiss)
4870 handle(misslist, backupmiss)
4871 break
4871 break
4872 else:
4872 else:
4873 if abs not in repo.dirstate:
4873 if abs not in repo.dirstate:
4874 if mfentry:
4874 if mfentry:
4875 handle(add, True)
4875 handle(add, True)
4876 elif exact:
4876 elif exact:
4877 ui.warn(_('file not managed: %s\n') % rel)
4877 ui.warn(_('file not managed: %s\n') % rel)
4878 continue
4878 continue
4879 # file has not changed in dirstate
4879 # file has not changed in dirstate
4880 if node == parent:
4880 if node == parent:
4881 if exact:
4881 if exact:
4882 ui.warn(_('no changes needed to %s\n') % rel)
4882 ui.warn(_('no changes needed to %s\n') % rel)
4883 continue
4883 continue
4884 if pmf is None:
4884 if pmf is None:
4885 # only need parent manifest in this unlikely case,
4885 # only need parent manifest in this unlikely case,
4886 # so do not read by default
4886 # so do not read by default
4887 pmf = repo[parent].manifest()
4887 pmf = repo[parent].manifest()
4888 if abs in pmf and mfentry:
4888 if abs in pmf and mfentry:
4889 # if version of file is same in parent and target
4889 # if version of file is same in parent and target
4890 # manifests, do nothing
4890 # manifests, do nothing
4891 if (pmf[abs] != mfentry or
4891 if (pmf[abs] != mfentry or
4892 pmf.flags(abs) != mf.flags(abs)):
4892 pmf.flags(abs) != mf.flags(abs)):
4893 handle(revert, False)
4893 handle(revert, False)
4894 else:
4894 else:
4895 handle(remove, False)
4895 handle(remove, False)
4896
4896
4897 if not opts.get('dry_run'):
4897 if not opts.get('dry_run'):
4898 def checkout(f):
4898 def checkout(f):
4899 fc = ctx[f]
4899 fc = ctx[f]
4900 repo.wwrite(f, fc.data(), fc.flags())
4900 repo.wwrite(f, fc.data(), fc.flags())
4901
4901
4902 audit_path = scmutil.pathauditor(repo.root)
4902 audit_path = scmutil.pathauditor(repo.root)
4903 for f in remove[0]:
4903 for f in remove[0]:
4904 if repo.dirstate[f] == 'a':
4904 if repo.dirstate[f] == 'a':
4905 repo.dirstate.drop(f)
4905 repo.dirstate.drop(f)
4906 continue
4906 continue
4907 audit_path(f)
4907 audit_path(f)
4908 try:
4908 try:
4909 util.unlinkpath(repo.wjoin(f))
4909 util.unlinkpath(repo.wjoin(f))
4910 except OSError:
4910 except OSError:
4911 pass
4911 pass
4912 repo.dirstate.remove(f)
4912 repo.dirstate.remove(f)
4913
4913
4914 normal = None
4914 normal = None
4915 if node == parent:
4915 if node == parent:
4916 # We're reverting to our parent. If possible, we'd like status
4916 # We're reverting to our parent. If possible, we'd like status
4917 # to report the file as clean. We have to use normallookup for
4917 # to report the file as clean. We have to use normallookup for
4918 # merges to avoid losing information about merged/dirty files.
4918 # merges to avoid losing information about merged/dirty files.
4919 if p2 != nullid:
4919 if p2 != nullid:
4920 normal = repo.dirstate.normallookup
4920 normal = repo.dirstate.normallookup
4921 else:
4921 else:
4922 normal = repo.dirstate.normal
4922 normal = repo.dirstate.normal
4923 for f in revert[0]:
4923 for f in revert[0]:
4924 checkout(f)
4924 checkout(f)
4925 if normal:
4925 if normal:
4926 normal(f)
4926 normal(f)
4927
4927
4928 for f in add[0]:
4928 for f in add[0]:
4929 checkout(f)
4929 checkout(f)
4930 repo.dirstate.add(f)
4930 repo.dirstate.add(f)
4931
4931
4932 normal = repo.dirstate.normallookup
4932 normal = repo.dirstate.normallookup
4933 if node == parent and p2 == nullid:
4933 if node == parent and p2 == nullid:
4934 normal = repo.dirstate.normal
4934 normal = repo.dirstate.normal
4935 for f in undelete[0]:
4935 for f in undelete[0]:
4936 checkout(f)
4936 checkout(f)
4937 normal(f)
4937 normal(f)
4938
4938
4939 finally:
4939 finally:
4940 wlock.release()
4940 wlock.release()
4941
4941
4942 @command('rollback', dryrunopts +
4942 @command('rollback', dryrunopts +
4943 [('f', 'force', False, _('ignore safety measures'))])
4943 [('f', 'force', False, _('ignore safety measures'))])
4944 def rollback(ui, repo, **opts):
4944 def rollback(ui, repo, **opts):
4945 """roll back the last transaction (dangerous)
4945 """roll back the last transaction (dangerous)
4946
4946
4947 This command should be used with care. There is only one level of
4947 This command should be used with care. There is only one level of
4948 rollback, and there is no way to undo a rollback. It will also
4948 rollback, and there is no way to undo a rollback. It will also
4949 restore the dirstate at the time of the last transaction, losing
4949 restore the dirstate at the time of the last transaction, losing
4950 any dirstate changes since that time. This command does not alter
4950 any dirstate changes since that time. This command does not alter
4951 the working directory.
4951 the working directory.
4952
4952
4953 Transactions are used to encapsulate the effects of all commands
4953 Transactions are used to encapsulate the effects of all commands
4954 that create new changesets or propagate existing changesets into a
4954 that create new changesets or propagate existing changesets into a
4955 repository. For example, the following commands are transactional,
4955 repository. For example, the following commands are transactional,
4956 and their effects can be rolled back:
4956 and their effects can be rolled back:
4957
4957
4958 - commit
4958 - commit
4959 - import
4959 - import
4960 - pull
4960 - pull
4961 - push (with this repository as the destination)
4961 - push (with this repository as the destination)
4962 - unbundle
4962 - unbundle
4963
4963
4964 To avoid permanent data loss, rollback will refuse to rollback a
4964 To avoid permanent data loss, rollback will refuse to rollback a
4965 commit transaction if it isn't checked out. Use --force to
4965 commit transaction if it isn't checked out. Use --force to
4966 override this protection.
4966 override this protection.
4967
4967
4968 This command is not intended for use on public repositories. Once
4968 This command is not intended for use on public repositories. Once
4969 changes are visible for pull by other users, rolling a transaction
4969 changes are visible for pull by other users, rolling a transaction
4970 back locally is ineffective (someone else may already have pulled
4970 back locally is ineffective (someone else may already have pulled
4971 the changes). Furthermore, a race is possible with readers of the
4971 the changes). Furthermore, a race is possible with readers of the
4972 repository; for example an in-progress pull from the repository
4972 repository; for example an in-progress pull from the repository
4973 may fail if a rollback is performed.
4973 may fail if a rollback is performed.
4974
4974
4975 Returns 0 on success, 1 if no rollback data is available.
4975 Returns 0 on success, 1 if no rollback data is available.
4976 """
4976 """
4977 return repo.rollback(dryrun=opts.get('dry_run'),
4977 return repo.rollback(dryrun=opts.get('dry_run'),
4978 force=opts.get('force'))
4978 force=opts.get('force'))
4979
4979
4980 @command('root', [])
4980 @command('root', [])
4981 def root(ui, repo):
4981 def root(ui, repo):
4982 """print the root (top) of the current working directory
4982 """print the root (top) of the current working directory
4983
4983
4984 Print the root directory of the current repository.
4984 Print the root directory of the current repository.
4985
4985
4986 Returns 0 on success.
4986 Returns 0 on success.
4987 """
4987 """
4988 ui.write(repo.root + "\n")
4988 ui.write(repo.root + "\n")
4989
4989
4990 @command('^serve',
4990 @command('^serve',
4991 [('A', 'accesslog', '', _('name of access log file to write to'),
4991 [('A', 'accesslog', '', _('name of access log file to write to'),
4992 _('FILE')),
4992 _('FILE')),
4993 ('d', 'daemon', None, _('run server in background')),
4993 ('d', 'daemon', None, _('run server in background')),
4994 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4994 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4995 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4995 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4996 # use string type, then we can check if something was passed
4996 # use string type, then we can check if something was passed
4997 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4997 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4998 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4998 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4999 _('ADDR')),
4999 _('ADDR')),
5000 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5000 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5001 _('PREFIX')),
5001 _('PREFIX')),
5002 ('n', 'name', '',
5002 ('n', 'name', '',
5003 _('name to show in web pages (default: working directory)'), _('NAME')),
5003 _('name to show in web pages (default: working directory)'), _('NAME')),
5004 ('', 'web-conf', '',
5004 ('', 'web-conf', '',
5005 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5005 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5006 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5006 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5007 _('FILE')),
5007 _('FILE')),
5008 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5008 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5009 ('', 'stdio', None, _('for remote clients')),
5009 ('', 'stdio', None, _('for remote clients')),
5010 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5010 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5011 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5011 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5012 ('', 'style', '', _('template style to use'), _('STYLE')),
5012 ('', 'style', '', _('template style to use'), _('STYLE')),
5013 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5013 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5014 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5014 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5015 _('[OPTION]...'))
5015 _('[OPTION]...'))
5016 def serve(ui, repo, **opts):
5016 def serve(ui, repo, **opts):
5017 """start stand-alone webserver
5017 """start stand-alone webserver
5018
5018
5019 Start a local HTTP repository browser and pull server. You can use
5019 Start a local HTTP repository browser and pull server. You can use
5020 this for ad-hoc sharing and browsing of repositories. It is
5020 this for ad-hoc sharing and browsing of repositories. It is
5021 recommended to use a real web server to serve a repository for
5021 recommended to use a real web server to serve a repository for
5022 longer periods of time.
5022 longer periods of time.
5023
5023
5024 Please note that the server does not implement access control.
5024 Please note that the server does not implement access control.
5025 This means that, by default, anybody can read from the server and
5025 This means that, by default, anybody can read from the server and
5026 nobody can write to it by default. Set the ``web.allow_push``
5026 nobody can write to it by default. Set the ``web.allow_push``
5027 option to ``*`` to allow everybody to push to the server. You
5027 option to ``*`` to allow everybody to push to the server. You
5028 should use a real web server if you need to authenticate users.
5028 should use a real web server if you need to authenticate users.
5029
5029
5030 By default, the server logs accesses to stdout and errors to
5030 By default, the server logs accesses to stdout and errors to
5031 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5031 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5032 files.
5032 files.
5033
5033
5034 To have the server choose a free port number to listen on, specify
5034 To have the server choose a free port number to listen on, specify
5035 a port number of 0; in this case, the server will print the port
5035 a port number of 0; in this case, the server will print the port
5036 number it uses.
5036 number it uses.
5037
5037
5038 Returns 0 on success.
5038 Returns 0 on success.
5039 """
5039 """
5040
5040
5041 if opts["stdio"] and opts["cmdserver"]:
5041 if opts["stdio"] and opts["cmdserver"]:
5042 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5042 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5043
5043
5044 def checkrepo():
5044 def checkrepo():
5045 if repo is None:
5045 if repo is None:
5046 raise error.RepoError(_("There is no Mercurial repository here"
5046 raise error.RepoError(_("There is no Mercurial repository here"
5047 " (.hg not found)"))
5047 " (.hg not found)"))
5048
5048
5049 if opts["stdio"]:
5049 if opts["stdio"]:
5050 checkrepo()
5050 checkrepo()
5051 s = sshserver.sshserver(ui, repo)
5051 s = sshserver.sshserver(ui, repo)
5052 s.serve_forever()
5052 s.serve_forever()
5053
5053
5054 if opts["cmdserver"]:
5054 if opts["cmdserver"]:
5055 checkrepo()
5055 checkrepo()
5056 s = commandserver.server(ui, repo, opts["cmdserver"])
5056 s = commandserver.server(ui, repo, opts["cmdserver"])
5057 return s.serve()
5057 return s.serve()
5058
5058
5059 # this way we can check if something was given in the command-line
5059 # this way we can check if something was given in the command-line
5060 if opts.get('port'):
5060 if opts.get('port'):
5061 opts['port'] = util.getport(opts.get('port'))
5061 opts['port'] = util.getport(opts.get('port'))
5062
5062
5063 baseui = repo and repo.baseui or ui
5063 baseui = repo and repo.baseui or ui
5064 optlist = ("name templates style address port prefix ipv6"
5064 optlist = ("name templates style address port prefix ipv6"
5065 " accesslog errorlog certificate encoding")
5065 " accesslog errorlog certificate encoding")
5066 for o in optlist.split():
5066 for o in optlist.split():
5067 val = opts.get(o, '')
5067 val = opts.get(o, '')
5068 if val in (None, ''): # should check against default options instead
5068 if val in (None, ''): # should check against default options instead
5069 continue
5069 continue
5070 baseui.setconfig("web", o, val)
5070 baseui.setconfig("web", o, val)
5071 if repo and repo.ui != baseui:
5071 if repo and repo.ui != baseui:
5072 repo.ui.setconfig("web", o, val)
5072 repo.ui.setconfig("web", o, val)
5073
5073
5074 o = opts.get('web_conf') or opts.get('webdir_conf')
5074 o = opts.get('web_conf') or opts.get('webdir_conf')
5075 if not o:
5075 if not o:
5076 if not repo:
5076 if not repo:
5077 raise error.RepoError(_("There is no Mercurial repository"
5077 raise error.RepoError(_("There is no Mercurial repository"
5078 " here (.hg not found)"))
5078 " here (.hg not found)"))
5079 o = repo.root
5079 o = repo.root
5080
5080
5081 app = hgweb.hgweb(o, baseui=ui)
5081 app = hgweb.hgweb(o, baseui=ui)
5082
5082
5083 class service(object):
5083 class service(object):
5084 def init(self):
5084 def init(self):
5085 util.setsignalhandler()
5085 util.setsignalhandler()
5086 self.httpd = hgweb.server.create_server(ui, app)
5086 self.httpd = hgweb.server.create_server(ui, app)
5087
5087
5088 if opts['port'] and not ui.verbose:
5088 if opts['port'] and not ui.verbose:
5089 return
5089 return
5090
5090
5091 if self.httpd.prefix:
5091 if self.httpd.prefix:
5092 prefix = self.httpd.prefix.strip('/') + '/'
5092 prefix = self.httpd.prefix.strip('/') + '/'
5093 else:
5093 else:
5094 prefix = ''
5094 prefix = ''
5095
5095
5096 port = ':%d' % self.httpd.port
5096 port = ':%d' % self.httpd.port
5097 if port == ':80':
5097 if port == ':80':
5098 port = ''
5098 port = ''
5099
5099
5100 bindaddr = self.httpd.addr
5100 bindaddr = self.httpd.addr
5101 if bindaddr == '0.0.0.0':
5101 if bindaddr == '0.0.0.0':
5102 bindaddr = '*'
5102 bindaddr = '*'
5103 elif ':' in bindaddr: # IPv6
5103 elif ':' in bindaddr: # IPv6
5104 bindaddr = '[%s]' % bindaddr
5104 bindaddr = '[%s]' % bindaddr
5105
5105
5106 fqaddr = self.httpd.fqaddr
5106 fqaddr = self.httpd.fqaddr
5107 if ':' in fqaddr:
5107 if ':' in fqaddr:
5108 fqaddr = '[%s]' % fqaddr
5108 fqaddr = '[%s]' % fqaddr
5109 if opts['port']:
5109 if opts['port']:
5110 write = ui.status
5110 write = ui.status
5111 else:
5111 else:
5112 write = ui.write
5112 write = ui.write
5113 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5113 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5114 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5114 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5115
5115
5116 def run(self):
5116 def run(self):
5117 self.httpd.serve_forever()
5117 self.httpd.serve_forever()
5118
5118
5119 service = service()
5119 service = service()
5120
5120
5121 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5121 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5122
5122
5123 @command('showconfig|debugconfig',
5123 @command('showconfig|debugconfig',
5124 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5124 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5125 _('[-u] [NAME]...'))
5125 _('[-u] [NAME]...'))
5126 def showconfig(ui, repo, *values, **opts):
5126 def showconfig(ui, repo, *values, **opts):
5127 """show combined config settings from all hgrc files
5127 """show combined config settings from all hgrc files
5128
5128
5129 With no arguments, print names and values of all config items.
5129 With no arguments, print names and values of all config items.
5130
5130
5131 With one argument of the form section.name, print just the value
5131 With one argument of the form section.name, print just the value
5132 of that config item.
5132 of that config item.
5133
5133
5134 With multiple arguments, print names and values of all config
5134 With multiple arguments, print names and values of all config
5135 items with matching section names.
5135 items with matching section names.
5136
5136
5137 With --debug, the source (filename and line number) is printed
5137 With --debug, the source (filename and line number) is printed
5138 for each config item.
5138 for each config item.
5139
5139
5140 Returns 0 on success.
5140 Returns 0 on success.
5141 """
5141 """
5142
5142
5143 for f in scmutil.rcpath():
5143 for f in scmutil.rcpath():
5144 ui.debug('read config from: %s\n' % f)
5144 ui.debug('read config from: %s\n' % f)
5145 untrusted = bool(opts.get('untrusted'))
5145 untrusted = bool(opts.get('untrusted'))
5146 if values:
5146 if values:
5147 sections = [v for v in values if '.' not in v]
5147 sections = [v for v in values if '.' not in v]
5148 items = [v for v in values if '.' in v]
5148 items = [v for v in values if '.' in v]
5149 if len(items) > 1 or items and sections:
5149 if len(items) > 1 or items and sections:
5150 raise util.Abort(_('only one config item permitted'))
5150 raise util.Abort(_('only one config item permitted'))
5151 for section, name, value in ui.walkconfig(untrusted=untrusted):
5151 for section, name, value in ui.walkconfig(untrusted=untrusted):
5152 value = str(value).replace('\n', '\\n')
5152 value = str(value).replace('\n', '\\n')
5153 sectname = section + '.' + name
5153 sectname = section + '.' + name
5154 if values:
5154 if values:
5155 for v in values:
5155 for v in values:
5156 if v == section:
5156 if v == section:
5157 ui.debug('%s: ' %
5157 ui.debug('%s: ' %
5158 ui.configsource(section, name, untrusted))
5158 ui.configsource(section, name, untrusted))
5159 ui.write('%s=%s\n' % (sectname, value))
5159 ui.write('%s=%s\n' % (sectname, value))
5160 elif v == sectname:
5160 elif v == sectname:
5161 ui.debug('%s: ' %
5161 ui.debug('%s: ' %
5162 ui.configsource(section, name, untrusted))
5162 ui.configsource(section, name, untrusted))
5163 ui.write(value, '\n')
5163 ui.write(value, '\n')
5164 else:
5164 else:
5165 ui.debug('%s: ' %
5165 ui.debug('%s: ' %
5166 ui.configsource(section, name, untrusted))
5166 ui.configsource(section, name, untrusted))
5167 ui.write('%s=%s\n' % (sectname, value))
5167 ui.write('%s=%s\n' % (sectname, value))
5168
5168
5169 @command('^status|st',
5169 @command('^status|st',
5170 [('A', 'all', None, _('show status of all files')),
5170 [('A', 'all', None, _('show status of all files')),
5171 ('m', 'modified', None, _('show only modified files')),
5171 ('m', 'modified', None, _('show only modified files')),
5172 ('a', 'added', None, _('show only added files')),
5172 ('a', 'added', None, _('show only added files')),
5173 ('r', 'removed', None, _('show only removed files')),
5173 ('r', 'removed', None, _('show only removed files')),
5174 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5174 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5175 ('c', 'clean', None, _('show only files without changes')),
5175 ('c', 'clean', None, _('show only files without changes')),
5176 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5176 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5177 ('i', 'ignored', None, _('show only ignored files')),
5177 ('i', 'ignored', None, _('show only ignored files')),
5178 ('n', 'no-status', None, _('hide status prefix')),
5178 ('n', 'no-status', None, _('hide status prefix')),
5179 ('C', 'copies', None, _('show source of copied files')),
5179 ('C', 'copies', None, _('show source of copied files')),
5180 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5180 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5181 ('', 'rev', [], _('show difference from revision'), _('REV')),
5181 ('', 'rev', [], _('show difference from revision'), _('REV')),
5182 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5182 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5183 ] + walkopts + subrepoopts,
5183 ] + walkopts + subrepoopts,
5184 _('[OPTION]... [FILE]...'))
5184 _('[OPTION]... [FILE]...'))
5185 def status(ui, repo, *pats, **opts):
5185 def status(ui, repo, *pats, **opts):
5186 """show changed files in the working directory
5186 """show changed files in the working directory
5187
5187
5188 Show status of files in the repository. If names are given, only
5188 Show status of files in the repository. If names are given, only
5189 files that match are shown. Files that are clean or ignored or
5189 files that match are shown. Files that are clean or ignored or
5190 the source of a copy/move operation, are not listed unless
5190 the source of a copy/move operation, are not listed unless
5191 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5191 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5192 Unless options described with "show only ..." are given, the
5192 Unless options described with "show only ..." are given, the
5193 options -mardu are used.
5193 options -mardu are used.
5194
5194
5195 Option -q/--quiet hides untracked (unknown and ignored) files
5195 Option -q/--quiet hides untracked (unknown and ignored) files
5196 unless explicitly requested with -u/--unknown or -i/--ignored.
5196 unless explicitly requested with -u/--unknown or -i/--ignored.
5197
5197
5198 .. note::
5198 .. note::
5199 status may appear to disagree with diff if permissions have
5199 status may appear to disagree with diff if permissions have
5200 changed or a merge has occurred. The standard diff format does
5200 changed or a merge has occurred. The standard diff format does
5201 not report permission changes and diff only reports changes
5201 not report permission changes and diff only reports changes
5202 relative to one merge parent.
5202 relative to one merge parent.
5203
5203
5204 If one revision is given, it is used as the base revision.
5204 If one revision is given, it is used as the base revision.
5205 If two revisions are given, the differences between them are
5205 If two revisions are given, the differences between them are
5206 shown. The --change option can also be used as a shortcut to list
5206 shown. The --change option can also be used as a shortcut to list
5207 the changed files of a revision from its first parent.
5207 the changed files of a revision from its first parent.
5208
5208
5209 The codes used to show the status of files are::
5209 The codes used to show the status of files are::
5210
5210
5211 M = modified
5211 M = modified
5212 A = added
5212 A = added
5213 R = removed
5213 R = removed
5214 C = clean
5214 C = clean
5215 ! = missing (deleted by non-hg command, but still tracked)
5215 ! = missing (deleted by non-hg command, but still tracked)
5216 ? = not tracked
5216 ? = not tracked
5217 I = ignored
5217 I = ignored
5218 = origin of the previous file listed as A (added)
5218 = origin of the previous file listed as A (added)
5219
5219
5220 .. container:: verbose
5220 .. container:: verbose
5221
5221
5222 Examples:
5222 Examples:
5223
5223
5224 - show changes in the working directory relative to a
5224 - show changes in the working directory relative to a
5225 changeset::
5225 changeset::
5226
5226
5227 hg status --rev 9353
5227 hg status --rev 9353
5228
5228
5229 - show all changes including copies in an existing changeset::
5229 - show all changes including copies in an existing changeset::
5230
5230
5231 hg status --copies --change 9353
5231 hg status --copies --change 9353
5232
5232
5233 - get a NUL separated list of added files, suitable for xargs::
5233 - get a NUL separated list of added files, suitable for xargs::
5234
5234
5235 hg status -an0
5235 hg status -an0
5236
5236
5237 Returns 0 on success.
5237 Returns 0 on success.
5238 """
5238 """
5239
5239
5240 revs = opts.get('rev')
5240 revs = opts.get('rev')
5241 change = opts.get('change')
5241 change = opts.get('change')
5242
5242
5243 if revs and change:
5243 if revs and change:
5244 msg = _('cannot specify --rev and --change at the same time')
5244 msg = _('cannot specify --rev and --change at the same time')
5245 raise util.Abort(msg)
5245 raise util.Abort(msg)
5246 elif change:
5246 elif change:
5247 node2 = scmutil.revsingle(repo, change, None).node()
5247 node2 = scmutil.revsingle(repo, change, None).node()
5248 node1 = repo[node2].p1().node()
5248 node1 = repo[node2].p1().node()
5249 else:
5249 else:
5250 node1, node2 = scmutil.revpair(repo, revs)
5250 node1, node2 = scmutil.revpair(repo, revs)
5251
5251
5252 cwd = (pats and repo.getcwd()) or ''
5252 cwd = (pats and repo.getcwd()) or ''
5253 end = opts.get('print0') and '\0' or '\n'
5253 end = opts.get('print0') and '\0' or '\n'
5254 copy = {}
5254 copy = {}
5255 states = 'modified added removed deleted unknown ignored clean'.split()
5255 states = 'modified added removed deleted unknown ignored clean'.split()
5256 show = [k for k in states if opts.get(k)]
5256 show = [k for k in states if opts.get(k)]
5257 if opts.get('all'):
5257 if opts.get('all'):
5258 show += ui.quiet and (states[:4] + ['clean']) or states
5258 show += ui.quiet and (states[:4] + ['clean']) or states
5259 if not show:
5259 if not show:
5260 show = ui.quiet and states[:4] or states[:5]
5260 show = ui.quiet and states[:4] or states[:5]
5261
5261
5262 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5262 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5263 'ignored' in show, 'clean' in show, 'unknown' in show,
5263 'ignored' in show, 'clean' in show, 'unknown' in show,
5264 opts.get('subrepos'))
5264 opts.get('subrepos'))
5265 changestates = zip(states, 'MAR!?IC', stat)
5265 changestates = zip(states, 'MAR!?IC', stat)
5266
5266
5267 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5267 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5268 copy = copies.pathcopies(repo[node1], repo[node2])
5268 copy = copies.pathcopies(repo[node1], repo[node2])
5269
5269
5270 for state, char, files in changestates:
5270 for state, char, files in changestates:
5271 if state in show:
5271 if state in show:
5272 format = "%s %%s%s" % (char, end)
5272 format = "%s %%s%s" % (char, end)
5273 if opts.get('no_status'):
5273 if opts.get('no_status'):
5274 format = "%%s%s" % end
5274 format = "%%s%s" % end
5275
5275
5276 for f in files:
5276 for f in files:
5277 ui.write(format % repo.pathto(f, cwd),
5277 ui.write(format % repo.pathto(f, cwd),
5278 label='status.' + state)
5278 label='status.' + state)
5279 if f in copy:
5279 if f in copy:
5280 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5280 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5281 label='status.copied')
5281 label='status.copied')
5282
5282
5283 @command('^summary|sum',
5283 @command('^summary|sum',
5284 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5284 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5285 def summary(ui, repo, **opts):
5285 def summary(ui, repo, **opts):
5286 """summarize working directory state
5286 """summarize working directory state
5287
5287
5288 This generates a brief summary of the working directory state,
5288 This generates a brief summary of the working directory state,
5289 including parents, branch, commit status, and available updates.
5289 including parents, branch, commit status, and available updates.
5290
5290
5291 With the --remote option, this will check the default paths for
5291 With the --remote option, this will check the default paths for
5292 incoming and outgoing changes. This can be time-consuming.
5292 incoming and outgoing changes. This can be time-consuming.
5293
5293
5294 Returns 0 on success.
5294 Returns 0 on success.
5295 """
5295 """
5296
5296
5297 ctx = repo[None]
5297 ctx = repo[None]
5298 parents = ctx.parents()
5298 parents = ctx.parents()
5299 pnode = parents[0].node()
5299 pnode = parents[0].node()
5300 marks = []
5300 marks = []
5301
5301
5302 for p in parents:
5302 for p in parents:
5303 # label with log.changeset (instead of log.parent) since this
5303 # label with log.changeset (instead of log.parent) since this
5304 # shows a working directory parent *changeset*:
5304 # shows a working directory parent *changeset*:
5305 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5305 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5306 label='log.changeset')
5306 label='log.changeset')
5307 ui.write(' '.join(p.tags()), label='log.tag')
5307 ui.write(' '.join(p.tags()), label='log.tag')
5308 if p.bookmarks():
5308 if p.bookmarks():
5309 marks.extend(p.bookmarks())
5309 marks.extend(p.bookmarks())
5310 if p.rev() == -1:
5310 if p.rev() == -1:
5311 if not len(repo):
5311 if not len(repo):
5312 ui.write(_(' (empty repository)'))
5312 ui.write(_(' (empty repository)'))
5313 else:
5313 else:
5314 ui.write(_(' (no revision checked out)'))
5314 ui.write(_(' (no revision checked out)'))
5315 ui.write('\n')
5315 ui.write('\n')
5316 if p.description():
5316 if p.description():
5317 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5317 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5318 label='log.summary')
5318 label='log.summary')
5319
5319
5320 branch = ctx.branch()
5320 branch = ctx.branch()
5321 bheads = repo.branchheads(branch)
5321 bheads = repo.branchheads(branch)
5322 m = _('branch: %s\n') % branch
5322 m = _('branch: %s\n') % branch
5323 if branch != 'default':
5323 if branch != 'default':
5324 ui.write(m, label='log.branch')
5324 ui.write(m, label='log.branch')
5325 else:
5325 else:
5326 ui.status(m, label='log.branch')
5326 ui.status(m, label='log.branch')
5327
5327
5328 if marks:
5328 if marks:
5329 current = repo._bookmarkcurrent
5329 current = repo._bookmarkcurrent
5330 ui.write(_('bookmarks:'), label='log.bookmark')
5330 ui.write(_('bookmarks:'), label='log.bookmark')
5331 if current is not None:
5331 if current is not None:
5332 try:
5332 try:
5333 marks.remove(current)
5333 marks.remove(current)
5334 ui.write(' *' + current, label='bookmarks.current')
5334 ui.write(' *' + current, label='bookmarks.current')
5335 except ValueError:
5335 except ValueError:
5336 # current bookmark not in parent ctx marks
5336 # current bookmark not in parent ctx marks
5337 pass
5337 pass
5338 for m in marks:
5338 for m in marks:
5339 ui.write(' ' + m, label='log.bookmark')
5339 ui.write(' ' + m, label='log.bookmark')
5340 ui.write('\n', label='log.bookmark')
5340 ui.write('\n', label='log.bookmark')
5341
5341
5342 st = list(repo.status(unknown=True))[:6]
5342 st = list(repo.status(unknown=True))[:6]
5343
5343
5344 c = repo.dirstate.copies()
5344 c = repo.dirstate.copies()
5345 copied, renamed = [], []
5345 copied, renamed = [], []
5346 for d, s in c.iteritems():
5346 for d, s in c.iteritems():
5347 if s in st[2]:
5347 if s in st[2]:
5348 st[2].remove(s)
5348 st[2].remove(s)
5349 renamed.append(d)
5349 renamed.append(d)
5350 else:
5350 else:
5351 copied.append(d)
5351 copied.append(d)
5352 if d in st[1]:
5352 if d in st[1]:
5353 st[1].remove(d)
5353 st[1].remove(d)
5354 st.insert(3, renamed)
5354 st.insert(3, renamed)
5355 st.insert(4, copied)
5355 st.insert(4, copied)
5356
5356
5357 ms = mergemod.mergestate(repo)
5357 ms = mergemod.mergestate(repo)
5358 st.append([f for f in ms if ms[f] == 'u'])
5358 st.append([f for f in ms if ms[f] == 'u'])
5359
5359
5360 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5360 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5361 st.append(subs)
5361 st.append(subs)
5362
5362
5363 labels = [ui.label(_('%d modified'), 'status.modified'),
5363 labels = [ui.label(_('%d modified'), 'status.modified'),
5364 ui.label(_('%d added'), 'status.added'),
5364 ui.label(_('%d added'), 'status.added'),
5365 ui.label(_('%d removed'), 'status.removed'),
5365 ui.label(_('%d removed'), 'status.removed'),
5366 ui.label(_('%d renamed'), 'status.copied'),
5366 ui.label(_('%d renamed'), 'status.copied'),
5367 ui.label(_('%d copied'), 'status.copied'),
5367 ui.label(_('%d copied'), 'status.copied'),
5368 ui.label(_('%d deleted'), 'status.deleted'),
5368 ui.label(_('%d deleted'), 'status.deleted'),
5369 ui.label(_('%d unknown'), 'status.unknown'),
5369 ui.label(_('%d unknown'), 'status.unknown'),
5370 ui.label(_('%d ignored'), 'status.ignored'),
5370 ui.label(_('%d ignored'), 'status.ignored'),
5371 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5371 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5372 ui.label(_('%d subrepos'), 'status.modified')]
5372 ui.label(_('%d subrepos'), 'status.modified')]
5373 t = []
5373 t = []
5374 for s, l in zip(st, labels):
5374 for s, l in zip(st, labels):
5375 if s:
5375 if s:
5376 t.append(l % len(s))
5376 t.append(l % len(s))
5377
5377
5378 t = ', '.join(t)
5378 t = ', '.join(t)
5379 cleanworkdir = False
5379 cleanworkdir = False
5380
5380
5381 if len(parents) > 1:
5381 if len(parents) > 1:
5382 t += _(' (merge)')
5382 t += _(' (merge)')
5383 elif branch != parents[0].branch():
5383 elif branch != parents[0].branch():
5384 t += _(' (new branch)')
5384 t += _(' (new branch)')
5385 elif (parents[0].extra().get('close') and
5385 elif (parents[0].extra().get('close') and
5386 pnode in repo.branchheads(branch, closed=True)):
5386 pnode in repo.branchheads(branch, closed=True)):
5387 t += _(' (head closed)')
5387 t += _(' (head closed)')
5388 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5388 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5389 t += _(' (clean)')
5389 t += _(' (clean)')
5390 cleanworkdir = True
5390 cleanworkdir = True
5391 elif pnode not in bheads:
5391 elif pnode not in bheads:
5392 t += _(' (new branch head)')
5392 t += _(' (new branch head)')
5393
5393
5394 if cleanworkdir:
5394 if cleanworkdir:
5395 ui.status(_('commit: %s\n') % t.strip())
5395 ui.status(_('commit: %s\n') % t.strip())
5396 else:
5396 else:
5397 ui.write(_('commit: %s\n') % t.strip())
5397 ui.write(_('commit: %s\n') % t.strip())
5398
5398
5399 # all ancestors of branch heads - all ancestors of parent = new csets
5399 # all ancestors of branch heads - all ancestors of parent = new csets
5400 new = [0] * len(repo)
5400 new = [0] * len(repo)
5401 cl = repo.changelog
5401 cl = repo.changelog
5402 for a in [cl.rev(n) for n in bheads]:
5402 for a in [cl.rev(n) for n in bheads]:
5403 new[a] = 1
5403 new[a] = 1
5404 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5404 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5405 new[a] = 1
5405 new[a] = 1
5406 for a in [p.rev() for p in parents]:
5406 for a in [p.rev() for p in parents]:
5407 if a >= 0:
5407 if a >= 0:
5408 new[a] = 0
5408 new[a] = 0
5409 for a in cl.ancestors(*[p.rev() for p in parents]):
5409 for a in cl.ancestors(*[p.rev() for p in parents]):
5410 new[a] = 0
5410 new[a] = 0
5411 new = sum(new)
5411 new = sum(new)
5412
5412
5413 if new == 0:
5413 if new == 0:
5414 ui.status(_('update: (current)\n'))
5414 ui.status(_('update: (current)\n'))
5415 elif pnode not in bheads:
5415 elif pnode not in bheads:
5416 ui.write(_('update: %d new changesets (update)\n') % new)
5416 ui.write(_('update: %d new changesets (update)\n') % new)
5417 else:
5417 else:
5418 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5418 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5419 (new, len(bheads)))
5419 (new, len(bheads)))
5420
5420
5421 if opts.get('remote'):
5421 if opts.get('remote'):
5422 t = []
5422 t = []
5423 source, branches = hg.parseurl(ui.expandpath('default'))
5423 source, branches = hg.parseurl(ui.expandpath('default'))
5424 other = hg.peer(repo, {}, source)
5424 other = hg.peer(repo, {}, source)
5425 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5425 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5426 ui.debug('comparing with %s\n' % util.hidepassword(source))
5426 ui.debug('comparing with %s\n' % util.hidepassword(source))
5427 repo.ui.pushbuffer()
5427 repo.ui.pushbuffer()
5428 commoninc = discovery.findcommonincoming(repo, other)
5428 commoninc = discovery.findcommonincoming(repo, other)
5429 _common, incoming, _rheads = commoninc
5429 _common, incoming, _rheads = commoninc
5430 repo.ui.popbuffer()
5430 repo.ui.popbuffer()
5431 if incoming:
5431 if incoming:
5432 t.append(_('1 or more incoming'))
5432 t.append(_('1 or more incoming'))
5433
5433
5434 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5434 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5435 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5435 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5436 if source != dest:
5436 if source != dest:
5437 other = hg.peer(repo, {}, dest)
5437 other = hg.peer(repo, {}, dest)
5438 commoninc = None
5438 commoninc = None
5439 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5439 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5440 repo.ui.pushbuffer()
5440 repo.ui.pushbuffer()
5441 outgoing = discovery.findcommonoutgoing(repo, other,
5441 outgoing = discovery.findcommonoutgoing(repo, other,
5442 commoninc=commoninc)
5442 commoninc=commoninc)
5443 repo.ui.popbuffer()
5443 repo.ui.popbuffer()
5444 o = outgoing.missing
5444 o = outgoing.missing
5445 if o:
5445 if o:
5446 t.append(_('%d outgoing') % len(o))
5446 t.append(_('%d outgoing') % len(o))
5447 if 'bookmarks' in other.listkeys('namespaces'):
5447 if 'bookmarks' in other.listkeys('namespaces'):
5448 lmarks = repo.listkeys('bookmarks')
5448 lmarks = repo.listkeys('bookmarks')
5449 rmarks = other.listkeys('bookmarks')
5449 rmarks = other.listkeys('bookmarks')
5450 diff = set(rmarks) - set(lmarks)
5450 diff = set(rmarks) - set(lmarks)
5451 if len(diff) > 0:
5451 if len(diff) > 0:
5452 t.append(_('%d incoming bookmarks') % len(diff))
5452 t.append(_('%d incoming bookmarks') % len(diff))
5453 diff = set(lmarks) - set(rmarks)
5453 diff = set(lmarks) - set(rmarks)
5454 if len(diff) > 0:
5454 if len(diff) > 0:
5455 t.append(_('%d outgoing bookmarks') % len(diff))
5455 t.append(_('%d outgoing bookmarks') % len(diff))
5456
5456
5457 if t:
5457 if t:
5458 ui.write(_('remote: %s\n') % (', '.join(t)))
5458 ui.write(_('remote: %s\n') % (', '.join(t)))
5459 else:
5459 else:
5460 ui.status(_('remote: (synced)\n'))
5460 ui.status(_('remote: (synced)\n'))
5461
5461
5462 @command('tag',
5462 @command('tag',
5463 [('f', 'force', None, _('force tag')),
5463 [('f', 'force', None, _('force tag')),
5464 ('l', 'local', None, _('make the tag local')),
5464 ('l', 'local', None, _('make the tag local')),
5465 ('r', 'rev', '', _('revision to tag'), _('REV')),
5465 ('r', 'rev', '', _('revision to tag'), _('REV')),
5466 ('', 'remove', None, _('remove a tag')),
5466 ('', 'remove', None, _('remove a tag')),
5467 # -l/--local is already there, commitopts cannot be used
5467 # -l/--local is already there, commitopts cannot be used
5468 ('e', 'edit', None, _('edit commit message')),
5468 ('e', 'edit', None, _('edit commit message')),
5469 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5469 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5470 ] + commitopts2,
5470 ] + commitopts2,
5471 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5471 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5472 def tag(ui, repo, name1, *names, **opts):
5472 def tag(ui, repo, name1, *names, **opts):
5473 """add one or more tags for the current or given revision
5473 """add one or more tags for the current or given revision
5474
5474
5475 Name a particular revision using <name>.
5475 Name a particular revision using <name>.
5476
5476
5477 Tags are used to name particular revisions of the repository and are
5477 Tags are used to name particular revisions of the repository and are
5478 very useful to compare different revisions, to go back to significant
5478 very useful to compare different revisions, to go back to significant
5479 earlier versions or to mark branch points as releases, etc. Changing
5479 earlier versions or to mark branch points as releases, etc. Changing
5480 an existing tag is normally disallowed; use -f/--force to override.
5480 an existing tag is normally disallowed; use -f/--force to override.
5481
5481
5482 If no revision is given, the parent of the working directory is
5482 If no revision is given, the parent of the working directory is
5483 used, or tip if no revision is checked out.
5483 used, or tip if no revision is checked out.
5484
5484
5485 To facilitate version control, distribution, and merging of tags,
5485 To facilitate version control, distribution, and merging of tags,
5486 they are stored as a file named ".hgtags" which is managed similarly
5486 they are stored as a file named ".hgtags" which is managed similarly
5487 to other project files and can be hand-edited if necessary. This
5487 to other project files and can be hand-edited if necessary. This
5488 also means that tagging creates a new commit. The file
5488 also means that tagging creates a new commit. The file
5489 ".hg/localtags" is used for local tags (not shared among
5489 ".hg/localtags" is used for local tags (not shared among
5490 repositories).
5490 repositories).
5491
5491
5492 Tag commits are usually made at the head of a branch. If the parent
5492 Tag commits are usually made at the head of a branch. If the parent
5493 of the working directory is not a branch head, :hg:`tag` aborts; use
5493 of the working directory is not a branch head, :hg:`tag` aborts; use
5494 -f/--force to force the tag commit to be based on a non-head
5494 -f/--force to force the tag commit to be based on a non-head
5495 changeset.
5495 changeset.
5496
5496
5497 See :hg:`help dates` for a list of formats valid for -d/--date.
5497 See :hg:`help dates` for a list of formats valid for -d/--date.
5498
5498
5499 Since tag names have priority over branch names during revision
5499 Since tag names have priority over branch names during revision
5500 lookup, using an existing branch name as a tag name is discouraged.
5500 lookup, using an existing branch name as a tag name is discouraged.
5501
5501
5502 Returns 0 on success.
5502 Returns 0 on success.
5503 """
5503 """
5504
5504 wlock = lock = None
5505 rev_ = "."
5505 try:
5506 names = [t.strip() for t in (name1,) + names]
5506 wlock = repo.wlock()
5507 if len(names) != len(set(names)):
5507 lock = repo.lock()
5508 raise util.Abort(_('tag names must be unique'))
5508 rev_ = "."
5509 for n in names:
5509 names = [t.strip() for t in (name1,) + names]
5510 if n in ['tip', '.', 'null']:
5510 if len(names) != len(set(names)):
5511 raise util.Abort(_("the name '%s' is reserved") % n)
5511 raise util.Abort(_('tag names must be unique'))
5512 if not n:
5513 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5514 if opts.get('rev') and opts.get('remove'):
5515 raise util.Abort(_("--rev and --remove are incompatible"))
5516 if opts.get('rev'):
5517 rev_ = opts['rev']
5518 message = opts.get('message')
5519 if opts.get('remove'):
5520 expectedtype = opts.get('local') and 'local' or 'global'
5521 for n in names:
5512 for n in names:
5522 if not repo.tagtype(n):
5513 if n in ['tip', '.', 'null']:
5523 raise util.Abort(_("tag '%s' does not exist") % n)
5514 raise util.Abort(_("the name '%s' is reserved") % n)
5524 if repo.tagtype(n) != expectedtype:
5515 if not n:
5525 if expectedtype == 'global':
5516 raise util.Abort(_('tag names cannot consist entirely of '
5526 raise util.Abort(_("tag '%s' is not a global tag") % n)
5517 'whitespace'))
5527 else:
5518 if opts.get('rev') and opts.get('remove'):
5528 raise util.Abort(_("tag '%s' is not a local tag") % n)
5519 raise util.Abort(_("--rev and --remove are incompatible"))
5529 rev_ = nullid
5520 if opts.get('rev'):
5521 rev_ = opts['rev']
5522 message = opts.get('message')
5523 if opts.get('remove'):
5524 expectedtype = opts.get('local') and 'local' or 'global'
5525 for n in names:
5526 if not repo.tagtype(n):
5527 raise util.Abort(_("tag '%s' does not exist") % n)
5528 if repo.tagtype(n) != expectedtype:
5529 if expectedtype == 'global':
5530 raise util.Abort(_("tag '%s' is not a global tag") % n)
5531 else:
5532 raise util.Abort(_("tag '%s' is not a local tag") % n)
5533 rev_ = nullid
5534 if not message:
5535 # we don't translate commit messages
5536 message = 'Removed tag %s' % ', '.join(names)
5537 elif not opts.get('force'):
5538 for n in names:
5539 if n in repo.tags():
5540 raise util.Abort(_("tag '%s' already exists "
5541 "(use -f to force)") % n)
5542 if not opts.get('local'):
5543 p1, p2 = repo.dirstate.parents()
5544 if p2 != nullid:
5545 raise util.Abort(_('uncommitted merge'))
5546 bheads = repo.branchheads()
5547 if not opts.get('force') and bheads and p1 not in bheads:
5548 raise util.Abort(_('not at a branch head (use -f to force)'))
5549 r = scmutil.revsingle(repo, rev_).node()
5550
5530 if not message:
5551 if not message:
5531 # we don't translate commit messages
5552 # we don't translate commit messages
5532 message = 'Removed tag %s' % ', '.join(names)
5553 message = ('Added tag %s for changeset %s' %
5533 elif not opts.get('force'):
5554 (', '.join(names), short(r)))
5534 for n in names:
5555
5535 if n in repo.tags():
5556 date = opts.get('date')
5536 raise util.Abort(_("tag '%s' already exists "
5557 if date:
5537 "(use -f to force)") % n)
5558 date = util.parsedate(date)
5538 if not opts.get('local'):
5559
5539 p1, p2 = repo.dirstate.parents()
5560 if opts.get('edit'):
5540 if p2 != nullid:
5561 message = ui.edit(message, ui.username())
5541 raise util.Abort(_('uncommitted merge'))
5562
5542 bheads = repo.branchheads()
5563 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5543 if not opts.get('force') and bheads and p1 not in bheads:
5564 finally:
5544 raise util.Abort(_('not at a branch head (use -f to force)'))
5565 release(lock, wlock)
5545 r = scmutil.revsingle(repo, rev_).node()
5546
5547 if not message:
5548 # we don't translate commit messages
5549 message = ('Added tag %s for changeset %s' %
5550 (', '.join(names), short(r)))
5551
5552 date = opts.get('date')
5553 if date:
5554 date = util.parsedate(date)
5555
5556 if opts.get('edit'):
5557 message = ui.edit(message, ui.username())
5558
5559 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5560
5566
5561 @command('tags', [], '')
5567 @command('tags', [], '')
5562 def tags(ui, repo):
5568 def tags(ui, repo):
5563 """list repository tags
5569 """list repository tags
5564
5570
5565 This lists both regular and local tags. When the -v/--verbose
5571 This lists both regular and local tags. When the -v/--verbose
5566 switch is used, a third column "local" is printed for local tags.
5572 switch is used, a third column "local" is printed for local tags.
5567
5573
5568 Returns 0 on success.
5574 Returns 0 on success.
5569 """
5575 """
5570
5576
5571 hexfunc = ui.debugflag and hex or short
5577 hexfunc = ui.debugflag and hex or short
5572 tagtype = ""
5578 tagtype = ""
5573
5579
5574 for t, n in reversed(repo.tagslist()):
5580 for t, n in reversed(repo.tagslist()):
5575 if ui.quiet:
5581 if ui.quiet:
5576 ui.write("%s\n" % t, label='tags.normal')
5582 ui.write("%s\n" % t, label='tags.normal')
5577 continue
5583 continue
5578
5584
5579 hn = hexfunc(n)
5585 hn = hexfunc(n)
5580 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5586 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5581 rev = ui.label(r, 'log.changeset')
5587 rev = ui.label(r, 'log.changeset')
5582 spaces = " " * (30 - encoding.colwidth(t))
5588 spaces = " " * (30 - encoding.colwidth(t))
5583
5589
5584 tag = ui.label(t, 'tags.normal')
5590 tag = ui.label(t, 'tags.normal')
5585 if ui.verbose:
5591 if ui.verbose:
5586 if repo.tagtype(t) == 'local':
5592 if repo.tagtype(t) == 'local':
5587 tagtype = " local"
5593 tagtype = " local"
5588 tag = ui.label(t, 'tags.local')
5594 tag = ui.label(t, 'tags.local')
5589 else:
5595 else:
5590 tagtype = ""
5596 tagtype = ""
5591 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5597 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5592
5598
5593 @command('tip',
5599 @command('tip',
5594 [('p', 'patch', None, _('show patch')),
5600 [('p', 'patch', None, _('show patch')),
5595 ('g', 'git', None, _('use git extended diff format')),
5601 ('g', 'git', None, _('use git extended diff format')),
5596 ] + templateopts,
5602 ] + templateopts,
5597 _('[-p] [-g]'))
5603 _('[-p] [-g]'))
5598 def tip(ui, repo, **opts):
5604 def tip(ui, repo, **opts):
5599 """show the tip revision
5605 """show the tip revision
5600
5606
5601 The tip revision (usually just called the tip) is the changeset
5607 The tip revision (usually just called the tip) is the changeset
5602 most recently added to the repository (and therefore the most
5608 most recently added to the repository (and therefore the most
5603 recently changed head).
5609 recently changed head).
5604
5610
5605 If you have just made a commit, that commit will be the tip. If
5611 If you have just made a commit, that commit will be the tip. If
5606 you have just pulled changes from another repository, the tip of
5612 you have just pulled changes from another repository, the tip of
5607 that repository becomes the current tip. The "tip" tag is special
5613 that repository becomes the current tip. The "tip" tag is special
5608 and cannot be renamed or assigned to a different changeset.
5614 and cannot be renamed or assigned to a different changeset.
5609
5615
5610 Returns 0 on success.
5616 Returns 0 on success.
5611 """
5617 """
5612 displayer = cmdutil.show_changeset(ui, repo, opts)
5618 displayer = cmdutil.show_changeset(ui, repo, opts)
5613 displayer.show(repo[len(repo) - 1])
5619 displayer.show(repo[len(repo) - 1])
5614 displayer.close()
5620 displayer.close()
5615
5621
5616 @command('unbundle',
5622 @command('unbundle',
5617 [('u', 'update', None,
5623 [('u', 'update', None,
5618 _('update to new branch head if changesets were unbundled'))],
5624 _('update to new branch head if changesets were unbundled'))],
5619 _('[-u] FILE...'))
5625 _('[-u] FILE...'))
5620 def unbundle(ui, repo, fname1, *fnames, **opts):
5626 def unbundle(ui, repo, fname1, *fnames, **opts):
5621 """apply one or more changegroup files
5627 """apply one or more changegroup files
5622
5628
5623 Apply one or more compressed changegroup files generated by the
5629 Apply one or more compressed changegroup files generated by the
5624 bundle command.
5630 bundle command.
5625
5631
5626 Returns 0 on success, 1 if an update has unresolved files.
5632 Returns 0 on success, 1 if an update has unresolved files.
5627 """
5633 """
5628 fnames = (fname1,) + fnames
5634 fnames = (fname1,) + fnames
5629
5635
5630 lock = repo.lock()
5636 lock = repo.lock()
5631 wc = repo['.']
5637 wc = repo['.']
5632 try:
5638 try:
5633 for fname in fnames:
5639 for fname in fnames:
5634 f = url.open(ui, fname)
5640 f = url.open(ui, fname)
5635 gen = changegroup.readbundle(f, fname)
5641 gen = changegroup.readbundle(f, fname)
5636 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5642 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5637 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5643 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5638 finally:
5644 finally:
5639 lock.release()
5645 lock.release()
5640 return postincoming(ui, repo, modheads, opts.get('update'), None)
5646 return postincoming(ui, repo, modheads, opts.get('update'), None)
5641
5647
5642 @command('^update|up|checkout|co',
5648 @command('^update|up|checkout|co',
5643 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5649 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5644 ('c', 'check', None,
5650 ('c', 'check', None,
5645 _('update across branches if no uncommitted changes')),
5651 _('update across branches if no uncommitted changes')),
5646 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5652 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5647 ('r', 'rev', '', _('revision'), _('REV'))],
5653 ('r', 'rev', '', _('revision'), _('REV'))],
5648 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5654 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5649 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5655 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5650 """update working directory (or switch revisions)
5656 """update working directory (or switch revisions)
5651
5657
5652 Update the repository's working directory to the specified
5658 Update the repository's working directory to the specified
5653 changeset. If no changeset is specified, update to the tip of the
5659 changeset. If no changeset is specified, update to the tip of the
5654 current named branch.
5660 current named branch.
5655
5661
5656 If the changeset is not a descendant of the working directory's
5662 If the changeset is not a descendant of the working directory's
5657 parent, the update is aborted. With the -c/--check option, the
5663 parent, the update is aborted. With the -c/--check option, the
5658 working directory is checked for uncommitted changes; if none are
5664 working directory is checked for uncommitted changes; if none are
5659 found, the working directory is updated to the specified
5665 found, the working directory is updated to the specified
5660 changeset.
5666 changeset.
5661
5667
5662 Update sets the working directory's parent revison to the specified
5668 Update sets the working directory's parent revison to the specified
5663 changeset (see :hg:`help parents`).
5669 changeset (see :hg:`help parents`).
5664
5670
5665 The following rules apply when the working directory contains
5671 The following rules apply when the working directory contains
5666 uncommitted changes:
5672 uncommitted changes:
5667
5673
5668 1. If neither -c/--check nor -C/--clean is specified, and if
5674 1. If neither -c/--check nor -C/--clean is specified, and if
5669 the requested changeset is an ancestor or descendant of
5675 the requested changeset is an ancestor or descendant of
5670 the working directory's parent, the uncommitted changes
5676 the working directory's parent, the uncommitted changes
5671 are merged into the requested changeset and the merged
5677 are merged into the requested changeset and the merged
5672 result is left uncommitted. If the requested changeset is
5678 result is left uncommitted. If the requested changeset is
5673 not an ancestor or descendant (that is, it is on another
5679 not an ancestor or descendant (that is, it is on another
5674 branch), the update is aborted and the uncommitted changes
5680 branch), the update is aborted and the uncommitted changes
5675 are preserved.
5681 are preserved.
5676
5682
5677 2. With the -c/--check option, the update is aborted and the
5683 2. With the -c/--check option, the update is aborted and the
5678 uncommitted changes are preserved.
5684 uncommitted changes are preserved.
5679
5685
5680 3. With the -C/--clean option, uncommitted changes are discarded and
5686 3. With the -C/--clean option, uncommitted changes are discarded and
5681 the working directory is updated to the requested changeset.
5687 the working directory is updated to the requested changeset.
5682
5688
5683 Use null as the changeset to remove the working directory (like
5689 Use null as the changeset to remove the working directory (like
5684 :hg:`clone -U`).
5690 :hg:`clone -U`).
5685
5691
5686 If you want to revert just one file to an older revision, use
5692 If you want to revert just one file to an older revision, use
5687 :hg:`revert [-r REV] NAME`.
5693 :hg:`revert [-r REV] NAME`.
5688
5694
5689 See :hg:`help dates` for a list of formats valid for -d/--date.
5695 See :hg:`help dates` for a list of formats valid for -d/--date.
5690
5696
5691 Returns 0 on success, 1 if there are unresolved files.
5697 Returns 0 on success, 1 if there are unresolved files.
5692 """
5698 """
5693 if rev and node:
5699 if rev and node:
5694 raise util.Abort(_("please specify just one revision"))
5700 raise util.Abort(_("please specify just one revision"))
5695
5701
5696 if rev is None or rev == '':
5702 if rev is None or rev == '':
5697 rev = node
5703 rev = node
5698
5704
5699 # if we defined a bookmark, we have to remember the original bookmark name
5705 # if we defined a bookmark, we have to remember the original bookmark name
5700 brev = rev
5706 brev = rev
5701 rev = scmutil.revsingle(repo, rev, rev).rev()
5707 rev = scmutil.revsingle(repo, rev, rev).rev()
5702
5708
5703 if check and clean:
5709 if check and clean:
5704 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5710 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5705
5711
5706 if check:
5712 if check:
5707 # we could use dirty() but we can ignore merge and branch trivia
5713 # we could use dirty() but we can ignore merge and branch trivia
5708 c = repo[None]
5714 c = repo[None]
5709 if c.modified() or c.added() or c.removed():
5715 if c.modified() or c.added() or c.removed():
5710 raise util.Abort(_("uncommitted local changes"))
5716 raise util.Abort(_("uncommitted local changes"))
5711
5717
5712 if date:
5718 if date:
5713 if rev is not None:
5719 if rev is not None:
5714 raise util.Abort(_("you can't specify a revision and a date"))
5720 raise util.Abort(_("you can't specify a revision and a date"))
5715 rev = cmdutil.finddate(ui, repo, date)
5721 rev = cmdutil.finddate(ui, repo, date)
5716
5722
5717 if clean or check:
5723 if clean or check:
5718 ret = hg.clean(repo, rev)
5724 ret = hg.clean(repo, rev)
5719 else:
5725 else:
5720 ret = hg.update(repo, rev)
5726 ret = hg.update(repo, rev)
5721
5727
5722 if brev in repo._bookmarks:
5728 if brev in repo._bookmarks:
5723 bookmarks.setcurrent(repo, brev)
5729 bookmarks.setcurrent(repo, brev)
5724
5730
5725 return ret
5731 return ret
5726
5732
5727 @command('verify', [])
5733 @command('verify', [])
5728 def verify(ui, repo):
5734 def verify(ui, repo):
5729 """verify the integrity of the repository
5735 """verify the integrity of the repository
5730
5736
5731 Verify the integrity of the current repository.
5737 Verify the integrity of the current repository.
5732
5738
5733 This will perform an extensive check of the repository's
5739 This will perform an extensive check of the repository's
5734 integrity, validating the hashes and checksums of each entry in
5740 integrity, validating the hashes and checksums of each entry in
5735 the changelog, manifest, and tracked files, as well as the
5741 the changelog, manifest, and tracked files, as well as the
5736 integrity of their crosslinks and indices.
5742 integrity of their crosslinks and indices.
5737
5743
5738 Returns 0 on success, 1 if errors are encountered.
5744 Returns 0 on success, 1 if errors are encountered.
5739 """
5745 """
5740 return hg.verify(repo)
5746 return hg.verify(repo)
5741
5747
5742 @command('version', [])
5748 @command('version', [])
5743 def version_(ui):
5749 def version_(ui):
5744 """output version and copyright information"""
5750 """output version and copyright information"""
5745 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5751 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5746 % util.version())
5752 % util.version())
5747 ui.status(_(
5753 ui.status(_(
5748 "(see http://mercurial.selenic.com for more information)\n"
5754 "(see http://mercurial.selenic.com for more information)\n"
5749 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5755 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5750 "This is free software; see the source for copying conditions. "
5756 "This is free software; see the source for copying conditions. "
5751 "There is NO\nwarranty; "
5757 "There is NO\nwarranty; "
5752 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5758 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5753 ))
5759 ))
5754
5760
5755 norepo = ("clone init version help debugcommands debugcomplete"
5761 norepo = ("clone init version help debugcommands debugcomplete"
5756 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5762 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5757 " debugknown debuggetbundle debugbundle")
5763 " debugknown debuggetbundle debugbundle")
5758 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5764 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5759 " debugdata debugindex debugindexdot debugrevlog")
5765 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,667 +1,664 b''
1 $ check_code="$TESTDIR"/../contrib/check-code.py
1 $ check_code="$TESTDIR"/../contrib/check-code.py
2 $ cd "$TESTDIR"/..
2 $ cd "$TESTDIR"/..
3
3
4 $ "$check_code" `hg manifest` || echo 'FAILURE IS NOT AN OPTION!!!'
4 $ "$check_code" `hg manifest` || echo 'FAILURE IS NOT AN OPTION!!!'
5
5
6 $ "$check_code" --warnings --nolineno --per-file=0 `hg manifest`
6 $ "$check_code" --warnings --nolineno --per-file=0 `hg manifest`
7 contrib/check-code.py:0:
7 contrib/check-code.py:0:
8 > # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
8 > # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
9 warning: line over 80 characters
9 warning: line over 80 characters
10 contrib/perf.py:0:
10 contrib/perf.py:0:
11 > except:
11 > except:
12 warning: naked except clause
12 warning: naked except clause
13 contrib/perf.py:0:
13 contrib/perf.py:0:
14 > #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, False))))
14 > #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, False))))
15 warning: line over 80 characters
15 warning: line over 80 characters
16 contrib/perf.py:0:
16 contrib/perf.py:0:
17 > except:
17 > except:
18 warning: naked except clause
18 warning: naked except clause
19 contrib/setup3k.py:0:
19 contrib/setup3k.py:0:
20 > except:
20 > except:
21 warning: naked except clause
21 warning: naked except clause
22 contrib/setup3k.py:0:
22 contrib/setup3k.py:0:
23 > except:
23 > except:
24 warning: naked except clause
24 warning: naked except clause
25 contrib/setup3k.py:0:
25 contrib/setup3k.py:0:
26 > except:
26 > except:
27 warning: naked except clause
27 warning: naked except clause
28 warning: naked except clause
28 warning: naked except clause
29 warning: naked except clause
29 warning: naked except clause
30 contrib/shrink-revlog.py:0:
30 contrib/shrink-revlog.py:0:
31 > '(You can delete those files when you are satisfied that your\n'
31 > '(You can delete those files when you are satisfied that your\n'
32 warning: line over 80 characters
32 warning: line over 80 characters
33 contrib/shrink-revlog.py:0:
33 contrib/shrink-revlog.py:0:
34 > ('', 'sort', 'reversepostorder', 'name of sort algorithm to use'),
34 > ('', 'sort', 'reversepostorder', 'name of sort algorithm to use'),
35 warning: line over 80 characters
35 warning: line over 80 characters
36 contrib/shrink-revlog.py:0:
36 contrib/shrink-revlog.py:0:
37 > [('', 'revlog', '', _('index (.i) file of the revlog to shrink')),
37 > [('', 'revlog', '', _('index (.i) file of the revlog to shrink')),
38 warning: line over 80 characters
38 warning: line over 80 characters
39 contrib/shrink-revlog.py:0:
39 contrib/shrink-revlog.py:0:
40 > except:
40 > except:
41 warning: naked except clause
41 warning: naked except clause
42 doc/gendoc.py:0:
42 doc/gendoc.py:0:
43 > "together with Mercurial. Help for other extensions is available "
43 > "together with Mercurial. Help for other extensions is available "
44 warning: line over 80 characters
44 warning: line over 80 characters
45 hgext/bugzilla.py:0:
45 hgext/bugzilla.py:0:
46 > raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
46 > raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
47 warning: line over 80 characters
47 warning: line over 80 characters
48 hgext/bugzilla.py:0:
48 hgext/bugzilla.py:0:
49 > bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
49 > bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
50 warning: line over 80 characters
50 warning: line over 80 characters
51 hgext/convert/__init__.py:0:
51 hgext/convert/__init__.py:0:
52 > ('', 'ancestors', '', _('show current changeset in ancestor branches')),
52 > ('', 'ancestors', '', _('show current changeset in ancestor branches')),
53 warning: line over 80 characters
53 warning: line over 80 characters
54 hgext/convert/bzr.py:0:
54 hgext/convert/bzr.py:0:
55 > except:
55 > except:
56 warning: naked except clause
56 warning: naked except clause
57 hgext/convert/common.py:0:
57 hgext/convert/common.py:0:
58 > except:
58 > except:
59 warning: naked except clause
59 warning: naked except clause
60 hgext/convert/common.py:0:
60 hgext/convert/common.py:0:
61 > except:
61 > except:
62 warning: naked except clause
62 warning: naked except clause
63 warning: naked except clause
63 warning: naked except clause
64 hgext/convert/convcmd.py:0:
64 hgext/convert/convcmd.py:0:
65 > except:
65 > except:
66 warning: naked except clause
66 warning: naked except clause
67 hgext/convert/cvs.py:0:
67 hgext/convert/cvs.py:0:
68 > # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
68 > # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
69 warning: line over 80 characters
69 warning: line over 80 characters
70 hgext/convert/cvsps.py:0:
70 hgext/convert/cvsps.py:0:
71 > assert len(branches) == 1, 'unknown branch: %s' % e.mergepoint
71 > assert len(branches) == 1, 'unknown branch: %s' % e.mergepoint
72 warning: line over 80 characters
72 warning: line over 80 characters
73 hgext/convert/cvsps.py:0:
73 hgext/convert/cvsps.py:0:
74 > ui.write('Ancestors: %s\n' % (','.join(r)))
74 > ui.write('Ancestors: %s\n' % (','.join(r)))
75 warning: unwrapped ui message
75 warning: unwrapped ui message
76 hgext/convert/cvsps.py:0:
76 hgext/convert/cvsps.py:0:
77 > ui.write('Parent: %d\n' % cs.parents[0].id)
77 > ui.write('Parent: %d\n' % cs.parents[0].id)
78 warning: unwrapped ui message
78 warning: unwrapped ui message
79 hgext/convert/cvsps.py:0:
79 hgext/convert/cvsps.py:0:
80 > ui.write('Parents: %s\n' %
80 > ui.write('Parents: %s\n' %
81 warning: unwrapped ui message
81 warning: unwrapped ui message
82 hgext/convert/cvsps.py:0:
82 hgext/convert/cvsps.py:0:
83 > except:
83 > except:
84 warning: naked except clause
84 warning: naked except clause
85 hgext/convert/cvsps.py:0:
85 hgext/convert/cvsps.py:0:
86 > ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
86 > ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
87 warning: unwrapped ui message
87 warning: unwrapped ui message
88 hgext/convert/cvsps.py:0:
88 hgext/convert/cvsps.py:0:
89 > ui.write('Author: %s\n' % cs.author)
89 > ui.write('Author: %s\n' % cs.author)
90 warning: unwrapped ui message
90 warning: unwrapped ui message
91 hgext/convert/cvsps.py:0:
91 hgext/convert/cvsps.py:0:
92 > ui.write('Branch: %s\n' % (cs.branch or 'HEAD'))
92 > ui.write('Branch: %s\n' % (cs.branch or 'HEAD'))
93 warning: unwrapped ui message
93 warning: unwrapped ui message
94 hgext/convert/cvsps.py:0:
94 hgext/convert/cvsps.py:0:
95 > ui.write('Date: %s\n' % util.datestr(cs.date,
95 > ui.write('Date: %s\n' % util.datestr(cs.date,
96 warning: unwrapped ui message
96 warning: unwrapped ui message
97 hgext/convert/cvsps.py:0:
97 hgext/convert/cvsps.py:0:
98 > ui.write('Log:\n')
98 > ui.write('Log:\n')
99 warning: unwrapped ui message
99 warning: unwrapped ui message
100 hgext/convert/cvsps.py:0:
100 hgext/convert/cvsps.py:0:
101 > ui.write('Members: \n')
101 > ui.write('Members: \n')
102 warning: unwrapped ui message
102 warning: unwrapped ui message
103 hgext/convert/cvsps.py:0:
103 hgext/convert/cvsps.py:0:
104 > ui.write('PatchSet %d \n' % cs.id)
104 > ui.write('PatchSet %d \n' % cs.id)
105 warning: unwrapped ui message
105 warning: unwrapped ui message
106 hgext/convert/cvsps.py:0:
106 hgext/convert/cvsps.py:0:
107 > ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
107 > ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
108 warning: unwrapped ui message
108 warning: unwrapped ui message
109 hgext/convert/git.py:0:
109 hgext/convert/git.py:0:
110 > except:
110 > except:
111 warning: naked except clause
111 warning: naked except clause
112 hgext/convert/git.py:0:
112 hgext/convert/git.py:0:
113 > fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
113 > fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
114 warning: line over 80 characters
114 warning: line over 80 characters
115 hgext/convert/hg.py:0:
115 hgext/convert/hg.py:0:
116 > # detect missing revlogs and abort on errors or populate self.ignored
116 > # detect missing revlogs and abort on errors or populate self.ignored
117 warning: line over 80 characters
117 warning: line over 80 characters
118 hgext/convert/hg.py:0:
118 hgext/convert/hg.py:0:
119 > except:
119 > except:
120 warning: naked except clause
120 warning: naked except clause
121 warning: naked except clause
121 warning: naked except clause
122 hgext/convert/hg.py:0:
122 hgext/convert/hg.py:0:
123 > except:
123 > except:
124 warning: naked except clause
124 warning: naked except clause
125 hgext/convert/monotone.py:0:
125 hgext/convert/monotone.py:0:
126 > except:
126 > except:
127 warning: naked except clause
127 warning: naked except clause
128 hgext/convert/monotone.py:0:
128 hgext/convert/monotone.py:0:
129 > except:
129 > except:
130 warning: naked except clause
130 warning: naked except clause
131 hgext/convert/subversion.py:0:
131 hgext/convert/subversion.py:0:
132 > raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
132 > raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
133 warning: line over 80 characters
133 warning: line over 80 characters
134 hgext/convert/subversion.py:0:
134 hgext/convert/subversion.py:0:
135 > except:
135 > except:
136 warning: naked except clause
136 warning: naked except clause
137 hgext/convert/subversion.py:0:
137 hgext/convert/subversion.py:0:
138 > args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
138 > args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
139 warning: line over 80 characters
139 warning: line over 80 characters
140 hgext/convert/subversion.py:0:
140 hgext/convert/subversion.py:0:
141 > self.trunkname = self.ui.config('convert', 'svn.trunk', 'trunk').strip('/')
141 > self.trunkname = self.ui.config('convert', 'svn.trunk', 'trunk').strip('/')
142 warning: line over 80 characters
142 warning: line over 80 characters
143 hgext/convert/subversion.py:0:
143 hgext/convert/subversion.py:0:
144 > except:
144 > except:
145 warning: naked except clause
145 warning: naked except clause
146 hgext/convert/subversion.py:0:
146 hgext/convert/subversion.py:0:
147 > def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
147 > def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
148 warning: line over 80 characters
148 warning: line over 80 characters
149 hgext/eol.py:0:
149 hgext/eol.py:0:
150 > if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
150 > if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
151 warning: line over 80 characters
151 warning: line over 80 characters
152 warning: line over 80 characters
152 warning: line over 80 characters
153 hgext/gpg.py:0:
153 hgext/gpg.py:0:
154 > except:
154 > except:
155 warning: naked except clause
155 warning: naked except clause
156 hgext/hgcia.py:0:
156 hgext/hgcia.py:0:
157 > except:
157 > except:
158 warning: naked except clause
158 warning: naked except clause
159 hgext/hgk.py:0:
159 hgext/hgk.py:0:
160 > ui.write("%s%s\n" % (prefix, description.replace('\n', nlprefix).strip()))
160 > ui.write("%s%s\n" % (prefix, description.replace('\n', nlprefix).strip()))
161 warning: line over 80 characters
161 warning: line over 80 characters
162 hgext/hgk.py:0:
162 hgext/hgk.py:0:
163 > ui.write("parent %s\n" % p)
163 > ui.write("parent %s\n" % p)
164 warning: unwrapped ui message
164 warning: unwrapped ui message
165 hgext/hgk.py:0:
165 hgext/hgk.py:0:
166 > ui.write('k=%s\nv=%s\n' % (name, value))
166 > ui.write('k=%s\nv=%s\n' % (name, value))
167 warning: unwrapped ui message
167 warning: unwrapped ui message
168 hgext/hgk.py:0:
168 hgext/hgk.py:0:
169 > ui.write("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1]))
169 > ui.write("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1]))
170 warning: unwrapped ui message
170 warning: unwrapped ui message
171 hgext/hgk.py:0:
171 hgext/hgk.py:0:
172 > ui.write("branch %s\n\n" % ctx.branch())
172 > ui.write("branch %s\n\n" % ctx.branch())
173 warning: unwrapped ui message
173 warning: unwrapped ui message
174 hgext/hgk.py:0:
174 hgext/hgk.py:0:
175 > ui.write("committer %s %s %s\n" % (committer, int(date[0]), date[1]))
175 > ui.write("committer %s %s %s\n" % (committer, int(date[0]), date[1]))
176 warning: unwrapped ui message
176 warning: unwrapped ui message
177 hgext/hgk.py:0:
177 hgext/hgk.py:0:
178 > ui.write("revision %d\n" % ctx.rev())
178 > ui.write("revision %d\n" % ctx.rev())
179 warning: unwrapped ui message
179 warning: unwrapped ui message
180 hgext/hgk.py:0:
180 hgext/hgk.py:0:
181 > ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
181 > ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
182 warning: line over 80 characters
182 warning: line over 80 characters
183 warning: unwrapped ui message
183 warning: unwrapped ui message
184 hgext/highlight/__init__.py:0:
184 hgext/highlight/__init__.py:0:
185 > extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
185 > extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
186 warning: line over 80 characters
186 warning: line over 80 characters
187 hgext/highlight/__init__.py:0:
187 hgext/highlight/__init__.py:0:
188 > return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
188 > return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
189 warning: line over 80 characters
189 warning: line over 80 characters
190 hgext/inotify/__init__.py:0:
190 hgext/inotify/__init__.py:0:
191 > if self._inotifyon and not ignored and not subrepos and not self._dirty:
191 > if self._inotifyon and not ignored and not subrepos and not self._dirty:
192 warning: line over 80 characters
192 warning: line over 80 characters
193 hgext/inotify/server.py:0:
193 hgext/inotify/server.py:0:
194 > except:
194 > except:
195 warning: naked except clause
195 warning: naked except clause
196 hgext/inotify/server.py:0:
196 hgext/inotify/server.py:0:
197 > except:
197 > except:
198 warning: naked except clause
198 warning: naked except clause
199 hgext/keyword.py:0:
199 hgext/keyword.py:0:
200 > ui.note("hg ci -m '%s'\n" % msg)
200 > ui.note("hg ci -m '%s'\n" % msg)
201 warning: unwrapped ui message
201 warning: unwrapped ui message
202 hgext/largefiles/overrides.py:0:
202 hgext/largefiles/overrides.py:0:
203 > # When we call orig below it creates the standins but we don't add them
203 > # When we call orig below it creates the standins but we don't add them
204 warning: line over 80 characters
204 warning: line over 80 characters
205 hgext/largefiles/reposetup.py:0:
205 hgext/largefiles/reposetup.py:0:
206 > if os.path.exists(self.wjoin(lfutil.standin(lfile))):
206 > if os.path.exists(self.wjoin(lfutil.standin(lfile))):
207 warning: line over 80 characters
207 warning: line over 80 characters
208 hgext/mq.py:0:
208 hgext/mq.py:0:
209 > raise util.Abort(_("%s does not have a parent recorded" % root))
209 > raise util.Abort(_("%s does not have a parent recorded" % root))
210 warning: line over 80 characters
210 warning: line over 80 characters
211 hgext/mq.py:0:
211 hgext/mq.py:0:
212 > raise util.Abort(_("cannot push --exact with applied patches"))
212 > raise util.Abort(_("cannot push --exact with applied patches"))
213 warning: line over 80 characters
213 warning: line over 80 characters
214 hgext/mq.py:0:
214 hgext/mq.py:0:
215 > raise util.Abort(_("cannot use --exact and --move together"))
215 > raise util.Abort(_("cannot use --exact and --move together"))
216 warning: line over 80 characters
216 warning: line over 80 characters
217 hgext/mq.py:0:
217 hgext/mq.py:0:
218 > self.ui.warn(_('Tag %s overrides mq patch of the same name\n')
218 > self.ui.warn(_('Tag %s overrides mq patch of the same name\n')
219 warning: line over 80 characters
219 warning: line over 80 characters
220 hgext/mq.py:0:
220 hgext/mq.py:0:
221 > except:
221 > except:
222 warning: naked except clause
222 warning: naked except clause
223 warning: naked except clause
223 warning: naked except clause
224 hgext/mq.py:0:
224 hgext/mq.py:0:
225 > except:
225 > except:
226 warning: naked except clause
226 warning: naked except clause
227 warning: naked except clause
227 warning: naked except clause
228 warning: naked except clause
228 warning: naked except clause
229 warning: naked except clause
229 warning: naked except clause
230 hgext/mq.py:0:
230 hgext/mq.py:0:
231 > raise util.Abort(_('cannot mix -l/--list with options or arguments'))
231 > raise util.Abort(_('cannot mix -l/--list with options or arguments'))
232 warning: line over 80 characters
232 warning: line over 80 characters
233 hgext/mq.py:0:
233 hgext/mq.py:0:
234 > raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
234 > raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
235 warning: line over 80 characters
235 warning: line over 80 characters
236 hgext/mq.py:0:
236 hgext/mq.py:0:
237 > ('', 'move', None, _('reorder patch series and apply only the patch'))],
237 > ('', 'move', None, _('reorder patch series and apply only the patch'))],
238 warning: line over 80 characters
238 warning: line over 80 characters
239 hgext/mq.py:0:
239 hgext/mq.py:0:
240 > ('U', 'noupdate', None, _('do not update the new working directories')),
240 > ('U', 'noupdate', None, _('do not update the new working directories')),
241 warning: line over 80 characters
241 warning: line over 80 characters
242 hgext/mq.py:0:
242 hgext/mq.py:0:
243 > ('e', 'exact', None, _('apply the target patch to its recorded parent')),
243 > ('e', 'exact', None, _('apply the target patch to its recorded parent')),
244 warning: line over 80 characters
244 warning: line over 80 characters
245 hgext/mq.py:0:
245 hgext/mq.py:0:
246 > except:
246 > except:
247 warning: naked except clause
247 warning: naked except clause
248 warning: naked except clause
248 warning: naked except clause
249 hgext/mq.py:0:
249 hgext/mq.py:0:
250 > ui.write("mq: %s\n" % ', '.join(m))
250 > ui.write("mq: %s\n" % ', '.join(m))
251 warning: unwrapped ui message
251 warning: unwrapped ui message
252 hgext/mq.py:0:
252 hgext/mq.py:0:
253 > repo.mq.qseries(repo, missing=opts.get('missing'), summary=opts.get('summary'))
253 > repo.mq.qseries(repo, missing=opts.get('missing'), summary=opts.get('summary'))
254 warning: line over 80 characters
254 warning: line over 80 characters
255 hgext/notify.py:0:
255 hgext/notify.py:0:
256 > ui.note(_('notify: suppressing notification for merge %d:%s\n') %
256 > ui.note(_('notify: suppressing notification for merge %d:%s\n') %
257 warning: line over 80 characters
257 warning: line over 80 characters
258 hgext/patchbomb.py:0:
258 hgext/patchbomb.py:0:
259 > binnode, seqno=idx, total=total)
259 > binnode, seqno=idx, total=total)
260 warning: line over 80 characters
260 warning: line over 80 characters
261 hgext/patchbomb.py:0:
261 hgext/patchbomb.py:0:
262 > except:
262 > except:
263 warning: naked except clause
263 warning: naked except clause
264 hgext/patchbomb.py:0:
264 hgext/patchbomb.py:0:
265 > ui.write('Subject: %s\n' % subj)
265 > ui.write('Subject: %s\n' % subj)
266 warning: unwrapped ui message
266 warning: unwrapped ui message
267 hgext/patchbomb.py:0:
267 hgext/patchbomb.py:0:
268 > p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
268 > p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
269 warning: line over 80 characters
269 warning: line over 80 characters
270 hgext/patchbomb.py:0:
270 hgext/patchbomb.py:0:
271 > ui.write('From: %s\n' % sender)
271 > ui.write('From: %s\n' % sender)
272 warning: unwrapped ui message
272 warning: unwrapped ui message
273 hgext/record.py:0:
273 hgext/record.py:0:
274 > ignoreblanklines=opts.get('ignore_blank_lines'))
274 > ignoreblanklines=opts.get('ignore_blank_lines'))
275 warning: line over 80 characters
275 warning: line over 80 characters
276 hgext/record.py:0:
276 hgext/record.py:0:
277 > ignorewsamount=opts.get('ignore_space_change'),
277 > ignorewsamount=opts.get('ignore_space_change'),
278 warning: line over 80 characters
278 warning: line over 80 characters
279 hgext/zeroconf/__init__.py:0:
279 hgext/zeroconf/__init__.py:0:
280 > publish(name, desc, path, util.getport(u.config("web", "port", 8000)))
280 > publish(name, desc, path, util.getport(u.config("web", "port", 8000)))
281 warning: line over 80 characters
281 warning: line over 80 characters
282 hgext/zeroconf/__init__.py:0:
282 hgext/zeroconf/__init__.py:0:
283 > except:
283 > except:
284 warning: naked except clause
284 warning: naked except clause
285 warning: naked except clause
285 warning: naked except clause
286 mercurial/bundlerepo.py:0:
286 mercurial/bundlerepo.py:0:
287 > is a bundlerepo for the obtained bundle when the original "other" is remote.
287 > is a bundlerepo for the obtained bundle when the original "other" is remote.
288 warning: line over 80 characters
288 warning: line over 80 characters
289 mercurial/bundlerepo.py:0:
289 mercurial/bundlerepo.py:0:
290 > "local" is a local repo from which to obtain the actual incoming changesets; it
290 > "local" is a local repo from which to obtain the actual incoming changesets; it
291 warning: line over 80 characters
291 warning: line over 80 characters
292 mercurial/bundlerepo.py:0:
292 mercurial/bundlerepo.py:0:
293 > tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force)
293 > tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force)
294 warning: line over 80 characters
294 warning: line over 80 characters
295 mercurial/commands.py:0:
295 mercurial/commands.py:0:
296 > " size " + basehdr + " link p1 p2 nodeid\n")
296 > " size " + basehdr + " link p1 p2 nodeid\n")
297 warning: line over 80 characters
297 warning: line over 80 characters
298 mercurial/commands.py:0:
298 mercurial/commands.py:0:
299 > raise util.Abort('cannot use localheads with old style discovery')
299 > raise util.Abort('cannot use localheads with old style discovery')
300 warning: line over 80 characters
300 warning: line over 80 characters
301 mercurial/commands.py:0:
301 mercurial/commands.py:0:
302 > ui.note('branch %s\n' % data)
302 > ui.note('branch %s\n' % data)
303 warning: unwrapped ui message
303 warning: unwrapped ui message
304 mercurial/commands.py:0:
304 mercurial/commands.py:0:
305 > ui.note('node %s\n' % str(data))
305 > ui.note('node %s\n' % str(data))
306 warning: unwrapped ui message
306 warning: unwrapped ui message
307 mercurial/commands.py:0:
307 mercurial/commands.py:0:
308 > ui.note('tag %s\n' % name)
308 > ui.note('tag %s\n' % name)
309 warning: unwrapped ui message
309 warning: unwrapped ui message
310 mercurial/commands.py:0:
310 mercurial/commands.py:0:
311 > ui.write("unpruned common: %s\n" % " ".join([short(n)
311 > ui.write("unpruned common: %s\n" % " ".join([short(n)
312 warning: unwrapped ui message
312 warning: unwrapped ui message
313 mercurial/commands.py:0:
313 mercurial/commands.py:0:
314 > yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
314 > yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
315 warning: line over 80 characters
315 warning: line over 80 characters
316 mercurial/commands.py:0:
316 mercurial/commands.py:0:
317 > yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
317 > yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
318 warning: line over 80 characters
318 warning: line over 80 characters
319 mercurial/commands.py:0:
319 mercurial/commands.py:0:
320 > except:
320 > except:
321 warning: naked except clause
321 warning: naked except clause
322 mercurial/commands.py:0:
322 mercurial/commands.py:0:
323 > raise util.Abort(_('tag names cannot consist entirely of whitespace'))
324 warning: line over 80 characters
325 mercurial/commands.py:0:
326 > ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
323 > ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
327 warning: line over 80 characters
324 warning: line over 80 characters
328 mercurial/commands.py:0:
325 mercurial/commands.py:0:
329 > ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
326 > ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
330 warning: unwrapped ui message
327 warning: unwrapped ui message
331 mercurial/commands.py:0:
328 mercurial/commands.py:0:
332 > ui.write("local is subset\n")
329 > ui.write("local is subset\n")
333 warning: unwrapped ui message
330 warning: unwrapped ui message
334 mercurial/commands.py:0:
331 mercurial/commands.py:0:
335 > ui.write("remote is subset\n")
332 > ui.write("remote is subset\n")
336 warning: unwrapped ui message
333 warning: unwrapped ui message
337 mercurial/commands.py:0:
334 mercurial/commands.py:0:
338 > ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
335 > ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
339 warning: line over 80 characters
336 warning: line over 80 characters
340 mercurial/commands.py:0:
337 mercurial/commands.py:0:
341 > ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
338 > ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
342 warning: line over 80 characters
339 warning: line over 80 characters
343 mercurial/commands.py:0:
340 mercurial/commands.py:0:
344 > ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
341 > ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
345 warning: line over 80 characters
342 warning: line over 80 characters
346 mercurial/commands.py:0:
343 mercurial/commands.py:0:
347 > ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
344 > ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
348 warning: line over 80 characters
345 warning: line over 80 characters
349 warning: unwrapped ui message
346 warning: unwrapped ui message
350 mercurial/commands.py:0:
347 mercurial/commands.py:0:
351 > ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
348 > ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
352 warning: unwrapped ui message
349 warning: unwrapped ui message
353 mercurial/commands.py:0:
350 mercurial/commands.py:0:
354 > ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
351 > ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
355 warning: unwrapped ui message
352 warning: unwrapped ui message
356 mercurial/commands.py:0:
353 mercurial/commands.py:0:
357 > cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
354 > cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
358 warning: line over 80 characters
355 warning: line over 80 characters
359 mercurial/commands.py:0:
356 mercurial/commands.py:0:
360 > except:
357 > except:
361 warning: naked except clause
358 warning: naked except clause
362 mercurial/commands.py:0:
359 mercurial/commands.py:0:
363 > revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
360 > revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
364 warning: line over 80 characters
361 warning: line over 80 characters
365 mercurial/commands.py:0:
362 mercurial/commands.py:0:
366 > ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
363 > ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
367 warning: unwrapped ui message
364 warning: unwrapped ui message
368 mercurial/commands.py:0:
365 mercurial/commands.py:0:
369 > ui.write("match: %s\n" % m(d[0]))
366 > ui.write("match: %s\n" % m(d[0]))
370 warning: unwrapped ui message
367 warning: unwrapped ui message
371 mercurial/commands.py:0:
368 mercurial/commands.py:0:
372 > ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
369 > ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
373 warning: unwrapped ui message
370 warning: unwrapped ui message
374 mercurial/commands.py:0:
371 mercurial/commands.py:0:
375 > ui.write('path %s\n' % k)
372 > ui.write('path %s\n' % k)
376 warning: unwrapped ui message
373 warning: unwrapped ui message
377 mercurial/commands.py:0:
374 mercurial/commands.py:0:
378 > ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
375 > ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
379 warning: unwrapped ui message
376 warning: unwrapped ui message
380 mercurial/commands.py:0:
377 mercurial/commands.py:0:
381 > Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
378 > Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
382 warning: line over 80 characters
379 warning: line over 80 characters
383 mercurial/commands.py:0:
380 mercurial/commands.py:0:
384 > remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
381 > remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
385 warning: line over 80 characters
382 warning: line over 80 characters
386 mercurial/commands.py:0:
383 mercurial/commands.py:0:
387 > ui.write("digraph G {\n")
384 > ui.write("digraph G {\n")
388 warning: unwrapped ui message
385 warning: unwrapped ui message
389 mercurial/commands.py:0:
386 mercurial/commands.py:0:
390 > ui.write("internal: %s %s\n" % d)
387 > ui.write("internal: %s %s\n" % d)
391 warning: unwrapped ui message
388 warning: unwrapped ui message
392 mercurial/commands.py:0:
389 mercurial/commands.py:0:
393 > ui.write("standard: %s\n" % util.datestr(d))
390 > ui.write("standard: %s\n" % util.datestr(d))
394 warning: unwrapped ui message
391 warning: unwrapped ui message
395 mercurial/commands.py:0:
392 mercurial/commands.py:0:
396 > ui.write('avg chain length : ' + fmt % avgchainlen)
393 > ui.write('avg chain length : ' + fmt % avgchainlen)
397 warning: unwrapped ui message
394 warning: unwrapped ui message
398 mercurial/commands.py:0:
395 mercurial/commands.py:0:
399 > ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
396 > ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
400 warning: unwrapped ui message
397 warning: unwrapped ui message
401 mercurial/commands.py:0:
398 mercurial/commands.py:0:
402 > ui.write('compression ratio : ' + fmt % compratio)
399 > ui.write('compression ratio : ' + fmt % compratio)
403 warning: unwrapped ui message
400 warning: unwrapped ui message
404 mercurial/commands.py:0:
401 mercurial/commands.py:0:
405 > ui.write('delta size (min/max/avg) : %d / %d / %d\n'
402 > ui.write('delta size (min/max/avg) : %d / %d / %d\n'
406 warning: unwrapped ui message
403 warning: unwrapped ui message
407 mercurial/commands.py:0:
404 mercurial/commands.py:0:
408 > ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
405 > ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
409 warning: unwrapped ui message
406 warning: unwrapped ui message
410 mercurial/commands.py:0:
407 mercurial/commands.py:0:
411 > ui.write('flags : %s\n' % ', '.join(flags))
408 > ui.write('flags : %s\n' % ', '.join(flags))
412 warning: unwrapped ui message
409 warning: unwrapped ui message
413 mercurial/commands.py:0:
410 mercurial/commands.py:0:
414 > ui.write('format : %d\n' % format)
411 > ui.write('format : %d\n' % format)
415 warning: unwrapped ui message
412 warning: unwrapped ui message
416 mercurial/commands.py:0:
413 mercurial/commands.py:0:
417 > ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
414 > ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
418 warning: unwrapped ui message
415 warning: unwrapped ui message
419 mercurial/commands.py:0:
416 mercurial/commands.py:0:
420 > ui.write('revision size : ' + fmt2 % totalsize)
417 > ui.write('revision size : ' + fmt2 % totalsize)
421 warning: unwrapped ui message
418 warning: unwrapped ui message
422 mercurial/commands.py:0:
419 mercurial/commands.py:0:
423 > ui.write('revisions : ' + fmt2 % numrevs)
420 > ui.write('revisions : ' + fmt2 % numrevs)
424 warning: unwrapped ui message
421 warning: unwrapped ui message
425 warning: unwrapped ui message
422 warning: unwrapped ui message
426 mercurial/commands.py:0:
423 mercurial/commands.py:0:
427 > ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
424 > ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
428 warning: unwrapped ui message
425 warning: unwrapped ui message
429 mercurial/commandserver.py:0:
426 mercurial/commandserver.py:0:
430 > # the ui here is really the repo ui so take its baseui so we don't end up
427 > # the ui here is really the repo ui so take its baseui so we don't end up
431 warning: line over 80 characters
428 warning: line over 80 characters
432 mercurial/context.py:0:
429 mercurial/context.py:0:
433 > return self._manifestdelta[path], self._manifestdelta.flags(path)
430 > return self._manifestdelta[path], self._manifestdelta.flags(path)
434 warning: line over 80 characters
431 warning: line over 80 characters
435 mercurial/dagparser.py:0:
432 mercurial/dagparser.py:0:
436 > raise util.Abort(_("invalid character in dag description: %s...") % s)
433 > raise util.Abort(_("invalid character in dag description: %s...") % s)
437 warning: line over 80 characters
434 warning: line over 80 characters
438 mercurial/dagparser.py:0:
435 mercurial/dagparser.py:0:
439 > >>> dagtext([('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))])
436 > >>> dagtext([('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))])
440 warning: line over 80 characters
437 warning: line over 80 characters
441 mercurial/dirstate.py:0:
438 mercurial/dirstate.py:0:
442 > if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
439 > if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
443 warning: line over 80 characters
440 warning: line over 80 characters
444 mercurial/discovery.py:0:
441 mercurial/discovery.py:0:
445 > repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
442 > repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
446 warning: line over 80 characters
443 warning: line over 80 characters
447 mercurial/discovery.py:0:
444 mercurial/discovery.py:0:
448 > If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
445 > If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
449 warning: line over 80 characters
446 warning: line over 80 characters
450 mercurial/discovery.py:0:
447 mercurial/discovery.py:0:
451 > def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
448 > def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
452 warning: line over 80 characters
449 warning: line over 80 characters
453 mercurial/dispatch.py:0:
450 mercurial/dispatch.py:0:
454 > " (.hg not found)") % os.getcwd())
451 > " (.hg not found)") % os.getcwd())
455 warning: line over 80 characters
452 warning: line over 80 characters
456 mercurial/dispatch.py:0:
453 mercurial/dispatch.py:0:
457 > aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
454 > aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
458 warning: line over 80 characters
455 warning: line over 80 characters
459 mercurial/dispatch.py:0:
456 mercurial/dispatch.py:0:
460 > except:
457 > except:
461 warning: naked except clause
458 warning: naked except clause
462 mercurial/dispatch.py:0:
459 mercurial/dispatch.py:0:
463 > return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
460 > return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
464 warning: line over 80 characters
461 warning: line over 80 characters
465 mercurial/dispatch.py:0:
462 mercurial/dispatch.py:0:
466 > def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None):
463 > def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None):
467 warning: line over 80 characters
464 warning: line over 80 characters
468 mercurial/dispatch.py:0:
465 mercurial/dispatch.py:0:
469 > except:
466 > except:
470 warning: naked except clause
467 warning: naked except clause
471 mercurial/hg.py:0:
468 mercurial/hg.py:0:
472 > except:
469 > except:
473 warning: naked except clause
470 warning: naked except clause
474 mercurial/hgweb/hgweb_mod.py:0:
471 mercurial/hgweb/hgweb_mod.py:0:
475 > self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
472 > self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
476 warning: line over 80 characters
473 warning: line over 80 characters
477 mercurial/keepalive.py:0:
474 mercurial/keepalive.py:0:
478 > except:
475 > except:
479 warning: naked except clause
476 warning: naked except clause
480 mercurial/keepalive.py:0:
477 mercurial/keepalive.py:0:
481 > except:
478 > except:
482 warning: naked except clause
479 warning: naked except clause
483 mercurial/localrepo.py:0:
480 mercurial/localrepo.py:0:
484 > hint=_("use --subrepos for recursive commit"))
481 > hint=_("use --subrepos for recursive commit"))
485 warning: line over 80 characters
482 warning: line over 80 characters
486 mercurial/localrepo.py:0:
483 mercurial/localrepo.py:0:
487 > # we return an integer indicating remote head count change
484 > # we return an integer indicating remote head count change
488 warning: line over 80 characters
485 warning: line over 80 characters
489 mercurial/localrepo.py:0:
486 mercurial/localrepo.py:0:
490 > raise util.Abort(_("empty or missing revlog for %s") % fname)
487 > raise util.Abort(_("empty or missing revlog for %s") % fname)
491 warning: line over 80 characters
488 warning: line over 80 characters
492 warning: line over 80 characters
489 warning: line over 80 characters
493 mercurial/localrepo.py:0:
490 mercurial/localrepo.py:0:
494 > if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
491 > if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
495 warning: line over 80 characters
492 warning: line over 80 characters
496 mercurial/localrepo.py:0:
493 mercurial/localrepo.py:0:
497 > self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
494 > self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
498 warning: line over 80 characters
495 warning: line over 80 characters
499 mercurial/localrepo.py:0:
496 mercurial/localrepo.py:0:
500 > # new requirements = old non-format requirements + new format-related
497 > # new requirements = old non-format requirements + new format-related
501 warning: line over 80 characters
498 warning: line over 80 characters
502 mercurial/localrepo.py:0:
499 mercurial/localrepo.py:0:
503 > except:
500 > except:
504 warning: naked except clause
501 warning: naked except clause
505 mercurial/localrepo.py:0:
502 mercurial/localrepo.py:0:
506 > """return status of files between two nodes or node and working directory
503 > """return status of files between two nodes or node and working directory
507 warning: line over 80 characters
504 warning: line over 80 characters
508 mercurial/localrepo.py:0:
505 mercurial/localrepo.py:0:
509 > '''Returns a tagscache object that contains various tags related caches.'''
506 > '''Returns a tagscache object that contains various tags related caches.'''
510 warning: line over 80 characters
507 warning: line over 80 characters
511 mercurial/manifest.py:0:
508 mercurial/manifest.py:0:
512 > return "".join(struct.pack(">lll", start, end, len(content)) + content
509 > return "".join(struct.pack(">lll", start, end, len(content)) + content
513 warning: line over 80 characters
510 warning: line over 80 characters
514 mercurial/merge.py:0:
511 mercurial/merge.py:0:
515 > subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
512 > subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
516 warning: line over 80 characters
513 warning: line over 80 characters
517 mercurial/patch.py:0:
514 mercurial/patch.py:0:
518 > modified, added, removed, copy, getfilectx, opts, losedata, prefix)
515 > modified, added, removed, copy, getfilectx, opts, losedata, prefix)
519 warning: line over 80 characters
516 warning: line over 80 characters
520 mercurial/patch.py:0:
517 mercurial/patch.py:0:
521 > diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
518 > diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
522 warning: line over 80 characters
519 warning: line over 80 characters
523 mercurial/patch.py:0:
520 mercurial/patch.py:0:
524 > output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
521 > output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
525 warning: line over 80 characters
522 warning: line over 80 characters
526 mercurial/patch.py:0:
523 mercurial/patch.py:0:
527 > except:
524 > except:
528 warning: naked except clause
525 warning: naked except clause
529 mercurial/pure/base85.py:0:
526 mercurial/pure/base85.py:0:
530 > raise OverflowError('Base85 overflow in hunk starting at byte %d' % i)
527 > raise OverflowError('Base85 overflow in hunk starting at byte %d' % i)
531 warning: line over 80 characters
528 warning: line over 80 characters
532 mercurial/pure/mpatch.py:0:
529 mercurial/pure/mpatch.py:0:
533 > frags.extend(reversed(new)) # what was left at the end
530 > frags.extend(reversed(new)) # what was left at the end
534 warning: line over 80 characters
531 warning: line over 80 characters
535 mercurial/repair.py:0:
532 mercurial/repair.py:0:
536 > except:
533 > except:
537 warning: naked except clause
534 warning: naked except clause
538 mercurial/repair.py:0:
535 mercurial/repair.py:0:
539 > except:
536 > except:
540 warning: naked except clause
537 warning: naked except clause
541 mercurial/revset.py:0:
538 mercurial/revset.py:0:
542 > elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
539 > elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
543 warning: line over 80 characters
540 warning: line over 80 characters
544 mercurial/revset.py:0:
541 mercurial/revset.py:0:
545 > Changesets that are the Nth ancestor (first parents only) of a changeset in set.
542 > Changesets that are the Nth ancestor (first parents only) of a changeset in set.
546 warning: line over 80 characters
543 warning: line over 80 characters
547 mercurial/scmutil.py:0:
544 mercurial/scmutil.py:0:
548 > raise util.Abort(_("path '%s' is inside nested repo %r") %
545 > raise util.Abort(_("path '%s' is inside nested repo %r") %
549 warning: line over 80 characters
546 warning: line over 80 characters
550 mercurial/scmutil.py:0:
547 mercurial/scmutil.py:0:
551 > "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
548 > "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
552 warning: line over 80 characters
549 warning: line over 80 characters
553 mercurial/scmutil.py:0:
550 mercurial/scmutil.py:0:
554 > elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
551 > elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
555 warning: line over 80 characters
552 warning: line over 80 characters
556 mercurial/setdiscovery.py:0:
553 mercurial/setdiscovery.py:0:
557 > # treat remote heads (and maybe own heads) as a first implicit sample response
554 > # treat remote heads (and maybe own heads) as a first implicit sample response
558 warning: line over 80 characters
555 warning: line over 80 characters
559 mercurial/setdiscovery.py:0:
556 mercurial/setdiscovery.py:0:
560 > undecided = dag.nodeset() # own nodes where I don't know if remote knows them
557 > undecided = dag.nodeset() # own nodes where I don't know if remote knows them
561 warning: line over 80 characters
558 warning: line over 80 characters
562 mercurial/similar.py:0:
559 mercurial/similar.py:0:
563 > repo.ui.progress(_('searching for similar files'), i, total=len(removed))
560 > repo.ui.progress(_('searching for similar files'), i, total=len(removed))
564 warning: line over 80 characters
561 warning: line over 80 characters
565 mercurial/simplemerge.py:0:
562 mercurial/simplemerge.py:0:
566 > for zmatch, zend, amatch, aend, bmatch, bend in self.find_sync_regions():
563 > for zmatch, zend, amatch, aend, bmatch, bend in self.find_sync_regions():
567 warning: line over 80 characters
564 warning: line over 80 characters
568 mercurial/sshrepo.py:0:
565 mercurial/sshrepo.py:0:
569 > self._abort(error.RepoError(_("no suitable response from remote hg")))
566 > self._abort(error.RepoError(_("no suitable response from remote hg")))
570 warning: line over 80 characters
567 warning: line over 80 characters
571 mercurial/sshrepo.py:0:
568 mercurial/sshrepo.py:0:
572 > except:
569 > except:
573 warning: naked except clause
570 warning: naked except clause
574 mercurial/subrepo.py:0:
571 mercurial/subrepo.py:0:
575 > other, self._repo = hg.clone(self._repo._subparent.ui, {}, other,
572 > other, self._repo = hg.clone(self._repo._subparent.ui, {}, other,
576 warning: line over 80 characters
573 warning: line over 80 characters
577 mercurial/subrepo.py:0:
574 mercurial/subrepo.py:0:
578 > msg = (_(' subrepository sources for %s differ (in checked out version)\n'
575 > msg = (_(' subrepository sources for %s differ (in checked out version)\n'
579 warning: line over 80 characters
576 warning: line over 80 characters
580 mercurial/transaction.py:0:
577 mercurial/transaction.py:0:
581 > except:
578 > except:
582 warning: naked except clause
579 warning: naked except clause
583 mercurial/ui.py:0:
580 mercurial/ui.py:0:
584 > traceback.print_exception(exc[0], exc[1], exc[2], file=self.ferr)
581 > traceback.print_exception(exc[0], exc[1], exc[2], file=self.ferr)
585 warning: line over 80 characters
582 warning: line over 80 characters
586 mercurial/url.py:0:
583 mercurial/url.py:0:
587 > conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
584 > conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
588 warning: line over 80 characters
585 warning: line over 80 characters
589 mercurial/util.py:0:
586 mercurial/util.py:0:
590 > except:
587 > except:
591 warning: naked except clause
588 warning: naked except clause
592 mercurial/util.py:0:
589 mercurial/util.py:0:
593 > except:
590 > except:
594 warning: naked except clause
591 warning: naked except clause
595 mercurial/verify.py:0:
592 mercurial/verify.py:0:
596 > except:
593 > except:
597 warning: naked except clause
594 warning: naked except clause
598 mercurial/verify.py:0:
595 mercurial/verify.py:0:
599 > except:
596 > except:
600 warning: naked except clause
597 warning: naked except clause
601 mercurial/wireproto.py:0:
598 mercurial/wireproto.py:0:
602 > # Assuming the future to be filled with the result from the batched request
599 > # Assuming the future to be filled with the result from the batched request
603 warning: line over 80 characters
600 warning: line over 80 characters
604 mercurial/wireproto.py:0:
601 mercurial/wireproto.py:0:
605 > '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
602 > '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
606 warning: line over 80 characters
603 warning: line over 80 characters
607 mercurial/wireproto.py:0:
604 mercurial/wireproto.py:0:
608 > All methods invoked on instances of this class are simply queued and return a
605 > All methods invoked on instances of this class are simply queued and return a
609 warning: line over 80 characters
606 warning: line over 80 characters
610 mercurial/wireproto.py:0:
607 mercurial/wireproto.py:0:
611 > The decorator returns a function which wraps this coroutine as a plain method,
608 > The decorator returns a function which wraps this coroutine as a plain method,
612 warning: line over 80 characters
609 warning: line over 80 characters
613 setup.py:0:
610 setup.py:0:
614 > raise SystemExit("Python headers are required to build Mercurial")
611 > raise SystemExit("Python headers are required to build Mercurial")
615 warning: line over 80 characters
612 warning: line over 80 characters
616 setup.py:0:
613 setup.py:0:
617 > except:
614 > except:
618 warning: naked except clause
615 warning: naked except clause
619 setup.py:0:
616 setup.py:0:
620 > # build_py), it will not find osutil & friends, thinking that those modules are
617 > # build_py), it will not find osutil & friends, thinking that those modules are
621 warning: line over 80 characters
618 warning: line over 80 characters
622 setup.py:0:
619 setup.py:0:
623 > except:
620 > except:
624 warning: naked except clause
621 warning: naked except clause
625 warning: naked except clause
622 warning: naked except clause
626 setup.py:0:
623 setup.py:0:
627 > isironpython = platform.python_implementation().lower().find("ironpython") != -1
624 > isironpython = platform.python_implementation().lower().find("ironpython") != -1
628 warning: line over 80 characters
625 warning: line over 80 characters
629 setup.py:0:
626 setup.py:0:
630 > except:
627 > except:
631 warning: naked except clause
628 warning: naked except clause
632 warning: naked except clause
629 warning: naked except clause
633 warning: naked except clause
630 warning: naked except clause
634 tests/autodiff.py:0:
631 tests/autodiff.py:0:
635 > ui.write('data lost for: %s\n' % fn)
632 > ui.write('data lost for: %s\n' % fn)
636 warning: unwrapped ui message
633 warning: unwrapped ui message
637 tests/run-tests.py:0:
634 tests/run-tests.py:0:
638 > except:
635 > except:
639 warning: naked except clause
636 warning: naked except clause
640 tests/test-commandserver.py:0:
637 tests/test-commandserver.py:0:
641 > 'hooks.pre-identify=python:test-commandserver.hook', 'id'],
638 > 'hooks.pre-identify=python:test-commandserver.hook', 'id'],
642 warning: line over 80 characters
639 warning: line over 80 characters
643 tests/test-commandserver.py:0:
640 tests/test-commandserver.py:0:
644 > # the cached repo local hgrc contains ui.foo=bar, so showconfig should show it
641 > # the cached repo local hgrc contains ui.foo=bar, so showconfig should show it
645 warning: line over 80 characters
642 warning: line over 80 characters
646 tests/test-commandserver.py:0:
643 tests/test-commandserver.py:0:
647 > print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', data))
644 > print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', data))
648 warning: line over 80 characters
645 warning: line over 80 characters
649 tests/test-filecache.py:0:
646 tests/test-filecache.py:0:
650 > except:
647 > except:
651 warning: naked except clause
648 warning: naked except clause
652 tests/test-filecache.py:0:
649 tests/test-filecache.py:0:
653 > if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
650 > if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
654 warning: line over 80 characters
651 warning: line over 80 characters
655 tests/test-ui-color.py:0:
652 tests/test-ui-color.py:0:
656 > testui.warn('warning\n')
653 > testui.warn('warning\n')
657 warning: unwrapped ui message
654 warning: unwrapped ui message
658 tests/test-ui-color.py:0:
655 tests/test-ui-color.py:0:
659 > testui.write('buffered\n')
656 > testui.write('buffered\n')
660 warning: unwrapped ui message
657 warning: unwrapped ui message
661 tests/test-walkrepo.py:0:
658 tests/test-walkrepo.py:0:
662 > print "Found %d repositories when I should have found 2" % (len(reposet),)
659 > print "Found %d repositories when I should have found 2" % (len(reposet),)
663 warning: line over 80 characters
660 warning: line over 80 characters
664 tests/test-walkrepo.py:0:
661 tests/test-walkrepo.py:0:
665 > print "Found %d repositories when I should have found 3" % (len(reposet),)
662 > print "Found %d repositories when I should have found 3" % (len(reposet),)
666 warning: line over 80 characters
663 warning: line over 80 characters
667 [1]
664 [1]
General Comments 0
You need to be logged in to leave comments. Login now