##// END OF EJS Templates
merge with stable
Matt Mackall -
r15717:9cf1620e merge default
parent child Browse files
Show More
@@ -1,5706 +1,5706 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
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ] + templateopts
101 ] + templateopts
102
102
103 diffopts = [
103 diffopts = [
104 ('a', 'text', None, _('treat all files as text')),
104 ('a', 'text', None, _('treat all files as text')),
105 ('g', 'git', None, _('use git extended diff format')),
105 ('g', 'git', None, _('use git extended diff format')),
106 ('', 'nodates', None, _('omit dates from diff headers'))
106 ('', 'nodates', None, _('omit dates from diff headers'))
107 ]
107 ]
108
108
109 diffwsopts = [
109 diffwsopts = [
110 ('w', 'ignore-all-space', None,
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
115 _('ignore changes whose lines are all blank')),
116 ]
116 ]
117
117
118 diffopts2 = [
118 diffopts2 = [
119 ('p', 'show-function', None, _('show which function each change is in')),
119 ('p', 'show-function', None, _('show which function each change is in')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ] + diffwsopts + [
121 ] + diffwsopts + [
122 ('U', 'unified', '',
122 ('U', 'unified', '',
123 _('number of lines of context to show'), _('NUM')),
123 _('number of lines of context to show'), _('NUM')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ]
125 ]
126
126
127 mergetoolopts = [
127 mergetoolopts = [
128 ('t', 'tool', '', _('specify merge tool')),
128 ('t', 'tool', '', _('specify merge tool')),
129 ]
129 ]
130
130
131 similarityopts = [
131 similarityopts = [
132 ('s', 'similarity', '',
132 ('s', 'similarity', '',
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 ]
134 ]
135
135
136 subrepoopts = [
136 subrepoopts = [
137 ('S', 'subrepos', None,
137 ('S', 'subrepos', None,
138 _('recurse into subrepositories'))
138 _('recurse into subrepositories'))
139 ]
139 ]
140
140
141 # Commands start here, listed alphabetically
141 # Commands start here, listed alphabetically
142
142
143 @command('^add',
143 @command('^add',
144 walkopts + subrepoopts + dryrunopts,
144 walkopts + subrepoopts + dryrunopts,
145 _('[OPTION]... [FILE]...'))
145 _('[OPTION]... [FILE]...'))
146 def add(ui, repo, *pats, **opts):
146 def add(ui, repo, *pats, **opts):
147 """add the specified files on the next commit
147 """add the specified files on the next commit
148
148
149 Schedule files to be version controlled and added to the
149 Schedule files to be version controlled and added to the
150 repository.
150 repository.
151
151
152 The files will be added to the repository at the next commit. To
152 The files will be added to the repository at the next commit. To
153 undo an add before that, see :hg:`forget`.
153 undo an add before that, see :hg:`forget`.
154
154
155 If no names are given, add all files to the repository.
155 If no names are given, add all files to the repository.
156
156
157 .. container:: verbose
157 .. container:: verbose
158
158
159 An example showing how new (unknown) files are added
159 An example showing how new (unknown) files are added
160 automatically by :hg:`add`::
160 automatically by :hg:`add`::
161
161
162 $ ls
162 $ ls
163 foo.c
163 foo.c
164 $ hg status
164 $ hg status
165 ? foo.c
165 ? foo.c
166 $ hg add
166 $ hg add
167 adding foo.c
167 adding foo.c
168 $ hg status
168 $ hg status
169 A foo.c
169 A foo.c
170
170
171 Returns 0 if all files are successfully added.
171 Returns 0 if all files are successfully added.
172 """
172 """
173
173
174 m = scmutil.match(repo[None], pats, opts)
174 m = scmutil.match(repo[None], pats, opts)
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 opts.get('subrepos'), prefix="")
176 opts.get('subrepos'), prefix="")
177 return rejected and 1 or 0
177 return rejected and 1 or 0
178
178
179 @command('addremove',
179 @command('addremove',
180 similarityopts + walkopts + dryrunopts,
180 similarityopts + walkopts + dryrunopts,
181 _('[OPTION]... [FILE]...'))
181 _('[OPTION]... [FILE]...'))
182 def addremove(ui, repo, *pats, **opts):
182 def addremove(ui, repo, *pats, **opts):
183 """add all new files, delete all missing files
183 """add all new files, delete all missing files
184
184
185 Add all new files and remove all missing files from the
185 Add all new files and remove all missing files from the
186 repository.
186 repository.
187
187
188 New files are ignored if they match any of the patterns in
188 New files are ignored if they match any of the patterns in
189 ``.hgignore``. As with add, these changes take effect at the next
189 ``.hgignore``. As with add, these changes take effect at the next
190 commit.
190 commit.
191
191
192 Use the -s/--similarity option to detect renamed files. With a
192 Use the -s/--similarity option to detect renamed files. With a
193 parameter greater than 0, this compares every removed file with
193 parameter greater than 0, this compares every removed file with
194 every added file and records those similar enough as renames. This
194 every added file and records those similar enough as renames. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. Detecting renamed files this way
196 be identical) as its parameter. Detecting renamed files this way
197 can be expensive. After using this option, :hg:`status -C` can be
197 can be expensive. After using this option, :hg:`status -C` can be
198 used to check which files were identified as moved or renamed.
198 used to check which files were identified as moved or renamed.
199
199
200 Returns 0 if all files are successfully added.
200 Returns 0 if all files are successfully added.
201 """
201 """
202 try:
202 try:
203 sim = float(opts.get('similarity') or 100)
203 sim = float(opts.get('similarity') or 100)
204 except ValueError:
204 except ValueError:
205 raise util.Abort(_('similarity must be a number'))
205 raise util.Abort(_('similarity must be a number'))
206 if sim < 0 or sim > 100:
206 if sim < 0 or sim > 100:
207 raise util.Abort(_('similarity must be between 0 and 100'))
207 raise util.Abort(_('similarity must be between 0 and 100'))
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
209
209
210 @command('^annotate|blame',
210 @command('^annotate|blame',
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
212 ('', 'follow', None,
212 ('', 'follow', None,
213 _('follow copies/renames and list the filename (DEPRECATED)')),
213 _('follow copies/renames and list the filename (DEPRECATED)')),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
215 ('a', 'text', None, _('treat all files as text')),
215 ('a', 'text', None, _('treat all files as text')),
216 ('u', 'user', None, _('list the author (long with -v)')),
216 ('u', 'user', None, _('list the author (long with -v)')),
217 ('f', 'file', None, _('list the filename')),
217 ('f', 'file', None, _('list the filename')),
218 ('d', 'date', None, _('list the date (short with -q)')),
218 ('d', 'date', None, _('list the date (short with -q)')),
219 ('n', 'number', None, _('list the revision number (default)')),
219 ('n', 'number', None, _('list the revision number (default)')),
220 ('c', 'changeset', None, _('list the changeset')),
220 ('c', 'changeset', None, _('list the changeset')),
221 ('l', 'line-number', None, _('show line number at the first appearance'))
221 ('l', 'line-number', None, _('show line number at the first appearance'))
222 ] + diffwsopts + walkopts,
222 ] + diffwsopts + walkopts,
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
224 def annotate(ui, repo, *pats, **opts):
224 def annotate(ui, repo, *pats, **opts):
225 """show changeset information by line for each file
225 """show changeset information by line for each file
226
226
227 List changes in files, showing the revision id responsible for
227 List changes in files, showing the revision id responsible for
228 each line
228 each line
229
229
230 This command is useful for discovering when a change was made and
230 This command is useful for discovering when a change was made and
231 by whom.
231 by whom.
232
232
233 Without the -a/--text option, annotate will avoid processing files
233 Without the -a/--text option, annotate will avoid processing files
234 it detects as binary. With -a, annotate will annotate the file
234 it detects as binary. With -a, annotate will annotate the file
235 anyway, although the results will probably be neither useful
235 anyway, although the results will probably be neither useful
236 nor desirable.
236 nor desirable.
237
237
238 Returns 0 on success.
238 Returns 0 on success.
239 """
239 """
240 if opts.get('follow'):
240 if opts.get('follow'):
241 # --follow is deprecated and now just an alias for -f/--file
241 # --follow is deprecated and now just an alias for -f/--file
242 # to mimic the behavior of Mercurial before version 1.5
242 # to mimic the behavior of Mercurial before version 1.5
243 opts['file'] = True
243 opts['file'] = True
244
244
245 datefunc = ui.quiet and util.shortdate or util.datestr
245 datefunc = ui.quiet and util.shortdate or util.datestr
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
247
247
248 if not pats:
248 if not pats:
249 raise util.Abort(_('at least one filename or pattern is required'))
249 raise util.Abort(_('at least one filename or pattern is required'))
250
250
251 hexfn = ui.debugflag and hex or short
251 hexfn = ui.debugflag and hex or short
252
252
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
254 ('number', ' ', lambda x: str(x[0].rev())),
254 ('number', ' ', lambda x: str(x[0].rev())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
256 ('date', ' ', getdate),
256 ('date', ' ', getdate),
257 ('file', ' ', lambda x: x[0].path()),
257 ('file', ' ', lambda x: x[0].path()),
258 ('line_number', ':', lambda x: str(x[1])),
258 ('line_number', ':', lambda x: str(x[1])),
259 ]
259 ]
260
260
261 if (not opts.get('user') and not opts.get('changeset')
261 if (not opts.get('user') and not opts.get('changeset')
262 and not opts.get('date') and not opts.get('file')):
262 and not opts.get('date') and not opts.get('file')):
263 opts['number'] = True
263 opts['number'] = True
264
264
265 linenumber = opts.get('line_number') is not None
265 linenumber = opts.get('line_number') is not None
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
268
268
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
271
271
272 def bad(x, y):
272 def bad(x, y):
273 raise util.Abort("%s: %s" % (x, y))
273 raise util.Abort("%s: %s" % (x, y))
274
274
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
276 m = scmutil.match(ctx, pats, opts)
276 m = scmutil.match(ctx, pats, opts)
277 m.bad = bad
277 m.bad = bad
278 follow = not opts.get('no_follow')
278 follow = not opts.get('no_follow')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
280 for abs in ctx.walk(m):
280 for abs in ctx.walk(m):
281 fctx = ctx[abs]
281 fctx = ctx[abs]
282 if not opts.get('text') and util.binary(fctx.data()):
282 if not opts.get('text') and util.binary(fctx.data()):
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
284 continue
284 continue
285
285
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
287 diffopts=diffopts)
287 diffopts=diffopts)
288 pieces = []
288 pieces = []
289
289
290 for f, sep in funcmap:
290 for f, sep in funcmap:
291 l = [f(n) for n, dummy in lines]
291 l = [f(n) for n, dummy in lines]
292 if l:
292 if l:
293 sized = [(x, encoding.colwidth(x)) for x in l]
293 sized = [(x, encoding.colwidth(x)) for x in l]
294 ml = max([w for x, w in sized])
294 ml = max([w for x, w in sized])
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
296 for x, w in sized])
296 for x, w in sized])
297
297
298 if pieces:
298 if pieces:
299 for p, l in zip(zip(*pieces), lines):
299 for p, l in zip(zip(*pieces), lines):
300 ui.write("%s: %s" % ("".join(p), l[1]))
300 ui.write("%s: %s" % ("".join(p), l[1]))
301
301
302 @command('archive',
302 @command('archive',
303 [('', 'no-decode', None, _('do not pass files through decoders')),
303 [('', 'no-decode', None, _('do not pass files through decoders')),
304 ('p', 'prefix', '', _('directory prefix for files in archive'),
304 ('p', 'prefix', '', _('directory prefix for files in archive'),
305 _('PREFIX')),
305 _('PREFIX')),
306 ('r', 'rev', '', _('revision to distribute'), _('REV')),
306 ('r', 'rev', '', _('revision to distribute'), _('REV')),
307 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
307 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
308 ] + subrepoopts + walkopts,
308 ] + subrepoopts + walkopts,
309 _('[OPTION]... DEST'))
309 _('[OPTION]... DEST'))
310 def archive(ui, repo, dest, **opts):
310 def archive(ui, repo, dest, **opts):
311 '''create an unversioned archive of a repository revision
311 '''create an unversioned archive of a repository revision
312
312
313 By default, the revision used is the parent of the working
313 By default, the revision used is the parent of the working
314 directory; use -r/--rev to specify a different revision.
314 directory; use -r/--rev to specify a different revision.
315
315
316 The archive type is automatically detected based on file
316 The archive type is automatically detected based on file
317 extension (or override using -t/--type).
317 extension (or override using -t/--type).
318
318
319 .. container:: verbose
319 .. container:: verbose
320
320
321 Examples:
321 Examples:
322
322
323 - create a zip file containing the 1.0 release::
323 - create a zip file containing the 1.0 release::
324
324
325 hg archive -r 1.0 project-1.0.zip
325 hg archive -r 1.0 project-1.0.zip
326
326
327 - create a tarball excluding .hg files::
327 - create a tarball excluding .hg files::
328
328
329 hg archive project.tar.gz -X ".hg*"
329 hg archive project.tar.gz -X ".hg*"
330
330
331 Valid types are:
331 Valid types are:
332
332
333 :``files``: a directory full of files (default)
333 :``files``: a directory full of files (default)
334 :``tar``: tar archive, uncompressed
334 :``tar``: tar archive, uncompressed
335 :``tbz2``: tar archive, compressed using bzip2
335 :``tbz2``: tar archive, compressed using bzip2
336 :``tgz``: tar archive, compressed using gzip
336 :``tgz``: tar archive, compressed using gzip
337 :``uzip``: zip archive, uncompressed
337 :``uzip``: zip archive, uncompressed
338 :``zip``: zip archive, compressed using deflate
338 :``zip``: zip archive, compressed using deflate
339
339
340 The exact name of the destination archive or directory is given
340 The exact name of the destination archive or directory is given
341 using a format string; see :hg:`help export` for details.
341 using a format string; see :hg:`help export` for details.
342
342
343 Each member added to an archive file has a directory prefix
343 Each member added to an archive file has a directory prefix
344 prepended. Use -p/--prefix to specify a format string for the
344 prepended. Use -p/--prefix to specify a format string for the
345 prefix. The default is the basename of the archive, with suffixes
345 prefix. The default is the basename of the archive, with suffixes
346 removed.
346 removed.
347
347
348 Returns 0 on success.
348 Returns 0 on success.
349 '''
349 '''
350
350
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
352 if not ctx:
352 if not ctx:
353 raise util.Abort(_('no working directory: please specify a revision'))
353 raise util.Abort(_('no working directory: please specify a revision'))
354 node = ctx.node()
354 node = ctx.node()
355 dest = cmdutil.makefilename(repo, dest, node)
355 dest = cmdutil.makefilename(repo, dest, node)
356 if os.path.realpath(dest) == repo.root:
356 if os.path.realpath(dest) == repo.root:
357 raise util.Abort(_('repository root cannot be destination'))
357 raise util.Abort(_('repository root cannot be destination'))
358
358
359 kind = opts.get('type') or archival.guesskind(dest) or 'files'
359 kind = opts.get('type') or archival.guesskind(dest) or 'files'
360 prefix = opts.get('prefix')
360 prefix = opts.get('prefix')
361
361
362 if dest == '-':
362 if dest == '-':
363 if kind == 'files':
363 if kind == 'files':
364 raise util.Abort(_('cannot archive plain files to stdout'))
364 raise util.Abort(_('cannot archive plain files to stdout'))
365 dest = cmdutil.makefileobj(repo, dest)
365 dest = cmdutil.makefileobj(repo, dest)
366 if not prefix:
366 if not prefix:
367 prefix = os.path.basename(repo.root) + '-%h'
367 prefix = os.path.basename(repo.root) + '-%h'
368
368
369 prefix = cmdutil.makefilename(repo, prefix, node)
369 prefix = cmdutil.makefilename(repo, prefix, node)
370 matchfn = scmutil.match(ctx, [], opts)
370 matchfn = scmutil.match(ctx, [], opts)
371 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
371 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
372 matchfn, prefix, subrepos=opts.get('subrepos'))
372 matchfn, prefix, subrepos=opts.get('subrepos'))
373
373
374 @command('backout',
374 @command('backout',
375 [('', 'merge', None, _('merge with old dirstate parent after backout')),
375 [('', 'merge', None, _('merge with old dirstate parent after backout')),
376 ('', 'parent', '',
376 ('', 'parent', '',
377 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
377 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
378 ('r', 'rev', '', _('revision to backout'), _('REV')),
378 ('r', 'rev', '', _('revision to backout'), _('REV')),
379 ] + mergetoolopts + walkopts + commitopts + commitopts2,
379 ] + mergetoolopts + walkopts + commitopts + commitopts2,
380 _('[OPTION]... [-r] REV'))
380 _('[OPTION]... [-r] REV'))
381 def backout(ui, repo, node=None, rev=None, **opts):
381 def backout(ui, repo, node=None, rev=None, **opts):
382 '''reverse effect of earlier changeset
382 '''reverse effect of earlier changeset
383
383
384 Prepare a new changeset with the effect of REV undone in the
384 Prepare a new changeset with the effect of REV undone in the
385 current working directory.
385 current working directory.
386
386
387 If REV is the parent of the working directory, then this new changeset
387 If REV is the parent of the working directory, then this new changeset
388 is committed automatically. Otherwise, hg needs to merge the
388 is committed automatically. Otherwise, hg needs to merge the
389 changes and the merged result is left uncommitted.
389 changes and the merged result is left uncommitted.
390
390
391 .. note::
391 .. note::
392 backout cannot be used to fix either an unwanted or
392 backout cannot be used to fix either an unwanted or
393 incorrect merge.
393 incorrect merge.
394
394
395 .. container:: verbose
395 .. container:: verbose
396
396
397 By default, the pending changeset will have one parent,
397 By default, the pending changeset will have one parent,
398 maintaining a linear history. With --merge, the pending
398 maintaining a linear history. With --merge, the pending
399 changeset will instead have two parents: the old parent of the
399 changeset will instead have two parents: the old parent of the
400 working directory and a new child of REV that simply undoes REV.
400 working directory and a new child of REV that simply undoes REV.
401
401
402 Before version 1.7, the behavior without --merge was equivalent
402 Before version 1.7, the behavior without --merge was equivalent
403 to specifying --merge followed by :hg:`update --clean .` to
403 to specifying --merge followed by :hg:`update --clean .` to
404 cancel the merge and leave the child of REV as a head to be
404 cancel the merge and leave the child of REV as a head to be
405 merged separately.
405 merged separately.
406
406
407 See :hg:`help dates` for a list of formats valid for -d/--date.
407 See :hg:`help dates` for a list of formats valid for -d/--date.
408
408
409 Returns 0 on success.
409 Returns 0 on success.
410 '''
410 '''
411 if rev and node:
411 if rev and node:
412 raise util.Abort(_("please specify just one revision"))
412 raise util.Abort(_("please specify just one revision"))
413
413
414 if not rev:
414 if not rev:
415 rev = node
415 rev = node
416
416
417 if not rev:
417 if not rev:
418 raise util.Abort(_("please specify a revision to backout"))
418 raise util.Abort(_("please specify a revision to backout"))
419
419
420 date = opts.get('date')
420 date = opts.get('date')
421 if date:
421 if date:
422 opts['date'] = util.parsedate(date)
422 opts['date'] = util.parsedate(date)
423
423
424 cmdutil.bailifchanged(repo)
424 cmdutil.bailifchanged(repo)
425 node = scmutil.revsingle(repo, rev).node()
425 node = scmutil.revsingle(repo, rev).node()
426
426
427 op1, op2 = repo.dirstate.parents()
427 op1, op2 = repo.dirstate.parents()
428 a = repo.changelog.ancestor(op1, node)
428 a = repo.changelog.ancestor(op1, node)
429 if a != node:
429 if a != node:
430 raise util.Abort(_('cannot backout change on a different branch'))
430 raise util.Abort(_('cannot backout change on a different branch'))
431
431
432 p1, p2 = repo.changelog.parents(node)
432 p1, p2 = repo.changelog.parents(node)
433 if p1 == nullid:
433 if p1 == nullid:
434 raise util.Abort(_('cannot backout a change with no parents'))
434 raise util.Abort(_('cannot backout a change with no parents'))
435 if p2 != nullid:
435 if p2 != nullid:
436 if not opts.get('parent'):
436 if not opts.get('parent'):
437 raise util.Abort(_('cannot backout a merge changeset'))
437 raise util.Abort(_('cannot backout a merge changeset'))
438 p = repo.lookup(opts['parent'])
438 p = repo.lookup(opts['parent'])
439 if p not in (p1, p2):
439 if p not in (p1, p2):
440 raise util.Abort(_('%s is not a parent of %s') %
440 raise util.Abort(_('%s is not a parent of %s') %
441 (short(p), short(node)))
441 (short(p), short(node)))
442 parent = p
442 parent = p
443 else:
443 else:
444 if opts.get('parent'):
444 if opts.get('parent'):
445 raise util.Abort(_('cannot use --parent on non-merge changeset'))
445 raise util.Abort(_('cannot use --parent on non-merge changeset'))
446 parent = p1
446 parent = p1
447
447
448 # the backout should appear on the same branch
448 # the backout should appear on the same branch
449 branch = repo.dirstate.branch()
449 branch = repo.dirstate.branch()
450 hg.clean(repo, node, show_stats=False)
450 hg.clean(repo, node, show_stats=False)
451 repo.dirstate.setbranch(branch)
451 repo.dirstate.setbranch(branch)
452 revert_opts = opts.copy()
452 revert_opts = opts.copy()
453 revert_opts['date'] = None
453 revert_opts['date'] = None
454 revert_opts['all'] = True
454 revert_opts['all'] = True
455 revert_opts['rev'] = hex(parent)
455 revert_opts['rev'] = hex(parent)
456 revert_opts['no_backup'] = None
456 revert_opts['no_backup'] = None
457 revert(ui, repo, **revert_opts)
457 revert(ui, repo, **revert_opts)
458 if not opts.get('merge') and op1 != node:
458 if not opts.get('merge') and op1 != node:
459 try:
459 try:
460 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
460 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
461 return hg.update(repo, op1)
461 return hg.update(repo, op1)
462 finally:
462 finally:
463 ui.setconfig('ui', 'forcemerge', '')
463 ui.setconfig('ui', 'forcemerge', '')
464
464
465 commit_opts = opts.copy()
465 commit_opts = opts.copy()
466 commit_opts['addremove'] = False
466 commit_opts['addremove'] = False
467 if not commit_opts['message'] and not commit_opts['logfile']:
467 if not commit_opts['message'] and not commit_opts['logfile']:
468 # we don't translate commit messages
468 # we don't translate commit messages
469 commit_opts['message'] = "Backed out changeset %s" % short(node)
469 commit_opts['message'] = "Backed out changeset %s" % short(node)
470 commit_opts['force_editor'] = True
470 commit_opts['force_editor'] = True
471 commit(ui, repo, **commit_opts)
471 commit(ui, repo, **commit_opts)
472 def nice(node):
472 def nice(node):
473 return '%d:%s' % (repo.changelog.rev(node), short(node))
473 return '%d:%s' % (repo.changelog.rev(node), short(node))
474 ui.status(_('changeset %s backs out changeset %s\n') %
474 ui.status(_('changeset %s backs out changeset %s\n') %
475 (nice(repo.changelog.tip()), nice(node)))
475 (nice(repo.changelog.tip()), nice(node)))
476 if opts.get('merge') and op1 != node:
476 if opts.get('merge') and op1 != node:
477 hg.clean(repo, op1, show_stats=False)
477 hg.clean(repo, op1, show_stats=False)
478 ui.status(_('merging with changeset %s\n')
478 ui.status(_('merging with changeset %s\n')
479 % nice(repo.changelog.tip()))
479 % nice(repo.changelog.tip()))
480 try:
480 try:
481 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
481 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
482 return hg.merge(repo, hex(repo.changelog.tip()))
482 return hg.merge(repo, hex(repo.changelog.tip()))
483 finally:
483 finally:
484 ui.setconfig('ui', 'forcemerge', '')
484 ui.setconfig('ui', 'forcemerge', '')
485 return 0
485 return 0
486
486
487 @command('bisect',
487 @command('bisect',
488 [('r', 'reset', False, _('reset bisect state')),
488 [('r', 'reset', False, _('reset bisect state')),
489 ('g', 'good', False, _('mark changeset good')),
489 ('g', 'good', False, _('mark changeset good')),
490 ('b', 'bad', False, _('mark changeset bad')),
490 ('b', 'bad', False, _('mark changeset bad')),
491 ('s', 'skip', False, _('skip testing changeset')),
491 ('s', 'skip', False, _('skip testing changeset')),
492 ('e', 'extend', False, _('extend the bisect range')),
492 ('e', 'extend', False, _('extend the bisect range')),
493 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
493 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
494 ('U', 'noupdate', False, _('do not update to target'))],
494 ('U', 'noupdate', False, _('do not update to target'))],
495 _("[-gbsr] [-U] [-c CMD] [REV]"))
495 _("[-gbsr] [-U] [-c CMD] [REV]"))
496 def bisect(ui, repo, rev=None, extra=None, command=None,
496 def bisect(ui, repo, rev=None, extra=None, command=None,
497 reset=None, good=None, bad=None, skip=None, extend=None,
497 reset=None, good=None, bad=None, skip=None, extend=None,
498 noupdate=None):
498 noupdate=None):
499 """subdivision search of changesets
499 """subdivision search of changesets
500
500
501 This command helps to find changesets which introduce problems. To
501 This command helps to find changesets which introduce problems. To
502 use, mark the earliest changeset you know exhibits the problem as
502 use, mark the earliest changeset you know exhibits the problem as
503 bad, then mark the latest changeset which is free from the problem
503 bad, then mark the latest changeset which is free from the problem
504 as good. Bisect will update your working directory to a revision
504 as good. Bisect will update your working directory to a revision
505 for testing (unless the -U/--noupdate option is specified). Once
505 for testing (unless the -U/--noupdate option is specified). Once
506 you have performed tests, mark the working directory as good or
506 you have performed tests, mark the working directory as good or
507 bad, and bisect will either update to another candidate changeset
507 bad, and bisect will either update to another candidate changeset
508 or announce that it has found the bad revision.
508 or announce that it has found the bad revision.
509
509
510 As a shortcut, you can also use the revision argument to mark a
510 As a shortcut, you can also use the revision argument to mark a
511 revision as good or bad without checking it out first.
511 revision as good or bad without checking it out first.
512
512
513 If you supply a command, it will be used for automatic bisection.
513 If you supply a command, it will be used for automatic bisection.
514 Its exit status will be used to mark revisions as good or bad:
514 Its exit status will be used to mark revisions as good or bad:
515 status 0 means good, 125 means to skip the revision, 127
515 status 0 means good, 125 means to skip the revision, 127
516 (command not found) will abort the bisection, and any other
516 (command not found) will abort the bisection, and any other
517 non-zero exit status means the revision is bad.
517 non-zero exit status means the revision is bad.
518
518
519 .. container:: verbose
519 .. container:: verbose
520
520
521 Some examples:
521 Some examples:
522
522
523 - start a bisection with known bad revision 12, and good revision 34::
523 - start a bisection with known bad revision 12, and good revision 34::
524
524
525 hg bisect --bad 34
525 hg bisect --bad 34
526 hg bisect --good 12
526 hg bisect --good 12
527
527
528 - advance the current bisection by marking current revision as good or
528 - advance the current bisection by marking current revision as good or
529 bad::
529 bad::
530
530
531 hg bisect --good
531 hg bisect --good
532 hg bisect --bad
532 hg bisect --bad
533
533
534 - mark the current revision, or a known revision, to be skipped (eg. if
534 - mark the current revision, or a known revision, to be skipped (eg. if
535 that revision is not usable because of another issue)::
535 that revision is not usable because of another issue)::
536
536
537 hg bisect --skip
537 hg bisect --skip
538 hg bisect --skip 23
538 hg bisect --skip 23
539
539
540 - forget the current bisection::
540 - forget the current bisection::
541
541
542 hg bisect --reset
542 hg bisect --reset
543
543
544 - use 'make && make tests' to automatically find the first broken
544 - use 'make && make tests' to automatically find the first broken
545 revision::
545 revision::
546
546
547 hg bisect --reset
547 hg bisect --reset
548 hg bisect --bad 34
548 hg bisect --bad 34
549 hg bisect --good 12
549 hg bisect --good 12
550 hg bisect --command 'make && make tests'
550 hg bisect --command 'make && make tests'
551
551
552 - see all changesets whose states are already known in the current
552 - see all changesets whose states are already known in the current
553 bisection::
553 bisection::
554
554
555 hg log -r "bisect(pruned)"
555 hg log -r "bisect(pruned)"
556
556
557 - see all changesets that took part in the current bisection::
557 - see all changesets that took part in the current bisection::
558
558
559 hg log -r "bisect(range)"
559 hg log -r "bisect(range)"
560
560
561 - with the graphlog extension, you can even get a nice graph::
561 - with the graphlog extension, you can even get a nice graph::
562
562
563 hg log --graph -r "bisect(range)"
563 hg log --graph -r "bisect(range)"
564
564
565 See :hg:`help revsets` for more about the `bisect()` keyword.
565 See :hg:`help revsets` for more about the `bisect()` keyword.
566
566
567 Returns 0 on success.
567 Returns 0 on success.
568 """
568 """
569 def extendbisectrange(nodes, good):
569 def extendbisectrange(nodes, good):
570 # bisect is incomplete when it ends on a merge node and
570 # bisect is incomplete when it ends on a merge node and
571 # one of the parent was not checked.
571 # one of the parent was not checked.
572 parents = repo[nodes[0]].parents()
572 parents = repo[nodes[0]].parents()
573 if len(parents) > 1:
573 if len(parents) > 1:
574 side = good and state['bad'] or state['good']
574 side = good and state['bad'] or state['good']
575 num = len(set(i.node() for i in parents) & set(side))
575 num = len(set(i.node() for i in parents) & set(side))
576 if num == 1:
576 if num == 1:
577 return parents[0].ancestor(parents[1])
577 return parents[0].ancestor(parents[1])
578 return None
578 return None
579
579
580 def print_result(nodes, good):
580 def print_result(nodes, good):
581 displayer = cmdutil.show_changeset(ui, repo, {})
581 displayer = cmdutil.show_changeset(ui, repo, {})
582 if len(nodes) == 1:
582 if len(nodes) == 1:
583 # narrowed it down to a single revision
583 # narrowed it down to a single revision
584 if good:
584 if good:
585 ui.write(_("The first good revision is:\n"))
585 ui.write(_("The first good revision is:\n"))
586 else:
586 else:
587 ui.write(_("The first bad revision is:\n"))
587 ui.write(_("The first bad revision is:\n"))
588 displayer.show(repo[nodes[0]])
588 displayer.show(repo[nodes[0]])
589 extendnode = extendbisectrange(nodes, good)
589 extendnode = extendbisectrange(nodes, good)
590 if extendnode is not None:
590 if extendnode is not None:
591 ui.write(_('Not all ancestors of this changeset have been'
591 ui.write(_('Not all ancestors of this changeset have been'
592 ' checked.\nUse bisect --extend to continue the '
592 ' checked.\nUse bisect --extend to continue the '
593 'bisection from\nthe common ancestor, %s.\n')
593 'bisection from\nthe common ancestor, %s.\n')
594 % extendnode)
594 % extendnode)
595 else:
595 else:
596 # multiple possible revisions
596 # multiple possible revisions
597 if good:
597 if good:
598 ui.write(_("Due to skipped revisions, the first "
598 ui.write(_("Due to skipped revisions, the first "
599 "good revision could be any of:\n"))
599 "good revision could be any of:\n"))
600 else:
600 else:
601 ui.write(_("Due to skipped revisions, the first "
601 ui.write(_("Due to skipped revisions, the first "
602 "bad revision could be any of:\n"))
602 "bad revision could be any of:\n"))
603 for n in nodes:
603 for n in nodes:
604 displayer.show(repo[n])
604 displayer.show(repo[n])
605 displayer.close()
605 displayer.close()
606
606
607 def check_state(state, interactive=True):
607 def check_state(state, interactive=True):
608 if not state['good'] or not state['bad']:
608 if not state['good'] or not state['bad']:
609 if (good or bad or skip or reset) and interactive:
609 if (good or bad or skip or reset) and interactive:
610 return
610 return
611 if not state['good']:
611 if not state['good']:
612 raise util.Abort(_('cannot bisect (no known good revisions)'))
612 raise util.Abort(_('cannot bisect (no known good revisions)'))
613 else:
613 else:
614 raise util.Abort(_('cannot bisect (no known bad revisions)'))
614 raise util.Abort(_('cannot bisect (no known bad revisions)'))
615 return True
615 return True
616
616
617 # backward compatibility
617 # backward compatibility
618 if rev in "good bad reset init".split():
618 if rev in "good bad reset init".split():
619 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
619 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
620 cmd, rev, extra = rev, extra, None
620 cmd, rev, extra = rev, extra, None
621 if cmd == "good":
621 if cmd == "good":
622 good = True
622 good = True
623 elif cmd == "bad":
623 elif cmd == "bad":
624 bad = True
624 bad = True
625 else:
625 else:
626 reset = True
626 reset = True
627 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
627 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
628 raise util.Abort(_('incompatible arguments'))
628 raise util.Abort(_('incompatible arguments'))
629
629
630 if reset:
630 if reset:
631 p = repo.join("bisect.state")
631 p = repo.join("bisect.state")
632 if os.path.exists(p):
632 if os.path.exists(p):
633 os.unlink(p)
633 os.unlink(p)
634 return
634 return
635
635
636 state = hbisect.load_state(repo)
636 state = hbisect.load_state(repo)
637
637
638 if command:
638 if command:
639 changesets = 1
639 changesets = 1
640 try:
640 try:
641 while changesets:
641 while changesets:
642 # update state
642 # update state
643 status = util.system(command, out=ui.fout)
643 status = util.system(command, out=ui.fout)
644 if status == 125:
644 if status == 125:
645 transition = "skip"
645 transition = "skip"
646 elif status == 0:
646 elif status == 0:
647 transition = "good"
647 transition = "good"
648 # status < 0 means process was killed
648 # status < 0 means process was killed
649 elif status == 127:
649 elif status == 127:
650 raise util.Abort(_("failed to execute %s") % command)
650 raise util.Abort(_("failed to execute %s") % command)
651 elif status < 0:
651 elif status < 0:
652 raise util.Abort(_("%s killed") % command)
652 raise util.Abort(_("%s killed") % command)
653 else:
653 else:
654 transition = "bad"
654 transition = "bad"
655 ctx = scmutil.revsingle(repo, rev)
655 ctx = scmutil.revsingle(repo, rev)
656 rev = None # clear for future iterations
656 rev = None # clear for future iterations
657 state[transition].append(ctx.node())
657 state[transition].append(ctx.node())
658 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
658 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
659 check_state(state, interactive=False)
659 check_state(state, interactive=False)
660 # bisect
660 # bisect
661 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
661 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
662 # update to next check
662 # update to next check
663 cmdutil.bailifchanged(repo)
663 cmdutil.bailifchanged(repo)
664 hg.clean(repo, nodes[0], show_stats=False)
664 hg.clean(repo, nodes[0], show_stats=False)
665 finally:
665 finally:
666 hbisect.save_state(repo, state)
666 hbisect.save_state(repo, state)
667 print_result(nodes, good)
667 print_result(nodes, good)
668 return
668 return
669
669
670 # update state
670 # update state
671
671
672 if rev:
672 if rev:
673 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
673 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
674 else:
674 else:
675 nodes = [repo.lookup('.')]
675 nodes = [repo.lookup('.')]
676
676
677 if good or bad or skip:
677 if good or bad or skip:
678 if good:
678 if good:
679 state['good'] += nodes
679 state['good'] += nodes
680 elif bad:
680 elif bad:
681 state['bad'] += nodes
681 state['bad'] += nodes
682 elif skip:
682 elif skip:
683 state['skip'] += nodes
683 state['skip'] += nodes
684 hbisect.save_state(repo, state)
684 hbisect.save_state(repo, state)
685
685
686 if not check_state(state):
686 if not check_state(state):
687 return
687 return
688
688
689 # actually bisect
689 # actually bisect
690 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
690 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
691 if extend:
691 if extend:
692 if not changesets:
692 if not changesets:
693 extendnode = extendbisectrange(nodes, good)
693 extendnode = extendbisectrange(nodes, good)
694 if extendnode is not None:
694 if extendnode is not None:
695 ui.write(_("Extending search to changeset %d:%s\n"
695 ui.write(_("Extending search to changeset %d:%s\n"
696 % (extendnode.rev(), extendnode)))
696 % (extendnode.rev(), extendnode)))
697 if noupdate:
697 if noupdate:
698 return
698 return
699 cmdutil.bailifchanged(repo)
699 cmdutil.bailifchanged(repo)
700 return hg.clean(repo, extendnode.node())
700 return hg.clean(repo, extendnode.node())
701 raise util.Abort(_("nothing to extend"))
701 raise util.Abort(_("nothing to extend"))
702
702
703 if changesets == 0:
703 if changesets == 0:
704 print_result(nodes, good)
704 print_result(nodes, good)
705 else:
705 else:
706 assert len(nodes) == 1 # only a single node can be tested next
706 assert len(nodes) == 1 # only a single node can be tested next
707 node = nodes[0]
707 node = nodes[0]
708 # compute the approximate number of remaining tests
708 # compute the approximate number of remaining tests
709 tests, size = 0, 2
709 tests, size = 0, 2
710 while size <= changesets:
710 while size <= changesets:
711 tests, size = tests + 1, size * 2
711 tests, size = tests + 1, size * 2
712 rev = repo.changelog.rev(node)
712 rev = repo.changelog.rev(node)
713 ui.write(_("Testing changeset %d:%s "
713 ui.write(_("Testing changeset %d:%s "
714 "(%d changesets remaining, ~%d tests)\n")
714 "(%d changesets remaining, ~%d tests)\n")
715 % (rev, short(node), changesets, tests))
715 % (rev, short(node), changesets, tests))
716 if not noupdate:
716 if not noupdate:
717 cmdutil.bailifchanged(repo)
717 cmdutil.bailifchanged(repo)
718 return hg.clean(repo, node)
718 return hg.clean(repo, node)
719
719
720 @command('bookmarks',
720 @command('bookmarks',
721 [('f', 'force', False, _('force')),
721 [('f', 'force', False, _('force')),
722 ('r', 'rev', '', _('revision'), _('REV')),
722 ('r', 'rev', '', _('revision'), _('REV')),
723 ('d', 'delete', False, _('delete a given bookmark')),
723 ('d', 'delete', False, _('delete a given bookmark')),
724 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
724 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
725 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
725 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
726 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
726 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
727 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
727 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
728 rename=None, inactive=False):
728 rename=None, inactive=False):
729 '''track a line of development with movable markers
729 '''track a line of development with movable markers
730
730
731 Bookmarks are pointers to certain commits that move when committing.
731 Bookmarks are pointers to certain commits that move when committing.
732 Bookmarks are local. They can be renamed, copied and deleted. It is
732 Bookmarks are local. They can be renamed, copied and deleted. It is
733 possible to use :hg:`merge NAME` to merge from a given bookmark, and
733 possible to use :hg:`merge NAME` to merge from a given bookmark, and
734 :hg:`update NAME` to update to a given bookmark.
734 :hg:`update NAME` to update to a given bookmark.
735
735
736 You can use :hg:`bookmark NAME` to set a bookmark on the working
736 You can use :hg:`bookmark NAME` to set a bookmark on the working
737 directory's parent revision with the given name. If you specify
737 directory's parent revision with the given name. If you specify
738 a revision using -r REV (where REV may be an existing bookmark),
738 a revision using -r REV (where REV may be an existing bookmark),
739 the bookmark is assigned to that revision.
739 the bookmark is assigned to that revision.
740
740
741 Bookmarks can be pushed and pulled between repositories (see :hg:`help
741 Bookmarks can be pushed and pulled between repositories (see :hg:`help
742 push` and :hg:`help pull`). This requires both the local and remote
742 push` and :hg:`help pull`). This requires both the local and remote
743 repositories to support bookmarks. For versions prior to 1.8, this means
743 repositories to support bookmarks. For versions prior to 1.8, this means
744 the bookmarks extension must be enabled.
744 the bookmarks extension must be enabled.
745 '''
745 '''
746 hexfn = ui.debugflag and hex or short
746 hexfn = ui.debugflag and hex or short
747 marks = repo._bookmarks
747 marks = repo._bookmarks
748 cur = repo.changectx('.').node()
748 cur = repo.changectx('.').node()
749
749
750 if delete:
750 if delete:
751 if mark is None:
751 if mark is None:
752 raise util.Abort(_("bookmark name required"))
752 raise util.Abort(_("bookmark name required"))
753 if mark not in marks:
753 if mark not in marks:
754 raise util.Abort(_("bookmark '%s' does not exist") % mark)
754 raise util.Abort(_("bookmark '%s' does not exist") % mark)
755 if mark == repo._bookmarkcurrent:
755 if mark == repo._bookmarkcurrent:
756 bookmarks.setcurrent(repo, None)
756 bookmarks.setcurrent(repo, None)
757 del marks[mark]
757 del marks[mark]
758 bookmarks.write(repo)
758 bookmarks.write(repo)
759 return
759 return
760
760
761 if rename:
761 if rename:
762 if rename not in marks:
762 if rename not in marks:
763 raise util.Abort(_("bookmark '%s' does not exist") % rename)
763 raise util.Abort(_("bookmark '%s' does not exist") % rename)
764 if mark in marks and not force:
764 if mark in marks and not force:
765 raise util.Abort(_("bookmark '%s' already exists "
765 raise util.Abort(_("bookmark '%s' already exists "
766 "(use -f to force)") % mark)
766 "(use -f to force)") % mark)
767 if mark is None:
767 if mark is None:
768 raise util.Abort(_("new bookmark name required"))
768 raise util.Abort(_("new bookmark name required"))
769 marks[mark] = marks[rename]
769 marks[mark] = marks[rename]
770 if repo._bookmarkcurrent == rename and not inactive:
770 if repo._bookmarkcurrent == rename and not inactive:
771 bookmarks.setcurrent(repo, mark)
771 bookmarks.setcurrent(repo, mark)
772 del marks[rename]
772 del marks[rename]
773 bookmarks.write(repo)
773 bookmarks.write(repo)
774 return
774 return
775
775
776 if mark is not None:
776 if mark is not None:
777 if "\n" in mark:
777 if "\n" in mark:
778 raise util.Abort(_("bookmark name cannot contain newlines"))
778 raise util.Abort(_("bookmark name cannot contain newlines"))
779 mark = mark.strip()
779 mark = mark.strip()
780 if not mark:
780 if not mark:
781 raise util.Abort(_("bookmark names cannot consist entirely of "
781 raise util.Abort(_("bookmark names cannot consist entirely of "
782 "whitespace"))
782 "whitespace"))
783 if inactive and mark == repo._bookmarkcurrent:
783 if inactive and mark == repo._bookmarkcurrent:
784 bookmarks.setcurrent(repo, None)
784 bookmarks.setcurrent(repo, None)
785 return
785 return
786 if mark in marks and not force:
786 if mark in marks and not force:
787 raise util.Abort(_("bookmark '%s' already exists "
787 raise util.Abort(_("bookmark '%s' already exists "
788 "(use -f to force)") % mark)
788 "(use -f to force)") % mark)
789 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
789 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
790 and not force):
790 and not force):
791 raise util.Abort(
791 raise util.Abort(
792 _("a bookmark cannot have the name of an existing branch"))
792 _("a bookmark cannot have the name of an existing branch"))
793 if rev:
793 if rev:
794 marks[mark] = repo.lookup(rev)
794 marks[mark] = repo.lookup(rev)
795 else:
795 else:
796 marks[mark] = cur
796 marks[mark] = cur
797 if not inactive and cur == marks[mark]:
797 if not inactive and cur == marks[mark]:
798 bookmarks.setcurrent(repo, mark)
798 bookmarks.setcurrent(repo, mark)
799 bookmarks.write(repo)
799 bookmarks.write(repo)
800 return
800 return
801
801
802 if mark is None:
802 if mark is None:
803 if rev:
803 if rev:
804 raise util.Abort(_("bookmark name required"))
804 raise util.Abort(_("bookmark name required"))
805 if len(marks) == 0:
805 if len(marks) == 0:
806 ui.status(_("no bookmarks set\n"))
806 ui.status(_("no bookmarks set\n"))
807 else:
807 else:
808 for bmark, n in sorted(marks.iteritems()):
808 for bmark, n in sorted(marks.iteritems()):
809 current = repo._bookmarkcurrent
809 current = repo._bookmarkcurrent
810 if bmark == current and n == cur:
810 if bmark == current and n == cur:
811 prefix, label = '*', 'bookmarks.current'
811 prefix, label = '*', 'bookmarks.current'
812 else:
812 else:
813 prefix, label = ' ', ''
813 prefix, label = ' ', ''
814
814
815 if ui.quiet:
815 if ui.quiet:
816 ui.write("%s\n" % bmark, label=label)
816 ui.write("%s\n" % bmark, label=label)
817 else:
817 else:
818 ui.write(" %s %-25s %d:%s\n" % (
818 ui.write(" %s %-25s %d:%s\n" % (
819 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
819 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
820 label=label)
820 label=label)
821 return
821 return
822
822
823 @command('branch',
823 @command('branch',
824 [('f', 'force', None,
824 [('f', 'force', None,
825 _('set branch name even if it shadows an existing branch')),
825 _('set branch name even if it shadows an existing branch')),
826 ('C', 'clean', None, _('reset branch name to parent branch name'))],
826 ('C', 'clean', None, _('reset branch name to parent branch name'))],
827 _('[-fC] [NAME]'))
827 _('[-fC] [NAME]'))
828 def branch(ui, repo, label=None, **opts):
828 def branch(ui, repo, label=None, **opts):
829 """set or show the current branch name
829 """set or show the current branch name
830
830
831 .. note::
831 .. note::
832 Branch names are permanent and global. Use :hg:`bookmark` to create a
832 Branch names are permanent and global. Use :hg:`bookmark` to create a
833 light-weight bookmark instead. See :hg:`help glossary` for more
833 light-weight bookmark instead. See :hg:`help glossary` for more
834 information about named branches and bookmarks.
834 information about named branches and bookmarks.
835
835
836 With no argument, show the current branch name. With one argument,
836 With no argument, show the current branch name. With one argument,
837 set the working directory branch name (the branch will not exist
837 set the working directory branch name (the branch will not exist
838 in the repository until the next commit). Standard practice
838 in the repository until the next commit). Standard practice
839 recommends that primary development take place on the 'default'
839 recommends that primary development take place on the 'default'
840 branch.
840 branch.
841
841
842 Unless -f/--force is specified, branch will not let you set a
842 Unless -f/--force is specified, branch will not let you set a
843 branch name that already exists, even if it's inactive.
843 branch name that already exists, even if it's inactive.
844
844
845 Use -C/--clean to reset the working directory branch to that of
845 Use -C/--clean to reset the working directory branch to that of
846 the parent of the working directory, negating a previous branch
846 the parent of the working directory, negating a previous branch
847 change.
847 change.
848
848
849 Use the command :hg:`update` to switch to an existing branch. Use
849 Use the command :hg:`update` to switch to an existing branch. Use
850 :hg:`commit --close-branch` to mark this branch as closed.
850 :hg:`commit --close-branch` to mark this branch as closed.
851
851
852 Returns 0 on success.
852 Returns 0 on success.
853 """
853 """
854
854
855 if opts.get('clean'):
855 if opts.get('clean'):
856 label = repo[None].p1().branch()
856 label = repo[None].p1().branch()
857 repo.dirstate.setbranch(label)
857 repo.dirstate.setbranch(label)
858 ui.status(_('reset working directory to branch %s\n') % label)
858 ui.status(_('reset working directory to branch %s\n') % label)
859 elif label:
859 elif label:
860 if not opts.get('force') and label in repo.branchtags():
860 if not opts.get('force') and label in repo.branchtags():
861 if label not in [p.branch() for p in repo.parents()]:
861 if label not in [p.branch() for p in repo.parents()]:
862 raise util.Abort(_('a branch of the same name already exists'),
862 raise util.Abort(_('a branch of the same name already exists'),
863 # i18n: "it" refers to an existing branch
863 # i18n: "it" refers to an existing branch
864 hint=_("use 'hg update' to switch to it"))
864 hint=_("use 'hg update' to switch to it"))
865 repo.dirstate.setbranch(label)
865 repo.dirstate.setbranch(label)
866 ui.status(_('marked working directory as branch %s\n') % label)
866 ui.status(_('marked working directory as branch %s\n') % label)
867 ui.status(_('(branches are permanent and global, '
867 ui.status(_('(branches are permanent and global, '
868 'did you want a bookmark?)\n'))
868 'did you want a bookmark?)\n'))
869 else:
869 else:
870 ui.write("%s\n" % repo.dirstate.branch())
870 ui.write("%s\n" % repo.dirstate.branch())
871
871
872 @command('branches',
872 @command('branches',
873 [('a', 'active', False, _('show only branches that have unmerged heads')),
873 [('a', 'active', False, _('show only branches that have unmerged heads')),
874 ('c', 'closed', False, _('show normal and closed branches'))],
874 ('c', 'closed', False, _('show normal and closed branches'))],
875 _('[-ac]'))
875 _('[-ac]'))
876 def branches(ui, repo, active=False, closed=False):
876 def branches(ui, repo, active=False, closed=False):
877 """list repository named branches
877 """list repository named branches
878
878
879 List the repository's named branches, indicating which ones are
879 List the repository's named branches, indicating which ones are
880 inactive. If -c/--closed is specified, also list branches which have
880 inactive. If -c/--closed is specified, also list branches which have
881 been marked closed (see :hg:`commit --close-branch`).
881 been marked closed (see :hg:`commit --close-branch`).
882
882
883 If -a/--active is specified, only show active branches. A branch
883 If -a/--active is specified, only show active branches. A branch
884 is considered active if it contains repository heads.
884 is considered active if it contains repository heads.
885
885
886 Use the command :hg:`update` to switch to an existing branch.
886 Use the command :hg:`update` to switch to an existing branch.
887
887
888 Returns 0.
888 Returns 0.
889 """
889 """
890
890
891 hexfunc = ui.debugflag and hex or short
891 hexfunc = ui.debugflag and hex or short
892 activebranches = [repo[n].branch() for n in repo.heads()]
892 activebranches = [repo[n].branch() for n in repo.heads()]
893 def testactive(tag, node):
893 def testactive(tag, node):
894 realhead = tag in activebranches
894 realhead = tag in activebranches
895 open = node in repo.branchheads(tag, closed=False)
895 open = node in repo.branchheads(tag, closed=False)
896 return realhead and open
896 return realhead and open
897 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
897 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
898 for tag, node in repo.branchtags().items()],
898 for tag, node in repo.branchtags().items()],
899 reverse=True)
899 reverse=True)
900
900
901 for isactive, node, tag in branches:
901 for isactive, node, tag in branches:
902 if (not active) or isactive:
902 if (not active) or isactive:
903 if ui.quiet:
903 if ui.quiet:
904 ui.write("%s\n" % tag)
904 ui.write("%s\n" % tag)
905 else:
905 else:
906 hn = repo.lookup(node)
906 hn = repo.lookup(node)
907 if isactive:
907 if isactive:
908 label = 'branches.active'
908 label = 'branches.active'
909 notice = ''
909 notice = ''
910 elif hn not in repo.branchheads(tag, closed=False):
910 elif hn not in repo.branchheads(tag, closed=False):
911 if not closed:
911 if not closed:
912 continue
912 continue
913 label = 'branches.closed'
913 label = 'branches.closed'
914 notice = _(' (closed)')
914 notice = _(' (closed)')
915 else:
915 else:
916 label = 'branches.inactive'
916 label = 'branches.inactive'
917 notice = _(' (inactive)')
917 notice = _(' (inactive)')
918 if tag == repo.dirstate.branch():
918 if tag == repo.dirstate.branch():
919 label = 'branches.current'
919 label = 'branches.current'
920 rev = str(node).rjust(31 - encoding.colwidth(tag))
920 rev = str(node).rjust(31 - encoding.colwidth(tag))
921 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
921 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
922 tag = ui.label(tag, label)
922 tag = ui.label(tag, label)
923 ui.write("%s %s%s\n" % (tag, rev, notice))
923 ui.write("%s %s%s\n" % (tag, rev, notice))
924
924
925 @command('bundle',
925 @command('bundle',
926 [('f', 'force', None, _('run even when the destination is unrelated')),
926 [('f', 'force', None, _('run even when the destination is unrelated')),
927 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
927 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
928 _('REV')),
928 _('REV')),
929 ('b', 'branch', [], _('a specific branch you would like to bundle'),
929 ('b', 'branch', [], _('a specific branch you would like to bundle'),
930 _('BRANCH')),
930 _('BRANCH')),
931 ('', 'base', [],
931 ('', 'base', [],
932 _('a base changeset assumed to be available at the destination'),
932 _('a base changeset assumed to be available at the destination'),
933 _('REV')),
933 _('REV')),
934 ('a', 'all', None, _('bundle all changesets in the repository')),
934 ('a', 'all', None, _('bundle all changesets in the repository')),
935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
936 ] + remoteopts,
936 ] + remoteopts,
937 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
937 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
938 def bundle(ui, repo, fname, dest=None, **opts):
938 def bundle(ui, repo, fname, dest=None, **opts):
939 """create a changegroup file
939 """create a changegroup file
940
940
941 Generate a compressed changegroup file collecting changesets not
941 Generate a compressed changegroup file collecting changesets not
942 known to be in another repository.
942 known to be in another repository.
943
943
944 If you omit the destination repository, then hg assumes the
944 If you omit the destination repository, then hg assumes the
945 destination will have all the nodes you specify with --base
945 destination will have all the nodes you specify with --base
946 parameters. To create a bundle containing all changesets, use
946 parameters. To create a bundle containing all changesets, use
947 -a/--all (or --base null).
947 -a/--all (or --base null).
948
948
949 You can change compression method with the -t/--type option.
949 You can change compression method with the -t/--type option.
950 The available compression methods are: none, bzip2, and
950 The available compression methods are: none, bzip2, and
951 gzip (by default, bundles are compressed using bzip2).
951 gzip (by default, bundles are compressed using bzip2).
952
952
953 The bundle file can then be transferred using conventional means
953 The bundle file can then be transferred using conventional means
954 and applied to another repository with the unbundle or pull
954 and applied to another repository with the unbundle or pull
955 command. This is useful when direct push and pull are not
955 command. This is useful when direct push and pull are not
956 available or when exporting an entire repository is undesirable.
956 available or when exporting an entire repository is undesirable.
957
957
958 Applying bundles preserves all changeset contents including
958 Applying bundles preserves all changeset contents including
959 permissions, copy/rename information, and revision history.
959 permissions, copy/rename information, and revision history.
960
960
961 Returns 0 on success, 1 if no changes found.
961 Returns 0 on success, 1 if no changes found.
962 """
962 """
963 revs = None
963 revs = None
964 if 'rev' in opts:
964 if 'rev' in opts:
965 revs = scmutil.revrange(repo, opts['rev'])
965 revs = scmutil.revrange(repo, opts['rev'])
966
966
967 if opts.get('all'):
967 if opts.get('all'):
968 base = ['null']
968 base = ['null']
969 else:
969 else:
970 base = scmutil.revrange(repo, opts.get('base'))
970 base = scmutil.revrange(repo, opts.get('base'))
971 if base:
971 if base:
972 if dest:
972 if dest:
973 raise util.Abort(_("--base is incompatible with specifying "
973 raise util.Abort(_("--base is incompatible with specifying "
974 "a destination"))
974 "a destination"))
975 common = [repo.lookup(rev) for rev in base]
975 common = [repo.lookup(rev) for rev in base]
976 heads = revs and map(repo.lookup, revs) or revs
976 heads = revs and map(repo.lookup, revs) or revs
977 else:
977 else:
978 dest = ui.expandpath(dest or 'default-push', dest or 'default')
978 dest = ui.expandpath(dest or 'default-push', dest or 'default')
979 dest, branches = hg.parseurl(dest, opts.get('branch'))
979 dest, branches = hg.parseurl(dest, opts.get('branch'))
980 other = hg.peer(repo, opts, dest)
980 other = hg.peer(repo, opts, dest)
981 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
981 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
982 heads = revs and map(repo.lookup, revs) or revs
982 heads = revs and map(repo.lookup, revs) or revs
983 common, outheads = discovery.findcommonoutgoing(repo, other,
983 common, outheads = discovery.findcommonoutgoing(repo, other,
984 onlyheads=heads,
984 onlyheads=heads,
985 force=opts.get('force'))
985 force=opts.get('force'))
986
986
987 cg = repo.getbundle('bundle', common=common, heads=heads)
987 cg = repo.getbundle('bundle', common=common, heads=heads)
988 if not cg:
988 if not cg:
989 ui.status(_("no changes found\n"))
989 ui.status(_("no changes found\n"))
990 return 1
990 return 1
991
991
992 bundletype = opts.get('type', 'bzip2').lower()
992 bundletype = opts.get('type', 'bzip2').lower()
993 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
993 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
994 bundletype = btypes.get(bundletype)
994 bundletype = btypes.get(bundletype)
995 if bundletype not in changegroup.bundletypes:
995 if bundletype not in changegroup.bundletypes:
996 raise util.Abort(_('unknown bundle type specified with --type'))
996 raise util.Abort(_('unknown bundle type specified with --type'))
997
997
998 changegroup.writebundle(cg, fname, bundletype)
998 changegroup.writebundle(cg, fname, bundletype)
999
999
1000 @command('cat',
1000 @command('cat',
1001 [('o', 'output', '',
1001 [('o', 'output', '',
1002 _('print output to file with formatted name'), _('FORMAT')),
1002 _('print output to file with formatted name'), _('FORMAT')),
1003 ('r', 'rev', '', _('print the given revision'), _('REV')),
1003 ('r', 'rev', '', _('print the given revision'), _('REV')),
1004 ('', 'decode', None, _('apply any matching decode filter')),
1004 ('', 'decode', None, _('apply any matching decode filter')),
1005 ] + walkopts,
1005 ] + walkopts,
1006 _('[OPTION]... FILE...'))
1006 _('[OPTION]... FILE...'))
1007 def cat(ui, repo, file1, *pats, **opts):
1007 def cat(ui, repo, file1, *pats, **opts):
1008 """output the current or given revision of files
1008 """output the current or given revision of files
1009
1009
1010 Print the specified files as they were at the given revision. If
1010 Print the specified files as they were at the given revision. If
1011 no revision is given, the parent of the working directory is used,
1011 no revision is given, the parent of the working directory is used,
1012 or tip if no revision is checked out.
1012 or tip if no revision is checked out.
1013
1013
1014 Output may be to a file, in which case the name of the file is
1014 Output may be to a file, in which case the name of the file is
1015 given using a format string. The formatting rules are the same as
1015 given using a format string. The formatting rules are the same as
1016 for the export command, with the following additions:
1016 for the export command, with the following additions:
1017
1017
1018 :``%s``: basename of file being printed
1018 :``%s``: basename of file being printed
1019 :``%d``: dirname of file being printed, or '.' if in repository root
1019 :``%d``: dirname of file being printed, or '.' if in repository root
1020 :``%p``: root-relative path name of file being printed
1020 :``%p``: root-relative path name of file being printed
1021
1021
1022 Returns 0 on success.
1022 Returns 0 on success.
1023 """
1023 """
1024 ctx = scmutil.revsingle(repo, opts.get('rev'))
1024 ctx = scmutil.revsingle(repo, opts.get('rev'))
1025 err = 1
1025 err = 1
1026 m = scmutil.match(ctx, (file1,) + pats, opts)
1026 m = scmutil.match(ctx, (file1,) + pats, opts)
1027 for abs in ctx.walk(m):
1027 for abs in ctx.walk(m):
1028 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1028 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1029 pathname=abs)
1029 pathname=abs)
1030 data = ctx[abs].data()
1030 data = ctx[abs].data()
1031 if opts.get('decode'):
1031 if opts.get('decode'):
1032 data = repo.wwritedata(abs, data)
1032 data = repo.wwritedata(abs, data)
1033 fp.write(data)
1033 fp.write(data)
1034 fp.close()
1034 fp.close()
1035 err = 0
1035 err = 0
1036 return err
1036 return err
1037
1037
1038 @command('^clone',
1038 @command('^clone',
1039 [('U', 'noupdate', None,
1039 [('U', 'noupdate', None,
1040 _('the clone will include an empty working copy (only a repository)')),
1040 _('the clone will include an empty working copy (only a repository)')),
1041 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1041 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1042 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1042 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1043 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1043 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1044 ('', 'pull', None, _('use pull protocol to copy metadata')),
1044 ('', 'pull', None, _('use pull protocol to copy metadata')),
1045 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1045 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1046 ] + remoteopts,
1046 ] + remoteopts,
1047 _('[OPTION]... SOURCE [DEST]'))
1047 _('[OPTION]... SOURCE [DEST]'))
1048 def clone(ui, source, dest=None, **opts):
1048 def clone(ui, source, dest=None, **opts):
1049 """make a copy of an existing repository
1049 """make a copy of an existing repository
1050
1050
1051 Create a copy of an existing repository in a new directory.
1051 Create a copy of an existing repository in a new directory.
1052
1052
1053 If no destination directory name is specified, it defaults to the
1053 If no destination directory name is specified, it defaults to the
1054 basename of the source.
1054 basename of the source.
1055
1055
1056 The location of the source is added to the new repository's
1056 The location of the source is added to the new repository's
1057 ``.hg/hgrc`` file, as the default to be used for future pulls.
1057 ``.hg/hgrc`` file, as the default to be used for future pulls.
1058
1058
1059 Only local paths and ``ssh://`` URLs are supported as
1059 Only local paths and ``ssh://`` URLs are supported as
1060 destinations. For ``ssh://`` destinations, no working directory or
1060 destinations. For ``ssh://`` destinations, no working directory or
1061 ``.hg/hgrc`` will be created on the remote side.
1061 ``.hg/hgrc`` will be created on the remote side.
1062
1062
1063 To pull only a subset of changesets, specify one or more revisions
1063 To pull only a subset of changesets, specify one or more revisions
1064 identifiers with -r/--rev or branches with -b/--branch. The
1064 identifiers with -r/--rev or branches with -b/--branch. The
1065 resulting clone will contain only the specified changesets and
1065 resulting clone will contain only the specified changesets and
1066 their ancestors. These options (or 'clone src#rev dest') imply
1066 their ancestors. These options (or 'clone src#rev dest') imply
1067 --pull, even for local source repositories. Note that specifying a
1067 --pull, even for local source repositories. Note that specifying a
1068 tag will include the tagged changeset but not the changeset
1068 tag will include the tagged changeset but not the changeset
1069 containing the tag.
1069 containing the tag.
1070
1070
1071 To check out a particular version, use -u/--update, or
1071 To check out a particular version, use -u/--update, or
1072 -U/--noupdate to create a clone with no working directory.
1072 -U/--noupdate to create a clone with no working directory.
1073
1073
1074 .. container:: verbose
1074 .. container:: verbose
1075
1075
1076 For efficiency, hardlinks are used for cloning whenever the
1076 For efficiency, hardlinks are used for cloning whenever the
1077 source and destination are on the same filesystem (note this
1077 source and destination are on the same filesystem (note this
1078 applies only to the repository data, not to the working
1078 applies only to the repository data, not to the working
1079 directory). Some filesystems, such as AFS, implement hardlinking
1079 directory). Some filesystems, such as AFS, implement hardlinking
1080 incorrectly, but do not report errors. In these cases, use the
1080 incorrectly, but do not report errors. In these cases, use the
1081 --pull option to avoid hardlinking.
1081 --pull option to avoid hardlinking.
1082
1082
1083 In some cases, you can clone repositories and the working
1083 In some cases, you can clone repositories and the working
1084 directory using full hardlinks with ::
1084 directory using full hardlinks with ::
1085
1085
1086 $ cp -al REPO REPOCLONE
1086 $ cp -al REPO REPOCLONE
1087
1087
1088 This is the fastest way to clone, but it is not always safe. The
1088 This is the fastest way to clone, but it is not always safe. The
1089 operation is not atomic (making sure REPO is not modified during
1089 operation is not atomic (making sure REPO is not modified during
1090 the operation is up to you) and you have to make sure your
1090 the operation is up to you) and you have to make sure your
1091 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1091 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1092 so). Also, this is not compatible with certain extensions that
1092 so). Also, this is not compatible with certain extensions that
1093 place their metadata under the .hg directory, such as mq.
1093 place their metadata under the .hg directory, such as mq.
1094
1094
1095 Mercurial will update the working directory to the first applicable
1095 Mercurial will update the working directory to the first applicable
1096 revision from this list:
1096 revision from this list:
1097
1097
1098 a) null if -U or the source repository has no changesets
1098 a) null if -U or the source repository has no changesets
1099 b) if -u . and the source repository is local, the first parent of
1099 b) if -u . and the source repository is local, the first parent of
1100 the source repository's working directory
1100 the source repository's working directory
1101 c) the changeset specified with -u (if a branch name, this means the
1101 c) the changeset specified with -u (if a branch name, this means the
1102 latest head of that branch)
1102 latest head of that branch)
1103 d) the changeset specified with -r
1103 d) the changeset specified with -r
1104 e) the tipmost head specified with -b
1104 e) the tipmost head specified with -b
1105 f) the tipmost head specified with the url#branch source syntax
1105 f) the tipmost head specified with the url#branch source syntax
1106 g) the tipmost head of the default branch
1106 g) the tipmost head of the default branch
1107 h) tip
1107 h) tip
1108
1108
1109 Examples:
1109 Examples:
1110
1110
1111 - clone a remote repository to a new directory named hg/::
1111 - clone a remote repository to a new directory named hg/::
1112
1112
1113 hg clone http://selenic.com/hg
1113 hg clone http://selenic.com/hg
1114
1114
1115 - create a lightweight local clone::
1115 - create a lightweight local clone::
1116
1116
1117 hg clone project/ project-feature/
1117 hg clone project/ project-feature/
1118
1118
1119 - clone from an absolute path on an ssh server (note double-slash)::
1119 - clone from an absolute path on an ssh server (note double-slash)::
1120
1120
1121 hg clone ssh://user@server//home/projects/alpha/
1121 hg clone ssh://user@server//home/projects/alpha/
1122
1122
1123 - do a high-speed clone over a LAN while checking out a
1123 - do a high-speed clone over a LAN while checking out a
1124 specified version::
1124 specified version::
1125
1125
1126 hg clone --uncompressed http://server/repo -u 1.5
1126 hg clone --uncompressed http://server/repo -u 1.5
1127
1127
1128 - create a repository without changesets after a particular revision::
1128 - create a repository without changesets after a particular revision::
1129
1129
1130 hg clone -r 04e544 experimental/ good/
1130 hg clone -r 04e544 experimental/ good/
1131
1131
1132 - clone (and track) a particular named branch::
1132 - clone (and track) a particular named branch::
1133
1133
1134 hg clone http://selenic.com/hg#stable
1134 hg clone http://selenic.com/hg#stable
1135
1135
1136 See :hg:`help urls` for details on specifying URLs.
1136 See :hg:`help urls` for details on specifying URLs.
1137
1137
1138 Returns 0 on success.
1138 Returns 0 on success.
1139 """
1139 """
1140 if opts.get('noupdate') and opts.get('updaterev'):
1140 if opts.get('noupdate') and opts.get('updaterev'):
1141 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1141 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1142
1142
1143 r = hg.clone(ui, opts, source, dest,
1143 r = hg.clone(ui, opts, source, dest,
1144 pull=opts.get('pull'),
1144 pull=opts.get('pull'),
1145 stream=opts.get('uncompressed'),
1145 stream=opts.get('uncompressed'),
1146 rev=opts.get('rev'),
1146 rev=opts.get('rev'),
1147 update=opts.get('updaterev') or not opts.get('noupdate'),
1147 update=opts.get('updaterev') or not opts.get('noupdate'),
1148 branch=opts.get('branch'))
1148 branch=opts.get('branch'))
1149
1149
1150 return r is None
1150 return r is None
1151
1151
1152 @command('^commit|ci',
1152 @command('^commit|ci',
1153 [('A', 'addremove', None,
1153 [('A', 'addremove', None,
1154 _('mark new/missing files as added/removed before committing')),
1154 _('mark new/missing files as added/removed before committing')),
1155 ('', 'close-branch', None,
1155 ('', 'close-branch', None,
1156 _('mark a branch as closed, hiding it from the branch list')),
1156 _('mark a branch as closed, hiding it from the branch list')),
1157 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1157 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1158 _('[OPTION]... [FILE]...'))
1158 _('[OPTION]... [FILE]...'))
1159 def commit(ui, repo, *pats, **opts):
1159 def commit(ui, repo, *pats, **opts):
1160 """commit the specified files or all outstanding changes
1160 """commit the specified files or all outstanding changes
1161
1161
1162 Commit changes to the given files into the repository. Unlike a
1162 Commit changes to the given files into the repository. Unlike a
1163 centralized SCM, this operation is a local operation. See
1163 centralized SCM, this operation is a local operation. See
1164 :hg:`push` for a way to actively distribute your changes.
1164 :hg:`push` for a way to actively distribute your changes.
1165
1165
1166 If a list of files is omitted, all changes reported by :hg:`status`
1166 If a list of files is omitted, all changes reported by :hg:`status`
1167 will be committed.
1167 will be committed.
1168
1168
1169 If you are committing the result of a merge, do not provide any
1169 If you are committing the result of a merge, do not provide any
1170 filenames or -I/-X filters.
1170 filenames or -I/-X filters.
1171
1171
1172 If no commit message is specified, Mercurial starts your
1172 If no commit message is specified, Mercurial starts your
1173 configured editor where you can enter a message. In case your
1173 configured editor where you can enter a message. In case your
1174 commit fails, you will find a backup of your message in
1174 commit fails, you will find a backup of your message in
1175 ``.hg/last-message.txt``.
1175 ``.hg/last-message.txt``.
1176
1176
1177 See :hg:`help dates` for a list of formats valid for -d/--date.
1177 See :hg:`help dates` for a list of formats valid for -d/--date.
1178
1178
1179 Returns 0 on success, 1 if nothing changed.
1179 Returns 0 on success, 1 if nothing changed.
1180 """
1180 """
1181 if opts.get('subrepos'):
1181 if opts.get('subrepos'):
1182 # Let --subrepos on the command line overide config setting.
1182 # Let --subrepos on the command line overide config setting.
1183 ui.setconfig('ui', 'commitsubrepos', True)
1183 ui.setconfig('ui', 'commitsubrepos', True)
1184
1184
1185 extra = {}
1185 extra = {}
1186 if opts.get('close_branch'):
1186 if opts.get('close_branch'):
1187 if repo['.'].node() not in repo.branchheads():
1187 if repo['.'].node() not in repo.branchheads():
1188 # The topo heads set is included in the branch heads set of the
1188 # The topo heads set is included in the branch heads set of the
1189 # current branch, so it's sufficient to test branchheads
1189 # current branch, so it's sufficient to test branchheads
1190 raise util.Abort(_('can only close branch heads'))
1190 raise util.Abort(_('can only close branch heads'))
1191 extra['close'] = 1
1191 extra['close'] = 1
1192 e = cmdutil.commiteditor
1192 e = cmdutil.commiteditor
1193 if opts.get('force_editor'):
1193 if opts.get('force_editor'):
1194 e = cmdutil.commitforceeditor
1194 e = cmdutil.commitforceeditor
1195
1195
1196 def commitfunc(ui, repo, message, match, opts):
1196 def commitfunc(ui, repo, message, match, opts):
1197 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1197 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1198 editor=e, extra=extra)
1198 editor=e, extra=extra)
1199
1199
1200 branch = repo[None].branch()
1200 branch = repo[None].branch()
1201 bheads = repo.branchheads(branch)
1201 bheads = repo.branchheads(branch)
1202
1202
1203 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1203 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1204 if not node:
1204 if not node:
1205 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1205 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1206 if stat[3]:
1206 if stat[3]:
1207 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1207 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1208 % len(stat[3]))
1208 % len(stat[3]))
1209 else:
1209 else:
1210 ui.status(_("nothing changed\n"))
1210 ui.status(_("nothing changed\n"))
1211 return 1
1211 return 1
1212
1212
1213 ctx = repo[node]
1213 ctx = repo[node]
1214 parents = ctx.parents()
1214 parents = ctx.parents()
1215
1215
1216 if (bheads and node not in bheads and not
1216 if (bheads and node not in bheads and not
1217 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1217 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1218 ui.status(_('created new head\n'))
1218 ui.status(_('created new head\n'))
1219 # The message is not printed for initial roots. For the other
1219 # The message is not printed for initial roots. For the other
1220 # changesets, it is printed in the following situations:
1220 # changesets, it is printed in the following situations:
1221 #
1221 #
1222 # Par column: for the 2 parents with ...
1222 # Par column: for the 2 parents with ...
1223 # N: null or no parent
1223 # N: null or no parent
1224 # B: parent is on another named branch
1224 # B: parent is on another named branch
1225 # C: parent is a regular non head changeset
1225 # C: parent is a regular non head changeset
1226 # H: parent was a branch head of the current branch
1226 # H: parent was a branch head of the current branch
1227 # Msg column: whether we print "created new head" message
1227 # Msg column: whether we print "created new head" message
1228 # In the following, it is assumed that there already exists some
1228 # In the following, it is assumed that there already exists some
1229 # initial branch heads of the current branch, otherwise nothing is
1229 # initial branch heads of the current branch, otherwise nothing is
1230 # printed anyway.
1230 # printed anyway.
1231 #
1231 #
1232 # Par Msg Comment
1232 # Par Msg Comment
1233 # NN y additional topo root
1233 # NN y additional topo root
1234 #
1234 #
1235 # BN y additional branch root
1235 # BN y additional branch root
1236 # CN y additional topo head
1236 # CN y additional topo head
1237 # HN n usual case
1237 # HN n usual case
1238 #
1238 #
1239 # BB y weird additional branch root
1239 # BB y weird additional branch root
1240 # CB y branch merge
1240 # CB y branch merge
1241 # HB n merge with named branch
1241 # HB n merge with named branch
1242 #
1242 #
1243 # CC y additional head from merge
1243 # CC y additional head from merge
1244 # CH n merge with a head
1244 # CH n merge with a head
1245 #
1245 #
1246 # HH n head merge: head count decreases
1246 # HH n head merge: head count decreases
1247
1247
1248 if not opts.get('close_branch'):
1248 if not opts.get('close_branch'):
1249 for r in parents:
1249 for r in parents:
1250 if r.extra().get('close') and r.branch() == branch:
1250 if r.extra().get('close') and r.branch() == branch:
1251 ui.status(_('reopening closed branch head %d\n') % r)
1251 ui.status(_('reopening closed branch head %d\n') % r)
1252
1252
1253 if ui.debugflag:
1253 if ui.debugflag:
1254 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1254 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1255 elif ui.verbose:
1255 elif ui.verbose:
1256 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1256 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1257
1257
1258 @command('copy|cp',
1258 @command('copy|cp',
1259 [('A', 'after', None, _('record a copy that has already occurred')),
1259 [('A', 'after', None, _('record a copy that has already occurred')),
1260 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1260 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1261 ] + walkopts + dryrunopts,
1261 ] + walkopts + dryrunopts,
1262 _('[OPTION]... [SOURCE]... DEST'))
1262 _('[OPTION]... [SOURCE]... DEST'))
1263 def copy(ui, repo, *pats, **opts):
1263 def copy(ui, repo, *pats, **opts):
1264 """mark files as copied for the next commit
1264 """mark files as copied for the next commit
1265
1265
1266 Mark dest as having copies of source files. If dest is a
1266 Mark dest as having copies of source files. If dest is a
1267 directory, copies are put in that directory. If dest is a file,
1267 directory, copies are put in that directory. If dest is a file,
1268 the source must be a single file.
1268 the source must be a single file.
1269
1269
1270 By default, this command copies the contents of files as they
1270 By default, this command copies the contents of files as they
1271 exist in the working directory. If invoked with -A/--after, the
1271 exist in the working directory. If invoked with -A/--after, the
1272 operation is recorded, but no copying is performed.
1272 operation is recorded, but no copying is performed.
1273
1273
1274 This command takes effect with the next commit. To undo a copy
1274 This command takes effect with the next commit. To undo a copy
1275 before that, see :hg:`revert`.
1275 before that, see :hg:`revert`.
1276
1276
1277 Returns 0 on success, 1 if errors are encountered.
1277 Returns 0 on success, 1 if errors are encountered.
1278 """
1278 """
1279 wlock = repo.wlock(False)
1279 wlock = repo.wlock(False)
1280 try:
1280 try:
1281 return cmdutil.copy(ui, repo, pats, opts)
1281 return cmdutil.copy(ui, repo, pats, opts)
1282 finally:
1282 finally:
1283 wlock.release()
1283 wlock.release()
1284
1284
1285 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1285 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1286 def debugancestor(ui, repo, *args):
1286 def debugancestor(ui, repo, *args):
1287 """find the ancestor revision of two revisions in a given index"""
1287 """find the ancestor revision of two revisions in a given index"""
1288 if len(args) == 3:
1288 if len(args) == 3:
1289 index, rev1, rev2 = args
1289 index, rev1, rev2 = args
1290 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1290 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1291 lookup = r.lookup
1291 lookup = r.lookup
1292 elif len(args) == 2:
1292 elif len(args) == 2:
1293 if not repo:
1293 if not repo:
1294 raise util.Abort(_("there is no Mercurial repository here "
1294 raise util.Abort(_("there is no Mercurial repository here "
1295 "(.hg not found)"))
1295 "(.hg not found)"))
1296 rev1, rev2 = args
1296 rev1, rev2 = args
1297 r = repo.changelog
1297 r = repo.changelog
1298 lookup = repo.lookup
1298 lookup = repo.lookup
1299 else:
1299 else:
1300 raise util.Abort(_('either two or three arguments required'))
1300 raise util.Abort(_('either two or three arguments required'))
1301 a = r.ancestor(lookup(rev1), lookup(rev2))
1301 a = r.ancestor(lookup(rev1), lookup(rev2))
1302 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1302 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1303
1303
1304 @command('debugbuilddag',
1304 @command('debugbuilddag',
1305 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1305 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1306 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1306 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1307 ('n', 'new-file', None, _('add new file at each rev'))],
1307 ('n', 'new-file', None, _('add new file at each rev'))],
1308 _('[OPTION]... [TEXT]'))
1308 _('[OPTION]... [TEXT]'))
1309 def debugbuilddag(ui, repo, text=None,
1309 def debugbuilddag(ui, repo, text=None,
1310 mergeable_file=False,
1310 mergeable_file=False,
1311 overwritten_file=False,
1311 overwritten_file=False,
1312 new_file=False):
1312 new_file=False):
1313 """builds a repo with a given DAG from scratch in the current empty repo
1313 """builds a repo with a given DAG from scratch in the current empty repo
1314
1314
1315 The description of the DAG is read from stdin if not given on the
1315 The description of the DAG is read from stdin if not given on the
1316 command line.
1316 command line.
1317
1317
1318 Elements:
1318 Elements:
1319
1319
1320 - "+n" is a linear run of n nodes based on the current default parent
1320 - "+n" is a linear run of n nodes based on the current default parent
1321 - "." is a single node based on the current default parent
1321 - "." is a single node based on the current default parent
1322 - "$" resets the default parent to null (implied at the start);
1322 - "$" resets the default parent to null (implied at the start);
1323 otherwise the default parent is always the last node created
1323 otherwise the default parent is always the last node created
1324 - "<p" sets the default parent to the backref p
1324 - "<p" sets the default parent to the backref p
1325 - "*p" is a fork at parent p, which is a backref
1325 - "*p" is a fork at parent p, which is a backref
1326 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1326 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1327 - "/p2" is a merge of the preceding node and p2
1327 - "/p2" is a merge of the preceding node and p2
1328 - ":tag" defines a local tag for the preceding node
1328 - ":tag" defines a local tag for the preceding node
1329 - "@branch" sets the named branch for subsequent nodes
1329 - "@branch" sets the named branch for subsequent nodes
1330 - "#...\\n" is a comment up to the end of the line
1330 - "#...\\n" is a comment up to the end of the line
1331
1331
1332 Whitespace between the above elements is ignored.
1332 Whitespace between the above elements is ignored.
1333
1333
1334 A backref is either
1334 A backref is either
1335
1335
1336 - a number n, which references the node curr-n, where curr is the current
1336 - a number n, which references the node curr-n, where curr is the current
1337 node, or
1337 node, or
1338 - the name of a local tag you placed earlier using ":tag", or
1338 - the name of a local tag you placed earlier using ":tag", or
1339 - empty to denote the default parent.
1339 - empty to denote the default parent.
1340
1340
1341 All string valued-elements are either strictly alphanumeric, or must
1341 All string valued-elements are either strictly alphanumeric, or must
1342 be enclosed in double quotes ("..."), with "\\" as escape character.
1342 be enclosed in double quotes ("..."), with "\\" as escape character.
1343 """
1343 """
1344
1344
1345 if text is None:
1345 if text is None:
1346 ui.status(_("reading DAG from stdin\n"))
1346 ui.status(_("reading DAG from stdin\n"))
1347 text = ui.fin.read()
1347 text = ui.fin.read()
1348
1348
1349 cl = repo.changelog
1349 cl = repo.changelog
1350 if len(cl) > 0:
1350 if len(cl) > 0:
1351 raise util.Abort(_('repository is not empty'))
1351 raise util.Abort(_('repository is not empty'))
1352
1352
1353 # determine number of revs in DAG
1353 # determine number of revs in DAG
1354 total = 0
1354 total = 0
1355 for type, data in dagparser.parsedag(text):
1355 for type, data in dagparser.parsedag(text):
1356 if type == 'n':
1356 if type == 'n':
1357 total += 1
1357 total += 1
1358
1358
1359 if mergeable_file:
1359 if mergeable_file:
1360 linesperrev = 2
1360 linesperrev = 2
1361 # make a file with k lines per rev
1361 # make a file with k lines per rev
1362 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1362 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1363 initialmergedlines.append("")
1363 initialmergedlines.append("")
1364
1364
1365 tags = []
1365 tags = []
1366
1366
1367 tr = repo.transaction("builddag")
1367 tr = repo.transaction("builddag")
1368 try:
1368 try:
1369
1369
1370 at = -1
1370 at = -1
1371 atbranch = 'default'
1371 atbranch = 'default'
1372 nodeids = []
1372 nodeids = []
1373 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1373 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1374 for type, data in dagparser.parsedag(text):
1374 for type, data in dagparser.parsedag(text):
1375 if type == 'n':
1375 if type == 'n':
1376 ui.note('node %s\n' % str(data))
1376 ui.note('node %s\n' % str(data))
1377 id, ps = data
1377 id, ps = data
1378
1378
1379 files = []
1379 files = []
1380 fctxs = {}
1380 fctxs = {}
1381
1381
1382 p2 = None
1382 p2 = None
1383 if mergeable_file:
1383 if mergeable_file:
1384 fn = "mf"
1384 fn = "mf"
1385 p1 = repo[ps[0]]
1385 p1 = repo[ps[0]]
1386 if len(ps) > 1:
1386 if len(ps) > 1:
1387 p2 = repo[ps[1]]
1387 p2 = repo[ps[1]]
1388 pa = p1.ancestor(p2)
1388 pa = p1.ancestor(p2)
1389 base, local, other = [x[fn].data() for x in pa, p1, p2]
1389 base, local, other = [x[fn].data() for x in pa, p1, p2]
1390 m3 = simplemerge.Merge3Text(base, local, other)
1390 m3 = simplemerge.Merge3Text(base, local, other)
1391 ml = [l.strip() for l in m3.merge_lines()]
1391 ml = [l.strip() for l in m3.merge_lines()]
1392 ml.append("")
1392 ml.append("")
1393 elif at > 0:
1393 elif at > 0:
1394 ml = p1[fn].data().split("\n")
1394 ml = p1[fn].data().split("\n")
1395 else:
1395 else:
1396 ml = initialmergedlines
1396 ml = initialmergedlines
1397 ml[id * linesperrev] += " r%i" % id
1397 ml[id * linesperrev] += " r%i" % id
1398 mergedtext = "\n".join(ml)
1398 mergedtext = "\n".join(ml)
1399 files.append(fn)
1399 files.append(fn)
1400 fctxs[fn] = context.memfilectx(fn, mergedtext)
1400 fctxs[fn] = context.memfilectx(fn, mergedtext)
1401
1401
1402 if overwritten_file:
1402 if overwritten_file:
1403 fn = "of"
1403 fn = "of"
1404 files.append(fn)
1404 files.append(fn)
1405 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1405 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1406
1406
1407 if new_file:
1407 if new_file:
1408 fn = "nf%i" % id
1408 fn = "nf%i" % id
1409 files.append(fn)
1409 files.append(fn)
1410 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1410 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1411 if len(ps) > 1:
1411 if len(ps) > 1:
1412 if not p2:
1412 if not p2:
1413 p2 = repo[ps[1]]
1413 p2 = repo[ps[1]]
1414 for fn in p2:
1414 for fn in p2:
1415 if fn.startswith("nf"):
1415 if fn.startswith("nf"):
1416 files.append(fn)
1416 files.append(fn)
1417 fctxs[fn] = p2[fn]
1417 fctxs[fn] = p2[fn]
1418
1418
1419 def fctxfn(repo, cx, path):
1419 def fctxfn(repo, cx, path):
1420 return fctxs.get(path)
1420 return fctxs.get(path)
1421
1421
1422 if len(ps) == 0 or ps[0] < 0:
1422 if len(ps) == 0 or ps[0] < 0:
1423 pars = [None, None]
1423 pars = [None, None]
1424 elif len(ps) == 1:
1424 elif len(ps) == 1:
1425 pars = [nodeids[ps[0]], None]
1425 pars = [nodeids[ps[0]], None]
1426 else:
1426 else:
1427 pars = [nodeids[p] for p in ps]
1427 pars = [nodeids[p] for p in ps]
1428 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1428 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1429 date=(id, 0),
1429 date=(id, 0),
1430 user="debugbuilddag",
1430 user="debugbuilddag",
1431 extra={'branch': atbranch})
1431 extra={'branch': atbranch})
1432 nodeid = repo.commitctx(cx)
1432 nodeid = repo.commitctx(cx)
1433 nodeids.append(nodeid)
1433 nodeids.append(nodeid)
1434 at = id
1434 at = id
1435 elif type == 'l':
1435 elif type == 'l':
1436 id, name = data
1436 id, name = data
1437 ui.note('tag %s\n' % name)
1437 ui.note('tag %s\n' % name)
1438 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1438 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1439 elif type == 'a':
1439 elif type == 'a':
1440 ui.note('branch %s\n' % data)
1440 ui.note('branch %s\n' % data)
1441 atbranch = data
1441 atbranch = data
1442 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1442 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1443 tr.close()
1443 tr.close()
1444 finally:
1444 finally:
1445 ui.progress(_('building'), None)
1445 ui.progress(_('building'), None)
1446 tr.release()
1446 tr.release()
1447
1447
1448 if tags:
1448 if tags:
1449 repo.opener.write("localtags", "".join(tags))
1449 repo.opener.write("localtags", "".join(tags))
1450
1450
1451 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1451 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1452 def debugbundle(ui, bundlepath, all=None, **opts):
1452 def debugbundle(ui, bundlepath, all=None, **opts):
1453 """lists the contents of a bundle"""
1453 """lists the contents of a bundle"""
1454 f = url.open(ui, bundlepath)
1454 f = url.open(ui, bundlepath)
1455 try:
1455 try:
1456 gen = changegroup.readbundle(f, bundlepath)
1456 gen = changegroup.readbundle(f, bundlepath)
1457 if all:
1457 if all:
1458 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1458 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1459
1459
1460 def showchunks(named):
1460 def showchunks(named):
1461 ui.write("\n%s\n" % named)
1461 ui.write("\n%s\n" % named)
1462 chain = None
1462 chain = None
1463 while True:
1463 while True:
1464 chunkdata = gen.deltachunk(chain)
1464 chunkdata = gen.deltachunk(chain)
1465 if not chunkdata:
1465 if not chunkdata:
1466 break
1466 break
1467 node = chunkdata['node']
1467 node = chunkdata['node']
1468 p1 = chunkdata['p1']
1468 p1 = chunkdata['p1']
1469 p2 = chunkdata['p2']
1469 p2 = chunkdata['p2']
1470 cs = chunkdata['cs']
1470 cs = chunkdata['cs']
1471 deltabase = chunkdata['deltabase']
1471 deltabase = chunkdata['deltabase']
1472 delta = chunkdata['delta']
1472 delta = chunkdata['delta']
1473 ui.write("%s %s %s %s %s %s\n" %
1473 ui.write("%s %s %s %s %s %s\n" %
1474 (hex(node), hex(p1), hex(p2),
1474 (hex(node), hex(p1), hex(p2),
1475 hex(cs), hex(deltabase), len(delta)))
1475 hex(cs), hex(deltabase), len(delta)))
1476 chain = node
1476 chain = node
1477
1477
1478 chunkdata = gen.changelogheader()
1478 chunkdata = gen.changelogheader()
1479 showchunks("changelog")
1479 showchunks("changelog")
1480 chunkdata = gen.manifestheader()
1480 chunkdata = gen.manifestheader()
1481 showchunks("manifest")
1481 showchunks("manifest")
1482 while True:
1482 while True:
1483 chunkdata = gen.filelogheader()
1483 chunkdata = gen.filelogheader()
1484 if not chunkdata:
1484 if not chunkdata:
1485 break
1485 break
1486 fname = chunkdata['filename']
1486 fname = chunkdata['filename']
1487 showchunks(fname)
1487 showchunks(fname)
1488 else:
1488 else:
1489 chunkdata = gen.changelogheader()
1489 chunkdata = gen.changelogheader()
1490 chain = None
1490 chain = None
1491 while True:
1491 while True:
1492 chunkdata = gen.deltachunk(chain)
1492 chunkdata = gen.deltachunk(chain)
1493 if not chunkdata:
1493 if not chunkdata:
1494 break
1494 break
1495 node = chunkdata['node']
1495 node = chunkdata['node']
1496 ui.write("%s\n" % hex(node))
1496 ui.write("%s\n" % hex(node))
1497 chain = node
1497 chain = node
1498 finally:
1498 finally:
1499 f.close()
1499 f.close()
1500
1500
1501 @command('debugcheckstate', [], '')
1501 @command('debugcheckstate', [], '')
1502 def debugcheckstate(ui, repo):
1502 def debugcheckstate(ui, repo):
1503 """validate the correctness of the current dirstate"""
1503 """validate the correctness of the current dirstate"""
1504 parent1, parent2 = repo.dirstate.parents()
1504 parent1, parent2 = repo.dirstate.parents()
1505 m1 = repo[parent1].manifest()
1505 m1 = repo[parent1].manifest()
1506 m2 = repo[parent2].manifest()
1506 m2 = repo[parent2].manifest()
1507 errors = 0
1507 errors = 0
1508 for f in repo.dirstate:
1508 for f in repo.dirstate:
1509 state = repo.dirstate[f]
1509 state = repo.dirstate[f]
1510 if state in "nr" and f not in m1:
1510 if state in "nr" and f not in m1:
1511 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1511 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1512 errors += 1
1512 errors += 1
1513 if state in "a" and f in m1:
1513 if state in "a" and f in m1:
1514 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1514 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1515 errors += 1
1515 errors += 1
1516 if state in "m" and f not in m1 and f not in m2:
1516 if state in "m" and f not in m1 and f not in m2:
1517 ui.warn(_("%s in state %s, but not in either manifest\n") %
1517 ui.warn(_("%s in state %s, but not in either manifest\n") %
1518 (f, state))
1518 (f, state))
1519 errors += 1
1519 errors += 1
1520 for f in m1:
1520 for f in m1:
1521 state = repo.dirstate[f]
1521 state = repo.dirstate[f]
1522 if state not in "nrm":
1522 if state not in "nrm":
1523 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1523 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1524 errors += 1
1524 errors += 1
1525 if errors:
1525 if errors:
1526 error = _(".hg/dirstate inconsistent with current parent's manifest")
1526 error = _(".hg/dirstate inconsistent with current parent's manifest")
1527 raise util.Abort(error)
1527 raise util.Abort(error)
1528
1528
1529 @command('debugcommands', [], _('[COMMAND]'))
1529 @command('debugcommands', [], _('[COMMAND]'))
1530 def debugcommands(ui, cmd='', *args):
1530 def debugcommands(ui, cmd='', *args):
1531 """list all available commands and options"""
1531 """list all available commands and options"""
1532 for cmd, vals in sorted(table.iteritems()):
1532 for cmd, vals in sorted(table.iteritems()):
1533 cmd = cmd.split('|')[0].strip('^')
1533 cmd = cmd.split('|')[0].strip('^')
1534 opts = ', '.join([i[1] for i in vals[1]])
1534 opts = ', '.join([i[1] for i in vals[1]])
1535 ui.write('%s: %s\n' % (cmd, opts))
1535 ui.write('%s: %s\n' % (cmd, opts))
1536
1536
1537 @command('debugcomplete',
1537 @command('debugcomplete',
1538 [('o', 'options', None, _('show the command options'))],
1538 [('o', 'options', None, _('show the command options'))],
1539 _('[-o] CMD'))
1539 _('[-o] CMD'))
1540 def debugcomplete(ui, cmd='', **opts):
1540 def debugcomplete(ui, cmd='', **opts):
1541 """returns the completion list associated with the given command"""
1541 """returns the completion list associated with the given command"""
1542
1542
1543 if opts.get('options'):
1543 if opts.get('options'):
1544 options = []
1544 options = []
1545 otables = [globalopts]
1545 otables = [globalopts]
1546 if cmd:
1546 if cmd:
1547 aliases, entry = cmdutil.findcmd(cmd, table, False)
1547 aliases, entry = cmdutil.findcmd(cmd, table, False)
1548 otables.append(entry[1])
1548 otables.append(entry[1])
1549 for t in otables:
1549 for t in otables:
1550 for o in t:
1550 for o in t:
1551 if "(DEPRECATED)" in o[3]:
1551 if "(DEPRECATED)" in o[3]:
1552 continue
1552 continue
1553 if o[0]:
1553 if o[0]:
1554 options.append('-%s' % o[0])
1554 options.append('-%s' % o[0])
1555 options.append('--%s' % o[1])
1555 options.append('--%s' % o[1])
1556 ui.write("%s\n" % "\n".join(options))
1556 ui.write("%s\n" % "\n".join(options))
1557 return
1557 return
1558
1558
1559 cmdlist = cmdutil.findpossible(cmd, table)
1559 cmdlist = cmdutil.findpossible(cmd, table)
1560 if ui.verbose:
1560 if ui.verbose:
1561 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1561 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1562 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1562 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1563
1563
1564 @command('debugdag',
1564 @command('debugdag',
1565 [('t', 'tags', None, _('use tags as labels')),
1565 [('t', 'tags', None, _('use tags as labels')),
1566 ('b', 'branches', None, _('annotate with branch names')),
1566 ('b', 'branches', None, _('annotate with branch names')),
1567 ('', 'dots', None, _('use dots for runs')),
1567 ('', 'dots', None, _('use dots for runs')),
1568 ('s', 'spaces', None, _('separate elements by spaces'))],
1568 ('s', 'spaces', None, _('separate elements by spaces'))],
1569 _('[OPTION]... [FILE [REV]...]'))
1569 _('[OPTION]... [FILE [REV]...]'))
1570 def debugdag(ui, repo, file_=None, *revs, **opts):
1570 def debugdag(ui, repo, file_=None, *revs, **opts):
1571 """format the changelog or an index DAG as a concise textual description
1571 """format the changelog or an index DAG as a concise textual description
1572
1572
1573 If you pass a revlog index, the revlog's DAG is emitted. If you list
1573 If you pass a revlog index, the revlog's DAG is emitted. If you list
1574 revision numbers, they get labelled in the output as rN.
1574 revision numbers, they get labelled in the output as rN.
1575
1575
1576 Otherwise, the changelog DAG of the current repo is emitted.
1576 Otherwise, the changelog DAG of the current repo is emitted.
1577 """
1577 """
1578 spaces = opts.get('spaces')
1578 spaces = opts.get('spaces')
1579 dots = opts.get('dots')
1579 dots = opts.get('dots')
1580 if file_:
1580 if file_:
1581 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1581 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1582 revs = set((int(r) for r in revs))
1582 revs = set((int(r) for r in revs))
1583 def events():
1583 def events():
1584 for r in rlog:
1584 for r in rlog:
1585 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1585 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1586 if r in revs:
1586 if r in revs:
1587 yield 'l', (r, "r%i" % r)
1587 yield 'l', (r, "r%i" % r)
1588 elif repo:
1588 elif repo:
1589 cl = repo.changelog
1589 cl = repo.changelog
1590 tags = opts.get('tags')
1590 tags = opts.get('tags')
1591 branches = opts.get('branches')
1591 branches = opts.get('branches')
1592 if tags:
1592 if tags:
1593 labels = {}
1593 labels = {}
1594 for l, n in repo.tags().items():
1594 for l, n in repo.tags().items():
1595 labels.setdefault(cl.rev(n), []).append(l)
1595 labels.setdefault(cl.rev(n), []).append(l)
1596 def events():
1596 def events():
1597 b = "default"
1597 b = "default"
1598 for r in cl:
1598 for r in cl:
1599 if branches:
1599 if branches:
1600 newb = cl.read(cl.node(r))[5]['branch']
1600 newb = cl.read(cl.node(r))[5]['branch']
1601 if newb != b:
1601 if newb != b:
1602 yield 'a', newb
1602 yield 'a', newb
1603 b = newb
1603 b = newb
1604 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1604 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1605 if tags:
1605 if tags:
1606 ls = labels.get(r)
1606 ls = labels.get(r)
1607 if ls:
1607 if ls:
1608 for l in ls:
1608 for l in ls:
1609 yield 'l', (r, l)
1609 yield 'l', (r, l)
1610 else:
1610 else:
1611 raise util.Abort(_('need repo for changelog dag'))
1611 raise util.Abort(_('need repo for changelog dag'))
1612
1612
1613 for line in dagparser.dagtextlines(events(),
1613 for line in dagparser.dagtextlines(events(),
1614 addspaces=spaces,
1614 addspaces=spaces,
1615 wraplabels=True,
1615 wraplabels=True,
1616 wrapannotations=True,
1616 wrapannotations=True,
1617 wrapnonlinear=dots,
1617 wrapnonlinear=dots,
1618 usedots=dots,
1618 usedots=dots,
1619 maxlinewidth=70):
1619 maxlinewidth=70):
1620 ui.write(line)
1620 ui.write(line)
1621 ui.write("\n")
1621 ui.write("\n")
1622
1622
1623 @command('debugdata',
1623 @command('debugdata',
1624 [('c', 'changelog', False, _('open changelog')),
1624 [('c', 'changelog', False, _('open changelog')),
1625 ('m', 'manifest', False, _('open manifest'))],
1625 ('m', 'manifest', False, _('open manifest'))],
1626 _('-c|-m|FILE REV'))
1626 _('-c|-m|FILE REV'))
1627 def debugdata(ui, repo, file_, rev = None, **opts):
1627 def debugdata(ui, repo, file_, rev = None, **opts):
1628 """dump the contents of a data file revision"""
1628 """dump the contents of a data file revision"""
1629 if opts.get('changelog') or opts.get('manifest'):
1629 if opts.get('changelog') or opts.get('manifest'):
1630 file_, rev = None, file_
1630 file_, rev = None, file_
1631 elif rev is None:
1631 elif rev is None:
1632 raise error.CommandError('debugdata', _('invalid arguments'))
1632 raise error.CommandError('debugdata', _('invalid arguments'))
1633 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1633 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1634 try:
1634 try:
1635 ui.write(r.revision(r.lookup(rev)))
1635 ui.write(r.revision(r.lookup(rev)))
1636 except KeyError:
1636 except KeyError:
1637 raise util.Abort(_('invalid revision identifier %s') % rev)
1637 raise util.Abort(_('invalid revision identifier %s') % rev)
1638
1638
1639 @command('debugdate',
1639 @command('debugdate',
1640 [('e', 'extended', None, _('try extended date formats'))],
1640 [('e', 'extended', None, _('try extended date formats'))],
1641 _('[-e] DATE [RANGE]'))
1641 _('[-e] DATE [RANGE]'))
1642 def debugdate(ui, date, range=None, **opts):
1642 def debugdate(ui, date, range=None, **opts):
1643 """parse and display a date"""
1643 """parse and display a date"""
1644 if opts["extended"]:
1644 if opts["extended"]:
1645 d = util.parsedate(date, util.extendeddateformats)
1645 d = util.parsedate(date, util.extendeddateformats)
1646 else:
1646 else:
1647 d = util.parsedate(date)
1647 d = util.parsedate(date)
1648 ui.write("internal: %s %s\n" % d)
1648 ui.write("internal: %s %s\n" % d)
1649 ui.write("standard: %s\n" % util.datestr(d))
1649 ui.write("standard: %s\n" % util.datestr(d))
1650 if range:
1650 if range:
1651 m = util.matchdate(range)
1651 m = util.matchdate(range)
1652 ui.write("match: %s\n" % m(d[0]))
1652 ui.write("match: %s\n" % m(d[0]))
1653
1653
1654 @command('debugdiscovery',
1654 @command('debugdiscovery',
1655 [('', 'old', None, _('use old-style discovery')),
1655 [('', 'old', None, _('use old-style discovery')),
1656 ('', 'nonheads', None,
1656 ('', 'nonheads', None,
1657 _('use old-style discovery with non-heads included')),
1657 _('use old-style discovery with non-heads included')),
1658 ] + remoteopts,
1658 ] + remoteopts,
1659 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1659 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1660 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1660 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1661 """runs the changeset discovery protocol in isolation"""
1661 """runs the changeset discovery protocol in isolation"""
1662 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1662 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1663 remote = hg.peer(repo, opts, remoteurl)
1663 remote = hg.peer(repo, opts, remoteurl)
1664 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1664 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1665
1665
1666 # make sure tests are repeatable
1666 # make sure tests are repeatable
1667 random.seed(12323)
1667 random.seed(12323)
1668
1668
1669 def doit(localheads, remoteheads):
1669 def doit(localheads, remoteheads):
1670 if opts.get('old'):
1670 if opts.get('old'):
1671 if localheads:
1671 if localheads:
1672 raise util.Abort('cannot use localheads with old style discovery')
1672 raise util.Abort('cannot use localheads with old style discovery')
1673 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1673 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1674 force=True)
1674 force=True)
1675 common = set(common)
1675 common = set(common)
1676 if not opts.get('nonheads'):
1676 if not opts.get('nonheads'):
1677 ui.write("unpruned common: %s\n" % " ".join([short(n)
1677 ui.write("unpruned common: %s\n" % " ".join([short(n)
1678 for n in common]))
1678 for n in common]))
1679 dag = dagutil.revlogdag(repo.changelog)
1679 dag = dagutil.revlogdag(repo.changelog)
1680 all = dag.ancestorset(dag.internalizeall(common))
1680 all = dag.ancestorset(dag.internalizeall(common))
1681 common = dag.externalizeall(dag.headsetofconnecteds(all))
1681 common = dag.externalizeall(dag.headsetofconnecteds(all))
1682 else:
1682 else:
1683 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1683 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1684 common = set(common)
1684 common = set(common)
1685 rheads = set(hds)
1685 rheads = set(hds)
1686 lheads = set(repo.heads())
1686 lheads = set(repo.heads())
1687 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1687 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1688 if lheads <= common:
1688 if lheads <= common:
1689 ui.write("local is subset\n")
1689 ui.write("local is subset\n")
1690 elif rheads <= common:
1690 elif rheads <= common:
1691 ui.write("remote is subset\n")
1691 ui.write("remote is subset\n")
1692
1692
1693 serverlogs = opts.get('serverlog')
1693 serverlogs = opts.get('serverlog')
1694 if serverlogs:
1694 if serverlogs:
1695 for filename in serverlogs:
1695 for filename in serverlogs:
1696 logfile = open(filename, 'r')
1696 logfile = open(filename, 'r')
1697 try:
1697 try:
1698 line = logfile.readline()
1698 line = logfile.readline()
1699 while line:
1699 while line:
1700 parts = line.strip().split(';')
1700 parts = line.strip().split(';')
1701 op = parts[1]
1701 op = parts[1]
1702 if op == 'cg':
1702 if op == 'cg':
1703 pass
1703 pass
1704 elif op == 'cgss':
1704 elif op == 'cgss':
1705 doit(parts[2].split(' '), parts[3].split(' '))
1705 doit(parts[2].split(' '), parts[3].split(' '))
1706 elif op == 'unb':
1706 elif op == 'unb':
1707 doit(parts[3].split(' '), parts[2].split(' '))
1707 doit(parts[3].split(' '), parts[2].split(' '))
1708 line = logfile.readline()
1708 line = logfile.readline()
1709 finally:
1709 finally:
1710 logfile.close()
1710 logfile.close()
1711
1711
1712 else:
1712 else:
1713 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1713 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1714 opts.get('remote_head'))
1714 opts.get('remote_head'))
1715 localrevs = opts.get('local_head')
1715 localrevs = opts.get('local_head')
1716 doit(localrevs, remoterevs)
1716 doit(localrevs, remoterevs)
1717
1717
1718 @command('debugfileset', [], ('REVSPEC'))
1718 @command('debugfileset', [], ('REVSPEC'))
1719 def debugfileset(ui, repo, expr):
1719 def debugfileset(ui, repo, expr):
1720 '''parse and apply a fileset specification'''
1720 '''parse and apply a fileset specification'''
1721 if ui.verbose:
1721 if ui.verbose:
1722 tree = fileset.parse(expr)[0]
1722 tree = fileset.parse(expr)[0]
1723 ui.note(tree, "\n")
1723 ui.note(tree, "\n")
1724
1724
1725 for f in fileset.getfileset(repo[None], expr):
1725 for f in fileset.getfileset(repo[None], expr):
1726 ui.write("%s\n" % f)
1726 ui.write("%s\n" % f)
1727
1727
1728 @command('debugfsinfo', [], _('[PATH]'))
1728 @command('debugfsinfo', [], _('[PATH]'))
1729 def debugfsinfo(ui, path = "."):
1729 def debugfsinfo(ui, path = "."):
1730 """show information detected about current filesystem"""
1730 """show information detected about current filesystem"""
1731 util.writefile('.debugfsinfo', '')
1731 util.writefile('.debugfsinfo', '')
1732 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1732 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1733 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1733 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1734 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1734 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1735 and 'yes' or 'no'))
1735 and 'yes' or 'no'))
1736 os.unlink('.debugfsinfo')
1736 os.unlink('.debugfsinfo')
1737
1737
1738 @command('debuggetbundle',
1738 @command('debuggetbundle',
1739 [('H', 'head', [], _('id of head node'), _('ID')),
1739 [('H', 'head', [], _('id of head node'), _('ID')),
1740 ('C', 'common', [], _('id of common node'), _('ID')),
1740 ('C', 'common', [], _('id of common node'), _('ID')),
1741 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1741 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1742 _('REPO FILE [-H|-C ID]...'))
1742 _('REPO FILE [-H|-C ID]...'))
1743 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1743 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1744 """retrieves a bundle from a repo
1744 """retrieves a bundle from a repo
1745
1745
1746 Every ID must be a full-length hex node id string. Saves the bundle to the
1746 Every ID must be a full-length hex node id string. Saves the bundle to the
1747 given file.
1747 given file.
1748 """
1748 """
1749 repo = hg.peer(ui, opts, repopath)
1749 repo = hg.peer(ui, opts, repopath)
1750 if not repo.capable('getbundle'):
1750 if not repo.capable('getbundle'):
1751 raise util.Abort("getbundle() not supported by target repository")
1751 raise util.Abort("getbundle() not supported by target repository")
1752 args = {}
1752 args = {}
1753 if common:
1753 if common:
1754 args['common'] = [bin(s) for s in common]
1754 args['common'] = [bin(s) for s in common]
1755 if head:
1755 if head:
1756 args['heads'] = [bin(s) for s in head]
1756 args['heads'] = [bin(s) for s in head]
1757 bundle = repo.getbundle('debug', **args)
1757 bundle = repo.getbundle('debug', **args)
1758
1758
1759 bundletype = opts.get('type', 'bzip2').lower()
1759 bundletype = opts.get('type', 'bzip2').lower()
1760 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1760 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1761 bundletype = btypes.get(bundletype)
1761 bundletype = btypes.get(bundletype)
1762 if bundletype not in changegroup.bundletypes:
1762 if bundletype not in changegroup.bundletypes:
1763 raise util.Abort(_('unknown bundle type specified with --type'))
1763 raise util.Abort(_('unknown bundle type specified with --type'))
1764 changegroup.writebundle(bundle, bundlepath, bundletype)
1764 changegroup.writebundle(bundle, bundlepath, bundletype)
1765
1765
1766 @command('debugignore', [], '')
1766 @command('debugignore', [], '')
1767 def debugignore(ui, repo, *values, **opts):
1767 def debugignore(ui, repo, *values, **opts):
1768 """display the combined ignore pattern"""
1768 """display the combined ignore pattern"""
1769 ignore = repo.dirstate._ignore
1769 ignore = repo.dirstate._ignore
1770 includepat = getattr(ignore, 'includepat', None)
1770 includepat = getattr(ignore, 'includepat', None)
1771 if includepat is not None:
1771 if includepat is not None:
1772 ui.write("%s\n" % includepat)
1772 ui.write("%s\n" % includepat)
1773 else:
1773 else:
1774 raise util.Abort(_("no ignore patterns found"))
1774 raise util.Abort(_("no ignore patterns found"))
1775
1775
1776 @command('debugindex',
1776 @command('debugindex',
1777 [('c', 'changelog', False, _('open changelog')),
1777 [('c', 'changelog', False, _('open changelog')),
1778 ('m', 'manifest', False, _('open manifest')),
1778 ('m', 'manifest', False, _('open manifest')),
1779 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1779 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1780 _('[-f FORMAT] -c|-m|FILE'))
1780 _('[-f FORMAT] -c|-m|FILE'))
1781 def debugindex(ui, repo, file_ = None, **opts):
1781 def debugindex(ui, repo, file_ = None, **opts):
1782 """dump the contents of an index file"""
1782 """dump the contents of an index file"""
1783 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1783 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1784 format = opts.get('format', 0)
1784 format = opts.get('format', 0)
1785 if format not in (0, 1):
1785 if format not in (0, 1):
1786 raise util.Abort(_("unknown format %d") % format)
1786 raise util.Abort(_("unknown format %d") % format)
1787
1787
1788 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1788 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1789 if generaldelta:
1789 if generaldelta:
1790 basehdr = ' delta'
1790 basehdr = ' delta'
1791 else:
1791 else:
1792 basehdr = ' base'
1792 basehdr = ' base'
1793
1793
1794 if format == 0:
1794 if format == 0:
1795 ui.write(" rev offset length " + basehdr + " linkrev"
1795 ui.write(" rev offset length " + basehdr + " linkrev"
1796 " nodeid p1 p2\n")
1796 " nodeid p1 p2\n")
1797 elif format == 1:
1797 elif format == 1:
1798 ui.write(" rev flag offset length"
1798 ui.write(" rev flag offset length"
1799 " size " + basehdr + " link p1 p2 nodeid\n")
1799 " size " + basehdr + " link p1 p2 nodeid\n")
1800
1800
1801 for i in r:
1801 for i in r:
1802 node = r.node(i)
1802 node = r.node(i)
1803 if generaldelta:
1803 if generaldelta:
1804 base = r.deltaparent(i)
1804 base = r.deltaparent(i)
1805 else:
1805 else:
1806 base = r.chainbase(i)
1806 base = r.chainbase(i)
1807 if format == 0:
1807 if format == 0:
1808 try:
1808 try:
1809 pp = r.parents(node)
1809 pp = r.parents(node)
1810 except:
1810 except:
1811 pp = [nullid, nullid]
1811 pp = [nullid, nullid]
1812 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1812 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1813 i, r.start(i), r.length(i), base, r.linkrev(i),
1813 i, r.start(i), r.length(i), base, r.linkrev(i),
1814 short(node), short(pp[0]), short(pp[1])))
1814 short(node), short(pp[0]), short(pp[1])))
1815 elif format == 1:
1815 elif format == 1:
1816 pr = r.parentrevs(i)
1816 pr = r.parentrevs(i)
1817 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1817 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1818 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1818 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1819 base, r.linkrev(i), pr[0], pr[1], short(node)))
1819 base, r.linkrev(i), pr[0], pr[1], short(node)))
1820
1820
1821 @command('debugindexdot', [], _('FILE'))
1821 @command('debugindexdot', [], _('FILE'))
1822 def debugindexdot(ui, repo, file_):
1822 def debugindexdot(ui, repo, file_):
1823 """dump an index DAG as a graphviz dot file"""
1823 """dump an index DAG as a graphviz dot file"""
1824 r = None
1824 r = None
1825 if repo:
1825 if repo:
1826 filelog = repo.file(file_)
1826 filelog = repo.file(file_)
1827 if len(filelog):
1827 if len(filelog):
1828 r = filelog
1828 r = filelog
1829 if not r:
1829 if not r:
1830 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1830 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1831 ui.write("digraph G {\n")
1831 ui.write("digraph G {\n")
1832 for i in r:
1832 for i in r:
1833 node = r.node(i)
1833 node = r.node(i)
1834 pp = r.parents(node)
1834 pp = r.parents(node)
1835 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1835 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1836 if pp[1] != nullid:
1836 if pp[1] != nullid:
1837 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1837 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1838 ui.write("}\n")
1838 ui.write("}\n")
1839
1839
1840 @command('debuginstall', [], '')
1840 @command('debuginstall', [], '')
1841 def debuginstall(ui):
1841 def debuginstall(ui):
1842 '''test Mercurial installation
1842 '''test Mercurial installation
1843
1843
1844 Returns 0 on success.
1844 Returns 0 on success.
1845 '''
1845 '''
1846
1846
1847 def writetemp(contents):
1847 def writetemp(contents):
1848 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1848 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1849 f = os.fdopen(fd, "wb")
1849 f = os.fdopen(fd, "wb")
1850 f.write(contents)
1850 f.write(contents)
1851 f.close()
1851 f.close()
1852 return name
1852 return name
1853
1853
1854 problems = 0
1854 problems = 0
1855
1855
1856 # encoding
1856 # encoding
1857 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1857 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1858 try:
1858 try:
1859 encoding.fromlocal("test")
1859 encoding.fromlocal("test")
1860 except util.Abort, inst:
1860 except util.Abort, inst:
1861 ui.write(" %s\n" % inst)
1861 ui.write(" %s\n" % inst)
1862 ui.write(_(" (check that your locale is properly set)\n"))
1862 ui.write(_(" (check that your locale is properly set)\n"))
1863 problems += 1
1863 problems += 1
1864
1864
1865 # compiled modules
1865 # compiled modules
1866 ui.status(_("Checking installed modules (%s)...\n")
1866 ui.status(_("Checking installed modules (%s)...\n")
1867 % os.path.dirname(__file__))
1867 % os.path.dirname(__file__))
1868 try:
1868 try:
1869 import bdiff, mpatch, base85, osutil
1869 import bdiff, mpatch, base85, osutil
1870 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1870 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1871 except Exception, inst:
1871 except Exception, inst:
1872 ui.write(" %s\n" % inst)
1872 ui.write(" %s\n" % inst)
1873 ui.write(_(" One or more extensions could not be found"))
1873 ui.write(_(" One or more extensions could not be found"))
1874 ui.write(_(" (check that you compiled the extensions)\n"))
1874 ui.write(_(" (check that you compiled the extensions)\n"))
1875 problems += 1
1875 problems += 1
1876
1876
1877 # templates
1877 # templates
1878 import templater
1878 import templater
1879 p = templater.templatepath()
1879 p = templater.templatepath()
1880 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1880 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1881 try:
1881 try:
1882 templater.templater(templater.templatepath("map-cmdline.default"))
1882 templater.templater(templater.templatepath("map-cmdline.default"))
1883 except Exception, inst:
1883 except Exception, inst:
1884 ui.write(" %s\n" % inst)
1884 ui.write(" %s\n" % inst)
1885 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1885 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1886 problems += 1
1886 problems += 1
1887
1887
1888 # editor
1888 # editor
1889 ui.status(_("Checking commit editor...\n"))
1889 ui.status(_("Checking commit editor...\n"))
1890 editor = ui.geteditor()
1890 editor = ui.geteditor()
1891 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1891 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1892 if not cmdpath:
1892 if not cmdpath:
1893 if editor == 'vi':
1893 if editor == 'vi':
1894 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1894 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1895 ui.write(_(" (specify a commit editor in your configuration"
1895 ui.write(_(" (specify a commit editor in your configuration"
1896 " file)\n"))
1896 " file)\n"))
1897 else:
1897 else:
1898 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1898 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
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 problems += 1
1901 problems += 1
1902
1902
1903 # check username
1903 # check username
1904 ui.status(_("Checking username...\n"))
1904 ui.status(_("Checking username...\n"))
1905 try:
1905 try:
1906 ui.username()
1906 ui.username()
1907 except util.Abort, e:
1907 except util.Abort, e:
1908 ui.write(" %s\n" % e)
1908 ui.write(" %s\n" % e)
1909 ui.write(_(" (specify a username in your configuration file)\n"))
1909 ui.write(_(" (specify a username in your configuration file)\n"))
1910 problems += 1
1910 problems += 1
1911
1911
1912 if not problems:
1912 if not problems:
1913 ui.status(_("No problems detected\n"))
1913 ui.status(_("No problems detected\n"))
1914 else:
1914 else:
1915 ui.write(_("%s problems detected,"
1915 ui.write(_("%s problems detected,"
1916 " please check your install!\n") % problems)
1916 " please check your install!\n") % problems)
1917
1917
1918 return problems
1918 return problems
1919
1919
1920 @command('debugknown', [], _('REPO ID...'))
1920 @command('debugknown', [], _('REPO ID...'))
1921 def debugknown(ui, repopath, *ids, **opts):
1921 def debugknown(ui, repopath, *ids, **opts):
1922 """test whether node ids are known to a repo
1922 """test whether node ids are known to a repo
1923
1923
1924 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1924 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1925 indicating unknown/known.
1925 indicating unknown/known.
1926 """
1926 """
1927 repo = hg.peer(ui, opts, repopath)
1927 repo = hg.peer(ui, opts, repopath)
1928 if not repo.capable('known'):
1928 if not repo.capable('known'):
1929 raise util.Abort("known() not supported by target repository")
1929 raise util.Abort("known() not supported by target repository")
1930 flags = repo.known([bin(s) for s in ids])
1930 flags = repo.known([bin(s) for s in ids])
1931 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1931 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1932
1932
1933 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1933 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1934 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1934 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1935 '''access the pushkey key/value protocol
1935 '''access the pushkey key/value protocol
1936
1936
1937 With two args, list the keys in the given namespace.
1937 With two args, list the keys in the given namespace.
1938
1938
1939 With five args, set a key to new if it currently is set to old.
1939 With five args, set a key to new if it currently is set to old.
1940 Reports success or failure.
1940 Reports success or failure.
1941 '''
1941 '''
1942
1942
1943 target = hg.peer(ui, {}, repopath)
1943 target = hg.peer(ui, {}, repopath)
1944 if keyinfo:
1944 if keyinfo:
1945 key, old, new = keyinfo
1945 key, old, new = keyinfo
1946 r = target.pushkey(namespace, key, old, new)
1946 r = target.pushkey(namespace, key, old, new)
1947 ui.status(str(r) + '\n')
1947 ui.status(str(r) + '\n')
1948 return not r
1948 return not r
1949 else:
1949 else:
1950 for k, v in target.listkeys(namespace).iteritems():
1950 for k, v in target.listkeys(namespace).iteritems():
1951 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1951 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1952 v.encode('string-escape')))
1952 v.encode('string-escape')))
1953
1953
1954 @command('debugrebuildstate',
1954 @command('debugrebuildstate',
1955 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1955 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1956 _('[-r REV] [REV]'))
1956 _('[-r REV] [REV]'))
1957 def debugrebuildstate(ui, repo, rev="tip"):
1957 def debugrebuildstate(ui, repo, rev="tip"):
1958 """rebuild the dirstate as it would look like for the given revision"""
1958 """rebuild the dirstate as it would look like for the given revision"""
1959 ctx = scmutil.revsingle(repo, rev)
1959 ctx = scmutil.revsingle(repo, rev)
1960 wlock = repo.wlock()
1960 wlock = repo.wlock()
1961 try:
1961 try:
1962 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1962 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1963 finally:
1963 finally:
1964 wlock.release()
1964 wlock.release()
1965
1965
1966 @command('debugrename',
1966 @command('debugrename',
1967 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1967 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1968 _('[-r REV] FILE'))
1968 _('[-r REV] FILE'))
1969 def debugrename(ui, repo, file1, *pats, **opts):
1969 def debugrename(ui, repo, file1, *pats, **opts):
1970 """dump rename information"""
1970 """dump rename information"""
1971
1971
1972 ctx = scmutil.revsingle(repo, opts.get('rev'))
1972 ctx = scmutil.revsingle(repo, opts.get('rev'))
1973 m = scmutil.match(ctx, (file1,) + pats, opts)
1973 m = scmutil.match(ctx, (file1,) + pats, opts)
1974 for abs in ctx.walk(m):
1974 for abs in ctx.walk(m):
1975 fctx = ctx[abs]
1975 fctx = ctx[abs]
1976 o = fctx.filelog().renamed(fctx.filenode())
1976 o = fctx.filelog().renamed(fctx.filenode())
1977 rel = m.rel(abs)
1977 rel = m.rel(abs)
1978 if o:
1978 if o:
1979 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1979 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1980 else:
1980 else:
1981 ui.write(_("%s not renamed\n") % rel)
1981 ui.write(_("%s not renamed\n") % rel)
1982
1982
1983 @command('debugrevlog',
1983 @command('debugrevlog',
1984 [('c', 'changelog', False, _('open changelog')),
1984 [('c', 'changelog', False, _('open changelog')),
1985 ('m', 'manifest', False, _('open manifest')),
1985 ('m', 'manifest', False, _('open manifest')),
1986 ('d', 'dump', False, _('dump index data'))],
1986 ('d', 'dump', False, _('dump index data'))],
1987 _('-c|-m|FILE'))
1987 _('-c|-m|FILE'))
1988 def debugrevlog(ui, repo, file_ = None, **opts):
1988 def debugrevlog(ui, repo, file_ = None, **opts):
1989 """show data and statistics about a revlog"""
1989 """show data and statistics about a revlog"""
1990 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1990 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1991
1991
1992 if opts.get("dump"):
1992 if opts.get("dump"):
1993 numrevs = len(r)
1993 numrevs = len(r)
1994 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1994 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1995 " rawsize totalsize compression heads\n")
1995 " rawsize totalsize compression heads\n")
1996 ts = 0
1996 ts = 0
1997 heads = set()
1997 heads = set()
1998 for rev in xrange(numrevs):
1998 for rev in xrange(numrevs):
1999 dbase = r.deltaparent(rev)
1999 dbase = r.deltaparent(rev)
2000 if dbase == -1:
2000 if dbase == -1:
2001 dbase = rev
2001 dbase = rev
2002 cbase = r.chainbase(rev)
2002 cbase = r.chainbase(rev)
2003 p1, p2 = r.parentrevs(rev)
2003 p1, p2 = r.parentrevs(rev)
2004 rs = r.rawsize(rev)
2004 rs = r.rawsize(rev)
2005 ts = ts + rs
2005 ts = ts + rs
2006 heads -= set(r.parentrevs(rev))
2006 heads -= set(r.parentrevs(rev))
2007 heads.add(rev)
2007 heads.add(rev)
2008 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2008 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2009 (rev, p1, p2, r.start(rev), r.end(rev),
2009 (rev, p1, p2, r.start(rev), r.end(rev),
2010 r.start(dbase), r.start(cbase),
2010 r.start(dbase), r.start(cbase),
2011 r.start(p1), r.start(p2),
2011 r.start(p1), r.start(p2),
2012 rs, ts, ts / r.end(rev), len(heads)))
2012 rs, ts, ts / r.end(rev), len(heads)))
2013 return 0
2013 return 0
2014
2014
2015 v = r.version
2015 v = r.version
2016 format = v & 0xFFFF
2016 format = v & 0xFFFF
2017 flags = []
2017 flags = []
2018 gdelta = False
2018 gdelta = False
2019 if v & revlog.REVLOGNGINLINEDATA:
2019 if v & revlog.REVLOGNGINLINEDATA:
2020 flags.append('inline')
2020 flags.append('inline')
2021 if v & revlog.REVLOGGENERALDELTA:
2021 if v & revlog.REVLOGGENERALDELTA:
2022 gdelta = True
2022 gdelta = True
2023 flags.append('generaldelta')
2023 flags.append('generaldelta')
2024 if not flags:
2024 if not flags:
2025 flags = ['(none)']
2025 flags = ['(none)']
2026
2026
2027 nummerges = 0
2027 nummerges = 0
2028 numfull = 0
2028 numfull = 0
2029 numprev = 0
2029 numprev = 0
2030 nump1 = 0
2030 nump1 = 0
2031 nump2 = 0
2031 nump2 = 0
2032 numother = 0
2032 numother = 0
2033 nump1prev = 0
2033 nump1prev = 0
2034 nump2prev = 0
2034 nump2prev = 0
2035 chainlengths = []
2035 chainlengths = []
2036
2036
2037 datasize = [None, 0, 0L]
2037 datasize = [None, 0, 0L]
2038 fullsize = [None, 0, 0L]
2038 fullsize = [None, 0, 0L]
2039 deltasize = [None, 0, 0L]
2039 deltasize = [None, 0, 0L]
2040
2040
2041 def addsize(size, l):
2041 def addsize(size, l):
2042 if l[0] is None or size < l[0]:
2042 if l[0] is None or size < l[0]:
2043 l[0] = size
2043 l[0] = size
2044 if size > l[1]:
2044 if size > l[1]:
2045 l[1] = size
2045 l[1] = size
2046 l[2] += size
2046 l[2] += size
2047
2047
2048 numrevs = len(r)
2048 numrevs = len(r)
2049 for rev in xrange(numrevs):
2049 for rev in xrange(numrevs):
2050 p1, p2 = r.parentrevs(rev)
2050 p1, p2 = r.parentrevs(rev)
2051 delta = r.deltaparent(rev)
2051 delta = r.deltaparent(rev)
2052 if format > 0:
2052 if format > 0:
2053 addsize(r.rawsize(rev), datasize)
2053 addsize(r.rawsize(rev), datasize)
2054 if p2 != nullrev:
2054 if p2 != nullrev:
2055 nummerges += 1
2055 nummerges += 1
2056 size = r.length(rev)
2056 size = r.length(rev)
2057 if delta == nullrev:
2057 if delta == nullrev:
2058 chainlengths.append(0)
2058 chainlengths.append(0)
2059 numfull += 1
2059 numfull += 1
2060 addsize(size, fullsize)
2060 addsize(size, fullsize)
2061 else:
2061 else:
2062 chainlengths.append(chainlengths[delta] + 1)
2062 chainlengths.append(chainlengths[delta] + 1)
2063 addsize(size, deltasize)
2063 addsize(size, deltasize)
2064 if delta == rev - 1:
2064 if delta == rev - 1:
2065 numprev += 1
2065 numprev += 1
2066 if delta == p1:
2066 if delta == p1:
2067 nump1prev += 1
2067 nump1prev += 1
2068 elif delta == p2:
2068 elif delta == p2:
2069 nump2prev += 1
2069 nump2prev += 1
2070 elif delta == p1:
2070 elif delta == p1:
2071 nump1 += 1
2071 nump1 += 1
2072 elif delta == p2:
2072 elif delta == p2:
2073 nump2 += 1
2073 nump2 += 1
2074 elif delta != nullrev:
2074 elif delta != nullrev:
2075 numother += 1
2075 numother += 1
2076
2076
2077 numdeltas = numrevs - numfull
2077 numdeltas = numrevs - numfull
2078 numoprev = numprev - nump1prev - nump2prev
2078 numoprev = numprev - nump1prev - nump2prev
2079 totalrawsize = datasize[2]
2079 totalrawsize = datasize[2]
2080 datasize[2] /= numrevs
2080 datasize[2] /= numrevs
2081 fulltotal = fullsize[2]
2081 fulltotal = fullsize[2]
2082 fullsize[2] /= numfull
2082 fullsize[2] /= numfull
2083 deltatotal = deltasize[2]
2083 deltatotal = deltasize[2]
2084 deltasize[2] /= numrevs - numfull
2084 deltasize[2] /= numrevs - numfull
2085 totalsize = fulltotal + deltatotal
2085 totalsize = fulltotal + deltatotal
2086 avgchainlen = sum(chainlengths) / numrevs
2086 avgchainlen = sum(chainlengths) / numrevs
2087 compratio = totalrawsize / totalsize
2087 compratio = totalrawsize / totalsize
2088
2088
2089 basedfmtstr = '%%%dd\n'
2089 basedfmtstr = '%%%dd\n'
2090 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2090 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2091
2091
2092 def dfmtstr(max):
2092 def dfmtstr(max):
2093 return basedfmtstr % len(str(max))
2093 return basedfmtstr % len(str(max))
2094 def pcfmtstr(max, padding=0):
2094 def pcfmtstr(max, padding=0):
2095 return basepcfmtstr % (len(str(max)), ' ' * padding)
2095 return basepcfmtstr % (len(str(max)), ' ' * padding)
2096
2096
2097 def pcfmt(value, total):
2097 def pcfmt(value, total):
2098 return (value, 100 * float(value) / total)
2098 return (value, 100 * float(value) / total)
2099
2099
2100 ui.write('format : %d\n' % format)
2100 ui.write('format : %d\n' % format)
2101 ui.write('flags : %s\n' % ', '.join(flags))
2101 ui.write('flags : %s\n' % ', '.join(flags))
2102
2102
2103 ui.write('\n')
2103 ui.write('\n')
2104 fmt = pcfmtstr(totalsize)
2104 fmt = pcfmtstr(totalsize)
2105 fmt2 = dfmtstr(totalsize)
2105 fmt2 = dfmtstr(totalsize)
2106 ui.write('revisions : ' + fmt2 % numrevs)
2106 ui.write('revisions : ' + fmt2 % numrevs)
2107 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2107 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2108 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2108 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2109 ui.write('revisions : ' + fmt2 % numrevs)
2109 ui.write('revisions : ' + fmt2 % numrevs)
2110 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2110 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2111 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2111 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2112 ui.write('revision size : ' + fmt2 % totalsize)
2112 ui.write('revision size : ' + fmt2 % totalsize)
2113 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2113 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2114 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2114 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2115
2115
2116 ui.write('\n')
2116 ui.write('\n')
2117 fmt = dfmtstr(max(avgchainlen, compratio))
2117 fmt = dfmtstr(max(avgchainlen, compratio))
2118 ui.write('avg chain length : ' + fmt % avgchainlen)
2118 ui.write('avg chain length : ' + fmt % avgchainlen)
2119 ui.write('compression ratio : ' + fmt % compratio)
2119 ui.write('compression ratio : ' + fmt % compratio)
2120
2120
2121 if format > 0:
2121 if format > 0:
2122 ui.write('\n')
2122 ui.write('\n')
2123 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2123 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2124 % tuple(datasize))
2124 % tuple(datasize))
2125 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2125 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2126 % tuple(fullsize))
2126 % tuple(fullsize))
2127 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2127 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2128 % tuple(deltasize))
2128 % tuple(deltasize))
2129
2129
2130 if numdeltas > 0:
2130 if numdeltas > 0:
2131 ui.write('\n')
2131 ui.write('\n')
2132 fmt = pcfmtstr(numdeltas)
2132 fmt = pcfmtstr(numdeltas)
2133 fmt2 = pcfmtstr(numdeltas, 4)
2133 fmt2 = pcfmtstr(numdeltas, 4)
2134 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2134 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2135 if numprev > 0:
2135 if numprev > 0:
2136 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2136 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2137 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2137 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2138 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2138 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2139 if gdelta:
2139 if gdelta:
2140 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2140 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2141 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2141 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2142 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2142 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2143
2143
2144 @command('debugrevspec', [], ('REVSPEC'))
2144 @command('debugrevspec', [], ('REVSPEC'))
2145 def debugrevspec(ui, repo, expr):
2145 def debugrevspec(ui, repo, expr):
2146 '''parse and apply a revision specification'''
2146 '''parse and apply a revision specification'''
2147 if ui.verbose:
2147 if ui.verbose:
2148 tree = revset.parse(expr)[0]
2148 tree = revset.parse(expr)[0]
2149 ui.note(tree, "\n")
2149 ui.note(tree, "\n")
2150 newtree = revset.findaliases(ui, tree)
2150 newtree = revset.findaliases(ui, tree)
2151 if newtree != tree:
2151 if newtree != tree:
2152 ui.note(newtree, "\n")
2152 ui.note(newtree, "\n")
2153 func = revset.match(ui, expr)
2153 func = revset.match(ui, expr)
2154 for c in func(repo, range(len(repo))):
2154 for c in func(repo, range(len(repo))):
2155 ui.write("%s\n" % c)
2155 ui.write("%s\n" % c)
2156
2156
2157 @command('debugsetparents', [], _('REV1 [REV2]'))
2157 @command('debugsetparents', [], _('REV1 [REV2]'))
2158 def debugsetparents(ui, repo, rev1, rev2=None):
2158 def debugsetparents(ui, repo, rev1, rev2=None):
2159 """manually set the parents of the current working directory
2159 """manually set the parents of the current working directory
2160
2160
2161 This is useful for writing repository conversion tools, but should
2161 This is useful for writing repository conversion tools, but should
2162 be used with care.
2162 be used with care.
2163
2163
2164 Returns 0 on success.
2164 Returns 0 on success.
2165 """
2165 """
2166
2166
2167 r1 = scmutil.revsingle(repo, rev1).node()
2167 r1 = scmutil.revsingle(repo, rev1).node()
2168 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2168 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2169
2169
2170 wlock = repo.wlock()
2170 wlock = repo.wlock()
2171 try:
2171 try:
2172 repo.dirstate.setparents(r1, r2)
2172 repo.dirstate.setparents(r1, r2)
2173 finally:
2173 finally:
2174 wlock.release()
2174 wlock.release()
2175
2175
2176 @command('debugstate',
2176 @command('debugstate',
2177 [('', 'nodates', None, _('do not display the saved mtime')),
2177 [('', 'nodates', None, _('do not display the saved mtime')),
2178 ('', 'datesort', None, _('sort by saved mtime'))],
2178 ('', 'datesort', None, _('sort by saved mtime'))],
2179 _('[OPTION]...'))
2179 _('[OPTION]...'))
2180 def debugstate(ui, repo, nodates=None, datesort=None):
2180 def debugstate(ui, repo, nodates=None, datesort=None):
2181 """show the contents of the current dirstate"""
2181 """show the contents of the current dirstate"""
2182 timestr = ""
2182 timestr = ""
2183 showdate = not nodates
2183 showdate = not nodates
2184 if datesort:
2184 if datesort:
2185 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2185 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2186 else:
2186 else:
2187 keyfunc = None # sort by filename
2187 keyfunc = None # sort by filename
2188 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2188 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2189 if showdate:
2189 if showdate:
2190 if ent[3] == -1:
2190 if ent[3] == -1:
2191 # Pad or slice to locale representation
2191 # Pad or slice to locale representation
2192 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2192 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2193 time.localtime(0)))
2193 time.localtime(0)))
2194 timestr = 'unset'
2194 timestr = 'unset'
2195 timestr = (timestr[:locale_len] +
2195 timestr = (timestr[:locale_len] +
2196 ' ' * (locale_len - len(timestr)))
2196 ' ' * (locale_len - len(timestr)))
2197 else:
2197 else:
2198 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2198 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2199 time.localtime(ent[3]))
2199 time.localtime(ent[3]))
2200 if ent[1] & 020000:
2200 if ent[1] & 020000:
2201 mode = 'lnk'
2201 mode = 'lnk'
2202 else:
2202 else:
2203 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2203 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2204 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2204 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2205 for f in repo.dirstate.copies():
2205 for f in repo.dirstate.copies():
2206 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2206 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2207
2207
2208 @command('debugsub',
2208 @command('debugsub',
2209 [('r', 'rev', '',
2209 [('r', 'rev', '',
2210 _('revision to check'), _('REV'))],
2210 _('revision to check'), _('REV'))],
2211 _('[-r REV] [REV]'))
2211 _('[-r REV] [REV]'))
2212 def debugsub(ui, repo, rev=None):
2212 def debugsub(ui, repo, rev=None):
2213 ctx = scmutil.revsingle(repo, rev, None)
2213 ctx = scmutil.revsingle(repo, rev, None)
2214 for k, v in sorted(ctx.substate.items()):
2214 for k, v in sorted(ctx.substate.items()):
2215 ui.write('path %s\n' % k)
2215 ui.write('path %s\n' % k)
2216 ui.write(' source %s\n' % v[0])
2216 ui.write(' source %s\n' % v[0])
2217 ui.write(' revision %s\n' % v[1])
2217 ui.write(' revision %s\n' % v[1])
2218
2218
2219 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2219 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2220 def debugwalk(ui, repo, *pats, **opts):
2220 def debugwalk(ui, repo, *pats, **opts):
2221 """show how files match on given patterns"""
2221 """show how files match on given patterns"""
2222 m = scmutil.match(repo[None], pats, opts)
2222 m = scmutil.match(repo[None], pats, opts)
2223 items = list(repo.walk(m))
2223 items = list(repo.walk(m))
2224 if not items:
2224 if not items:
2225 return
2225 return
2226 fmt = 'f %%-%ds %%-%ds %%s' % (
2226 fmt = 'f %%-%ds %%-%ds %%s' % (
2227 max([len(abs) for abs in items]),
2227 max([len(abs) for abs in items]),
2228 max([len(m.rel(abs)) for abs in items]))
2228 max([len(m.rel(abs)) for abs in items]))
2229 for abs in items:
2229 for abs in items:
2230 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2230 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2231 ui.write("%s\n" % line.rstrip())
2231 ui.write("%s\n" % line.rstrip())
2232
2232
2233 @command('debugwireargs',
2233 @command('debugwireargs',
2234 [('', 'three', '', 'three'),
2234 [('', 'three', '', 'three'),
2235 ('', 'four', '', 'four'),
2235 ('', 'four', '', 'four'),
2236 ('', 'five', '', 'five'),
2236 ('', 'five', '', 'five'),
2237 ] + remoteopts,
2237 ] + remoteopts,
2238 _('REPO [OPTIONS]... [ONE [TWO]]'))
2238 _('REPO [OPTIONS]... [ONE [TWO]]'))
2239 def debugwireargs(ui, repopath, *vals, **opts):
2239 def debugwireargs(ui, repopath, *vals, **opts):
2240 repo = hg.peer(ui, opts, repopath)
2240 repo = hg.peer(ui, opts, repopath)
2241 for opt in remoteopts:
2241 for opt in remoteopts:
2242 del opts[opt[1]]
2242 del opts[opt[1]]
2243 args = {}
2243 args = {}
2244 for k, v in opts.iteritems():
2244 for k, v in opts.iteritems():
2245 if v:
2245 if v:
2246 args[k] = v
2246 args[k] = v
2247 # run twice to check that we don't mess up the stream for the next command
2247 # run twice to check that we don't mess up the stream for the next command
2248 res1 = repo.debugwireargs(*vals, **args)
2248 res1 = repo.debugwireargs(*vals, **args)
2249 res2 = repo.debugwireargs(*vals, **args)
2249 res2 = repo.debugwireargs(*vals, **args)
2250 ui.write("%s\n" % res1)
2250 ui.write("%s\n" % res1)
2251 if res1 != res2:
2251 if res1 != res2:
2252 ui.warn("%s\n" % res2)
2252 ui.warn("%s\n" % res2)
2253
2253
2254 @command('^diff',
2254 @command('^diff',
2255 [('r', 'rev', [], _('revision'), _('REV')),
2255 [('r', 'rev', [], _('revision'), _('REV')),
2256 ('c', 'change', '', _('change made by revision'), _('REV'))
2256 ('c', 'change', '', _('change made by revision'), _('REV'))
2257 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2257 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2258 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2258 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2259 def diff(ui, repo, *pats, **opts):
2259 def diff(ui, repo, *pats, **opts):
2260 """diff repository (or selected files)
2260 """diff repository (or selected files)
2261
2261
2262 Show differences between revisions for the specified files.
2262 Show differences between revisions for the specified files.
2263
2263
2264 Differences between files are shown using the unified diff format.
2264 Differences between files are shown using the unified diff format.
2265
2265
2266 .. note::
2266 .. note::
2267 diff may generate unexpected results for merges, as it will
2267 diff may generate unexpected results for merges, as it will
2268 default to comparing against the working directory's first
2268 default to comparing against the working directory's first
2269 parent changeset if no revisions are specified.
2269 parent changeset if no revisions are specified.
2270
2270
2271 When two revision arguments are given, then changes are shown
2271 When two revision arguments are given, then changes are shown
2272 between those revisions. If only one revision is specified then
2272 between those revisions. If only one revision is specified then
2273 that revision is compared to the working directory, and, when no
2273 that revision is compared to the working directory, and, when no
2274 revisions are specified, the working directory files are compared
2274 revisions are specified, the working directory files are compared
2275 to its parent.
2275 to its parent.
2276
2276
2277 Alternatively you can specify -c/--change with a revision to see
2277 Alternatively you can specify -c/--change with a revision to see
2278 the changes in that changeset relative to its first parent.
2278 the changes in that changeset relative to its first parent.
2279
2279
2280 Without the -a/--text option, diff will avoid generating diffs of
2280 Without the -a/--text option, diff will avoid generating diffs of
2281 files it detects as binary. With -a, diff will generate a diff
2281 files it detects as binary. With -a, diff will generate a diff
2282 anyway, probably with undesirable results.
2282 anyway, probably with undesirable results.
2283
2283
2284 Use the -g/--git option to generate diffs in the git extended diff
2284 Use the -g/--git option to generate diffs in the git extended diff
2285 format. For more information, read :hg:`help diffs`.
2285 format. For more information, read :hg:`help diffs`.
2286
2286
2287 .. container:: verbose
2287 .. container:: verbose
2288
2288
2289 Examples:
2289 Examples:
2290
2290
2291 - compare a file in the current working directory to its parent::
2291 - compare a file in the current working directory to its parent::
2292
2292
2293 hg diff foo.c
2293 hg diff foo.c
2294
2294
2295 - compare two historical versions of a directory, with rename info::
2295 - compare two historical versions of a directory, with rename info::
2296
2296
2297 hg diff --git -r 1.0:1.2 lib/
2297 hg diff --git -r 1.0:1.2 lib/
2298
2298
2299 - get change stats relative to the last change on some date::
2299 - get change stats relative to the last change on some date::
2300
2300
2301 hg diff --stat -r "date('may 2')"
2301 hg diff --stat -r "date('may 2')"
2302
2302
2303 - diff all newly-added files that contain a keyword::
2303 - diff all newly-added files that contain a keyword::
2304
2304
2305 hg diff "set:added() and grep(GNU)"
2305 hg diff "set:added() and grep(GNU)"
2306
2306
2307 - compare a revision and its parents::
2307 - compare a revision and its parents::
2308
2308
2309 hg diff -c 9353 # compare against first parent
2309 hg diff -c 9353 # compare against first parent
2310 hg diff -r 9353^:9353 # same using revset syntax
2310 hg diff -r 9353^:9353 # same using revset syntax
2311 hg diff -r 9353^2:9353 # compare against the second parent
2311 hg diff -r 9353^2:9353 # compare against the second parent
2312
2312
2313 Returns 0 on success.
2313 Returns 0 on success.
2314 """
2314 """
2315
2315
2316 revs = opts.get('rev')
2316 revs = opts.get('rev')
2317 change = opts.get('change')
2317 change = opts.get('change')
2318 stat = opts.get('stat')
2318 stat = opts.get('stat')
2319 reverse = opts.get('reverse')
2319 reverse = opts.get('reverse')
2320
2320
2321 if revs and change:
2321 if revs and change:
2322 msg = _('cannot specify --rev and --change at the same time')
2322 msg = _('cannot specify --rev and --change at the same time')
2323 raise util.Abort(msg)
2323 raise util.Abort(msg)
2324 elif change:
2324 elif change:
2325 node2 = scmutil.revsingle(repo, change, None).node()
2325 node2 = scmutil.revsingle(repo, change, None).node()
2326 node1 = repo[node2].p1().node()
2326 node1 = repo[node2].p1().node()
2327 else:
2327 else:
2328 node1, node2 = scmutil.revpair(repo, revs)
2328 node1, node2 = scmutil.revpair(repo, revs)
2329
2329
2330 if reverse:
2330 if reverse:
2331 node1, node2 = node2, node1
2331 node1, node2 = node2, node1
2332
2332
2333 diffopts = patch.diffopts(ui, opts)
2333 diffopts = patch.diffopts(ui, opts)
2334 m = scmutil.match(repo[node2], pats, opts)
2334 m = scmutil.match(repo[node2], pats, opts)
2335 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2335 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2336 listsubrepos=opts.get('subrepos'))
2336 listsubrepos=opts.get('subrepos'))
2337
2337
2338 @command('^export',
2338 @command('^export',
2339 [('o', 'output', '',
2339 [('o', 'output', '',
2340 _('print output to file with formatted name'), _('FORMAT')),
2340 _('print output to file with formatted name'), _('FORMAT')),
2341 ('', 'switch-parent', None, _('diff against the second parent')),
2341 ('', 'switch-parent', None, _('diff against the second parent')),
2342 ('r', 'rev', [], _('revisions to export'), _('REV')),
2342 ('r', 'rev', [], _('revisions to export'), _('REV')),
2343 ] + diffopts,
2343 ] + diffopts,
2344 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2344 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2345 def export(ui, repo, *changesets, **opts):
2345 def export(ui, repo, *changesets, **opts):
2346 """dump the header and diffs for one or more changesets
2346 """dump the header and diffs for one or more changesets
2347
2347
2348 Print the changeset header and diffs for one or more revisions.
2348 Print the changeset header and diffs for one or more revisions.
2349
2349
2350 The information shown in the changeset header is: author, date,
2350 The information shown in the changeset header is: author, date,
2351 branch name (if non-default), changeset hash, parent(s) and commit
2351 branch name (if non-default), changeset hash, parent(s) and commit
2352 comment.
2352 comment.
2353
2353
2354 .. note::
2354 .. note::
2355 export may generate unexpected diff output for merge
2355 export may generate unexpected diff output for merge
2356 changesets, as it will compare the merge changeset against its
2356 changesets, as it will compare the merge changeset against its
2357 first parent only.
2357 first parent only.
2358
2358
2359 Output may be to a file, in which case the name of the file is
2359 Output may be to a file, in which case the name of the file is
2360 given using a format string. The formatting rules are as follows:
2360 given using a format string. The formatting rules are as follows:
2361
2361
2362 :``%%``: literal "%" character
2362 :``%%``: literal "%" character
2363 :``%H``: changeset hash (40 hexadecimal digits)
2363 :``%H``: changeset hash (40 hexadecimal digits)
2364 :``%N``: number of patches being generated
2364 :``%N``: number of patches being generated
2365 :``%R``: changeset revision number
2365 :``%R``: changeset revision number
2366 :``%b``: basename of the exporting repository
2366 :``%b``: basename of the exporting repository
2367 :``%h``: short-form changeset hash (12 hexadecimal digits)
2367 :``%h``: short-form changeset hash (12 hexadecimal digits)
2368 :``%m``: first line of the commit message (only alphanumeric characters)
2368 :``%m``: first line of the commit message (only alphanumeric characters)
2369 :``%n``: zero-padded sequence number, starting at 1
2369 :``%n``: zero-padded sequence number, starting at 1
2370 :``%r``: zero-padded changeset revision number
2370 :``%r``: zero-padded changeset revision number
2371
2371
2372 Without the -a/--text option, export will avoid generating diffs
2372 Without the -a/--text option, export will avoid generating diffs
2373 of files it detects as binary. With -a, export will generate a
2373 of files it detects as binary. With -a, export will generate a
2374 diff anyway, probably with undesirable results.
2374 diff anyway, probably with undesirable results.
2375
2375
2376 Use the -g/--git option to generate diffs in the git extended diff
2376 Use the -g/--git option to generate diffs in the git extended diff
2377 format. See :hg:`help diffs` for more information.
2377 format. See :hg:`help diffs` for more information.
2378
2378
2379 With the --switch-parent option, the diff will be against the
2379 With the --switch-parent option, the diff will be against the
2380 second parent. It can be useful to review a merge.
2380 second parent. It can be useful to review a merge.
2381
2381
2382 .. container:: verbose
2382 .. container:: verbose
2383
2383
2384 Examples:
2384 Examples:
2385
2385
2386 - use export and import to transplant a bugfix to the current
2386 - use export and import to transplant a bugfix to the current
2387 branch::
2387 branch::
2388
2388
2389 hg export -r 9353 | hg import -
2389 hg export -r 9353 | hg import -
2390
2390
2391 - export all the changesets between two revisions to a file with
2391 - export all the changesets between two revisions to a file with
2392 rename information::
2392 rename information::
2393
2393
2394 hg export --git -r 123:150 > changes.txt
2394 hg export --git -r 123:150 > changes.txt
2395
2395
2396 - split outgoing changes into a series of patches with
2396 - split outgoing changes into a series of patches with
2397 descriptive names::
2397 descriptive names::
2398
2398
2399 hg export -r "outgoing()" -o "%n-%m.patch"
2399 hg export -r "outgoing()" -o "%n-%m.patch"
2400
2400
2401 Returns 0 on success.
2401 Returns 0 on success.
2402 """
2402 """
2403 changesets += tuple(opts.get('rev', []))
2403 changesets += tuple(opts.get('rev', []))
2404 if not changesets:
2404 if not changesets:
2405 raise util.Abort(_("export requires at least one changeset"))
2405 raise util.Abort(_("export requires at least one changeset"))
2406 revs = scmutil.revrange(repo, changesets)
2406 revs = scmutil.revrange(repo, changesets)
2407 if len(revs) > 1:
2407 if len(revs) > 1:
2408 ui.note(_('exporting patches:\n'))
2408 ui.note(_('exporting patches:\n'))
2409 else:
2409 else:
2410 ui.note(_('exporting patch:\n'))
2410 ui.note(_('exporting patch:\n'))
2411 cmdutil.export(repo, revs, template=opts.get('output'),
2411 cmdutil.export(repo, revs, template=opts.get('output'),
2412 switch_parent=opts.get('switch_parent'),
2412 switch_parent=opts.get('switch_parent'),
2413 opts=patch.diffopts(ui, opts))
2413 opts=patch.diffopts(ui, opts))
2414
2414
2415 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2415 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2416 def forget(ui, repo, *pats, **opts):
2416 def forget(ui, repo, *pats, **opts):
2417 """forget the specified files on the next commit
2417 """forget the specified files on the next commit
2418
2418
2419 Mark the specified files so they will no longer be tracked
2419 Mark the specified files so they will no longer be tracked
2420 after the next commit.
2420 after the next commit.
2421
2421
2422 This only removes files from the current branch, not from the
2422 This only removes files from the current branch, not from the
2423 entire project history, and it does not delete them from the
2423 entire project history, and it does not delete them from the
2424 working directory.
2424 working directory.
2425
2425
2426 To undo a forget before the next commit, see :hg:`add`.
2426 To undo a forget before the next commit, see :hg:`add`.
2427
2427
2428 .. container:: verbose
2428 .. container:: verbose
2429
2429
2430 Examples:
2430 Examples:
2431
2431
2432 - forget newly-added binary files::
2432 - forget newly-added binary files::
2433
2433
2434 hg forget "set:added() and binary()"
2434 hg forget "set:added() and binary()"
2435
2435
2436 - forget files that would be excluded by .hgignore::
2436 - forget files that would be excluded by .hgignore::
2437
2437
2438 hg forget "set:hgignore()"
2438 hg forget "set:hgignore()"
2439
2439
2440 Returns 0 on success.
2440 Returns 0 on success.
2441 """
2441 """
2442
2442
2443 if not pats:
2443 if not pats:
2444 raise util.Abort(_('no files specified'))
2444 raise util.Abort(_('no files specified'))
2445
2445
2446 wctx = repo[None]
2446 wctx = repo[None]
2447 m = scmutil.match(wctx, pats, opts)
2447 m = scmutil.match(wctx, pats, opts)
2448 s = repo.status(match=m, clean=True)
2448 s = repo.status(match=m, clean=True)
2449 forget = sorted(s[0] + s[1] + s[3] + s[6])
2449 forget = sorted(s[0] + s[1] + s[3] + s[6])
2450 subforget = {}
2450 subforget = {}
2451 errs = 0
2451 errs = 0
2452
2452
2453 for subpath in wctx.substate:
2453 for subpath in wctx.substate:
2454 sub = wctx.sub(subpath)
2454 sub = wctx.sub(subpath)
2455 try:
2455 try:
2456 submatch = matchmod.narrowmatcher(subpath, m)
2456 submatch = matchmod.narrowmatcher(subpath, m)
2457 for fsub in sub.walk(submatch):
2457 for fsub in sub.walk(submatch):
2458 if submatch.exact(fsub):
2458 if submatch.exact(fsub):
2459 subforget[subpath + '/' + fsub] = (fsub, sub)
2459 subforget[subpath + '/' + fsub] = (fsub, sub)
2460 except error.LookupError:
2460 except error.LookupError:
2461 ui.status(_("skipping missing subrepository: %s\n") % subpath)
2461 ui.status(_("skipping missing subrepository: %s\n") % subpath)
2462
2462
2463 for f in m.files():
2463 for f in m.files():
2464 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2464 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2465 if f not in subforget:
2465 if f not in subforget:
2466 if os.path.exists(m.rel(f)):
2466 if os.path.exists(m.rel(f)):
2467 ui.warn(_('not removing %s: file is already untracked\n')
2467 ui.warn(_('not removing %s: file is already untracked\n')
2468 % m.rel(f))
2468 % m.rel(f))
2469 errs = 1
2469 errs = 1
2470
2470
2471 for f in forget:
2471 for f in forget:
2472 if ui.verbose or not m.exact(f):
2472 if ui.verbose or not m.exact(f):
2473 ui.status(_('removing %s\n') % m.rel(f))
2473 ui.status(_('removing %s\n') % m.rel(f))
2474
2474
2475 if ui.verbose:
2475 if ui.verbose:
2476 for f in sorted(subforget.keys()):
2476 for f in sorted(subforget.keys()):
2477 ui.status(_('removing %s\n') % m.rel(f))
2477 ui.status(_('removing %s\n') % m.rel(f))
2478
2478
2479 wctx.forget(forget)
2479 wctx.forget(forget)
2480
2480
2481 for f in sorted(subforget.keys()):
2481 for f in sorted(subforget.keys()):
2482 fsub, sub = subforget[f]
2482 fsub, sub = subforget[f]
2483 sub.forget([fsub])
2483 sub.forget([fsub])
2484
2484
2485 return errs
2485 return errs
2486
2486
2487 @command(
2487 @command(
2488 'graft',
2488 'graft',
2489 [('c', 'continue', False, _('resume interrupted graft')),
2489 [('c', 'continue', False, _('resume interrupted graft')),
2490 ('e', 'edit', False, _('invoke editor on commit messages')),
2490 ('e', 'edit', False, _('invoke editor on commit messages')),
2491 ('D', 'currentdate', False,
2491 ('D', 'currentdate', False,
2492 _('record the current date as commit date')),
2492 _('record the current date as commit date')),
2493 ('U', 'currentuser', False,
2493 ('U', 'currentuser', False,
2494 _('record the current user as committer'), _('DATE'))]
2494 _('record the current user as committer'), _('DATE'))]
2495 + commitopts2 + mergetoolopts,
2495 + commitopts2 + mergetoolopts,
2496 _('[OPTION]... REVISION...'))
2496 _('[OPTION]... REVISION...'))
2497 def graft(ui, repo, *revs, **opts):
2497 def graft(ui, repo, *revs, **opts):
2498 '''copy changes from other branches onto the current branch
2498 '''copy changes from other branches onto the current branch
2499
2499
2500 This command uses Mercurial's merge logic to copy individual
2500 This command uses Mercurial's merge logic to copy individual
2501 changes from other branches without merging branches in the
2501 changes from other branches without merging branches in the
2502 history graph. This is sometimes known as 'backporting' or
2502 history graph. This is sometimes known as 'backporting' or
2503 'cherry-picking'. By default, graft will copy user, date, and
2503 'cherry-picking'. By default, graft will copy user, date, and
2504 description from the source changesets.
2504 description from the source changesets.
2505
2505
2506 Changesets that are ancestors of the current revision, that have
2506 Changesets that are ancestors of the current revision, that have
2507 already been grafted, or that are merges will be skipped.
2507 already been grafted, or that are merges will be skipped.
2508
2508
2509 If a graft merge results in conflicts, the graft process is
2509 If a graft merge results in conflicts, the graft process is
2510 aborted so that the current merge can be manually resolved. Once
2510 interrupted so that the current merge can be manually resolved.
2511 all conflicts are addressed, the graft process can be continued
2511 Once all conflicts are addressed, the graft process can be
2512 with the -c/--continue option.
2512 continued with the -c/--continue option.
2513
2513
2514 .. note::
2514 .. note::
2515 The -c/--continue option does not reapply earlier options.
2515 The -c/--continue option does not reapply earlier options.
2516
2516
2517 .. container:: verbose
2517 .. container:: verbose
2518
2518
2519 Examples:
2519 Examples:
2520
2520
2521 - copy a single change to the stable branch and edit its description::
2521 - copy a single change to the stable branch and edit its description::
2522
2522
2523 hg update stable
2523 hg update stable
2524 hg graft --edit 9393
2524 hg graft --edit 9393
2525
2525
2526 - graft a range of changesets with one exception, updating dates::
2526 - graft a range of changesets with one exception, updating dates::
2527
2527
2528 hg graft -D "2085::2093 and not 2091"
2528 hg graft -D "2085::2093 and not 2091"
2529
2529
2530 - continue a graft after resolving conflicts::
2530 - continue a graft after resolving conflicts::
2531
2531
2532 hg graft -c
2532 hg graft -c
2533
2533
2534 - show the source of a grafted changeset::
2534 - show the source of a grafted changeset::
2535
2535
2536 hg log --debug -r tip
2536 hg log --debug -r tip
2537
2537
2538 Returns 0 on successful completion.
2538 Returns 0 on successful completion.
2539 '''
2539 '''
2540
2540
2541 if not opts.get('user') and opts.get('currentuser'):
2541 if not opts.get('user') and opts.get('currentuser'):
2542 opts['user'] = ui.username()
2542 opts['user'] = ui.username()
2543 if not opts.get('date') and opts.get('currentdate'):
2543 if not opts.get('date') and opts.get('currentdate'):
2544 opts['date'] = "%d %d" % util.makedate()
2544 opts['date'] = "%d %d" % util.makedate()
2545
2545
2546 editor = None
2546 editor = None
2547 if opts.get('edit'):
2547 if opts.get('edit'):
2548 editor = cmdutil.commitforceeditor
2548 editor = cmdutil.commitforceeditor
2549
2549
2550 cont = False
2550 cont = False
2551 if opts['continue']:
2551 if opts['continue']:
2552 cont = True
2552 cont = True
2553 if revs:
2553 if revs:
2554 raise util.Abort(_("can't specify --continue and revisions"))
2554 raise util.Abort(_("can't specify --continue and revisions"))
2555 # read in unfinished revisions
2555 # read in unfinished revisions
2556 try:
2556 try:
2557 nodes = repo.opener.read('graftstate').splitlines()
2557 nodes = repo.opener.read('graftstate').splitlines()
2558 revs = [repo[node].rev() for node in nodes]
2558 revs = [repo[node].rev() for node in nodes]
2559 except IOError, inst:
2559 except IOError, inst:
2560 if inst.errno != errno.ENOENT:
2560 if inst.errno != errno.ENOENT:
2561 raise
2561 raise
2562 raise util.Abort(_("no graft state found, can't continue"))
2562 raise util.Abort(_("no graft state found, can't continue"))
2563 else:
2563 else:
2564 cmdutil.bailifchanged(repo)
2564 cmdutil.bailifchanged(repo)
2565 if not revs:
2565 if not revs:
2566 raise util.Abort(_('no revisions specified'))
2566 raise util.Abort(_('no revisions specified'))
2567 revs = scmutil.revrange(repo, revs)
2567 revs = scmutil.revrange(repo, revs)
2568
2568
2569 # check for merges
2569 # check for merges
2570 for rev in repo.revs('%ld and merge()', revs):
2570 for rev in repo.revs('%ld and merge()', revs):
2571 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2571 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2572 revs.remove(rev)
2572 revs.remove(rev)
2573 if not revs:
2573 if not revs:
2574 return -1
2574 return -1
2575
2575
2576 # check for ancestors of dest branch
2576 # check for ancestors of dest branch
2577 for rev in repo.revs('::. and %ld', revs):
2577 for rev in repo.revs('::. and %ld', revs):
2578 ui.warn(_('skipping ancestor revision %s\n') % rev)
2578 ui.warn(_('skipping ancestor revision %s\n') % rev)
2579 revs.remove(rev)
2579 revs.remove(rev)
2580 if not revs:
2580 if not revs:
2581 return -1
2581 return -1
2582
2582
2583 # analyze revs for earlier grafts
2583 # analyze revs for earlier grafts
2584 ids = {}
2584 ids = {}
2585 for ctx in repo.set("%ld", revs):
2585 for ctx in repo.set("%ld", revs):
2586 ids[ctx.hex()] = ctx.rev()
2586 ids[ctx.hex()] = ctx.rev()
2587 n = ctx.extra().get('source')
2587 n = ctx.extra().get('source')
2588 if n:
2588 if n:
2589 ids[n] = ctx.rev()
2589 ids[n] = ctx.rev()
2590
2590
2591 # check ancestors for earlier grafts
2591 # check ancestors for earlier grafts
2592 ui.debug('scanning for duplicate grafts\n')
2592 ui.debug('scanning for duplicate grafts\n')
2593 for ctx in repo.set("::. - ::%ld", revs):
2593 for ctx in repo.set("::. - ::%ld", revs):
2594 n = ctx.extra().get('source')
2594 n = ctx.extra().get('source')
2595 if n in ids:
2595 if n in ids:
2596 r = repo[n].rev()
2596 r = repo[n].rev()
2597 if r in revs:
2597 if r in revs:
2598 ui.warn(_('skipping already grafted revision %s\n') % r)
2598 ui.warn(_('skipping already grafted revision %s\n') % r)
2599 revs.remove(r)
2599 revs.remove(r)
2600 elif ids[n] in revs:
2600 elif ids[n] in revs:
2601 ui.warn(_('skipping already grafted revision %s '
2601 ui.warn(_('skipping already grafted revision %s '
2602 '(same origin %d)\n') % (ids[n], r))
2602 '(same origin %d)\n') % (ids[n], r))
2603 revs.remove(ids[n])
2603 revs.remove(ids[n])
2604 elif ctx.hex() in ids:
2604 elif ctx.hex() in ids:
2605 r = ids[ctx.hex()]
2605 r = ids[ctx.hex()]
2606 ui.warn(_('skipping already grafted revision %s '
2606 ui.warn(_('skipping already grafted revision %s '
2607 '(was grafted from %d)\n') % (r, ctx.rev()))
2607 '(was grafted from %d)\n') % (r, ctx.rev()))
2608 revs.remove(r)
2608 revs.remove(r)
2609 if not revs:
2609 if not revs:
2610 return -1
2610 return -1
2611
2611
2612 for pos, ctx in enumerate(repo.set("%ld", revs)):
2612 for pos, ctx in enumerate(repo.set("%ld", revs)):
2613 current = repo['.']
2613 current = repo['.']
2614 ui.status(_('grafting revision %s\n') % ctx.rev())
2614 ui.status(_('grafting revision %s\n') % ctx.rev())
2615
2615
2616 # we don't merge the first commit when continuing
2616 # we don't merge the first commit when continuing
2617 if not cont:
2617 if not cont:
2618 # perform the graft merge with p1(rev) as 'ancestor'
2618 # perform the graft merge with p1(rev) as 'ancestor'
2619 try:
2619 try:
2620 # ui.forcemerge is an internal variable, do not document
2620 # ui.forcemerge is an internal variable, do not document
2621 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2621 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2622 stats = mergemod.update(repo, ctx.node(), True, True, False,
2622 stats = mergemod.update(repo, ctx.node(), True, True, False,
2623 ctx.p1().node())
2623 ctx.p1().node())
2624 finally:
2624 finally:
2625 ui.setconfig('ui', 'forcemerge', '')
2625 ui.setconfig('ui', 'forcemerge', '')
2626 # drop the second merge parent
2626 # drop the second merge parent
2627 repo.dirstate.setparents(current.node(), nullid)
2627 repo.dirstate.setparents(current.node(), nullid)
2628 repo.dirstate.write()
2628 repo.dirstate.write()
2629 # fix up dirstate for copies and renames
2629 # fix up dirstate for copies and renames
2630 cmdutil.duplicatecopies(repo, ctx.rev(), current.node(), nullid)
2630 cmdutil.duplicatecopies(repo, ctx.rev(), current.node(), nullid)
2631 # report any conflicts
2631 # report any conflicts
2632 if stats and stats[3] > 0:
2632 if stats and stats[3] > 0:
2633 # write out state for --continue
2633 # write out state for --continue
2634 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2634 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2635 repo.opener.write('graftstate', ''.join(nodelines))
2635 repo.opener.write('graftstate', ''.join(nodelines))
2636 raise util.Abort(
2636 raise util.Abort(
2637 _("unresolved conflicts, can't continue"),
2637 _("unresolved conflicts, can't continue"),
2638 hint=_('use hg resolve and hg graft --continue'))
2638 hint=_('use hg resolve and hg graft --continue'))
2639 else:
2639 else:
2640 cont = False
2640 cont = False
2641
2641
2642 # commit
2642 # commit
2643 source = ctx.extra().get('source')
2643 source = ctx.extra().get('source')
2644 if not source:
2644 if not source:
2645 source = ctx.hex()
2645 source = ctx.hex()
2646 extra = {'source': source}
2646 extra = {'source': source}
2647 user = ctx.user()
2647 user = ctx.user()
2648 if opts.get('user'):
2648 if opts.get('user'):
2649 user = opts['user']
2649 user = opts['user']
2650 date = ctx.date()
2650 date = ctx.date()
2651 if opts.get('date'):
2651 if opts.get('date'):
2652 date = opts['date']
2652 date = opts['date']
2653 repo.commit(text=ctx.description(), user=user,
2653 repo.commit(text=ctx.description(), user=user,
2654 date=date, extra=extra, editor=editor)
2654 date=date, extra=extra, editor=editor)
2655
2655
2656 # remove state when we complete successfully
2656 # remove state when we complete successfully
2657 if os.path.exists(repo.join('graftstate')):
2657 if os.path.exists(repo.join('graftstate')):
2658 util.unlinkpath(repo.join('graftstate'))
2658 util.unlinkpath(repo.join('graftstate'))
2659
2659
2660 return 0
2660 return 0
2661
2661
2662 @command('grep',
2662 @command('grep',
2663 [('0', 'print0', None, _('end fields with NUL')),
2663 [('0', 'print0', None, _('end fields with NUL')),
2664 ('', 'all', None, _('print all revisions that match')),
2664 ('', 'all', None, _('print all revisions that match')),
2665 ('a', 'text', None, _('treat all files as text')),
2665 ('a', 'text', None, _('treat all files as text')),
2666 ('f', 'follow', None,
2666 ('f', 'follow', None,
2667 _('follow changeset history,'
2667 _('follow changeset history,'
2668 ' or file history across copies and renames')),
2668 ' or file history across copies and renames')),
2669 ('i', 'ignore-case', None, _('ignore case when matching')),
2669 ('i', 'ignore-case', None, _('ignore case when matching')),
2670 ('l', 'files-with-matches', None,
2670 ('l', 'files-with-matches', None,
2671 _('print only filenames and revisions that match')),
2671 _('print only filenames and revisions that match')),
2672 ('n', 'line-number', None, _('print matching line numbers')),
2672 ('n', 'line-number', None, _('print matching line numbers')),
2673 ('r', 'rev', [],
2673 ('r', 'rev', [],
2674 _('only search files changed within revision range'), _('REV')),
2674 _('only search files changed within revision range'), _('REV')),
2675 ('u', 'user', None, _('list the author (long with -v)')),
2675 ('u', 'user', None, _('list the author (long with -v)')),
2676 ('d', 'date', None, _('list the date (short with -q)')),
2676 ('d', 'date', None, _('list the date (short with -q)')),
2677 ] + walkopts,
2677 ] + walkopts,
2678 _('[OPTION]... PATTERN [FILE]...'))
2678 _('[OPTION]... PATTERN [FILE]...'))
2679 def grep(ui, repo, pattern, *pats, **opts):
2679 def grep(ui, repo, pattern, *pats, **opts):
2680 """search for a pattern in specified files and revisions
2680 """search for a pattern in specified files and revisions
2681
2681
2682 Search revisions of files for a regular expression.
2682 Search revisions of files for a regular expression.
2683
2683
2684 This command behaves differently than Unix grep. It only accepts
2684 This command behaves differently than Unix grep. It only accepts
2685 Python/Perl regexps. It searches repository history, not the
2685 Python/Perl regexps. It searches repository history, not the
2686 working directory. It always prints the revision number in which a
2686 working directory. It always prints the revision number in which a
2687 match appears.
2687 match appears.
2688
2688
2689 By default, grep only prints output for the first revision of a
2689 By default, grep only prints output for the first revision of a
2690 file in which it finds a match. To get it to print every revision
2690 file in which it finds a match. To get it to print every revision
2691 that contains a change in match status ("-" for a match that
2691 that contains a change in match status ("-" for a match that
2692 becomes a non-match, or "+" for a non-match that becomes a match),
2692 becomes a non-match, or "+" for a non-match that becomes a match),
2693 use the --all flag.
2693 use the --all flag.
2694
2694
2695 Returns 0 if a match is found, 1 otherwise.
2695 Returns 0 if a match is found, 1 otherwise.
2696 """
2696 """
2697 reflags = 0
2697 reflags = 0
2698 if opts.get('ignore_case'):
2698 if opts.get('ignore_case'):
2699 reflags |= re.I
2699 reflags |= re.I
2700 try:
2700 try:
2701 regexp = re.compile(pattern, reflags)
2701 regexp = re.compile(pattern, reflags)
2702 except re.error, inst:
2702 except re.error, inst:
2703 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2703 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2704 return 1
2704 return 1
2705 sep, eol = ':', '\n'
2705 sep, eol = ':', '\n'
2706 if opts.get('print0'):
2706 if opts.get('print0'):
2707 sep = eol = '\0'
2707 sep = eol = '\0'
2708
2708
2709 getfile = util.lrucachefunc(repo.file)
2709 getfile = util.lrucachefunc(repo.file)
2710
2710
2711 def matchlines(body):
2711 def matchlines(body):
2712 begin = 0
2712 begin = 0
2713 linenum = 0
2713 linenum = 0
2714 while True:
2714 while True:
2715 match = regexp.search(body, begin)
2715 match = regexp.search(body, begin)
2716 if not match:
2716 if not match:
2717 break
2717 break
2718 mstart, mend = match.span()
2718 mstart, mend = match.span()
2719 linenum += body.count('\n', begin, mstart) + 1
2719 linenum += body.count('\n', begin, mstart) + 1
2720 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2720 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2721 begin = body.find('\n', mend) + 1 or len(body) + 1
2721 begin = body.find('\n', mend) + 1 or len(body) + 1
2722 lend = begin - 1
2722 lend = begin - 1
2723 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2723 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2724
2724
2725 class linestate(object):
2725 class linestate(object):
2726 def __init__(self, line, linenum, colstart, colend):
2726 def __init__(self, line, linenum, colstart, colend):
2727 self.line = line
2727 self.line = line
2728 self.linenum = linenum
2728 self.linenum = linenum
2729 self.colstart = colstart
2729 self.colstart = colstart
2730 self.colend = colend
2730 self.colend = colend
2731
2731
2732 def __hash__(self):
2732 def __hash__(self):
2733 return hash((self.linenum, self.line))
2733 return hash((self.linenum, self.line))
2734
2734
2735 def __eq__(self, other):
2735 def __eq__(self, other):
2736 return self.line == other.line
2736 return self.line == other.line
2737
2737
2738 matches = {}
2738 matches = {}
2739 copies = {}
2739 copies = {}
2740 def grepbody(fn, rev, body):
2740 def grepbody(fn, rev, body):
2741 matches[rev].setdefault(fn, [])
2741 matches[rev].setdefault(fn, [])
2742 m = matches[rev][fn]
2742 m = matches[rev][fn]
2743 for lnum, cstart, cend, line in matchlines(body):
2743 for lnum, cstart, cend, line in matchlines(body):
2744 s = linestate(line, lnum, cstart, cend)
2744 s = linestate(line, lnum, cstart, cend)
2745 m.append(s)
2745 m.append(s)
2746
2746
2747 def difflinestates(a, b):
2747 def difflinestates(a, b):
2748 sm = difflib.SequenceMatcher(None, a, b)
2748 sm = difflib.SequenceMatcher(None, a, b)
2749 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2749 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2750 if tag == 'insert':
2750 if tag == 'insert':
2751 for i in xrange(blo, bhi):
2751 for i in xrange(blo, bhi):
2752 yield ('+', b[i])
2752 yield ('+', b[i])
2753 elif tag == 'delete':
2753 elif tag == 'delete':
2754 for i in xrange(alo, ahi):
2754 for i in xrange(alo, ahi):
2755 yield ('-', a[i])
2755 yield ('-', a[i])
2756 elif tag == 'replace':
2756 elif tag == 'replace':
2757 for i in xrange(alo, ahi):
2757 for i in xrange(alo, ahi):
2758 yield ('-', a[i])
2758 yield ('-', a[i])
2759 for i in xrange(blo, bhi):
2759 for i in xrange(blo, bhi):
2760 yield ('+', b[i])
2760 yield ('+', b[i])
2761
2761
2762 def display(fn, ctx, pstates, states):
2762 def display(fn, ctx, pstates, states):
2763 rev = ctx.rev()
2763 rev = ctx.rev()
2764 datefunc = ui.quiet and util.shortdate or util.datestr
2764 datefunc = ui.quiet and util.shortdate or util.datestr
2765 found = False
2765 found = False
2766 filerevmatches = {}
2766 filerevmatches = {}
2767 def binary():
2767 def binary():
2768 flog = getfile(fn)
2768 flog = getfile(fn)
2769 return util.binary(flog.read(ctx.filenode(fn)))
2769 return util.binary(flog.read(ctx.filenode(fn)))
2770
2770
2771 if opts.get('all'):
2771 if opts.get('all'):
2772 iter = difflinestates(pstates, states)
2772 iter = difflinestates(pstates, states)
2773 else:
2773 else:
2774 iter = [('', l) for l in states]
2774 iter = [('', l) for l in states]
2775 for change, l in iter:
2775 for change, l in iter:
2776 cols = [fn, str(rev)]
2776 cols = [fn, str(rev)]
2777 before, match, after = None, None, None
2777 before, match, after = None, None, None
2778 if opts.get('line_number'):
2778 if opts.get('line_number'):
2779 cols.append(str(l.linenum))
2779 cols.append(str(l.linenum))
2780 if opts.get('all'):
2780 if opts.get('all'):
2781 cols.append(change)
2781 cols.append(change)
2782 if opts.get('user'):
2782 if opts.get('user'):
2783 cols.append(ui.shortuser(ctx.user()))
2783 cols.append(ui.shortuser(ctx.user()))
2784 if opts.get('date'):
2784 if opts.get('date'):
2785 cols.append(datefunc(ctx.date()))
2785 cols.append(datefunc(ctx.date()))
2786 if opts.get('files_with_matches'):
2786 if opts.get('files_with_matches'):
2787 c = (fn, rev)
2787 c = (fn, rev)
2788 if c in filerevmatches:
2788 if c in filerevmatches:
2789 continue
2789 continue
2790 filerevmatches[c] = 1
2790 filerevmatches[c] = 1
2791 else:
2791 else:
2792 before = l.line[:l.colstart]
2792 before = l.line[:l.colstart]
2793 match = l.line[l.colstart:l.colend]
2793 match = l.line[l.colstart:l.colend]
2794 after = l.line[l.colend:]
2794 after = l.line[l.colend:]
2795 ui.write(sep.join(cols))
2795 ui.write(sep.join(cols))
2796 if before is not None:
2796 if before is not None:
2797 if not opts.get('text') and binary():
2797 if not opts.get('text') and binary():
2798 ui.write(sep + " Binary file matches")
2798 ui.write(sep + " Binary file matches")
2799 else:
2799 else:
2800 ui.write(sep + before)
2800 ui.write(sep + before)
2801 ui.write(match, label='grep.match')
2801 ui.write(match, label='grep.match')
2802 ui.write(after)
2802 ui.write(after)
2803 ui.write(eol)
2803 ui.write(eol)
2804 found = True
2804 found = True
2805 return found
2805 return found
2806
2806
2807 skip = {}
2807 skip = {}
2808 revfiles = {}
2808 revfiles = {}
2809 matchfn = scmutil.match(repo[None], pats, opts)
2809 matchfn = scmutil.match(repo[None], pats, opts)
2810 found = False
2810 found = False
2811 follow = opts.get('follow')
2811 follow = opts.get('follow')
2812
2812
2813 def prep(ctx, fns):
2813 def prep(ctx, fns):
2814 rev = ctx.rev()
2814 rev = ctx.rev()
2815 pctx = ctx.p1()
2815 pctx = ctx.p1()
2816 parent = pctx.rev()
2816 parent = pctx.rev()
2817 matches.setdefault(rev, {})
2817 matches.setdefault(rev, {})
2818 matches.setdefault(parent, {})
2818 matches.setdefault(parent, {})
2819 files = revfiles.setdefault(rev, [])
2819 files = revfiles.setdefault(rev, [])
2820 for fn in fns:
2820 for fn in fns:
2821 flog = getfile(fn)
2821 flog = getfile(fn)
2822 try:
2822 try:
2823 fnode = ctx.filenode(fn)
2823 fnode = ctx.filenode(fn)
2824 except error.LookupError:
2824 except error.LookupError:
2825 continue
2825 continue
2826
2826
2827 copied = flog.renamed(fnode)
2827 copied = flog.renamed(fnode)
2828 copy = follow and copied and copied[0]
2828 copy = follow and copied and copied[0]
2829 if copy:
2829 if copy:
2830 copies.setdefault(rev, {})[fn] = copy
2830 copies.setdefault(rev, {})[fn] = copy
2831 if fn in skip:
2831 if fn in skip:
2832 if copy:
2832 if copy:
2833 skip[copy] = True
2833 skip[copy] = True
2834 continue
2834 continue
2835 files.append(fn)
2835 files.append(fn)
2836
2836
2837 if fn not in matches[rev]:
2837 if fn not in matches[rev]:
2838 grepbody(fn, rev, flog.read(fnode))
2838 grepbody(fn, rev, flog.read(fnode))
2839
2839
2840 pfn = copy or fn
2840 pfn = copy or fn
2841 if pfn not in matches[parent]:
2841 if pfn not in matches[parent]:
2842 try:
2842 try:
2843 fnode = pctx.filenode(pfn)
2843 fnode = pctx.filenode(pfn)
2844 grepbody(pfn, parent, flog.read(fnode))
2844 grepbody(pfn, parent, flog.read(fnode))
2845 except error.LookupError:
2845 except error.LookupError:
2846 pass
2846 pass
2847
2847
2848 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2848 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2849 rev = ctx.rev()
2849 rev = ctx.rev()
2850 parent = ctx.p1().rev()
2850 parent = ctx.p1().rev()
2851 for fn in sorted(revfiles.get(rev, [])):
2851 for fn in sorted(revfiles.get(rev, [])):
2852 states = matches[rev][fn]
2852 states = matches[rev][fn]
2853 copy = copies.get(rev, {}).get(fn)
2853 copy = copies.get(rev, {}).get(fn)
2854 if fn in skip:
2854 if fn in skip:
2855 if copy:
2855 if copy:
2856 skip[copy] = True
2856 skip[copy] = True
2857 continue
2857 continue
2858 pstates = matches.get(parent, {}).get(copy or fn, [])
2858 pstates = matches.get(parent, {}).get(copy or fn, [])
2859 if pstates or states:
2859 if pstates or states:
2860 r = display(fn, ctx, pstates, states)
2860 r = display(fn, ctx, pstates, states)
2861 found = found or r
2861 found = found or r
2862 if r and not opts.get('all'):
2862 if r and not opts.get('all'):
2863 skip[fn] = True
2863 skip[fn] = True
2864 if copy:
2864 if copy:
2865 skip[copy] = True
2865 skip[copy] = True
2866 del matches[rev]
2866 del matches[rev]
2867 del revfiles[rev]
2867 del revfiles[rev]
2868
2868
2869 return not found
2869 return not found
2870
2870
2871 @command('heads',
2871 @command('heads',
2872 [('r', 'rev', '',
2872 [('r', 'rev', '',
2873 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2873 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2874 ('t', 'topo', False, _('show topological heads only')),
2874 ('t', 'topo', False, _('show topological heads only')),
2875 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2875 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2876 ('c', 'closed', False, _('show normal and closed branch heads')),
2876 ('c', 'closed', False, _('show normal and closed branch heads')),
2877 ] + templateopts,
2877 ] + templateopts,
2878 _('[-ac] [-r STARTREV] [REV]...'))
2878 _('[-ac] [-r STARTREV] [REV]...'))
2879 def heads(ui, repo, *branchrevs, **opts):
2879 def heads(ui, repo, *branchrevs, **opts):
2880 """show current repository heads or show branch heads
2880 """show current repository heads or show branch heads
2881
2881
2882 With no arguments, show all repository branch heads.
2882 With no arguments, show all repository branch heads.
2883
2883
2884 Repository "heads" are changesets with no child changesets. They are
2884 Repository "heads" are changesets with no child changesets. They are
2885 where development generally takes place and are the usual targets
2885 where development generally takes place and are the usual targets
2886 for update and merge operations. Branch heads are changesets that have
2886 for update and merge operations. Branch heads are changesets that have
2887 no child changeset on the same branch.
2887 no child changeset on the same branch.
2888
2888
2889 If one or more REVs are given, only branch heads on the branches
2889 If one or more REVs are given, only branch heads on the branches
2890 associated with the specified changesets are shown. This means
2890 associated with the specified changesets are shown. This means
2891 that you can use :hg:`heads foo` to see the heads on a branch
2891 that you can use :hg:`heads foo` to see the heads on a branch
2892 named ``foo``.
2892 named ``foo``.
2893
2893
2894 If -c/--closed is specified, also show branch heads marked closed
2894 If -c/--closed is specified, also show branch heads marked closed
2895 (see :hg:`commit --close-branch`).
2895 (see :hg:`commit --close-branch`).
2896
2896
2897 If STARTREV is specified, only those heads that are descendants of
2897 If STARTREV is specified, only those heads that are descendants of
2898 STARTREV will be displayed.
2898 STARTREV will be displayed.
2899
2899
2900 If -t/--topo is specified, named branch mechanics will be ignored and only
2900 If -t/--topo is specified, named branch mechanics will be ignored and only
2901 changesets without children will be shown.
2901 changesets without children will be shown.
2902
2902
2903 Returns 0 if matching heads are found, 1 if not.
2903 Returns 0 if matching heads are found, 1 if not.
2904 """
2904 """
2905
2905
2906 start = None
2906 start = None
2907 if 'rev' in opts:
2907 if 'rev' in opts:
2908 start = scmutil.revsingle(repo, opts['rev'], None).node()
2908 start = scmutil.revsingle(repo, opts['rev'], None).node()
2909
2909
2910 if opts.get('topo'):
2910 if opts.get('topo'):
2911 heads = [repo[h] for h in repo.heads(start)]
2911 heads = [repo[h] for h in repo.heads(start)]
2912 else:
2912 else:
2913 heads = []
2913 heads = []
2914 for branch in repo.branchmap():
2914 for branch in repo.branchmap():
2915 heads += repo.branchheads(branch, start, opts.get('closed'))
2915 heads += repo.branchheads(branch, start, opts.get('closed'))
2916 heads = [repo[h] for h in heads]
2916 heads = [repo[h] for h in heads]
2917
2917
2918 if branchrevs:
2918 if branchrevs:
2919 branches = set(repo[br].branch() for br in branchrevs)
2919 branches = set(repo[br].branch() for br in branchrevs)
2920 heads = [h for h in heads if h.branch() in branches]
2920 heads = [h for h in heads if h.branch() in branches]
2921
2921
2922 if opts.get('active') and branchrevs:
2922 if opts.get('active') and branchrevs:
2923 dagheads = repo.heads(start)
2923 dagheads = repo.heads(start)
2924 heads = [h for h in heads if h.node() in dagheads]
2924 heads = [h for h in heads if h.node() in dagheads]
2925
2925
2926 if branchrevs:
2926 if branchrevs:
2927 haveheads = set(h.branch() for h in heads)
2927 haveheads = set(h.branch() for h in heads)
2928 if branches - haveheads:
2928 if branches - haveheads:
2929 headless = ', '.join(b for b in branches - haveheads)
2929 headless = ', '.join(b for b in branches - haveheads)
2930 msg = _('no open branch heads found on branches %s')
2930 msg = _('no open branch heads found on branches %s')
2931 if opts.get('rev'):
2931 if opts.get('rev'):
2932 msg += _(' (started at %s)' % opts['rev'])
2932 msg += _(' (started at %s)' % opts['rev'])
2933 ui.warn((msg + '\n') % headless)
2933 ui.warn((msg + '\n') % headless)
2934
2934
2935 if not heads:
2935 if not heads:
2936 return 1
2936 return 1
2937
2937
2938 heads = sorted(heads, key=lambda x: -x.rev())
2938 heads = sorted(heads, key=lambda x: -x.rev())
2939 displayer = cmdutil.show_changeset(ui, repo, opts)
2939 displayer = cmdutil.show_changeset(ui, repo, opts)
2940 for ctx in heads:
2940 for ctx in heads:
2941 displayer.show(ctx)
2941 displayer.show(ctx)
2942 displayer.close()
2942 displayer.close()
2943
2943
2944 @command('help',
2944 @command('help',
2945 [('e', 'extension', None, _('show only help for extensions')),
2945 [('e', 'extension', None, _('show only help for extensions')),
2946 ('c', 'command', None, _('show only help for commands'))],
2946 ('c', 'command', None, _('show only help for commands'))],
2947 _('[-ec] [TOPIC]'))
2947 _('[-ec] [TOPIC]'))
2948 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2948 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2949 """show help for a given topic or a help overview
2949 """show help for a given topic or a help overview
2950
2950
2951 With no arguments, print a list of commands with short help messages.
2951 With no arguments, print a list of commands with short help messages.
2952
2952
2953 Given a topic, extension, or command name, print help for that
2953 Given a topic, extension, or command name, print help for that
2954 topic.
2954 topic.
2955
2955
2956 Returns 0 if successful.
2956 Returns 0 if successful.
2957 """
2957 """
2958
2958
2959 textwidth = min(ui.termwidth(), 80) - 2
2959 textwidth = min(ui.termwidth(), 80) - 2
2960
2960
2961 def optrst(options):
2961 def optrst(options):
2962 data = []
2962 data = []
2963 multioccur = False
2963 multioccur = False
2964 for option in options:
2964 for option in options:
2965 if len(option) == 5:
2965 if len(option) == 5:
2966 shortopt, longopt, default, desc, optlabel = option
2966 shortopt, longopt, default, desc, optlabel = option
2967 else:
2967 else:
2968 shortopt, longopt, default, desc = option
2968 shortopt, longopt, default, desc = option
2969 optlabel = _("VALUE") # default label
2969 optlabel = _("VALUE") # default label
2970
2970
2971 if _("DEPRECATED") in desc and not ui.verbose:
2971 if _("DEPRECATED") in desc and not ui.verbose:
2972 continue
2972 continue
2973
2973
2974 so = ''
2974 so = ''
2975 if shortopt:
2975 if shortopt:
2976 so = '-' + shortopt
2976 so = '-' + shortopt
2977 lo = '--' + longopt
2977 lo = '--' + longopt
2978 if default:
2978 if default:
2979 desc += _(" (default: %s)") % default
2979 desc += _(" (default: %s)") % default
2980
2980
2981 if isinstance(default, list):
2981 if isinstance(default, list):
2982 lo += " %s [+]" % optlabel
2982 lo += " %s [+]" % optlabel
2983 multioccur = True
2983 multioccur = True
2984 elif (default is not None) and not isinstance(default, bool):
2984 elif (default is not None) and not isinstance(default, bool):
2985 lo += " %s" % optlabel
2985 lo += " %s" % optlabel
2986
2986
2987 data.append((so, lo, desc))
2987 data.append((so, lo, desc))
2988
2988
2989 rst = minirst.maketable(data, 1)
2989 rst = minirst.maketable(data, 1)
2990
2990
2991 if multioccur:
2991 if multioccur:
2992 rst += _("\n[+] marked option can be specified multiple times\n")
2992 rst += _("\n[+] marked option can be specified multiple times\n")
2993
2993
2994 return rst
2994 return rst
2995
2995
2996 # list all option lists
2996 # list all option lists
2997 def opttext(optlist, width):
2997 def opttext(optlist, width):
2998 rst = ''
2998 rst = ''
2999 if not optlist:
2999 if not optlist:
3000 return ''
3000 return ''
3001
3001
3002 for title, options in optlist:
3002 for title, options in optlist:
3003 rst += '\n%s\n' % title
3003 rst += '\n%s\n' % title
3004 if options:
3004 if options:
3005 rst += "\n"
3005 rst += "\n"
3006 rst += optrst(options)
3006 rst += optrst(options)
3007 rst += '\n'
3007 rst += '\n'
3008
3008
3009 return '\n' + minirst.format(rst, width)
3009 return '\n' + minirst.format(rst, width)
3010
3010
3011 def addglobalopts(optlist, aliases):
3011 def addglobalopts(optlist, aliases):
3012 if ui.quiet:
3012 if ui.quiet:
3013 return []
3013 return []
3014
3014
3015 if ui.verbose:
3015 if ui.verbose:
3016 optlist.append((_("global options:"), globalopts))
3016 optlist.append((_("global options:"), globalopts))
3017 if name == 'shortlist':
3017 if name == 'shortlist':
3018 optlist.append((_('use "hg help" for the full list '
3018 optlist.append((_('use "hg help" for the full list '
3019 'of commands'), ()))
3019 'of commands'), ()))
3020 else:
3020 else:
3021 if name == 'shortlist':
3021 if name == 'shortlist':
3022 msg = _('use "hg help" for the full list of commands '
3022 msg = _('use "hg help" for the full list of commands '
3023 'or "hg -v" for details')
3023 'or "hg -v" for details')
3024 elif name and not full:
3024 elif name and not full:
3025 msg = _('use "hg help %s" to show the full help text' % name)
3025 msg = _('use "hg help %s" to show the full help text' % name)
3026 elif aliases:
3026 elif aliases:
3027 msg = _('use "hg -v help%s" to show builtin aliases and '
3027 msg = _('use "hg -v help%s" to show builtin aliases and '
3028 'global options') % (name and " " + name or "")
3028 'global options') % (name and " " + name or "")
3029 else:
3029 else:
3030 msg = _('use "hg -v help %s" to show more info') % name
3030 msg = _('use "hg -v help %s" to show more info') % name
3031 optlist.append((msg, ()))
3031 optlist.append((msg, ()))
3032
3032
3033 def helpcmd(name):
3033 def helpcmd(name):
3034 try:
3034 try:
3035 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3035 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3036 except error.AmbiguousCommand, inst:
3036 except error.AmbiguousCommand, inst:
3037 # py3k fix: except vars can't be used outside the scope of the
3037 # py3k fix: except vars can't be used outside the scope of the
3038 # except block, nor can be used inside a lambda. python issue4617
3038 # except block, nor can be used inside a lambda. python issue4617
3039 prefix = inst.args[0]
3039 prefix = inst.args[0]
3040 select = lambda c: c.lstrip('^').startswith(prefix)
3040 select = lambda c: c.lstrip('^').startswith(prefix)
3041 helplist(select)
3041 helplist(select)
3042 return
3042 return
3043
3043
3044 # check if it's an invalid alias and display its error if it is
3044 # check if it's an invalid alias and display its error if it is
3045 if getattr(entry[0], 'badalias', False):
3045 if getattr(entry[0], 'badalias', False):
3046 if not unknowncmd:
3046 if not unknowncmd:
3047 entry[0](ui)
3047 entry[0](ui)
3048 return
3048 return
3049
3049
3050 rst = ""
3050 rst = ""
3051
3051
3052 # synopsis
3052 # synopsis
3053 if len(entry) > 2:
3053 if len(entry) > 2:
3054 if entry[2].startswith('hg'):
3054 if entry[2].startswith('hg'):
3055 rst += "%s\n" % entry[2]
3055 rst += "%s\n" % entry[2]
3056 else:
3056 else:
3057 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3057 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3058 else:
3058 else:
3059 rst += 'hg %s\n' % aliases[0]
3059 rst += 'hg %s\n' % aliases[0]
3060
3060
3061 # aliases
3061 # aliases
3062 if full and not ui.quiet and len(aliases) > 1:
3062 if full and not ui.quiet and len(aliases) > 1:
3063 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3063 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3064
3064
3065 # description
3065 # description
3066 doc = gettext(entry[0].__doc__)
3066 doc = gettext(entry[0].__doc__)
3067 if not doc:
3067 if not doc:
3068 doc = _("(no help text available)")
3068 doc = _("(no help text available)")
3069 if util.safehasattr(entry[0], 'definition'): # aliased command
3069 if util.safehasattr(entry[0], 'definition'): # aliased command
3070 if entry[0].definition.startswith('!'): # shell alias
3070 if entry[0].definition.startswith('!'): # shell alias
3071 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3071 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3072 else:
3072 else:
3073 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3073 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3074 if ui.quiet or not full:
3074 if ui.quiet or not full:
3075 doc = doc.splitlines()[0]
3075 doc = doc.splitlines()[0]
3076 rst += "\n" + doc + "\n"
3076 rst += "\n" + doc + "\n"
3077
3077
3078 # check if this command shadows a non-trivial (multi-line)
3078 # check if this command shadows a non-trivial (multi-line)
3079 # extension help text
3079 # extension help text
3080 try:
3080 try:
3081 mod = extensions.find(name)
3081 mod = extensions.find(name)
3082 doc = gettext(mod.__doc__) or ''
3082 doc = gettext(mod.__doc__) or ''
3083 if '\n' in doc.strip():
3083 if '\n' in doc.strip():
3084 msg = _('use "hg help -e %s" to show help for '
3084 msg = _('use "hg help -e %s" to show help for '
3085 'the %s extension') % (name, name)
3085 'the %s extension') % (name, name)
3086 rst += '\n%s\n' % msg
3086 rst += '\n%s\n' % msg
3087 except KeyError:
3087 except KeyError:
3088 pass
3088 pass
3089
3089
3090 # options
3090 # options
3091 if not ui.quiet and entry[1]:
3091 if not ui.quiet and entry[1]:
3092 rst += '\noptions:\n\n'
3092 rst += '\noptions:\n\n'
3093 rst += optrst(entry[1])
3093 rst += optrst(entry[1])
3094
3094
3095 if ui.verbose:
3095 if ui.verbose:
3096 rst += '\nglobal options:\n\n'
3096 rst += '\nglobal options:\n\n'
3097 rst += optrst(globalopts)
3097 rst += optrst(globalopts)
3098
3098
3099 keep = ui.verbose and ['verbose'] or []
3099 keep = ui.verbose and ['verbose'] or []
3100 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3100 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3101 ui.write(formatted)
3101 ui.write(formatted)
3102
3102
3103 if not ui.verbose:
3103 if not ui.verbose:
3104 if not full:
3104 if not full:
3105 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3105 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3106 % name)
3106 % name)
3107 elif not ui.quiet:
3107 elif not ui.quiet:
3108 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3108 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3109
3109
3110
3110
3111 def helplist(select=None):
3111 def helplist(select=None):
3112 # list of commands
3112 # list of commands
3113 if name == "shortlist":
3113 if name == "shortlist":
3114 header = _('basic commands:\n\n')
3114 header = _('basic commands:\n\n')
3115 else:
3115 else:
3116 header = _('list of commands:\n\n')
3116 header = _('list of commands:\n\n')
3117
3117
3118 h = {}
3118 h = {}
3119 cmds = {}
3119 cmds = {}
3120 for c, e in table.iteritems():
3120 for c, e in table.iteritems():
3121 f = c.split("|", 1)[0]
3121 f = c.split("|", 1)[0]
3122 if select and not select(f):
3122 if select and not select(f):
3123 continue
3123 continue
3124 if (not select and name != 'shortlist' and
3124 if (not select and name != 'shortlist' and
3125 e[0].__module__ != __name__):
3125 e[0].__module__ != __name__):
3126 continue
3126 continue
3127 if name == "shortlist" and not f.startswith("^"):
3127 if name == "shortlist" and not f.startswith("^"):
3128 continue
3128 continue
3129 f = f.lstrip("^")
3129 f = f.lstrip("^")
3130 if not ui.debugflag and f.startswith("debug"):
3130 if not ui.debugflag and f.startswith("debug"):
3131 continue
3131 continue
3132 doc = e[0].__doc__
3132 doc = e[0].__doc__
3133 if doc and 'DEPRECATED' in doc and not ui.verbose:
3133 if doc and 'DEPRECATED' in doc and not ui.verbose:
3134 continue
3134 continue
3135 doc = gettext(doc)
3135 doc = gettext(doc)
3136 if not doc:
3136 if not doc:
3137 doc = _("(no help text available)")
3137 doc = _("(no help text available)")
3138 h[f] = doc.splitlines()[0].rstrip()
3138 h[f] = doc.splitlines()[0].rstrip()
3139 cmds[f] = c.lstrip("^")
3139 cmds[f] = c.lstrip("^")
3140
3140
3141 if not h:
3141 if not h:
3142 ui.status(_('no commands defined\n'))
3142 ui.status(_('no commands defined\n'))
3143 return
3143 return
3144
3144
3145 ui.status(header)
3145 ui.status(header)
3146 fns = sorted(h)
3146 fns = sorted(h)
3147 m = max(map(len, fns))
3147 m = max(map(len, fns))
3148 for f in fns:
3148 for f in fns:
3149 if ui.verbose:
3149 if ui.verbose:
3150 commands = cmds[f].replace("|",", ")
3150 commands = cmds[f].replace("|",", ")
3151 ui.write(" %s:\n %s\n"%(commands, h[f]))
3151 ui.write(" %s:\n %s\n"%(commands, h[f]))
3152 else:
3152 else:
3153 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3153 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3154 initindent=' %-*s ' % (m, f),
3154 initindent=' %-*s ' % (m, f),
3155 hangindent=' ' * (m + 4))))
3155 hangindent=' ' * (m + 4))))
3156
3156
3157 if not name:
3157 if not name:
3158 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3158 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3159 if text:
3159 if text:
3160 ui.write("\n%s" % minirst.format(text, textwidth))
3160 ui.write("\n%s" % minirst.format(text, textwidth))
3161
3161
3162 ui.write(_("\nadditional help topics:\n\n"))
3162 ui.write(_("\nadditional help topics:\n\n"))
3163 topics = []
3163 topics = []
3164 for names, header, doc in help.helptable:
3164 for names, header, doc in help.helptable:
3165 topics.append((sorted(names, key=len, reverse=True)[0], header))
3165 topics.append((sorted(names, key=len, reverse=True)[0], header))
3166 topics_len = max([len(s[0]) for s in topics])
3166 topics_len = max([len(s[0]) for s in topics])
3167 for t, desc in topics:
3167 for t, desc in topics:
3168 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3168 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3169
3169
3170 optlist = []
3170 optlist = []
3171 addglobalopts(optlist, True)
3171 addglobalopts(optlist, True)
3172 ui.write(opttext(optlist, textwidth))
3172 ui.write(opttext(optlist, textwidth))
3173
3173
3174 def helptopic(name):
3174 def helptopic(name):
3175 for names, header, doc in help.helptable:
3175 for names, header, doc in help.helptable:
3176 if name in names:
3176 if name in names:
3177 break
3177 break
3178 else:
3178 else:
3179 raise error.UnknownCommand(name)
3179 raise error.UnknownCommand(name)
3180
3180
3181 # description
3181 # description
3182 if not doc:
3182 if not doc:
3183 doc = _("(no help text available)")
3183 doc = _("(no help text available)")
3184 if util.safehasattr(doc, '__call__'):
3184 if util.safehasattr(doc, '__call__'):
3185 doc = doc()
3185 doc = doc()
3186
3186
3187 ui.write("%s\n\n" % header)
3187 ui.write("%s\n\n" % header)
3188 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3188 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3189 try:
3189 try:
3190 cmdutil.findcmd(name, table)
3190 cmdutil.findcmd(name, table)
3191 ui.write(_('\nuse "hg help -c %s" to see help for '
3191 ui.write(_('\nuse "hg help -c %s" to see help for '
3192 'the %s command\n') % (name, name))
3192 'the %s command\n') % (name, name))
3193 except error.UnknownCommand:
3193 except error.UnknownCommand:
3194 pass
3194 pass
3195
3195
3196 def helpext(name):
3196 def helpext(name):
3197 try:
3197 try:
3198 mod = extensions.find(name)
3198 mod = extensions.find(name)
3199 doc = gettext(mod.__doc__) or _('no help text available')
3199 doc = gettext(mod.__doc__) or _('no help text available')
3200 except KeyError:
3200 except KeyError:
3201 mod = None
3201 mod = None
3202 doc = extensions.disabledext(name)
3202 doc = extensions.disabledext(name)
3203 if not doc:
3203 if not doc:
3204 raise error.UnknownCommand(name)
3204 raise error.UnknownCommand(name)
3205
3205
3206 if '\n' not in doc:
3206 if '\n' not in doc:
3207 head, tail = doc, ""
3207 head, tail = doc, ""
3208 else:
3208 else:
3209 head, tail = doc.split('\n', 1)
3209 head, tail = doc.split('\n', 1)
3210 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3210 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3211 if tail:
3211 if tail:
3212 ui.write(minirst.format(tail, textwidth))
3212 ui.write(minirst.format(tail, textwidth))
3213 ui.status('\n')
3213 ui.status('\n')
3214
3214
3215 if mod:
3215 if mod:
3216 try:
3216 try:
3217 ct = mod.cmdtable
3217 ct = mod.cmdtable
3218 except AttributeError:
3218 except AttributeError:
3219 ct = {}
3219 ct = {}
3220 modcmds = set([c.split('|', 1)[0] for c in ct])
3220 modcmds = set([c.split('|', 1)[0] for c in ct])
3221 helplist(modcmds.__contains__)
3221 helplist(modcmds.__contains__)
3222 else:
3222 else:
3223 ui.write(_('use "hg help extensions" for information on enabling '
3223 ui.write(_('use "hg help extensions" for information on enabling '
3224 'extensions\n'))
3224 'extensions\n'))
3225
3225
3226 def helpextcmd(name):
3226 def helpextcmd(name):
3227 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3227 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3228 doc = gettext(mod.__doc__).splitlines()[0]
3228 doc = gettext(mod.__doc__).splitlines()[0]
3229
3229
3230 msg = help.listexts(_("'%s' is provided by the following "
3230 msg = help.listexts(_("'%s' is provided by the following "
3231 "extension:") % cmd, {ext: doc}, indent=4)
3231 "extension:") % cmd, {ext: doc}, indent=4)
3232 ui.write(minirst.format(msg, textwidth))
3232 ui.write(minirst.format(msg, textwidth))
3233 ui.write('\n')
3233 ui.write('\n')
3234 ui.write(_('use "hg help extensions" for information on enabling '
3234 ui.write(_('use "hg help extensions" for information on enabling '
3235 'extensions\n'))
3235 'extensions\n'))
3236
3236
3237 if name and name != 'shortlist':
3237 if name and name != 'shortlist':
3238 i = None
3238 i = None
3239 if unknowncmd:
3239 if unknowncmd:
3240 queries = (helpextcmd,)
3240 queries = (helpextcmd,)
3241 elif opts.get('extension'):
3241 elif opts.get('extension'):
3242 queries = (helpext,)
3242 queries = (helpext,)
3243 elif opts.get('command'):
3243 elif opts.get('command'):
3244 queries = (helpcmd,)
3244 queries = (helpcmd,)
3245 else:
3245 else:
3246 queries = (helptopic, helpcmd, helpext, helpextcmd)
3246 queries = (helptopic, helpcmd, helpext, helpextcmd)
3247 for f in queries:
3247 for f in queries:
3248 try:
3248 try:
3249 f(name)
3249 f(name)
3250 i = None
3250 i = None
3251 break
3251 break
3252 except error.UnknownCommand, inst:
3252 except error.UnknownCommand, inst:
3253 i = inst
3253 i = inst
3254 if i:
3254 if i:
3255 raise i
3255 raise i
3256 else:
3256 else:
3257 # program name
3257 # program name
3258 ui.status(_("Mercurial Distributed SCM\n"))
3258 ui.status(_("Mercurial Distributed SCM\n"))
3259 ui.status('\n')
3259 ui.status('\n')
3260 helplist()
3260 helplist()
3261
3261
3262
3262
3263 @command('identify|id',
3263 @command('identify|id',
3264 [('r', 'rev', '',
3264 [('r', 'rev', '',
3265 _('identify the specified revision'), _('REV')),
3265 _('identify the specified revision'), _('REV')),
3266 ('n', 'num', None, _('show local revision number')),
3266 ('n', 'num', None, _('show local revision number')),
3267 ('i', 'id', None, _('show global revision id')),
3267 ('i', 'id', None, _('show global revision id')),
3268 ('b', 'branch', None, _('show branch')),
3268 ('b', 'branch', None, _('show branch')),
3269 ('t', 'tags', None, _('show tags')),
3269 ('t', 'tags', None, _('show tags')),
3270 ('B', 'bookmarks', None, _('show bookmarks')),
3270 ('B', 'bookmarks', None, _('show bookmarks')),
3271 ] + remoteopts,
3271 ] + remoteopts,
3272 _('[-nibtB] [-r REV] [SOURCE]'))
3272 _('[-nibtB] [-r REV] [SOURCE]'))
3273 def identify(ui, repo, source=None, rev=None,
3273 def identify(ui, repo, source=None, rev=None,
3274 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3274 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3275 """identify the working copy or specified revision
3275 """identify the working copy or specified revision
3276
3276
3277 Print a summary identifying the repository state at REV using one or
3277 Print a summary identifying the repository state at REV using one or
3278 two parent hash identifiers, followed by a "+" if the working
3278 two parent hash identifiers, followed by a "+" if the working
3279 directory has uncommitted changes, the branch name (if not default),
3279 directory has uncommitted changes, the branch name (if not default),
3280 a list of tags, and a list of bookmarks.
3280 a list of tags, and a list of bookmarks.
3281
3281
3282 When REV is not given, print a summary of the current state of the
3282 When REV is not given, print a summary of the current state of the
3283 repository.
3283 repository.
3284
3284
3285 Specifying a path to a repository root or Mercurial bundle will
3285 Specifying a path to a repository root or Mercurial bundle will
3286 cause lookup to operate on that repository/bundle.
3286 cause lookup to operate on that repository/bundle.
3287
3287
3288 .. container:: verbose
3288 .. container:: verbose
3289
3289
3290 Examples:
3290 Examples:
3291
3291
3292 - generate a build identifier for the working directory::
3292 - generate a build identifier for the working directory::
3293
3293
3294 hg id --id > build-id.dat
3294 hg id --id > build-id.dat
3295
3295
3296 - find the revision corresponding to a tag::
3296 - find the revision corresponding to a tag::
3297
3297
3298 hg id -n -r 1.3
3298 hg id -n -r 1.3
3299
3299
3300 - check the most recent revision of a remote repository::
3300 - check the most recent revision of a remote repository::
3301
3301
3302 hg id -r tip http://selenic.com/hg/
3302 hg id -r tip http://selenic.com/hg/
3303
3303
3304 Returns 0 if successful.
3304 Returns 0 if successful.
3305 """
3305 """
3306
3306
3307 if not repo and not source:
3307 if not repo and not source:
3308 raise util.Abort(_("there is no Mercurial repository here "
3308 raise util.Abort(_("there is no Mercurial repository here "
3309 "(.hg not found)"))
3309 "(.hg not found)"))
3310
3310
3311 hexfunc = ui.debugflag and hex or short
3311 hexfunc = ui.debugflag and hex or short
3312 default = not (num or id or branch or tags or bookmarks)
3312 default = not (num or id or branch or tags or bookmarks)
3313 output = []
3313 output = []
3314 revs = []
3314 revs = []
3315
3315
3316 if source:
3316 if source:
3317 source, branches = hg.parseurl(ui.expandpath(source))
3317 source, branches = hg.parseurl(ui.expandpath(source))
3318 repo = hg.peer(ui, opts, source)
3318 repo = hg.peer(ui, opts, source)
3319 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3319 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3320
3320
3321 if not repo.local():
3321 if not repo.local():
3322 if num or branch or tags:
3322 if num or branch or tags:
3323 raise util.Abort(
3323 raise util.Abort(
3324 _("can't query remote revision number, branch, or tags"))
3324 _("can't query remote revision number, branch, or tags"))
3325 if not rev and revs:
3325 if not rev and revs:
3326 rev = revs[0]
3326 rev = revs[0]
3327 if not rev:
3327 if not rev:
3328 rev = "tip"
3328 rev = "tip"
3329
3329
3330 remoterev = repo.lookup(rev)
3330 remoterev = repo.lookup(rev)
3331 if default or id:
3331 if default or id:
3332 output = [hexfunc(remoterev)]
3332 output = [hexfunc(remoterev)]
3333
3333
3334 def getbms():
3334 def getbms():
3335 bms = []
3335 bms = []
3336
3336
3337 if 'bookmarks' in repo.listkeys('namespaces'):
3337 if 'bookmarks' in repo.listkeys('namespaces'):
3338 hexremoterev = hex(remoterev)
3338 hexremoterev = hex(remoterev)
3339 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3339 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3340 if bmr == hexremoterev]
3340 if bmr == hexremoterev]
3341
3341
3342 return bms
3342 return bms
3343
3343
3344 if bookmarks:
3344 if bookmarks:
3345 output.extend(getbms())
3345 output.extend(getbms())
3346 elif default and not ui.quiet:
3346 elif default and not ui.quiet:
3347 # multiple bookmarks for a single parent separated by '/'
3347 # multiple bookmarks for a single parent separated by '/'
3348 bm = '/'.join(getbms())
3348 bm = '/'.join(getbms())
3349 if bm:
3349 if bm:
3350 output.append(bm)
3350 output.append(bm)
3351 else:
3351 else:
3352 if not rev:
3352 if not rev:
3353 ctx = repo[None]
3353 ctx = repo[None]
3354 parents = ctx.parents()
3354 parents = ctx.parents()
3355 changed = ""
3355 changed = ""
3356 if default or id or num:
3356 if default or id or num:
3357 changed = util.any(repo.status()) and "+" or ""
3357 changed = util.any(repo.status()) and "+" or ""
3358 if default or id:
3358 if default or id:
3359 output = ["%s%s" %
3359 output = ["%s%s" %
3360 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3360 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3361 if num:
3361 if num:
3362 output.append("%s%s" %
3362 output.append("%s%s" %
3363 ('+'.join([str(p.rev()) for p in parents]), changed))
3363 ('+'.join([str(p.rev()) for p in parents]), changed))
3364 else:
3364 else:
3365 ctx = scmutil.revsingle(repo, rev)
3365 ctx = scmutil.revsingle(repo, rev)
3366 if default or id:
3366 if default or id:
3367 output = [hexfunc(ctx.node())]
3367 output = [hexfunc(ctx.node())]
3368 if num:
3368 if num:
3369 output.append(str(ctx.rev()))
3369 output.append(str(ctx.rev()))
3370
3370
3371 if default and not ui.quiet:
3371 if default and not ui.quiet:
3372 b = ctx.branch()
3372 b = ctx.branch()
3373 if b != 'default':
3373 if b != 'default':
3374 output.append("(%s)" % b)
3374 output.append("(%s)" % b)
3375
3375
3376 # multiple tags for a single parent separated by '/'
3376 # multiple tags for a single parent separated by '/'
3377 t = '/'.join(ctx.tags())
3377 t = '/'.join(ctx.tags())
3378 if t:
3378 if t:
3379 output.append(t)
3379 output.append(t)
3380
3380
3381 # multiple bookmarks for a single parent separated by '/'
3381 # multiple bookmarks for a single parent separated by '/'
3382 bm = '/'.join(ctx.bookmarks())
3382 bm = '/'.join(ctx.bookmarks())
3383 if bm:
3383 if bm:
3384 output.append(bm)
3384 output.append(bm)
3385 else:
3385 else:
3386 if branch:
3386 if branch:
3387 output.append(ctx.branch())
3387 output.append(ctx.branch())
3388
3388
3389 if tags:
3389 if tags:
3390 output.extend(ctx.tags())
3390 output.extend(ctx.tags())
3391
3391
3392 if bookmarks:
3392 if bookmarks:
3393 output.extend(ctx.bookmarks())
3393 output.extend(ctx.bookmarks())
3394
3394
3395 ui.write("%s\n" % ' '.join(output))
3395 ui.write("%s\n" % ' '.join(output))
3396
3396
3397 @command('import|patch',
3397 @command('import|patch',
3398 [('p', 'strip', 1,
3398 [('p', 'strip', 1,
3399 _('directory strip option for patch. This has the same '
3399 _('directory strip option for patch. This has the same '
3400 'meaning as the corresponding patch option'), _('NUM')),
3400 'meaning as the corresponding patch option'), _('NUM')),
3401 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3401 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3402 ('e', 'edit', False, _('invoke editor on commit messages')),
3402 ('e', 'edit', False, _('invoke editor on commit messages')),
3403 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3403 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3404 ('', 'no-commit', None,
3404 ('', 'no-commit', None,
3405 _("don't commit, just update the working directory")),
3405 _("don't commit, just update the working directory")),
3406 ('', 'bypass', None,
3406 ('', 'bypass', None,
3407 _("apply patch without touching the working directory")),
3407 _("apply patch without touching the working directory")),
3408 ('', 'exact', None,
3408 ('', 'exact', None,
3409 _('apply patch to the nodes from which it was generated')),
3409 _('apply patch to the nodes from which it was generated')),
3410 ('', 'import-branch', None,
3410 ('', 'import-branch', None,
3411 _('use any branch information in patch (implied by --exact)'))] +
3411 _('use any branch information in patch (implied by --exact)'))] +
3412 commitopts + commitopts2 + similarityopts,
3412 commitopts + commitopts2 + similarityopts,
3413 _('[OPTION]... PATCH...'))
3413 _('[OPTION]... PATCH...'))
3414 def import_(ui, repo, patch1=None, *patches, **opts):
3414 def import_(ui, repo, patch1=None, *patches, **opts):
3415 """import an ordered set of patches
3415 """import an ordered set of patches
3416
3416
3417 Import a list of patches and commit them individually (unless
3417 Import a list of patches and commit them individually (unless
3418 --no-commit is specified).
3418 --no-commit is specified).
3419
3419
3420 If there are outstanding changes in the working directory, import
3420 If there are outstanding changes in the working directory, import
3421 will abort unless given the -f/--force flag.
3421 will abort unless given the -f/--force flag.
3422
3422
3423 You can import a patch straight from a mail message. Even patches
3423 You can import a patch straight from a mail message. Even patches
3424 as attachments work (to use the body part, it must have type
3424 as attachments work (to use the body part, it must have type
3425 text/plain or text/x-patch). From and Subject headers of email
3425 text/plain or text/x-patch). From and Subject headers of email
3426 message are used as default committer and commit message. All
3426 message are used as default committer and commit message. All
3427 text/plain body parts before first diff are added to commit
3427 text/plain body parts before first diff are added to commit
3428 message.
3428 message.
3429
3429
3430 If the imported patch was generated by :hg:`export`, user and
3430 If the imported patch was generated by :hg:`export`, user and
3431 description from patch override values from message headers and
3431 description from patch override values from message headers and
3432 body. Values given on command line with -m/--message and -u/--user
3432 body. Values given on command line with -m/--message and -u/--user
3433 override these.
3433 override these.
3434
3434
3435 If --exact is specified, import will set the working directory to
3435 If --exact is specified, import will set the working directory to
3436 the parent of each patch before applying it, and will abort if the
3436 the parent of each patch before applying it, and will abort if the
3437 resulting changeset has a different ID than the one recorded in
3437 resulting changeset has a different ID than the one recorded in
3438 the patch. This may happen due to character set problems or other
3438 the patch. This may happen due to character set problems or other
3439 deficiencies in the text patch format.
3439 deficiencies in the text patch format.
3440
3440
3441 Use --bypass to apply and commit patches directly to the
3441 Use --bypass to apply and commit patches directly to the
3442 repository, not touching the working directory. Without --exact,
3442 repository, not touching the working directory. Without --exact,
3443 patches will be applied on top of the working directory parent
3443 patches will be applied on top of the working directory parent
3444 revision.
3444 revision.
3445
3445
3446 With -s/--similarity, hg will attempt to discover renames and
3446 With -s/--similarity, hg will attempt to discover renames and
3447 copies in the patch in the same way as 'addremove'.
3447 copies in the patch in the same way as 'addremove'.
3448
3448
3449 To read a patch from standard input, use "-" as the patch name. If
3449 To read a patch from standard input, use "-" as the patch name. If
3450 a URL is specified, the patch will be downloaded from it.
3450 a URL is specified, the patch will be downloaded from it.
3451 See :hg:`help dates` for a list of formats valid for -d/--date.
3451 See :hg:`help dates` for a list of formats valid for -d/--date.
3452
3452
3453 .. container:: verbose
3453 .. container:: verbose
3454
3454
3455 Examples:
3455 Examples:
3456
3456
3457 - import a traditional patch from a website and detect renames::
3457 - import a traditional patch from a website and detect renames::
3458
3458
3459 hg import -s 80 http://example.com/bugfix.patch
3459 hg import -s 80 http://example.com/bugfix.patch
3460
3460
3461 - import a changeset from an hgweb server::
3461 - import a changeset from an hgweb server::
3462
3462
3463 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3463 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3464
3464
3465 - import all the patches in an Unix-style mbox::
3465 - import all the patches in an Unix-style mbox::
3466
3466
3467 hg import incoming-patches.mbox
3467 hg import incoming-patches.mbox
3468
3468
3469 - attempt to exactly restore an exported changeset (not always
3469 - attempt to exactly restore an exported changeset (not always
3470 possible)::
3470 possible)::
3471
3471
3472 hg import --exact proposed-fix.patch
3472 hg import --exact proposed-fix.patch
3473
3473
3474 Returns 0 on success.
3474 Returns 0 on success.
3475 """
3475 """
3476
3476
3477 if not patch1:
3477 if not patch1:
3478 raise util.Abort(_('need at least one patch to import'))
3478 raise util.Abort(_('need at least one patch to import'))
3479
3479
3480 patches = (patch1,) + patches
3480 patches = (patch1,) + patches
3481
3481
3482 date = opts.get('date')
3482 date = opts.get('date')
3483 if date:
3483 if date:
3484 opts['date'] = util.parsedate(date)
3484 opts['date'] = util.parsedate(date)
3485
3485
3486 editor = cmdutil.commiteditor
3486 editor = cmdutil.commiteditor
3487 if opts.get('edit'):
3487 if opts.get('edit'):
3488 editor = cmdutil.commitforceeditor
3488 editor = cmdutil.commitforceeditor
3489
3489
3490 update = not opts.get('bypass')
3490 update = not opts.get('bypass')
3491 if not update and opts.get('no_commit'):
3491 if not update and opts.get('no_commit'):
3492 raise util.Abort(_('cannot use --no-commit with --bypass'))
3492 raise util.Abort(_('cannot use --no-commit with --bypass'))
3493 try:
3493 try:
3494 sim = float(opts.get('similarity') or 0)
3494 sim = float(opts.get('similarity') or 0)
3495 except ValueError:
3495 except ValueError:
3496 raise util.Abort(_('similarity must be a number'))
3496 raise util.Abort(_('similarity must be a number'))
3497 if sim < 0 or sim > 100:
3497 if sim < 0 or sim > 100:
3498 raise util.Abort(_('similarity must be between 0 and 100'))
3498 raise util.Abort(_('similarity must be between 0 and 100'))
3499 if sim and not update:
3499 if sim and not update:
3500 raise util.Abort(_('cannot use --similarity with --bypass'))
3500 raise util.Abort(_('cannot use --similarity with --bypass'))
3501
3501
3502 if (opts.get('exact') or not opts.get('force')) and update:
3502 if (opts.get('exact') or not opts.get('force')) and update:
3503 cmdutil.bailifchanged(repo)
3503 cmdutil.bailifchanged(repo)
3504
3504
3505 base = opts["base"]
3505 base = opts["base"]
3506 strip = opts["strip"]
3506 strip = opts["strip"]
3507 wlock = lock = tr = None
3507 wlock = lock = tr = None
3508 msgs = []
3508 msgs = []
3509
3509
3510 def checkexact(repo, n, nodeid):
3510 def checkexact(repo, n, nodeid):
3511 if opts.get('exact') and hex(n) != nodeid:
3511 if opts.get('exact') and hex(n) != nodeid:
3512 repo.rollback()
3512 repo.rollback()
3513 raise util.Abort(_('patch is damaged or loses information'))
3513 raise util.Abort(_('patch is damaged or loses information'))
3514
3514
3515 def tryone(ui, hunk, parents):
3515 def tryone(ui, hunk, parents):
3516 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3516 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3517 patch.extract(ui, hunk)
3517 patch.extract(ui, hunk)
3518
3518
3519 if not tmpname:
3519 if not tmpname:
3520 return (None, None)
3520 return (None, None)
3521 msg = _('applied to working directory')
3521 msg = _('applied to working directory')
3522
3522
3523 try:
3523 try:
3524 cmdline_message = cmdutil.logmessage(ui, opts)
3524 cmdline_message = cmdutil.logmessage(ui, opts)
3525 if cmdline_message:
3525 if cmdline_message:
3526 # pickup the cmdline msg
3526 # pickup the cmdline msg
3527 message = cmdline_message
3527 message = cmdline_message
3528 elif message:
3528 elif message:
3529 # pickup the patch msg
3529 # pickup the patch msg
3530 message = message.strip()
3530 message = message.strip()
3531 else:
3531 else:
3532 # launch the editor
3532 # launch the editor
3533 message = None
3533 message = None
3534 ui.debug('message:\n%s\n' % message)
3534 ui.debug('message:\n%s\n' % message)
3535
3535
3536 if len(parents) == 1:
3536 if len(parents) == 1:
3537 parents.append(repo[nullid])
3537 parents.append(repo[nullid])
3538 if opts.get('exact'):
3538 if opts.get('exact'):
3539 if not nodeid or not p1:
3539 if not nodeid or not p1:
3540 raise util.Abort(_('not a Mercurial patch'))
3540 raise util.Abort(_('not a Mercurial patch'))
3541 p1 = repo[p1]
3541 p1 = repo[p1]
3542 p2 = repo[p2 or nullid]
3542 p2 = repo[p2 or nullid]
3543 elif p2:
3543 elif p2:
3544 try:
3544 try:
3545 p1 = repo[p1]
3545 p1 = repo[p1]
3546 p2 = repo[p2]
3546 p2 = repo[p2]
3547 # Without any options, consider p2 only if the
3547 # Without any options, consider p2 only if the
3548 # patch is being applied on top of the recorded
3548 # patch is being applied on top of the recorded
3549 # first parent.
3549 # first parent.
3550 if p1 != parents[0]:
3550 if p1 != parents[0]:
3551 p1 = parents[0]
3551 p1 = parents[0]
3552 p2 = repo[nullid]
3552 p2 = repo[nullid]
3553 except error.RepoError:
3553 except error.RepoError:
3554 p1, p2 = parents
3554 p1, p2 = parents
3555 else:
3555 else:
3556 p1, p2 = parents
3556 p1, p2 = parents
3557
3557
3558 n = None
3558 n = None
3559 if update:
3559 if update:
3560 if p1 != parents[0]:
3560 if p1 != parents[0]:
3561 hg.clean(repo, p1.node())
3561 hg.clean(repo, p1.node())
3562 if p2 != parents[1]:
3562 if p2 != parents[1]:
3563 repo.dirstate.setparents(p1.node(), p2.node())
3563 repo.dirstate.setparents(p1.node(), p2.node())
3564
3564
3565 if opts.get('exact') or opts.get('import_branch'):
3565 if opts.get('exact') or opts.get('import_branch'):
3566 repo.dirstate.setbranch(branch or 'default')
3566 repo.dirstate.setbranch(branch or 'default')
3567
3567
3568 files = set()
3568 files = set()
3569 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3569 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3570 eolmode=None, similarity=sim / 100.0)
3570 eolmode=None, similarity=sim / 100.0)
3571 files = list(files)
3571 files = list(files)
3572 if opts.get('no_commit'):
3572 if opts.get('no_commit'):
3573 if message:
3573 if message:
3574 msgs.append(message)
3574 msgs.append(message)
3575 else:
3575 else:
3576 if opts.get('exact') or p2:
3576 if opts.get('exact') or p2:
3577 # If you got here, you either use --force and know what
3577 # If you got here, you either use --force and know what
3578 # you are doing or used --exact or a merge patch while
3578 # you are doing or used --exact or a merge patch while
3579 # being updated to its first parent.
3579 # being updated to its first parent.
3580 m = None
3580 m = None
3581 else:
3581 else:
3582 m = scmutil.matchfiles(repo, files or [])
3582 m = scmutil.matchfiles(repo, files or [])
3583 n = repo.commit(message, opts.get('user') or user,
3583 n = repo.commit(message, opts.get('user') or user,
3584 opts.get('date') or date, match=m,
3584 opts.get('date') or date, match=m,
3585 editor=editor)
3585 editor=editor)
3586 checkexact(repo, n, nodeid)
3586 checkexact(repo, n, nodeid)
3587 else:
3587 else:
3588 if opts.get('exact') or opts.get('import_branch'):
3588 if opts.get('exact') or opts.get('import_branch'):
3589 branch = branch or 'default'
3589 branch = branch or 'default'
3590 else:
3590 else:
3591 branch = p1.branch()
3591 branch = p1.branch()
3592 store = patch.filestore()
3592 store = patch.filestore()
3593 try:
3593 try:
3594 files = set()
3594 files = set()
3595 try:
3595 try:
3596 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3596 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3597 files, eolmode=None)
3597 files, eolmode=None)
3598 except patch.PatchError, e:
3598 except patch.PatchError, e:
3599 raise util.Abort(str(e))
3599 raise util.Abort(str(e))
3600 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3600 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3601 message,
3601 message,
3602 opts.get('user') or user,
3602 opts.get('user') or user,
3603 opts.get('date') or date,
3603 opts.get('date') or date,
3604 branch, files, store,
3604 branch, files, store,
3605 editor=cmdutil.commiteditor)
3605 editor=cmdutil.commiteditor)
3606 repo.savecommitmessage(memctx.description())
3606 repo.savecommitmessage(memctx.description())
3607 n = memctx.commit()
3607 n = memctx.commit()
3608 checkexact(repo, n, nodeid)
3608 checkexact(repo, n, nodeid)
3609 finally:
3609 finally:
3610 store.close()
3610 store.close()
3611 if n:
3611 if n:
3612 # i18n: refers to a short changeset id
3612 # i18n: refers to a short changeset id
3613 msg = _('created %s') % short(n)
3613 msg = _('created %s') % short(n)
3614 return (msg, n)
3614 return (msg, n)
3615 finally:
3615 finally:
3616 os.unlink(tmpname)
3616 os.unlink(tmpname)
3617
3617
3618 try:
3618 try:
3619 try:
3619 try:
3620 wlock = repo.wlock()
3620 wlock = repo.wlock()
3621 lock = repo.lock()
3621 lock = repo.lock()
3622 tr = repo.transaction('import')
3622 tr = repo.transaction('import')
3623 parents = repo.parents()
3623 parents = repo.parents()
3624 for patchurl in patches:
3624 for patchurl in patches:
3625 if patchurl == '-':
3625 if patchurl == '-':
3626 ui.status(_('applying patch from stdin\n'))
3626 ui.status(_('applying patch from stdin\n'))
3627 patchfile = ui.fin
3627 patchfile = ui.fin
3628 patchurl = 'stdin' # for error message
3628 patchurl = 'stdin' # for error message
3629 else:
3629 else:
3630 patchurl = os.path.join(base, patchurl)
3630 patchurl = os.path.join(base, patchurl)
3631 ui.status(_('applying %s\n') % patchurl)
3631 ui.status(_('applying %s\n') % patchurl)
3632 patchfile = url.open(ui, patchurl)
3632 patchfile = url.open(ui, patchurl)
3633
3633
3634 haspatch = False
3634 haspatch = False
3635 for hunk in patch.split(patchfile):
3635 for hunk in patch.split(patchfile):
3636 (msg, node) = tryone(ui, hunk, parents)
3636 (msg, node) = tryone(ui, hunk, parents)
3637 if msg:
3637 if msg:
3638 haspatch = True
3638 haspatch = True
3639 ui.note(msg + '\n')
3639 ui.note(msg + '\n')
3640 if update or opts.get('exact'):
3640 if update or opts.get('exact'):
3641 parents = repo.parents()
3641 parents = repo.parents()
3642 else:
3642 else:
3643 parents = [repo[node]]
3643 parents = [repo[node]]
3644
3644
3645 if not haspatch:
3645 if not haspatch:
3646 raise util.Abort(_('%s: no diffs found') % patchurl)
3646 raise util.Abort(_('%s: no diffs found') % patchurl)
3647
3647
3648 tr.close()
3648 tr.close()
3649 if msgs:
3649 if msgs:
3650 repo.savecommitmessage('\n* * *\n'.join(msgs))
3650 repo.savecommitmessage('\n* * *\n'.join(msgs))
3651 except:
3651 except:
3652 # wlock.release() indirectly calls dirstate.write(): since
3652 # wlock.release() indirectly calls dirstate.write(): since
3653 # we're crashing, we do not want to change the working dir
3653 # we're crashing, we do not want to change the working dir
3654 # parent after all, so make sure it writes nothing
3654 # parent after all, so make sure it writes nothing
3655 repo.dirstate.invalidate()
3655 repo.dirstate.invalidate()
3656 raise
3656 raise
3657 finally:
3657 finally:
3658 if tr:
3658 if tr:
3659 tr.release()
3659 tr.release()
3660 release(lock, wlock)
3660 release(lock, wlock)
3661
3661
3662 @command('incoming|in',
3662 @command('incoming|in',
3663 [('f', 'force', None,
3663 [('f', 'force', None,
3664 _('run even if remote repository is unrelated')),
3664 _('run even if remote repository is unrelated')),
3665 ('n', 'newest-first', None, _('show newest record first')),
3665 ('n', 'newest-first', None, _('show newest record first')),
3666 ('', 'bundle', '',
3666 ('', 'bundle', '',
3667 _('file to store the bundles into'), _('FILE')),
3667 _('file to store the bundles into'), _('FILE')),
3668 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3668 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3669 ('B', 'bookmarks', False, _("compare bookmarks")),
3669 ('B', 'bookmarks', False, _("compare bookmarks")),
3670 ('b', 'branch', [],
3670 ('b', 'branch', [],
3671 _('a specific branch you would like to pull'), _('BRANCH')),
3671 _('a specific branch you would like to pull'), _('BRANCH')),
3672 ] + logopts + remoteopts + subrepoopts,
3672 ] + logopts + remoteopts + subrepoopts,
3673 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3673 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3674 def incoming(ui, repo, source="default", **opts):
3674 def incoming(ui, repo, source="default", **opts):
3675 """show new changesets found in source
3675 """show new changesets found in source
3676
3676
3677 Show new changesets found in the specified path/URL or the default
3677 Show new changesets found in the specified path/URL or the default
3678 pull location. These are the changesets that would have been pulled
3678 pull location. These are the changesets that would have been pulled
3679 if a pull at the time you issued this command.
3679 if a pull at the time you issued this command.
3680
3680
3681 For remote repository, using --bundle avoids downloading the
3681 For remote repository, using --bundle avoids downloading the
3682 changesets twice if the incoming is followed by a pull.
3682 changesets twice if the incoming is followed by a pull.
3683
3683
3684 See pull for valid source format details.
3684 See pull for valid source format details.
3685
3685
3686 Returns 0 if there are incoming changes, 1 otherwise.
3686 Returns 0 if there are incoming changes, 1 otherwise.
3687 """
3687 """
3688 if opts.get('bundle') and opts.get('subrepos'):
3688 if opts.get('bundle') and opts.get('subrepos'):
3689 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3689 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3690
3690
3691 if opts.get('bookmarks'):
3691 if opts.get('bookmarks'):
3692 source, branches = hg.parseurl(ui.expandpath(source),
3692 source, branches = hg.parseurl(ui.expandpath(source),
3693 opts.get('branch'))
3693 opts.get('branch'))
3694 other = hg.peer(repo, opts, source)
3694 other = hg.peer(repo, opts, source)
3695 if 'bookmarks' not in other.listkeys('namespaces'):
3695 if 'bookmarks' not in other.listkeys('namespaces'):
3696 ui.warn(_("remote doesn't support bookmarks\n"))
3696 ui.warn(_("remote doesn't support bookmarks\n"))
3697 return 0
3697 return 0
3698 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3698 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3699 return bookmarks.diff(ui, repo, other)
3699 return bookmarks.diff(ui, repo, other)
3700
3700
3701 repo._subtoppath = ui.expandpath(source)
3701 repo._subtoppath = ui.expandpath(source)
3702 try:
3702 try:
3703 return hg.incoming(ui, repo, source, opts)
3703 return hg.incoming(ui, repo, source, opts)
3704 finally:
3704 finally:
3705 del repo._subtoppath
3705 del repo._subtoppath
3706
3706
3707
3707
3708 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3708 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3709 def init(ui, dest=".", **opts):
3709 def init(ui, dest=".", **opts):
3710 """create a new repository in the given directory
3710 """create a new repository in the given directory
3711
3711
3712 Initialize a new repository in the given directory. If the given
3712 Initialize a new repository in the given directory. If the given
3713 directory does not exist, it will be created.
3713 directory does not exist, it will be created.
3714
3714
3715 If no directory is given, the current directory is used.
3715 If no directory is given, the current directory is used.
3716
3716
3717 It is possible to specify an ``ssh://`` URL as the destination.
3717 It is possible to specify an ``ssh://`` URL as the destination.
3718 See :hg:`help urls` for more information.
3718 See :hg:`help urls` for more information.
3719
3719
3720 Returns 0 on success.
3720 Returns 0 on success.
3721 """
3721 """
3722 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3722 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3723
3723
3724 @command('locate',
3724 @command('locate',
3725 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3725 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3726 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3726 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3727 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3727 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3728 ] + walkopts,
3728 ] + walkopts,
3729 _('[OPTION]... [PATTERN]...'))
3729 _('[OPTION]... [PATTERN]...'))
3730 def locate(ui, repo, *pats, **opts):
3730 def locate(ui, repo, *pats, **opts):
3731 """locate files matching specific patterns
3731 """locate files matching specific patterns
3732
3732
3733 Print files under Mercurial control in the working directory whose
3733 Print files under Mercurial control in the working directory whose
3734 names match the given patterns.
3734 names match the given patterns.
3735
3735
3736 By default, this command searches all directories in the working
3736 By default, this command searches all directories in the working
3737 directory. To search just the current directory and its
3737 directory. To search just the current directory and its
3738 subdirectories, use "--include .".
3738 subdirectories, use "--include .".
3739
3739
3740 If no patterns are given to match, this command prints the names
3740 If no patterns are given to match, this command prints the names
3741 of all files under Mercurial control in the working directory.
3741 of all files under Mercurial control in the working directory.
3742
3742
3743 If you want to feed the output of this command into the "xargs"
3743 If you want to feed the output of this command into the "xargs"
3744 command, use the -0 option to both this command and "xargs". This
3744 command, use the -0 option to both this command and "xargs". This
3745 will avoid the problem of "xargs" treating single filenames that
3745 will avoid the problem of "xargs" treating single filenames that
3746 contain whitespace as multiple filenames.
3746 contain whitespace as multiple filenames.
3747
3747
3748 Returns 0 if a match is found, 1 otherwise.
3748 Returns 0 if a match is found, 1 otherwise.
3749 """
3749 """
3750 end = opts.get('print0') and '\0' or '\n'
3750 end = opts.get('print0') and '\0' or '\n'
3751 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3751 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3752
3752
3753 ret = 1
3753 ret = 1
3754 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3754 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3755 m.bad = lambda x, y: False
3755 m.bad = lambda x, y: False
3756 for abs in repo[rev].walk(m):
3756 for abs in repo[rev].walk(m):
3757 if not rev and abs not in repo.dirstate:
3757 if not rev and abs not in repo.dirstate:
3758 continue
3758 continue
3759 if opts.get('fullpath'):
3759 if opts.get('fullpath'):
3760 ui.write(repo.wjoin(abs), end)
3760 ui.write(repo.wjoin(abs), end)
3761 else:
3761 else:
3762 ui.write(((pats and m.rel(abs)) or abs), end)
3762 ui.write(((pats and m.rel(abs)) or abs), end)
3763 ret = 0
3763 ret = 0
3764
3764
3765 return ret
3765 return ret
3766
3766
3767 @command('^log|history',
3767 @command('^log|history',
3768 [('f', 'follow', None,
3768 [('f', 'follow', None,
3769 _('follow changeset history, or file history across copies and renames')),
3769 _('follow changeset history, or file history across copies and renames')),
3770 ('', 'follow-first', None,
3770 ('', 'follow-first', None,
3771 _('only follow the first parent of merge changesets (DEPRECATED)')),
3771 _('only follow the first parent of merge changesets (DEPRECATED)')),
3772 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3772 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3773 ('C', 'copies', None, _('show copied files')),
3773 ('C', 'copies', None, _('show copied files')),
3774 ('k', 'keyword', [],
3774 ('k', 'keyword', [],
3775 _('do case-insensitive search for a given text'), _('TEXT')),
3775 _('do case-insensitive search for a given text'), _('TEXT')),
3776 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3776 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3777 ('', 'removed', None, _('include revisions where files were removed')),
3777 ('', 'removed', None, _('include revisions where files were removed')),
3778 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3778 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3779 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3779 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3780 ('', 'only-branch', [],
3780 ('', 'only-branch', [],
3781 _('show only changesets within the given named branch (DEPRECATED)'),
3781 _('show only changesets within the given named branch (DEPRECATED)'),
3782 _('BRANCH')),
3782 _('BRANCH')),
3783 ('b', 'branch', [],
3783 ('b', 'branch', [],
3784 _('show changesets within the given named branch'), _('BRANCH')),
3784 _('show changesets within the given named branch'), _('BRANCH')),
3785 ('P', 'prune', [],
3785 ('P', 'prune', [],
3786 _('do not display revision or any of its ancestors'), _('REV')),
3786 _('do not display revision or any of its ancestors'), _('REV')),
3787 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3787 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3788 ] + logopts + walkopts,
3788 ] + logopts + walkopts,
3789 _('[OPTION]... [FILE]'))
3789 _('[OPTION]... [FILE]'))
3790 def log(ui, repo, *pats, **opts):
3790 def log(ui, repo, *pats, **opts):
3791 """show revision history of entire repository or files
3791 """show revision history of entire repository or files
3792
3792
3793 Print the revision history of the specified files or the entire
3793 Print the revision history of the specified files or the entire
3794 project.
3794 project.
3795
3795
3796 If no revision range is specified, the default is ``tip:0`` unless
3796 If no revision range is specified, the default is ``tip:0`` unless
3797 --follow is set, in which case the working directory parent is
3797 --follow is set, in which case the working directory parent is
3798 used as the starting revision.
3798 used as the starting revision.
3799
3799
3800 File history is shown without following rename or copy history of
3800 File history is shown without following rename or copy history of
3801 files. Use -f/--follow with a filename to follow history across
3801 files. Use -f/--follow with a filename to follow history across
3802 renames and copies. --follow without a filename will only show
3802 renames and copies. --follow without a filename will only show
3803 ancestors or descendants of the starting revision.
3803 ancestors or descendants of the starting revision.
3804
3804
3805 By default this command prints revision number and changeset id,
3805 By default this command prints revision number and changeset id,
3806 tags, non-trivial parents, user, date and time, and a summary for
3806 tags, non-trivial parents, user, date and time, and a summary for
3807 each commit. When the -v/--verbose switch is used, the list of
3807 each commit. When the -v/--verbose switch is used, the list of
3808 changed files and full commit message are shown.
3808 changed files and full commit message are shown.
3809
3809
3810 .. note::
3810 .. note::
3811 log -p/--patch may generate unexpected diff output for merge
3811 log -p/--patch may generate unexpected diff output for merge
3812 changesets, as it will only compare the merge changeset against
3812 changesets, as it will only compare the merge changeset against
3813 its first parent. Also, only files different from BOTH parents
3813 its first parent. Also, only files different from BOTH parents
3814 will appear in files:.
3814 will appear in files:.
3815
3815
3816 .. note::
3816 .. note::
3817 for performance reasons, log FILE may omit duplicate changes
3817 for performance reasons, log FILE may omit duplicate changes
3818 made on branches and will not show deletions. To see all
3818 made on branches and will not show deletions. To see all
3819 changes including duplicates and deletions, use the --removed
3819 changes including duplicates and deletions, use the --removed
3820 switch.
3820 switch.
3821
3821
3822 .. container:: verbose
3822 .. container:: verbose
3823
3823
3824 Some examples:
3824 Some examples:
3825
3825
3826 - changesets with full descriptions and file lists::
3826 - changesets with full descriptions and file lists::
3827
3827
3828 hg log -v
3828 hg log -v
3829
3829
3830 - changesets ancestral to the working directory::
3830 - changesets ancestral to the working directory::
3831
3831
3832 hg log -f
3832 hg log -f
3833
3833
3834 - last 10 commits on the current branch::
3834 - last 10 commits on the current branch::
3835
3835
3836 hg log -l 10 -b .
3836 hg log -l 10 -b .
3837
3837
3838 - changesets showing all modifications of a file, including removals::
3838 - changesets showing all modifications of a file, including removals::
3839
3839
3840 hg log --removed file.c
3840 hg log --removed file.c
3841
3841
3842 - all changesets that touch a directory, with diffs, excluding merges::
3842 - all changesets that touch a directory, with diffs, excluding merges::
3843
3843
3844 hg log -Mp lib/
3844 hg log -Mp lib/
3845
3845
3846 - all revision numbers that match a keyword::
3846 - all revision numbers that match a keyword::
3847
3847
3848 hg log -k bug --template "{rev}\\n"
3848 hg log -k bug --template "{rev}\\n"
3849
3849
3850 - check if a given changeset is included is a tagged release::
3850 - check if a given changeset is included is a tagged release::
3851
3851
3852 hg log -r "a21ccf and ancestor(1.9)"
3852 hg log -r "a21ccf and ancestor(1.9)"
3853
3853
3854 - find all changesets by some user in a date range::
3854 - find all changesets by some user in a date range::
3855
3855
3856 hg log -k alice -d "may 2008 to jul 2008"
3856 hg log -k alice -d "may 2008 to jul 2008"
3857
3857
3858 - summary of all changesets after the last tag::
3858 - summary of all changesets after the last tag::
3859
3859
3860 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3860 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3861
3861
3862 See :hg:`help dates` for a list of formats valid for -d/--date.
3862 See :hg:`help dates` for a list of formats valid for -d/--date.
3863
3863
3864 See :hg:`help revisions` and :hg:`help revsets` for more about
3864 See :hg:`help revisions` and :hg:`help revsets` for more about
3865 specifying revisions.
3865 specifying revisions.
3866
3866
3867 Returns 0 on success.
3867 Returns 0 on success.
3868 """
3868 """
3869
3869
3870 matchfn = scmutil.match(repo[None], pats, opts)
3870 matchfn = scmutil.match(repo[None], pats, opts)
3871 limit = cmdutil.loglimit(opts)
3871 limit = cmdutil.loglimit(opts)
3872 count = 0
3872 count = 0
3873
3873
3874 endrev = None
3874 endrev = None
3875 if opts.get('copies') and opts.get('rev'):
3875 if opts.get('copies') and opts.get('rev'):
3876 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3876 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3877
3877
3878 df = False
3878 df = False
3879 if opts["date"]:
3879 if opts["date"]:
3880 df = util.matchdate(opts["date"])
3880 df = util.matchdate(opts["date"])
3881
3881
3882 branches = opts.get('branch', []) + opts.get('only_branch', [])
3882 branches = opts.get('branch', []) + opts.get('only_branch', [])
3883 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3883 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3884
3884
3885 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3885 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3886 def prep(ctx, fns):
3886 def prep(ctx, fns):
3887 rev = ctx.rev()
3887 rev = ctx.rev()
3888 parents = [p for p in repo.changelog.parentrevs(rev)
3888 parents = [p for p in repo.changelog.parentrevs(rev)
3889 if p != nullrev]
3889 if p != nullrev]
3890 if opts.get('no_merges') and len(parents) == 2:
3890 if opts.get('no_merges') and len(parents) == 2:
3891 return
3891 return
3892 if opts.get('only_merges') and len(parents) != 2:
3892 if opts.get('only_merges') and len(parents) != 2:
3893 return
3893 return
3894 if opts.get('branch') and ctx.branch() not in opts['branch']:
3894 if opts.get('branch') and ctx.branch() not in opts['branch']:
3895 return
3895 return
3896 if not opts.get('hidden') and ctx.hidden():
3896 if not opts.get('hidden') and ctx.hidden():
3897 return
3897 return
3898 if df and not df(ctx.date()[0]):
3898 if df and not df(ctx.date()[0]):
3899 return
3899 return
3900 if opts['user'] and not [k for k in opts['user']
3900 if opts['user'] and not [k for k in opts['user']
3901 if k.lower() in ctx.user().lower()]:
3901 if k.lower() in ctx.user().lower()]:
3902 return
3902 return
3903 if opts.get('keyword'):
3903 if opts.get('keyword'):
3904 for k in [kw.lower() for kw in opts['keyword']]:
3904 for k in [kw.lower() for kw in opts['keyword']]:
3905 if (k in ctx.user().lower() or
3905 if (k in ctx.user().lower() or
3906 k in ctx.description().lower() or
3906 k in ctx.description().lower() or
3907 k in " ".join(ctx.files()).lower()):
3907 k in " ".join(ctx.files()).lower()):
3908 break
3908 break
3909 else:
3909 else:
3910 return
3910 return
3911
3911
3912 copies = None
3912 copies = None
3913 if opts.get('copies') and rev:
3913 if opts.get('copies') and rev:
3914 copies = []
3914 copies = []
3915 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3915 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3916 for fn in ctx.files():
3916 for fn in ctx.files():
3917 rename = getrenamed(fn, rev)
3917 rename = getrenamed(fn, rev)
3918 if rename:
3918 if rename:
3919 copies.append((fn, rename[0]))
3919 copies.append((fn, rename[0]))
3920
3920
3921 revmatchfn = None
3921 revmatchfn = None
3922 if opts.get('patch') or opts.get('stat'):
3922 if opts.get('patch') or opts.get('stat'):
3923 if opts.get('follow') or opts.get('follow_first'):
3923 if opts.get('follow') or opts.get('follow_first'):
3924 # note: this might be wrong when following through merges
3924 # note: this might be wrong when following through merges
3925 revmatchfn = scmutil.match(repo[None], fns, default='path')
3925 revmatchfn = scmutil.match(repo[None], fns, default='path')
3926 else:
3926 else:
3927 revmatchfn = matchfn
3927 revmatchfn = matchfn
3928
3928
3929 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3929 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3930
3930
3931 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3931 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3932 if count == limit:
3932 if count == limit:
3933 break
3933 break
3934 if displayer.flush(ctx.rev()):
3934 if displayer.flush(ctx.rev()):
3935 count += 1
3935 count += 1
3936 displayer.close()
3936 displayer.close()
3937
3937
3938 @command('manifest',
3938 @command('manifest',
3939 [('r', 'rev', '', _('revision to display'), _('REV')),
3939 [('r', 'rev', '', _('revision to display'), _('REV')),
3940 ('', 'all', False, _("list files from all revisions"))],
3940 ('', 'all', False, _("list files from all revisions"))],
3941 _('[-r REV]'))
3941 _('[-r REV]'))
3942 def manifest(ui, repo, node=None, rev=None, **opts):
3942 def manifest(ui, repo, node=None, rev=None, **opts):
3943 """output the current or given revision of the project manifest
3943 """output the current or given revision of the project manifest
3944
3944
3945 Print a list of version controlled files for the given revision.
3945 Print a list of version controlled files for the given revision.
3946 If no revision is given, the first parent of the working directory
3946 If no revision is given, the first parent of the working directory
3947 is used, or the null revision if no revision is checked out.
3947 is used, or the null revision if no revision is checked out.
3948
3948
3949 With -v, print file permissions, symlink and executable bits.
3949 With -v, print file permissions, symlink and executable bits.
3950 With --debug, print file revision hashes.
3950 With --debug, print file revision hashes.
3951
3951
3952 If option --all is specified, the list of all files from all revisions
3952 If option --all is specified, the list of all files from all revisions
3953 is printed. This includes deleted and renamed files.
3953 is printed. This includes deleted and renamed files.
3954
3954
3955 Returns 0 on success.
3955 Returns 0 on success.
3956 """
3956 """
3957 if opts.get('all'):
3957 if opts.get('all'):
3958 if rev or node:
3958 if rev or node:
3959 raise util.Abort(_("can't specify a revision with --all"))
3959 raise util.Abort(_("can't specify a revision with --all"))
3960
3960
3961 res = []
3961 res = []
3962 prefix = "data/"
3962 prefix = "data/"
3963 suffix = ".i"
3963 suffix = ".i"
3964 plen = len(prefix)
3964 plen = len(prefix)
3965 slen = len(suffix)
3965 slen = len(suffix)
3966 lock = repo.lock()
3966 lock = repo.lock()
3967 try:
3967 try:
3968 for fn, b, size in repo.store.datafiles():
3968 for fn, b, size in repo.store.datafiles():
3969 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3969 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3970 res.append(fn[plen:-slen])
3970 res.append(fn[plen:-slen])
3971 finally:
3971 finally:
3972 lock.release()
3972 lock.release()
3973 for f in sorted(res):
3973 for f in sorted(res):
3974 ui.write("%s\n" % f)
3974 ui.write("%s\n" % f)
3975 return
3975 return
3976
3976
3977 if rev and node:
3977 if rev and node:
3978 raise util.Abort(_("please specify just one revision"))
3978 raise util.Abort(_("please specify just one revision"))
3979
3979
3980 if not node:
3980 if not node:
3981 node = rev
3981 node = rev
3982
3982
3983 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3983 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3984 ctx = scmutil.revsingle(repo, node)
3984 ctx = scmutil.revsingle(repo, node)
3985 for f in ctx:
3985 for f in ctx:
3986 if ui.debugflag:
3986 if ui.debugflag:
3987 ui.write("%40s " % hex(ctx.manifest()[f]))
3987 ui.write("%40s " % hex(ctx.manifest()[f]))
3988 if ui.verbose:
3988 if ui.verbose:
3989 ui.write(decor[ctx.flags(f)])
3989 ui.write(decor[ctx.flags(f)])
3990 ui.write("%s\n" % f)
3990 ui.write("%s\n" % f)
3991
3991
3992 @command('^merge',
3992 @command('^merge',
3993 [('f', 'force', None, _('force a merge with outstanding changes')),
3993 [('f', 'force', None, _('force a merge with outstanding changes')),
3994 ('r', 'rev', '', _('revision to merge'), _('REV')),
3994 ('r', 'rev', '', _('revision to merge'), _('REV')),
3995 ('P', 'preview', None,
3995 ('P', 'preview', None,
3996 _('review revisions to merge (no merge is performed)'))
3996 _('review revisions to merge (no merge is performed)'))
3997 ] + mergetoolopts,
3997 ] + mergetoolopts,
3998 _('[-P] [-f] [[-r] REV]'))
3998 _('[-P] [-f] [[-r] REV]'))
3999 def merge(ui, repo, node=None, **opts):
3999 def merge(ui, repo, node=None, **opts):
4000 """merge working directory with another revision
4000 """merge working directory with another revision
4001
4001
4002 The current working directory is updated with all changes made in
4002 The current working directory is updated with all changes made in
4003 the requested revision since the last common predecessor revision.
4003 the requested revision since the last common predecessor revision.
4004
4004
4005 Files that changed between either parent are marked as changed for
4005 Files that changed between either parent are marked as changed for
4006 the next commit and a commit must be performed before any further
4006 the next commit and a commit must be performed before any further
4007 updates to the repository are allowed. The next commit will have
4007 updates to the repository are allowed. The next commit will have
4008 two parents.
4008 two parents.
4009
4009
4010 ``--tool`` can be used to specify the merge tool used for file
4010 ``--tool`` can be used to specify the merge tool used for file
4011 merges. It overrides the HGMERGE environment variable and your
4011 merges. It overrides the HGMERGE environment variable and your
4012 configuration files. See :hg:`help merge-tools` for options.
4012 configuration files. See :hg:`help merge-tools` for options.
4013
4013
4014 If no revision is specified, the working directory's parent is a
4014 If no revision is specified, the working directory's parent is a
4015 head revision, and the current branch contains exactly one other
4015 head revision, and the current branch contains exactly one other
4016 head, the other head is merged with by default. Otherwise, an
4016 head, the other head is merged with by default. Otherwise, an
4017 explicit revision with which to merge with must be provided.
4017 explicit revision with which to merge with must be provided.
4018
4018
4019 :hg:`resolve` must be used to resolve unresolved files.
4019 :hg:`resolve` must be used to resolve unresolved files.
4020
4020
4021 To undo an uncommitted merge, use :hg:`update --clean .` which
4021 To undo an uncommitted merge, use :hg:`update --clean .` which
4022 will check out a clean copy of the original merge parent, losing
4022 will check out a clean copy of the original merge parent, losing
4023 all changes.
4023 all changes.
4024
4024
4025 Returns 0 on success, 1 if there are unresolved files.
4025 Returns 0 on success, 1 if there are unresolved files.
4026 """
4026 """
4027
4027
4028 if opts.get('rev') and node:
4028 if opts.get('rev') and node:
4029 raise util.Abort(_("please specify just one revision"))
4029 raise util.Abort(_("please specify just one revision"))
4030 if not node:
4030 if not node:
4031 node = opts.get('rev')
4031 node = opts.get('rev')
4032
4032
4033 if not node:
4033 if not node:
4034 branch = repo[None].branch()
4034 branch = repo[None].branch()
4035 bheads = repo.branchheads(branch)
4035 bheads = repo.branchheads(branch)
4036 if len(bheads) > 2:
4036 if len(bheads) > 2:
4037 raise util.Abort(_("branch '%s' has %d heads - "
4037 raise util.Abort(_("branch '%s' has %d heads - "
4038 "please merge with an explicit rev")
4038 "please merge with an explicit rev")
4039 % (branch, len(bheads)),
4039 % (branch, len(bheads)),
4040 hint=_("run 'hg heads .' to see heads"))
4040 hint=_("run 'hg heads .' to see heads"))
4041
4041
4042 parent = repo.dirstate.p1()
4042 parent = repo.dirstate.p1()
4043 if len(bheads) == 1:
4043 if len(bheads) == 1:
4044 if len(repo.heads()) > 1:
4044 if len(repo.heads()) > 1:
4045 raise util.Abort(_("branch '%s' has one head - "
4045 raise util.Abort(_("branch '%s' has one head - "
4046 "please merge with an explicit rev")
4046 "please merge with an explicit rev")
4047 % branch,
4047 % branch,
4048 hint=_("run 'hg heads' to see all heads"))
4048 hint=_("run 'hg heads' to see all heads"))
4049 msg, hint = _('nothing to merge'), None
4049 msg, hint = _('nothing to merge'), None
4050 if parent != repo.lookup(branch):
4050 if parent != repo.lookup(branch):
4051 hint = _("use 'hg update' instead")
4051 hint = _("use 'hg update' instead")
4052 raise util.Abort(msg, hint=hint)
4052 raise util.Abort(msg, hint=hint)
4053
4053
4054 if parent not in bheads:
4054 if parent not in bheads:
4055 raise util.Abort(_('working directory not at a head revision'),
4055 raise util.Abort(_('working directory not at a head revision'),
4056 hint=_("use 'hg update' or merge with an "
4056 hint=_("use 'hg update' or merge with an "
4057 "explicit revision"))
4057 "explicit revision"))
4058 node = parent == bheads[0] and bheads[-1] or bheads[0]
4058 node = parent == bheads[0] and bheads[-1] or bheads[0]
4059 else:
4059 else:
4060 node = scmutil.revsingle(repo, node).node()
4060 node = scmutil.revsingle(repo, node).node()
4061
4061
4062 if opts.get('preview'):
4062 if opts.get('preview'):
4063 # find nodes that are ancestors of p2 but not of p1
4063 # find nodes that are ancestors of p2 but not of p1
4064 p1 = repo.lookup('.')
4064 p1 = repo.lookup('.')
4065 p2 = repo.lookup(node)
4065 p2 = repo.lookup(node)
4066 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4066 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4067
4067
4068 displayer = cmdutil.show_changeset(ui, repo, opts)
4068 displayer = cmdutil.show_changeset(ui, repo, opts)
4069 for node in nodes:
4069 for node in nodes:
4070 displayer.show(repo[node])
4070 displayer.show(repo[node])
4071 displayer.close()
4071 displayer.close()
4072 return 0
4072 return 0
4073
4073
4074 try:
4074 try:
4075 # ui.forcemerge is an internal variable, do not document
4075 # ui.forcemerge is an internal variable, do not document
4076 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4076 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4077 return hg.merge(repo, node, force=opts.get('force'))
4077 return hg.merge(repo, node, force=opts.get('force'))
4078 finally:
4078 finally:
4079 ui.setconfig('ui', 'forcemerge', '')
4079 ui.setconfig('ui', 'forcemerge', '')
4080
4080
4081 @command('outgoing|out',
4081 @command('outgoing|out',
4082 [('f', 'force', None, _('run even when the destination is unrelated')),
4082 [('f', 'force', None, _('run even when the destination is unrelated')),
4083 ('r', 'rev', [],
4083 ('r', 'rev', [],
4084 _('a changeset intended to be included in the destination'), _('REV')),
4084 _('a changeset intended to be included in the destination'), _('REV')),
4085 ('n', 'newest-first', None, _('show newest record first')),
4085 ('n', 'newest-first', None, _('show newest record first')),
4086 ('B', 'bookmarks', False, _('compare bookmarks')),
4086 ('B', 'bookmarks', False, _('compare bookmarks')),
4087 ('b', 'branch', [], _('a specific branch you would like to push'),
4087 ('b', 'branch', [], _('a specific branch you would like to push'),
4088 _('BRANCH')),
4088 _('BRANCH')),
4089 ] + logopts + remoteopts + subrepoopts,
4089 ] + logopts + remoteopts + subrepoopts,
4090 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4090 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4091 def outgoing(ui, repo, dest=None, **opts):
4091 def outgoing(ui, repo, dest=None, **opts):
4092 """show changesets not found in the destination
4092 """show changesets not found in the destination
4093
4093
4094 Show changesets not found in the specified destination repository
4094 Show changesets not found in the specified destination repository
4095 or the default push location. These are the changesets that would
4095 or the default push location. These are the changesets that would
4096 be pushed if a push was requested.
4096 be pushed if a push was requested.
4097
4097
4098 See pull for details of valid destination formats.
4098 See pull for details of valid destination formats.
4099
4099
4100 Returns 0 if there are outgoing changes, 1 otherwise.
4100 Returns 0 if there are outgoing changes, 1 otherwise.
4101 """
4101 """
4102
4102
4103 if opts.get('bookmarks'):
4103 if opts.get('bookmarks'):
4104 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4104 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4105 dest, branches = hg.parseurl(dest, opts.get('branch'))
4105 dest, branches = hg.parseurl(dest, opts.get('branch'))
4106 other = hg.peer(repo, opts, dest)
4106 other = hg.peer(repo, opts, dest)
4107 if 'bookmarks' not in other.listkeys('namespaces'):
4107 if 'bookmarks' not in other.listkeys('namespaces'):
4108 ui.warn(_("remote doesn't support bookmarks\n"))
4108 ui.warn(_("remote doesn't support bookmarks\n"))
4109 return 0
4109 return 0
4110 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4110 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4111 return bookmarks.diff(ui, other, repo)
4111 return bookmarks.diff(ui, other, repo)
4112
4112
4113 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4113 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4114 try:
4114 try:
4115 return hg.outgoing(ui, repo, dest, opts)
4115 return hg.outgoing(ui, repo, dest, opts)
4116 finally:
4116 finally:
4117 del repo._subtoppath
4117 del repo._subtoppath
4118
4118
4119 @command('parents',
4119 @command('parents',
4120 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4120 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4121 ] + templateopts,
4121 ] + templateopts,
4122 _('[-r REV] [FILE]'))
4122 _('[-r REV] [FILE]'))
4123 def parents(ui, repo, file_=None, **opts):
4123 def parents(ui, repo, file_=None, **opts):
4124 """show the parents of the working directory or revision
4124 """show the parents of the working directory or revision
4125
4125
4126 Print the working directory's parent revisions. If a revision is
4126 Print the working directory's parent revisions. If a revision is
4127 given via -r/--rev, the parent of that revision will be printed.
4127 given via -r/--rev, the parent of that revision will be printed.
4128 If a file argument is given, the revision in which the file was
4128 If a file argument is given, the revision in which the file was
4129 last changed (before the working directory revision or the
4129 last changed (before the working directory revision or the
4130 argument to --rev if given) is printed.
4130 argument to --rev if given) is printed.
4131
4131
4132 Returns 0 on success.
4132 Returns 0 on success.
4133 """
4133 """
4134
4134
4135 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4135 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4136
4136
4137 if file_:
4137 if file_:
4138 m = scmutil.match(ctx, (file_,), opts)
4138 m = scmutil.match(ctx, (file_,), opts)
4139 if m.anypats() or len(m.files()) != 1:
4139 if m.anypats() or len(m.files()) != 1:
4140 raise util.Abort(_('can only specify an explicit filename'))
4140 raise util.Abort(_('can only specify an explicit filename'))
4141 file_ = m.files()[0]
4141 file_ = m.files()[0]
4142 filenodes = []
4142 filenodes = []
4143 for cp in ctx.parents():
4143 for cp in ctx.parents():
4144 if not cp:
4144 if not cp:
4145 continue
4145 continue
4146 try:
4146 try:
4147 filenodes.append(cp.filenode(file_))
4147 filenodes.append(cp.filenode(file_))
4148 except error.LookupError:
4148 except error.LookupError:
4149 pass
4149 pass
4150 if not filenodes:
4150 if not filenodes:
4151 raise util.Abort(_("'%s' not found in manifest!") % file_)
4151 raise util.Abort(_("'%s' not found in manifest!") % file_)
4152 fl = repo.file(file_)
4152 fl = repo.file(file_)
4153 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4153 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4154 else:
4154 else:
4155 p = [cp.node() for cp in ctx.parents()]
4155 p = [cp.node() for cp in ctx.parents()]
4156
4156
4157 displayer = cmdutil.show_changeset(ui, repo, opts)
4157 displayer = cmdutil.show_changeset(ui, repo, opts)
4158 for n in p:
4158 for n in p:
4159 if n != nullid:
4159 if n != nullid:
4160 displayer.show(repo[n])
4160 displayer.show(repo[n])
4161 displayer.close()
4161 displayer.close()
4162
4162
4163 @command('paths', [], _('[NAME]'))
4163 @command('paths', [], _('[NAME]'))
4164 def paths(ui, repo, search=None):
4164 def paths(ui, repo, search=None):
4165 """show aliases for remote repositories
4165 """show aliases for remote repositories
4166
4166
4167 Show definition of symbolic path name NAME. If no name is given,
4167 Show definition of symbolic path name NAME. If no name is given,
4168 show definition of all available names.
4168 show definition of all available names.
4169
4169
4170 Option -q/--quiet suppresses all output when searching for NAME
4170 Option -q/--quiet suppresses all output when searching for NAME
4171 and shows only the path names when listing all definitions.
4171 and shows only the path names when listing all definitions.
4172
4172
4173 Path names are defined in the [paths] section of your
4173 Path names are defined in the [paths] section of your
4174 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4174 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4175 repository, ``.hg/hgrc`` is used, too.
4175 repository, ``.hg/hgrc`` is used, too.
4176
4176
4177 The path names ``default`` and ``default-push`` have a special
4177 The path names ``default`` and ``default-push`` have a special
4178 meaning. When performing a push or pull operation, they are used
4178 meaning. When performing a push or pull operation, they are used
4179 as fallbacks if no location is specified on the command-line.
4179 as fallbacks if no location is specified on the command-line.
4180 When ``default-push`` is set, it will be used for push and
4180 When ``default-push`` is set, it will be used for push and
4181 ``default`` will be used for pull; otherwise ``default`` is used
4181 ``default`` will be used for pull; otherwise ``default`` is used
4182 as the fallback for both. When cloning a repository, the clone
4182 as the fallback for both. When cloning a repository, the clone
4183 source is written as ``default`` in ``.hg/hgrc``. Note that
4183 source is written as ``default`` in ``.hg/hgrc``. Note that
4184 ``default`` and ``default-push`` apply to all inbound (e.g.
4184 ``default`` and ``default-push`` apply to all inbound (e.g.
4185 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4185 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4186 :hg:`bundle`) operations.
4186 :hg:`bundle`) operations.
4187
4187
4188 See :hg:`help urls` for more information.
4188 See :hg:`help urls` for more information.
4189
4189
4190 Returns 0 on success.
4190 Returns 0 on success.
4191 """
4191 """
4192 if search:
4192 if search:
4193 for name, path in ui.configitems("paths"):
4193 for name, path in ui.configitems("paths"):
4194 if name == search:
4194 if name == search:
4195 ui.status("%s\n" % util.hidepassword(path))
4195 ui.status("%s\n" % util.hidepassword(path))
4196 return
4196 return
4197 if not ui.quiet:
4197 if not ui.quiet:
4198 ui.warn(_("not found!\n"))
4198 ui.warn(_("not found!\n"))
4199 return 1
4199 return 1
4200 else:
4200 else:
4201 for name, path in ui.configitems("paths"):
4201 for name, path in ui.configitems("paths"):
4202 if ui.quiet:
4202 if ui.quiet:
4203 ui.write("%s\n" % name)
4203 ui.write("%s\n" % name)
4204 else:
4204 else:
4205 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4205 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4206
4206
4207 def postincoming(ui, repo, modheads, optupdate, checkout):
4207 def postincoming(ui, repo, modheads, optupdate, checkout):
4208 if modheads == 0:
4208 if modheads == 0:
4209 return
4209 return
4210 if optupdate:
4210 if optupdate:
4211 try:
4211 try:
4212 return hg.update(repo, checkout)
4212 return hg.update(repo, checkout)
4213 except util.Abort, inst:
4213 except util.Abort, inst:
4214 ui.warn(_("not updating: %s\n" % str(inst)))
4214 ui.warn(_("not updating: %s\n" % str(inst)))
4215 return 0
4215 return 0
4216 if modheads > 1:
4216 if modheads > 1:
4217 currentbranchheads = len(repo.branchheads())
4217 currentbranchheads = len(repo.branchheads())
4218 if currentbranchheads == modheads:
4218 if currentbranchheads == modheads:
4219 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4219 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4220 elif currentbranchheads > 1:
4220 elif currentbranchheads > 1:
4221 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4221 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4222 else:
4222 else:
4223 ui.status(_("(run 'hg heads' to see heads)\n"))
4223 ui.status(_("(run 'hg heads' to see heads)\n"))
4224 else:
4224 else:
4225 ui.status(_("(run 'hg update' to get a working copy)\n"))
4225 ui.status(_("(run 'hg update' to get a working copy)\n"))
4226
4226
4227 @command('^pull',
4227 @command('^pull',
4228 [('u', 'update', None,
4228 [('u', 'update', None,
4229 _('update to new branch head if changesets were pulled')),
4229 _('update to new branch head if changesets were pulled')),
4230 ('f', 'force', None, _('run even when remote repository is unrelated')),
4230 ('f', 'force', None, _('run even when remote repository is unrelated')),
4231 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4231 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4232 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4232 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4233 ('b', 'branch', [], _('a specific branch you would like to pull'),
4233 ('b', 'branch', [], _('a specific branch you would like to pull'),
4234 _('BRANCH')),
4234 _('BRANCH')),
4235 ] + remoteopts,
4235 ] + remoteopts,
4236 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4236 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4237 def pull(ui, repo, source="default", **opts):
4237 def pull(ui, repo, source="default", **opts):
4238 """pull changes from the specified source
4238 """pull changes from the specified source
4239
4239
4240 Pull changes from a remote repository to a local one.
4240 Pull changes from a remote repository to a local one.
4241
4241
4242 This finds all changes from the repository at the specified path
4242 This finds all changes from the repository at the specified path
4243 or URL and adds them to a local repository (the current one unless
4243 or URL and adds them to a local repository (the current one unless
4244 -R is specified). By default, this does not update the copy of the
4244 -R is specified). By default, this does not update the copy of the
4245 project in the working directory.
4245 project in the working directory.
4246
4246
4247 Use :hg:`incoming` if you want to see what would have been added
4247 Use :hg:`incoming` if you want to see what would have been added
4248 by a pull at the time you issued this command. If you then decide
4248 by a pull at the time you issued this command. If you then decide
4249 to add those changes to the repository, you should use :hg:`pull
4249 to add those changes to the repository, you should use :hg:`pull
4250 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4250 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4251
4251
4252 If SOURCE is omitted, the 'default' path will be used.
4252 If SOURCE is omitted, the 'default' path will be used.
4253 See :hg:`help urls` for more information.
4253 See :hg:`help urls` for more information.
4254
4254
4255 Returns 0 on success, 1 if an update had unresolved files.
4255 Returns 0 on success, 1 if an update had unresolved files.
4256 """
4256 """
4257 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4257 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4258 other = hg.peer(repo, opts, source)
4258 other = hg.peer(repo, opts, source)
4259 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4259 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4260 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4260 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4261
4261
4262 if opts.get('bookmark'):
4262 if opts.get('bookmark'):
4263 if not revs:
4263 if not revs:
4264 revs = []
4264 revs = []
4265 rb = other.listkeys('bookmarks')
4265 rb = other.listkeys('bookmarks')
4266 for b in opts['bookmark']:
4266 for b in opts['bookmark']:
4267 if b not in rb:
4267 if b not in rb:
4268 raise util.Abort(_('remote bookmark %s not found!') % b)
4268 raise util.Abort(_('remote bookmark %s not found!') % b)
4269 revs.append(rb[b])
4269 revs.append(rb[b])
4270
4270
4271 if revs:
4271 if revs:
4272 try:
4272 try:
4273 revs = [other.lookup(rev) for rev in revs]
4273 revs = [other.lookup(rev) for rev in revs]
4274 except error.CapabilityError:
4274 except error.CapabilityError:
4275 err = _("other repository doesn't support revision lookup, "
4275 err = _("other repository doesn't support revision lookup, "
4276 "so a rev cannot be specified.")
4276 "so a rev cannot be specified.")
4277 raise util.Abort(err)
4277 raise util.Abort(err)
4278
4278
4279 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4279 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4280 bookmarks.updatefromremote(ui, repo, other, source)
4280 bookmarks.updatefromremote(ui, repo, other, source)
4281 if checkout:
4281 if checkout:
4282 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4282 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4283 repo._subtoppath = source
4283 repo._subtoppath = source
4284 try:
4284 try:
4285 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4285 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4286
4286
4287 finally:
4287 finally:
4288 del repo._subtoppath
4288 del repo._subtoppath
4289
4289
4290 # update specified bookmarks
4290 # update specified bookmarks
4291 if opts.get('bookmark'):
4291 if opts.get('bookmark'):
4292 for b in opts['bookmark']:
4292 for b in opts['bookmark']:
4293 # explicit pull overrides local bookmark if any
4293 # explicit pull overrides local bookmark if any
4294 ui.status(_("importing bookmark %s\n") % b)
4294 ui.status(_("importing bookmark %s\n") % b)
4295 repo._bookmarks[b] = repo[rb[b]].node()
4295 repo._bookmarks[b] = repo[rb[b]].node()
4296 bookmarks.write(repo)
4296 bookmarks.write(repo)
4297
4297
4298 return ret
4298 return ret
4299
4299
4300 @command('^push',
4300 @command('^push',
4301 [('f', 'force', None, _('force push')),
4301 [('f', 'force', None, _('force push')),
4302 ('r', 'rev', [],
4302 ('r', 'rev', [],
4303 _('a changeset intended to be included in the destination'),
4303 _('a changeset intended to be included in the destination'),
4304 _('REV')),
4304 _('REV')),
4305 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4305 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4306 ('b', 'branch', [],
4306 ('b', 'branch', [],
4307 _('a specific branch you would like to push'), _('BRANCH')),
4307 _('a specific branch you would like to push'), _('BRANCH')),
4308 ('', 'new-branch', False, _('allow pushing a new branch')),
4308 ('', 'new-branch', False, _('allow pushing a new branch')),
4309 ] + remoteopts,
4309 ] + remoteopts,
4310 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4310 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4311 def push(ui, repo, dest=None, **opts):
4311 def push(ui, repo, dest=None, **opts):
4312 """push changes to the specified destination
4312 """push changes to the specified destination
4313
4313
4314 Push changesets from the local repository to the specified
4314 Push changesets from the local repository to the specified
4315 destination.
4315 destination.
4316
4316
4317 This operation is symmetrical to pull: it is identical to a pull
4317 This operation is symmetrical to pull: it is identical to a pull
4318 in the destination repository from the current one.
4318 in the destination repository from the current one.
4319
4319
4320 By default, push will not allow creation of new heads at the
4320 By default, push will not allow creation of new heads at the
4321 destination, since multiple heads would make it unclear which head
4321 destination, since multiple heads would make it unclear which head
4322 to use. In this situation, it is recommended to pull and merge
4322 to use. In this situation, it is recommended to pull and merge
4323 before pushing.
4323 before pushing.
4324
4324
4325 Use --new-branch if you want to allow push to create a new named
4325 Use --new-branch if you want to allow push to create a new named
4326 branch that is not present at the destination. This allows you to
4326 branch that is not present at the destination. This allows you to
4327 only create a new branch without forcing other changes.
4327 only create a new branch without forcing other changes.
4328
4328
4329 Use -f/--force to override the default behavior and push all
4329 Use -f/--force to override the default behavior and push all
4330 changesets on all branches.
4330 changesets on all branches.
4331
4331
4332 If -r/--rev is used, the specified revision and all its ancestors
4332 If -r/--rev is used, the specified revision and all its ancestors
4333 will be pushed to the remote repository.
4333 will be pushed to the remote repository.
4334
4334
4335 Please see :hg:`help urls` for important details about ``ssh://``
4335 Please see :hg:`help urls` for important details about ``ssh://``
4336 URLs. If DESTINATION is omitted, a default path will be used.
4336 URLs. If DESTINATION is omitted, a default path will be used.
4337
4337
4338 Returns 0 if push was successful, 1 if nothing to push.
4338 Returns 0 if push was successful, 1 if nothing to push.
4339 """
4339 """
4340
4340
4341 if opts.get('bookmark'):
4341 if opts.get('bookmark'):
4342 for b in opts['bookmark']:
4342 for b in opts['bookmark']:
4343 # translate -B options to -r so changesets get pushed
4343 # translate -B options to -r so changesets get pushed
4344 if b in repo._bookmarks:
4344 if b in repo._bookmarks:
4345 opts.setdefault('rev', []).append(b)
4345 opts.setdefault('rev', []).append(b)
4346 else:
4346 else:
4347 # if we try to push a deleted bookmark, translate it to null
4347 # if we try to push a deleted bookmark, translate it to null
4348 # this lets simultaneous -r, -b options continue working
4348 # this lets simultaneous -r, -b options continue working
4349 opts.setdefault('rev', []).append("null")
4349 opts.setdefault('rev', []).append("null")
4350
4350
4351 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4351 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4352 dest, branches = hg.parseurl(dest, opts.get('branch'))
4352 dest, branches = hg.parseurl(dest, opts.get('branch'))
4353 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4353 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4354 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4354 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4355 other = hg.peer(repo, opts, dest)
4355 other = hg.peer(repo, opts, dest)
4356 if revs:
4356 if revs:
4357 revs = [repo.lookup(rev) for rev in revs]
4357 revs = [repo.lookup(rev) for rev in revs]
4358
4358
4359 repo._subtoppath = dest
4359 repo._subtoppath = dest
4360 try:
4360 try:
4361 # push subrepos depth-first for coherent ordering
4361 # push subrepos depth-first for coherent ordering
4362 c = repo['']
4362 c = repo['']
4363 subs = c.substate # only repos that are committed
4363 subs = c.substate # only repos that are committed
4364 for s in sorted(subs):
4364 for s in sorted(subs):
4365 if not c.sub(s).push(opts):
4365 if not c.sub(s).push(opts):
4366 return False
4366 return False
4367 finally:
4367 finally:
4368 del repo._subtoppath
4368 del repo._subtoppath
4369 result = repo.push(other, opts.get('force'), revs=revs,
4369 result = repo.push(other, opts.get('force'), revs=revs,
4370 newbranch=opts.get('new_branch'))
4370 newbranch=opts.get('new_branch'))
4371
4371
4372 result = (result == 0)
4372 result = (result == 0)
4373
4373
4374 if opts.get('bookmark'):
4374 if opts.get('bookmark'):
4375 rb = other.listkeys('bookmarks')
4375 rb = other.listkeys('bookmarks')
4376 for b in opts['bookmark']:
4376 for b in opts['bookmark']:
4377 # explicit push overrides remote bookmark if any
4377 # explicit push overrides remote bookmark if any
4378 if b in repo._bookmarks:
4378 if b in repo._bookmarks:
4379 ui.status(_("exporting bookmark %s\n") % b)
4379 ui.status(_("exporting bookmark %s\n") % b)
4380 new = repo[b].hex()
4380 new = repo[b].hex()
4381 elif b in rb:
4381 elif b in rb:
4382 ui.status(_("deleting remote bookmark %s\n") % b)
4382 ui.status(_("deleting remote bookmark %s\n") % b)
4383 new = '' # delete
4383 new = '' # delete
4384 else:
4384 else:
4385 ui.warn(_('bookmark %s does not exist on the local '
4385 ui.warn(_('bookmark %s does not exist on the local '
4386 'or remote repository!\n') % b)
4386 'or remote repository!\n') % b)
4387 return 2
4387 return 2
4388 old = rb.get(b, '')
4388 old = rb.get(b, '')
4389 r = other.pushkey('bookmarks', b, old, new)
4389 r = other.pushkey('bookmarks', b, old, new)
4390 if not r:
4390 if not r:
4391 ui.warn(_('updating bookmark %s failed!\n') % b)
4391 ui.warn(_('updating bookmark %s failed!\n') % b)
4392 if not result:
4392 if not result:
4393 result = 2
4393 result = 2
4394
4394
4395 return result
4395 return result
4396
4396
4397 @command('recover', [])
4397 @command('recover', [])
4398 def recover(ui, repo):
4398 def recover(ui, repo):
4399 """roll back an interrupted transaction
4399 """roll back an interrupted transaction
4400
4400
4401 Recover from an interrupted commit or pull.
4401 Recover from an interrupted commit or pull.
4402
4402
4403 This command tries to fix the repository status after an
4403 This command tries to fix the repository status after an
4404 interrupted operation. It should only be necessary when Mercurial
4404 interrupted operation. It should only be necessary when Mercurial
4405 suggests it.
4405 suggests it.
4406
4406
4407 Returns 0 if successful, 1 if nothing to recover or verify fails.
4407 Returns 0 if successful, 1 if nothing to recover or verify fails.
4408 """
4408 """
4409 if repo.recover():
4409 if repo.recover():
4410 return hg.verify(repo)
4410 return hg.verify(repo)
4411 return 1
4411 return 1
4412
4412
4413 @command('^remove|rm',
4413 @command('^remove|rm',
4414 [('A', 'after', None, _('record delete for missing files')),
4414 [('A', 'after', None, _('record delete for missing files')),
4415 ('f', 'force', None,
4415 ('f', 'force', None,
4416 _('remove (and delete) file even if added or modified')),
4416 _('remove (and delete) file even if added or modified')),
4417 ] + walkopts,
4417 ] + walkopts,
4418 _('[OPTION]... FILE...'))
4418 _('[OPTION]... FILE...'))
4419 def remove(ui, repo, *pats, **opts):
4419 def remove(ui, repo, *pats, **opts):
4420 """remove the specified files on the next commit
4420 """remove the specified files on the next commit
4421
4421
4422 Schedule the indicated files for removal from the current branch.
4422 Schedule the indicated files for removal from the current branch.
4423
4423
4424 This command schedules the files to be removed at the next commit.
4424 This command schedules the files to be removed at the next commit.
4425 To undo a remove before that, see :hg:`revert`. To undo added
4425 To undo a remove before that, see :hg:`revert`. To undo added
4426 files, see :hg:`forget`.
4426 files, see :hg:`forget`.
4427
4427
4428 .. container:: verbose
4428 .. container:: verbose
4429
4429
4430 -A/--after can be used to remove only files that have already
4430 -A/--after can be used to remove only files that have already
4431 been deleted, -f/--force can be used to force deletion, and -Af
4431 been deleted, -f/--force can be used to force deletion, and -Af
4432 can be used to remove files from the next revision without
4432 can be used to remove files from the next revision without
4433 deleting them from the working directory.
4433 deleting them from the working directory.
4434
4434
4435 The following table details the behavior of remove for different
4435 The following table details the behavior of remove for different
4436 file states (columns) and option combinations (rows). The file
4436 file states (columns) and option combinations (rows). The file
4437 states are Added [A], Clean [C], Modified [M] and Missing [!]
4437 states are Added [A], Clean [C], Modified [M] and Missing [!]
4438 (as reported by :hg:`status`). The actions are Warn, Remove
4438 (as reported by :hg:`status`). The actions are Warn, Remove
4439 (from branch) and Delete (from disk):
4439 (from branch) and Delete (from disk):
4440
4440
4441 ======= == == == ==
4441 ======= == == == ==
4442 A C M !
4442 A C M !
4443 ======= == == == ==
4443 ======= == == == ==
4444 none W RD W R
4444 none W RD W R
4445 -f R RD RD R
4445 -f R RD RD R
4446 -A W W W R
4446 -A W W W R
4447 -Af R R R R
4447 -Af R R R R
4448 ======= == == == ==
4448 ======= == == == ==
4449
4449
4450 Note that remove never deletes files in Added [A] state from the
4450 Note that remove never deletes files in Added [A] state from the
4451 working directory, not even if option --force is specified.
4451 working directory, not even if option --force is specified.
4452
4452
4453 Returns 0 on success, 1 if any warnings encountered.
4453 Returns 0 on success, 1 if any warnings encountered.
4454 """
4454 """
4455
4455
4456 ret = 0
4456 ret = 0
4457 after, force = opts.get('after'), opts.get('force')
4457 after, force = opts.get('after'), opts.get('force')
4458 if not pats and not after:
4458 if not pats and not after:
4459 raise util.Abort(_('no files specified'))
4459 raise util.Abort(_('no files specified'))
4460
4460
4461 m = scmutil.match(repo[None], pats, opts)
4461 m = scmutil.match(repo[None], pats, opts)
4462 s = repo.status(match=m, clean=True)
4462 s = repo.status(match=m, clean=True)
4463 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4463 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4464
4464
4465 for f in m.files():
4465 for f in m.files():
4466 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4466 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4467 if os.path.exists(m.rel(f)):
4467 if os.path.exists(m.rel(f)):
4468 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4468 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4469 ret = 1
4469 ret = 1
4470
4470
4471 if force:
4471 if force:
4472 list = modified + deleted + clean + added
4472 list = modified + deleted + clean + added
4473 elif after:
4473 elif after:
4474 list = deleted
4474 list = deleted
4475 for f in modified + added + clean:
4475 for f in modified + added + clean:
4476 ui.warn(_('not removing %s: file still exists (use -f'
4476 ui.warn(_('not removing %s: file still exists (use -f'
4477 ' to force removal)\n') % m.rel(f))
4477 ' to force removal)\n') % m.rel(f))
4478 ret = 1
4478 ret = 1
4479 else:
4479 else:
4480 list = deleted + clean
4480 list = deleted + clean
4481 for f in modified:
4481 for f in modified:
4482 ui.warn(_('not removing %s: file is modified (use -f'
4482 ui.warn(_('not removing %s: file is modified (use -f'
4483 ' to force removal)\n') % m.rel(f))
4483 ' to force removal)\n') % m.rel(f))
4484 ret = 1
4484 ret = 1
4485 for f in added:
4485 for f in added:
4486 ui.warn(_('not removing %s: file has been marked for add'
4486 ui.warn(_('not removing %s: file has been marked for add'
4487 ' (use forget to undo)\n') % m.rel(f))
4487 ' (use forget to undo)\n') % m.rel(f))
4488 ret = 1
4488 ret = 1
4489
4489
4490 for f in sorted(list):
4490 for f in sorted(list):
4491 if ui.verbose or not m.exact(f):
4491 if ui.verbose or not m.exact(f):
4492 ui.status(_('removing %s\n') % m.rel(f))
4492 ui.status(_('removing %s\n') % m.rel(f))
4493
4493
4494 wlock = repo.wlock()
4494 wlock = repo.wlock()
4495 try:
4495 try:
4496 if not after:
4496 if not after:
4497 for f in list:
4497 for f in list:
4498 if f in added:
4498 if f in added:
4499 continue # we never unlink added files on remove
4499 continue # we never unlink added files on remove
4500 try:
4500 try:
4501 util.unlinkpath(repo.wjoin(f))
4501 util.unlinkpath(repo.wjoin(f))
4502 except OSError, inst:
4502 except OSError, inst:
4503 if inst.errno != errno.ENOENT:
4503 if inst.errno != errno.ENOENT:
4504 raise
4504 raise
4505 repo[None].forget(list)
4505 repo[None].forget(list)
4506 finally:
4506 finally:
4507 wlock.release()
4507 wlock.release()
4508
4508
4509 return ret
4509 return ret
4510
4510
4511 @command('rename|move|mv',
4511 @command('rename|move|mv',
4512 [('A', 'after', None, _('record a rename that has already occurred')),
4512 [('A', 'after', None, _('record a rename that has already occurred')),
4513 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4513 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4514 ] + walkopts + dryrunopts,
4514 ] + walkopts + dryrunopts,
4515 _('[OPTION]... SOURCE... DEST'))
4515 _('[OPTION]... SOURCE... DEST'))
4516 def rename(ui, repo, *pats, **opts):
4516 def rename(ui, repo, *pats, **opts):
4517 """rename files; equivalent of copy + remove
4517 """rename files; equivalent of copy + remove
4518
4518
4519 Mark dest as copies of sources; mark sources for deletion. If dest
4519 Mark dest as copies of sources; mark sources for deletion. If dest
4520 is a directory, copies are put in that directory. If dest is a
4520 is a directory, copies are put in that directory. If dest is a
4521 file, there can only be one source.
4521 file, there can only be one source.
4522
4522
4523 By default, this command copies the contents of files as they
4523 By default, this command copies the contents of files as they
4524 exist in the working directory. If invoked with -A/--after, the
4524 exist in the working directory. If invoked with -A/--after, the
4525 operation is recorded, but no copying is performed.
4525 operation is recorded, but no copying is performed.
4526
4526
4527 This command takes effect at the next commit. To undo a rename
4527 This command takes effect at the next commit. To undo a rename
4528 before that, see :hg:`revert`.
4528 before that, see :hg:`revert`.
4529
4529
4530 Returns 0 on success, 1 if errors are encountered.
4530 Returns 0 on success, 1 if errors are encountered.
4531 """
4531 """
4532 wlock = repo.wlock(False)
4532 wlock = repo.wlock(False)
4533 try:
4533 try:
4534 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4534 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4535 finally:
4535 finally:
4536 wlock.release()
4536 wlock.release()
4537
4537
4538 @command('resolve',
4538 @command('resolve',
4539 [('a', 'all', None, _('select all unresolved files')),
4539 [('a', 'all', None, _('select all unresolved files')),
4540 ('l', 'list', None, _('list state of files needing merge')),
4540 ('l', 'list', None, _('list state of files needing merge')),
4541 ('m', 'mark', None, _('mark files as resolved')),
4541 ('m', 'mark', None, _('mark files as resolved')),
4542 ('u', 'unmark', None, _('mark files as unresolved')),
4542 ('u', 'unmark', None, _('mark files as unresolved')),
4543 ('n', 'no-status', None, _('hide status prefix'))]
4543 ('n', 'no-status', None, _('hide status prefix'))]
4544 + mergetoolopts + walkopts,
4544 + mergetoolopts + walkopts,
4545 _('[OPTION]... [FILE]...'))
4545 _('[OPTION]... [FILE]...'))
4546 def resolve(ui, repo, *pats, **opts):
4546 def resolve(ui, repo, *pats, **opts):
4547 """redo merges or set/view the merge status of files
4547 """redo merges or set/view the merge status of files
4548
4548
4549 Merges with unresolved conflicts are often the result of
4549 Merges with unresolved conflicts are often the result of
4550 non-interactive merging using the ``internal:merge`` configuration
4550 non-interactive merging using the ``internal:merge`` configuration
4551 setting, or a command-line merge tool like ``diff3``. The resolve
4551 setting, or a command-line merge tool like ``diff3``. The resolve
4552 command is used to manage the files involved in a merge, after
4552 command is used to manage the files involved in a merge, after
4553 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4553 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4554 working directory must have two parents).
4554 working directory must have two parents).
4555
4555
4556 The resolve command can be used in the following ways:
4556 The resolve command can be used in the following ways:
4557
4557
4558 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4558 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4559 files, discarding any previous merge attempts. Re-merging is not
4559 files, discarding any previous merge attempts. Re-merging is not
4560 performed for files already marked as resolved. Use ``--all/-a``
4560 performed for files already marked as resolved. Use ``--all/-a``
4561 to select all unresolved files. ``--tool`` can be used to specify
4561 to select all unresolved files. ``--tool`` can be used to specify
4562 the merge tool used for the given files. It overrides the HGMERGE
4562 the merge tool used for the given files. It overrides the HGMERGE
4563 environment variable and your configuration files. Previous file
4563 environment variable and your configuration files. Previous file
4564 contents are saved with a ``.orig`` suffix.
4564 contents are saved with a ``.orig`` suffix.
4565
4565
4566 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4566 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4567 (e.g. after having manually fixed-up the files). The default is
4567 (e.g. after having manually fixed-up the files). The default is
4568 to mark all unresolved files.
4568 to mark all unresolved files.
4569
4569
4570 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4570 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4571 default is to mark all resolved files.
4571 default is to mark all resolved files.
4572
4572
4573 - :hg:`resolve -l`: list files which had or still have conflicts.
4573 - :hg:`resolve -l`: list files which had or still have conflicts.
4574 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4574 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4575
4575
4576 Note that Mercurial will not let you commit files with unresolved
4576 Note that Mercurial will not let you commit files with unresolved
4577 merge conflicts. You must use :hg:`resolve -m ...` before you can
4577 merge conflicts. You must use :hg:`resolve -m ...` before you can
4578 commit after a conflicting merge.
4578 commit after a conflicting merge.
4579
4579
4580 Returns 0 on success, 1 if any files fail a resolve attempt.
4580 Returns 0 on success, 1 if any files fail a resolve attempt.
4581 """
4581 """
4582
4582
4583 all, mark, unmark, show, nostatus = \
4583 all, mark, unmark, show, nostatus = \
4584 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4584 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4585
4585
4586 if (show and (mark or unmark)) or (mark and unmark):
4586 if (show and (mark or unmark)) or (mark and unmark):
4587 raise util.Abort(_("too many options specified"))
4587 raise util.Abort(_("too many options specified"))
4588 if pats and all:
4588 if pats and all:
4589 raise util.Abort(_("can't specify --all and patterns"))
4589 raise util.Abort(_("can't specify --all and patterns"))
4590 if not (all or pats or show or mark or unmark):
4590 if not (all or pats or show or mark or unmark):
4591 raise util.Abort(_('no files or directories specified; '
4591 raise util.Abort(_('no files or directories specified; '
4592 'use --all to remerge all files'))
4592 'use --all to remerge all files'))
4593
4593
4594 ms = mergemod.mergestate(repo)
4594 ms = mergemod.mergestate(repo)
4595 m = scmutil.match(repo[None], pats, opts)
4595 m = scmutil.match(repo[None], pats, opts)
4596 ret = 0
4596 ret = 0
4597
4597
4598 for f in ms:
4598 for f in ms:
4599 if m(f):
4599 if m(f):
4600 if show:
4600 if show:
4601 if nostatus:
4601 if nostatus:
4602 ui.write("%s\n" % f)
4602 ui.write("%s\n" % f)
4603 else:
4603 else:
4604 ui.write("%s %s\n" % (ms[f].upper(), f),
4604 ui.write("%s %s\n" % (ms[f].upper(), f),
4605 label='resolve.' +
4605 label='resolve.' +
4606 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4606 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4607 elif mark:
4607 elif mark:
4608 ms.mark(f, "r")
4608 ms.mark(f, "r")
4609 elif unmark:
4609 elif unmark:
4610 ms.mark(f, "u")
4610 ms.mark(f, "u")
4611 else:
4611 else:
4612 wctx = repo[None]
4612 wctx = repo[None]
4613 mctx = wctx.parents()[-1]
4613 mctx = wctx.parents()[-1]
4614
4614
4615 # backup pre-resolve (merge uses .orig for its own purposes)
4615 # backup pre-resolve (merge uses .orig for its own purposes)
4616 a = repo.wjoin(f)
4616 a = repo.wjoin(f)
4617 util.copyfile(a, a + ".resolve")
4617 util.copyfile(a, a + ".resolve")
4618
4618
4619 try:
4619 try:
4620 # resolve file
4620 # resolve file
4621 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4621 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4622 if ms.resolve(f, wctx, mctx):
4622 if ms.resolve(f, wctx, mctx):
4623 ret = 1
4623 ret = 1
4624 finally:
4624 finally:
4625 ui.setconfig('ui', 'forcemerge', '')
4625 ui.setconfig('ui', 'forcemerge', '')
4626
4626
4627 # replace filemerge's .orig file with our resolve file
4627 # replace filemerge's .orig file with our resolve file
4628 util.rename(a + ".resolve", a + ".orig")
4628 util.rename(a + ".resolve", a + ".orig")
4629
4629
4630 ms.commit()
4630 ms.commit()
4631 return ret
4631 return ret
4632
4632
4633 @command('revert',
4633 @command('revert',
4634 [('a', 'all', None, _('revert all changes when no arguments given')),
4634 [('a', 'all', None, _('revert all changes when no arguments given')),
4635 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4635 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4636 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4636 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4637 ('C', 'no-backup', None, _('do not save backup copies of files')),
4637 ('C', 'no-backup', None, _('do not save backup copies of files')),
4638 ] + walkopts + dryrunopts,
4638 ] + walkopts + dryrunopts,
4639 _('[OPTION]... [-r REV] [NAME]...'))
4639 _('[OPTION]... [-r REV] [NAME]...'))
4640 def revert(ui, repo, *pats, **opts):
4640 def revert(ui, repo, *pats, **opts):
4641 """restore files to their checkout state
4641 """restore files to their checkout state
4642
4642
4643 .. note::
4643 .. note::
4644 To check out earlier revisions, you should use :hg:`update REV`.
4644 To check out earlier revisions, you should use :hg:`update REV`.
4645 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4645 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4646
4646
4647 With no revision specified, revert the specified files or directories
4647 With no revision specified, revert the specified files or directories
4648 to the contents they had in the parent of the working directory.
4648 to the contents they had in the parent of the working directory.
4649 This restores the contents of files to an unmodified
4649 This restores the contents of files to an unmodified
4650 state and unschedules adds, removes, copies, and renames. If the
4650 state and unschedules adds, removes, copies, and renames. If the
4651 working directory has two parents, you must explicitly specify a
4651 working directory has two parents, you must explicitly specify a
4652 revision.
4652 revision.
4653
4653
4654 Using the -r/--rev or -d/--date options, revert the given files or
4654 Using the -r/--rev or -d/--date options, revert the given files or
4655 directories to their states as of a specific revision. Because
4655 directories to their states as of a specific revision. Because
4656 revert does not change the working directory parents, this will
4656 revert does not change the working directory parents, this will
4657 cause these files to appear modified. This can be helpful to "back
4657 cause these files to appear modified. This can be helpful to "back
4658 out" some or all of an earlier change. See :hg:`backout` for a
4658 out" some or all of an earlier change. See :hg:`backout` for a
4659 related method.
4659 related method.
4660
4660
4661 Modified files are saved with a .orig suffix before reverting.
4661 Modified files are saved with a .orig suffix before reverting.
4662 To disable these backups, use --no-backup.
4662 To disable these backups, use --no-backup.
4663
4663
4664 See :hg:`help dates` for a list of formats valid for -d/--date.
4664 See :hg:`help dates` for a list of formats valid for -d/--date.
4665
4665
4666 Returns 0 on success.
4666 Returns 0 on success.
4667 """
4667 """
4668
4668
4669 if opts.get("date"):
4669 if opts.get("date"):
4670 if opts.get("rev"):
4670 if opts.get("rev"):
4671 raise util.Abort(_("you can't specify a revision and a date"))
4671 raise util.Abort(_("you can't specify a revision and a date"))
4672 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4672 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4673
4673
4674 parent, p2 = repo.dirstate.parents()
4674 parent, p2 = repo.dirstate.parents()
4675 if not opts.get('rev') and p2 != nullid:
4675 if not opts.get('rev') and p2 != nullid:
4676 # revert after merge is a trap for new users (issue2915)
4676 # revert after merge is a trap for new users (issue2915)
4677 raise util.Abort(_('uncommitted merge with no revision specified'),
4677 raise util.Abort(_('uncommitted merge with no revision specified'),
4678 hint=_('use "hg update" or see "hg help revert"'))
4678 hint=_('use "hg update" or see "hg help revert"'))
4679
4679
4680 ctx = scmutil.revsingle(repo, opts.get('rev'))
4680 ctx = scmutil.revsingle(repo, opts.get('rev'))
4681 node = ctx.node()
4681 node = ctx.node()
4682
4682
4683 if not pats and not opts.get('all'):
4683 if not pats and not opts.get('all'):
4684 msg = _("no files or directories specified")
4684 msg = _("no files or directories specified")
4685 if p2 != nullid:
4685 if p2 != nullid:
4686 hint = _("uncommitted merge, use --all to discard all changes,"
4686 hint = _("uncommitted merge, use --all to discard all changes,"
4687 " or 'hg update -C .' to abort the merge")
4687 " or 'hg update -C .' to abort the merge")
4688 raise util.Abort(msg, hint=hint)
4688 raise util.Abort(msg, hint=hint)
4689 dirty = util.any(repo.status())
4689 dirty = util.any(repo.status())
4690 if node != parent:
4690 if node != parent:
4691 if dirty:
4691 if dirty:
4692 hint = _("uncommitted changes, use --all to discard all"
4692 hint = _("uncommitted changes, use --all to discard all"
4693 " changes, or 'hg update %s' to update") % ctx.rev()
4693 " changes, or 'hg update %s' to update") % ctx.rev()
4694 else:
4694 else:
4695 hint = _("use --all to revert all files,"
4695 hint = _("use --all to revert all files,"
4696 " or 'hg update %s' to update") % ctx.rev()
4696 " or 'hg update %s' to update") % ctx.rev()
4697 elif dirty:
4697 elif dirty:
4698 hint = _("uncommitted changes, use --all to discard all changes")
4698 hint = _("uncommitted changes, use --all to discard all changes")
4699 else:
4699 else:
4700 hint = _("use --all to revert all files")
4700 hint = _("use --all to revert all files")
4701 raise util.Abort(msg, hint=hint)
4701 raise util.Abort(msg, hint=hint)
4702
4702
4703 mf = ctx.manifest()
4703 mf = ctx.manifest()
4704 if node == parent:
4704 if node == parent:
4705 pmf = mf
4705 pmf = mf
4706 else:
4706 else:
4707 pmf = None
4707 pmf = None
4708
4708
4709 # need all matching names in dirstate and manifest of target rev,
4709 # need all matching names in dirstate and manifest of target rev,
4710 # so have to walk both. do not print errors if files exist in one
4710 # so have to walk both. do not print errors if files exist in one
4711 # but not other.
4711 # but not other.
4712
4712
4713 names = {}
4713 names = {}
4714
4714
4715 wlock = repo.wlock()
4715 wlock = repo.wlock()
4716 try:
4716 try:
4717 # walk dirstate.
4717 # walk dirstate.
4718
4718
4719 m = scmutil.match(repo[None], pats, opts)
4719 m = scmutil.match(repo[None], pats, opts)
4720 m.bad = lambda x, y: False
4720 m.bad = lambda x, y: False
4721 for abs in repo.walk(m):
4721 for abs in repo.walk(m):
4722 names[abs] = m.rel(abs), m.exact(abs)
4722 names[abs] = m.rel(abs), m.exact(abs)
4723
4723
4724 # walk target manifest.
4724 # walk target manifest.
4725
4725
4726 def badfn(path, msg):
4726 def badfn(path, msg):
4727 if path in names:
4727 if path in names:
4728 return
4728 return
4729 if path in repo[node].substate:
4729 if path in repo[node].substate:
4730 ui.warn("%s: %s\n" % (m.rel(path),
4730 ui.warn("%s: %s\n" % (m.rel(path),
4731 'reverting subrepos is unsupported'))
4731 'reverting subrepos is unsupported'))
4732 return
4732 return
4733 path_ = path + '/'
4733 path_ = path + '/'
4734 for f in names:
4734 for f in names:
4735 if f.startswith(path_):
4735 if f.startswith(path_):
4736 return
4736 return
4737 ui.warn("%s: %s\n" % (m.rel(path), msg))
4737 ui.warn("%s: %s\n" % (m.rel(path), msg))
4738
4738
4739 m = scmutil.match(repo[node], pats, opts)
4739 m = scmutil.match(repo[node], pats, opts)
4740 m.bad = badfn
4740 m.bad = badfn
4741 for abs in repo[node].walk(m):
4741 for abs in repo[node].walk(m):
4742 if abs not in names:
4742 if abs not in names:
4743 names[abs] = m.rel(abs), m.exact(abs)
4743 names[abs] = m.rel(abs), m.exact(abs)
4744
4744
4745 m = scmutil.matchfiles(repo, names)
4745 m = scmutil.matchfiles(repo, names)
4746 changes = repo.status(match=m)[:4]
4746 changes = repo.status(match=m)[:4]
4747 modified, added, removed, deleted = map(set, changes)
4747 modified, added, removed, deleted = map(set, changes)
4748
4748
4749 # if f is a rename, also revert the source
4749 # if f is a rename, also revert the source
4750 cwd = repo.getcwd()
4750 cwd = repo.getcwd()
4751 for f in added:
4751 for f in added:
4752 src = repo.dirstate.copied(f)
4752 src = repo.dirstate.copied(f)
4753 if src and src not in names and repo.dirstate[src] == 'r':
4753 if src and src not in names and repo.dirstate[src] == 'r':
4754 removed.add(src)
4754 removed.add(src)
4755 names[src] = (repo.pathto(src, cwd), True)
4755 names[src] = (repo.pathto(src, cwd), True)
4756
4756
4757 def removeforget(abs):
4757 def removeforget(abs):
4758 if repo.dirstate[abs] == 'a':
4758 if repo.dirstate[abs] == 'a':
4759 return _('forgetting %s\n')
4759 return _('forgetting %s\n')
4760 return _('removing %s\n')
4760 return _('removing %s\n')
4761
4761
4762 revert = ([], _('reverting %s\n'))
4762 revert = ([], _('reverting %s\n'))
4763 add = ([], _('adding %s\n'))
4763 add = ([], _('adding %s\n'))
4764 remove = ([], removeforget)
4764 remove = ([], removeforget)
4765 undelete = ([], _('undeleting %s\n'))
4765 undelete = ([], _('undeleting %s\n'))
4766
4766
4767 disptable = (
4767 disptable = (
4768 # dispatch table:
4768 # dispatch table:
4769 # file state
4769 # file state
4770 # action if in target manifest
4770 # action if in target manifest
4771 # action if not in target manifest
4771 # action if not in target manifest
4772 # make backup if in target manifest
4772 # make backup if in target manifest
4773 # make backup if not in target manifest
4773 # make backup if not in target manifest
4774 (modified, revert, remove, True, True),
4774 (modified, revert, remove, True, True),
4775 (added, revert, remove, True, False),
4775 (added, revert, remove, True, False),
4776 (removed, undelete, None, False, False),
4776 (removed, undelete, None, False, False),
4777 (deleted, revert, remove, False, False),
4777 (deleted, revert, remove, False, False),
4778 )
4778 )
4779
4779
4780 for abs, (rel, exact) in sorted(names.items()):
4780 for abs, (rel, exact) in sorted(names.items()):
4781 mfentry = mf.get(abs)
4781 mfentry = mf.get(abs)
4782 target = repo.wjoin(abs)
4782 target = repo.wjoin(abs)
4783 def handle(xlist, dobackup):
4783 def handle(xlist, dobackup):
4784 xlist[0].append(abs)
4784 xlist[0].append(abs)
4785 if (dobackup and not opts.get('no_backup') and
4785 if (dobackup and not opts.get('no_backup') and
4786 os.path.lexists(target)):
4786 os.path.lexists(target)):
4787 bakname = "%s.orig" % rel
4787 bakname = "%s.orig" % rel
4788 ui.note(_('saving current version of %s as %s\n') %
4788 ui.note(_('saving current version of %s as %s\n') %
4789 (rel, bakname))
4789 (rel, bakname))
4790 if not opts.get('dry_run'):
4790 if not opts.get('dry_run'):
4791 util.rename(target, bakname)
4791 util.rename(target, bakname)
4792 if ui.verbose or not exact:
4792 if ui.verbose or not exact:
4793 msg = xlist[1]
4793 msg = xlist[1]
4794 if not isinstance(msg, basestring):
4794 if not isinstance(msg, basestring):
4795 msg = msg(abs)
4795 msg = msg(abs)
4796 ui.status(msg % rel)
4796 ui.status(msg % rel)
4797 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4797 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4798 if abs not in table:
4798 if abs not in table:
4799 continue
4799 continue
4800 # file has changed in dirstate
4800 # file has changed in dirstate
4801 if mfentry:
4801 if mfentry:
4802 handle(hitlist, backuphit)
4802 handle(hitlist, backuphit)
4803 elif misslist is not None:
4803 elif misslist is not None:
4804 handle(misslist, backupmiss)
4804 handle(misslist, backupmiss)
4805 break
4805 break
4806 else:
4806 else:
4807 if abs not in repo.dirstate:
4807 if abs not in repo.dirstate:
4808 if mfentry:
4808 if mfentry:
4809 handle(add, True)
4809 handle(add, True)
4810 elif exact:
4810 elif exact:
4811 ui.warn(_('file not managed: %s\n') % rel)
4811 ui.warn(_('file not managed: %s\n') % rel)
4812 continue
4812 continue
4813 # file has not changed in dirstate
4813 # file has not changed in dirstate
4814 if node == parent:
4814 if node == parent:
4815 if exact:
4815 if exact:
4816 ui.warn(_('no changes needed to %s\n') % rel)
4816 ui.warn(_('no changes needed to %s\n') % rel)
4817 continue
4817 continue
4818 if pmf is None:
4818 if pmf is None:
4819 # only need parent manifest in this unlikely case,
4819 # only need parent manifest in this unlikely case,
4820 # so do not read by default
4820 # so do not read by default
4821 pmf = repo[parent].manifest()
4821 pmf = repo[parent].manifest()
4822 if abs in pmf and mfentry:
4822 if abs in pmf and mfentry:
4823 # if version of file is same in parent and target
4823 # if version of file is same in parent and target
4824 # manifests, do nothing
4824 # manifests, do nothing
4825 if (pmf[abs] != mfentry or
4825 if (pmf[abs] != mfentry or
4826 pmf.flags(abs) != mf.flags(abs)):
4826 pmf.flags(abs) != mf.flags(abs)):
4827 handle(revert, False)
4827 handle(revert, False)
4828 else:
4828 else:
4829 handle(remove, False)
4829 handle(remove, False)
4830
4830
4831 if not opts.get('dry_run'):
4831 if not opts.get('dry_run'):
4832 def checkout(f):
4832 def checkout(f):
4833 fc = ctx[f]
4833 fc = ctx[f]
4834 repo.wwrite(f, fc.data(), fc.flags())
4834 repo.wwrite(f, fc.data(), fc.flags())
4835
4835
4836 audit_path = scmutil.pathauditor(repo.root)
4836 audit_path = scmutil.pathauditor(repo.root)
4837 for f in remove[0]:
4837 for f in remove[0]:
4838 if repo.dirstate[f] == 'a':
4838 if repo.dirstate[f] == 'a':
4839 repo.dirstate.drop(f)
4839 repo.dirstate.drop(f)
4840 continue
4840 continue
4841 audit_path(f)
4841 audit_path(f)
4842 try:
4842 try:
4843 util.unlinkpath(repo.wjoin(f))
4843 util.unlinkpath(repo.wjoin(f))
4844 except OSError:
4844 except OSError:
4845 pass
4845 pass
4846 repo.dirstate.remove(f)
4846 repo.dirstate.remove(f)
4847
4847
4848 normal = None
4848 normal = None
4849 if node == parent:
4849 if node == parent:
4850 # We're reverting to our parent. If possible, we'd like status
4850 # We're reverting to our parent. If possible, we'd like status
4851 # to report the file as clean. We have to use normallookup for
4851 # to report the file as clean. We have to use normallookup for
4852 # merges to avoid losing information about merged/dirty files.
4852 # merges to avoid losing information about merged/dirty files.
4853 if p2 != nullid:
4853 if p2 != nullid:
4854 normal = repo.dirstate.normallookup
4854 normal = repo.dirstate.normallookup
4855 else:
4855 else:
4856 normal = repo.dirstate.normal
4856 normal = repo.dirstate.normal
4857 for f in revert[0]:
4857 for f in revert[0]:
4858 checkout(f)
4858 checkout(f)
4859 if normal:
4859 if normal:
4860 normal(f)
4860 normal(f)
4861
4861
4862 for f in add[0]:
4862 for f in add[0]:
4863 checkout(f)
4863 checkout(f)
4864 repo.dirstate.add(f)
4864 repo.dirstate.add(f)
4865
4865
4866 normal = repo.dirstate.normallookup
4866 normal = repo.dirstate.normallookup
4867 if node == parent and p2 == nullid:
4867 if node == parent and p2 == nullid:
4868 normal = repo.dirstate.normal
4868 normal = repo.dirstate.normal
4869 for f in undelete[0]:
4869 for f in undelete[0]:
4870 checkout(f)
4870 checkout(f)
4871 normal(f)
4871 normal(f)
4872
4872
4873 finally:
4873 finally:
4874 wlock.release()
4874 wlock.release()
4875
4875
4876 @command('rollback', dryrunopts +
4876 @command('rollback', dryrunopts +
4877 [('f', 'force', False, _('ignore safety measures'))])
4877 [('f', 'force', False, _('ignore safety measures'))])
4878 def rollback(ui, repo, **opts):
4878 def rollback(ui, repo, **opts):
4879 """roll back the last transaction (dangerous)
4879 """roll back the last transaction (dangerous)
4880
4880
4881 This command should be used with care. There is only one level of
4881 This command should be used with care. There is only one level of
4882 rollback, and there is no way to undo a rollback. It will also
4882 rollback, and there is no way to undo a rollback. It will also
4883 restore the dirstate at the time of the last transaction, losing
4883 restore the dirstate at the time of the last transaction, losing
4884 any dirstate changes since that time. This command does not alter
4884 any dirstate changes since that time. This command does not alter
4885 the working directory.
4885 the working directory.
4886
4886
4887 Transactions are used to encapsulate the effects of all commands
4887 Transactions are used to encapsulate the effects of all commands
4888 that create new changesets or propagate existing changesets into a
4888 that create new changesets or propagate existing changesets into a
4889 repository. For example, the following commands are transactional,
4889 repository. For example, the following commands are transactional,
4890 and their effects can be rolled back:
4890 and their effects can be rolled back:
4891
4891
4892 - commit
4892 - commit
4893 - import
4893 - import
4894 - pull
4894 - pull
4895 - push (with this repository as the destination)
4895 - push (with this repository as the destination)
4896 - unbundle
4896 - unbundle
4897
4897
4898 It's possible to lose data with rollback: commit, update back to
4898 It's possible to lose data with rollback: commit, update back to
4899 an older changeset, and then rollback. The update removes the
4899 an older changeset, and then rollback. The update removes the
4900 changes you committed from the working directory, and rollback
4900 changes you committed from the working directory, and rollback
4901 removes them from history. To avoid data loss, you must pass
4901 removes them from history. To avoid data loss, you must pass
4902 --force in this case.
4902 --force in this case.
4903
4903
4904 This command is not intended for use on public repositories. Once
4904 This command is not intended for use on public repositories. Once
4905 changes are visible for pull by other users, rolling a transaction
4905 changes are visible for pull by other users, rolling a transaction
4906 back locally is ineffective (someone else may already have pulled
4906 back locally is ineffective (someone else may already have pulled
4907 the changes). Furthermore, a race is possible with readers of the
4907 the changes). Furthermore, a race is possible with readers of the
4908 repository; for example an in-progress pull from the repository
4908 repository; for example an in-progress pull from the repository
4909 may fail if a rollback is performed.
4909 may fail if a rollback is performed.
4910
4910
4911 Returns 0 on success, 1 if no rollback data is available.
4911 Returns 0 on success, 1 if no rollback data is available.
4912 """
4912 """
4913 return repo.rollback(dryrun=opts.get('dry_run'),
4913 return repo.rollback(dryrun=opts.get('dry_run'),
4914 force=opts.get('force'))
4914 force=opts.get('force'))
4915
4915
4916 @command('root', [])
4916 @command('root', [])
4917 def root(ui, repo):
4917 def root(ui, repo):
4918 """print the root (top) of the current working directory
4918 """print the root (top) of the current working directory
4919
4919
4920 Print the root directory of the current repository.
4920 Print the root directory of the current repository.
4921
4921
4922 Returns 0 on success.
4922 Returns 0 on success.
4923 """
4923 """
4924 ui.write(repo.root + "\n")
4924 ui.write(repo.root + "\n")
4925
4925
4926 @command('^serve',
4926 @command('^serve',
4927 [('A', 'accesslog', '', _('name of access log file to write to'),
4927 [('A', 'accesslog', '', _('name of access log file to write to'),
4928 _('FILE')),
4928 _('FILE')),
4929 ('d', 'daemon', None, _('run server in background')),
4929 ('d', 'daemon', None, _('run server in background')),
4930 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4930 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4931 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4931 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4932 # use string type, then we can check if something was passed
4932 # use string type, then we can check if something was passed
4933 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4933 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4934 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4934 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4935 _('ADDR')),
4935 _('ADDR')),
4936 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4936 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4937 _('PREFIX')),
4937 _('PREFIX')),
4938 ('n', 'name', '',
4938 ('n', 'name', '',
4939 _('name to show in web pages (default: working directory)'), _('NAME')),
4939 _('name to show in web pages (default: working directory)'), _('NAME')),
4940 ('', 'web-conf', '',
4940 ('', 'web-conf', '',
4941 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4941 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4942 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4942 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4943 _('FILE')),
4943 _('FILE')),
4944 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4944 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4945 ('', 'stdio', None, _('for remote clients')),
4945 ('', 'stdio', None, _('for remote clients')),
4946 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4946 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4947 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4947 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4948 ('', 'style', '', _('template style to use'), _('STYLE')),
4948 ('', 'style', '', _('template style to use'), _('STYLE')),
4949 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4949 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4950 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4950 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4951 _('[OPTION]...'))
4951 _('[OPTION]...'))
4952 def serve(ui, repo, **opts):
4952 def serve(ui, repo, **opts):
4953 """start stand-alone webserver
4953 """start stand-alone webserver
4954
4954
4955 Start a local HTTP repository browser and pull server. You can use
4955 Start a local HTTP repository browser and pull server. You can use
4956 this for ad-hoc sharing and browsing of repositories. It is
4956 this for ad-hoc sharing and browsing of repositories. It is
4957 recommended to use a real web server to serve a repository for
4957 recommended to use a real web server to serve a repository for
4958 longer periods of time.
4958 longer periods of time.
4959
4959
4960 Please note that the server does not implement access control.
4960 Please note that the server does not implement access control.
4961 This means that, by default, anybody can read from the server and
4961 This means that, by default, anybody can read from the server and
4962 nobody can write to it by default. Set the ``web.allow_push``
4962 nobody can write to it by default. Set the ``web.allow_push``
4963 option to ``*`` to allow everybody to push to the server. You
4963 option to ``*`` to allow everybody to push to the server. You
4964 should use a real web server if you need to authenticate users.
4964 should use a real web server if you need to authenticate users.
4965
4965
4966 By default, the server logs accesses to stdout and errors to
4966 By default, the server logs accesses to stdout and errors to
4967 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4967 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4968 files.
4968 files.
4969
4969
4970 To have the server choose a free port number to listen on, specify
4970 To have the server choose a free port number to listen on, specify
4971 a port number of 0; in this case, the server will print the port
4971 a port number of 0; in this case, the server will print the port
4972 number it uses.
4972 number it uses.
4973
4973
4974 Returns 0 on success.
4974 Returns 0 on success.
4975 """
4975 """
4976
4976
4977 if opts["stdio"] and opts["cmdserver"]:
4977 if opts["stdio"] and opts["cmdserver"]:
4978 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4978 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4979
4979
4980 def checkrepo():
4980 def checkrepo():
4981 if repo is None:
4981 if repo is None:
4982 raise error.RepoError(_("There is no Mercurial repository here"
4982 raise error.RepoError(_("There is no Mercurial repository here"
4983 " (.hg not found)"))
4983 " (.hg not found)"))
4984
4984
4985 if opts["stdio"]:
4985 if opts["stdio"]:
4986 checkrepo()
4986 checkrepo()
4987 s = sshserver.sshserver(ui, repo)
4987 s = sshserver.sshserver(ui, repo)
4988 s.serve_forever()
4988 s.serve_forever()
4989
4989
4990 if opts["cmdserver"]:
4990 if opts["cmdserver"]:
4991 checkrepo()
4991 checkrepo()
4992 s = commandserver.server(ui, repo, opts["cmdserver"])
4992 s = commandserver.server(ui, repo, opts["cmdserver"])
4993 return s.serve()
4993 return s.serve()
4994
4994
4995 # this way we can check if something was given in the command-line
4995 # this way we can check if something was given in the command-line
4996 if opts.get('port'):
4996 if opts.get('port'):
4997 opts['port'] = util.getport(opts.get('port'))
4997 opts['port'] = util.getport(opts.get('port'))
4998
4998
4999 baseui = repo and repo.baseui or ui
4999 baseui = repo and repo.baseui or ui
5000 optlist = ("name templates style address port prefix ipv6"
5000 optlist = ("name templates style address port prefix ipv6"
5001 " accesslog errorlog certificate encoding")
5001 " accesslog errorlog certificate encoding")
5002 for o in optlist.split():
5002 for o in optlist.split():
5003 val = opts.get(o, '')
5003 val = opts.get(o, '')
5004 if val in (None, ''): # should check against default options instead
5004 if val in (None, ''): # should check against default options instead
5005 continue
5005 continue
5006 baseui.setconfig("web", o, val)
5006 baseui.setconfig("web", o, val)
5007 if repo and repo.ui != baseui:
5007 if repo and repo.ui != baseui:
5008 repo.ui.setconfig("web", o, val)
5008 repo.ui.setconfig("web", o, val)
5009
5009
5010 o = opts.get('web_conf') or opts.get('webdir_conf')
5010 o = opts.get('web_conf') or opts.get('webdir_conf')
5011 if not o:
5011 if not o:
5012 if not repo:
5012 if not repo:
5013 raise error.RepoError(_("There is no Mercurial repository"
5013 raise error.RepoError(_("There is no Mercurial repository"
5014 " here (.hg not found)"))
5014 " here (.hg not found)"))
5015 o = repo.root
5015 o = repo.root
5016
5016
5017 app = hgweb.hgweb(o, baseui=ui)
5017 app = hgweb.hgweb(o, baseui=ui)
5018
5018
5019 class service(object):
5019 class service(object):
5020 def init(self):
5020 def init(self):
5021 util.setsignalhandler()
5021 util.setsignalhandler()
5022 self.httpd = hgweb.server.create_server(ui, app)
5022 self.httpd = hgweb.server.create_server(ui, app)
5023
5023
5024 if opts['port'] and not ui.verbose:
5024 if opts['port'] and not ui.verbose:
5025 return
5025 return
5026
5026
5027 if self.httpd.prefix:
5027 if self.httpd.prefix:
5028 prefix = self.httpd.prefix.strip('/') + '/'
5028 prefix = self.httpd.prefix.strip('/') + '/'
5029 else:
5029 else:
5030 prefix = ''
5030 prefix = ''
5031
5031
5032 port = ':%d' % self.httpd.port
5032 port = ':%d' % self.httpd.port
5033 if port == ':80':
5033 if port == ':80':
5034 port = ''
5034 port = ''
5035
5035
5036 bindaddr = self.httpd.addr
5036 bindaddr = self.httpd.addr
5037 if bindaddr == '0.0.0.0':
5037 if bindaddr == '0.0.0.0':
5038 bindaddr = '*'
5038 bindaddr = '*'
5039 elif ':' in bindaddr: # IPv6
5039 elif ':' in bindaddr: # IPv6
5040 bindaddr = '[%s]' % bindaddr
5040 bindaddr = '[%s]' % bindaddr
5041
5041
5042 fqaddr = self.httpd.fqaddr
5042 fqaddr = self.httpd.fqaddr
5043 if ':' in fqaddr:
5043 if ':' in fqaddr:
5044 fqaddr = '[%s]' % fqaddr
5044 fqaddr = '[%s]' % fqaddr
5045 if opts['port']:
5045 if opts['port']:
5046 write = ui.status
5046 write = ui.status
5047 else:
5047 else:
5048 write = ui.write
5048 write = ui.write
5049 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5049 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5050 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5050 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5051
5051
5052 def run(self):
5052 def run(self):
5053 self.httpd.serve_forever()
5053 self.httpd.serve_forever()
5054
5054
5055 service = service()
5055 service = service()
5056
5056
5057 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5057 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5058
5058
5059 @command('showconfig|debugconfig',
5059 @command('showconfig|debugconfig',
5060 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5060 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5061 _('[-u] [NAME]...'))
5061 _('[-u] [NAME]...'))
5062 def showconfig(ui, repo, *values, **opts):
5062 def showconfig(ui, repo, *values, **opts):
5063 """show combined config settings from all hgrc files
5063 """show combined config settings from all hgrc files
5064
5064
5065 With no arguments, print names and values of all config items.
5065 With no arguments, print names and values of all config items.
5066
5066
5067 With one argument of the form section.name, print just the value
5067 With one argument of the form section.name, print just the value
5068 of that config item.
5068 of that config item.
5069
5069
5070 With multiple arguments, print names and values of all config
5070 With multiple arguments, print names and values of all config
5071 items with matching section names.
5071 items with matching section names.
5072
5072
5073 With --debug, the source (filename and line number) is printed
5073 With --debug, the source (filename and line number) is printed
5074 for each config item.
5074 for each config item.
5075
5075
5076 Returns 0 on success.
5076 Returns 0 on success.
5077 """
5077 """
5078
5078
5079 for f in scmutil.rcpath():
5079 for f in scmutil.rcpath():
5080 ui.debug('read config from: %s\n' % f)
5080 ui.debug('read config from: %s\n' % f)
5081 untrusted = bool(opts.get('untrusted'))
5081 untrusted = bool(opts.get('untrusted'))
5082 if values:
5082 if values:
5083 sections = [v for v in values if '.' not in v]
5083 sections = [v for v in values if '.' not in v]
5084 items = [v for v in values if '.' in v]
5084 items = [v for v in values if '.' in v]
5085 if len(items) > 1 or items and sections:
5085 if len(items) > 1 or items and sections:
5086 raise util.Abort(_('only one config item permitted'))
5086 raise util.Abort(_('only one config item permitted'))
5087 for section, name, value in ui.walkconfig(untrusted=untrusted):
5087 for section, name, value in ui.walkconfig(untrusted=untrusted):
5088 value = str(value).replace('\n', '\\n')
5088 value = str(value).replace('\n', '\\n')
5089 sectname = section + '.' + name
5089 sectname = section + '.' + name
5090 if values:
5090 if values:
5091 for v in values:
5091 for v in values:
5092 if v == section:
5092 if v == section:
5093 ui.debug('%s: ' %
5093 ui.debug('%s: ' %
5094 ui.configsource(section, name, untrusted))
5094 ui.configsource(section, name, untrusted))
5095 ui.write('%s=%s\n' % (sectname, value))
5095 ui.write('%s=%s\n' % (sectname, value))
5096 elif v == sectname:
5096 elif v == sectname:
5097 ui.debug('%s: ' %
5097 ui.debug('%s: ' %
5098 ui.configsource(section, name, untrusted))
5098 ui.configsource(section, name, untrusted))
5099 ui.write(value, '\n')
5099 ui.write(value, '\n')
5100 else:
5100 else:
5101 ui.debug('%s: ' %
5101 ui.debug('%s: ' %
5102 ui.configsource(section, name, untrusted))
5102 ui.configsource(section, name, untrusted))
5103 ui.write('%s=%s\n' % (sectname, value))
5103 ui.write('%s=%s\n' % (sectname, value))
5104
5104
5105 @command('^status|st',
5105 @command('^status|st',
5106 [('A', 'all', None, _('show status of all files')),
5106 [('A', 'all', None, _('show status of all files')),
5107 ('m', 'modified', None, _('show only modified files')),
5107 ('m', 'modified', None, _('show only modified files')),
5108 ('a', 'added', None, _('show only added files')),
5108 ('a', 'added', None, _('show only added files')),
5109 ('r', 'removed', None, _('show only removed files')),
5109 ('r', 'removed', None, _('show only removed files')),
5110 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5110 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5111 ('c', 'clean', None, _('show only files without changes')),
5111 ('c', 'clean', None, _('show only files without changes')),
5112 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5112 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5113 ('i', 'ignored', None, _('show only ignored files')),
5113 ('i', 'ignored', None, _('show only ignored files')),
5114 ('n', 'no-status', None, _('hide status prefix')),
5114 ('n', 'no-status', None, _('hide status prefix')),
5115 ('C', 'copies', None, _('show source of copied files')),
5115 ('C', 'copies', None, _('show source of copied files')),
5116 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5116 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5117 ('', 'rev', [], _('show difference from revision'), _('REV')),
5117 ('', 'rev', [], _('show difference from revision'), _('REV')),
5118 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5118 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5119 ] + walkopts + subrepoopts,
5119 ] + walkopts + subrepoopts,
5120 _('[OPTION]... [FILE]...'))
5120 _('[OPTION]... [FILE]...'))
5121 def status(ui, repo, *pats, **opts):
5121 def status(ui, repo, *pats, **opts):
5122 """show changed files in the working directory
5122 """show changed files in the working directory
5123
5123
5124 Show status of files in the repository. If names are given, only
5124 Show status of files in the repository. If names are given, only
5125 files that match are shown. Files that are clean or ignored or
5125 files that match are shown. Files that are clean or ignored or
5126 the source of a copy/move operation, are not listed unless
5126 the source of a copy/move operation, are not listed unless
5127 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5127 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5128 Unless options described with "show only ..." are given, the
5128 Unless options described with "show only ..." are given, the
5129 options -mardu are used.
5129 options -mardu are used.
5130
5130
5131 Option -q/--quiet hides untracked (unknown and ignored) files
5131 Option -q/--quiet hides untracked (unknown and ignored) files
5132 unless explicitly requested with -u/--unknown or -i/--ignored.
5132 unless explicitly requested with -u/--unknown or -i/--ignored.
5133
5133
5134 .. note::
5134 .. note::
5135 status may appear to disagree with diff if permissions have
5135 status may appear to disagree with diff if permissions have
5136 changed or a merge has occurred. The standard diff format does
5136 changed or a merge has occurred. The standard diff format does
5137 not report permission changes and diff only reports changes
5137 not report permission changes and diff only reports changes
5138 relative to one merge parent.
5138 relative to one merge parent.
5139
5139
5140 If one revision is given, it is used as the base revision.
5140 If one revision is given, it is used as the base revision.
5141 If two revisions are given, the differences between them are
5141 If two revisions are given, the differences between them are
5142 shown. The --change option can also be used as a shortcut to list
5142 shown. The --change option can also be used as a shortcut to list
5143 the changed files of a revision from its first parent.
5143 the changed files of a revision from its first parent.
5144
5144
5145 The codes used to show the status of files are::
5145 The codes used to show the status of files are::
5146
5146
5147 M = modified
5147 M = modified
5148 A = added
5148 A = added
5149 R = removed
5149 R = removed
5150 C = clean
5150 C = clean
5151 ! = missing (deleted by non-hg command, but still tracked)
5151 ! = missing (deleted by non-hg command, but still tracked)
5152 ? = not tracked
5152 ? = not tracked
5153 I = ignored
5153 I = ignored
5154 = origin of the previous file listed as A (added)
5154 = origin of the previous file listed as A (added)
5155
5155
5156 .. container:: verbose
5156 .. container:: verbose
5157
5157
5158 Examples:
5158 Examples:
5159
5159
5160 - show changes in the working directory relative to a
5160 - show changes in the working directory relative to a
5161 changeset::
5161 changeset::
5162
5162
5163 hg status --rev 9353
5163 hg status --rev 9353
5164
5164
5165 - show all changes including copies in an existing changeset::
5165 - show all changes including copies in an existing changeset::
5166
5166
5167 hg status --copies --change 9353
5167 hg status --copies --change 9353
5168
5168
5169 - get a NUL separated list of added files, suitable for xargs::
5169 - get a NUL separated list of added files, suitable for xargs::
5170
5170
5171 hg status -an0
5171 hg status -an0
5172
5172
5173 Returns 0 on success.
5173 Returns 0 on success.
5174 """
5174 """
5175
5175
5176 revs = opts.get('rev')
5176 revs = opts.get('rev')
5177 change = opts.get('change')
5177 change = opts.get('change')
5178
5178
5179 if revs and change:
5179 if revs and change:
5180 msg = _('cannot specify --rev and --change at the same time')
5180 msg = _('cannot specify --rev and --change at the same time')
5181 raise util.Abort(msg)
5181 raise util.Abort(msg)
5182 elif change:
5182 elif change:
5183 node2 = scmutil.revsingle(repo, change, None).node()
5183 node2 = scmutil.revsingle(repo, change, None).node()
5184 node1 = repo[node2].p1().node()
5184 node1 = repo[node2].p1().node()
5185 else:
5185 else:
5186 node1, node2 = scmutil.revpair(repo, revs)
5186 node1, node2 = scmutil.revpair(repo, revs)
5187
5187
5188 cwd = (pats and repo.getcwd()) or ''
5188 cwd = (pats and repo.getcwd()) or ''
5189 end = opts.get('print0') and '\0' or '\n'
5189 end = opts.get('print0') and '\0' or '\n'
5190 copy = {}
5190 copy = {}
5191 states = 'modified added removed deleted unknown ignored clean'.split()
5191 states = 'modified added removed deleted unknown ignored clean'.split()
5192 show = [k for k in states if opts.get(k)]
5192 show = [k for k in states if opts.get(k)]
5193 if opts.get('all'):
5193 if opts.get('all'):
5194 show += ui.quiet and (states[:4] + ['clean']) or states
5194 show += ui.quiet and (states[:4] + ['clean']) or states
5195 if not show:
5195 if not show:
5196 show = ui.quiet and states[:4] or states[:5]
5196 show = ui.quiet and states[:4] or states[:5]
5197
5197
5198 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5198 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5199 'ignored' in show, 'clean' in show, 'unknown' in show,
5199 'ignored' in show, 'clean' in show, 'unknown' in show,
5200 opts.get('subrepos'))
5200 opts.get('subrepos'))
5201 changestates = zip(states, 'MAR!?IC', stat)
5201 changestates = zip(states, 'MAR!?IC', stat)
5202
5202
5203 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5203 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5204 ctxn = repo[nullid]
5204 ctxn = repo[nullid]
5205 ctx1 = repo[node1]
5205 ctx1 = repo[node1]
5206 ctx2 = repo[node2]
5206 ctx2 = repo[node2]
5207 added = stat[1]
5207 added = stat[1]
5208 if node2 is None:
5208 if node2 is None:
5209 added = stat[0] + stat[1] # merged?
5209 added = stat[0] + stat[1] # merged?
5210
5210
5211 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
5211 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
5212 if k in added:
5212 if k in added:
5213 copy[k] = v
5213 copy[k] = v
5214 elif v in added:
5214 elif v in added:
5215 copy[v] = k
5215 copy[v] = k
5216
5216
5217 for state, char, files in changestates:
5217 for state, char, files in changestates:
5218 if state in show:
5218 if state in show:
5219 format = "%s %%s%s" % (char, end)
5219 format = "%s %%s%s" % (char, end)
5220 if opts.get('no_status'):
5220 if opts.get('no_status'):
5221 format = "%%s%s" % end
5221 format = "%%s%s" % end
5222
5222
5223 for f in files:
5223 for f in files:
5224 ui.write(format % repo.pathto(f, cwd),
5224 ui.write(format % repo.pathto(f, cwd),
5225 label='status.' + state)
5225 label='status.' + state)
5226 if f in copy:
5226 if f in copy:
5227 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5227 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5228 label='status.copied')
5228 label='status.copied')
5229
5229
5230 @command('^summary|sum',
5230 @command('^summary|sum',
5231 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5231 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5232 def summary(ui, repo, **opts):
5232 def summary(ui, repo, **opts):
5233 """summarize working directory state
5233 """summarize working directory state
5234
5234
5235 This generates a brief summary of the working directory state,
5235 This generates a brief summary of the working directory state,
5236 including parents, branch, commit status, and available updates.
5236 including parents, branch, commit status, and available updates.
5237
5237
5238 With the --remote option, this will check the default paths for
5238 With the --remote option, this will check the default paths for
5239 incoming and outgoing changes. This can be time-consuming.
5239 incoming and outgoing changes. This can be time-consuming.
5240
5240
5241 Returns 0 on success.
5241 Returns 0 on success.
5242 """
5242 """
5243
5243
5244 ctx = repo[None]
5244 ctx = repo[None]
5245 parents = ctx.parents()
5245 parents = ctx.parents()
5246 pnode = parents[0].node()
5246 pnode = parents[0].node()
5247 marks = []
5247 marks = []
5248
5248
5249 for p in parents:
5249 for p in parents:
5250 # label with log.changeset (instead of log.parent) since this
5250 # label with log.changeset (instead of log.parent) since this
5251 # shows a working directory parent *changeset*:
5251 # shows a working directory parent *changeset*:
5252 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5252 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5253 label='log.changeset')
5253 label='log.changeset')
5254 ui.write(' '.join(p.tags()), label='log.tag')
5254 ui.write(' '.join(p.tags()), label='log.tag')
5255 if p.bookmarks():
5255 if p.bookmarks():
5256 marks.extend(p.bookmarks())
5256 marks.extend(p.bookmarks())
5257 if p.rev() == -1:
5257 if p.rev() == -1:
5258 if not len(repo):
5258 if not len(repo):
5259 ui.write(_(' (empty repository)'))
5259 ui.write(_(' (empty repository)'))
5260 else:
5260 else:
5261 ui.write(_(' (no revision checked out)'))
5261 ui.write(_(' (no revision checked out)'))
5262 ui.write('\n')
5262 ui.write('\n')
5263 if p.description():
5263 if p.description():
5264 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5264 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5265 label='log.summary')
5265 label='log.summary')
5266
5266
5267 branch = ctx.branch()
5267 branch = ctx.branch()
5268 bheads = repo.branchheads(branch)
5268 bheads = repo.branchheads(branch)
5269 m = _('branch: %s\n') % branch
5269 m = _('branch: %s\n') % branch
5270 if branch != 'default':
5270 if branch != 'default':
5271 ui.write(m, label='log.branch')
5271 ui.write(m, label='log.branch')
5272 else:
5272 else:
5273 ui.status(m, label='log.branch')
5273 ui.status(m, label='log.branch')
5274
5274
5275 if marks:
5275 if marks:
5276 current = repo._bookmarkcurrent
5276 current = repo._bookmarkcurrent
5277 ui.write(_('bookmarks:'), label='log.bookmark')
5277 ui.write(_('bookmarks:'), label='log.bookmark')
5278 if current is not None:
5278 if current is not None:
5279 try:
5279 try:
5280 marks.remove(current)
5280 marks.remove(current)
5281 ui.write(' *' + current, label='bookmarks.current')
5281 ui.write(' *' + current, label='bookmarks.current')
5282 except ValueError:
5282 except ValueError:
5283 # current bookmark not in parent ctx marks
5283 # current bookmark not in parent ctx marks
5284 pass
5284 pass
5285 for m in marks:
5285 for m in marks:
5286 ui.write(' ' + m, label='log.bookmark')
5286 ui.write(' ' + m, label='log.bookmark')
5287 ui.write('\n', label='log.bookmark')
5287 ui.write('\n', label='log.bookmark')
5288
5288
5289 st = list(repo.status(unknown=True))[:6]
5289 st = list(repo.status(unknown=True))[:6]
5290
5290
5291 c = repo.dirstate.copies()
5291 c = repo.dirstate.copies()
5292 copied, renamed = [], []
5292 copied, renamed = [], []
5293 for d, s in c.iteritems():
5293 for d, s in c.iteritems():
5294 if s in st[2]:
5294 if s in st[2]:
5295 st[2].remove(s)
5295 st[2].remove(s)
5296 renamed.append(d)
5296 renamed.append(d)
5297 else:
5297 else:
5298 copied.append(d)
5298 copied.append(d)
5299 if d in st[1]:
5299 if d in st[1]:
5300 st[1].remove(d)
5300 st[1].remove(d)
5301 st.insert(3, renamed)
5301 st.insert(3, renamed)
5302 st.insert(4, copied)
5302 st.insert(4, copied)
5303
5303
5304 ms = mergemod.mergestate(repo)
5304 ms = mergemod.mergestate(repo)
5305 st.append([f for f in ms if ms[f] == 'u'])
5305 st.append([f for f in ms if ms[f] == 'u'])
5306
5306
5307 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5307 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5308 st.append(subs)
5308 st.append(subs)
5309
5309
5310 labels = [ui.label(_('%d modified'), 'status.modified'),
5310 labels = [ui.label(_('%d modified'), 'status.modified'),
5311 ui.label(_('%d added'), 'status.added'),
5311 ui.label(_('%d added'), 'status.added'),
5312 ui.label(_('%d removed'), 'status.removed'),
5312 ui.label(_('%d removed'), 'status.removed'),
5313 ui.label(_('%d renamed'), 'status.copied'),
5313 ui.label(_('%d renamed'), 'status.copied'),
5314 ui.label(_('%d copied'), 'status.copied'),
5314 ui.label(_('%d copied'), 'status.copied'),
5315 ui.label(_('%d deleted'), 'status.deleted'),
5315 ui.label(_('%d deleted'), 'status.deleted'),
5316 ui.label(_('%d unknown'), 'status.unknown'),
5316 ui.label(_('%d unknown'), 'status.unknown'),
5317 ui.label(_('%d ignored'), 'status.ignored'),
5317 ui.label(_('%d ignored'), 'status.ignored'),
5318 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5318 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5319 ui.label(_('%d subrepos'), 'status.modified')]
5319 ui.label(_('%d subrepos'), 'status.modified')]
5320 t = []
5320 t = []
5321 for s, l in zip(st, labels):
5321 for s, l in zip(st, labels):
5322 if s:
5322 if s:
5323 t.append(l % len(s))
5323 t.append(l % len(s))
5324
5324
5325 t = ', '.join(t)
5325 t = ', '.join(t)
5326 cleanworkdir = False
5326 cleanworkdir = False
5327
5327
5328 if len(parents) > 1:
5328 if len(parents) > 1:
5329 t += _(' (merge)')
5329 t += _(' (merge)')
5330 elif branch != parents[0].branch():
5330 elif branch != parents[0].branch():
5331 t += _(' (new branch)')
5331 t += _(' (new branch)')
5332 elif (parents[0].extra().get('close') and
5332 elif (parents[0].extra().get('close') and
5333 pnode in repo.branchheads(branch, closed=True)):
5333 pnode in repo.branchheads(branch, closed=True)):
5334 t += _(' (head closed)')
5334 t += _(' (head closed)')
5335 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5335 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5336 t += _(' (clean)')
5336 t += _(' (clean)')
5337 cleanworkdir = True
5337 cleanworkdir = True
5338 elif pnode not in bheads:
5338 elif pnode not in bheads:
5339 t += _(' (new branch head)')
5339 t += _(' (new branch head)')
5340
5340
5341 if cleanworkdir:
5341 if cleanworkdir:
5342 ui.status(_('commit: %s\n') % t.strip())
5342 ui.status(_('commit: %s\n') % t.strip())
5343 else:
5343 else:
5344 ui.write(_('commit: %s\n') % t.strip())
5344 ui.write(_('commit: %s\n') % t.strip())
5345
5345
5346 # all ancestors of branch heads - all ancestors of parent = new csets
5346 # all ancestors of branch heads - all ancestors of parent = new csets
5347 new = [0] * len(repo)
5347 new = [0] * len(repo)
5348 cl = repo.changelog
5348 cl = repo.changelog
5349 for a in [cl.rev(n) for n in bheads]:
5349 for a in [cl.rev(n) for n in bheads]:
5350 new[a] = 1
5350 new[a] = 1
5351 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5351 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5352 new[a] = 1
5352 new[a] = 1
5353 for a in [p.rev() for p in parents]:
5353 for a in [p.rev() for p in parents]:
5354 if a >= 0:
5354 if a >= 0:
5355 new[a] = 0
5355 new[a] = 0
5356 for a in cl.ancestors(*[p.rev() for p in parents]):
5356 for a in cl.ancestors(*[p.rev() for p in parents]):
5357 new[a] = 0
5357 new[a] = 0
5358 new = sum(new)
5358 new = sum(new)
5359
5359
5360 if new == 0:
5360 if new == 0:
5361 ui.status(_('update: (current)\n'))
5361 ui.status(_('update: (current)\n'))
5362 elif pnode not in bheads:
5362 elif pnode not in bheads:
5363 ui.write(_('update: %d new changesets (update)\n') % new)
5363 ui.write(_('update: %d new changesets (update)\n') % new)
5364 else:
5364 else:
5365 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5365 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5366 (new, len(bheads)))
5366 (new, len(bheads)))
5367
5367
5368 if opts.get('remote'):
5368 if opts.get('remote'):
5369 t = []
5369 t = []
5370 source, branches = hg.parseurl(ui.expandpath('default'))
5370 source, branches = hg.parseurl(ui.expandpath('default'))
5371 other = hg.peer(repo, {}, source)
5371 other = hg.peer(repo, {}, source)
5372 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5372 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5373 ui.debug('comparing with %s\n' % util.hidepassword(source))
5373 ui.debug('comparing with %s\n' % util.hidepassword(source))
5374 repo.ui.pushbuffer()
5374 repo.ui.pushbuffer()
5375 commoninc = discovery.findcommonincoming(repo, other)
5375 commoninc = discovery.findcommonincoming(repo, other)
5376 _common, incoming, _rheads = commoninc
5376 _common, incoming, _rheads = commoninc
5377 repo.ui.popbuffer()
5377 repo.ui.popbuffer()
5378 if incoming:
5378 if incoming:
5379 t.append(_('1 or more incoming'))
5379 t.append(_('1 or more incoming'))
5380
5380
5381 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5381 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5382 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5382 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5383 if source != dest:
5383 if source != dest:
5384 other = hg.peer(repo, {}, dest)
5384 other = hg.peer(repo, {}, dest)
5385 commoninc = None
5385 commoninc = None
5386 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5386 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5387 repo.ui.pushbuffer()
5387 repo.ui.pushbuffer()
5388 common, outheads = discovery.findcommonoutgoing(repo, other,
5388 common, outheads = discovery.findcommonoutgoing(repo, other,
5389 commoninc=commoninc)
5389 commoninc=commoninc)
5390 repo.ui.popbuffer()
5390 repo.ui.popbuffer()
5391 o = repo.changelog.findmissing(common=common, heads=outheads)
5391 o = repo.changelog.findmissing(common=common, heads=outheads)
5392 if o:
5392 if o:
5393 t.append(_('%d outgoing') % len(o))
5393 t.append(_('%d outgoing') % len(o))
5394 if 'bookmarks' in other.listkeys('namespaces'):
5394 if 'bookmarks' in other.listkeys('namespaces'):
5395 lmarks = repo.listkeys('bookmarks')
5395 lmarks = repo.listkeys('bookmarks')
5396 rmarks = other.listkeys('bookmarks')
5396 rmarks = other.listkeys('bookmarks')
5397 diff = set(rmarks) - set(lmarks)
5397 diff = set(rmarks) - set(lmarks)
5398 if len(diff) > 0:
5398 if len(diff) > 0:
5399 t.append(_('%d incoming bookmarks') % len(diff))
5399 t.append(_('%d incoming bookmarks') % len(diff))
5400 diff = set(lmarks) - set(rmarks)
5400 diff = set(lmarks) - set(rmarks)
5401 if len(diff) > 0:
5401 if len(diff) > 0:
5402 t.append(_('%d outgoing bookmarks') % len(diff))
5402 t.append(_('%d outgoing bookmarks') % len(diff))
5403
5403
5404 if t:
5404 if t:
5405 ui.write(_('remote: %s\n') % (', '.join(t)))
5405 ui.write(_('remote: %s\n') % (', '.join(t)))
5406 else:
5406 else:
5407 ui.status(_('remote: (synced)\n'))
5407 ui.status(_('remote: (synced)\n'))
5408
5408
5409 @command('tag',
5409 @command('tag',
5410 [('f', 'force', None, _('force tag')),
5410 [('f', 'force', None, _('force tag')),
5411 ('l', 'local', None, _('make the tag local')),
5411 ('l', 'local', None, _('make the tag local')),
5412 ('r', 'rev', '', _('revision to tag'), _('REV')),
5412 ('r', 'rev', '', _('revision to tag'), _('REV')),
5413 ('', 'remove', None, _('remove a tag')),
5413 ('', 'remove', None, _('remove a tag')),
5414 # -l/--local is already there, commitopts cannot be used
5414 # -l/--local is already there, commitopts cannot be used
5415 ('e', 'edit', None, _('edit commit message')),
5415 ('e', 'edit', None, _('edit commit message')),
5416 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5416 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5417 ] + commitopts2,
5417 ] + commitopts2,
5418 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5418 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5419 def tag(ui, repo, name1, *names, **opts):
5419 def tag(ui, repo, name1, *names, **opts):
5420 """add one or more tags for the current or given revision
5420 """add one or more tags for the current or given revision
5421
5421
5422 Name a particular revision using <name>.
5422 Name a particular revision using <name>.
5423
5423
5424 Tags are used to name particular revisions of the repository and are
5424 Tags are used to name particular revisions of the repository and are
5425 very useful to compare different revisions, to go back to significant
5425 very useful to compare different revisions, to go back to significant
5426 earlier versions or to mark branch points as releases, etc. Changing
5426 earlier versions or to mark branch points as releases, etc. Changing
5427 an existing tag is normally disallowed; use -f/--force to override.
5427 an existing tag is normally disallowed; use -f/--force to override.
5428
5428
5429 If no revision is given, the parent of the working directory is
5429 If no revision is given, the parent of the working directory is
5430 used, or tip if no revision is checked out.
5430 used, or tip if no revision is checked out.
5431
5431
5432 To facilitate version control, distribution, and merging of tags,
5432 To facilitate version control, distribution, and merging of tags,
5433 they are stored as a file named ".hgtags" which is managed similarly
5433 they are stored as a file named ".hgtags" which is managed similarly
5434 to other project files and can be hand-edited if necessary. This
5434 to other project files and can be hand-edited if necessary. This
5435 also means that tagging creates a new commit. The file
5435 also means that tagging creates a new commit. The file
5436 ".hg/localtags" is used for local tags (not shared among
5436 ".hg/localtags" is used for local tags (not shared among
5437 repositories).
5437 repositories).
5438
5438
5439 Tag commits are usually made at the head of a branch. If the parent
5439 Tag commits are usually made at the head of a branch. If the parent
5440 of the working directory is not a branch head, :hg:`tag` aborts; use
5440 of the working directory is not a branch head, :hg:`tag` aborts; use
5441 -f/--force to force the tag commit to be based on a non-head
5441 -f/--force to force the tag commit to be based on a non-head
5442 changeset.
5442 changeset.
5443
5443
5444 See :hg:`help dates` for a list of formats valid for -d/--date.
5444 See :hg:`help dates` for a list of formats valid for -d/--date.
5445
5445
5446 Since tag names have priority over branch names during revision
5446 Since tag names have priority over branch names during revision
5447 lookup, using an existing branch name as a tag name is discouraged.
5447 lookup, using an existing branch name as a tag name is discouraged.
5448
5448
5449 Returns 0 on success.
5449 Returns 0 on success.
5450 """
5450 """
5451
5451
5452 rev_ = "."
5452 rev_ = "."
5453 names = [t.strip() for t in (name1,) + names]
5453 names = [t.strip() for t in (name1,) + names]
5454 if len(names) != len(set(names)):
5454 if len(names) != len(set(names)):
5455 raise util.Abort(_('tag names must be unique'))
5455 raise util.Abort(_('tag names must be unique'))
5456 for n in names:
5456 for n in names:
5457 if n in ['tip', '.', 'null']:
5457 if n in ['tip', '.', 'null']:
5458 raise util.Abort(_("the name '%s' is reserved") % n)
5458 raise util.Abort(_("the name '%s' is reserved") % n)
5459 if not n:
5459 if not n:
5460 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5460 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5461 if opts.get('rev') and opts.get('remove'):
5461 if opts.get('rev') and opts.get('remove'):
5462 raise util.Abort(_("--rev and --remove are incompatible"))
5462 raise util.Abort(_("--rev and --remove are incompatible"))
5463 if opts.get('rev'):
5463 if opts.get('rev'):
5464 rev_ = opts['rev']
5464 rev_ = opts['rev']
5465 message = opts.get('message')
5465 message = opts.get('message')
5466 if opts.get('remove'):
5466 if opts.get('remove'):
5467 expectedtype = opts.get('local') and 'local' or 'global'
5467 expectedtype = opts.get('local') and 'local' or 'global'
5468 for n in names:
5468 for n in names:
5469 if not repo.tagtype(n):
5469 if not repo.tagtype(n):
5470 raise util.Abort(_("tag '%s' does not exist") % n)
5470 raise util.Abort(_("tag '%s' does not exist") % n)
5471 if repo.tagtype(n) != expectedtype:
5471 if repo.tagtype(n) != expectedtype:
5472 if expectedtype == 'global':
5472 if expectedtype == 'global':
5473 raise util.Abort(_("tag '%s' is not a global tag") % n)
5473 raise util.Abort(_("tag '%s' is not a global tag") % n)
5474 else:
5474 else:
5475 raise util.Abort(_("tag '%s' is not a local tag") % n)
5475 raise util.Abort(_("tag '%s' is not a local tag") % n)
5476 rev_ = nullid
5476 rev_ = nullid
5477 if not message:
5477 if not message:
5478 # we don't translate commit messages
5478 # we don't translate commit messages
5479 message = 'Removed tag %s' % ', '.join(names)
5479 message = 'Removed tag %s' % ', '.join(names)
5480 elif not opts.get('force'):
5480 elif not opts.get('force'):
5481 for n in names:
5481 for n in names:
5482 if n in repo.tags():
5482 if n in repo.tags():
5483 raise util.Abort(_("tag '%s' already exists "
5483 raise util.Abort(_("tag '%s' already exists "
5484 "(use -f to force)") % n)
5484 "(use -f to force)") % n)
5485 if not opts.get('local'):
5485 if not opts.get('local'):
5486 p1, p2 = repo.dirstate.parents()
5486 p1, p2 = repo.dirstate.parents()
5487 if p2 != nullid:
5487 if p2 != nullid:
5488 raise util.Abort(_('uncommitted merge'))
5488 raise util.Abort(_('uncommitted merge'))
5489 bheads = repo.branchheads()
5489 bheads = repo.branchheads()
5490 if not opts.get('force') and bheads and p1 not in bheads:
5490 if not opts.get('force') and bheads and p1 not in bheads:
5491 raise util.Abort(_('not at a branch head (use -f to force)'))
5491 raise util.Abort(_('not at a branch head (use -f to force)'))
5492 r = scmutil.revsingle(repo, rev_).node()
5492 r = scmutil.revsingle(repo, rev_).node()
5493
5493
5494 if not message:
5494 if not message:
5495 # we don't translate commit messages
5495 # we don't translate commit messages
5496 message = ('Added tag %s for changeset %s' %
5496 message = ('Added tag %s for changeset %s' %
5497 (', '.join(names), short(r)))
5497 (', '.join(names), short(r)))
5498
5498
5499 date = opts.get('date')
5499 date = opts.get('date')
5500 if date:
5500 if date:
5501 date = util.parsedate(date)
5501 date = util.parsedate(date)
5502
5502
5503 if opts.get('edit'):
5503 if opts.get('edit'):
5504 message = ui.edit(message, ui.username())
5504 message = ui.edit(message, ui.username())
5505
5505
5506 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5506 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5507
5507
5508 @command('tags', [], '')
5508 @command('tags', [], '')
5509 def tags(ui, repo):
5509 def tags(ui, repo):
5510 """list repository tags
5510 """list repository tags
5511
5511
5512 This lists both regular and local tags. When the -v/--verbose
5512 This lists both regular and local tags. When the -v/--verbose
5513 switch is used, a third column "local" is printed for local tags.
5513 switch is used, a third column "local" is printed for local tags.
5514
5514
5515 Returns 0 on success.
5515 Returns 0 on success.
5516 """
5516 """
5517
5517
5518 hexfunc = ui.debugflag and hex or short
5518 hexfunc = ui.debugflag and hex or short
5519 tagtype = ""
5519 tagtype = ""
5520
5520
5521 for t, n in reversed(repo.tagslist()):
5521 for t, n in reversed(repo.tagslist()):
5522 if ui.quiet:
5522 if ui.quiet:
5523 ui.write("%s\n" % t, label='tags.normal')
5523 ui.write("%s\n" % t, label='tags.normal')
5524 continue
5524 continue
5525
5525
5526 hn = hexfunc(n)
5526 hn = hexfunc(n)
5527 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5527 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5528 rev = ui.label(r, 'log.changeset')
5528 rev = ui.label(r, 'log.changeset')
5529 spaces = " " * (30 - encoding.colwidth(t))
5529 spaces = " " * (30 - encoding.colwidth(t))
5530
5530
5531 tag = ui.label(t, 'tags.normal')
5531 tag = ui.label(t, 'tags.normal')
5532 if ui.verbose:
5532 if ui.verbose:
5533 if repo.tagtype(t) == 'local':
5533 if repo.tagtype(t) == 'local':
5534 tagtype = " local"
5534 tagtype = " local"
5535 tag = ui.label(t, 'tags.local')
5535 tag = ui.label(t, 'tags.local')
5536 else:
5536 else:
5537 tagtype = ""
5537 tagtype = ""
5538 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5538 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5539
5539
5540 @command('tip',
5540 @command('tip',
5541 [('p', 'patch', None, _('show patch')),
5541 [('p', 'patch', None, _('show patch')),
5542 ('g', 'git', None, _('use git extended diff format')),
5542 ('g', 'git', None, _('use git extended diff format')),
5543 ] + templateopts,
5543 ] + templateopts,
5544 _('[-p] [-g]'))
5544 _('[-p] [-g]'))
5545 def tip(ui, repo, **opts):
5545 def tip(ui, repo, **opts):
5546 """show the tip revision
5546 """show the tip revision
5547
5547
5548 The tip revision (usually just called the tip) is the changeset
5548 The tip revision (usually just called the tip) is the changeset
5549 most recently added to the repository (and therefore the most
5549 most recently added to the repository (and therefore the most
5550 recently changed head).
5550 recently changed head).
5551
5551
5552 If you have just made a commit, that commit will be the tip. If
5552 If you have just made a commit, that commit will be the tip. If
5553 you have just pulled changes from another repository, the tip of
5553 you have just pulled changes from another repository, the tip of
5554 that repository becomes the current tip. The "tip" tag is special
5554 that repository becomes the current tip. The "tip" tag is special
5555 and cannot be renamed or assigned to a different changeset.
5555 and cannot be renamed or assigned to a different changeset.
5556
5556
5557 Returns 0 on success.
5557 Returns 0 on success.
5558 """
5558 """
5559 displayer = cmdutil.show_changeset(ui, repo, opts)
5559 displayer = cmdutil.show_changeset(ui, repo, opts)
5560 displayer.show(repo[len(repo) - 1])
5560 displayer.show(repo[len(repo) - 1])
5561 displayer.close()
5561 displayer.close()
5562
5562
5563 @command('unbundle',
5563 @command('unbundle',
5564 [('u', 'update', None,
5564 [('u', 'update', None,
5565 _('update to new branch head if changesets were unbundled'))],
5565 _('update to new branch head if changesets were unbundled'))],
5566 _('[-u] FILE...'))
5566 _('[-u] FILE...'))
5567 def unbundle(ui, repo, fname1, *fnames, **opts):
5567 def unbundle(ui, repo, fname1, *fnames, **opts):
5568 """apply one or more changegroup files
5568 """apply one or more changegroup files
5569
5569
5570 Apply one or more compressed changegroup files generated by the
5570 Apply one or more compressed changegroup files generated by the
5571 bundle command.
5571 bundle command.
5572
5572
5573 Returns 0 on success, 1 if an update has unresolved files.
5573 Returns 0 on success, 1 if an update has unresolved files.
5574 """
5574 """
5575 fnames = (fname1,) + fnames
5575 fnames = (fname1,) + fnames
5576
5576
5577 lock = repo.lock()
5577 lock = repo.lock()
5578 wc = repo['.']
5578 wc = repo['.']
5579 try:
5579 try:
5580 for fname in fnames:
5580 for fname in fnames:
5581 f = url.open(ui, fname)
5581 f = url.open(ui, fname)
5582 gen = changegroup.readbundle(f, fname)
5582 gen = changegroup.readbundle(f, fname)
5583 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5583 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5584 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5584 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5585 finally:
5585 finally:
5586 lock.release()
5586 lock.release()
5587 return postincoming(ui, repo, modheads, opts.get('update'), None)
5587 return postincoming(ui, repo, modheads, opts.get('update'), None)
5588
5588
5589 @command('^update|up|checkout|co',
5589 @command('^update|up|checkout|co',
5590 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5590 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5591 ('c', 'check', None,
5591 ('c', 'check', None,
5592 _('update across branches if no uncommitted changes')),
5592 _('update across branches if no uncommitted changes')),
5593 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5593 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5594 ('r', 'rev', '', _('revision'), _('REV'))],
5594 ('r', 'rev', '', _('revision'), _('REV'))],
5595 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5595 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5596 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5596 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5597 """update working directory (or switch revisions)
5597 """update working directory (or switch revisions)
5598
5598
5599 Update the repository's working directory to the specified
5599 Update the repository's working directory to the specified
5600 changeset. If no changeset is specified, update to the tip of the
5600 changeset. If no changeset is specified, update to the tip of the
5601 current named branch.
5601 current named branch.
5602
5602
5603 If the changeset is not a descendant of the working directory's
5603 If the changeset is not a descendant of the working directory's
5604 parent, the update is aborted. With the -c/--check option, the
5604 parent, the update is aborted. With the -c/--check option, the
5605 working directory is checked for uncommitted changes; if none are
5605 working directory is checked for uncommitted changes; if none are
5606 found, the working directory is updated to the specified
5606 found, the working directory is updated to the specified
5607 changeset.
5607 changeset.
5608
5608
5609 Update sets the working directory's parent revison to the specified
5609 Update sets the working directory's parent revison to the specified
5610 changeset (see :hg:`help parents`).
5610 changeset (see :hg:`help parents`).
5611
5611
5612 The following rules apply when the working directory contains
5612 The following rules apply when the working directory contains
5613 uncommitted changes:
5613 uncommitted changes:
5614
5614
5615 1. If neither -c/--check nor -C/--clean is specified, and if
5615 1. If neither -c/--check nor -C/--clean is specified, and if
5616 the requested changeset is an ancestor or descendant of
5616 the requested changeset is an ancestor or descendant of
5617 the working directory's parent, the uncommitted changes
5617 the working directory's parent, the uncommitted changes
5618 are merged into the requested changeset and the merged
5618 are merged into the requested changeset and the merged
5619 result is left uncommitted. If the requested changeset is
5619 result is left uncommitted. If the requested changeset is
5620 not an ancestor or descendant (that is, it is on another
5620 not an ancestor or descendant (that is, it is on another
5621 branch), the update is aborted and the uncommitted changes
5621 branch), the update is aborted and the uncommitted changes
5622 are preserved.
5622 are preserved.
5623
5623
5624 2. With the -c/--check option, the update is aborted and the
5624 2. With the -c/--check option, the update is aborted and the
5625 uncommitted changes are preserved.
5625 uncommitted changes are preserved.
5626
5626
5627 3. With the -C/--clean option, uncommitted changes are discarded and
5627 3. With the -C/--clean option, uncommitted changes are discarded and
5628 the working directory is updated to the requested changeset.
5628 the working directory is updated to the requested changeset.
5629
5629
5630 Use null as the changeset to remove the working directory (like
5630 Use null as the changeset to remove the working directory (like
5631 :hg:`clone -U`).
5631 :hg:`clone -U`).
5632
5632
5633 If you want to revert just one file to an older revision, use
5633 If you want to revert just one file to an older revision, use
5634 :hg:`revert [-r REV] NAME`.
5634 :hg:`revert [-r REV] NAME`.
5635
5635
5636 See :hg:`help dates` for a list of formats valid for -d/--date.
5636 See :hg:`help dates` for a list of formats valid for -d/--date.
5637
5637
5638 Returns 0 on success, 1 if there are unresolved files.
5638 Returns 0 on success, 1 if there are unresolved files.
5639 """
5639 """
5640 if rev and node:
5640 if rev and node:
5641 raise util.Abort(_("please specify just one revision"))
5641 raise util.Abort(_("please specify just one revision"))
5642
5642
5643 if rev is None or rev == '':
5643 if rev is None or rev == '':
5644 rev = node
5644 rev = node
5645
5645
5646 # if we defined a bookmark, we have to remember the original bookmark name
5646 # if we defined a bookmark, we have to remember the original bookmark name
5647 brev = rev
5647 brev = rev
5648 rev = scmutil.revsingle(repo, rev, rev).rev()
5648 rev = scmutil.revsingle(repo, rev, rev).rev()
5649
5649
5650 if check and clean:
5650 if check and clean:
5651 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5651 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5652
5652
5653 if check:
5653 if check:
5654 # we could use dirty() but we can ignore merge and branch trivia
5654 # we could use dirty() but we can ignore merge and branch trivia
5655 c = repo[None]
5655 c = repo[None]
5656 if c.modified() or c.added() or c.removed():
5656 if c.modified() or c.added() or c.removed():
5657 raise util.Abort(_("uncommitted local changes"))
5657 raise util.Abort(_("uncommitted local changes"))
5658
5658
5659 if date:
5659 if date:
5660 if rev is not None:
5660 if rev is not None:
5661 raise util.Abort(_("you can't specify a revision and a date"))
5661 raise util.Abort(_("you can't specify a revision and a date"))
5662 rev = cmdutil.finddate(ui, repo, date)
5662 rev = cmdutil.finddate(ui, repo, date)
5663
5663
5664 if clean or check:
5664 if clean or check:
5665 ret = hg.clean(repo, rev)
5665 ret = hg.clean(repo, rev)
5666 else:
5666 else:
5667 ret = hg.update(repo, rev)
5667 ret = hg.update(repo, rev)
5668
5668
5669 if brev in repo._bookmarks:
5669 if brev in repo._bookmarks:
5670 bookmarks.setcurrent(repo, brev)
5670 bookmarks.setcurrent(repo, brev)
5671
5671
5672 return ret
5672 return ret
5673
5673
5674 @command('verify', [])
5674 @command('verify', [])
5675 def verify(ui, repo):
5675 def verify(ui, repo):
5676 """verify the integrity of the repository
5676 """verify the integrity of the repository
5677
5677
5678 Verify the integrity of the current repository.
5678 Verify the integrity of the current repository.
5679
5679
5680 This will perform an extensive check of the repository's
5680 This will perform an extensive check of the repository's
5681 integrity, validating the hashes and checksums of each entry in
5681 integrity, validating the hashes and checksums of each entry in
5682 the changelog, manifest, and tracked files, as well as the
5682 the changelog, manifest, and tracked files, as well as the
5683 integrity of their crosslinks and indices.
5683 integrity of their crosslinks and indices.
5684
5684
5685 Returns 0 on success, 1 if errors are encountered.
5685 Returns 0 on success, 1 if errors are encountered.
5686 """
5686 """
5687 return hg.verify(repo)
5687 return hg.verify(repo)
5688
5688
5689 @command('version', [])
5689 @command('version', [])
5690 def version_(ui):
5690 def version_(ui):
5691 """output version and copyright information"""
5691 """output version and copyright information"""
5692 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5692 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5693 % util.version())
5693 % util.version())
5694 ui.status(_(
5694 ui.status(_(
5695 "(see http://mercurial.selenic.com for more information)\n"
5695 "(see http://mercurial.selenic.com for more information)\n"
5696 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5696 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5697 "This is free software; see the source for copying conditions. "
5697 "This is free software; see the source for copying conditions. "
5698 "There is NO\nwarranty; "
5698 "There is NO\nwarranty; "
5699 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5699 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5700 ))
5700 ))
5701
5701
5702 norepo = ("clone init version help debugcommands debugcomplete"
5702 norepo = ("clone init version help debugcommands debugcomplete"
5703 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5703 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5704 " debugknown debuggetbundle debugbundle")
5704 " debugknown debuggetbundle debugbundle")
5705 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5705 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5706 " debugdata debugindex debugindexdot debugrevlog")
5706 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now