##// END OF EJS Templates
debugbuilddag: lock repo before starting transaction
Mads Kiilerich -
r15875:7eca9db6 default
parent child Browse files
Show More
@@ -1,5757 +1,5759 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 tr = repo.transaction("builddag")
1371 lock = tr = None
1372 try:
1372 try:
1373 lock = repo.lock()
1374 tr = repo.transaction("builddag")
1373
1375
1374 at = -1
1376 at = -1
1375 atbranch = 'default'
1377 atbranch = 'default'
1376 nodeids = []
1378 nodeids = []
1377 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1379 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1378 for type, data in dagparser.parsedag(text):
1380 for type, data in dagparser.parsedag(text):
1379 if type == 'n':
1381 if type == 'n':
1380 ui.note('node %s\n' % str(data))
1382 ui.note('node %s\n' % str(data))
1381 id, ps = data
1383 id, ps = data
1382
1384
1383 files = []
1385 files = []
1384 fctxs = {}
1386 fctxs = {}
1385
1387
1386 p2 = None
1388 p2 = None
1387 if mergeable_file:
1389 if mergeable_file:
1388 fn = "mf"
1390 fn = "mf"
1389 p1 = repo[ps[0]]
1391 p1 = repo[ps[0]]
1390 if len(ps) > 1:
1392 if len(ps) > 1:
1391 p2 = repo[ps[1]]
1393 p2 = repo[ps[1]]
1392 pa = p1.ancestor(p2)
1394 pa = p1.ancestor(p2)
1393 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]
1394 m3 = simplemerge.Merge3Text(base, local, other)
1396 m3 = simplemerge.Merge3Text(base, local, other)
1395 ml = [l.strip() for l in m3.merge_lines()]
1397 ml = [l.strip() for l in m3.merge_lines()]
1396 ml.append("")
1398 ml.append("")
1397 elif at > 0:
1399 elif at > 0:
1398 ml = p1[fn].data().split("\n")
1400 ml = p1[fn].data().split("\n")
1399 else:
1401 else:
1400 ml = initialmergedlines
1402 ml = initialmergedlines
1401 ml[id * linesperrev] += " r%i" % id
1403 ml[id * linesperrev] += " r%i" % id
1402 mergedtext = "\n".join(ml)
1404 mergedtext = "\n".join(ml)
1403 files.append(fn)
1405 files.append(fn)
1404 fctxs[fn] = context.memfilectx(fn, mergedtext)
1406 fctxs[fn] = context.memfilectx(fn, mergedtext)
1405
1407
1406 if overwritten_file:
1408 if overwritten_file:
1407 fn = "of"
1409 fn = "of"
1408 files.append(fn)
1410 files.append(fn)
1409 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1411 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1410
1412
1411 if new_file:
1413 if new_file:
1412 fn = "nf%i" % id
1414 fn = "nf%i" % id
1413 files.append(fn)
1415 files.append(fn)
1414 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1416 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1415 if len(ps) > 1:
1417 if len(ps) > 1:
1416 if not p2:
1418 if not p2:
1417 p2 = repo[ps[1]]
1419 p2 = repo[ps[1]]
1418 for fn in p2:
1420 for fn in p2:
1419 if fn.startswith("nf"):
1421 if fn.startswith("nf"):
1420 files.append(fn)
1422 files.append(fn)
1421 fctxs[fn] = p2[fn]
1423 fctxs[fn] = p2[fn]
1422
1424
1423 def fctxfn(repo, cx, path):
1425 def fctxfn(repo, cx, path):
1424 return fctxs.get(path)
1426 return fctxs.get(path)
1425
1427
1426 if len(ps) == 0 or ps[0] < 0:
1428 if len(ps) == 0 or ps[0] < 0:
1427 pars = [None, None]
1429 pars = [None, None]
1428 elif len(ps) == 1:
1430 elif len(ps) == 1:
1429 pars = [nodeids[ps[0]], None]
1431 pars = [nodeids[ps[0]], None]
1430 else:
1432 else:
1431 pars = [nodeids[p] for p in ps]
1433 pars = [nodeids[p] for p in ps]
1432 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1434 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1433 date=(id, 0),
1435 date=(id, 0),
1434 user="debugbuilddag",
1436 user="debugbuilddag",
1435 extra={'branch': atbranch})
1437 extra={'branch': atbranch})
1436 nodeid = repo.commitctx(cx)
1438 nodeid = repo.commitctx(cx)
1437 nodeids.append(nodeid)
1439 nodeids.append(nodeid)
1438 at = id
1440 at = id
1439 elif type == 'l':
1441 elif type == 'l':
1440 id, name = data
1442 id, name = data
1441 ui.note('tag %s\n' % name)
1443 ui.note('tag %s\n' % name)
1442 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1444 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1443 elif type == 'a':
1445 elif type == 'a':
1444 ui.note('branch %s\n' % data)
1446 ui.note('branch %s\n' % data)
1445 atbranch = data
1447 atbranch = data
1446 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1448 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1447 tr.close()
1449 tr.close()
1450
1451 if tags:
1452 repo.opener.write("localtags", "".join(tags))
1448 finally:
1453 finally:
1449 ui.progress(_('building'), None)
1454 ui.progress(_('building'), None)
1450 tr.release()
1455 release(tr, lock)
1451
1452 if tags:
1453 repo.opener.write("localtags", "".join(tags))
1454
1456
1455 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1457 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1456 def debugbundle(ui, bundlepath, all=None, **opts):
1458 def debugbundle(ui, bundlepath, all=None, **opts):
1457 """lists the contents of a bundle"""
1459 """lists the contents of a bundle"""
1458 f = url.open(ui, bundlepath)
1460 f = url.open(ui, bundlepath)
1459 try:
1461 try:
1460 gen = changegroup.readbundle(f, bundlepath)
1462 gen = changegroup.readbundle(f, bundlepath)
1461 if all:
1463 if all:
1462 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")
1463
1465
1464 def showchunks(named):
1466 def showchunks(named):
1465 ui.write("\n%s\n" % named)
1467 ui.write("\n%s\n" % named)
1466 chain = None
1468 chain = None
1467 while True:
1469 while True:
1468 chunkdata = gen.deltachunk(chain)
1470 chunkdata = gen.deltachunk(chain)
1469 if not chunkdata:
1471 if not chunkdata:
1470 break
1472 break
1471 node = chunkdata['node']
1473 node = chunkdata['node']
1472 p1 = chunkdata['p1']
1474 p1 = chunkdata['p1']
1473 p2 = chunkdata['p2']
1475 p2 = chunkdata['p2']
1474 cs = chunkdata['cs']
1476 cs = chunkdata['cs']
1475 deltabase = chunkdata['deltabase']
1477 deltabase = chunkdata['deltabase']
1476 delta = chunkdata['delta']
1478 delta = chunkdata['delta']
1477 ui.write("%s %s %s %s %s %s\n" %
1479 ui.write("%s %s %s %s %s %s\n" %
1478 (hex(node), hex(p1), hex(p2),
1480 (hex(node), hex(p1), hex(p2),
1479 hex(cs), hex(deltabase), len(delta)))
1481 hex(cs), hex(deltabase), len(delta)))
1480 chain = node
1482 chain = node
1481
1483
1482 chunkdata = gen.changelogheader()
1484 chunkdata = gen.changelogheader()
1483 showchunks("changelog")
1485 showchunks("changelog")
1484 chunkdata = gen.manifestheader()
1486 chunkdata = gen.manifestheader()
1485 showchunks("manifest")
1487 showchunks("manifest")
1486 while True:
1488 while True:
1487 chunkdata = gen.filelogheader()
1489 chunkdata = gen.filelogheader()
1488 if not chunkdata:
1490 if not chunkdata:
1489 break
1491 break
1490 fname = chunkdata['filename']
1492 fname = chunkdata['filename']
1491 showchunks(fname)
1493 showchunks(fname)
1492 else:
1494 else:
1493 chunkdata = gen.changelogheader()
1495 chunkdata = gen.changelogheader()
1494 chain = None
1496 chain = None
1495 while True:
1497 while True:
1496 chunkdata = gen.deltachunk(chain)
1498 chunkdata = gen.deltachunk(chain)
1497 if not chunkdata:
1499 if not chunkdata:
1498 break
1500 break
1499 node = chunkdata['node']
1501 node = chunkdata['node']
1500 ui.write("%s\n" % hex(node))
1502 ui.write("%s\n" % hex(node))
1501 chain = node
1503 chain = node
1502 finally:
1504 finally:
1503 f.close()
1505 f.close()
1504
1506
1505 @command('debugcheckstate', [], '')
1507 @command('debugcheckstate', [], '')
1506 def debugcheckstate(ui, repo):
1508 def debugcheckstate(ui, repo):
1507 """validate the correctness of the current dirstate"""
1509 """validate the correctness of the current dirstate"""
1508 parent1, parent2 = repo.dirstate.parents()
1510 parent1, parent2 = repo.dirstate.parents()
1509 m1 = repo[parent1].manifest()
1511 m1 = repo[parent1].manifest()
1510 m2 = repo[parent2].manifest()
1512 m2 = repo[parent2].manifest()
1511 errors = 0
1513 errors = 0
1512 for f in repo.dirstate:
1514 for f in repo.dirstate:
1513 state = repo.dirstate[f]
1515 state = repo.dirstate[f]
1514 if state in "nr" and f not in m1:
1516 if state in "nr" and f not in m1:
1515 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))
1516 errors += 1
1518 errors += 1
1517 if state in "a" and f in m1:
1519 if state in "a" and f in m1:
1518 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))
1519 errors += 1
1521 errors += 1
1520 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:
1521 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") %
1522 (f, state))
1524 (f, state))
1523 errors += 1
1525 errors += 1
1524 for f in m1:
1526 for f in m1:
1525 state = repo.dirstate[f]
1527 state = repo.dirstate[f]
1526 if state not in "nrm":
1528 if state not in "nrm":
1527 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))
1528 errors += 1
1530 errors += 1
1529 if errors:
1531 if errors:
1530 error = _(".hg/dirstate inconsistent with current parent's manifest")
1532 error = _(".hg/dirstate inconsistent with current parent's manifest")
1531 raise util.Abort(error)
1533 raise util.Abort(error)
1532
1534
1533 @command('debugcommands', [], _('[COMMAND]'))
1535 @command('debugcommands', [], _('[COMMAND]'))
1534 def debugcommands(ui, cmd='', *args):
1536 def debugcommands(ui, cmd='', *args):
1535 """list all available commands and options"""
1537 """list all available commands and options"""
1536 for cmd, vals in sorted(table.iteritems()):
1538 for cmd, vals in sorted(table.iteritems()):
1537 cmd = cmd.split('|')[0].strip('^')
1539 cmd = cmd.split('|')[0].strip('^')
1538 opts = ', '.join([i[1] for i in vals[1]])
1540 opts = ', '.join([i[1] for i in vals[1]])
1539 ui.write('%s: %s\n' % (cmd, opts))
1541 ui.write('%s: %s\n' % (cmd, opts))
1540
1542
1541 @command('debugcomplete',
1543 @command('debugcomplete',
1542 [('o', 'options', None, _('show the command options'))],
1544 [('o', 'options', None, _('show the command options'))],
1543 _('[-o] CMD'))
1545 _('[-o] CMD'))
1544 def debugcomplete(ui, cmd='', **opts):
1546 def debugcomplete(ui, cmd='', **opts):
1545 """returns the completion list associated with the given command"""
1547 """returns the completion list associated with the given command"""
1546
1548
1547 if opts.get('options'):
1549 if opts.get('options'):
1548 options = []
1550 options = []
1549 otables = [globalopts]
1551 otables = [globalopts]
1550 if cmd:
1552 if cmd:
1551 aliases, entry = cmdutil.findcmd(cmd, table, False)
1553 aliases, entry = cmdutil.findcmd(cmd, table, False)
1552 otables.append(entry[1])
1554 otables.append(entry[1])
1553 for t in otables:
1555 for t in otables:
1554 for o in t:
1556 for o in t:
1555 if "(DEPRECATED)" in o[3]:
1557 if "(DEPRECATED)" in o[3]:
1556 continue
1558 continue
1557 if o[0]:
1559 if o[0]:
1558 options.append('-%s' % o[0])
1560 options.append('-%s' % o[0])
1559 options.append('--%s' % o[1])
1561 options.append('--%s' % o[1])
1560 ui.write("%s\n" % "\n".join(options))
1562 ui.write("%s\n" % "\n".join(options))
1561 return
1563 return
1562
1564
1563 cmdlist = cmdutil.findpossible(cmd, table)
1565 cmdlist = cmdutil.findpossible(cmd, table)
1564 if ui.verbose:
1566 if ui.verbose:
1565 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1567 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1566 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1568 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1567
1569
1568 @command('debugdag',
1570 @command('debugdag',
1569 [('t', 'tags', None, _('use tags as labels')),
1571 [('t', 'tags', None, _('use tags as labels')),
1570 ('b', 'branches', None, _('annotate with branch names')),
1572 ('b', 'branches', None, _('annotate with branch names')),
1571 ('', 'dots', None, _('use dots for runs')),
1573 ('', 'dots', None, _('use dots for runs')),
1572 ('s', 'spaces', None, _('separate elements by spaces'))],
1574 ('s', 'spaces', None, _('separate elements by spaces'))],
1573 _('[OPTION]... [FILE [REV]...]'))
1575 _('[OPTION]... [FILE [REV]...]'))
1574 def debugdag(ui, repo, file_=None, *revs, **opts):
1576 def debugdag(ui, repo, file_=None, *revs, **opts):
1575 """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
1576
1578
1577 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
1578 revision numbers, they get labelled in the output as rN.
1580 revision numbers, they get labelled in the output as rN.
1579
1581
1580 Otherwise, the changelog DAG of the current repo is emitted.
1582 Otherwise, the changelog DAG of the current repo is emitted.
1581 """
1583 """
1582 spaces = opts.get('spaces')
1584 spaces = opts.get('spaces')
1583 dots = opts.get('dots')
1585 dots = opts.get('dots')
1584 if file_:
1586 if file_:
1585 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1587 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1586 revs = set((int(r) for r in revs))
1588 revs = set((int(r) for r in revs))
1587 def events():
1589 def events():
1588 for r in rlog:
1590 for r in rlog:
1589 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)))
1590 if r in revs:
1592 if r in revs:
1591 yield 'l', (r, "r%i" % r)
1593 yield 'l', (r, "r%i" % r)
1592 elif repo:
1594 elif repo:
1593 cl = repo.changelog
1595 cl = repo.changelog
1594 tags = opts.get('tags')
1596 tags = opts.get('tags')
1595 branches = opts.get('branches')
1597 branches = opts.get('branches')
1596 if tags:
1598 if tags:
1597 labels = {}
1599 labels = {}
1598 for l, n in repo.tags().items():
1600 for l, n in repo.tags().items():
1599 labels.setdefault(cl.rev(n), []).append(l)
1601 labels.setdefault(cl.rev(n), []).append(l)
1600 def events():
1602 def events():
1601 b = "default"
1603 b = "default"
1602 for r in cl:
1604 for r in cl:
1603 if branches:
1605 if branches:
1604 newb = cl.read(cl.node(r))[5]['branch']
1606 newb = cl.read(cl.node(r))[5]['branch']
1605 if newb != b:
1607 if newb != b:
1606 yield 'a', newb
1608 yield 'a', newb
1607 b = newb
1609 b = newb
1608 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)))
1609 if tags:
1611 if tags:
1610 ls = labels.get(r)
1612 ls = labels.get(r)
1611 if ls:
1613 if ls:
1612 for l in ls:
1614 for l in ls:
1613 yield 'l', (r, l)
1615 yield 'l', (r, l)
1614 else:
1616 else:
1615 raise util.Abort(_('need repo for changelog dag'))
1617 raise util.Abort(_('need repo for changelog dag'))
1616
1618
1617 for line in dagparser.dagtextlines(events(),
1619 for line in dagparser.dagtextlines(events(),
1618 addspaces=spaces,
1620 addspaces=spaces,
1619 wraplabels=True,
1621 wraplabels=True,
1620 wrapannotations=True,
1622 wrapannotations=True,
1621 wrapnonlinear=dots,
1623 wrapnonlinear=dots,
1622 usedots=dots,
1624 usedots=dots,
1623 maxlinewidth=70):
1625 maxlinewidth=70):
1624 ui.write(line)
1626 ui.write(line)
1625 ui.write("\n")
1627 ui.write("\n")
1626
1628
1627 @command('debugdata',
1629 @command('debugdata',
1628 [('c', 'changelog', False, _('open changelog')),
1630 [('c', 'changelog', False, _('open changelog')),
1629 ('m', 'manifest', False, _('open manifest'))],
1631 ('m', 'manifest', False, _('open manifest'))],
1630 _('-c|-m|FILE REV'))
1632 _('-c|-m|FILE REV'))
1631 def debugdata(ui, repo, file_, rev = None, **opts):
1633 def debugdata(ui, repo, file_, rev = None, **opts):
1632 """dump the contents of a data file revision"""
1634 """dump the contents of a data file revision"""
1633 if opts.get('changelog') or opts.get('manifest'):
1635 if opts.get('changelog') or opts.get('manifest'):
1634 file_, rev = None, file_
1636 file_, rev = None, file_
1635 elif rev is None:
1637 elif rev is None:
1636 raise error.CommandError('debugdata', _('invalid arguments'))
1638 raise error.CommandError('debugdata', _('invalid arguments'))
1637 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1639 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1638 try:
1640 try:
1639 ui.write(r.revision(r.lookup(rev)))
1641 ui.write(r.revision(r.lookup(rev)))
1640 except KeyError:
1642 except KeyError:
1641 raise util.Abort(_('invalid revision identifier %s') % rev)
1643 raise util.Abort(_('invalid revision identifier %s') % rev)
1642
1644
1643 @command('debugdate',
1645 @command('debugdate',
1644 [('e', 'extended', None, _('try extended date formats'))],
1646 [('e', 'extended', None, _('try extended date formats'))],
1645 _('[-e] DATE [RANGE]'))
1647 _('[-e] DATE [RANGE]'))
1646 def debugdate(ui, date, range=None, **opts):
1648 def debugdate(ui, date, range=None, **opts):
1647 """parse and display a date"""
1649 """parse and display a date"""
1648 if opts["extended"]:
1650 if opts["extended"]:
1649 d = util.parsedate(date, util.extendeddateformats)
1651 d = util.parsedate(date, util.extendeddateformats)
1650 else:
1652 else:
1651 d = util.parsedate(date)
1653 d = util.parsedate(date)
1652 ui.write("internal: %s %s\n" % d)
1654 ui.write("internal: %s %s\n" % d)
1653 ui.write("standard: %s\n" % util.datestr(d))
1655 ui.write("standard: %s\n" % util.datestr(d))
1654 if range:
1656 if range:
1655 m = util.matchdate(range)
1657 m = util.matchdate(range)
1656 ui.write("match: %s\n" % m(d[0]))
1658 ui.write("match: %s\n" % m(d[0]))
1657
1659
1658 @command('debugdiscovery',
1660 @command('debugdiscovery',
1659 [('', 'old', None, _('use old-style discovery')),
1661 [('', 'old', None, _('use old-style discovery')),
1660 ('', 'nonheads', None,
1662 ('', 'nonheads', None,
1661 _('use old-style discovery with non-heads included')),
1663 _('use old-style discovery with non-heads included')),
1662 ] + remoteopts,
1664 ] + remoteopts,
1663 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1665 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1664 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1666 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1665 """runs the changeset discovery protocol in isolation"""
1667 """runs the changeset discovery protocol in isolation"""
1666 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1668 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1667 remote = hg.peer(repo, opts, remoteurl)
1669 remote = hg.peer(repo, opts, remoteurl)
1668 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1670 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1669
1671
1670 # make sure tests are repeatable
1672 # make sure tests are repeatable
1671 random.seed(12323)
1673 random.seed(12323)
1672
1674
1673 def doit(localheads, remoteheads):
1675 def doit(localheads, remoteheads):
1674 if opts.get('old'):
1676 if opts.get('old'):
1675 if localheads:
1677 if localheads:
1676 raise util.Abort('cannot use localheads with old style discovery')
1678 raise util.Abort('cannot use localheads with old style discovery')
1677 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1679 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1678 force=True)
1680 force=True)
1679 common = set(common)
1681 common = set(common)
1680 if not opts.get('nonheads'):
1682 if not opts.get('nonheads'):
1681 ui.write("unpruned common: %s\n" % " ".join([short(n)
1683 ui.write("unpruned common: %s\n" % " ".join([short(n)
1682 for n in common]))
1684 for n in common]))
1683 dag = dagutil.revlogdag(repo.changelog)
1685 dag = dagutil.revlogdag(repo.changelog)
1684 all = dag.ancestorset(dag.internalizeall(common))
1686 all = dag.ancestorset(dag.internalizeall(common))
1685 common = dag.externalizeall(dag.headsetofconnecteds(all))
1687 common = dag.externalizeall(dag.headsetofconnecteds(all))
1686 else:
1688 else:
1687 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1689 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1688 common = set(common)
1690 common = set(common)
1689 rheads = set(hds)
1691 rheads = set(hds)
1690 lheads = set(repo.heads())
1692 lheads = set(repo.heads())
1691 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]))
1692 if lheads <= common:
1694 if lheads <= common:
1693 ui.write("local is subset\n")
1695 ui.write("local is subset\n")
1694 elif rheads <= common:
1696 elif rheads <= common:
1695 ui.write("remote is subset\n")
1697 ui.write("remote is subset\n")
1696
1698
1697 serverlogs = opts.get('serverlog')
1699 serverlogs = opts.get('serverlog')
1698 if serverlogs:
1700 if serverlogs:
1699 for filename in serverlogs:
1701 for filename in serverlogs:
1700 logfile = open(filename, 'r')
1702 logfile = open(filename, 'r')
1701 try:
1703 try:
1702 line = logfile.readline()
1704 line = logfile.readline()
1703 while line:
1705 while line:
1704 parts = line.strip().split(';')
1706 parts = line.strip().split(';')
1705 op = parts[1]
1707 op = parts[1]
1706 if op == 'cg':
1708 if op == 'cg':
1707 pass
1709 pass
1708 elif op == 'cgss':
1710 elif op == 'cgss':
1709 doit(parts[2].split(' '), parts[3].split(' '))
1711 doit(parts[2].split(' '), parts[3].split(' '))
1710 elif op == 'unb':
1712 elif op == 'unb':
1711 doit(parts[3].split(' '), parts[2].split(' '))
1713 doit(parts[3].split(' '), parts[2].split(' '))
1712 line = logfile.readline()
1714 line = logfile.readline()
1713 finally:
1715 finally:
1714 logfile.close()
1716 logfile.close()
1715
1717
1716 else:
1718 else:
1717 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1719 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1718 opts.get('remote_head'))
1720 opts.get('remote_head'))
1719 localrevs = opts.get('local_head')
1721 localrevs = opts.get('local_head')
1720 doit(localrevs, remoterevs)
1722 doit(localrevs, remoterevs)
1721
1723
1722 @command('debugfileset', [], ('REVSPEC'))
1724 @command('debugfileset', [], ('REVSPEC'))
1723 def debugfileset(ui, repo, expr):
1725 def debugfileset(ui, repo, expr):
1724 '''parse and apply a fileset specification'''
1726 '''parse and apply a fileset specification'''
1725 if ui.verbose:
1727 if ui.verbose:
1726 tree = fileset.parse(expr)[0]
1728 tree = fileset.parse(expr)[0]
1727 ui.note(tree, "\n")
1729 ui.note(tree, "\n")
1728
1730
1729 for f in fileset.getfileset(repo[None], expr):
1731 for f in fileset.getfileset(repo[None], expr):
1730 ui.write("%s\n" % f)
1732 ui.write("%s\n" % f)
1731
1733
1732 @command('debugfsinfo', [], _('[PATH]'))
1734 @command('debugfsinfo', [], _('[PATH]'))
1733 def debugfsinfo(ui, path = "."):
1735 def debugfsinfo(ui, path = "."):
1734 """show information detected about current filesystem"""
1736 """show information detected about current filesystem"""
1735 util.writefile('.debugfsinfo', '')
1737 util.writefile('.debugfsinfo', '')
1736 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'))
1737 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'))
1738 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1740 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1739 and 'yes' or 'no'))
1741 and 'yes' or 'no'))
1740 os.unlink('.debugfsinfo')
1742 os.unlink('.debugfsinfo')
1741
1743
1742 @command('debuggetbundle',
1744 @command('debuggetbundle',
1743 [('H', 'head', [], _('id of head node'), _('ID')),
1745 [('H', 'head', [], _('id of head node'), _('ID')),
1744 ('C', 'common', [], _('id of common node'), _('ID')),
1746 ('C', 'common', [], _('id of common node'), _('ID')),
1745 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1747 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1746 _('REPO FILE [-H|-C ID]...'))
1748 _('REPO FILE [-H|-C ID]...'))
1747 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1749 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1748 """retrieves a bundle from a repo
1750 """retrieves a bundle from a repo
1749
1751
1750 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
1751 given file.
1753 given file.
1752 """
1754 """
1753 repo = hg.peer(ui, opts, repopath)
1755 repo = hg.peer(ui, opts, repopath)
1754 if not repo.capable('getbundle'):
1756 if not repo.capable('getbundle'):
1755 raise util.Abort("getbundle() not supported by target repository")
1757 raise util.Abort("getbundle() not supported by target repository")
1756 args = {}
1758 args = {}
1757 if common:
1759 if common:
1758 args['common'] = [bin(s) for s in common]
1760 args['common'] = [bin(s) for s in common]
1759 if head:
1761 if head:
1760 args['heads'] = [bin(s) for s in head]
1762 args['heads'] = [bin(s) for s in head]
1761 bundle = repo.getbundle('debug', **args)
1763 bundle = repo.getbundle('debug', **args)
1762
1764
1763 bundletype = opts.get('type', 'bzip2').lower()
1765 bundletype = opts.get('type', 'bzip2').lower()
1764 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1766 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1765 bundletype = btypes.get(bundletype)
1767 bundletype = btypes.get(bundletype)
1766 if bundletype not in changegroup.bundletypes:
1768 if bundletype not in changegroup.bundletypes:
1767 raise util.Abort(_('unknown bundle type specified with --type'))
1769 raise util.Abort(_('unknown bundle type specified with --type'))
1768 changegroup.writebundle(bundle, bundlepath, bundletype)
1770 changegroup.writebundle(bundle, bundlepath, bundletype)
1769
1771
1770 @command('debugignore', [], '')
1772 @command('debugignore', [], '')
1771 def debugignore(ui, repo, *values, **opts):
1773 def debugignore(ui, repo, *values, **opts):
1772 """display the combined ignore pattern"""
1774 """display the combined ignore pattern"""
1773 ignore = repo.dirstate._ignore
1775 ignore = repo.dirstate._ignore
1774 includepat = getattr(ignore, 'includepat', None)
1776 includepat = getattr(ignore, 'includepat', None)
1775 if includepat is not None:
1777 if includepat is not None:
1776 ui.write("%s\n" % includepat)
1778 ui.write("%s\n" % includepat)
1777 else:
1779 else:
1778 raise util.Abort(_("no ignore patterns found"))
1780 raise util.Abort(_("no ignore patterns found"))
1779
1781
1780 @command('debugindex',
1782 @command('debugindex',
1781 [('c', 'changelog', False, _('open changelog')),
1783 [('c', 'changelog', False, _('open changelog')),
1782 ('m', 'manifest', False, _('open manifest')),
1784 ('m', 'manifest', False, _('open manifest')),
1783 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1785 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1784 _('[-f FORMAT] -c|-m|FILE'))
1786 _('[-f FORMAT] -c|-m|FILE'))
1785 def debugindex(ui, repo, file_ = None, **opts):
1787 def debugindex(ui, repo, file_ = None, **opts):
1786 """dump the contents of an index file"""
1788 """dump the contents of an index file"""
1787 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1789 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1788 format = opts.get('format', 0)
1790 format = opts.get('format', 0)
1789 if format not in (0, 1):
1791 if format not in (0, 1):
1790 raise util.Abort(_("unknown format %d") % format)
1792 raise util.Abort(_("unknown format %d") % format)
1791
1793
1792 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1794 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1793 if generaldelta:
1795 if generaldelta:
1794 basehdr = ' delta'
1796 basehdr = ' delta'
1795 else:
1797 else:
1796 basehdr = ' base'
1798 basehdr = ' base'
1797
1799
1798 if format == 0:
1800 if format == 0:
1799 ui.write(" rev offset length " + basehdr + " linkrev"
1801 ui.write(" rev offset length " + basehdr + " linkrev"
1800 " nodeid p1 p2\n")
1802 " nodeid p1 p2\n")
1801 elif format == 1:
1803 elif format == 1:
1802 ui.write(" rev flag offset length"
1804 ui.write(" rev flag offset length"
1803 " size " + basehdr + " link p1 p2 nodeid\n")
1805 " size " + basehdr + " link p1 p2 nodeid\n")
1804
1806
1805 for i in r:
1807 for i in r:
1806 node = r.node(i)
1808 node = r.node(i)
1807 if generaldelta:
1809 if generaldelta:
1808 base = r.deltaparent(i)
1810 base = r.deltaparent(i)
1809 else:
1811 else:
1810 base = r.chainbase(i)
1812 base = r.chainbase(i)
1811 if format == 0:
1813 if format == 0:
1812 try:
1814 try:
1813 pp = r.parents(node)
1815 pp = r.parents(node)
1814 except:
1816 except:
1815 pp = [nullid, nullid]
1817 pp = [nullid, nullid]
1816 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1818 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1817 i, r.start(i), r.length(i), base, r.linkrev(i),
1819 i, r.start(i), r.length(i), base, r.linkrev(i),
1818 short(node), short(pp[0]), short(pp[1])))
1820 short(node), short(pp[0]), short(pp[1])))
1819 elif format == 1:
1821 elif format == 1:
1820 pr = r.parentrevs(i)
1822 pr = r.parentrevs(i)
1821 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" % (
1822 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),
1823 base, r.linkrev(i), pr[0], pr[1], short(node)))
1825 base, r.linkrev(i), pr[0], pr[1], short(node)))
1824
1826
1825 @command('debugindexdot', [], _('FILE'))
1827 @command('debugindexdot', [], _('FILE'))
1826 def debugindexdot(ui, repo, file_):
1828 def debugindexdot(ui, repo, file_):
1827 """dump an index DAG as a graphviz dot file"""
1829 """dump an index DAG as a graphviz dot file"""
1828 r = None
1830 r = None
1829 if repo:
1831 if repo:
1830 filelog = repo.file(file_)
1832 filelog = repo.file(file_)
1831 if len(filelog):
1833 if len(filelog):
1832 r = filelog
1834 r = filelog
1833 if not r:
1835 if not r:
1834 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1836 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1835 ui.write("digraph G {\n")
1837 ui.write("digraph G {\n")
1836 for i in r:
1838 for i in r:
1837 node = r.node(i)
1839 node = r.node(i)
1838 pp = r.parents(node)
1840 pp = r.parents(node)
1839 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1841 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1840 if pp[1] != nullid:
1842 if pp[1] != nullid:
1841 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1843 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1842 ui.write("}\n")
1844 ui.write("}\n")
1843
1845
1844 @command('debuginstall', [], '')
1846 @command('debuginstall', [], '')
1845 def debuginstall(ui):
1847 def debuginstall(ui):
1846 '''test Mercurial installation
1848 '''test Mercurial installation
1847
1849
1848 Returns 0 on success.
1850 Returns 0 on success.
1849 '''
1851 '''
1850
1852
1851 def writetemp(contents):
1853 def writetemp(contents):
1852 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1854 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1853 f = os.fdopen(fd, "wb")
1855 f = os.fdopen(fd, "wb")
1854 f.write(contents)
1856 f.write(contents)
1855 f.close()
1857 f.close()
1856 return name
1858 return name
1857
1859
1858 problems = 0
1860 problems = 0
1859
1861
1860 # encoding
1862 # encoding
1861 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1863 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1862 try:
1864 try:
1863 encoding.fromlocal("test")
1865 encoding.fromlocal("test")
1864 except util.Abort, inst:
1866 except util.Abort, inst:
1865 ui.write(" %s\n" % inst)
1867 ui.write(" %s\n" % inst)
1866 ui.write(_(" (check that your locale is properly set)\n"))
1868 ui.write(_(" (check that your locale is properly set)\n"))
1867 problems += 1
1869 problems += 1
1868
1870
1869 # compiled modules
1871 # compiled modules
1870 ui.status(_("Checking installed modules (%s)...\n")
1872 ui.status(_("Checking installed modules (%s)...\n")
1871 % os.path.dirname(__file__))
1873 % os.path.dirname(__file__))
1872 try:
1874 try:
1873 import bdiff, mpatch, base85, osutil
1875 import bdiff, mpatch, base85, osutil
1874 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1876 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1875 except Exception, inst:
1877 except Exception, inst:
1876 ui.write(" %s\n" % inst)
1878 ui.write(" %s\n" % inst)
1877 ui.write(_(" One or more extensions could not be found"))
1879 ui.write(_(" One or more extensions could not be found"))
1878 ui.write(_(" (check that you compiled the extensions)\n"))
1880 ui.write(_(" (check that you compiled the extensions)\n"))
1879 problems += 1
1881 problems += 1
1880
1882
1881 # templates
1883 # templates
1882 import templater
1884 import templater
1883 p = templater.templatepath()
1885 p = templater.templatepath()
1884 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1886 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1885 try:
1887 try:
1886 templater.templater(templater.templatepath("map-cmdline.default"))
1888 templater.templater(templater.templatepath("map-cmdline.default"))
1887 except Exception, inst:
1889 except Exception, inst:
1888 ui.write(" %s\n" % inst)
1890 ui.write(" %s\n" % inst)
1889 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1891 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1890 problems += 1
1892 problems += 1
1891
1893
1892 # editor
1894 # editor
1893 ui.status(_("Checking commit editor...\n"))
1895 ui.status(_("Checking commit editor...\n"))
1894 editor = ui.geteditor()
1896 editor = ui.geteditor()
1895 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1897 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1896 if not cmdpath:
1898 if not cmdpath:
1897 if editor == 'vi':
1899 if editor == 'vi':
1898 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"))
1899 ui.write(_(" (specify a commit editor in your configuration"
1901 ui.write(_(" (specify a commit editor in your configuration"
1900 " file)\n"))
1902 " file)\n"))
1901 else:
1903 else:
1902 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1904 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1903 ui.write(_(" (specify a commit editor in your configuration"
1905 ui.write(_(" (specify a commit editor in your configuration"
1904 " file)\n"))
1906 " file)\n"))
1905 problems += 1
1907 problems += 1
1906
1908
1907 # check username
1909 # check username
1908 ui.status(_("Checking username...\n"))
1910 ui.status(_("Checking username...\n"))
1909 try:
1911 try:
1910 ui.username()
1912 ui.username()
1911 except util.Abort, e:
1913 except util.Abort, e:
1912 ui.write(" %s\n" % e)
1914 ui.write(" %s\n" % e)
1913 ui.write(_(" (specify a username in your configuration file)\n"))
1915 ui.write(_(" (specify a username in your configuration file)\n"))
1914 problems += 1
1916 problems += 1
1915
1917
1916 if not problems:
1918 if not problems:
1917 ui.status(_("No problems detected\n"))
1919 ui.status(_("No problems detected\n"))
1918 else:
1920 else:
1919 ui.write(_("%s problems detected,"
1921 ui.write(_("%s problems detected,"
1920 " please check your install!\n") % problems)
1922 " please check your install!\n") % problems)
1921
1923
1922 return problems
1924 return problems
1923
1925
1924 @command('debugknown', [], _('REPO ID...'))
1926 @command('debugknown', [], _('REPO ID...'))
1925 def debugknown(ui, repopath, *ids, **opts):
1927 def debugknown(ui, repopath, *ids, **opts):
1926 """test whether node ids are known to a repo
1928 """test whether node ids are known to a repo
1927
1929
1928 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
1929 indicating unknown/known.
1931 indicating unknown/known.
1930 """
1932 """
1931 repo = hg.peer(ui, opts, repopath)
1933 repo = hg.peer(ui, opts, repopath)
1932 if not repo.capable('known'):
1934 if not repo.capable('known'):
1933 raise util.Abort("known() not supported by target repository")
1935 raise util.Abort("known() not supported by target repository")
1934 flags = repo.known([bin(s) for s in ids])
1936 flags = repo.known([bin(s) for s in ids])
1935 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])))
1936
1938
1937 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1939 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1938 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1940 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1939 '''access the pushkey key/value protocol
1941 '''access the pushkey key/value protocol
1940
1942
1941 With two args, list the keys in the given namespace.
1943 With two args, list the keys in the given namespace.
1942
1944
1943 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.
1944 Reports success or failure.
1946 Reports success or failure.
1945 '''
1947 '''
1946
1948
1947 target = hg.peer(ui, {}, repopath)
1949 target = hg.peer(ui, {}, repopath)
1948 if keyinfo:
1950 if keyinfo:
1949 key, old, new = keyinfo
1951 key, old, new = keyinfo
1950 r = target.pushkey(namespace, key, old, new)
1952 r = target.pushkey(namespace, key, old, new)
1951 ui.status(str(r) + '\n')
1953 ui.status(str(r) + '\n')
1952 return not r
1954 return not r
1953 else:
1955 else:
1954 for k, v in target.listkeys(namespace).iteritems():
1956 for k, v in target.listkeys(namespace).iteritems():
1955 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1957 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1956 v.encode('string-escape')))
1958 v.encode('string-escape')))
1957
1959
1958 @command('debugrebuildstate',
1960 @command('debugrebuildstate',
1959 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1961 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1960 _('[-r REV] [REV]'))
1962 _('[-r REV] [REV]'))
1961 def debugrebuildstate(ui, repo, rev="tip"):
1963 def debugrebuildstate(ui, repo, rev="tip"):
1962 """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"""
1963 ctx = scmutil.revsingle(repo, rev)
1965 ctx = scmutil.revsingle(repo, rev)
1964 wlock = repo.wlock()
1966 wlock = repo.wlock()
1965 try:
1967 try:
1966 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1968 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1967 finally:
1969 finally:
1968 wlock.release()
1970 wlock.release()
1969
1971
1970 @command('debugrename',
1972 @command('debugrename',
1971 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1973 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1972 _('[-r REV] FILE'))
1974 _('[-r REV] FILE'))
1973 def debugrename(ui, repo, file1, *pats, **opts):
1975 def debugrename(ui, repo, file1, *pats, **opts):
1974 """dump rename information"""
1976 """dump rename information"""
1975
1977
1976 ctx = scmutil.revsingle(repo, opts.get('rev'))
1978 ctx = scmutil.revsingle(repo, opts.get('rev'))
1977 m = scmutil.match(ctx, (file1,) + pats, opts)
1979 m = scmutil.match(ctx, (file1,) + pats, opts)
1978 for abs in ctx.walk(m):
1980 for abs in ctx.walk(m):
1979 fctx = ctx[abs]
1981 fctx = ctx[abs]
1980 o = fctx.filelog().renamed(fctx.filenode())
1982 o = fctx.filelog().renamed(fctx.filenode())
1981 rel = m.rel(abs)
1983 rel = m.rel(abs)
1982 if o:
1984 if o:
1983 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])))
1984 else:
1986 else:
1985 ui.write(_("%s not renamed\n") % rel)
1987 ui.write(_("%s not renamed\n") % rel)
1986
1988
1987 @command('debugrevlog',
1989 @command('debugrevlog',
1988 [('c', 'changelog', False, _('open changelog')),
1990 [('c', 'changelog', False, _('open changelog')),
1989 ('m', 'manifest', False, _('open manifest')),
1991 ('m', 'manifest', False, _('open manifest')),
1990 ('d', 'dump', False, _('dump index data'))],
1992 ('d', 'dump', False, _('dump index data'))],
1991 _('-c|-m|FILE'))
1993 _('-c|-m|FILE'))
1992 def debugrevlog(ui, repo, file_ = None, **opts):
1994 def debugrevlog(ui, repo, file_ = None, **opts):
1993 """show data and statistics about a revlog"""
1995 """show data and statistics about a revlog"""
1994 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1996 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1995
1997
1996 if opts.get("dump"):
1998 if opts.get("dump"):
1997 numrevs = len(r)
1999 numrevs = len(r)
1998 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2000 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1999 " rawsize totalsize compression heads\n")
2001 " rawsize totalsize compression heads\n")
2000 ts = 0
2002 ts = 0
2001 heads = set()
2003 heads = set()
2002 for rev in xrange(numrevs):
2004 for rev in xrange(numrevs):
2003 dbase = r.deltaparent(rev)
2005 dbase = r.deltaparent(rev)
2004 if dbase == -1:
2006 if dbase == -1:
2005 dbase = rev
2007 dbase = rev
2006 cbase = r.chainbase(rev)
2008 cbase = r.chainbase(rev)
2007 p1, p2 = r.parentrevs(rev)
2009 p1, p2 = r.parentrevs(rev)
2008 rs = r.rawsize(rev)
2010 rs = r.rawsize(rev)
2009 ts = ts + rs
2011 ts = ts + rs
2010 heads -= set(r.parentrevs(rev))
2012 heads -= set(r.parentrevs(rev))
2011 heads.add(rev)
2013 heads.add(rev)
2012 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" %
2013 (rev, p1, p2, r.start(rev), r.end(rev),
2015 (rev, p1, p2, r.start(rev), r.end(rev),
2014 r.start(dbase), r.start(cbase),
2016 r.start(dbase), r.start(cbase),
2015 r.start(p1), r.start(p2),
2017 r.start(p1), r.start(p2),
2016 rs, ts, ts / r.end(rev), len(heads)))
2018 rs, ts, ts / r.end(rev), len(heads)))
2017 return 0
2019 return 0
2018
2020
2019 v = r.version
2021 v = r.version
2020 format = v & 0xFFFF
2022 format = v & 0xFFFF
2021 flags = []
2023 flags = []
2022 gdelta = False
2024 gdelta = False
2023 if v & revlog.REVLOGNGINLINEDATA:
2025 if v & revlog.REVLOGNGINLINEDATA:
2024 flags.append('inline')
2026 flags.append('inline')
2025 if v & revlog.REVLOGGENERALDELTA:
2027 if v & revlog.REVLOGGENERALDELTA:
2026 gdelta = True
2028 gdelta = True
2027 flags.append('generaldelta')
2029 flags.append('generaldelta')
2028 if not flags:
2030 if not flags:
2029 flags = ['(none)']
2031 flags = ['(none)']
2030
2032
2031 nummerges = 0
2033 nummerges = 0
2032 numfull = 0
2034 numfull = 0
2033 numprev = 0
2035 numprev = 0
2034 nump1 = 0
2036 nump1 = 0
2035 nump2 = 0
2037 nump2 = 0
2036 numother = 0
2038 numother = 0
2037 nump1prev = 0
2039 nump1prev = 0
2038 nump2prev = 0
2040 nump2prev = 0
2039 chainlengths = []
2041 chainlengths = []
2040
2042
2041 datasize = [None, 0, 0L]
2043 datasize = [None, 0, 0L]
2042 fullsize = [None, 0, 0L]
2044 fullsize = [None, 0, 0L]
2043 deltasize = [None, 0, 0L]
2045 deltasize = [None, 0, 0L]
2044
2046
2045 def addsize(size, l):
2047 def addsize(size, l):
2046 if l[0] is None or size < l[0]:
2048 if l[0] is None or size < l[0]:
2047 l[0] = size
2049 l[0] = size
2048 if size > l[1]:
2050 if size > l[1]:
2049 l[1] = size
2051 l[1] = size
2050 l[2] += size
2052 l[2] += size
2051
2053
2052 numrevs = len(r)
2054 numrevs = len(r)
2053 for rev in xrange(numrevs):
2055 for rev in xrange(numrevs):
2054 p1, p2 = r.parentrevs(rev)
2056 p1, p2 = r.parentrevs(rev)
2055 delta = r.deltaparent(rev)
2057 delta = r.deltaparent(rev)
2056 if format > 0:
2058 if format > 0:
2057 addsize(r.rawsize(rev), datasize)
2059 addsize(r.rawsize(rev), datasize)
2058 if p2 != nullrev:
2060 if p2 != nullrev:
2059 nummerges += 1
2061 nummerges += 1
2060 size = r.length(rev)
2062 size = r.length(rev)
2061 if delta == nullrev:
2063 if delta == nullrev:
2062 chainlengths.append(0)
2064 chainlengths.append(0)
2063 numfull += 1
2065 numfull += 1
2064 addsize(size, fullsize)
2066 addsize(size, fullsize)
2065 else:
2067 else:
2066 chainlengths.append(chainlengths[delta] + 1)
2068 chainlengths.append(chainlengths[delta] + 1)
2067 addsize(size, deltasize)
2069 addsize(size, deltasize)
2068 if delta == rev - 1:
2070 if delta == rev - 1:
2069 numprev += 1
2071 numprev += 1
2070 if delta == p1:
2072 if delta == p1:
2071 nump1prev += 1
2073 nump1prev += 1
2072 elif delta == p2:
2074 elif delta == p2:
2073 nump2prev += 1
2075 nump2prev += 1
2074 elif delta == p1:
2076 elif delta == p1:
2075 nump1 += 1
2077 nump1 += 1
2076 elif delta == p2:
2078 elif delta == p2:
2077 nump2 += 1
2079 nump2 += 1
2078 elif delta != nullrev:
2080 elif delta != nullrev:
2079 numother += 1
2081 numother += 1
2080
2082
2081 numdeltas = numrevs - numfull
2083 numdeltas = numrevs - numfull
2082 numoprev = numprev - nump1prev - nump2prev
2084 numoprev = numprev - nump1prev - nump2prev
2083 totalrawsize = datasize[2]
2085 totalrawsize = datasize[2]
2084 datasize[2] /= numrevs
2086 datasize[2] /= numrevs
2085 fulltotal = fullsize[2]
2087 fulltotal = fullsize[2]
2086 fullsize[2] /= numfull
2088 fullsize[2] /= numfull
2087 deltatotal = deltasize[2]
2089 deltatotal = deltasize[2]
2088 deltasize[2] /= numrevs - numfull
2090 deltasize[2] /= numrevs - numfull
2089 totalsize = fulltotal + deltatotal
2091 totalsize = fulltotal + deltatotal
2090 avgchainlen = sum(chainlengths) / numrevs
2092 avgchainlen = sum(chainlengths) / numrevs
2091 compratio = totalrawsize / totalsize
2093 compratio = totalrawsize / totalsize
2092
2094
2093 basedfmtstr = '%%%dd\n'
2095 basedfmtstr = '%%%dd\n'
2094 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2096 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2095
2097
2096 def dfmtstr(max):
2098 def dfmtstr(max):
2097 return basedfmtstr % len(str(max))
2099 return basedfmtstr % len(str(max))
2098 def pcfmtstr(max, padding=0):
2100 def pcfmtstr(max, padding=0):
2099 return basepcfmtstr % (len(str(max)), ' ' * padding)
2101 return basepcfmtstr % (len(str(max)), ' ' * padding)
2100
2102
2101 def pcfmt(value, total):
2103 def pcfmt(value, total):
2102 return (value, 100 * float(value) / total)
2104 return (value, 100 * float(value) / total)
2103
2105
2104 ui.write('format : %d\n' % format)
2106 ui.write('format : %d\n' % format)
2105 ui.write('flags : %s\n' % ', '.join(flags))
2107 ui.write('flags : %s\n' % ', '.join(flags))
2106
2108
2107 ui.write('\n')
2109 ui.write('\n')
2108 fmt = pcfmtstr(totalsize)
2110 fmt = pcfmtstr(totalsize)
2109 fmt2 = dfmtstr(totalsize)
2111 fmt2 = dfmtstr(totalsize)
2110 ui.write('revisions : ' + fmt2 % numrevs)
2112 ui.write('revisions : ' + fmt2 % numrevs)
2111 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2113 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2112 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2114 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2113 ui.write('revisions : ' + fmt2 % numrevs)
2115 ui.write('revisions : ' + fmt2 % numrevs)
2114 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2116 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2115 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2117 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2116 ui.write('revision size : ' + fmt2 % totalsize)
2118 ui.write('revision size : ' + fmt2 % totalsize)
2117 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2119 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2118 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2120 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2119
2121
2120 ui.write('\n')
2122 ui.write('\n')
2121 fmt = dfmtstr(max(avgchainlen, compratio))
2123 fmt = dfmtstr(max(avgchainlen, compratio))
2122 ui.write('avg chain length : ' + fmt % avgchainlen)
2124 ui.write('avg chain length : ' + fmt % avgchainlen)
2123 ui.write('compression ratio : ' + fmt % compratio)
2125 ui.write('compression ratio : ' + fmt % compratio)
2124
2126
2125 if format > 0:
2127 if format > 0:
2126 ui.write('\n')
2128 ui.write('\n')
2127 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'
2128 % tuple(datasize))
2130 % tuple(datasize))
2129 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'
2130 % tuple(fullsize))
2132 % tuple(fullsize))
2131 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2133 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2132 % tuple(deltasize))
2134 % tuple(deltasize))
2133
2135
2134 if numdeltas > 0:
2136 if numdeltas > 0:
2135 ui.write('\n')
2137 ui.write('\n')
2136 fmt = pcfmtstr(numdeltas)
2138 fmt = pcfmtstr(numdeltas)
2137 fmt2 = pcfmtstr(numdeltas, 4)
2139 fmt2 = pcfmtstr(numdeltas, 4)
2138 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2140 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2139 if numprev > 0:
2141 if numprev > 0:
2140 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2142 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2141 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2143 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2142 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2144 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2143 if gdelta:
2145 if gdelta:
2144 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2146 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2145 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2147 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2146 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2148 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2147
2149
2148 @command('debugrevspec', [], ('REVSPEC'))
2150 @command('debugrevspec', [], ('REVSPEC'))
2149 def debugrevspec(ui, repo, expr):
2151 def debugrevspec(ui, repo, expr):
2150 '''parse and apply a revision specification'''
2152 '''parse and apply a revision specification'''
2151 if ui.verbose:
2153 if ui.verbose:
2152 tree = revset.parse(expr)[0]
2154 tree = revset.parse(expr)[0]
2153 ui.note(tree, "\n")
2155 ui.note(tree, "\n")
2154 newtree = revset.findaliases(ui, tree)
2156 newtree = revset.findaliases(ui, tree)
2155 if newtree != tree:
2157 if newtree != tree:
2156 ui.note(newtree, "\n")
2158 ui.note(newtree, "\n")
2157 func = revset.match(ui, expr)
2159 func = revset.match(ui, expr)
2158 for c in func(repo, range(len(repo))):
2160 for c in func(repo, range(len(repo))):
2159 ui.write("%s\n" % c)
2161 ui.write("%s\n" % c)
2160
2162
2161 @command('debugsetparents', [], _('REV1 [REV2]'))
2163 @command('debugsetparents', [], _('REV1 [REV2]'))
2162 def debugsetparents(ui, repo, rev1, rev2=None):
2164 def debugsetparents(ui, repo, rev1, rev2=None):
2163 """manually set the parents of the current working directory
2165 """manually set the parents of the current working directory
2164
2166
2165 This is useful for writing repository conversion tools, but should
2167 This is useful for writing repository conversion tools, but should
2166 be used with care.
2168 be used with care.
2167
2169
2168 Returns 0 on success.
2170 Returns 0 on success.
2169 """
2171 """
2170
2172
2171 r1 = scmutil.revsingle(repo, rev1).node()
2173 r1 = scmutil.revsingle(repo, rev1).node()
2172 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2174 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2173
2175
2174 wlock = repo.wlock()
2176 wlock = repo.wlock()
2175 try:
2177 try:
2176 repo.dirstate.setparents(r1, r2)
2178 repo.dirstate.setparents(r1, r2)
2177 finally:
2179 finally:
2178 wlock.release()
2180 wlock.release()
2179
2181
2180 @command('debugstate',
2182 @command('debugstate',
2181 [('', 'nodates', None, _('do not display the saved mtime')),
2183 [('', 'nodates', None, _('do not display the saved mtime')),
2182 ('', 'datesort', None, _('sort by saved mtime'))],
2184 ('', 'datesort', None, _('sort by saved mtime'))],
2183 _('[OPTION]...'))
2185 _('[OPTION]...'))
2184 def debugstate(ui, repo, nodates=None, datesort=None):
2186 def debugstate(ui, repo, nodates=None, datesort=None):
2185 """show the contents of the current dirstate"""
2187 """show the contents of the current dirstate"""
2186 timestr = ""
2188 timestr = ""
2187 showdate = not nodates
2189 showdate = not nodates
2188 if datesort:
2190 if datesort:
2189 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
2190 else:
2192 else:
2191 keyfunc = None # sort by filename
2193 keyfunc = None # sort by filename
2192 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2194 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2193 if showdate:
2195 if showdate:
2194 if ent[3] == -1:
2196 if ent[3] == -1:
2195 # Pad or slice to locale representation
2197 # Pad or slice to locale representation
2196 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2198 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2197 time.localtime(0)))
2199 time.localtime(0)))
2198 timestr = 'unset'
2200 timestr = 'unset'
2199 timestr = (timestr[:locale_len] +
2201 timestr = (timestr[:locale_len] +
2200 ' ' * (locale_len - len(timestr)))
2202 ' ' * (locale_len - len(timestr)))
2201 else:
2203 else:
2202 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2204 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2203 time.localtime(ent[3]))
2205 time.localtime(ent[3]))
2204 if ent[1] & 020000:
2206 if ent[1] & 020000:
2205 mode = 'lnk'
2207 mode = 'lnk'
2206 else:
2208 else:
2207 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2209 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2208 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_))
2209 for f in repo.dirstate.copies():
2211 for f in repo.dirstate.copies():
2210 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2212 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2211
2213
2212 @command('debugsub',
2214 @command('debugsub',
2213 [('r', 'rev', '',
2215 [('r', 'rev', '',
2214 _('revision to check'), _('REV'))],
2216 _('revision to check'), _('REV'))],
2215 _('[-r REV] [REV]'))
2217 _('[-r REV] [REV]'))
2216 def debugsub(ui, repo, rev=None):
2218 def debugsub(ui, repo, rev=None):
2217 ctx = scmutil.revsingle(repo, rev, None)
2219 ctx = scmutil.revsingle(repo, rev, None)
2218 for k, v in sorted(ctx.substate.items()):
2220 for k, v in sorted(ctx.substate.items()):
2219 ui.write('path %s\n' % k)
2221 ui.write('path %s\n' % k)
2220 ui.write(' source %s\n' % v[0])
2222 ui.write(' source %s\n' % v[0])
2221 ui.write(' revision %s\n' % v[1])
2223 ui.write(' revision %s\n' % v[1])
2222
2224
2223 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2225 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2224 def debugwalk(ui, repo, *pats, **opts):
2226 def debugwalk(ui, repo, *pats, **opts):
2225 """show how files match on given patterns"""
2227 """show how files match on given patterns"""
2226 m = scmutil.match(repo[None], pats, opts)
2228 m = scmutil.match(repo[None], pats, opts)
2227 items = list(repo.walk(m))
2229 items = list(repo.walk(m))
2228 if not items:
2230 if not items:
2229 return
2231 return
2230 fmt = 'f %%-%ds %%-%ds %%s' % (
2232 fmt = 'f %%-%ds %%-%ds %%s' % (
2231 max([len(abs) for abs in items]),
2233 max([len(abs) for abs in items]),
2232 max([len(m.rel(abs)) for abs in items]))
2234 max([len(m.rel(abs)) for abs in items]))
2233 for abs in items:
2235 for abs in items:
2234 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 '')
2235 ui.write("%s\n" % line.rstrip())
2237 ui.write("%s\n" % line.rstrip())
2236
2238
2237 @command('debugwireargs',
2239 @command('debugwireargs',
2238 [('', 'three', '', 'three'),
2240 [('', 'three', '', 'three'),
2239 ('', 'four', '', 'four'),
2241 ('', 'four', '', 'four'),
2240 ('', 'five', '', 'five'),
2242 ('', 'five', '', 'five'),
2241 ] + remoteopts,
2243 ] + remoteopts,
2242 _('REPO [OPTIONS]... [ONE [TWO]]'))
2244 _('REPO [OPTIONS]... [ONE [TWO]]'))
2243 def debugwireargs(ui, repopath, *vals, **opts):
2245 def debugwireargs(ui, repopath, *vals, **opts):
2244 repo = hg.peer(ui, opts, repopath)
2246 repo = hg.peer(ui, opts, repopath)
2245 for opt in remoteopts:
2247 for opt in remoteopts:
2246 del opts[opt[1]]
2248 del opts[opt[1]]
2247 args = {}
2249 args = {}
2248 for k, v in opts.iteritems():
2250 for k, v in opts.iteritems():
2249 if v:
2251 if v:
2250 args[k] = v
2252 args[k] = v
2251 # 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
2252 res1 = repo.debugwireargs(*vals, **args)
2254 res1 = repo.debugwireargs(*vals, **args)
2253 res2 = repo.debugwireargs(*vals, **args)
2255 res2 = repo.debugwireargs(*vals, **args)
2254 ui.write("%s\n" % res1)
2256 ui.write("%s\n" % res1)
2255 if res1 != res2:
2257 if res1 != res2:
2256 ui.warn("%s\n" % res2)
2258 ui.warn("%s\n" % res2)
2257
2259
2258 @command('^diff',
2260 @command('^diff',
2259 [('r', 'rev', [], _('revision'), _('REV')),
2261 [('r', 'rev', [], _('revision'), _('REV')),
2260 ('c', 'change', '', _('change made by revision'), _('REV'))
2262 ('c', 'change', '', _('change made by revision'), _('REV'))
2261 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2263 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2262 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2264 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2263 def diff(ui, repo, *pats, **opts):
2265 def diff(ui, repo, *pats, **opts):
2264 """diff repository (or selected files)
2266 """diff repository (or selected files)
2265
2267
2266 Show differences between revisions for the specified files.
2268 Show differences between revisions for the specified files.
2267
2269
2268 Differences between files are shown using the unified diff format.
2270 Differences between files are shown using the unified diff format.
2269
2271
2270 .. note::
2272 .. note::
2271 diff may generate unexpected results for merges, as it will
2273 diff may generate unexpected results for merges, as it will
2272 default to comparing against the working directory's first
2274 default to comparing against the working directory's first
2273 parent changeset if no revisions are specified.
2275 parent changeset if no revisions are specified.
2274
2276
2275 When two revision arguments are given, then changes are shown
2277 When two revision arguments are given, then changes are shown
2276 between those revisions. If only one revision is specified then
2278 between those revisions. If only one revision is specified then
2277 that revision is compared to the working directory, and, when no
2279 that revision is compared to the working directory, and, when no
2278 revisions are specified, the working directory files are compared
2280 revisions are specified, the working directory files are compared
2279 to its parent.
2281 to its parent.
2280
2282
2281 Alternatively you can specify -c/--change with a revision to see
2283 Alternatively you can specify -c/--change with a revision to see
2282 the changes in that changeset relative to its first parent.
2284 the changes in that changeset relative to its first parent.
2283
2285
2284 Without the -a/--text option, diff will avoid generating diffs of
2286 Without the -a/--text option, diff will avoid generating diffs of
2285 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
2286 anyway, probably with undesirable results.
2288 anyway, probably with undesirable results.
2287
2289
2288 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
2289 format. For more information, read :hg:`help diffs`.
2291 format. For more information, read :hg:`help diffs`.
2290
2292
2291 .. container:: verbose
2293 .. container:: verbose
2292
2294
2293 Examples:
2295 Examples:
2294
2296
2295 - compare a file in the current working directory to its parent::
2297 - compare a file in the current working directory to its parent::
2296
2298
2297 hg diff foo.c
2299 hg diff foo.c
2298
2300
2299 - compare two historical versions of a directory, with rename info::
2301 - compare two historical versions of a directory, with rename info::
2300
2302
2301 hg diff --git -r 1.0:1.2 lib/
2303 hg diff --git -r 1.0:1.2 lib/
2302
2304
2303 - get change stats relative to the last change on some date::
2305 - get change stats relative to the last change on some date::
2304
2306
2305 hg diff --stat -r "date('may 2')"
2307 hg diff --stat -r "date('may 2')"
2306
2308
2307 - diff all newly-added files that contain a keyword::
2309 - diff all newly-added files that contain a keyword::
2308
2310
2309 hg diff "set:added() and grep(GNU)"
2311 hg diff "set:added() and grep(GNU)"
2310
2312
2311 - compare a revision and its parents::
2313 - compare a revision and its parents::
2312
2314
2313 hg diff -c 9353 # compare against first parent
2315 hg diff -c 9353 # compare against first parent
2314 hg diff -r 9353^:9353 # same using revset syntax
2316 hg diff -r 9353^:9353 # same using revset syntax
2315 hg diff -r 9353^2:9353 # compare against the second parent
2317 hg diff -r 9353^2:9353 # compare against the second parent
2316
2318
2317 Returns 0 on success.
2319 Returns 0 on success.
2318 """
2320 """
2319
2321
2320 revs = opts.get('rev')
2322 revs = opts.get('rev')
2321 change = opts.get('change')
2323 change = opts.get('change')
2322 stat = opts.get('stat')
2324 stat = opts.get('stat')
2323 reverse = opts.get('reverse')
2325 reverse = opts.get('reverse')
2324
2326
2325 if revs and change:
2327 if revs and change:
2326 msg = _('cannot specify --rev and --change at the same time')
2328 msg = _('cannot specify --rev and --change at the same time')
2327 raise util.Abort(msg)
2329 raise util.Abort(msg)
2328 elif change:
2330 elif change:
2329 node2 = scmutil.revsingle(repo, change, None).node()
2331 node2 = scmutil.revsingle(repo, change, None).node()
2330 node1 = repo[node2].p1().node()
2332 node1 = repo[node2].p1().node()
2331 else:
2333 else:
2332 node1, node2 = scmutil.revpair(repo, revs)
2334 node1, node2 = scmutil.revpair(repo, revs)
2333
2335
2334 if reverse:
2336 if reverse:
2335 node1, node2 = node2, node1
2337 node1, node2 = node2, node1
2336
2338
2337 diffopts = patch.diffopts(ui, opts)
2339 diffopts = patch.diffopts(ui, opts)
2338 m = scmutil.match(repo[node2], pats, opts)
2340 m = scmutil.match(repo[node2], pats, opts)
2339 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2341 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2340 listsubrepos=opts.get('subrepos'))
2342 listsubrepos=opts.get('subrepos'))
2341
2343
2342 @command('^export',
2344 @command('^export',
2343 [('o', 'output', '',
2345 [('o', 'output', '',
2344 _('print output to file with formatted name'), _('FORMAT')),
2346 _('print output to file with formatted name'), _('FORMAT')),
2345 ('', 'switch-parent', None, _('diff against the second parent')),
2347 ('', 'switch-parent', None, _('diff against the second parent')),
2346 ('r', 'rev', [], _('revisions to export'), _('REV')),
2348 ('r', 'rev', [], _('revisions to export'), _('REV')),
2347 ] + diffopts,
2349 ] + diffopts,
2348 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2350 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2349 def export(ui, repo, *changesets, **opts):
2351 def export(ui, repo, *changesets, **opts):
2350 """dump the header and diffs for one or more changesets
2352 """dump the header and diffs for one or more changesets
2351
2353
2352 Print the changeset header and diffs for one or more revisions.
2354 Print the changeset header and diffs for one or more revisions.
2353
2355
2354 The information shown in the changeset header is: author, date,
2356 The information shown in the changeset header is: author, date,
2355 branch name (if non-default), changeset hash, parent(s) and commit
2357 branch name (if non-default), changeset hash, parent(s) and commit
2356 comment.
2358 comment.
2357
2359
2358 .. note::
2360 .. note::
2359 export may generate unexpected diff output for merge
2361 export may generate unexpected diff output for merge
2360 changesets, as it will compare the merge changeset against its
2362 changesets, as it will compare the merge changeset against its
2361 first parent only.
2363 first parent only.
2362
2364
2363 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
2364 given using a format string. The formatting rules are as follows:
2366 given using a format string. The formatting rules are as follows:
2365
2367
2366 :``%%``: literal "%" character
2368 :``%%``: literal "%" character
2367 :``%H``: changeset hash (40 hexadecimal digits)
2369 :``%H``: changeset hash (40 hexadecimal digits)
2368 :``%N``: number of patches being generated
2370 :``%N``: number of patches being generated
2369 :``%R``: changeset revision number
2371 :``%R``: changeset revision number
2370 :``%b``: basename of the exporting repository
2372 :``%b``: basename of the exporting repository
2371 :``%h``: short-form changeset hash (12 hexadecimal digits)
2373 :``%h``: short-form changeset hash (12 hexadecimal digits)
2372 :``%m``: first line of the commit message (only alphanumeric characters)
2374 :``%m``: first line of the commit message (only alphanumeric characters)
2373 :``%n``: zero-padded sequence number, starting at 1
2375 :``%n``: zero-padded sequence number, starting at 1
2374 :``%r``: zero-padded changeset revision number
2376 :``%r``: zero-padded changeset revision number
2375
2377
2376 Without the -a/--text option, export will avoid generating diffs
2378 Without the -a/--text option, export will avoid generating diffs
2377 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
2378 diff anyway, probably with undesirable results.
2380 diff anyway, probably with undesirable results.
2379
2381
2380 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
2381 format. See :hg:`help diffs` for more information.
2383 format. See :hg:`help diffs` for more information.
2382
2384
2383 With the --switch-parent option, the diff will be against the
2385 With the --switch-parent option, the diff will be against the
2384 second parent. It can be useful to review a merge.
2386 second parent. It can be useful to review a merge.
2385
2387
2386 .. container:: verbose
2388 .. container:: verbose
2387
2389
2388 Examples:
2390 Examples:
2389
2391
2390 - use export and import to transplant a bugfix to the current
2392 - use export and import to transplant a bugfix to the current
2391 branch::
2393 branch::
2392
2394
2393 hg export -r 9353 | hg import -
2395 hg export -r 9353 | hg import -
2394
2396
2395 - export all the changesets between two revisions to a file with
2397 - export all the changesets between two revisions to a file with
2396 rename information::
2398 rename information::
2397
2399
2398 hg export --git -r 123:150 > changes.txt
2400 hg export --git -r 123:150 > changes.txt
2399
2401
2400 - split outgoing changes into a series of patches with
2402 - split outgoing changes into a series of patches with
2401 descriptive names::
2403 descriptive names::
2402
2404
2403 hg export -r "outgoing()" -o "%n-%m.patch"
2405 hg export -r "outgoing()" -o "%n-%m.patch"
2404
2406
2405 Returns 0 on success.
2407 Returns 0 on success.
2406 """
2408 """
2407 changesets += tuple(opts.get('rev', []))
2409 changesets += tuple(opts.get('rev', []))
2408 if not changesets:
2410 if not changesets:
2409 raise util.Abort(_("export requires at least one changeset"))
2411 raise util.Abort(_("export requires at least one changeset"))
2410 revs = scmutil.revrange(repo, changesets)
2412 revs = scmutil.revrange(repo, changesets)
2411 if len(revs) > 1:
2413 if len(revs) > 1:
2412 ui.note(_('exporting patches:\n'))
2414 ui.note(_('exporting patches:\n'))
2413 else:
2415 else:
2414 ui.note(_('exporting patch:\n'))
2416 ui.note(_('exporting patch:\n'))
2415 cmdutil.export(repo, revs, template=opts.get('output'),
2417 cmdutil.export(repo, revs, template=opts.get('output'),
2416 switch_parent=opts.get('switch_parent'),
2418 switch_parent=opts.get('switch_parent'),
2417 opts=patch.diffopts(ui, opts))
2419 opts=patch.diffopts(ui, opts))
2418
2420
2419 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2421 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2420 def forget(ui, repo, *pats, **opts):
2422 def forget(ui, repo, *pats, **opts):
2421 """forget the specified files on the next commit
2423 """forget the specified files on the next commit
2422
2424
2423 Mark the specified files so they will no longer be tracked
2425 Mark the specified files so they will no longer be tracked
2424 after the next commit.
2426 after the next commit.
2425
2427
2426 This only removes files from the current branch, not from the
2428 This only removes files from the current branch, not from the
2427 entire project history, and it does not delete them from the
2429 entire project history, and it does not delete them from the
2428 working directory.
2430 working directory.
2429
2431
2430 To undo a forget before the next commit, see :hg:`add`.
2432 To undo a forget before the next commit, see :hg:`add`.
2431
2433
2432 .. container:: verbose
2434 .. container:: verbose
2433
2435
2434 Examples:
2436 Examples:
2435
2437
2436 - forget newly-added binary files::
2438 - forget newly-added binary files::
2437
2439
2438 hg forget "set:added() and binary()"
2440 hg forget "set:added() and binary()"
2439
2441
2440 - forget files that would be excluded by .hgignore::
2442 - forget files that would be excluded by .hgignore::
2441
2443
2442 hg forget "set:hgignore()"
2444 hg forget "set:hgignore()"
2443
2445
2444 Returns 0 on success.
2446 Returns 0 on success.
2445 """
2447 """
2446
2448
2447 if not pats:
2449 if not pats:
2448 raise util.Abort(_('no files specified'))
2450 raise util.Abort(_('no files specified'))
2449
2451
2450 wctx = repo[None]
2452 wctx = repo[None]
2451 m = scmutil.match(wctx, pats, opts)
2453 m = scmutil.match(wctx, pats, opts)
2452 s = repo.status(match=m, clean=True)
2454 s = repo.status(match=m, clean=True)
2453 forget = sorted(s[0] + s[1] + s[3] + s[6])
2455 forget = sorted(s[0] + s[1] + s[3] + s[6])
2454 subforget = {}
2456 subforget = {}
2455 errs = 0
2457 errs = 0
2456
2458
2457 for subpath in wctx.substate:
2459 for subpath in wctx.substate:
2458 sub = wctx.sub(subpath)
2460 sub = wctx.sub(subpath)
2459 try:
2461 try:
2460 submatch = matchmod.narrowmatcher(subpath, m)
2462 submatch = matchmod.narrowmatcher(subpath, m)
2461 for fsub in sub.walk(submatch):
2463 for fsub in sub.walk(submatch):
2462 if submatch.exact(fsub):
2464 if submatch.exact(fsub):
2463 subforget[subpath + '/' + fsub] = (fsub, sub)
2465 subforget[subpath + '/' + fsub] = (fsub, sub)
2464 except error.LookupError:
2466 except error.LookupError:
2465 ui.status(_("skipping missing subrepository: %s\n") % subpath)
2467 ui.status(_("skipping missing subrepository: %s\n") % subpath)
2466
2468
2467 for f in m.files():
2469 for f in m.files():
2468 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)):
2469 if f not in subforget:
2471 if f not in subforget:
2470 if os.path.exists(m.rel(f)):
2472 if os.path.exists(m.rel(f)):
2471 ui.warn(_('not removing %s: file is already untracked\n')
2473 ui.warn(_('not removing %s: file is already untracked\n')
2472 % m.rel(f))
2474 % m.rel(f))
2473 errs = 1
2475 errs = 1
2474
2476
2475 for f in forget:
2477 for f in forget:
2476 if ui.verbose or not m.exact(f):
2478 if ui.verbose or not m.exact(f):
2477 ui.status(_('removing %s\n') % m.rel(f))
2479 ui.status(_('removing %s\n') % m.rel(f))
2478
2480
2479 if ui.verbose:
2481 if ui.verbose:
2480 for f in sorted(subforget.keys()):
2482 for f in sorted(subforget.keys()):
2481 ui.status(_('removing %s\n') % m.rel(f))
2483 ui.status(_('removing %s\n') % m.rel(f))
2482
2484
2483 wctx.forget(forget)
2485 wctx.forget(forget)
2484
2486
2485 for f in sorted(subforget.keys()):
2487 for f in sorted(subforget.keys()):
2486 fsub, sub = subforget[f]
2488 fsub, sub = subforget[f]
2487 sub.forget([fsub])
2489 sub.forget([fsub])
2488
2490
2489 return errs
2491 return errs
2490
2492
2491 @command(
2493 @command(
2492 'graft',
2494 'graft',
2493 [('c', 'continue', False, _('resume interrupted graft')),
2495 [('c', 'continue', False, _('resume interrupted graft')),
2494 ('e', 'edit', False, _('invoke editor on commit messages')),
2496 ('e', 'edit', False, _('invoke editor on commit messages')),
2495 ('D', 'currentdate', False,
2497 ('D', 'currentdate', False,
2496 _('record the current date as commit date')),
2498 _('record the current date as commit date')),
2497 ('U', 'currentuser', False,
2499 ('U', 'currentuser', False,
2498 _('record the current user as committer'), _('DATE'))]
2500 _('record the current user as committer'), _('DATE'))]
2499 + commitopts2 + mergetoolopts,
2501 + commitopts2 + mergetoolopts,
2500 _('[OPTION]... REVISION...'))
2502 _('[OPTION]... REVISION...'))
2501 def graft(ui, repo, *revs, **opts):
2503 def graft(ui, repo, *revs, **opts):
2502 '''copy changes from other branches onto the current branch
2504 '''copy changes from other branches onto the current branch
2503
2505
2504 This command uses Mercurial's merge logic to copy individual
2506 This command uses Mercurial's merge logic to copy individual
2505 changes from other branches without merging branches in the
2507 changes from other branches without merging branches in the
2506 history graph. This is sometimes known as 'backporting' or
2508 history graph. This is sometimes known as 'backporting' or
2507 'cherry-picking'. By default, graft will copy user, date, and
2509 'cherry-picking'. By default, graft will copy user, date, and
2508 description from the source changesets.
2510 description from the source changesets.
2509
2511
2510 Changesets that are ancestors of the current revision, that have
2512 Changesets that are ancestors of the current revision, that have
2511 already been grafted, or that are merges will be skipped.
2513 already been grafted, or that are merges will be skipped.
2512
2514
2513 If a graft merge results in conflicts, the graft process is
2515 If a graft merge results in conflicts, the graft process is
2514 interrupted so that the current merge can be manually resolved.
2516 interrupted so that the current merge can be manually resolved.
2515 Once all conflicts are addressed, the graft process can be
2517 Once all conflicts are addressed, the graft process can be
2516 continued with the -c/--continue option.
2518 continued with the -c/--continue option.
2517
2519
2518 .. note::
2520 .. note::
2519 The -c/--continue option does not reapply earlier options.
2521 The -c/--continue option does not reapply earlier options.
2520
2522
2521 .. container:: verbose
2523 .. container:: verbose
2522
2524
2523 Examples:
2525 Examples:
2524
2526
2525 - 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::
2526
2528
2527 hg update stable
2529 hg update stable
2528 hg graft --edit 9393
2530 hg graft --edit 9393
2529
2531
2530 - graft a range of changesets with one exception, updating dates::
2532 - graft a range of changesets with one exception, updating dates::
2531
2533
2532 hg graft -D "2085::2093 and not 2091"
2534 hg graft -D "2085::2093 and not 2091"
2533
2535
2534 - continue a graft after resolving conflicts::
2536 - continue a graft after resolving conflicts::
2535
2537
2536 hg graft -c
2538 hg graft -c
2537
2539
2538 - show the source of a grafted changeset::
2540 - show the source of a grafted changeset::
2539
2541
2540 hg log --debug -r tip
2542 hg log --debug -r tip
2541
2543
2542 Returns 0 on successful completion.
2544 Returns 0 on successful completion.
2543 '''
2545 '''
2544
2546
2545 if not opts.get('user') and opts.get('currentuser'):
2547 if not opts.get('user') and opts.get('currentuser'):
2546 opts['user'] = ui.username()
2548 opts['user'] = ui.username()
2547 if not opts.get('date') and opts.get('currentdate'):
2549 if not opts.get('date') and opts.get('currentdate'):
2548 opts['date'] = "%d %d" % util.makedate()
2550 opts['date'] = "%d %d" % util.makedate()
2549
2551
2550 editor = None
2552 editor = None
2551 if opts.get('edit'):
2553 if opts.get('edit'):
2552 editor = cmdutil.commitforceeditor
2554 editor = cmdutil.commitforceeditor
2553
2555
2554 cont = False
2556 cont = False
2555 if opts['continue']:
2557 if opts['continue']:
2556 cont = True
2558 cont = True
2557 if revs:
2559 if revs:
2558 raise util.Abort(_("can't specify --continue and revisions"))
2560 raise util.Abort(_("can't specify --continue and revisions"))
2559 # read in unfinished revisions
2561 # read in unfinished revisions
2560 try:
2562 try:
2561 nodes = repo.opener.read('graftstate').splitlines()
2563 nodes = repo.opener.read('graftstate').splitlines()
2562 revs = [repo[node].rev() for node in nodes]
2564 revs = [repo[node].rev() for node in nodes]
2563 except IOError, inst:
2565 except IOError, inst:
2564 if inst.errno != errno.ENOENT:
2566 if inst.errno != errno.ENOENT:
2565 raise
2567 raise
2566 raise util.Abort(_("no graft state found, can't continue"))
2568 raise util.Abort(_("no graft state found, can't continue"))
2567 else:
2569 else:
2568 cmdutil.bailifchanged(repo)
2570 cmdutil.bailifchanged(repo)
2569 if not revs:
2571 if not revs:
2570 raise util.Abort(_('no revisions specified'))
2572 raise util.Abort(_('no revisions specified'))
2571 revs = scmutil.revrange(repo, revs)
2573 revs = scmutil.revrange(repo, revs)
2572
2574
2573 # check for merges
2575 # check for merges
2574 for rev in repo.revs('%ld and merge()', revs):
2576 for rev in repo.revs('%ld and merge()', revs):
2575 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2577 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2576 revs.remove(rev)
2578 revs.remove(rev)
2577 if not revs:
2579 if not revs:
2578 return -1
2580 return -1
2579
2581
2580 # check for ancestors of dest branch
2582 # check for ancestors of dest branch
2581 for rev in repo.revs('::. and %ld', revs):
2583 for rev in repo.revs('::. and %ld', revs):
2582 ui.warn(_('skipping ancestor revision %s\n') % rev)
2584 ui.warn(_('skipping ancestor revision %s\n') % rev)
2583 revs.remove(rev)
2585 revs.remove(rev)
2584 if not revs:
2586 if not revs:
2585 return -1
2587 return -1
2586
2588
2587 # analyze revs for earlier grafts
2589 # analyze revs for earlier grafts
2588 ids = {}
2590 ids = {}
2589 for ctx in repo.set("%ld", revs):
2591 for ctx in repo.set("%ld", revs):
2590 ids[ctx.hex()] = ctx.rev()
2592 ids[ctx.hex()] = ctx.rev()
2591 n = ctx.extra().get('source')
2593 n = ctx.extra().get('source')
2592 if n:
2594 if n:
2593 ids[n] = ctx.rev()
2595 ids[n] = ctx.rev()
2594
2596
2595 # check ancestors for earlier grafts
2597 # check ancestors for earlier grafts
2596 ui.debug('scanning for duplicate grafts\n')
2598 ui.debug('scanning for duplicate grafts\n')
2597 for ctx in repo.set("::. - ::%ld", revs):
2599 for ctx in repo.set("::. - ::%ld", revs):
2598 n = ctx.extra().get('source')
2600 n = ctx.extra().get('source')
2599 if n in ids:
2601 if n in ids:
2600 r = repo[n].rev()
2602 r = repo[n].rev()
2601 if r in revs:
2603 if r in revs:
2602 ui.warn(_('skipping already grafted revision %s\n') % r)
2604 ui.warn(_('skipping already grafted revision %s\n') % r)
2603 revs.remove(r)
2605 revs.remove(r)
2604 elif ids[n] in revs:
2606 elif ids[n] in revs:
2605 ui.warn(_('skipping already grafted revision %s '
2607 ui.warn(_('skipping already grafted revision %s '
2606 '(same origin %d)\n') % (ids[n], r))
2608 '(same origin %d)\n') % (ids[n], r))
2607 revs.remove(ids[n])
2609 revs.remove(ids[n])
2608 elif ctx.hex() in ids:
2610 elif ctx.hex() in ids:
2609 r = ids[ctx.hex()]
2611 r = ids[ctx.hex()]
2610 ui.warn(_('skipping already grafted revision %s '
2612 ui.warn(_('skipping already grafted revision %s '
2611 '(was grafted from %d)\n') % (r, ctx.rev()))
2613 '(was grafted from %d)\n') % (r, ctx.rev()))
2612 revs.remove(r)
2614 revs.remove(r)
2613 if not revs:
2615 if not revs:
2614 return -1
2616 return -1
2615
2617
2616 for pos, ctx in enumerate(repo.set("%ld", revs)):
2618 for pos, ctx in enumerate(repo.set("%ld", revs)):
2617 current = repo['.']
2619 current = repo['.']
2618 ui.status(_('grafting revision %s\n') % ctx.rev())
2620 ui.status(_('grafting revision %s\n') % ctx.rev())
2619
2621
2620 # we don't merge the first commit when continuing
2622 # we don't merge the first commit when continuing
2621 if not cont:
2623 if not cont:
2622 # perform the graft merge with p1(rev) as 'ancestor'
2624 # perform the graft merge with p1(rev) as 'ancestor'
2623 try:
2625 try:
2624 # ui.forcemerge is an internal variable, do not document
2626 # ui.forcemerge is an internal variable, do not document
2625 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2627 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2626 stats = mergemod.update(repo, ctx.node(), True, True, False,
2628 stats = mergemod.update(repo, ctx.node(), True, True, False,
2627 ctx.p1().node())
2629 ctx.p1().node())
2628 finally:
2630 finally:
2629 ui.setconfig('ui', 'forcemerge', '')
2631 ui.setconfig('ui', 'forcemerge', '')
2630 # drop the second merge parent
2632 # drop the second merge parent
2631 repo.dirstate.setparents(current.node(), nullid)
2633 repo.dirstate.setparents(current.node(), nullid)
2632 repo.dirstate.write()
2634 repo.dirstate.write()
2633 # fix up dirstate for copies and renames
2635 # fix up dirstate for copies and renames
2634 cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
2636 cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
2635 # report any conflicts
2637 # report any conflicts
2636 if stats and stats[3] > 0:
2638 if stats and stats[3] > 0:
2637 # write out state for --continue
2639 # write out state for --continue
2638 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2640 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2639 repo.opener.write('graftstate', ''.join(nodelines))
2641 repo.opener.write('graftstate', ''.join(nodelines))
2640 raise util.Abort(
2642 raise util.Abort(
2641 _("unresolved conflicts, can't continue"),
2643 _("unresolved conflicts, can't continue"),
2642 hint=_('use hg resolve and hg graft --continue'))
2644 hint=_('use hg resolve and hg graft --continue'))
2643 else:
2645 else:
2644 cont = False
2646 cont = False
2645
2647
2646 # commit
2648 # commit
2647 source = ctx.extra().get('source')
2649 source = ctx.extra().get('source')
2648 if not source:
2650 if not source:
2649 source = ctx.hex()
2651 source = ctx.hex()
2650 extra = {'source': source}
2652 extra = {'source': source}
2651 user = ctx.user()
2653 user = ctx.user()
2652 if opts.get('user'):
2654 if opts.get('user'):
2653 user = opts['user']
2655 user = opts['user']
2654 date = ctx.date()
2656 date = ctx.date()
2655 if opts.get('date'):
2657 if opts.get('date'):
2656 date = opts['date']
2658 date = opts['date']
2657 repo.commit(text=ctx.description(), user=user,
2659 repo.commit(text=ctx.description(), user=user,
2658 date=date, extra=extra, editor=editor)
2660 date=date, extra=extra, editor=editor)
2659
2661
2660 # remove state when we complete successfully
2662 # remove state when we complete successfully
2661 if os.path.exists(repo.join('graftstate')):
2663 if os.path.exists(repo.join('graftstate')):
2662 util.unlinkpath(repo.join('graftstate'))
2664 util.unlinkpath(repo.join('graftstate'))
2663
2665
2664 return 0
2666 return 0
2665
2667
2666 @command('grep',
2668 @command('grep',
2667 [('0', 'print0', None, _('end fields with NUL')),
2669 [('0', 'print0', None, _('end fields with NUL')),
2668 ('', 'all', None, _('print all revisions that match')),
2670 ('', 'all', None, _('print all revisions that match')),
2669 ('a', 'text', None, _('treat all files as text')),
2671 ('a', 'text', None, _('treat all files as text')),
2670 ('f', 'follow', None,
2672 ('f', 'follow', None,
2671 _('follow changeset history,'
2673 _('follow changeset history,'
2672 ' or file history across copies and renames')),
2674 ' or file history across copies and renames')),
2673 ('i', 'ignore-case', None, _('ignore case when matching')),
2675 ('i', 'ignore-case', None, _('ignore case when matching')),
2674 ('l', 'files-with-matches', None,
2676 ('l', 'files-with-matches', None,
2675 _('print only filenames and revisions that match')),
2677 _('print only filenames and revisions that match')),
2676 ('n', 'line-number', None, _('print matching line numbers')),
2678 ('n', 'line-number', None, _('print matching line numbers')),
2677 ('r', 'rev', [],
2679 ('r', 'rev', [],
2678 _('only search files changed within revision range'), _('REV')),
2680 _('only search files changed within revision range'), _('REV')),
2679 ('u', 'user', None, _('list the author (long with -v)')),
2681 ('u', 'user', None, _('list the author (long with -v)')),
2680 ('d', 'date', None, _('list the date (short with -q)')),
2682 ('d', 'date', None, _('list the date (short with -q)')),
2681 ] + walkopts,
2683 ] + walkopts,
2682 _('[OPTION]... PATTERN [FILE]...'))
2684 _('[OPTION]... PATTERN [FILE]...'))
2683 def grep(ui, repo, pattern, *pats, **opts):
2685 def grep(ui, repo, pattern, *pats, **opts):
2684 """search for a pattern in specified files and revisions
2686 """search for a pattern in specified files and revisions
2685
2687
2686 Search revisions of files for a regular expression.
2688 Search revisions of files for a regular expression.
2687
2689
2688 This command behaves differently than Unix grep. It only accepts
2690 This command behaves differently than Unix grep. It only accepts
2689 Python/Perl regexps. It searches repository history, not the
2691 Python/Perl regexps. It searches repository history, not the
2690 working directory. It always prints the revision number in which a
2692 working directory. It always prints the revision number in which a
2691 match appears.
2693 match appears.
2692
2694
2693 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
2694 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
2695 that contains a change in match status ("-" for a match that
2697 that contains a change in match status ("-" for a match that
2696 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),
2697 use the --all flag.
2699 use the --all flag.
2698
2700
2699 Returns 0 if a match is found, 1 otherwise.
2701 Returns 0 if a match is found, 1 otherwise.
2700 """
2702 """
2701 reflags = re.M
2703 reflags = re.M
2702 if opts.get('ignore_case'):
2704 if opts.get('ignore_case'):
2703 reflags |= re.I
2705 reflags |= re.I
2704 try:
2706 try:
2705 regexp = re.compile(pattern, reflags)
2707 regexp = re.compile(pattern, reflags)
2706 except re.error, inst:
2708 except re.error, inst:
2707 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2709 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2708 return 1
2710 return 1
2709 sep, eol = ':', '\n'
2711 sep, eol = ':', '\n'
2710 if opts.get('print0'):
2712 if opts.get('print0'):
2711 sep = eol = '\0'
2713 sep = eol = '\0'
2712
2714
2713 getfile = util.lrucachefunc(repo.file)
2715 getfile = util.lrucachefunc(repo.file)
2714
2716
2715 def matchlines(body):
2717 def matchlines(body):
2716 begin = 0
2718 begin = 0
2717 linenum = 0
2719 linenum = 0
2718 while True:
2720 while True:
2719 match = regexp.search(body, begin)
2721 match = regexp.search(body, begin)
2720 if not match:
2722 if not match:
2721 break
2723 break
2722 mstart, mend = match.span()
2724 mstart, mend = match.span()
2723 linenum += body.count('\n', begin, mstart) + 1
2725 linenum += body.count('\n', begin, mstart) + 1
2724 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2726 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2725 begin = body.find('\n', mend) + 1 or len(body) + 1
2727 begin = body.find('\n', mend) + 1 or len(body) + 1
2726 lend = begin - 1
2728 lend = begin - 1
2727 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2729 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2728
2730
2729 class linestate(object):
2731 class linestate(object):
2730 def __init__(self, line, linenum, colstart, colend):
2732 def __init__(self, line, linenum, colstart, colend):
2731 self.line = line
2733 self.line = line
2732 self.linenum = linenum
2734 self.linenum = linenum
2733 self.colstart = colstart
2735 self.colstart = colstart
2734 self.colend = colend
2736 self.colend = colend
2735
2737
2736 def __hash__(self):
2738 def __hash__(self):
2737 return hash((self.linenum, self.line))
2739 return hash((self.linenum, self.line))
2738
2740
2739 def __eq__(self, other):
2741 def __eq__(self, other):
2740 return self.line == other.line
2742 return self.line == other.line
2741
2743
2742 matches = {}
2744 matches = {}
2743 copies = {}
2745 copies = {}
2744 def grepbody(fn, rev, body):
2746 def grepbody(fn, rev, body):
2745 matches[rev].setdefault(fn, [])
2747 matches[rev].setdefault(fn, [])
2746 m = matches[rev][fn]
2748 m = matches[rev][fn]
2747 for lnum, cstart, cend, line in matchlines(body):
2749 for lnum, cstart, cend, line in matchlines(body):
2748 s = linestate(line, lnum, cstart, cend)
2750 s = linestate(line, lnum, cstart, cend)
2749 m.append(s)
2751 m.append(s)
2750
2752
2751 def difflinestates(a, b):
2753 def difflinestates(a, b):
2752 sm = difflib.SequenceMatcher(None, a, b)
2754 sm = difflib.SequenceMatcher(None, a, b)
2753 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2755 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2754 if tag == 'insert':
2756 if tag == 'insert':
2755 for i in xrange(blo, bhi):
2757 for i in xrange(blo, bhi):
2756 yield ('+', b[i])
2758 yield ('+', b[i])
2757 elif tag == 'delete':
2759 elif tag == 'delete':
2758 for i in xrange(alo, ahi):
2760 for i in xrange(alo, ahi):
2759 yield ('-', a[i])
2761 yield ('-', a[i])
2760 elif tag == 'replace':
2762 elif tag == 'replace':
2761 for i in xrange(alo, ahi):
2763 for i in xrange(alo, ahi):
2762 yield ('-', a[i])
2764 yield ('-', a[i])
2763 for i in xrange(blo, bhi):
2765 for i in xrange(blo, bhi):
2764 yield ('+', b[i])
2766 yield ('+', b[i])
2765
2767
2766 def display(fn, ctx, pstates, states):
2768 def display(fn, ctx, pstates, states):
2767 rev = ctx.rev()
2769 rev = ctx.rev()
2768 datefunc = ui.quiet and util.shortdate or util.datestr
2770 datefunc = ui.quiet and util.shortdate or util.datestr
2769 found = False
2771 found = False
2770 filerevmatches = {}
2772 filerevmatches = {}
2771 def binary():
2773 def binary():
2772 flog = getfile(fn)
2774 flog = getfile(fn)
2773 return util.binary(flog.read(ctx.filenode(fn)))
2775 return util.binary(flog.read(ctx.filenode(fn)))
2774
2776
2775 if opts.get('all'):
2777 if opts.get('all'):
2776 iter = difflinestates(pstates, states)
2778 iter = difflinestates(pstates, states)
2777 else:
2779 else:
2778 iter = [('', l) for l in states]
2780 iter = [('', l) for l in states]
2779 for change, l in iter:
2781 for change, l in iter:
2780 cols = [fn, str(rev)]
2782 cols = [fn, str(rev)]
2781 before, match, after = None, None, None
2783 before, match, after = None, None, None
2782 if opts.get('line_number'):
2784 if opts.get('line_number'):
2783 cols.append(str(l.linenum))
2785 cols.append(str(l.linenum))
2784 if opts.get('all'):
2786 if opts.get('all'):
2785 cols.append(change)
2787 cols.append(change)
2786 if opts.get('user'):
2788 if opts.get('user'):
2787 cols.append(ui.shortuser(ctx.user()))
2789 cols.append(ui.shortuser(ctx.user()))
2788 if opts.get('date'):
2790 if opts.get('date'):
2789 cols.append(datefunc(ctx.date()))
2791 cols.append(datefunc(ctx.date()))
2790 if opts.get('files_with_matches'):
2792 if opts.get('files_with_matches'):
2791 c = (fn, rev)
2793 c = (fn, rev)
2792 if c in filerevmatches:
2794 if c in filerevmatches:
2793 continue
2795 continue
2794 filerevmatches[c] = 1
2796 filerevmatches[c] = 1
2795 else:
2797 else:
2796 before = l.line[:l.colstart]
2798 before = l.line[:l.colstart]
2797 match = l.line[l.colstart:l.colend]
2799 match = l.line[l.colstart:l.colend]
2798 after = l.line[l.colend:]
2800 after = l.line[l.colend:]
2799 ui.write(sep.join(cols))
2801 ui.write(sep.join(cols))
2800 if before is not None:
2802 if before is not None:
2801 if not opts.get('text') and binary():
2803 if not opts.get('text') and binary():
2802 ui.write(sep + " Binary file matches")
2804 ui.write(sep + " Binary file matches")
2803 else:
2805 else:
2804 ui.write(sep + before)
2806 ui.write(sep + before)
2805 ui.write(match, label='grep.match')
2807 ui.write(match, label='grep.match')
2806 ui.write(after)
2808 ui.write(after)
2807 ui.write(eol)
2809 ui.write(eol)
2808 found = True
2810 found = True
2809 return found
2811 return found
2810
2812
2811 skip = {}
2813 skip = {}
2812 revfiles = {}
2814 revfiles = {}
2813 matchfn = scmutil.match(repo[None], pats, opts)
2815 matchfn = scmutil.match(repo[None], pats, opts)
2814 found = False
2816 found = False
2815 follow = opts.get('follow')
2817 follow = opts.get('follow')
2816
2818
2817 def prep(ctx, fns):
2819 def prep(ctx, fns):
2818 rev = ctx.rev()
2820 rev = ctx.rev()
2819 pctx = ctx.p1()
2821 pctx = ctx.p1()
2820 parent = pctx.rev()
2822 parent = pctx.rev()
2821 matches.setdefault(rev, {})
2823 matches.setdefault(rev, {})
2822 matches.setdefault(parent, {})
2824 matches.setdefault(parent, {})
2823 files = revfiles.setdefault(rev, [])
2825 files = revfiles.setdefault(rev, [])
2824 for fn in fns:
2826 for fn in fns:
2825 flog = getfile(fn)
2827 flog = getfile(fn)
2826 try:
2828 try:
2827 fnode = ctx.filenode(fn)
2829 fnode = ctx.filenode(fn)
2828 except error.LookupError:
2830 except error.LookupError:
2829 continue
2831 continue
2830
2832
2831 copied = flog.renamed(fnode)
2833 copied = flog.renamed(fnode)
2832 copy = follow and copied and copied[0]
2834 copy = follow and copied and copied[0]
2833 if copy:
2835 if copy:
2834 copies.setdefault(rev, {})[fn] = copy
2836 copies.setdefault(rev, {})[fn] = copy
2835 if fn in skip:
2837 if fn in skip:
2836 if copy:
2838 if copy:
2837 skip[copy] = True
2839 skip[copy] = True
2838 continue
2840 continue
2839 files.append(fn)
2841 files.append(fn)
2840
2842
2841 if fn not in matches[rev]:
2843 if fn not in matches[rev]:
2842 grepbody(fn, rev, flog.read(fnode))
2844 grepbody(fn, rev, flog.read(fnode))
2843
2845
2844 pfn = copy or fn
2846 pfn = copy or fn
2845 if pfn not in matches[parent]:
2847 if pfn not in matches[parent]:
2846 try:
2848 try:
2847 fnode = pctx.filenode(pfn)
2849 fnode = pctx.filenode(pfn)
2848 grepbody(pfn, parent, flog.read(fnode))
2850 grepbody(pfn, parent, flog.read(fnode))
2849 except error.LookupError:
2851 except error.LookupError:
2850 pass
2852 pass
2851
2853
2852 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2854 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2853 rev = ctx.rev()
2855 rev = ctx.rev()
2854 parent = ctx.p1().rev()
2856 parent = ctx.p1().rev()
2855 for fn in sorted(revfiles.get(rev, [])):
2857 for fn in sorted(revfiles.get(rev, [])):
2856 states = matches[rev][fn]
2858 states = matches[rev][fn]
2857 copy = copies.get(rev, {}).get(fn)
2859 copy = copies.get(rev, {}).get(fn)
2858 if fn in skip:
2860 if fn in skip:
2859 if copy:
2861 if copy:
2860 skip[copy] = True
2862 skip[copy] = True
2861 continue
2863 continue
2862 pstates = matches.get(parent, {}).get(copy or fn, [])
2864 pstates = matches.get(parent, {}).get(copy or fn, [])
2863 if pstates or states:
2865 if pstates or states:
2864 r = display(fn, ctx, pstates, states)
2866 r = display(fn, ctx, pstates, states)
2865 found = found or r
2867 found = found or r
2866 if r and not opts.get('all'):
2868 if r and not opts.get('all'):
2867 skip[fn] = True
2869 skip[fn] = True
2868 if copy:
2870 if copy:
2869 skip[copy] = True
2871 skip[copy] = True
2870 del matches[rev]
2872 del matches[rev]
2871 del revfiles[rev]
2873 del revfiles[rev]
2872
2874
2873 return not found
2875 return not found
2874
2876
2875 @command('heads',
2877 @command('heads',
2876 [('r', 'rev', '',
2878 [('r', 'rev', '',
2877 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2879 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2878 ('t', 'topo', False, _('show topological heads only')),
2880 ('t', 'topo', False, _('show topological heads only')),
2879 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2881 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2880 ('c', 'closed', False, _('show normal and closed branch heads')),
2882 ('c', 'closed', False, _('show normal and closed branch heads')),
2881 ] + templateopts,
2883 ] + templateopts,
2882 _('[-ac] [-r STARTREV] [REV]...'))
2884 _('[-ac] [-r STARTREV] [REV]...'))
2883 def heads(ui, repo, *branchrevs, **opts):
2885 def heads(ui, repo, *branchrevs, **opts):
2884 """show current repository heads or show branch heads
2886 """show current repository heads or show branch heads
2885
2887
2886 With no arguments, show all repository branch heads.
2888 With no arguments, show all repository branch heads.
2887
2889
2888 Repository "heads" are changesets with no child changesets. They are
2890 Repository "heads" are changesets with no child changesets. They are
2889 where development generally takes place and are the usual targets
2891 where development generally takes place and are the usual targets
2890 for update and merge operations. Branch heads are changesets that have
2892 for update and merge operations. Branch heads are changesets that have
2891 no child changeset on the same branch.
2893 no child changeset on the same branch.
2892
2894
2893 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
2894 associated with the specified changesets are shown. This means
2896 associated with the specified changesets are shown. This means
2895 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
2896 named ``foo``.
2898 named ``foo``.
2897
2899
2898 If -c/--closed is specified, also show branch heads marked closed
2900 If -c/--closed is specified, also show branch heads marked closed
2899 (see :hg:`commit --close-branch`).
2901 (see :hg:`commit --close-branch`).
2900
2902
2901 If STARTREV is specified, only those heads that are descendants of
2903 If STARTREV is specified, only those heads that are descendants of
2902 STARTREV will be displayed.
2904 STARTREV will be displayed.
2903
2905
2904 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
2905 changesets without children will be shown.
2907 changesets without children will be shown.
2906
2908
2907 Returns 0 if matching heads are found, 1 if not.
2909 Returns 0 if matching heads are found, 1 if not.
2908 """
2910 """
2909
2911
2910 start = None
2912 start = None
2911 if 'rev' in opts:
2913 if 'rev' in opts:
2912 start = scmutil.revsingle(repo, opts['rev'], None).node()
2914 start = scmutil.revsingle(repo, opts['rev'], None).node()
2913
2915
2914 if opts.get('topo'):
2916 if opts.get('topo'):
2915 heads = [repo[h] for h in repo.heads(start)]
2917 heads = [repo[h] for h in repo.heads(start)]
2916 else:
2918 else:
2917 heads = []
2919 heads = []
2918 for branch in repo.branchmap():
2920 for branch in repo.branchmap():
2919 heads += repo.branchheads(branch, start, opts.get('closed'))
2921 heads += repo.branchheads(branch, start, opts.get('closed'))
2920 heads = [repo[h] for h in heads]
2922 heads = [repo[h] for h in heads]
2921
2923
2922 if branchrevs:
2924 if branchrevs:
2923 branches = set(repo[br].branch() for br in branchrevs)
2925 branches = set(repo[br].branch() for br in branchrevs)
2924 heads = [h for h in heads if h.branch() in branches]
2926 heads = [h for h in heads if h.branch() in branches]
2925
2927
2926 if opts.get('active') and branchrevs:
2928 if opts.get('active') and branchrevs:
2927 dagheads = repo.heads(start)
2929 dagheads = repo.heads(start)
2928 heads = [h for h in heads if h.node() in dagheads]
2930 heads = [h for h in heads if h.node() in dagheads]
2929
2931
2930 if branchrevs:
2932 if branchrevs:
2931 haveheads = set(h.branch() for h in heads)
2933 haveheads = set(h.branch() for h in heads)
2932 if branches - haveheads:
2934 if branches - haveheads:
2933 headless = ', '.join(b for b in branches - haveheads)
2935 headless = ', '.join(b for b in branches - haveheads)
2934 msg = _('no open branch heads found on branches %s')
2936 msg = _('no open branch heads found on branches %s')
2935 if opts.get('rev'):
2937 if opts.get('rev'):
2936 msg += _(' (started at %s)' % opts['rev'])
2938 msg += _(' (started at %s)' % opts['rev'])
2937 ui.warn((msg + '\n') % headless)
2939 ui.warn((msg + '\n') % headless)
2938
2940
2939 if not heads:
2941 if not heads:
2940 return 1
2942 return 1
2941
2943
2942 heads = sorted(heads, key=lambda x: -x.rev())
2944 heads = sorted(heads, key=lambda x: -x.rev())
2943 displayer = cmdutil.show_changeset(ui, repo, opts)
2945 displayer = cmdutil.show_changeset(ui, repo, opts)
2944 for ctx in heads:
2946 for ctx in heads:
2945 displayer.show(ctx)
2947 displayer.show(ctx)
2946 displayer.close()
2948 displayer.close()
2947
2949
2948 @command('help',
2950 @command('help',
2949 [('e', 'extension', None, _('show only help for extensions')),
2951 [('e', 'extension', None, _('show only help for extensions')),
2950 ('c', 'command', None, _('show only help for commands'))],
2952 ('c', 'command', None, _('show only help for commands'))],
2951 _('[-ec] [TOPIC]'))
2953 _('[-ec] [TOPIC]'))
2952 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2954 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2953 """show help for a given topic or a help overview
2955 """show help for a given topic or a help overview
2954
2956
2955 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.
2956
2958
2957 Given a topic, extension, or command name, print help for that
2959 Given a topic, extension, or command name, print help for that
2958 topic.
2960 topic.
2959
2961
2960 Returns 0 if successful.
2962 Returns 0 if successful.
2961 """
2963 """
2962
2964
2963 textwidth = min(ui.termwidth(), 80) - 2
2965 textwidth = min(ui.termwidth(), 80) - 2
2964
2966
2965 def optrst(options):
2967 def optrst(options):
2966 data = []
2968 data = []
2967 multioccur = False
2969 multioccur = False
2968 for option in options:
2970 for option in options:
2969 if len(option) == 5:
2971 if len(option) == 5:
2970 shortopt, longopt, default, desc, optlabel = option
2972 shortopt, longopt, default, desc, optlabel = option
2971 else:
2973 else:
2972 shortopt, longopt, default, desc = option
2974 shortopt, longopt, default, desc = option
2973 optlabel = _("VALUE") # default label
2975 optlabel = _("VALUE") # default label
2974
2976
2975 if _("DEPRECATED") in desc and not ui.verbose:
2977 if _("DEPRECATED") in desc and not ui.verbose:
2976 continue
2978 continue
2977
2979
2978 so = ''
2980 so = ''
2979 if shortopt:
2981 if shortopt:
2980 so = '-' + shortopt
2982 so = '-' + shortopt
2981 lo = '--' + longopt
2983 lo = '--' + longopt
2982 if default:
2984 if default:
2983 desc += _(" (default: %s)") % default
2985 desc += _(" (default: %s)") % default
2984
2986
2985 if isinstance(default, list):
2987 if isinstance(default, list):
2986 lo += " %s [+]" % optlabel
2988 lo += " %s [+]" % optlabel
2987 multioccur = True
2989 multioccur = True
2988 elif (default is not None) and not isinstance(default, bool):
2990 elif (default is not None) and not isinstance(default, bool):
2989 lo += " %s" % optlabel
2991 lo += " %s" % optlabel
2990
2992
2991 data.append((so, lo, desc))
2993 data.append((so, lo, desc))
2992
2994
2993 rst = minirst.maketable(data, 1)
2995 rst = minirst.maketable(data, 1)
2994
2996
2995 if multioccur:
2997 if multioccur:
2996 rst += _("\n[+] marked option can be specified multiple times\n")
2998 rst += _("\n[+] marked option can be specified multiple times\n")
2997
2999
2998 return rst
3000 return rst
2999
3001
3000 # list all option lists
3002 # list all option lists
3001 def opttext(optlist, width):
3003 def opttext(optlist, width):
3002 rst = ''
3004 rst = ''
3003 if not optlist:
3005 if not optlist:
3004 return ''
3006 return ''
3005
3007
3006 for title, options in optlist:
3008 for title, options in optlist:
3007 rst += '\n%s\n' % title
3009 rst += '\n%s\n' % title
3008 if options:
3010 if options:
3009 rst += "\n"
3011 rst += "\n"
3010 rst += optrst(options)
3012 rst += optrst(options)
3011 rst += '\n'
3013 rst += '\n'
3012
3014
3013 return '\n' + minirst.format(rst, width)
3015 return '\n' + minirst.format(rst, width)
3014
3016
3015 def addglobalopts(optlist, aliases):
3017 def addglobalopts(optlist, aliases):
3016 if ui.quiet:
3018 if ui.quiet:
3017 return []
3019 return []
3018
3020
3019 if ui.verbose:
3021 if ui.verbose:
3020 optlist.append((_("global options:"), globalopts))
3022 optlist.append((_("global options:"), globalopts))
3021 if name == 'shortlist':
3023 if name == 'shortlist':
3022 optlist.append((_('use "hg help" for the full list '
3024 optlist.append((_('use "hg help" for the full list '
3023 'of commands'), ()))
3025 'of commands'), ()))
3024 else:
3026 else:
3025 if name == 'shortlist':
3027 if name == 'shortlist':
3026 msg = _('use "hg help" for the full list of commands '
3028 msg = _('use "hg help" for the full list of commands '
3027 'or "hg -v" for details')
3029 'or "hg -v" for details')
3028 elif name and not full:
3030 elif name and not full:
3029 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)
3030 elif aliases:
3032 elif aliases:
3031 msg = _('use "hg -v help%s" to show builtin aliases and '
3033 msg = _('use "hg -v help%s" to show builtin aliases and '
3032 'global options') % (name and " " + name or "")
3034 'global options') % (name and " " + name or "")
3033 else:
3035 else:
3034 msg = _('use "hg -v help %s" to show more info') % name
3036 msg = _('use "hg -v help %s" to show more info') % name
3035 optlist.append((msg, ()))
3037 optlist.append((msg, ()))
3036
3038
3037 def helpcmd(name):
3039 def helpcmd(name):
3038 try:
3040 try:
3039 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3041 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3040 except error.AmbiguousCommand, inst:
3042 except error.AmbiguousCommand, inst:
3041 # 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
3042 # except block, nor can be used inside a lambda. python issue4617
3044 # except block, nor can be used inside a lambda. python issue4617
3043 prefix = inst.args[0]
3045 prefix = inst.args[0]
3044 select = lambda c: c.lstrip('^').startswith(prefix)
3046 select = lambda c: c.lstrip('^').startswith(prefix)
3045 helplist(select)
3047 helplist(select)
3046 return
3048 return
3047
3049
3048 # 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
3049 if getattr(entry[0], 'badalias', False):
3051 if getattr(entry[0], 'badalias', False):
3050 if not unknowncmd:
3052 if not unknowncmd:
3051 entry[0](ui)
3053 entry[0](ui)
3052 return
3054 return
3053
3055
3054 rst = ""
3056 rst = ""
3055
3057
3056 # synopsis
3058 # synopsis
3057 if len(entry) > 2:
3059 if len(entry) > 2:
3058 if entry[2].startswith('hg'):
3060 if entry[2].startswith('hg'):
3059 rst += "%s\n" % entry[2]
3061 rst += "%s\n" % entry[2]
3060 else:
3062 else:
3061 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3063 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3062 else:
3064 else:
3063 rst += 'hg %s\n' % aliases[0]
3065 rst += 'hg %s\n' % aliases[0]
3064
3066
3065 # aliases
3067 # aliases
3066 if full and not ui.quiet and len(aliases) > 1:
3068 if full and not ui.quiet and len(aliases) > 1:
3067 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3069 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3068
3070
3069 # description
3071 # description
3070 doc = gettext(entry[0].__doc__)
3072 doc = gettext(entry[0].__doc__)
3071 if not doc:
3073 if not doc:
3072 doc = _("(no help text available)")
3074 doc = _("(no help text available)")
3073 if util.safehasattr(entry[0], 'definition'): # aliased command
3075 if util.safehasattr(entry[0], 'definition'): # aliased command
3074 if entry[0].definition.startswith('!'): # shell alias
3076 if entry[0].definition.startswith('!'): # shell alias
3075 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3077 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3076 else:
3078 else:
3077 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)
3078 if ui.quiet or not full:
3080 if ui.quiet or not full:
3079 doc = doc.splitlines()[0]
3081 doc = doc.splitlines()[0]
3080 rst += "\n" + doc + "\n"
3082 rst += "\n" + doc + "\n"
3081
3083
3082 # check if this command shadows a non-trivial (multi-line)
3084 # check if this command shadows a non-trivial (multi-line)
3083 # extension help text
3085 # extension help text
3084 try:
3086 try:
3085 mod = extensions.find(name)
3087 mod = extensions.find(name)
3086 doc = gettext(mod.__doc__) or ''
3088 doc = gettext(mod.__doc__) or ''
3087 if '\n' in doc.strip():
3089 if '\n' in doc.strip():
3088 msg = _('use "hg help -e %s" to show help for '
3090 msg = _('use "hg help -e %s" to show help for '
3089 'the %s extension') % (name, name)
3091 'the %s extension') % (name, name)
3090 rst += '\n%s\n' % msg
3092 rst += '\n%s\n' % msg
3091 except KeyError:
3093 except KeyError:
3092 pass
3094 pass
3093
3095
3094 # options
3096 # options
3095 if not ui.quiet and entry[1]:
3097 if not ui.quiet and entry[1]:
3096 rst += '\noptions:\n\n'
3098 rst += '\noptions:\n\n'
3097 rst += optrst(entry[1])
3099 rst += optrst(entry[1])
3098
3100
3099 if ui.verbose:
3101 if ui.verbose:
3100 rst += '\nglobal options:\n\n'
3102 rst += '\nglobal options:\n\n'
3101 rst += optrst(globalopts)
3103 rst += optrst(globalopts)
3102
3104
3103 keep = ui.verbose and ['verbose'] or []
3105 keep = ui.verbose and ['verbose'] or []
3104 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3106 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3105 ui.write(formatted)
3107 ui.write(formatted)
3106
3108
3107 if not ui.verbose:
3109 if not ui.verbose:
3108 if not full:
3110 if not full:
3109 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')
3110 % name)
3112 % name)
3111 elif not ui.quiet:
3113 elif not ui.quiet:
3112 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)
3113
3115
3114
3116
3115 def helplist(select=None):
3117 def helplist(select=None):
3116 # list of commands
3118 # list of commands
3117 if name == "shortlist":
3119 if name == "shortlist":
3118 header = _('basic commands:\n\n')
3120 header = _('basic commands:\n\n')
3119 else:
3121 else:
3120 header = _('list of commands:\n\n')
3122 header = _('list of commands:\n\n')
3121
3123
3122 h = {}
3124 h = {}
3123 cmds = {}
3125 cmds = {}
3124 for c, e in table.iteritems():
3126 for c, e in table.iteritems():
3125 f = c.split("|", 1)[0]
3127 f = c.split("|", 1)[0]
3126 if select and not select(f):
3128 if select and not select(f):
3127 continue
3129 continue
3128 if (not select and name != 'shortlist' and
3130 if (not select and name != 'shortlist' and
3129 e[0].__module__ != __name__):
3131 e[0].__module__ != __name__):
3130 continue
3132 continue
3131 if name == "shortlist" and not f.startswith("^"):
3133 if name == "shortlist" and not f.startswith("^"):
3132 continue
3134 continue
3133 f = f.lstrip("^")
3135 f = f.lstrip("^")
3134 if not ui.debugflag and f.startswith("debug"):
3136 if not ui.debugflag and f.startswith("debug"):
3135 continue
3137 continue
3136 doc = e[0].__doc__
3138 doc = e[0].__doc__
3137 if doc and 'DEPRECATED' in doc and not ui.verbose:
3139 if doc and 'DEPRECATED' in doc and not ui.verbose:
3138 continue
3140 continue
3139 doc = gettext(doc)
3141 doc = gettext(doc)
3140 if not doc:
3142 if not doc:
3141 doc = _("(no help text available)")
3143 doc = _("(no help text available)")
3142 h[f] = doc.splitlines()[0].rstrip()
3144 h[f] = doc.splitlines()[0].rstrip()
3143 cmds[f] = c.lstrip("^")
3145 cmds[f] = c.lstrip("^")
3144
3146
3145 if not h:
3147 if not h:
3146 ui.status(_('no commands defined\n'))
3148 ui.status(_('no commands defined\n'))
3147 return
3149 return
3148
3150
3149 ui.status(header)
3151 ui.status(header)
3150 fns = sorted(h)
3152 fns = sorted(h)
3151 m = max(map(len, fns))
3153 m = max(map(len, fns))
3152 for f in fns:
3154 for f in fns:
3153 if ui.verbose:
3155 if ui.verbose:
3154 commands = cmds[f].replace("|",", ")
3156 commands = cmds[f].replace("|",", ")
3155 ui.write(" %s:\n %s\n"%(commands, h[f]))
3157 ui.write(" %s:\n %s\n"%(commands, h[f]))
3156 else:
3158 else:
3157 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3159 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3158 initindent=' %-*s ' % (m, f),
3160 initindent=' %-*s ' % (m, f),
3159 hangindent=' ' * (m + 4))))
3161 hangindent=' ' * (m + 4))))
3160
3162
3161 if not name:
3163 if not name:
3162 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3164 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3163 if text:
3165 if text:
3164 ui.write("\n%s" % minirst.format(text, textwidth))
3166 ui.write("\n%s" % minirst.format(text, textwidth))
3165
3167
3166 ui.write(_("\nadditional help topics:\n\n"))
3168 ui.write(_("\nadditional help topics:\n\n"))
3167 topics = []
3169 topics = []
3168 for names, header, doc in help.helptable:
3170 for names, header, doc in help.helptable:
3169 topics.append((sorted(names, key=len, reverse=True)[0], header))
3171 topics.append((sorted(names, key=len, reverse=True)[0], header))
3170 topics_len = max([len(s[0]) for s in topics])
3172 topics_len = max([len(s[0]) for s in topics])
3171 for t, desc in topics:
3173 for t, desc in topics:
3172 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3174 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3173
3175
3174 optlist = []
3176 optlist = []
3175 addglobalopts(optlist, True)
3177 addglobalopts(optlist, True)
3176 ui.write(opttext(optlist, textwidth))
3178 ui.write(opttext(optlist, textwidth))
3177
3179
3178 def helptopic(name):
3180 def helptopic(name):
3179 for names, header, doc in help.helptable:
3181 for names, header, doc in help.helptable:
3180 if name in names:
3182 if name in names:
3181 break
3183 break
3182 else:
3184 else:
3183 raise error.UnknownCommand(name)
3185 raise error.UnknownCommand(name)
3184
3186
3185 # description
3187 # description
3186 if not doc:
3188 if not doc:
3187 doc = _("(no help text available)")
3189 doc = _("(no help text available)")
3188 if util.safehasattr(doc, '__call__'):
3190 if util.safehasattr(doc, '__call__'):
3189 doc = doc()
3191 doc = doc()
3190
3192
3191 ui.write("%s\n\n" % header)
3193 ui.write("%s\n\n" % header)
3192 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3194 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3193 try:
3195 try:
3194 cmdutil.findcmd(name, table)
3196 cmdutil.findcmd(name, table)
3195 ui.write(_('\nuse "hg help -c %s" to see help for '
3197 ui.write(_('\nuse "hg help -c %s" to see help for '
3196 'the %s command\n') % (name, name))
3198 'the %s command\n') % (name, name))
3197 except error.UnknownCommand:
3199 except error.UnknownCommand:
3198 pass
3200 pass
3199
3201
3200 def helpext(name):
3202 def helpext(name):
3201 try:
3203 try:
3202 mod = extensions.find(name)
3204 mod = extensions.find(name)
3203 doc = gettext(mod.__doc__) or _('no help text available')
3205 doc = gettext(mod.__doc__) or _('no help text available')
3204 except KeyError:
3206 except KeyError:
3205 mod = None
3207 mod = None
3206 doc = extensions.disabledext(name)
3208 doc = extensions.disabledext(name)
3207 if not doc:
3209 if not doc:
3208 raise error.UnknownCommand(name)
3210 raise error.UnknownCommand(name)
3209
3211
3210 if '\n' not in doc:
3212 if '\n' not in doc:
3211 head, tail = doc, ""
3213 head, tail = doc, ""
3212 else:
3214 else:
3213 head, tail = doc.split('\n', 1)
3215 head, tail = doc.split('\n', 1)
3214 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3216 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3215 if tail:
3217 if tail:
3216 ui.write(minirst.format(tail, textwidth))
3218 ui.write(minirst.format(tail, textwidth))
3217 ui.status('\n')
3219 ui.status('\n')
3218
3220
3219 if mod:
3221 if mod:
3220 try:
3222 try:
3221 ct = mod.cmdtable
3223 ct = mod.cmdtable
3222 except AttributeError:
3224 except AttributeError:
3223 ct = {}
3225 ct = {}
3224 modcmds = set([c.split('|', 1)[0] for c in ct])
3226 modcmds = set([c.split('|', 1)[0] for c in ct])
3225 helplist(modcmds.__contains__)
3227 helplist(modcmds.__contains__)
3226 else:
3228 else:
3227 ui.write(_('use "hg help extensions" for information on enabling '
3229 ui.write(_('use "hg help extensions" for information on enabling '
3228 'extensions\n'))
3230 'extensions\n'))
3229
3231
3230 def helpextcmd(name):
3232 def helpextcmd(name):
3231 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3233 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3232 doc = gettext(mod.__doc__).splitlines()[0]
3234 doc = gettext(mod.__doc__).splitlines()[0]
3233
3235
3234 msg = help.listexts(_("'%s' is provided by the following "
3236 msg = help.listexts(_("'%s' is provided by the following "
3235 "extension:") % cmd, {ext: doc}, indent=4)
3237 "extension:") % cmd, {ext: doc}, indent=4)
3236 ui.write(minirst.format(msg, textwidth))
3238 ui.write(minirst.format(msg, textwidth))
3237 ui.write('\n')
3239 ui.write('\n')
3238 ui.write(_('use "hg help extensions" for information on enabling '
3240 ui.write(_('use "hg help extensions" for information on enabling '
3239 'extensions\n'))
3241 'extensions\n'))
3240
3242
3241 if name and name != 'shortlist':
3243 if name and name != 'shortlist':
3242 i = None
3244 i = None
3243 if unknowncmd:
3245 if unknowncmd:
3244 queries = (helpextcmd,)
3246 queries = (helpextcmd,)
3245 elif opts.get('extension'):
3247 elif opts.get('extension'):
3246 queries = (helpext,)
3248 queries = (helpext,)
3247 elif opts.get('command'):
3249 elif opts.get('command'):
3248 queries = (helpcmd,)
3250 queries = (helpcmd,)
3249 else:
3251 else:
3250 queries = (helptopic, helpcmd, helpext, helpextcmd)
3252 queries = (helptopic, helpcmd, helpext, helpextcmd)
3251 for f in queries:
3253 for f in queries:
3252 try:
3254 try:
3253 f(name)
3255 f(name)
3254 i = None
3256 i = None
3255 break
3257 break
3256 except error.UnknownCommand, inst:
3258 except error.UnknownCommand, inst:
3257 i = inst
3259 i = inst
3258 if i:
3260 if i:
3259 raise i
3261 raise i
3260 else:
3262 else:
3261 # program name
3263 # program name
3262 ui.status(_("Mercurial Distributed SCM\n"))
3264 ui.status(_("Mercurial Distributed SCM\n"))
3263 ui.status('\n')
3265 ui.status('\n')
3264 helplist()
3266 helplist()
3265
3267
3266
3268
3267 @command('identify|id',
3269 @command('identify|id',
3268 [('r', 'rev', '',
3270 [('r', 'rev', '',
3269 _('identify the specified revision'), _('REV')),
3271 _('identify the specified revision'), _('REV')),
3270 ('n', 'num', None, _('show local revision number')),
3272 ('n', 'num', None, _('show local revision number')),
3271 ('i', 'id', None, _('show global revision id')),
3273 ('i', 'id', None, _('show global revision id')),
3272 ('b', 'branch', None, _('show branch')),
3274 ('b', 'branch', None, _('show branch')),
3273 ('t', 'tags', None, _('show tags')),
3275 ('t', 'tags', None, _('show tags')),
3274 ('B', 'bookmarks', None, _('show bookmarks')),
3276 ('B', 'bookmarks', None, _('show bookmarks')),
3275 ] + remoteopts,
3277 ] + remoteopts,
3276 _('[-nibtB] [-r REV] [SOURCE]'))
3278 _('[-nibtB] [-r REV] [SOURCE]'))
3277 def identify(ui, repo, source=None, rev=None,
3279 def identify(ui, repo, source=None, rev=None,
3278 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3280 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3279 """identify the working copy or specified revision
3281 """identify the working copy or specified revision
3280
3282
3281 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
3282 two parent hash identifiers, followed by a "+" if the working
3284 two parent hash identifiers, followed by a "+" if the working
3283 directory has uncommitted changes, the branch name (if not default),
3285 directory has uncommitted changes, the branch name (if not default),
3284 a list of tags, and a list of bookmarks.
3286 a list of tags, and a list of bookmarks.
3285
3287
3286 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
3287 repository.
3289 repository.
3288
3290
3289 Specifying a path to a repository root or Mercurial bundle will
3291 Specifying a path to a repository root or Mercurial bundle will
3290 cause lookup to operate on that repository/bundle.
3292 cause lookup to operate on that repository/bundle.
3291
3293
3292 .. container:: verbose
3294 .. container:: verbose
3293
3295
3294 Examples:
3296 Examples:
3295
3297
3296 - generate a build identifier for the working directory::
3298 - generate a build identifier for the working directory::
3297
3299
3298 hg id --id > build-id.dat
3300 hg id --id > build-id.dat
3299
3301
3300 - find the revision corresponding to a tag::
3302 - find the revision corresponding to a tag::
3301
3303
3302 hg id -n -r 1.3
3304 hg id -n -r 1.3
3303
3305
3304 - check the most recent revision of a remote repository::
3306 - check the most recent revision of a remote repository::
3305
3307
3306 hg id -r tip http://selenic.com/hg/
3308 hg id -r tip http://selenic.com/hg/
3307
3309
3308 Returns 0 if successful.
3310 Returns 0 if successful.
3309 """
3311 """
3310
3312
3311 if not repo and not source:
3313 if not repo and not source:
3312 raise util.Abort(_("there is no Mercurial repository here "
3314 raise util.Abort(_("there is no Mercurial repository here "
3313 "(.hg not found)"))
3315 "(.hg not found)"))
3314
3316
3315 hexfunc = ui.debugflag and hex or short
3317 hexfunc = ui.debugflag and hex or short
3316 default = not (num or id or branch or tags or bookmarks)
3318 default = not (num or id or branch or tags or bookmarks)
3317 output = []
3319 output = []
3318 revs = []
3320 revs = []
3319
3321
3320 if source:
3322 if source:
3321 source, branches = hg.parseurl(ui.expandpath(source))
3323 source, branches = hg.parseurl(ui.expandpath(source))
3322 repo = hg.peer(ui, opts, source)
3324 repo = hg.peer(ui, opts, source)
3323 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3325 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3324
3326
3325 if not repo.local():
3327 if not repo.local():
3326 if num or branch or tags:
3328 if num or branch or tags:
3327 raise util.Abort(
3329 raise util.Abort(
3328 _("can't query remote revision number, branch, or tags"))
3330 _("can't query remote revision number, branch, or tags"))
3329 if not rev and revs:
3331 if not rev and revs:
3330 rev = revs[0]
3332 rev = revs[0]
3331 if not rev:
3333 if not rev:
3332 rev = "tip"
3334 rev = "tip"
3333
3335
3334 remoterev = repo.lookup(rev)
3336 remoterev = repo.lookup(rev)
3335 if default or id:
3337 if default or id:
3336 output = [hexfunc(remoterev)]
3338 output = [hexfunc(remoterev)]
3337
3339
3338 def getbms():
3340 def getbms():
3339 bms = []
3341 bms = []
3340
3342
3341 if 'bookmarks' in repo.listkeys('namespaces'):
3343 if 'bookmarks' in repo.listkeys('namespaces'):
3342 hexremoterev = hex(remoterev)
3344 hexremoterev = hex(remoterev)
3343 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3345 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3344 if bmr == hexremoterev]
3346 if bmr == hexremoterev]
3345
3347
3346 return bms
3348 return bms
3347
3349
3348 if bookmarks:
3350 if bookmarks:
3349 output.extend(getbms())
3351 output.extend(getbms())
3350 elif default and not ui.quiet:
3352 elif default and not ui.quiet:
3351 # multiple bookmarks for a single parent separated by '/'
3353 # multiple bookmarks for a single parent separated by '/'
3352 bm = '/'.join(getbms())
3354 bm = '/'.join(getbms())
3353 if bm:
3355 if bm:
3354 output.append(bm)
3356 output.append(bm)
3355 else:
3357 else:
3356 if not rev:
3358 if not rev:
3357 ctx = repo[None]
3359 ctx = repo[None]
3358 parents = ctx.parents()
3360 parents = ctx.parents()
3359 changed = ""
3361 changed = ""
3360 if default or id or num:
3362 if default or id or num:
3361 changed = util.any(repo.status()) and "+" or ""
3363 changed = util.any(repo.status()) and "+" or ""
3362 if default or id:
3364 if default or id:
3363 output = ["%s%s" %
3365 output = ["%s%s" %
3364 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3366 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3365 if num:
3367 if num:
3366 output.append("%s%s" %
3368 output.append("%s%s" %
3367 ('+'.join([str(p.rev()) for p in parents]), changed))
3369 ('+'.join([str(p.rev()) for p in parents]), changed))
3368 else:
3370 else:
3369 ctx = scmutil.revsingle(repo, rev)
3371 ctx = scmutil.revsingle(repo, rev)
3370 if default or id:
3372 if default or id:
3371 output = [hexfunc(ctx.node())]
3373 output = [hexfunc(ctx.node())]
3372 if num:
3374 if num:
3373 output.append(str(ctx.rev()))
3375 output.append(str(ctx.rev()))
3374
3376
3375 if default and not ui.quiet:
3377 if default and not ui.quiet:
3376 b = ctx.branch()
3378 b = ctx.branch()
3377 if b != 'default':
3379 if b != 'default':
3378 output.append("(%s)" % b)
3380 output.append("(%s)" % b)
3379
3381
3380 # multiple tags for a single parent separated by '/'
3382 # multiple tags for a single parent separated by '/'
3381 t = '/'.join(ctx.tags())
3383 t = '/'.join(ctx.tags())
3382 if t:
3384 if t:
3383 output.append(t)
3385 output.append(t)
3384
3386
3385 # multiple bookmarks for a single parent separated by '/'
3387 # multiple bookmarks for a single parent separated by '/'
3386 bm = '/'.join(ctx.bookmarks())
3388 bm = '/'.join(ctx.bookmarks())
3387 if bm:
3389 if bm:
3388 output.append(bm)
3390 output.append(bm)
3389 else:
3391 else:
3390 if branch:
3392 if branch:
3391 output.append(ctx.branch())
3393 output.append(ctx.branch())
3392
3394
3393 if tags:
3395 if tags:
3394 output.extend(ctx.tags())
3396 output.extend(ctx.tags())
3395
3397
3396 if bookmarks:
3398 if bookmarks:
3397 output.extend(ctx.bookmarks())
3399 output.extend(ctx.bookmarks())
3398
3400
3399 ui.write("%s\n" % ' '.join(output))
3401 ui.write("%s\n" % ' '.join(output))
3400
3402
3401 @command('import|patch',
3403 @command('import|patch',
3402 [('p', 'strip', 1,
3404 [('p', 'strip', 1,
3403 _('directory strip option for patch. This has the same '
3405 _('directory strip option for patch. This has the same '
3404 'meaning as the corresponding patch option'), _('NUM')),
3406 'meaning as the corresponding patch option'), _('NUM')),
3405 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3407 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3406 ('e', 'edit', False, _('invoke editor on commit messages')),
3408 ('e', 'edit', False, _('invoke editor on commit messages')),
3407 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3409 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3408 ('', 'no-commit', None,
3410 ('', 'no-commit', None,
3409 _("don't commit, just update the working directory")),
3411 _("don't commit, just update the working directory")),
3410 ('', 'bypass', None,
3412 ('', 'bypass', None,
3411 _("apply patch without touching the working directory")),
3413 _("apply patch without touching the working directory")),
3412 ('', 'exact', None,
3414 ('', 'exact', None,
3413 _('apply patch to the nodes from which it was generated')),
3415 _('apply patch to the nodes from which it was generated')),
3414 ('', 'import-branch', None,
3416 ('', 'import-branch', None,
3415 _('use any branch information in patch (implied by --exact)'))] +
3417 _('use any branch information in patch (implied by --exact)'))] +
3416 commitopts + commitopts2 + similarityopts,
3418 commitopts + commitopts2 + similarityopts,
3417 _('[OPTION]... PATCH...'))
3419 _('[OPTION]... PATCH...'))
3418 def import_(ui, repo, patch1=None, *patches, **opts):
3420 def import_(ui, repo, patch1=None, *patches, **opts):
3419 """import an ordered set of patches
3421 """import an ordered set of patches
3420
3422
3421 Import a list of patches and commit them individually (unless
3423 Import a list of patches and commit them individually (unless
3422 --no-commit is specified).
3424 --no-commit is specified).
3423
3425
3424 If there are outstanding changes in the working directory, import
3426 If there are outstanding changes in the working directory, import
3425 will abort unless given the -f/--force flag.
3427 will abort unless given the -f/--force flag.
3426
3428
3427 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
3428 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
3429 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
3430 message are used as default committer and commit message. All
3432 message are used as default committer and commit message. All
3431 text/plain body parts before first diff are added to commit
3433 text/plain body parts before first diff are added to commit
3432 message.
3434 message.
3433
3435
3434 If the imported patch was generated by :hg:`export`, user and
3436 If the imported patch was generated by :hg:`export`, user and
3435 description from patch override values from message headers and
3437 description from patch override values from message headers and
3436 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
3437 override these.
3439 override these.
3438
3440
3439 If --exact is specified, import will set the working directory to
3441 If --exact is specified, import will set the working directory to
3440 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
3441 resulting changeset has a different ID than the one recorded in
3443 resulting changeset has a different ID than the one recorded in
3442 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
3443 deficiencies in the text patch format.
3445 deficiencies in the text patch format.
3444
3446
3445 Use --bypass to apply and commit patches directly to the
3447 Use --bypass to apply and commit patches directly to the
3446 repository, not touching the working directory. Without --exact,
3448 repository, not touching the working directory. Without --exact,
3447 patches will be applied on top of the working directory parent
3449 patches will be applied on top of the working directory parent
3448 revision.
3450 revision.
3449
3451
3450 With -s/--similarity, hg will attempt to discover renames and
3452 With -s/--similarity, hg will attempt to discover renames and
3451 copies in the patch in the same way as :hg:`addremove`.
3453 copies in the patch in the same way as :hg:`addremove`.
3452
3454
3453 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
3454 a URL is specified, the patch will be downloaded from it.
3456 a URL is specified, the patch will be downloaded from it.
3455 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.
3456
3458
3457 .. container:: verbose
3459 .. container:: verbose
3458
3460
3459 Examples:
3461 Examples:
3460
3462
3461 - import a traditional patch from a website and detect renames::
3463 - import a traditional patch from a website and detect renames::
3462
3464
3463 hg import -s 80 http://example.com/bugfix.patch
3465 hg import -s 80 http://example.com/bugfix.patch
3464
3466
3465 - import a changeset from an hgweb server::
3467 - import a changeset from an hgweb server::
3466
3468
3467 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3469 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3468
3470
3469 - import all the patches in an Unix-style mbox::
3471 - import all the patches in an Unix-style mbox::
3470
3472
3471 hg import incoming-patches.mbox
3473 hg import incoming-patches.mbox
3472
3474
3473 - attempt to exactly restore an exported changeset (not always
3475 - attempt to exactly restore an exported changeset (not always
3474 possible)::
3476 possible)::
3475
3477
3476 hg import --exact proposed-fix.patch
3478 hg import --exact proposed-fix.patch
3477
3479
3478 Returns 0 on success.
3480 Returns 0 on success.
3479 """
3481 """
3480
3482
3481 if not patch1:
3483 if not patch1:
3482 raise util.Abort(_('need at least one patch to import'))
3484 raise util.Abort(_('need at least one patch to import'))
3483
3485
3484 patches = (patch1,) + patches
3486 patches = (patch1,) + patches
3485
3487
3486 date = opts.get('date')
3488 date = opts.get('date')
3487 if date:
3489 if date:
3488 opts['date'] = util.parsedate(date)
3490 opts['date'] = util.parsedate(date)
3489
3491
3490 editor = cmdutil.commiteditor
3492 editor = cmdutil.commiteditor
3491 if opts.get('edit'):
3493 if opts.get('edit'):
3492 editor = cmdutil.commitforceeditor
3494 editor = cmdutil.commitforceeditor
3493
3495
3494 update = not opts.get('bypass')
3496 update = not opts.get('bypass')
3495 if not update and opts.get('no_commit'):
3497 if not update and opts.get('no_commit'):
3496 raise util.Abort(_('cannot use --no-commit with --bypass'))
3498 raise util.Abort(_('cannot use --no-commit with --bypass'))
3497 try:
3499 try:
3498 sim = float(opts.get('similarity') or 0)
3500 sim = float(opts.get('similarity') or 0)
3499 except ValueError:
3501 except ValueError:
3500 raise util.Abort(_('similarity must be a number'))
3502 raise util.Abort(_('similarity must be a number'))
3501 if sim < 0 or sim > 100:
3503 if sim < 0 or sim > 100:
3502 raise util.Abort(_('similarity must be between 0 and 100'))
3504 raise util.Abort(_('similarity must be between 0 and 100'))
3503 if sim and not update:
3505 if sim and not update:
3504 raise util.Abort(_('cannot use --similarity with --bypass'))
3506 raise util.Abort(_('cannot use --similarity with --bypass'))
3505
3507
3506 if (opts.get('exact') or not opts.get('force')) and update:
3508 if (opts.get('exact') or not opts.get('force')) and update:
3507 cmdutil.bailifchanged(repo)
3509 cmdutil.bailifchanged(repo)
3508
3510
3509 base = opts["base"]
3511 base = opts["base"]
3510 strip = opts["strip"]
3512 strip = opts["strip"]
3511 wlock = lock = tr = None
3513 wlock = lock = tr = None
3512 msgs = []
3514 msgs = []
3513
3515
3514 def checkexact(repo, n, nodeid):
3516 def checkexact(repo, n, nodeid):
3515 if opts.get('exact') and hex(n) != nodeid:
3517 if opts.get('exact') and hex(n) != nodeid:
3516 repo.rollback()
3518 repo.rollback()
3517 raise util.Abort(_('patch is damaged or loses information'))
3519 raise util.Abort(_('patch is damaged or loses information'))
3518
3520
3519 def tryone(ui, hunk, parents):
3521 def tryone(ui, hunk, parents):
3520 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3522 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3521 patch.extract(ui, hunk)
3523 patch.extract(ui, hunk)
3522
3524
3523 if not tmpname:
3525 if not tmpname:
3524 return (None, None)
3526 return (None, None)
3525 msg = _('applied to working directory')
3527 msg = _('applied to working directory')
3526
3528
3527 try:
3529 try:
3528 cmdline_message = cmdutil.logmessage(ui, opts)
3530 cmdline_message = cmdutil.logmessage(ui, opts)
3529 if cmdline_message:
3531 if cmdline_message:
3530 # pickup the cmdline msg
3532 # pickup the cmdline msg
3531 message = cmdline_message
3533 message = cmdline_message
3532 elif message:
3534 elif message:
3533 # pickup the patch msg
3535 # pickup the patch msg
3534 message = message.strip()
3536 message = message.strip()
3535 else:
3537 else:
3536 # launch the editor
3538 # launch the editor
3537 message = None
3539 message = None
3538 ui.debug('message:\n%s\n' % message)
3540 ui.debug('message:\n%s\n' % message)
3539
3541
3540 if len(parents) == 1:
3542 if len(parents) == 1:
3541 parents.append(repo[nullid])
3543 parents.append(repo[nullid])
3542 if opts.get('exact'):
3544 if opts.get('exact'):
3543 if not nodeid or not p1:
3545 if not nodeid or not p1:
3544 raise util.Abort(_('not a Mercurial patch'))
3546 raise util.Abort(_('not a Mercurial patch'))
3545 p1 = repo[p1]
3547 p1 = repo[p1]
3546 p2 = repo[p2 or nullid]
3548 p2 = repo[p2 or nullid]
3547 elif p2:
3549 elif p2:
3548 try:
3550 try:
3549 p1 = repo[p1]
3551 p1 = repo[p1]
3550 p2 = repo[p2]
3552 p2 = repo[p2]
3551 # Without any options, consider p2 only if the
3553 # Without any options, consider p2 only if the
3552 # patch is being applied on top of the recorded
3554 # patch is being applied on top of the recorded
3553 # first parent.
3555 # first parent.
3554 if p1 != parents[0]:
3556 if p1 != parents[0]:
3555 p1 = parents[0]
3557 p1 = parents[0]
3556 p2 = repo[nullid]
3558 p2 = repo[nullid]
3557 except error.RepoError:
3559 except error.RepoError:
3558 p1, p2 = parents
3560 p1, p2 = parents
3559 else:
3561 else:
3560 p1, p2 = parents
3562 p1, p2 = parents
3561
3563
3562 n = None
3564 n = None
3563 if update:
3565 if update:
3564 if p1 != parents[0]:
3566 if p1 != parents[0]:
3565 hg.clean(repo, p1.node())
3567 hg.clean(repo, p1.node())
3566 if p2 != parents[1]:
3568 if p2 != parents[1]:
3567 repo.dirstate.setparents(p1.node(), p2.node())
3569 repo.dirstate.setparents(p1.node(), p2.node())
3568
3570
3569 if opts.get('exact') or opts.get('import_branch'):
3571 if opts.get('exact') or opts.get('import_branch'):
3570 repo.dirstate.setbranch(branch or 'default')
3572 repo.dirstate.setbranch(branch or 'default')
3571
3573
3572 files = set()
3574 files = set()
3573 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3575 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3574 eolmode=None, similarity=sim / 100.0)
3576 eolmode=None, similarity=sim / 100.0)
3575 files = list(files)
3577 files = list(files)
3576 if opts.get('no_commit'):
3578 if opts.get('no_commit'):
3577 if message:
3579 if message:
3578 msgs.append(message)
3580 msgs.append(message)
3579 else:
3581 else:
3580 if opts.get('exact') or p2:
3582 if opts.get('exact') or p2:
3581 # If you got here, you either use --force and know what
3583 # If you got here, you either use --force and know what
3582 # you are doing or used --exact or a merge patch while
3584 # you are doing or used --exact or a merge patch while
3583 # being updated to its first parent.
3585 # being updated to its first parent.
3584 m = None
3586 m = None
3585 else:
3587 else:
3586 m = scmutil.matchfiles(repo, files or [])
3588 m = scmutil.matchfiles(repo, files or [])
3587 n = repo.commit(message, opts.get('user') or user,
3589 n = repo.commit(message, opts.get('user') or user,
3588 opts.get('date') or date, match=m,
3590 opts.get('date') or date, match=m,
3589 editor=editor)
3591 editor=editor)
3590 checkexact(repo, n, nodeid)
3592 checkexact(repo, n, nodeid)
3591 else:
3593 else:
3592 if opts.get('exact') or opts.get('import_branch'):
3594 if opts.get('exact') or opts.get('import_branch'):
3593 branch = branch or 'default'
3595 branch = branch or 'default'
3594 else:
3596 else:
3595 branch = p1.branch()
3597 branch = p1.branch()
3596 store = patch.filestore()
3598 store = patch.filestore()
3597 try:
3599 try:
3598 files = set()
3600 files = set()
3599 try:
3601 try:
3600 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3602 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3601 files, eolmode=None)
3603 files, eolmode=None)
3602 except patch.PatchError, e:
3604 except patch.PatchError, e:
3603 raise util.Abort(str(e))
3605 raise util.Abort(str(e))
3604 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3606 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3605 message,
3607 message,
3606 opts.get('user') or user,
3608 opts.get('user') or user,
3607 opts.get('date') or date,
3609 opts.get('date') or date,
3608 branch, files, store,
3610 branch, files, store,
3609 editor=cmdutil.commiteditor)
3611 editor=cmdutil.commiteditor)
3610 repo.savecommitmessage(memctx.description())
3612 repo.savecommitmessage(memctx.description())
3611 n = memctx.commit()
3613 n = memctx.commit()
3612 checkexact(repo, n, nodeid)
3614 checkexact(repo, n, nodeid)
3613 finally:
3615 finally:
3614 store.close()
3616 store.close()
3615 if n:
3617 if n:
3616 # i18n: refers to a short changeset id
3618 # i18n: refers to a short changeset id
3617 msg = _('created %s') % short(n)
3619 msg = _('created %s') % short(n)
3618 return (msg, n)
3620 return (msg, n)
3619 finally:
3621 finally:
3620 os.unlink(tmpname)
3622 os.unlink(tmpname)
3621
3623
3622 try:
3624 try:
3623 try:
3625 try:
3624 wlock = repo.wlock()
3626 wlock = repo.wlock()
3625 lock = repo.lock()
3627 lock = repo.lock()
3626 tr = repo.transaction('import')
3628 tr = repo.transaction('import')
3627 parents = repo.parents()
3629 parents = repo.parents()
3628 for patchurl in patches:
3630 for patchurl in patches:
3629 if patchurl == '-':
3631 if patchurl == '-':
3630 ui.status(_('applying patch from stdin\n'))
3632 ui.status(_('applying patch from stdin\n'))
3631 patchfile = ui.fin
3633 patchfile = ui.fin
3632 patchurl = 'stdin' # for error message
3634 patchurl = 'stdin' # for error message
3633 else:
3635 else:
3634 patchurl = os.path.join(base, patchurl)
3636 patchurl = os.path.join(base, patchurl)
3635 ui.status(_('applying %s\n') % patchurl)
3637 ui.status(_('applying %s\n') % patchurl)
3636 patchfile = url.open(ui, patchurl)
3638 patchfile = url.open(ui, patchurl)
3637
3639
3638 haspatch = False
3640 haspatch = False
3639 for hunk in patch.split(patchfile):
3641 for hunk in patch.split(patchfile):
3640 (msg, node) = tryone(ui, hunk, parents)
3642 (msg, node) = tryone(ui, hunk, parents)
3641 if msg:
3643 if msg:
3642 haspatch = True
3644 haspatch = True
3643 ui.note(msg + '\n')
3645 ui.note(msg + '\n')
3644 if update or opts.get('exact'):
3646 if update or opts.get('exact'):
3645 parents = repo.parents()
3647 parents = repo.parents()
3646 else:
3648 else:
3647 parents = [repo[node]]
3649 parents = [repo[node]]
3648
3650
3649 if not haspatch:
3651 if not haspatch:
3650 raise util.Abort(_('%s: no diffs found') % patchurl)
3652 raise util.Abort(_('%s: no diffs found') % patchurl)
3651
3653
3652 tr.close()
3654 tr.close()
3653 if msgs:
3655 if msgs:
3654 repo.savecommitmessage('\n* * *\n'.join(msgs))
3656 repo.savecommitmessage('\n* * *\n'.join(msgs))
3655 except:
3657 except:
3656 # wlock.release() indirectly calls dirstate.write(): since
3658 # wlock.release() indirectly calls dirstate.write(): since
3657 # 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
3658 # parent after all, so make sure it writes nothing
3660 # parent after all, so make sure it writes nothing
3659 repo.dirstate.invalidate()
3661 repo.dirstate.invalidate()
3660 raise
3662 raise
3661 finally:
3663 finally:
3662 if tr:
3664 if tr:
3663 tr.release()
3665 tr.release()
3664 release(lock, wlock)
3666 release(lock, wlock)
3665
3667
3666 @command('incoming|in',
3668 @command('incoming|in',
3667 [('f', 'force', None,
3669 [('f', 'force', None,
3668 _('run even if remote repository is unrelated')),
3670 _('run even if remote repository is unrelated')),
3669 ('n', 'newest-first', None, _('show newest record first')),
3671 ('n', 'newest-first', None, _('show newest record first')),
3670 ('', 'bundle', '',
3672 ('', 'bundle', '',
3671 _('file to store the bundles into'), _('FILE')),
3673 _('file to store the bundles into'), _('FILE')),
3672 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3674 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3673 ('B', 'bookmarks', False, _("compare bookmarks")),
3675 ('B', 'bookmarks', False, _("compare bookmarks")),
3674 ('b', 'branch', [],
3676 ('b', 'branch', [],
3675 _('a specific branch you would like to pull'), _('BRANCH')),
3677 _('a specific branch you would like to pull'), _('BRANCH')),
3676 ] + logopts + remoteopts + subrepoopts,
3678 ] + logopts + remoteopts + subrepoopts,
3677 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3679 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3678 def incoming(ui, repo, source="default", **opts):
3680 def incoming(ui, repo, source="default", **opts):
3679 """show new changesets found in source
3681 """show new changesets found in source
3680
3682
3681 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
3682 pull location. These are the changesets that would have been pulled
3684 pull location. These are the changesets that would have been pulled
3683 if a pull at the time you issued this command.
3685 if a pull at the time you issued this command.
3684
3686
3685 For remote repository, using --bundle avoids downloading the
3687 For remote repository, using --bundle avoids downloading the
3686 changesets twice if the incoming is followed by a pull.
3688 changesets twice if the incoming is followed by a pull.
3687
3689
3688 See pull for valid source format details.
3690 See pull for valid source format details.
3689
3691
3690 Returns 0 if there are incoming changes, 1 otherwise.
3692 Returns 0 if there are incoming changes, 1 otherwise.
3691 """
3693 """
3692 if opts.get('bundle') and opts.get('subrepos'):
3694 if opts.get('bundle') and opts.get('subrepos'):
3693 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3695 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3694
3696
3695 if opts.get('bookmarks'):
3697 if opts.get('bookmarks'):
3696 source, branches = hg.parseurl(ui.expandpath(source),
3698 source, branches = hg.parseurl(ui.expandpath(source),
3697 opts.get('branch'))
3699 opts.get('branch'))
3698 other = hg.peer(repo, opts, source)
3700 other = hg.peer(repo, opts, source)
3699 if 'bookmarks' not in other.listkeys('namespaces'):
3701 if 'bookmarks' not in other.listkeys('namespaces'):
3700 ui.warn(_("remote doesn't support bookmarks\n"))
3702 ui.warn(_("remote doesn't support bookmarks\n"))
3701 return 0
3703 return 0
3702 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3704 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3703 return bookmarks.diff(ui, repo, other)
3705 return bookmarks.diff(ui, repo, other)
3704
3706
3705 repo._subtoppath = ui.expandpath(source)
3707 repo._subtoppath = ui.expandpath(source)
3706 try:
3708 try:
3707 return hg.incoming(ui, repo, source, opts)
3709 return hg.incoming(ui, repo, source, opts)
3708 finally:
3710 finally:
3709 del repo._subtoppath
3711 del repo._subtoppath
3710
3712
3711
3713
3712 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3714 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3713 def init(ui, dest=".", **opts):
3715 def init(ui, dest=".", **opts):
3714 """create a new repository in the given directory
3716 """create a new repository in the given directory
3715
3717
3716 Initialize a new repository in the given directory. If the given
3718 Initialize a new repository in the given directory. If the given
3717 directory does not exist, it will be created.
3719 directory does not exist, it will be created.
3718
3720
3719 If no directory is given, the current directory is used.
3721 If no directory is given, the current directory is used.
3720
3722
3721 It is possible to specify an ``ssh://`` URL as the destination.
3723 It is possible to specify an ``ssh://`` URL as the destination.
3722 See :hg:`help urls` for more information.
3724 See :hg:`help urls` for more information.
3723
3725
3724 Returns 0 on success.
3726 Returns 0 on success.
3725 """
3727 """
3726 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3728 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3727
3729
3728 @command('locate',
3730 @command('locate',
3729 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3731 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3730 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3732 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3731 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3733 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3732 ] + walkopts,
3734 ] + walkopts,
3733 _('[OPTION]... [PATTERN]...'))
3735 _('[OPTION]... [PATTERN]...'))
3734 def locate(ui, repo, *pats, **opts):
3736 def locate(ui, repo, *pats, **opts):
3735 """locate files matching specific patterns
3737 """locate files matching specific patterns
3736
3738
3737 Print files under Mercurial control in the working directory whose
3739 Print files under Mercurial control in the working directory whose
3738 names match the given patterns.
3740 names match the given patterns.
3739
3741
3740 By default, this command searches all directories in the working
3742 By default, this command searches all directories in the working
3741 directory. To search just the current directory and its
3743 directory. To search just the current directory and its
3742 subdirectories, use "--include .".
3744 subdirectories, use "--include .".
3743
3745
3744 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
3745 of all files under Mercurial control in the working directory.
3747 of all files under Mercurial control in the working directory.
3746
3748
3747 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"
3748 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
3749 will avoid the problem of "xargs" treating single filenames that
3751 will avoid the problem of "xargs" treating single filenames that
3750 contain whitespace as multiple filenames.
3752 contain whitespace as multiple filenames.
3751
3753
3752 Returns 0 if a match is found, 1 otherwise.
3754 Returns 0 if a match is found, 1 otherwise.
3753 """
3755 """
3754 end = opts.get('print0') and '\0' or '\n'
3756 end = opts.get('print0') and '\0' or '\n'
3755 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3757 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3756
3758
3757 ret = 1
3759 ret = 1
3758 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3760 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3759 m.bad = lambda x, y: False
3761 m.bad = lambda x, y: False
3760 for abs in repo[rev].walk(m):
3762 for abs in repo[rev].walk(m):
3761 if not rev and abs not in repo.dirstate:
3763 if not rev and abs not in repo.dirstate:
3762 continue
3764 continue
3763 if opts.get('fullpath'):
3765 if opts.get('fullpath'):
3764 ui.write(repo.wjoin(abs), end)
3766 ui.write(repo.wjoin(abs), end)
3765 else:
3767 else:
3766 ui.write(((pats and m.rel(abs)) or abs), end)
3768 ui.write(((pats and m.rel(abs)) or abs), end)
3767 ret = 0
3769 ret = 0
3768
3770
3769 return ret
3771 return ret
3770
3772
3771 @command('^log|history',
3773 @command('^log|history',
3772 [('f', 'follow', None,
3774 [('f', 'follow', None,
3773 _('follow changeset history, or file history across copies and renames')),
3775 _('follow changeset history, or file history across copies and renames')),
3774 ('', 'follow-first', None,
3776 ('', 'follow-first', None,
3775 _('only follow the first parent of merge changesets (DEPRECATED)')),
3777 _('only follow the first parent of merge changesets (DEPRECATED)')),
3776 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3778 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3777 ('C', 'copies', None, _('show copied files')),
3779 ('C', 'copies', None, _('show copied files')),
3778 ('k', 'keyword', [],
3780 ('k', 'keyword', [],
3779 _('do case-insensitive search for a given text'), _('TEXT')),
3781 _('do case-insensitive search for a given text'), _('TEXT')),
3780 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3782 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3781 ('', 'removed', None, _('include revisions where files were removed')),
3783 ('', 'removed', None, _('include revisions where files were removed')),
3782 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3784 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3783 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3785 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3784 ('', 'only-branch', [],
3786 ('', 'only-branch', [],
3785 _('show only changesets within the given named branch (DEPRECATED)'),
3787 _('show only changesets within the given named branch (DEPRECATED)'),
3786 _('BRANCH')),
3788 _('BRANCH')),
3787 ('b', 'branch', [],
3789 ('b', 'branch', [],
3788 _('show changesets within the given named branch'), _('BRANCH')),
3790 _('show changesets within the given named branch'), _('BRANCH')),
3789 ('P', 'prune', [],
3791 ('P', 'prune', [],
3790 _('do not display revision or any of its ancestors'), _('REV')),
3792 _('do not display revision or any of its ancestors'), _('REV')),
3791 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3793 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3792 ] + logopts + walkopts,
3794 ] + logopts + walkopts,
3793 _('[OPTION]... [FILE]'))
3795 _('[OPTION]... [FILE]'))
3794 def log(ui, repo, *pats, **opts):
3796 def log(ui, repo, *pats, **opts):
3795 """show revision history of entire repository or files
3797 """show revision history of entire repository or files
3796
3798
3797 Print the revision history of the specified files or the entire
3799 Print the revision history of the specified files or the entire
3798 project.
3800 project.
3799
3801
3800 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
3801 --follow is set, in which case the working directory parent is
3803 --follow is set, in which case the working directory parent is
3802 used as the starting revision.
3804 used as the starting revision.
3803
3805
3804 File history is shown without following rename or copy history of
3806 File history is shown without following rename or copy history of
3805 files. Use -f/--follow with a filename to follow history across
3807 files. Use -f/--follow with a filename to follow history across
3806 renames and copies. --follow without a filename will only show
3808 renames and copies. --follow without a filename will only show
3807 ancestors or descendants of the starting revision.
3809 ancestors or descendants of the starting revision.
3808
3810
3809 By default this command prints revision number and changeset id,
3811 By default this command prints revision number and changeset id,
3810 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
3811 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
3812 changed files and full commit message are shown.
3814 changed files and full commit message are shown.
3813
3815
3814 .. note::
3816 .. note::
3815 log -p/--patch may generate unexpected diff output for merge
3817 log -p/--patch may generate unexpected diff output for merge
3816 changesets, as it will only compare the merge changeset against
3818 changesets, as it will only compare the merge changeset against
3817 its first parent. Also, only files different from BOTH parents
3819 its first parent. Also, only files different from BOTH parents
3818 will appear in files:.
3820 will appear in files:.
3819
3821
3820 .. note::
3822 .. note::
3821 for performance reasons, log FILE may omit duplicate changes
3823 for performance reasons, log FILE may omit duplicate changes
3822 made on branches and will not show deletions. To see all
3824 made on branches and will not show deletions. To see all
3823 changes including duplicates and deletions, use the --removed
3825 changes including duplicates and deletions, use the --removed
3824 switch.
3826 switch.
3825
3827
3826 .. container:: verbose
3828 .. container:: verbose
3827
3829
3828 Some examples:
3830 Some examples:
3829
3831
3830 - changesets with full descriptions and file lists::
3832 - changesets with full descriptions and file lists::
3831
3833
3832 hg log -v
3834 hg log -v
3833
3835
3834 - changesets ancestral to the working directory::
3836 - changesets ancestral to the working directory::
3835
3837
3836 hg log -f
3838 hg log -f
3837
3839
3838 - last 10 commits on the current branch::
3840 - last 10 commits on the current branch::
3839
3841
3840 hg log -l 10 -b .
3842 hg log -l 10 -b .
3841
3843
3842 - changesets showing all modifications of a file, including removals::
3844 - changesets showing all modifications of a file, including removals::
3843
3845
3844 hg log --removed file.c
3846 hg log --removed file.c
3845
3847
3846 - all changesets that touch a directory, with diffs, excluding merges::
3848 - all changesets that touch a directory, with diffs, excluding merges::
3847
3849
3848 hg log -Mp lib/
3850 hg log -Mp lib/
3849
3851
3850 - all revision numbers that match a keyword::
3852 - all revision numbers that match a keyword::
3851
3853
3852 hg log -k bug --template "{rev}\\n"
3854 hg log -k bug --template "{rev}\\n"
3853
3855
3854 - check if a given changeset is included is a tagged release::
3856 - check if a given changeset is included is a tagged release::
3855
3857
3856 hg log -r "a21ccf and ancestor(1.9)"
3858 hg log -r "a21ccf and ancestor(1.9)"
3857
3859
3858 - find all changesets by some user in a date range::
3860 - find all changesets by some user in a date range::
3859
3861
3860 hg log -k alice -d "may 2008 to jul 2008"
3862 hg log -k alice -d "may 2008 to jul 2008"
3861
3863
3862 - summary of all changesets after the last tag::
3864 - summary of all changesets after the last tag::
3863
3865
3864 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3866 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3865
3867
3866 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.
3867
3869
3868 See :hg:`help revisions` and :hg:`help revsets` for more about
3870 See :hg:`help revisions` and :hg:`help revsets` for more about
3869 specifying revisions.
3871 specifying revisions.
3870
3872
3871 Returns 0 on success.
3873 Returns 0 on success.
3872 """
3874 """
3873
3875
3874 matchfn = scmutil.match(repo[None], pats, opts)
3876 matchfn = scmutil.match(repo[None], pats, opts)
3875 limit = cmdutil.loglimit(opts)
3877 limit = cmdutil.loglimit(opts)
3876 count = 0
3878 count = 0
3877
3879
3878 endrev = None
3880 endrev = None
3879 if opts.get('copies') and opts.get('rev'):
3881 if opts.get('copies') and opts.get('rev'):
3880 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3882 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3881
3883
3882 df = False
3884 df = False
3883 if opts["date"]:
3885 if opts["date"]:
3884 df = util.matchdate(opts["date"])
3886 df = util.matchdate(opts["date"])
3885
3887
3886 branches = opts.get('branch', []) + opts.get('only_branch', [])
3888 branches = opts.get('branch', []) + opts.get('only_branch', [])
3887 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3889 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3888
3890
3889 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3891 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3890 def prep(ctx, fns):
3892 def prep(ctx, fns):
3891 rev = ctx.rev()
3893 rev = ctx.rev()
3892 parents = [p for p in repo.changelog.parentrevs(rev)
3894 parents = [p for p in repo.changelog.parentrevs(rev)
3893 if p != nullrev]
3895 if p != nullrev]
3894 if opts.get('no_merges') and len(parents) == 2:
3896 if opts.get('no_merges') and len(parents) == 2:
3895 return
3897 return
3896 if opts.get('only_merges') and len(parents) != 2:
3898 if opts.get('only_merges') and len(parents) != 2:
3897 return
3899 return
3898 if opts.get('branch') and ctx.branch() not in opts['branch']:
3900 if opts.get('branch') and ctx.branch() not in opts['branch']:
3899 return
3901 return
3900 if not opts.get('hidden') and ctx.hidden():
3902 if not opts.get('hidden') and ctx.hidden():
3901 return
3903 return
3902 if df and not df(ctx.date()[0]):
3904 if df and not df(ctx.date()[0]):
3903 return
3905 return
3904
3906
3905 lower = encoding.lower
3907 lower = encoding.lower
3906 if opts.get('user'):
3908 if opts.get('user'):
3907 luser = lower(ctx.user())
3909 luser = lower(ctx.user())
3908 for k in [lower(x) for x in opts['user']]:
3910 for k in [lower(x) for x in opts['user']]:
3909 if (k in luser):
3911 if (k in luser):
3910 break
3912 break
3911 else:
3913 else:
3912 return
3914 return
3913 if opts.get('keyword'):
3915 if opts.get('keyword'):
3914 luser = lower(ctx.user())
3916 luser = lower(ctx.user())
3915 ldesc = lower(ctx.description())
3917 ldesc = lower(ctx.description())
3916 lfiles = lower(" ".join(ctx.files()))
3918 lfiles = lower(" ".join(ctx.files()))
3917 for k in [lower(x) for x in opts['keyword']]:
3919 for k in [lower(x) for x in opts['keyword']]:
3918 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):
3919 break
3921 break
3920 else:
3922 else:
3921 return
3923 return
3922
3924
3923 copies = None
3925 copies = None
3924 if opts.get('copies') and rev:
3926 if opts.get('copies') and rev:
3925 copies = []
3927 copies = []
3926 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3928 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3927 for fn in ctx.files():
3929 for fn in ctx.files():
3928 rename = getrenamed(fn, rev)
3930 rename = getrenamed(fn, rev)
3929 if rename:
3931 if rename:
3930 copies.append((fn, rename[0]))
3932 copies.append((fn, rename[0]))
3931
3933
3932 revmatchfn = None
3934 revmatchfn = None
3933 if opts.get('patch') or opts.get('stat'):
3935 if opts.get('patch') or opts.get('stat'):
3934 if opts.get('follow') or opts.get('follow_first'):
3936 if opts.get('follow') or opts.get('follow_first'):
3935 # note: this might be wrong when following through merges
3937 # note: this might be wrong when following through merges
3936 revmatchfn = scmutil.match(repo[None], fns, default='path')
3938 revmatchfn = scmutil.match(repo[None], fns, default='path')
3937 else:
3939 else:
3938 revmatchfn = matchfn
3940 revmatchfn = matchfn
3939
3941
3940 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3942 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3941
3943
3942 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3944 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3943 if count == limit:
3945 if count == limit:
3944 break
3946 break
3945 if displayer.flush(ctx.rev()):
3947 if displayer.flush(ctx.rev()):
3946 count += 1
3948 count += 1
3947 displayer.close()
3949 displayer.close()
3948
3950
3949 @command('manifest',
3951 @command('manifest',
3950 [('r', 'rev', '', _('revision to display'), _('REV')),
3952 [('r', 'rev', '', _('revision to display'), _('REV')),
3951 ('', 'all', False, _("list files from all revisions"))],
3953 ('', 'all', False, _("list files from all revisions"))],
3952 _('[-r REV]'))
3954 _('[-r REV]'))
3953 def manifest(ui, repo, node=None, rev=None, **opts):
3955 def manifest(ui, repo, node=None, rev=None, **opts):
3954 """output the current or given revision of the project manifest
3956 """output the current or given revision of the project manifest
3955
3957
3956 Print a list of version controlled files for the given revision.
3958 Print a list of version controlled files for the given revision.
3957 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
3958 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.
3959
3961
3960 With -v, print file permissions, symlink and executable bits.
3962 With -v, print file permissions, symlink and executable bits.
3961 With --debug, print file revision hashes.
3963 With --debug, print file revision hashes.
3962
3964
3963 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
3964 is printed. This includes deleted and renamed files.
3966 is printed. This includes deleted and renamed files.
3965
3967
3966 Returns 0 on success.
3968 Returns 0 on success.
3967 """
3969 """
3968 if opts.get('all'):
3970 if opts.get('all'):
3969 if rev or node:
3971 if rev or node:
3970 raise util.Abort(_("can't specify a revision with --all"))
3972 raise util.Abort(_("can't specify a revision with --all"))
3971
3973
3972 res = []
3974 res = []
3973 prefix = "data/"
3975 prefix = "data/"
3974 suffix = ".i"
3976 suffix = ".i"
3975 plen = len(prefix)
3977 plen = len(prefix)
3976 slen = len(suffix)
3978 slen = len(suffix)
3977 lock = repo.lock()
3979 lock = repo.lock()
3978 try:
3980 try:
3979 for fn, b, size in repo.store.datafiles():
3981 for fn, b, size in repo.store.datafiles():
3980 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3982 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3981 res.append(fn[plen:-slen])
3983 res.append(fn[plen:-slen])
3982 finally:
3984 finally:
3983 lock.release()
3985 lock.release()
3984 for f in sorted(res):
3986 for f in sorted(res):
3985 ui.write("%s\n" % f)
3987 ui.write("%s\n" % f)
3986 return
3988 return
3987
3989
3988 if rev and node:
3990 if rev and node:
3989 raise util.Abort(_("please specify just one revision"))
3991 raise util.Abort(_("please specify just one revision"))
3990
3992
3991 if not node:
3993 if not node:
3992 node = rev
3994 node = rev
3993
3995
3994 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3996 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3995 ctx = scmutil.revsingle(repo, node)
3997 ctx = scmutil.revsingle(repo, node)
3996 for f in ctx:
3998 for f in ctx:
3997 if ui.debugflag:
3999 if ui.debugflag:
3998 ui.write("%40s " % hex(ctx.manifest()[f]))
4000 ui.write("%40s " % hex(ctx.manifest()[f]))
3999 if ui.verbose:
4001 if ui.verbose:
4000 ui.write(decor[ctx.flags(f)])
4002 ui.write(decor[ctx.flags(f)])
4001 ui.write("%s\n" % f)
4003 ui.write("%s\n" % f)
4002
4004
4003 @command('^merge',
4005 @command('^merge',
4004 [('f', 'force', None, _('force a merge with outstanding changes')),
4006 [('f', 'force', None, _('force a merge with outstanding changes')),
4005 ('r', 'rev', '', _('revision to merge'), _('REV')),
4007 ('r', 'rev', '', _('revision to merge'), _('REV')),
4006 ('P', 'preview', None,
4008 ('P', 'preview', None,
4007 _('review revisions to merge (no merge is performed)'))
4009 _('review revisions to merge (no merge is performed)'))
4008 ] + mergetoolopts,
4010 ] + mergetoolopts,
4009 _('[-P] [-f] [[-r] REV]'))
4011 _('[-P] [-f] [[-r] REV]'))
4010 def merge(ui, repo, node=None, **opts):
4012 def merge(ui, repo, node=None, **opts):
4011 """merge working directory with another revision
4013 """merge working directory with another revision
4012
4014
4013 The current working directory is updated with all changes made in
4015 The current working directory is updated with all changes made in
4014 the requested revision since the last common predecessor revision.
4016 the requested revision since the last common predecessor revision.
4015
4017
4016 Files that changed between either parent are marked as changed for
4018 Files that changed between either parent are marked as changed for
4017 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
4018 updates to the repository are allowed. The next commit will have
4020 updates to the repository are allowed. The next commit will have
4019 two parents.
4021 two parents.
4020
4022
4021 ``--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
4022 merges. It overrides the HGMERGE environment variable and your
4024 merges. It overrides the HGMERGE environment variable and your
4023 configuration files. See :hg:`help merge-tools` for options.
4025 configuration files. See :hg:`help merge-tools` for options.
4024
4026
4025 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
4026 head revision, and the current branch contains exactly one other
4028 head revision, and the current branch contains exactly one other
4027 head, the other head is merged with by default. Otherwise, an
4029 head, the other head is merged with by default. Otherwise, an
4028 explicit revision with which to merge with must be provided.
4030 explicit revision with which to merge with must be provided.
4029
4031
4030 :hg:`resolve` must be used to resolve unresolved files.
4032 :hg:`resolve` must be used to resolve unresolved files.
4031
4033
4032 To undo an uncommitted merge, use :hg:`update --clean .` which
4034 To undo an uncommitted merge, use :hg:`update --clean .` which
4033 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
4034 all changes.
4036 all changes.
4035
4037
4036 Returns 0 on success, 1 if there are unresolved files.
4038 Returns 0 on success, 1 if there are unresolved files.
4037 """
4039 """
4038
4040
4039 if opts.get('rev') and node:
4041 if opts.get('rev') and node:
4040 raise util.Abort(_("please specify just one revision"))
4042 raise util.Abort(_("please specify just one revision"))
4041 if not node:
4043 if not node:
4042 node = opts.get('rev')
4044 node = opts.get('rev')
4043
4045
4044 if not node:
4046 if not node:
4045 branch = repo[None].branch()
4047 branch = repo[None].branch()
4046 bheads = repo.branchheads(branch)
4048 bheads = repo.branchheads(branch)
4047 if len(bheads) > 2:
4049 if len(bheads) > 2:
4048 raise util.Abort(_("branch '%s' has %d heads - "
4050 raise util.Abort(_("branch '%s' has %d heads - "
4049 "please merge with an explicit rev")
4051 "please merge with an explicit rev")
4050 % (branch, len(bheads)),
4052 % (branch, len(bheads)),
4051 hint=_("run 'hg heads .' to see heads"))
4053 hint=_("run 'hg heads .' to see heads"))
4052
4054
4053 parent = repo.dirstate.p1()
4055 parent = repo.dirstate.p1()
4054 if len(bheads) == 1:
4056 if len(bheads) == 1:
4055 if len(repo.heads()) > 1:
4057 if len(repo.heads()) > 1:
4056 raise util.Abort(_("branch '%s' has one head - "
4058 raise util.Abort(_("branch '%s' has one head - "
4057 "please merge with an explicit rev")
4059 "please merge with an explicit rev")
4058 % branch,
4060 % branch,
4059 hint=_("run 'hg heads' to see all heads"))
4061 hint=_("run 'hg heads' to see all heads"))
4060 msg, hint = _('nothing to merge'), None
4062 msg, hint = _('nothing to merge'), None
4061 if parent != repo.lookup(branch):
4063 if parent != repo.lookup(branch):
4062 hint = _("use 'hg update' instead")
4064 hint = _("use 'hg update' instead")
4063 raise util.Abort(msg, hint=hint)
4065 raise util.Abort(msg, hint=hint)
4064
4066
4065 if parent not in bheads:
4067 if parent not in bheads:
4066 raise util.Abort(_('working directory not at a head revision'),
4068 raise util.Abort(_('working directory not at a head revision'),
4067 hint=_("use 'hg update' or merge with an "
4069 hint=_("use 'hg update' or merge with an "
4068 "explicit revision"))
4070 "explicit revision"))
4069 node = parent == bheads[0] and bheads[-1] or bheads[0]
4071 node = parent == bheads[0] and bheads[-1] or bheads[0]
4070 else:
4072 else:
4071 node = scmutil.revsingle(repo, node).node()
4073 node = scmutil.revsingle(repo, node).node()
4072
4074
4073 if opts.get('preview'):
4075 if opts.get('preview'):
4074 # find nodes that are ancestors of p2 but not of p1
4076 # find nodes that are ancestors of p2 but not of p1
4075 p1 = repo.lookup('.')
4077 p1 = repo.lookup('.')
4076 p2 = repo.lookup(node)
4078 p2 = repo.lookup(node)
4077 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4079 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4078
4080
4079 displayer = cmdutil.show_changeset(ui, repo, opts)
4081 displayer = cmdutil.show_changeset(ui, repo, opts)
4080 for node in nodes:
4082 for node in nodes:
4081 displayer.show(repo[node])
4083 displayer.show(repo[node])
4082 displayer.close()
4084 displayer.close()
4083 return 0
4085 return 0
4084
4086
4085 try:
4087 try:
4086 # ui.forcemerge is an internal variable, do not document
4088 # ui.forcemerge is an internal variable, do not document
4087 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4089 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4088 return hg.merge(repo, node, force=opts.get('force'))
4090 return hg.merge(repo, node, force=opts.get('force'))
4089 finally:
4091 finally:
4090 ui.setconfig('ui', 'forcemerge', '')
4092 ui.setconfig('ui', 'forcemerge', '')
4091
4093
4092 @command('outgoing|out',
4094 @command('outgoing|out',
4093 [('f', 'force', None, _('run even when the destination is unrelated')),
4095 [('f', 'force', None, _('run even when the destination is unrelated')),
4094 ('r', 'rev', [],
4096 ('r', 'rev', [],
4095 _('a changeset intended to be included in the destination'), _('REV')),
4097 _('a changeset intended to be included in the destination'), _('REV')),
4096 ('n', 'newest-first', None, _('show newest record first')),
4098 ('n', 'newest-first', None, _('show newest record first')),
4097 ('B', 'bookmarks', False, _('compare bookmarks')),
4099 ('B', 'bookmarks', False, _('compare bookmarks')),
4098 ('b', 'branch', [], _('a specific branch you would like to push'),
4100 ('b', 'branch', [], _('a specific branch you would like to push'),
4099 _('BRANCH')),
4101 _('BRANCH')),
4100 ] + logopts + remoteopts + subrepoopts,
4102 ] + logopts + remoteopts + subrepoopts,
4101 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4103 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4102 def outgoing(ui, repo, dest=None, **opts):
4104 def outgoing(ui, repo, dest=None, **opts):
4103 """show changesets not found in the destination
4105 """show changesets not found in the destination
4104
4106
4105 Show changesets not found in the specified destination repository
4107 Show changesets not found in the specified destination repository
4106 or the default push location. These are the changesets that would
4108 or the default push location. These are the changesets that would
4107 be pushed if a push was requested.
4109 be pushed if a push was requested.
4108
4110
4109 See pull for details of valid destination formats.
4111 See pull for details of valid destination formats.
4110
4112
4111 Returns 0 if there are outgoing changes, 1 otherwise.
4113 Returns 0 if there are outgoing changes, 1 otherwise.
4112 """
4114 """
4113
4115
4114 if opts.get('bookmarks'):
4116 if opts.get('bookmarks'):
4115 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4117 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4116 dest, branches = hg.parseurl(dest, opts.get('branch'))
4118 dest, branches = hg.parseurl(dest, opts.get('branch'))
4117 other = hg.peer(repo, opts, dest)
4119 other = hg.peer(repo, opts, dest)
4118 if 'bookmarks' not in other.listkeys('namespaces'):
4120 if 'bookmarks' not in other.listkeys('namespaces'):
4119 ui.warn(_("remote doesn't support bookmarks\n"))
4121 ui.warn(_("remote doesn't support bookmarks\n"))
4120 return 0
4122 return 0
4121 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4123 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4122 return bookmarks.diff(ui, other, repo)
4124 return bookmarks.diff(ui, other, repo)
4123
4125
4124 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4126 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4125 try:
4127 try:
4126 return hg.outgoing(ui, repo, dest, opts)
4128 return hg.outgoing(ui, repo, dest, opts)
4127 finally:
4129 finally:
4128 del repo._subtoppath
4130 del repo._subtoppath
4129
4131
4130 @command('parents',
4132 @command('parents',
4131 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4133 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4132 ] + templateopts,
4134 ] + templateopts,
4133 _('[-r REV] [FILE]'))
4135 _('[-r REV] [FILE]'))
4134 def parents(ui, repo, file_=None, **opts):
4136 def parents(ui, repo, file_=None, **opts):
4135 """show the parents of the working directory or revision
4137 """show the parents of the working directory or revision
4136
4138
4137 Print the working directory's parent revisions. If a revision is
4139 Print the working directory's parent revisions. If a revision is
4138 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.
4139 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
4140 last changed (before the working directory revision or the
4142 last changed (before the working directory revision or the
4141 argument to --rev if given) is printed.
4143 argument to --rev if given) is printed.
4142
4144
4143 Returns 0 on success.
4145 Returns 0 on success.
4144 """
4146 """
4145
4147
4146 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4148 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4147
4149
4148 if file_:
4150 if file_:
4149 m = scmutil.match(ctx, (file_,), opts)
4151 m = scmutil.match(ctx, (file_,), opts)
4150 if m.anypats() or len(m.files()) != 1:
4152 if m.anypats() or len(m.files()) != 1:
4151 raise util.Abort(_('can only specify an explicit filename'))
4153 raise util.Abort(_('can only specify an explicit filename'))
4152 file_ = m.files()[0]
4154 file_ = m.files()[0]
4153 filenodes = []
4155 filenodes = []
4154 for cp in ctx.parents():
4156 for cp in ctx.parents():
4155 if not cp:
4157 if not cp:
4156 continue
4158 continue
4157 try:
4159 try:
4158 filenodes.append(cp.filenode(file_))
4160 filenodes.append(cp.filenode(file_))
4159 except error.LookupError:
4161 except error.LookupError:
4160 pass
4162 pass
4161 if not filenodes:
4163 if not filenodes:
4162 raise util.Abort(_("'%s' not found in manifest!") % file_)
4164 raise util.Abort(_("'%s' not found in manifest!") % file_)
4163 fl = repo.file(file_)
4165 fl = repo.file(file_)
4164 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]
4165 else:
4167 else:
4166 p = [cp.node() for cp in ctx.parents()]
4168 p = [cp.node() for cp in ctx.parents()]
4167
4169
4168 displayer = cmdutil.show_changeset(ui, repo, opts)
4170 displayer = cmdutil.show_changeset(ui, repo, opts)
4169 for n in p:
4171 for n in p:
4170 if n != nullid:
4172 if n != nullid:
4171 displayer.show(repo[n])
4173 displayer.show(repo[n])
4172 displayer.close()
4174 displayer.close()
4173
4175
4174 @command('paths', [], _('[NAME]'))
4176 @command('paths', [], _('[NAME]'))
4175 def paths(ui, repo, search=None):
4177 def paths(ui, repo, search=None):
4176 """show aliases for remote repositories
4178 """show aliases for remote repositories
4177
4179
4178 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,
4179 show definition of all available names.
4181 show definition of all available names.
4180
4182
4181 Option -q/--quiet suppresses all output when searching for NAME
4183 Option -q/--quiet suppresses all output when searching for NAME
4182 and shows only the path names when listing all definitions.
4184 and shows only the path names when listing all definitions.
4183
4185
4184 Path names are defined in the [paths] section of your
4186 Path names are defined in the [paths] section of your
4185 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4187 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4186 repository, ``.hg/hgrc`` is used, too.
4188 repository, ``.hg/hgrc`` is used, too.
4187
4189
4188 The path names ``default`` and ``default-push`` have a special
4190 The path names ``default`` and ``default-push`` have a special
4189 meaning. When performing a push or pull operation, they are used
4191 meaning. When performing a push or pull operation, they are used
4190 as fallbacks if no location is specified on the command-line.
4192 as fallbacks if no location is specified on the command-line.
4191 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
4192 ``default`` will be used for pull; otherwise ``default`` is used
4194 ``default`` will be used for pull; otherwise ``default`` is used
4193 as the fallback for both. When cloning a repository, the clone
4195 as the fallback for both. When cloning a repository, the clone
4194 source is written as ``default`` in ``.hg/hgrc``. Note that
4196 source is written as ``default`` in ``.hg/hgrc``. Note that
4195 ``default`` and ``default-push`` apply to all inbound (e.g.
4197 ``default`` and ``default-push`` apply to all inbound (e.g.
4196 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4198 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4197 :hg:`bundle`) operations.
4199 :hg:`bundle`) operations.
4198
4200
4199 See :hg:`help urls` for more information.
4201 See :hg:`help urls` for more information.
4200
4202
4201 Returns 0 on success.
4203 Returns 0 on success.
4202 """
4204 """
4203 if search:
4205 if search:
4204 for name, path in ui.configitems("paths"):
4206 for name, path in ui.configitems("paths"):
4205 if name == search:
4207 if name == search:
4206 ui.status("%s\n" % util.hidepassword(path))
4208 ui.status("%s\n" % util.hidepassword(path))
4207 return
4209 return
4208 if not ui.quiet:
4210 if not ui.quiet:
4209 ui.warn(_("not found!\n"))
4211 ui.warn(_("not found!\n"))
4210 return 1
4212 return 1
4211 else:
4213 else:
4212 for name, path in ui.configitems("paths"):
4214 for name, path in ui.configitems("paths"):
4213 if ui.quiet:
4215 if ui.quiet:
4214 ui.write("%s\n" % name)
4216 ui.write("%s\n" % name)
4215 else:
4217 else:
4216 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4218 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4217
4219
4218 @command('^phase',
4220 @command('^phase',
4219 [('p', 'public', False, _('set changeset phase to public')),
4221 [('p', 'public', False, _('set changeset phase to public')),
4220 ('d', 'draft', False, _('set changeset phase to draft')),
4222 ('d', 'draft', False, _('set changeset phase to draft')),
4221 ('s', 'secret', False, _('set changeset phase to secret')),
4223 ('s', 'secret', False, _('set changeset phase to secret')),
4222 ('f', 'force', False, _('allow to move boundary backward')),
4224 ('f', 'force', False, _('allow to move boundary backward')),
4223 ('r', 'rev', [], _('target revision'), _('REV')),
4225 ('r', 'rev', [], _('target revision'), _('REV')),
4224 ],
4226 ],
4225 _('[-p|-d|-s] [-f] [-r] REV...'))
4227 _('[-p|-d|-s] [-f] [-r] REV...'))
4226 def phase(ui, repo, *revs, **opts):
4228 def phase(ui, repo, *revs, **opts):
4227 """set or show the current phase name
4229 """set or show the current phase name
4228
4230
4229 With no argument, show the phase name of specified revisions.
4231 With no argument, show the phase name of specified revisions.
4230
4232
4231 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
4232 phase value of the specified revisions.
4234 phase value of the specified revisions.
4233
4235
4234 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
4235 lower phase to an higher phase. Phases are ordered as follows::
4237 lower phase to an higher phase. Phases are ordered as follows::
4236
4238
4237 public < draft < secret
4239 public < draft < secret
4238 """
4240 """
4239 # search for a unique phase argument
4241 # search for a unique phase argument
4240 targetphase = None
4242 targetphase = None
4241 for idx, name in enumerate(phases.phasenames):
4243 for idx, name in enumerate(phases.phasenames):
4242 if opts[name]:
4244 if opts[name]:
4243 if targetphase is not None:
4245 if targetphase is not None:
4244 raise util.Abort(_('only one phase can be specified'))
4246 raise util.Abort(_('only one phase can be specified'))
4245 targetphase = idx
4247 targetphase = idx
4246
4248
4247 # look for specified revision
4249 # look for specified revision
4248 revs = list(revs)
4250 revs = list(revs)
4249 revs.extend(opts['rev'])
4251 revs.extend(opts['rev'])
4250 if not revs:
4252 if not revs:
4251 raise util.Abort(_('no revisions specified!'))
4253 raise util.Abort(_('no revisions specified!'))
4252
4254
4253 lock = None
4255 lock = None
4254 if targetphase is None:
4256 if targetphase is None:
4255 # display
4257 # display
4256 for ctx in repo.set('%lr', revs):
4258 for ctx in repo.set('%lr', revs):
4257 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4259 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4258 else:
4260 else:
4259 lock = repo.lock()
4261 lock = repo.lock()
4260 try:
4262 try:
4261 # set phase
4263 # set phase
4262 nodes = [ctx.node() for ctx in repo.set('%lr', revs)]
4264 nodes = [ctx.node() for ctx in repo.set('%lr', revs)]
4263 if not nodes:
4265 if not nodes:
4264 raise util.Abort(_('empty revision set'))
4266 raise util.Abort(_('empty revision set'))
4265 phases.advanceboundary(repo, targetphase, nodes)
4267 phases.advanceboundary(repo, targetphase, nodes)
4266 if opts['force']:
4268 if opts['force']:
4267 phases.retractboundary(repo, targetphase, nodes)
4269 phases.retractboundary(repo, targetphase, nodes)
4268 finally:
4270 finally:
4269 lock.release()
4271 lock.release()
4270
4272
4271 def postincoming(ui, repo, modheads, optupdate, checkout):
4273 def postincoming(ui, repo, modheads, optupdate, checkout):
4272 if modheads == 0:
4274 if modheads == 0:
4273 return
4275 return
4274 if optupdate:
4276 if optupdate:
4275 try:
4277 try:
4276 return hg.update(repo, checkout)
4278 return hg.update(repo, checkout)
4277 except util.Abort, inst:
4279 except util.Abort, inst:
4278 ui.warn(_("not updating: %s\n" % str(inst)))
4280 ui.warn(_("not updating: %s\n" % str(inst)))
4279 return 0
4281 return 0
4280 if modheads > 1:
4282 if modheads > 1:
4281 currentbranchheads = len(repo.branchheads())
4283 currentbranchheads = len(repo.branchheads())
4282 if currentbranchheads == modheads:
4284 if currentbranchheads == modheads:
4283 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"))
4284 elif currentbranchheads > 1:
4286 elif currentbranchheads > 1:
4285 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"))
4286 else:
4288 else:
4287 ui.status(_("(run 'hg heads' to see heads)\n"))
4289 ui.status(_("(run 'hg heads' to see heads)\n"))
4288 else:
4290 else:
4289 ui.status(_("(run 'hg update' to get a working copy)\n"))
4291 ui.status(_("(run 'hg update' to get a working copy)\n"))
4290
4292
4291 @command('^pull',
4293 @command('^pull',
4292 [('u', 'update', None,
4294 [('u', 'update', None,
4293 _('update to new branch head if changesets were pulled')),
4295 _('update to new branch head if changesets were pulled')),
4294 ('f', 'force', None, _('run even when remote repository is unrelated')),
4296 ('f', 'force', None, _('run even when remote repository is unrelated')),
4295 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4297 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4296 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4298 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4297 ('b', 'branch', [], _('a specific branch you would like to pull'),
4299 ('b', 'branch', [], _('a specific branch you would like to pull'),
4298 _('BRANCH')),
4300 _('BRANCH')),
4299 ] + remoteopts,
4301 ] + remoteopts,
4300 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4302 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4301 def pull(ui, repo, source="default", **opts):
4303 def pull(ui, repo, source="default", **opts):
4302 """pull changes from the specified source
4304 """pull changes from the specified source
4303
4305
4304 Pull changes from a remote repository to a local one.
4306 Pull changes from a remote repository to a local one.
4305
4307
4306 This finds all changes from the repository at the specified path
4308 This finds all changes from the repository at the specified path
4307 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
4308 -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
4309 project in the working directory.
4311 project in the working directory.
4310
4312
4311 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
4312 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
4313 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
4314 -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`.
4315
4317
4316 If SOURCE is omitted, the 'default' path will be used.
4318 If SOURCE is omitted, the 'default' path will be used.
4317 See :hg:`help urls` for more information.
4319 See :hg:`help urls` for more information.
4318
4320
4319 Returns 0 on success, 1 if an update had unresolved files.
4321 Returns 0 on success, 1 if an update had unresolved files.
4320 """
4322 """
4321 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4323 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4322 other = hg.peer(repo, opts, source)
4324 other = hg.peer(repo, opts, source)
4323 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4325 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4324 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4326 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4325
4327
4326 if opts.get('bookmark'):
4328 if opts.get('bookmark'):
4327 if not revs:
4329 if not revs:
4328 revs = []
4330 revs = []
4329 rb = other.listkeys('bookmarks')
4331 rb = other.listkeys('bookmarks')
4330 for b in opts['bookmark']:
4332 for b in opts['bookmark']:
4331 if b not in rb:
4333 if b not in rb:
4332 raise util.Abort(_('remote bookmark %s not found!') % b)
4334 raise util.Abort(_('remote bookmark %s not found!') % b)
4333 revs.append(rb[b])
4335 revs.append(rb[b])
4334
4336
4335 if revs:
4337 if revs:
4336 try:
4338 try:
4337 revs = [other.lookup(rev) for rev in revs]
4339 revs = [other.lookup(rev) for rev in revs]
4338 except error.CapabilityError:
4340 except error.CapabilityError:
4339 err = _("other repository doesn't support revision lookup, "
4341 err = _("other repository doesn't support revision lookup, "
4340 "so a rev cannot be specified.")
4342 "so a rev cannot be specified.")
4341 raise util.Abort(err)
4343 raise util.Abort(err)
4342
4344
4343 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4345 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4344 bookmarks.updatefromremote(ui, repo, other, source)
4346 bookmarks.updatefromremote(ui, repo, other, source)
4345 if checkout:
4347 if checkout:
4346 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4348 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4347 repo._subtoppath = source
4349 repo._subtoppath = source
4348 try:
4350 try:
4349 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4351 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4350
4352
4351 finally:
4353 finally:
4352 del repo._subtoppath
4354 del repo._subtoppath
4353
4355
4354 # update specified bookmarks
4356 # update specified bookmarks
4355 if opts.get('bookmark'):
4357 if opts.get('bookmark'):
4356 for b in opts['bookmark']:
4358 for b in opts['bookmark']:
4357 # explicit pull overrides local bookmark if any
4359 # explicit pull overrides local bookmark if any
4358 ui.status(_("importing bookmark %s\n") % b)
4360 ui.status(_("importing bookmark %s\n") % b)
4359 repo._bookmarks[b] = repo[rb[b]].node()
4361 repo._bookmarks[b] = repo[rb[b]].node()
4360 bookmarks.write(repo)
4362 bookmarks.write(repo)
4361
4363
4362 return ret
4364 return ret
4363
4365
4364 @command('^push',
4366 @command('^push',
4365 [('f', 'force', None, _('force push')),
4367 [('f', 'force', None, _('force push')),
4366 ('r', 'rev', [],
4368 ('r', 'rev', [],
4367 _('a changeset intended to be included in the destination'),
4369 _('a changeset intended to be included in the destination'),
4368 _('REV')),
4370 _('REV')),
4369 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4371 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4370 ('b', 'branch', [],
4372 ('b', 'branch', [],
4371 _('a specific branch you would like to push'), _('BRANCH')),
4373 _('a specific branch you would like to push'), _('BRANCH')),
4372 ('', 'new-branch', False, _('allow pushing a new branch')),
4374 ('', 'new-branch', False, _('allow pushing a new branch')),
4373 ] + remoteopts,
4375 ] + remoteopts,
4374 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4376 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4375 def push(ui, repo, dest=None, **opts):
4377 def push(ui, repo, dest=None, **opts):
4376 """push changes to the specified destination
4378 """push changes to the specified destination
4377
4379
4378 Push changesets from the local repository to the specified
4380 Push changesets from the local repository to the specified
4379 destination.
4381 destination.
4380
4382
4381 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
4382 in the destination repository from the current one.
4384 in the destination repository from the current one.
4383
4385
4384 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
4385 destination, since multiple heads would make it unclear which head
4387 destination, since multiple heads would make it unclear which head
4386 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
4387 before pushing.
4389 before pushing.
4388
4390
4389 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
4390 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
4391 only create a new branch without forcing other changes.
4393 only create a new branch without forcing other changes.
4392
4394
4393 Use -f/--force to override the default behavior and push all
4395 Use -f/--force to override the default behavior and push all
4394 changesets on all branches.
4396 changesets on all branches.
4395
4397
4396 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
4397 will be pushed to the remote repository.
4399 will be pushed to the remote repository.
4398
4400
4399 Please see :hg:`help urls` for important details about ``ssh://``
4401 Please see :hg:`help urls` for important details about ``ssh://``
4400 URLs. If DESTINATION is omitted, a default path will be used.
4402 URLs. If DESTINATION is omitted, a default path will be used.
4401
4403
4402 Returns 0 if push was successful, 1 if nothing to push.
4404 Returns 0 if push was successful, 1 if nothing to push.
4403 """
4405 """
4404
4406
4405 if opts.get('bookmark'):
4407 if opts.get('bookmark'):
4406 for b in opts['bookmark']:
4408 for b in opts['bookmark']:
4407 # translate -B options to -r so changesets get pushed
4409 # translate -B options to -r so changesets get pushed
4408 if b in repo._bookmarks:
4410 if b in repo._bookmarks:
4409 opts.setdefault('rev', []).append(b)
4411 opts.setdefault('rev', []).append(b)
4410 else:
4412 else:
4411 # 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
4412 # this lets simultaneous -r, -b options continue working
4414 # this lets simultaneous -r, -b options continue working
4413 opts.setdefault('rev', []).append("null")
4415 opts.setdefault('rev', []).append("null")
4414
4416
4415 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4417 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4416 dest, branches = hg.parseurl(dest, opts.get('branch'))
4418 dest, branches = hg.parseurl(dest, opts.get('branch'))
4417 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4419 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4418 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4420 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4419 other = hg.peer(repo, opts, dest)
4421 other = hg.peer(repo, opts, dest)
4420 if revs:
4422 if revs:
4421 revs = [repo.lookup(rev) for rev in revs]
4423 revs = [repo.lookup(rev) for rev in revs]
4422
4424
4423 repo._subtoppath = dest
4425 repo._subtoppath = dest
4424 try:
4426 try:
4425 # push subrepos depth-first for coherent ordering
4427 # push subrepos depth-first for coherent ordering
4426 c = repo['']
4428 c = repo['']
4427 subs = c.substate # only repos that are committed
4429 subs = c.substate # only repos that are committed
4428 for s in sorted(subs):
4430 for s in sorted(subs):
4429 if not c.sub(s).push(opts):
4431 if not c.sub(s).push(opts):
4430 return False
4432 return False
4431 finally:
4433 finally:
4432 del repo._subtoppath
4434 del repo._subtoppath
4433 result = repo.push(other, opts.get('force'), revs=revs,
4435 result = repo.push(other, opts.get('force'), revs=revs,
4434 newbranch=opts.get('new_branch'))
4436 newbranch=opts.get('new_branch'))
4435
4437
4436 result = (result == 0)
4438 result = (result == 0)
4437
4439
4438 if opts.get('bookmark'):
4440 if opts.get('bookmark'):
4439 rb = other.listkeys('bookmarks')
4441 rb = other.listkeys('bookmarks')
4440 for b in opts['bookmark']:
4442 for b in opts['bookmark']:
4441 # explicit push overrides remote bookmark if any
4443 # explicit push overrides remote bookmark if any
4442 if b in repo._bookmarks:
4444 if b in repo._bookmarks:
4443 ui.status(_("exporting bookmark %s\n") % b)
4445 ui.status(_("exporting bookmark %s\n") % b)
4444 new = repo[b].hex()
4446 new = repo[b].hex()
4445 elif b in rb:
4447 elif b in rb:
4446 ui.status(_("deleting remote bookmark %s\n") % b)
4448 ui.status(_("deleting remote bookmark %s\n") % b)
4447 new = '' # delete
4449 new = '' # delete
4448 else:
4450 else:
4449 ui.warn(_('bookmark %s does not exist on the local '
4451 ui.warn(_('bookmark %s does not exist on the local '
4450 'or remote repository!\n') % b)
4452 'or remote repository!\n') % b)
4451 return 2
4453 return 2
4452 old = rb.get(b, '')
4454 old = rb.get(b, '')
4453 r = other.pushkey('bookmarks', b, old, new)
4455 r = other.pushkey('bookmarks', b, old, new)
4454 if not r:
4456 if not r:
4455 ui.warn(_('updating bookmark %s failed!\n') % b)
4457 ui.warn(_('updating bookmark %s failed!\n') % b)
4456 if not result:
4458 if not result:
4457 result = 2
4459 result = 2
4458
4460
4459 return result
4461 return result
4460
4462
4461 @command('recover', [])
4463 @command('recover', [])
4462 def recover(ui, repo):
4464 def recover(ui, repo):
4463 """roll back an interrupted transaction
4465 """roll back an interrupted transaction
4464
4466
4465 Recover from an interrupted commit or pull.
4467 Recover from an interrupted commit or pull.
4466
4468
4467 This command tries to fix the repository status after an
4469 This command tries to fix the repository status after an
4468 interrupted operation. It should only be necessary when Mercurial
4470 interrupted operation. It should only be necessary when Mercurial
4469 suggests it.
4471 suggests it.
4470
4472
4471 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.
4472 """
4474 """
4473 if repo.recover():
4475 if repo.recover():
4474 return hg.verify(repo)
4476 return hg.verify(repo)
4475 return 1
4477 return 1
4476
4478
4477 @command('^remove|rm',
4479 @command('^remove|rm',
4478 [('A', 'after', None, _('record delete for missing files')),
4480 [('A', 'after', None, _('record delete for missing files')),
4479 ('f', 'force', None,
4481 ('f', 'force', None,
4480 _('remove (and delete) file even if added or modified')),
4482 _('remove (and delete) file even if added or modified')),
4481 ] + walkopts,
4483 ] + walkopts,
4482 _('[OPTION]... FILE...'))
4484 _('[OPTION]... FILE...'))
4483 def remove(ui, repo, *pats, **opts):
4485 def remove(ui, repo, *pats, **opts):
4484 """remove the specified files on the next commit
4486 """remove the specified files on the next commit
4485
4487
4486 Schedule the indicated files for removal from the current branch.
4488 Schedule the indicated files for removal from the current branch.
4487
4489
4488 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.
4489 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
4490 files, see :hg:`forget`.
4492 files, see :hg:`forget`.
4491
4493
4492 .. container:: verbose
4494 .. container:: verbose
4493
4495
4494 -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
4495 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
4496 can be used to remove files from the next revision without
4498 can be used to remove files from the next revision without
4497 deleting them from the working directory.
4499 deleting them from the working directory.
4498
4500
4499 The following table details the behavior of remove for different
4501 The following table details the behavior of remove for different
4500 file states (columns) and option combinations (rows). The file
4502 file states (columns) and option combinations (rows). The file
4501 states are Added [A], Clean [C], Modified [M] and Missing [!]
4503 states are Added [A], Clean [C], Modified [M] and Missing [!]
4502 (as reported by :hg:`status`). The actions are Warn, Remove
4504 (as reported by :hg:`status`). The actions are Warn, Remove
4503 (from branch) and Delete (from disk):
4505 (from branch) and Delete (from disk):
4504
4506
4505 ======= == == == ==
4507 ======= == == == ==
4506 A C M !
4508 A C M !
4507 ======= == == == ==
4509 ======= == == == ==
4508 none W RD W R
4510 none W RD W R
4509 -f R RD RD R
4511 -f R RD RD R
4510 -A W W W R
4512 -A W W W R
4511 -Af R R R R
4513 -Af R R R R
4512 ======= == == == ==
4514 ======= == == == ==
4513
4515
4514 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
4515 working directory, not even if option --force is specified.
4517 working directory, not even if option --force is specified.
4516
4518
4517 Returns 0 on success, 1 if any warnings encountered.
4519 Returns 0 on success, 1 if any warnings encountered.
4518 """
4520 """
4519
4521
4520 ret = 0
4522 ret = 0
4521 after, force = opts.get('after'), opts.get('force')
4523 after, force = opts.get('after'), opts.get('force')
4522 if not pats and not after:
4524 if not pats and not after:
4523 raise util.Abort(_('no files specified'))
4525 raise util.Abort(_('no files specified'))
4524
4526
4525 m = scmutil.match(repo[None], pats, opts)
4527 m = scmutil.match(repo[None], pats, opts)
4526 s = repo.status(match=m, clean=True)
4528 s = repo.status(match=m, clean=True)
4527 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]
4528
4530
4529 for f in m.files():
4531 for f in m.files():
4530 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)):
4531 if os.path.exists(m.rel(f)):
4533 if os.path.exists(m.rel(f)):
4532 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))
4533 ret = 1
4535 ret = 1
4534
4536
4535 if force:
4537 if force:
4536 list = modified + deleted + clean + added
4538 list = modified + deleted + clean + added
4537 elif after:
4539 elif after:
4538 list = deleted
4540 list = deleted
4539 for f in modified + added + clean:
4541 for f in modified + added + clean:
4540 ui.warn(_('not removing %s: file still exists (use -f'
4542 ui.warn(_('not removing %s: file still exists (use -f'
4541 ' to force removal)\n') % m.rel(f))
4543 ' to force removal)\n') % m.rel(f))
4542 ret = 1
4544 ret = 1
4543 else:
4545 else:
4544 list = deleted + clean
4546 list = deleted + clean
4545 for f in modified:
4547 for f in modified:
4546 ui.warn(_('not removing %s: file is modified (use -f'
4548 ui.warn(_('not removing %s: file is modified (use -f'
4547 ' to force removal)\n') % m.rel(f))
4549 ' to force removal)\n') % m.rel(f))
4548 ret = 1
4550 ret = 1
4549 for f in added:
4551 for f in added:
4550 ui.warn(_('not removing %s: file has been marked for add'
4552 ui.warn(_('not removing %s: file has been marked for add'
4551 ' (use forget to undo)\n') % m.rel(f))
4553 ' (use forget to undo)\n') % m.rel(f))
4552 ret = 1
4554 ret = 1
4553
4555
4554 for f in sorted(list):
4556 for f in sorted(list):
4555 if ui.verbose or not m.exact(f):
4557 if ui.verbose or not m.exact(f):
4556 ui.status(_('removing %s\n') % m.rel(f))
4558 ui.status(_('removing %s\n') % m.rel(f))
4557
4559
4558 wlock = repo.wlock()
4560 wlock = repo.wlock()
4559 try:
4561 try:
4560 if not after:
4562 if not after:
4561 for f in list:
4563 for f in list:
4562 if f in added:
4564 if f in added:
4563 continue # we never unlink added files on remove
4565 continue # we never unlink added files on remove
4564 try:
4566 try:
4565 util.unlinkpath(repo.wjoin(f))
4567 util.unlinkpath(repo.wjoin(f))
4566 except OSError, inst:
4568 except OSError, inst:
4567 if inst.errno != errno.ENOENT:
4569 if inst.errno != errno.ENOENT:
4568 raise
4570 raise
4569 repo[None].forget(list)
4571 repo[None].forget(list)
4570 finally:
4572 finally:
4571 wlock.release()
4573 wlock.release()
4572
4574
4573 return ret
4575 return ret
4574
4576
4575 @command('rename|move|mv',
4577 @command('rename|move|mv',
4576 [('A', 'after', None, _('record a rename that has already occurred')),
4578 [('A', 'after', None, _('record a rename that has already occurred')),
4577 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4579 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4578 ] + walkopts + dryrunopts,
4580 ] + walkopts + dryrunopts,
4579 _('[OPTION]... SOURCE... DEST'))
4581 _('[OPTION]... SOURCE... DEST'))
4580 def rename(ui, repo, *pats, **opts):
4582 def rename(ui, repo, *pats, **opts):
4581 """rename files; equivalent of copy + remove
4583 """rename files; equivalent of copy + remove
4582
4584
4583 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
4584 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
4585 file, there can only be one source.
4587 file, there can only be one source.
4586
4588
4587 By default, this command copies the contents of files as they
4589 By default, this command copies the contents of files as they
4588 exist in the working directory. If invoked with -A/--after, the
4590 exist in the working directory. If invoked with -A/--after, the
4589 operation is recorded, but no copying is performed.
4591 operation is recorded, but no copying is performed.
4590
4592
4591 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
4592 before that, see :hg:`revert`.
4594 before that, see :hg:`revert`.
4593
4595
4594 Returns 0 on success, 1 if errors are encountered.
4596 Returns 0 on success, 1 if errors are encountered.
4595 """
4597 """
4596 wlock = repo.wlock(False)
4598 wlock = repo.wlock(False)
4597 try:
4599 try:
4598 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4600 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4599 finally:
4601 finally:
4600 wlock.release()
4602 wlock.release()
4601
4603
4602 @command('resolve',
4604 @command('resolve',
4603 [('a', 'all', None, _('select all unresolved files')),
4605 [('a', 'all', None, _('select all unresolved files')),
4604 ('l', 'list', None, _('list state of files needing merge')),
4606 ('l', 'list', None, _('list state of files needing merge')),
4605 ('m', 'mark', None, _('mark files as resolved')),
4607 ('m', 'mark', None, _('mark files as resolved')),
4606 ('u', 'unmark', None, _('mark files as unresolved')),
4608 ('u', 'unmark', None, _('mark files as unresolved')),
4607 ('n', 'no-status', None, _('hide status prefix'))]
4609 ('n', 'no-status', None, _('hide status prefix'))]
4608 + mergetoolopts + walkopts,
4610 + mergetoolopts + walkopts,
4609 _('[OPTION]... [FILE]...'))
4611 _('[OPTION]... [FILE]...'))
4610 def resolve(ui, repo, *pats, **opts):
4612 def resolve(ui, repo, *pats, **opts):
4611 """redo merges or set/view the merge status of files
4613 """redo merges or set/view the merge status of files
4612
4614
4613 Merges with unresolved conflicts are often the result of
4615 Merges with unresolved conflicts are often the result of
4614 non-interactive merging using the ``internal:merge`` configuration
4616 non-interactive merging using the ``internal:merge`` configuration
4615 setting, or a command-line merge tool like ``diff3``. The resolve
4617 setting, or a command-line merge tool like ``diff3``. The resolve
4616 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
4617 :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
4618 working directory must have two parents).
4620 working directory must have two parents).
4619
4621
4620 The resolve command can be used in the following ways:
4622 The resolve command can be used in the following ways:
4621
4623
4622 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4624 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4623 files, discarding any previous merge attempts. Re-merging is not
4625 files, discarding any previous merge attempts. Re-merging is not
4624 performed for files already marked as resolved. Use ``--all/-a``
4626 performed for files already marked as resolved. Use ``--all/-a``
4625 to select all unresolved files. ``--tool`` can be used to specify
4627 to select all unresolved files. ``--tool`` can be used to specify
4626 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
4627 environment variable and your configuration files. Previous file
4629 environment variable and your configuration files. Previous file
4628 contents are saved with a ``.orig`` suffix.
4630 contents are saved with a ``.orig`` suffix.
4629
4631
4630 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4632 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4631 (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
4632 to mark all unresolved files.
4634 to mark all unresolved files.
4633
4635
4634 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4636 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4635 default is to mark all resolved files.
4637 default is to mark all resolved files.
4636
4638
4637 - :hg:`resolve -l`: list files which had or still have conflicts.
4639 - :hg:`resolve -l`: list files which had or still have conflicts.
4638 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4640 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4639
4641
4640 Note that Mercurial will not let you commit files with unresolved
4642 Note that Mercurial will not let you commit files with unresolved
4641 merge conflicts. You must use :hg:`resolve -m ...` before you can
4643 merge conflicts. You must use :hg:`resolve -m ...` before you can
4642 commit after a conflicting merge.
4644 commit after a conflicting merge.
4643
4645
4644 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.
4645 """
4647 """
4646
4648
4647 all, mark, unmark, show, nostatus = \
4649 all, mark, unmark, show, nostatus = \
4648 [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()]
4649
4651
4650 if (show and (mark or unmark)) or (mark and unmark):
4652 if (show and (mark or unmark)) or (mark and unmark):
4651 raise util.Abort(_("too many options specified"))
4653 raise util.Abort(_("too many options specified"))
4652 if pats and all:
4654 if pats and all:
4653 raise util.Abort(_("can't specify --all and patterns"))
4655 raise util.Abort(_("can't specify --all and patterns"))
4654 if not (all or pats or show or mark or unmark):
4656 if not (all or pats or show or mark or unmark):
4655 raise util.Abort(_('no files or directories specified; '
4657 raise util.Abort(_('no files or directories specified; '
4656 'use --all to remerge all files'))
4658 'use --all to remerge all files'))
4657
4659
4658 ms = mergemod.mergestate(repo)
4660 ms = mergemod.mergestate(repo)
4659 m = scmutil.match(repo[None], pats, opts)
4661 m = scmutil.match(repo[None], pats, opts)
4660 ret = 0
4662 ret = 0
4661
4663
4662 for f in ms:
4664 for f in ms:
4663 if m(f):
4665 if m(f):
4664 if show:
4666 if show:
4665 if nostatus:
4667 if nostatus:
4666 ui.write("%s\n" % f)
4668 ui.write("%s\n" % f)
4667 else:
4669 else:
4668 ui.write("%s %s\n" % (ms[f].upper(), f),
4670 ui.write("%s %s\n" % (ms[f].upper(), f),
4669 label='resolve.' +
4671 label='resolve.' +
4670 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4672 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4671 elif mark:
4673 elif mark:
4672 ms.mark(f, "r")
4674 ms.mark(f, "r")
4673 elif unmark:
4675 elif unmark:
4674 ms.mark(f, "u")
4676 ms.mark(f, "u")
4675 else:
4677 else:
4676 wctx = repo[None]
4678 wctx = repo[None]
4677 mctx = wctx.parents()[-1]
4679 mctx = wctx.parents()[-1]
4678
4680
4679 # backup pre-resolve (merge uses .orig for its own purposes)
4681 # backup pre-resolve (merge uses .orig for its own purposes)
4680 a = repo.wjoin(f)
4682 a = repo.wjoin(f)
4681 util.copyfile(a, a + ".resolve")
4683 util.copyfile(a, a + ".resolve")
4682
4684
4683 try:
4685 try:
4684 # resolve file
4686 # resolve file
4685 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4687 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4686 if ms.resolve(f, wctx, mctx):
4688 if ms.resolve(f, wctx, mctx):
4687 ret = 1
4689 ret = 1
4688 finally:
4690 finally:
4689 ui.setconfig('ui', 'forcemerge', '')
4691 ui.setconfig('ui', 'forcemerge', '')
4690
4692
4691 # replace filemerge's .orig file with our resolve file
4693 # replace filemerge's .orig file with our resolve file
4692 util.rename(a + ".resolve", a + ".orig")
4694 util.rename(a + ".resolve", a + ".orig")
4693
4695
4694 ms.commit()
4696 ms.commit()
4695 return ret
4697 return ret
4696
4698
4697 @command('revert',
4699 @command('revert',
4698 [('a', 'all', None, _('revert all changes when no arguments given')),
4700 [('a', 'all', None, _('revert all changes when no arguments given')),
4699 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4701 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4700 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4702 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4701 ('C', 'no-backup', None, _('do not save backup copies of files')),
4703 ('C', 'no-backup', None, _('do not save backup copies of files')),
4702 ] + walkopts + dryrunopts,
4704 ] + walkopts + dryrunopts,
4703 _('[OPTION]... [-r REV] [NAME]...'))
4705 _('[OPTION]... [-r REV] [NAME]...'))
4704 def revert(ui, repo, *pats, **opts):
4706 def revert(ui, repo, *pats, **opts):
4705 """restore files to their checkout state
4707 """restore files to their checkout state
4706
4708
4707 .. note::
4709 .. note::
4708 To check out earlier revisions, you should use :hg:`update REV`.
4710 To check out earlier revisions, you should use :hg:`update REV`.
4709 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 .`.
4710
4712
4711 With no revision specified, revert the specified files or directories
4713 With no revision specified, revert the specified files or directories
4712 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.
4713 This restores the contents of files to an unmodified
4715 This restores the contents of files to an unmodified
4714 state and unschedules adds, removes, copies, and renames. If the
4716 state and unschedules adds, removes, copies, and renames. If the
4715 working directory has two parents, you must explicitly specify a
4717 working directory has two parents, you must explicitly specify a
4716 revision.
4718 revision.
4717
4719
4718 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
4719 directories to their states as of a specific revision. Because
4721 directories to their states as of a specific revision. Because
4720 revert does not change the working directory parents, this will
4722 revert does not change the working directory parents, this will
4721 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
4722 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
4723 related method.
4725 related method.
4724
4726
4725 Modified files are saved with a .orig suffix before reverting.
4727 Modified files are saved with a .orig suffix before reverting.
4726 To disable these backups, use --no-backup.
4728 To disable these backups, use --no-backup.
4727
4729
4728 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.
4729
4731
4730 Returns 0 on success.
4732 Returns 0 on success.
4731 """
4733 """
4732
4734
4733 if opts.get("date"):
4735 if opts.get("date"):
4734 if opts.get("rev"):
4736 if opts.get("rev"):
4735 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"))
4736 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4738 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4737
4739
4738 parent, p2 = repo.dirstate.parents()
4740 parent, p2 = repo.dirstate.parents()
4739 if not opts.get('rev') and p2 != nullid:
4741 if not opts.get('rev') and p2 != nullid:
4740 # revert after merge is a trap for new users (issue2915)
4742 # revert after merge is a trap for new users (issue2915)
4741 raise util.Abort(_('uncommitted merge with no revision specified'),
4743 raise util.Abort(_('uncommitted merge with no revision specified'),
4742 hint=_('use "hg update" or see "hg help revert"'))
4744 hint=_('use "hg update" or see "hg help revert"'))
4743
4745
4744 ctx = scmutil.revsingle(repo, opts.get('rev'))
4746 ctx = scmutil.revsingle(repo, opts.get('rev'))
4745 node = ctx.node()
4747 node = ctx.node()
4746
4748
4747 if not pats and not opts.get('all'):
4749 if not pats and not opts.get('all'):
4748 msg = _("no files or directories specified")
4750 msg = _("no files or directories specified")
4749 if p2 != nullid:
4751 if p2 != nullid:
4750 hint = _("uncommitted merge, use --all to discard all changes,"
4752 hint = _("uncommitted merge, use --all to discard all changes,"
4751 " or 'hg update -C .' to abort the merge")
4753 " or 'hg update -C .' to abort the merge")
4752 raise util.Abort(msg, hint=hint)
4754 raise util.Abort(msg, hint=hint)
4753 dirty = util.any(repo.status())
4755 dirty = util.any(repo.status())
4754 if node != parent:
4756 if node != parent:
4755 if dirty:
4757 if dirty:
4756 hint = _("uncommitted changes, use --all to discard all"
4758 hint = _("uncommitted changes, use --all to discard all"
4757 " changes, or 'hg update %s' to update") % ctx.rev()
4759 " changes, or 'hg update %s' to update") % ctx.rev()
4758 else:
4760 else:
4759 hint = _("use --all to revert all files,"
4761 hint = _("use --all to revert all files,"
4760 " or 'hg update %s' to update") % ctx.rev()
4762 " or 'hg update %s' to update") % ctx.rev()
4761 elif dirty:
4763 elif dirty:
4762 hint = _("uncommitted changes, use --all to discard all changes")
4764 hint = _("uncommitted changes, use --all to discard all changes")
4763 else:
4765 else:
4764 hint = _("use --all to revert all files")
4766 hint = _("use --all to revert all files")
4765 raise util.Abort(msg, hint=hint)
4767 raise util.Abort(msg, hint=hint)
4766
4768
4767 mf = ctx.manifest()
4769 mf = ctx.manifest()
4768 if node == parent:
4770 if node == parent:
4769 pmf = mf
4771 pmf = mf
4770 else:
4772 else:
4771 pmf = None
4773 pmf = None
4772
4774
4773 # need all matching names in dirstate and manifest of target rev,
4775 # need all matching names in dirstate and manifest of target rev,
4774 # 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
4775 # but not other.
4777 # but not other.
4776
4778
4777 names = {}
4779 names = {}
4778
4780
4779 wlock = repo.wlock()
4781 wlock = repo.wlock()
4780 try:
4782 try:
4781 # walk dirstate.
4783 # walk dirstate.
4782
4784
4783 m = scmutil.match(repo[None], pats, opts)
4785 m = scmutil.match(repo[None], pats, opts)
4784 m.bad = lambda x, y: False
4786 m.bad = lambda x, y: False
4785 for abs in repo.walk(m):
4787 for abs in repo.walk(m):
4786 names[abs] = m.rel(abs), m.exact(abs)
4788 names[abs] = m.rel(abs), m.exact(abs)
4787
4789
4788 # walk target manifest.
4790 # walk target manifest.
4789
4791
4790 def badfn(path, msg):
4792 def badfn(path, msg):
4791 if path in names:
4793 if path in names:
4792 return
4794 return
4793 if path in repo[node].substate:
4795 if path in repo[node].substate:
4794 ui.warn("%s: %s\n" % (m.rel(path),
4796 ui.warn("%s: %s\n" % (m.rel(path),
4795 'reverting subrepos is unsupported'))
4797 'reverting subrepos is unsupported'))
4796 return
4798 return
4797 path_ = path + '/'
4799 path_ = path + '/'
4798 for f in names:
4800 for f in names:
4799 if f.startswith(path_):
4801 if f.startswith(path_):
4800 return
4802 return
4801 ui.warn("%s: %s\n" % (m.rel(path), msg))
4803 ui.warn("%s: %s\n" % (m.rel(path), msg))
4802
4804
4803 m = scmutil.match(repo[node], pats, opts)
4805 m = scmutil.match(repo[node], pats, opts)
4804 m.bad = badfn
4806 m.bad = badfn
4805 for abs in repo[node].walk(m):
4807 for abs in repo[node].walk(m):
4806 if abs not in names:
4808 if abs not in names:
4807 names[abs] = m.rel(abs), m.exact(abs)
4809 names[abs] = m.rel(abs), m.exact(abs)
4808
4810
4809 m = scmutil.matchfiles(repo, names)
4811 m = scmutil.matchfiles(repo, names)
4810 changes = repo.status(match=m)[:4]
4812 changes = repo.status(match=m)[:4]
4811 modified, added, removed, deleted = map(set, changes)
4813 modified, added, removed, deleted = map(set, changes)
4812
4814
4813 # if f is a rename, also revert the source
4815 # if f is a rename, also revert the source
4814 cwd = repo.getcwd()
4816 cwd = repo.getcwd()
4815 for f in added:
4817 for f in added:
4816 src = repo.dirstate.copied(f)
4818 src = repo.dirstate.copied(f)
4817 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':
4818 removed.add(src)
4820 removed.add(src)
4819 names[src] = (repo.pathto(src, cwd), True)
4821 names[src] = (repo.pathto(src, cwd), True)
4820
4822
4821 def removeforget(abs):
4823 def removeforget(abs):
4822 if repo.dirstate[abs] == 'a':
4824 if repo.dirstate[abs] == 'a':
4823 return _('forgetting %s\n')
4825 return _('forgetting %s\n')
4824 return _('removing %s\n')
4826 return _('removing %s\n')
4825
4827
4826 revert = ([], _('reverting %s\n'))
4828 revert = ([], _('reverting %s\n'))
4827 add = ([], _('adding %s\n'))
4829 add = ([], _('adding %s\n'))
4828 remove = ([], removeforget)
4830 remove = ([], removeforget)
4829 undelete = ([], _('undeleting %s\n'))
4831 undelete = ([], _('undeleting %s\n'))
4830
4832
4831 disptable = (
4833 disptable = (
4832 # dispatch table:
4834 # dispatch table:
4833 # file state
4835 # file state
4834 # action if in target manifest
4836 # action if in target manifest
4835 # action if not in target manifest
4837 # action if not in target manifest
4836 # make backup if in target manifest
4838 # make backup if in target manifest
4837 # make backup if not in target manifest
4839 # make backup if not in target manifest
4838 (modified, revert, remove, True, True),
4840 (modified, revert, remove, True, True),
4839 (added, revert, remove, True, False),
4841 (added, revert, remove, True, False),
4840 (removed, undelete, None, False, False),
4842 (removed, undelete, None, False, False),
4841 (deleted, revert, remove, False, False),
4843 (deleted, revert, remove, False, False),
4842 )
4844 )
4843
4845
4844 for abs, (rel, exact) in sorted(names.items()):
4846 for abs, (rel, exact) in sorted(names.items()):
4845 mfentry = mf.get(abs)
4847 mfentry = mf.get(abs)
4846 target = repo.wjoin(abs)
4848 target = repo.wjoin(abs)
4847 def handle(xlist, dobackup):
4849 def handle(xlist, dobackup):
4848 xlist[0].append(abs)
4850 xlist[0].append(abs)
4849 if (dobackup and not opts.get('no_backup') and
4851 if (dobackup and not opts.get('no_backup') and
4850 os.path.lexists(target)):
4852 os.path.lexists(target)):
4851 bakname = "%s.orig" % rel
4853 bakname = "%s.orig" % rel
4852 ui.note(_('saving current version of %s as %s\n') %
4854 ui.note(_('saving current version of %s as %s\n') %
4853 (rel, bakname))
4855 (rel, bakname))
4854 if not opts.get('dry_run'):
4856 if not opts.get('dry_run'):
4855 util.rename(target, bakname)
4857 util.rename(target, bakname)
4856 if ui.verbose or not exact:
4858 if ui.verbose or not exact:
4857 msg = xlist[1]
4859 msg = xlist[1]
4858 if not isinstance(msg, basestring):
4860 if not isinstance(msg, basestring):
4859 msg = msg(abs)
4861 msg = msg(abs)
4860 ui.status(msg % rel)
4862 ui.status(msg % rel)
4861 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4863 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4862 if abs not in table:
4864 if abs not in table:
4863 continue
4865 continue
4864 # file has changed in dirstate
4866 # file has changed in dirstate
4865 if mfentry:
4867 if mfentry:
4866 handle(hitlist, backuphit)
4868 handle(hitlist, backuphit)
4867 elif misslist is not None:
4869 elif misslist is not None:
4868 handle(misslist, backupmiss)
4870 handle(misslist, backupmiss)
4869 break
4871 break
4870 else:
4872 else:
4871 if abs not in repo.dirstate:
4873 if abs not in repo.dirstate:
4872 if mfentry:
4874 if mfentry:
4873 handle(add, True)
4875 handle(add, True)
4874 elif exact:
4876 elif exact:
4875 ui.warn(_('file not managed: %s\n') % rel)
4877 ui.warn(_('file not managed: %s\n') % rel)
4876 continue
4878 continue
4877 # file has not changed in dirstate
4879 # file has not changed in dirstate
4878 if node == parent:
4880 if node == parent:
4879 if exact:
4881 if exact:
4880 ui.warn(_('no changes needed to %s\n') % rel)
4882 ui.warn(_('no changes needed to %s\n') % rel)
4881 continue
4883 continue
4882 if pmf is None:
4884 if pmf is None:
4883 # only need parent manifest in this unlikely case,
4885 # only need parent manifest in this unlikely case,
4884 # so do not read by default
4886 # so do not read by default
4885 pmf = repo[parent].manifest()
4887 pmf = repo[parent].manifest()
4886 if abs in pmf and mfentry:
4888 if abs in pmf and mfentry:
4887 # if version of file is same in parent and target
4889 # if version of file is same in parent and target
4888 # manifests, do nothing
4890 # manifests, do nothing
4889 if (pmf[abs] != mfentry or
4891 if (pmf[abs] != mfentry or
4890 pmf.flags(abs) != mf.flags(abs)):
4892 pmf.flags(abs) != mf.flags(abs)):
4891 handle(revert, False)
4893 handle(revert, False)
4892 else:
4894 else:
4893 handle(remove, False)
4895 handle(remove, False)
4894
4896
4895 if not opts.get('dry_run'):
4897 if not opts.get('dry_run'):
4896 def checkout(f):
4898 def checkout(f):
4897 fc = ctx[f]
4899 fc = ctx[f]
4898 repo.wwrite(f, fc.data(), fc.flags())
4900 repo.wwrite(f, fc.data(), fc.flags())
4899
4901
4900 audit_path = scmutil.pathauditor(repo.root)
4902 audit_path = scmutil.pathauditor(repo.root)
4901 for f in remove[0]:
4903 for f in remove[0]:
4902 if repo.dirstate[f] == 'a':
4904 if repo.dirstate[f] == 'a':
4903 repo.dirstate.drop(f)
4905 repo.dirstate.drop(f)
4904 continue
4906 continue
4905 audit_path(f)
4907 audit_path(f)
4906 try:
4908 try:
4907 util.unlinkpath(repo.wjoin(f))
4909 util.unlinkpath(repo.wjoin(f))
4908 except OSError:
4910 except OSError:
4909 pass
4911 pass
4910 repo.dirstate.remove(f)
4912 repo.dirstate.remove(f)
4911
4913
4912 normal = None
4914 normal = None
4913 if node == parent:
4915 if node == parent:
4914 # 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
4915 # 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
4916 # merges to avoid losing information about merged/dirty files.
4918 # merges to avoid losing information about merged/dirty files.
4917 if p2 != nullid:
4919 if p2 != nullid:
4918 normal = repo.dirstate.normallookup
4920 normal = repo.dirstate.normallookup
4919 else:
4921 else:
4920 normal = repo.dirstate.normal
4922 normal = repo.dirstate.normal
4921 for f in revert[0]:
4923 for f in revert[0]:
4922 checkout(f)
4924 checkout(f)
4923 if normal:
4925 if normal:
4924 normal(f)
4926 normal(f)
4925
4927
4926 for f in add[0]:
4928 for f in add[0]:
4927 checkout(f)
4929 checkout(f)
4928 repo.dirstate.add(f)
4930 repo.dirstate.add(f)
4929
4931
4930 normal = repo.dirstate.normallookup
4932 normal = repo.dirstate.normallookup
4931 if node == parent and p2 == nullid:
4933 if node == parent and p2 == nullid:
4932 normal = repo.dirstate.normal
4934 normal = repo.dirstate.normal
4933 for f in undelete[0]:
4935 for f in undelete[0]:
4934 checkout(f)
4936 checkout(f)
4935 normal(f)
4937 normal(f)
4936
4938
4937 finally:
4939 finally:
4938 wlock.release()
4940 wlock.release()
4939
4941
4940 @command('rollback', dryrunopts +
4942 @command('rollback', dryrunopts +
4941 [('f', 'force', False, _('ignore safety measures'))])
4943 [('f', 'force', False, _('ignore safety measures'))])
4942 def rollback(ui, repo, **opts):
4944 def rollback(ui, repo, **opts):
4943 """roll back the last transaction (dangerous)
4945 """roll back the last transaction (dangerous)
4944
4946
4945 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
4946 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
4947 restore the dirstate at the time of the last transaction, losing
4949 restore the dirstate at the time of the last transaction, losing
4948 any dirstate changes since that time. This command does not alter
4950 any dirstate changes since that time. This command does not alter
4949 the working directory.
4951 the working directory.
4950
4952
4951 Transactions are used to encapsulate the effects of all commands
4953 Transactions are used to encapsulate the effects of all commands
4952 that create new changesets or propagate existing changesets into a
4954 that create new changesets or propagate existing changesets into a
4953 repository. For example, the following commands are transactional,
4955 repository. For example, the following commands are transactional,
4954 and their effects can be rolled back:
4956 and their effects can be rolled back:
4955
4957
4956 - commit
4958 - commit
4957 - import
4959 - import
4958 - pull
4960 - pull
4959 - push (with this repository as the destination)
4961 - push (with this repository as the destination)
4960 - unbundle
4962 - unbundle
4961
4963
4962 To avoid permanent data loss, rollback will refuse to rollback a
4964 To avoid permanent data loss, rollback will refuse to rollback a
4963 commit transaction if it isn't checked out. Use --force to
4965 commit transaction if it isn't checked out. Use --force to
4964 override this protection.
4966 override this protection.
4965
4967
4966 This command is not intended for use on public repositories. Once
4968 This command is not intended for use on public repositories. Once
4967 changes are visible for pull by other users, rolling a transaction
4969 changes are visible for pull by other users, rolling a transaction
4968 back locally is ineffective (someone else may already have pulled
4970 back locally is ineffective (someone else may already have pulled
4969 the changes). Furthermore, a race is possible with readers of the
4971 the changes). Furthermore, a race is possible with readers of the
4970 repository; for example an in-progress pull from the repository
4972 repository; for example an in-progress pull from the repository
4971 may fail if a rollback is performed.
4973 may fail if a rollback is performed.
4972
4974
4973 Returns 0 on success, 1 if no rollback data is available.
4975 Returns 0 on success, 1 if no rollback data is available.
4974 """
4976 """
4975 return repo.rollback(dryrun=opts.get('dry_run'),
4977 return repo.rollback(dryrun=opts.get('dry_run'),
4976 force=opts.get('force'))
4978 force=opts.get('force'))
4977
4979
4978 @command('root', [])
4980 @command('root', [])
4979 def root(ui, repo):
4981 def root(ui, repo):
4980 """print the root (top) of the current working directory
4982 """print the root (top) of the current working directory
4981
4983
4982 Print the root directory of the current repository.
4984 Print the root directory of the current repository.
4983
4985
4984 Returns 0 on success.
4986 Returns 0 on success.
4985 """
4987 """
4986 ui.write(repo.root + "\n")
4988 ui.write(repo.root + "\n")
4987
4989
4988 @command('^serve',
4990 @command('^serve',
4989 [('A', 'accesslog', '', _('name of access log file to write to'),
4991 [('A', 'accesslog', '', _('name of access log file to write to'),
4990 _('FILE')),
4992 _('FILE')),
4991 ('d', 'daemon', None, _('run server in background')),
4993 ('d', 'daemon', None, _('run server in background')),
4992 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4994 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4993 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4995 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4994 # use string type, then we can check if something was passed
4996 # use string type, then we can check if something was passed
4995 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4997 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4996 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4998 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4997 _('ADDR')),
4999 _('ADDR')),
4998 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5000 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4999 _('PREFIX')),
5001 _('PREFIX')),
5000 ('n', 'name', '',
5002 ('n', 'name', '',
5001 _('name to show in web pages (default: working directory)'), _('NAME')),
5003 _('name to show in web pages (default: working directory)'), _('NAME')),
5002 ('', 'web-conf', '',
5004 ('', 'web-conf', '',
5003 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5005 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5004 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5006 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5005 _('FILE')),
5007 _('FILE')),
5006 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5008 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5007 ('', 'stdio', None, _('for remote clients')),
5009 ('', 'stdio', None, _('for remote clients')),
5008 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5010 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5009 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5011 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5010 ('', 'style', '', _('template style to use'), _('STYLE')),
5012 ('', 'style', '', _('template style to use'), _('STYLE')),
5011 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5013 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5012 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5014 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5013 _('[OPTION]...'))
5015 _('[OPTION]...'))
5014 def serve(ui, repo, **opts):
5016 def serve(ui, repo, **opts):
5015 """start stand-alone webserver
5017 """start stand-alone webserver
5016
5018
5017 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
5018 this for ad-hoc sharing and browsing of repositories. It is
5020 this for ad-hoc sharing and browsing of repositories. It is
5019 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
5020 longer periods of time.
5022 longer periods of time.
5021
5023
5022 Please note that the server does not implement access control.
5024 Please note that the server does not implement access control.
5023 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
5024 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``
5025 option to ``*`` to allow everybody to push to the server. You
5027 option to ``*`` to allow everybody to push to the server. You
5026 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.
5027
5029
5028 By default, the server logs accesses to stdout and errors to
5030 By default, the server logs accesses to stdout and errors to
5029 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
5030 files.
5032 files.
5031
5033
5032 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
5033 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
5034 number it uses.
5036 number it uses.
5035
5037
5036 Returns 0 on success.
5038 Returns 0 on success.
5037 """
5039 """
5038
5040
5039 if opts["stdio"] and opts["cmdserver"]:
5041 if opts["stdio"] and opts["cmdserver"]:
5040 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5042 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5041
5043
5042 def checkrepo():
5044 def checkrepo():
5043 if repo is None:
5045 if repo is None:
5044 raise error.RepoError(_("There is no Mercurial repository here"
5046 raise error.RepoError(_("There is no Mercurial repository here"
5045 " (.hg not found)"))
5047 " (.hg not found)"))
5046
5048
5047 if opts["stdio"]:
5049 if opts["stdio"]:
5048 checkrepo()
5050 checkrepo()
5049 s = sshserver.sshserver(ui, repo)
5051 s = sshserver.sshserver(ui, repo)
5050 s.serve_forever()
5052 s.serve_forever()
5051
5053
5052 if opts["cmdserver"]:
5054 if opts["cmdserver"]:
5053 checkrepo()
5055 checkrepo()
5054 s = commandserver.server(ui, repo, opts["cmdserver"])
5056 s = commandserver.server(ui, repo, opts["cmdserver"])
5055 return s.serve()
5057 return s.serve()
5056
5058
5057 # 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
5058 if opts.get('port'):
5060 if opts.get('port'):
5059 opts['port'] = util.getport(opts.get('port'))
5061 opts['port'] = util.getport(opts.get('port'))
5060
5062
5061 baseui = repo and repo.baseui or ui
5063 baseui = repo and repo.baseui or ui
5062 optlist = ("name templates style address port prefix ipv6"
5064 optlist = ("name templates style address port prefix ipv6"
5063 " accesslog errorlog certificate encoding")
5065 " accesslog errorlog certificate encoding")
5064 for o in optlist.split():
5066 for o in optlist.split():
5065 val = opts.get(o, '')
5067 val = opts.get(o, '')
5066 if val in (None, ''): # should check against default options instead
5068 if val in (None, ''): # should check against default options instead
5067 continue
5069 continue
5068 baseui.setconfig("web", o, val)
5070 baseui.setconfig("web", o, val)
5069 if repo and repo.ui != baseui:
5071 if repo and repo.ui != baseui:
5070 repo.ui.setconfig("web", o, val)
5072 repo.ui.setconfig("web", o, val)
5071
5073
5072 o = opts.get('web_conf') or opts.get('webdir_conf')
5074 o = opts.get('web_conf') or opts.get('webdir_conf')
5073 if not o:
5075 if not o:
5074 if not repo:
5076 if not repo:
5075 raise error.RepoError(_("There is no Mercurial repository"
5077 raise error.RepoError(_("There is no Mercurial repository"
5076 " here (.hg not found)"))
5078 " here (.hg not found)"))
5077 o = repo.root
5079 o = repo.root
5078
5080
5079 app = hgweb.hgweb(o, baseui=ui)
5081 app = hgweb.hgweb(o, baseui=ui)
5080
5082
5081 class service(object):
5083 class service(object):
5082 def init(self):
5084 def init(self):
5083 util.setsignalhandler()
5085 util.setsignalhandler()
5084 self.httpd = hgweb.server.create_server(ui, app)
5086 self.httpd = hgweb.server.create_server(ui, app)
5085
5087
5086 if opts['port'] and not ui.verbose:
5088 if opts['port'] and not ui.verbose:
5087 return
5089 return
5088
5090
5089 if self.httpd.prefix:
5091 if self.httpd.prefix:
5090 prefix = self.httpd.prefix.strip('/') + '/'
5092 prefix = self.httpd.prefix.strip('/') + '/'
5091 else:
5093 else:
5092 prefix = ''
5094 prefix = ''
5093
5095
5094 port = ':%d' % self.httpd.port
5096 port = ':%d' % self.httpd.port
5095 if port == ':80':
5097 if port == ':80':
5096 port = ''
5098 port = ''
5097
5099
5098 bindaddr = self.httpd.addr
5100 bindaddr = self.httpd.addr
5099 if bindaddr == '0.0.0.0':
5101 if bindaddr == '0.0.0.0':
5100 bindaddr = '*'
5102 bindaddr = '*'
5101 elif ':' in bindaddr: # IPv6
5103 elif ':' in bindaddr: # IPv6
5102 bindaddr = '[%s]' % bindaddr
5104 bindaddr = '[%s]' % bindaddr
5103
5105
5104 fqaddr = self.httpd.fqaddr
5106 fqaddr = self.httpd.fqaddr
5105 if ':' in fqaddr:
5107 if ':' in fqaddr:
5106 fqaddr = '[%s]' % fqaddr
5108 fqaddr = '[%s]' % fqaddr
5107 if opts['port']:
5109 if opts['port']:
5108 write = ui.status
5110 write = ui.status
5109 else:
5111 else:
5110 write = ui.write
5112 write = ui.write
5111 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') %
5112 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5114 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5113
5115
5114 def run(self):
5116 def run(self):
5115 self.httpd.serve_forever()
5117 self.httpd.serve_forever()
5116
5118
5117 service = service()
5119 service = service()
5118
5120
5119 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5121 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5120
5122
5121 @command('showconfig|debugconfig',
5123 @command('showconfig|debugconfig',
5122 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5124 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5123 _('[-u] [NAME]...'))
5125 _('[-u] [NAME]...'))
5124 def showconfig(ui, repo, *values, **opts):
5126 def showconfig(ui, repo, *values, **opts):
5125 """show combined config settings from all hgrc files
5127 """show combined config settings from all hgrc files
5126
5128
5127 With no arguments, print names and values of all config items.
5129 With no arguments, print names and values of all config items.
5128
5130
5129 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
5130 of that config item.
5132 of that config item.
5131
5133
5132 With multiple arguments, print names and values of all config
5134 With multiple arguments, print names and values of all config
5133 items with matching section names.
5135 items with matching section names.
5134
5136
5135 With --debug, the source (filename and line number) is printed
5137 With --debug, the source (filename and line number) is printed
5136 for each config item.
5138 for each config item.
5137
5139
5138 Returns 0 on success.
5140 Returns 0 on success.
5139 """
5141 """
5140
5142
5141 for f in scmutil.rcpath():
5143 for f in scmutil.rcpath():
5142 ui.debug('read config from: %s\n' % f)
5144 ui.debug('read config from: %s\n' % f)
5143 untrusted = bool(opts.get('untrusted'))
5145 untrusted = bool(opts.get('untrusted'))
5144 if values:
5146 if values:
5145 sections = [v for v in values if '.' not in v]
5147 sections = [v for v in values if '.' not in v]
5146 items = [v for v in values if '.' in v]
5148 items = [v for v in values if '.' in v]
5147 if len(items) > 1 or items and sections:
5149 if len(items) > 1 or items and sections:
5148 raise util.Abort(_('only one config item permitted'))
5150 raise util.Abort(_('only one config item permitted'))
5149 for section, name, value in ui.walkconfig(untrusted=untrusted):
5151 for section, name, value in ui.walkconfig(untrusted=untrusted):
5150 value = str(value).replace('\n', '\\n')
5152 value = str(value).replace('\n', '\\n')
5151 sectname = section + '.' + name
5153 sectname = section + '.' + name
5152 if values:
5154 if values:
5153 for v in values:
5155 for v in values:
5154 if v == section:
5156 if v == section:
5155 ui.debug('%s: ' %
5157 ui.debug('%s: ' %
5156 ui.configsource(section, name, untrusted))
5158 ui.configsource(section, name, untrusted))
5157 ui.write('%s=%s\n' % (sectname, value))
5159 ui.write('%s=%s\n' % (sectname, value))
5158 elif v == sectname:
5160 elif v == sectname:
5159 ui.debug('%s: ' %
5161 ui.debug('%s: ' %
5160 ui.configsource(section, name, untrusted))
5162 ui.configsource(section, name, untrusted))
5161 ui.write(value, '\n')
5163 ui.write(value, '\n')
5162 else:
5164 else:
5163 ui.debug('%s: ' %
5165 ui.debug('%s: ' %
5164 ui.configsource(section, name, untrusted))
5166 ui.configsource(section, name, untrusted))
5165 ui.write('%s=%s\n' % (sectname, value))
5167 ui.write('%s=%s\n' % (sectname, value))
5166
5168
5167 @command('^status|st',
5169 @command('^status|st',
5168 [('A', 'all', None, _('show status of all files')),
5170 [('A', 'all', None, _('show status of all files')),
5169 ('m', 'modified', None, _('show only modified files')),
5171 ('m', 'modified', None, _('show only modified files')),
5170 ('a', 'added', None, _('show only added files')),
5172 ('a', 'added', None, _('show only added files')),
5171 ('r', 'removed', None, _('show only removed files')),
5173 ('r', 'removed', None, _('show only removed files')),
5172 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5174 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5173 ('c', 'clean', None, _('show only files without changes')),
5175 ('c', 'clean', None, _('show only files without changes')),
5174 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5176 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5175 ('i', 'ignored', None, _('show only ignored files')),
5177 ('i', 'ignored', None, _('show only ignored files')),
5176 ('n', 'no-status', None, _('hide status prefix')),
5178 ('n', 'no-status', None, _('hide status prefix')),
5177 ('C', 'copies', None, _('show source of copied files')),
5179 ('C', 'copies', None, _('show source of copied files')),
5178 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5180 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5179 ('', 'rev', [], _('show difference from revision'), _('REV')),
5181 ('', 'rev', [], _('show difference from revision'), _('REV')),
5180 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5182 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5181 ] + walkopts + subrepoopts,
5183 ] + walkopts + subrepoopts,
5182 _('[OPTION]... [FILE]...'))
5184 _('[OPTION]... [FILE]...'))
5183 def status(ui, repo, *pats, **opts):
5185 def status(ui, repo, *pats, **opts):
5184 """show changed files in the working directory
5186 """show changed files in the working directory
5185
5187
5186 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
5187 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
5188 the source of a copy/move operation, are not listed unless
5190 the source of a copy/move operation, are not listed unless
5189 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5191 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5190 Unless options described with "show only ..." are given, the
5192 Unless options described with "show only ..." are given, the
5191 options -mardu are used.
5193 options -mardu are used.
5192
5194
5193 Option -q/--quiet hides untracked (unknown and ignored) files
5195 Option -q/--quiet hides untracked (unknown and ignored) files
5194 unless explicitly requested with -u/--unknown or -i/--ignored.
5196 unless explicitly requested with -u/--unknown or -i/--ignored.
5195
5197
5196 .. note::
5198 .. note::
5197 status may appear to disagree with diff if permissions have
5199 status may appear to disagree with diff if permissions have
5198 changed or a merge has occurred. The standard diff format does
5200 changed or a merge has occurred. The standard diff format does
5199 not report permission changes and diff only reports changes
5201 not report permission changes and diff only reports changes
5200 relative to one merge parent.
5202 relative to one merge parent.
5201
5203
5202 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.
5203 If two revisions are given, the differences between them are
5205 If two revisions are given, the differences between them are
5204 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
5205 the changed files of a revision from its first parent.
5207 the changed files of a revision from its first parent.
5206
5208
5207 The codes used to show the status of files are::
5209 The codes used to show the status of files are::
5208
5210
5209 M = modified
5211 M = modified
5210 A = added
5212 A = added
5211 R = removed
5213 R = removed
5212 C = clean
5214 C = clean
5213 ! = missing (deleted by non-hg command, but still tracked)
5215 ! = missing (deleted by non-hg command, but still tracked)
5214 ? = not tracked
5216 ? = not tracked
5215 I = ignored
5217 I = ignored
5216 = origin of the previous file listed as A (added)
5218 = origin of the previous file listed as A (added)
5217
5219
5218 .. container:: verbose
5220 .. container:: verbose
5219
5221
5220 Examples:
5222 Examples:
5221
5223
5222 - show changes in the working directory relative to a
5224 - show changes in the working directory relative to a
5223 changeset::
5225 changeset::
5224
5226
5225 hg status --rev 9353
5227 hg status --rev 9353
5226
5228
5227 - show all changes including copies in an existing changeset::
5229 - show all changes including copies in an existing changeset::
5228
5230
5229 hg status --copies --change 9353
5231 hg status --copies --change 9353
5230
5232
5231 - get a NUL separated list of added files, suitable for xargs::
5233 - get a NUL separated list of added files, suitable for xargs::
5232
5234
5233 hg status -an0
5235 hg status -an0
5234
5236
5235 Returns 0 on success.
5237 Returns 0 on success.
5236 """
5238 """
5237
5239
5238 revs = opts.get('rev')
5240 revs = opts.get('rev')
5239 change = opts.get('change')
5241 change = opts.get('change')
5240
5242
5241 if revs and change:
5243 if revs and change:
5242 msg = _('cannot specify --rev and --change at the same time')
5244 msg = _('cannot specify --rev and --change at the same time')
5243 raise util.Abort(msg)
5245 raise util.Abort(msg)
5244 elif change:
5246 elif change:
5245 node2 = scmutil.revsingle(repo, change, None).node()
5247 node2 = scmutil.revsingle(repo, change, None).node()
5246 node1 = repo[node2].p1().node()
5248 node1 = repo[node2].p1().node()
5247 else:
5249 else:
5248 node1, node2 = scmutil.revpair(repo, revs)
5250 node1, node2 = scmutil.revpair(repo, revs)
5249
5251
5250 cwd = (pats and repo.getcwd()) or ''
5252 cwd = (pats and repo.getcwd()) or ''
5251 end = opts.get('print0') and '\0' or '\n'
5253 end = opts.get('print0') and '\0' or '\n'
5252 copy = {}
5254 copy = {}
5253 states = 'modified added removed deleted unknown ignored clean'.split()
5255 states = 'modified added removed deleted unknown ignored clean'.split()
5254 show = [k for k in states if opts.get(k)]
5256 show = [k for k in states if opts.get(k)]
5255 if opts.get('all'):
5257 if opts.get('all'):
5256 show += ui.quiet and (states[:4] + ['clean']) or states
5258 show += ui.quiet and (states[:4] + ['clean']) or states
5257 if not show:
5259 if not show:
5258 show = ui.quiet and states[:4] or states[:5]
5260 show = ui.quiet and states[:4] or states[:5]
5259
5261
5260 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5262 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5261 'ignored' in show, 'clean' in show, 'unknown' in show,
5263 'ignored' in show, 'clean' in show, 'unknown' in show,
5262 opts.get('subrepos'))
5264 opts.get('subrepos'))
5263 changestates = zip(states, 'MAR!?IC', stat)
5265 changestates = zip(states, 'MAR!?IC', stat)
5264
5266
5265 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'):
5266 copy = copies.pathcopies(repo[node1], repo[node2])
5268 copy = copies.pathcopies(repo[node1], repo[node2])
5267
5269
5268 for state, char, files in changestates:
5270 for state, char, files in changestates:
5269 if state in show:
5271 if state in show:
5270 format = "%s %%s%s" % (char, end)
5272 format = "%s %%s%s" % (char, end)
5271 if opts.get('no_status'):
5273 if opts.get('no_status'):
5272 format = "%%s%s" % end
5274 format = "%%s%s" % end
5273
5275
5274 for f in files:
5276 for f in files:
5275 ui.write(format % repo.pathto(f, cwd),
5277 ui.write(format % repo.pathto(f, cwd),
5276 label='status.' + state)
5278 label='status.' + state)
5277 if f in copy:
5279 if f in copy:
5278 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5280 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5279 label='status.copied')
5281 label='status.copied')
5280
5282
5281 @command('^summary|sum',
5283 @command('^summary|sum',
5282 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5284 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5283 def summary(ui, repo, **opts):
5285 def summary(ui, repo, **opts):
5284 """summarize working directory state
5286 """summarize working directory state
5285
5287
5286 This generates a brief summary of the working directory state,
5288 This generates a brief summary of the working directory state,
5287 including parents, branch, commit status, and available updates.
5289 including parents, branch, commit status, and available updates.
5288
5290
5289 With the --remote option, this will check the default paths for
5291 With the --remote option, this will check the default paths for
5290 incoming and outgoing changes. This can be time-consuming.
5292 incoming and outgoing changes. This can be time-consuming.
5291
5293
5292 Returns 0 on success.
5294 Returns 0 on success.
5293 """
5295 """
5294
5296
5295 ctx = repo[None]
5297 ctx = repo[None]
5296 parents = ctx.parents()
5298 parents = ctx.parents()
5297 pnode = parents[0].node()
5299 pnode = parents[0].node()
5298 marks = []
5300 marks = []
5299
5301
5300 for p in parents:
5302 for p in parents:
5301 # label with log.changeset (instead of log.parent) since this
5303 # label with log.changeset (instead of log.parent) since this
5302 # shows a working directory parent *changeset*:
5304 # shows a working directory parent *changeset*:
5303 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5305 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5304 label='log.changeset')
5306 label='log.changeset')
5305 ui.write(' '.join(p.tags()), label='log.tag')
5307 ui.write(' '.join(p.tags()), label='log.tag')
5306 if p.bookmarks():
5308 if p.bookmarks():
5307 marks.extend(p.bookmarks())
5309 marks.extend(p.bookmarks())
5308 if p.rev() == -1:
5310 if p.rev() == -1:
5309 if not len(repo):
5311 if not len(repo):
5310 ui.write(_(' (empty repository)'))
5312 ui.write(_(' (empty repository)'))
5311 else:
5313 else:
5312 ui.write(_(' (no revision checked out)'))
5314 ui.write(_(' (no revision checked out)'))
5313 ui.write('\n')
5315 ui.write('\n')
5314 if p.description():
5316 if p.description():
5315 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5317 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5316 label='log.summary')
5318 label='log.summary')
5317
5319
5318 branch = ctx.branch()
5320 branch = ctx.branch()
5319 bheads = repo.branchheads(branch)
5321 bheads = repo.branchheads(branch)
5320 m = _('branch: %s\n') % branch
5322 m = _('branch: %s\n') % branch
5321 if branch != 'default':
5323 if branch != 'default':
5322 ui.write(m, label='log.branch')
5324 ui.write(m, label='log.branch')
5323 else:
5325 else:
5324 ui.status(m, label='log.branch')
5326 ui.status(m, label='log.branch')
5325
5327
5326 if marks:
5328 if marks:
5327 current = repo._bookmarkcurrent
5329 current = repo._bookmarkcurrent
5328 ui.write(_('bookmarks:'), label='log.bookmark')
5330 ui.write(_('bookmarks:'), label='log.bookmark')
5329 if current is not None:
5331 if current is not None:
5330 try:
5332 try:
5331 marks.remove(current)
5333 marks.remove(current)
5332 ui.write(' *' + current, label='bookmarks.current')
5334 ui.write(' *' + current, label='bookmarks.current')
5333 except ValueError:
5335 except ValueError:
5334 # current bookmark not in parent ctx marks
5336 # current bookmark not in parent ctx marks
5335 pass
5337 pass
5336 for m in marks:
5338 for m in marks:
5337 ui.write(' ' + m, label='log.bookmark')
5339 ui.write(' ' + m, label='log.bookmark')
5338 ui.write('\n', label='log.bookmark')
5340 ui.write('\n', label='log.bookmark')
5339
5341
5340 st = list(repo.status(unknown=True))[:6]
5342 st = list(repo.status(unknown=True))[:6]
5341
5343
5342 c = repo.dirstate.copies()
5344 c = repo.dirstate.copies()
5343 copied, renamed = [], []
5345 copied, renamed = [], []
5344 for d, s in c.iteritems():
5346 for d, s in c.iteritems():
5345 if s in st[2]:
5347 if s in st[2]:
5346 st[2].remove(s)
5348 st[2].remove(s)
5347 renamed.append(d)
5349 renamed.append(d)
5348 else:
5350 else:
5349 copied.append(d)
5351 copied.append(d)
5350 if d in st[1]:
5352 if d in st[1]:
5351 st[1].remove(d)
5353 st[1].remove(d)
5352 st.insert(3, renamed)
5354 st.insert(3, renamed)
5353 st.insert(4, copied)
5355 st.insert(4, copied)
5354
5356
5355 ms = mergemod.mergestate(repo)
5357 ms = mergemod.mergestate(repo)
5356 st.append([f for f in ms if ms[f] == 'u'])
5358 st.append([f for f in ms if ms[f] == 'u'])
5357
5359
5358 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()]
5359 st.append(subs)
5361 st.append(subs)
5360
5362
5361 labels = [ui.label(_('%d modified'), 'status.modified'),
5363 labels = [ui.label(_('%d modified'), 'status.modified'),
5362 ui.label(_('%d added'), 'status.added'),
5364 ui.label(_('%d added'), 'status.added'),
5363 ui.label(_('%d removed'), 'status.removed'),
5365 ui.label(_('%d removed'), 'status.removed'),
5364 ui.label(_('%d renamed'), 'status.copied'),
5366 ui.label(_('%d renamed'), 'status.copied'),
5365 ui.label(_('%d copied'), 'status.copied'),
5367 ui.label(_('%d copied'), 'status.copied'),
5366 ui.label(_('%d deleted'), 'status.deleted'),
5368 ui.label(_('%d deleted'), 'status.deleted'),
5367 ui.label(_('%d unknown'), 'status.unknown'),
5369 ui.label(_('%d unknown'), 'status.unknown'),
5368 ui.label(_('%d ignored'), 'status.ignored'),
5370 ui.label(_('%d ignored'), 'status.ignored'),
5369 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5371 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5370 ui.label(_('%d subrepos'), 'status.modified')]
5372 ui.label(_('%d subrepos'), 'status.modified')]
5371 t = []
5373 t = []
5372 for s, l in zip(st, labels):
5374 for s, l in zip(st, labels):
5373 if s:
5375 if s:
5374 t.append(l % len(s))
5376 t.append(l % len(s))
5375
5377
5376 t = ', '.join(t)
5378 t = ', '.join(t)
5377 cleanworkdir = False
5379 cleanworkdir = False
5378
5380
5379 if len(parents) > 1:
5381 if len(parents) > 1:
5380 t += _(' (merge)')
5382 t += _(' (merge)')
5381 elif branch != parents[0].branch():
5383 elif branch != parents[0].branch():
5382 t += _(' (new branch)')
5384 t += _(' (new branch)')
5383 elif (parents[0].extra().get('close') and
5385 elif (parents[0].extra().get('close') and
5384 pnode in repo.branchheads(branch, closed=True)):
5386 pnode in repo.branchheads(branch, closed=True)):
5385 t += _(' (head closed)')
5387 t += _(' (head closed)')
5386 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]):
5387 t += _(' (clean)')
5389 t += _(' (clean)')
5388 cleanworkdir = True
5390 cleanworkdir = True
5389 elif pnode not in bheads:
5391 elif pnode not in bheads:
5390 t += _(' (new branch head)')
5392 t += _(' (new branch head)')
5391
5393
5392 if cleanworkdir:
5394 if cleanworkdir:
5393 ui.status(_('commit: %s\n') % t.strip())
5395 ui.status(_('commit: %s\n') % t.strip())
5394 else:
5396 else:
5395 ui.write(_('commit: %s\n') % t.strip())
5397 ui.write(_('commit: %s\n') % t.strip())
5396
5398
5397 # all ancestors of branch heads - all ancestors of parent = new csets
5399 # all ancestors of branch heads - all ancestors of parent = new csets
5398 new = [0] * len(repo)
5400 new = [0] * len(repo)
5399 cl = repo.changelog
5401 cl = repo.changelog
5400 for a in [cl.rev(n) for n in bheads]:
5402 for a in [cl.rev(n) for n in bheads]:
5401 new[a] = 1
5403 new[a] = 1
5402 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]):
5403 new[a] = 1
5405 new[a] = 1
5404 for a in [p.rev() for p in parents]:
5406 for a in [p.rev() for p in parents]:
5405 if a >= 0:
5407 if a >= 0:
5406 new[a] = 0
5408 new[a] = 0
5407 for a in cl.ancestors(*[p.rev() for p in parents]):
5409 for a in cl.ancestors(*[p.rev() for p in parents]):
5408 new[a] = 0
5410 new[a] = 0
5409 new = sum(new)
5411 new = sum(new)
5410
5412
5411 if new == 0:
5413 if new == 0:
5412 ui.status(_('update: (current)\n'))
5414 ui.status(_('update: (current)\n'))
5413 elif pnode not in bheads:
5415 elif pnode not in bheads:
5414 ui.write(_('update: %d new changesets (update)\n') % new)
5416 ui.write(_('update: %d new changesets (update)\n') % new)
5415 else:
5417 else:
5416 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5418 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5417 (new, len(bheads)))
5419 (new, len(bheads)))
5418
5420
5419 if opts.get('remote'):
5421 if opts.get('remote'):
5420 t = []
5422 t = []
5421 source, branches = hg.parseurl(ui.expandpath('default'))
5423 source, branches = hg.parseurl(ui.expandpath('default'))
5422 other = hg.peer(repo, {}, source)
5424 other = hg.peer(repo, {}, source)
5423 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5425 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5424 ui.debug('comparing with %s\n' % util.hidepassword(source))
5426 ui.debug('comparing with %s\n' % util.hidepassword(source))
5425 repo.ui.pushbuffer()
5427 repo.ui.pushbuffer()
5426 commoninc = discovery.findcommonincoming(repo, other)
5428 commoninc = discovery.findcommonincoming(repo, other)
5427 _common, incoming, _rheads = commoninc
5429 _common, incoming, _rheads = commoninc
5428 repo.ui.popbuffer()
5430 repo.ui.popbuffer()
5429 if incoming:
5431 if incoming:
5430 t.append(_('1 or more incoming'))
5432 t.append(_('1 or more incoming'))
5431
5433
5432 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5434 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5433 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5435 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5434 if source != dest:
5436 if source != dest:
5435 other = hg.peer(repo, {}, dest)
5437 other = hg.peer(repo, {}, dest)
5436 commoninc = None
5438 commoninc = None
5437 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5439 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5438 repo.ui.pushbuffer()
5440 repo.ui.pushbuffer()
5439 outgoing = discovery.findcommonoutgoing(repo, other,
5441 outgoing = discovery.findcommonoutgoing(repo, other,
5440 commoninc=commoninc)
5442 commoninc=commoninc)
5441 repo.ui.popbuffer()
5443 repo.ui.popbuffer()
5442 o = outgoing.missing
5444 o = outgoing.missing
5443 if o:
5445 if o:
5444 t.append(_('%d outgoing') % len(o))
5446 t.append(_('%d outgoing') % len(o))
5445 if 'bookmarks' in other.listkeys('namespaces'):
5447 if 'bookmarks' in other.listkeys('namespaces'):
5446 lmarks = repo.listkeys('bookmarks')
5448 lmarks = repo.listkeys('bookmarks')
5447 rmarks = other.listkeys('bookmarks')
5449 rmarks = other.listkeys('bookmarks')
5448 diff = set(rmarks) - set(lmarks)
5450 diff = set(rmarks) - set(lmarks)
5449 if len(diff) > 0:
5451 if len(diff) > 0:
5450 t.append(_('%d incoming bookmarks') % len(diff))
5452 t.append(_('%d incoming bookmarks') % len(diff))
5451 diff = set(lmarks) - set(rmarks)
5453 diff = set(lmarks) - set(rmarks)
5452 if len(diff) > 0:
5454 if len(diff) > 0:
5453 t.append(_('%d outgoing bookmarks') % len(diff))
5455 t.append(_('%d outgoing bookmarks') % len(diff))
5454
5456
5455 if t:
5457 if t:
5456 ui.write(_('remote: %s\n') % (', '.join(t)))
5458 ui.write(_('remote: %s\n') % (', '.join(t)))
5457 else:
5459 else:
5458 ui.status(_('remote: (synced)\n'))
5460 ui.status(_('remote: (synced)\n'))
5459
5461
5460 @command('tag',
5462 @command('tag',
5461 [('f', 'force', None, _('force tag')),
5463 [('f', 'force', None, _('force tag')),
5462 ('l', 'local', None, _('make the tag local')),
5464 ('l', 'local', None, _('make the tag local')),
5463 ('r', 'rev', '', _('revision to tag'), _('REV')),
5465 ('r', 'rev', '', _('revision to tag'), _('REV')),
5464 ('', 'remove', None, _('remove a tag')),
5466 ('', 'remove', None, _('remove a tag')),
5465 # -l/--local is already there, commitopts cannot be used
5467 # -l/--local is already there, commitopts cannot be used
5466 ('e', 'edit', None, _('edit commit message')),
5468 ('e', 'edit', None, _('edit commit message')),
5467 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5469 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5468 ] + commitopts2,
5470 ] + commitopts2,
5469 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5471 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5470 def tag(ui, repo, name1, *names, **opts):
5472 def tag(ui, repo, name1, *names, **opts):
5471 """add one or more tags for the current or given revision
5473 """add one or more tags for the current or given revision
5472
5474
5473 Name a particular revision using <name>.
5475 Name a particular revision using <name>.
5474
5476
5475 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
5476 very useful to compare different revisions, to go back to significant
5478 very useful to compare different revisions, to go back to significant
5477 earlier versions or to mark branch points as releases, etc. Changing
5479 earlier versions or to mark branch points as releases, etc. Changing
5478 an existing tag is normally disallowed; use -f/--force to override.
5480 an existing tag is normally disallowed; use -f/--force to override.
5479
5481
5480 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
5481 used, or tip if no revision is checked out.
5483 used, or tip if no revision is checked out.
5482
5484
5483 To facilitate version control, distribution, and merging of tags,
5485 To facilitate version control, distribution, and merging of tags,
5484 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
5485 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
5486 also means that tagging creates a new commit. The file
5488 also means that tagging creates a new commit. The file
5487 ".hg/localtags" is used for local tags (not shared among
5489 ".hg/localtags" is used for local tags (not shared among
5488 repositories).
5490 repositories).
5489
5491
5490 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
5491 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
5492 -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
5493 changeset.
5495 changeset.
5494
5496
5495 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.
5496
5498
5497 Since tag names have priority over branch names during revision
5499 Since tag names have priority over branch names during revision
5498 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.
5499
5501
5500 Returns 0 on success.
5502 Returns 0 on success.
5501 """
5503 """
5502
5504
5503 rev_ = "."
5505 rev_ = "."
5504 names = [t.strip() for t in (name1,) + names]
5506 names = [t.strip() for t in (name1,) + names]
5505 if len(names) != len(set(names)):
5507 if len(names) != len(set(names)):
5506 raise util.Abort(_('tag names must be unique'))
5508 raise util.Abort(_('tag names must be unique'))
5507 for n in names:
5509 for n in names:
5508 if n in ['tip', '.', 'null']:
5510 if n in ['tip', '.', 'null']:
5509 raise util.Abort(_("the name '%s' is reserved") % n)
5511 raise util.Abort(_("the name '%s' is reserved") % n)
5510 if not n:
5512 if not n:
5511 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5513 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5512 if opts.get('rev') and opts.get('remove'):
5514 if opts.get('rev') and opts.get('remove'):
5513 raise util.Abort(_("--rev and --remove are incompatible"))
5515 raise util.Abort(_("--rev and --remove are incompatible"))
5514 if opts.get('rev'):
5516 if opts.get('rev'):
5515 rev_ = opts['rev']
5517 rev_ = opts['rev']
5516 message = opts.get('message')
5518 message = opts.get('message')
5517 if opts.get('remove'):
5519 if opts.get('remove'):
5518 expectedtype = opts.get('local') and 'local' or 'global'
5520 expectedtype = opts.get('local') and 'local' or 'global'
5519 for n in names:
5521 for n in names:
5520 if not repo.tagtype(n):
5522 if not repo.tagtype(n):
5521 raise util.Abort(_("tag '%s' does not exist") % n)
5523 raise util.Abort(_("tag '%s' does not exist") % n)
5522 if repo.tagtype(n) != expectedtype:
5524 if repo.tagtype(n) != expectedtype:
5523 if expectedtype == 'global':
5525 if expectedtype == 'global':
5524 raise util.Abort(_("tag '%s' is not a global tag") % n)
5526 raise util.Abort(_("tag '%s' is not a global tag") % n)
5525 else:
5527 else:
5526 raise util.Abort(_("tag '%s' is not a local tag") % n)
5528 raise util.Abort(_("tag '%s' is not a local tag") % n)
5527 rev_ = nullid
5529 rev_ = nullid
5528 if not message:
5530 if not message:
5529 # we don't translate commit messages
5531 # we don't translate commit messages
5530 message = 'Removed tag %s' % ', '.join(names)
5532 message = 'Removed tag %s' % ', '.join(names)
5531 elif not opts.get('force'):
5533 elif not opts.get('force'):
5532 for n in names:
5534 for n in names:
5533 if n in repo.tags():
5535 if n in repo.tags():
5534 raise util.Abort(_("tag '%s' already exists "
5536 raise util.Abort(_("tag '%s' already exists "
5535 "(use -f to force)") % n)
5537 "(use -f to force)") % n)
5536 if not opts.get('local'):
5538 if not opts.get('local'):
5537 p1, p2 = repo.dirstate.parents()
5539 p1, p2 = repo.dirstate.parents()
5538 if p2 != nullid:
5540 if p2 != nullid:
5539 raise util.Abort(_('uncommitted merge'))
5541 raise util.Abort(_('uncommitted merge'))
5540 bheads = repo.branchheads()
5542 bheads = repo.branchheads()
5541 if not opts.get('force') and bheads and p1 not in bheads:
5543 if not opts.get('force') and bheads and p1 not in bheads:
5542 raise util.Abort(_('not at a branch head (use -f to force)'))
5544 raise util.Abort(_('not at a branch head (use -f to force)'))
5543 r = scmutil.revsingle(repo, rev_).node()
5545 r = scmutil.revsingle(repo, rev_).node()
5544
5546
5545 if not message:
5547 if not message:
5546 # we don't translate commit messages
5548 # we don't translate commit messages
5547 message = ('Added tag %s for changeset %s' %
5549 message = ('Added tag %s for changeset %s' %
5548 (', '.join(names), short(r)))
5550 (', '.join(names), short(r)))
5549
5551
5550 date = opts.get('date')
5552 date = opts.get('date')
5551 if date:
5553 if date:
5552 date = util.parsedate(date)
5554 date = util.parsedate(date)
5553
5555
5554 if opts.get('edit'):
5556 if opts.get('edit'):
5555 message = ui.edit(message, ui.username())
5557 message = ui.edit(message, ui.username())
5556
5558
5557 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5559 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5558
5560
5559 @command('tags', [], '')
5561 @command('tags', [], '')
5560 def tags(ui, repo):
5562 def tags(ui, repo):
5561 """list repository tags
5563 """list repository tags
5562
5564
5563 This lists both regular and local tags. When the -v/--verbose
5565 This lists both regular and local tags. When the -v/--verbose
5564 switch is used, a third column "local" is printed for local tags.
5566 switch is used, a third column "local" is printed for local tags.
5565
5567
5566 Returns 0 on success.
5568 Returns 0 on success.
5567 """
5569 """
5568
5570
5569 hexfunc = ui.debugflag and hex or short
5571 hexfunc = ui.debugflag and hex or short
5570 tagtype = ""
5572 tagtype = ""
5571
5573
5572 for t, n in reversed(repo.tagslist()):
5574 for t, n in reversed(repo.tagslist()):
5573 if ui.quiet:
5575 if ui.quiet:
5574 ui.write("%s\n" % t, label='tags.normal')
5576 ui.write("%s\n" % t, label='tags.normal')
5575 continue
5577 continue
5576
5578
5577 hn = hexfunc(n)
5579 hn = hexfunc(n)
5578 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5580 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5579 rev = ui.label(r, 'log.changeset')
5581 rev = ui.label(r, 'log.changeset')
5580 spaces = " " * (30 - encoding.colwidth(t))
5582 spaces = " " * (30 - encoding.colwidth(t))
5581
5583
5582 tag = ui.label(t, 'tags.normal')
5584 tag = ui.label(t, 'tags.normal')
5583 if ui.verbose:
5585 if ui.verbose:
5584 if repo.tagtype(t) == 'local':
5586 if repo.tagtype(t) == 'local':
5585 tagtype = " local"
5587 tagtype = " local"
5586 tag = ui.label(t, 'tags.local')
5588 tag = ui.label(t, 'tags.local')
5587 else:
5589 else:
5588 tagtype = ""
5590 tagtype = ""
5589 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5591 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5590
5592
5591 @command('tip',
5593 @command('tip',
5592 [('p', 'patch', None, _('show patch')),
5594 [('p', 'patch', None, _('show patch')),
5593 ('g', 'git', None, _('use git extended diff format')),
5595 ('g', 'git', None, _('use git extended diff format')),
5594 ] + templateopts,
5596 ] + templateopts,
5595 _('[-p] [-g]'))
5597 _('[-p] [-g]'))
5596 def tip(ui, repo, **opts):
5598 def tip(ui, repo, **opts):
5597 """show the tip revision
5599 """show the tip revision
5598
5600
5599 The tip revision (usually just called the tip) is the changeset
5601 The tip revision (usually just called the tip) is the changeset
5600 most recently added to the repository (and therefore the most
5602 most recently added to the repository (and therefore the most
5601 recently changed head).
5603 recently changed head).
5602
5604
5603 If you have just made a commit, that commit will be the tip. If
5605 If you have just made a commit, that commit will be the tip. If
5604 you have just pulled changes from another repository, the tip of
5606 you have just pulled changes from another repository, the tip of
5605 that repository becomes the current tip. The "tip" tag is special
5607 that repository becomes the current tip. The "tip" tag is special
5606 and cannot be renamed or assigned to a different changeset.
5608 and cannot be renamed or assigned to a different changeset.
5607
5609
5608 Returns 0 on success.
5610 Returns 0 on success.
5609 """
5611 """
5610 displayer = cmdutil.show_changeset(ui, repo, opts)
5612 displayer = cmdutil.show_changeset(ui, repo, opts)
5611 displayer.show(repo[len(repo) - 1])
5613 displayer.show(repo[len(repo) - 1])
5612 displayer.close()
5614 displayer.close()
5613
5615
5614 @command('unbundle',
5616 @command('unbundle',
5615 [('u', 'update', None,
5617 [('u', 'update', None,
5616 _('update to new branch head if changesets were unbundled'))],
5618 _('update to new branch head if changesets were unbundled'))],
5617 _('[-u] FILE...'))
5619 _('[-u] FILE...'))
5618 def unbundle(ui, repo, fname1, *fnames, **opts):
5620 def unbundle(ui, repo, fname1, *fnames, **opts):
5619 """apply one or more changegroup files
5621 """apply one or more changegroup files
5620
5622
5621 Apply one or more compressed changegroup files generated by the
5623 Apply one or more compressed changegroup files generated by the
5622 bundle command.
5624 bundle command.
5623
5625
5624 Returns 0 on success, 1 if an update has unresolved files.
5626 Returns 0 on success, 1 if an update has unresolved files.
5625 """
5627 """
5626 fnames = (fname1,) + fnames
5628 fnames = (fname1,) + fnames
5627
5629
5628 lock = repo.lock()
5630 lock = repo.lock()
5629 wc = repo['.']
5631 wc = repo['.']
5630 try:
5632 try:
5631 for fname in fnames:
5633 for fname in fnames:
5632 f = url.open(ui, fname)
5634 f = url.open(ui, fname)
5633 gen = changegroup.readbundle(f, fname)
5635 gen = changegroup.readbundle(f, fname)
5634 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5636 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5635 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5637 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5636 finally:
5638 finally:
5637 lock.release()
5639 lock.release()
5638 return postincoming(ui, repo, modheads, opts.get('update'), None)
5640 return postincoming(ui, repo, modheads, opts.get('update'), None)
5639
5641
5640 @command('^update|up|checkout|co',
5642 @command('^update|up|checkout|co',
5641 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5643 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5642 ('c', 'check', None,
5644 ('c', 'check', None,
5643 _('update across branches if no uncommitted changes')),
5645 _('update across branches if no uncommitted changes')),
5644 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5646 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5645 ('r', 'rev', '', _('revision'), _('REV'))],
5647 ('r', 'rev', '', _('revision'), _('REV'))],
5646 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5648 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5647 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5649 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5648 """update working directory (or switch revisions)
5650 """update working directory (or switch revisions)
5649
5651
5650 Update the repository's working directory to the specified
5652 Update the repository's working directory to the specified
5651 changeset. If no changeset is specified, update to the tip of the
5653 changeset. If no changeset is specified, update to the tip of the
5652 current named branch.
5654 current named branch.
5653
5655
5654 If the changeset is not a descendant of the working directory's
5656 If the changeset is not a descendant of the working directory's
5655 parent, the update is aborted. With the -c/--check option, the
5657 parent, the update is aborted. With the -c/--check option, the
5656 working directory is checked for uncommitted changes; if none are
5658 working directory is checked for uncommitted changes; if none are
5657 found, the working directory is updated to the specified
5659 found, the working directory is updated to the specified
5658 changeset.
5660 changeset.
5659
5661
5660 Update sets the working directory's parent revison to the specified
5662 Update sets the working directory's parent revison to the specified
5661 changeset (see :hg:`help parents`).
5663 changeset (see :hg:`help parents`).
5662
5664
5663 The following rules apply when the working directory contains
5665 The following rules apply when the working directory contains
5664 uncommitted changes:
5666 uncommitted changes:
5665
5667
5666 1. If neither -c/--check nor -C/--clean is specified, and if
5668 1. If neither -c/--check nor -C/--clean is specified, and if
5667 the requested changeset is an ancestor or descendant of
5669 the requested changeset is an ancestor or descendant of
5668 the working directory's parent, the uncommitted changes
5670 the working directory's parent, the uncommitted changes
5669 are merged into the requested changeset and the merged
5671 are merged into the requested changeset and the merged
5670 result is left uncommitted. If the requested changeset is
5672 result is left uncommitted. If the requested changeset is
5671 not an ancestor or descendant (that is, it is on another
5673 not an ancestor or descendant (that is, it is on another
5672 branch), the update is aborted and the uncommitted changes
5674 branch), the update is aborted and the uncommitted changes
5673 are preserved.
5675 are preserved.
5674
5676
5675 2. With the -c/--check option, the update is aborted and the
5677 2. With the -c/--check option, the update is aborted and the
5676 uncommitted changes are preserved.
5678 uncommitted changes are preserved.
5677
5679
5678 3. With the -C/--clean option, uncommitted changes are discarded and
5680 3. With the -C/--clean option, uncommitted changes are discarded and
5679 the working directory is updated to the requested changeset.
5681 the working directory is updated to the requested changeset.
5680
5682
5681 Use null as the changeset to remove the working directory (like
5683 Use null as the changeset to remove the working directory (like
5682 :hg:`clone -U`).
5684 :hg:`clone -U`).
5683
5685
5684 If you want to revert just one file to an older revision, use
5686 If you want to revert just one file to an older revision, use
5685 :hg:`revert [-r REV] NAME`.
5687 :hg:`revert [-r REV] NAME`.
5686
5688
5687 See :hg:`help dates` for a list of formats valid for -d/--date.
5689 See :hg:`help dates` for a list of formats valid for -d/--date.
5688
5690
5689 Returns 0 on success, 1 if there are unresolved files.
5691 Returns 0 on success, 1 if there are unresolved files.
5690 """
5692 """
5691 if rev and node:
5693 if rev and node:
5692 raise util.Abort(_("please specify just one revision"))
5694 raise util.Abort(_("please specify just one revision"))
5693
5695
5694 if rev is None or rev == '':
5696 if rev is None or rev == '':
5695 rev = node
5697 rev = node
5696
5698
5697 # if we defined a bookmark, we have to remember the original bookmark name
5699 # if we defined a bookmark, we have to remember the original bookmark name
5698 brev = rev
5700 brev = rev
5699 rev = scmutil.revsingle(repo, rev, rev).rev()
5701 rev = scmutil.revsingle(repo, rev, rev).rev()
5700
5702
5701 if check and clean:
5703 if check and clean:
5702 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5704 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5703
5705
5704 if check:
5706 if check:
5705 # we could use dirty() but we can ignore merge and branch trivia
5707 # we could use dirty() but we can ignore merge and branch trivia
5706 c = repo[None]
5708 c = repo[None]
5707 if c.modified() or c.added() or c.removed():
5709 if c.modified() or c.added() or c.removed():
5708 raise util.Abort(_("uncommitted local changes"))
5710 raise util.Abort(_("uncommitted local changes"))
5709
5711
5710 if date:
5712 if date:
5711 if rev is not None:
5713 if rev is not None:
5712 raise util.Abort(_("you can't specify a revision and a date"))
5714 raise util.Abort(_("you can't specify a revision and a date"))
5713 rev = cmdutil.finddate(ui, repo, date)
5715 rev = cmdutil.finddate(ui, repo, date)
5714
5716
5715 if clean or check:
5717 if clean or check:
5716 ret = hg.clean(repo, rev)
5718 ret = hg.clean(repo, rev)
5717 else:
5719 else:
5718 ret = hg.update(repo, rev)
5720 ret = hg.update(repo, rev)
5719
5721
5720 if brev in repo._bookmarks:
5722 if brev in repo._bookmarks:
5721 bookmarks.setcurrent(repo, brev)
5723 bookmarks.setcurrent(repo, brev)
5722
5724
5723 return ret
5725 return ret
5724
5726
5725 @command('verify', [])
5727 @command('verify', [])
5726 def verify(ui, repo):
5728 def verify(ui, repo):
5727 """verify the integrity of the repository
5729 """verify the integrity of the repository
5728
5730
5729 Verify the integrity of the current repository.
5731 Verify the integrity of the current repository.
5730
5732
5731 This will perform an extensive check of the repository's
5733 This will perform an extensive check of the repository's
5732 integrity, validating the hashes and checksums of each entry in
5734 integrity, validating the hashes and checksums of each entry in
5733 the changelog, manifest, and tracked files, as well as the
5735 the changelog, manifest, and tracked files, as well as the
5734 integrity of their crosslinks and indices.
5736 integrity of their crosslinks and indices.
5735
5737
5736 Returns 0 on success, 1 if errors are encountered.
5738 Returns 0 on success, 1 if errors are encountered.
5737 """
5739 """
5738 return hg.verify(repo)
5740 return hg.verify(repo)
5739
5741
5740 @command('version', [])
5742 @command('version', [])
5741 def version_(ui):
5743 def version_(ui):
5742 """output version and copyright information"""
5744 """output version and copyright information"""
5743 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5745 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5744 % util.version())
5746 % util.version())
5745 ui.status(_(
5747 ui.status(_(
5746 "(see http://mercurial.selenic.com for more information)\n"
5748 "(see http://mercurial.selenic.com for more information)\n"
5747 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5749 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5748 "This is free software; see the source for copying conditions. "
5750 "This is free software; see the source for copying conditions. "
5749 "There is NO\nwarranty; "
5751 "There is NO\nwarranty; "
5750 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5752 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5751 ))
5753 ))
5752
5754
5753 norepo = ("clone init version help debugcommands debugcomplete"
5755 norepo = ("clone init version help debugcommands debugcomplete"
5754 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5756 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5755 " debugknown debuggetbundle debugbundle")
5757 " debugknown debuggetbundle debugbundle")
5756 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5758 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5757 " debugdata debugindex debugindexdot debugrevlog")
5759 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now