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