##// END OF EJS Templates
import: rename some local variables
Greg Ward -
r15195:5b2a3bb0 default
parent child Browse files
Show More
@@ -1,5443 +1,5442 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 merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge
18 import dagparser, context, simplemerge
19 import random, setdiscovery, treediscovery, dagutil
19 import random, setdiscovery, treediscovery, dagutil
20
20
21 table = {}
21 table = {}
22
22
23 command = cmdutil.command(table)
23 command = cmdutil.command(table)
24
24
25 # common command options
25 # common command options
26
26
27 globalopts = [
27 globalopts = [
28 ('R', 'repository', '',
28 ('R', 'repository', '',
29 _('repository root directory or name of overlay bundle file'),
29 _('repository root directory or name of overlay bundle file'),
30 _('REPO')),
30 _('REPO')),
31 ('', 'cwd', '',
31 ('', 'cwd', '',
32 _('change working directory'), _('DIR')),
32 _('change working directory'), _('DIR')),
33 ('y', 'noninteractive', None,
33 ('y', 'noninteractive', None,
34 _('do not prompt, automatically pick the first choice for all prompts')),
34 _('do not prompt, automatically pick the first choice for all prompts')),
35 ('q', 'quiet', None, _('suppress output')),
35 ('q', 'quiet', None, _('suppress output')),
36 ('v', 'verbose', None, _('enable additional output')),
36 ('v', 'verbose', None, _('enable additional output')),
37 ('', 'config', [],
37 ('', 'config', [],
38 _('set/override config option (use \'section.name=value\')'),
38 _('set/override config option (use \'section.name=value\')'),
39 _('CONFIG')),
39 _('CONFIG')),
40 ('', 'debug', None, _('enable debugging output')),
40 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debugger', None, _('start debugger')),
41 ('', 'debugger', None, _('start debugger')),
42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 _('ENCODE')),
43 _('ENCODE')),
44 ('', 'encodingmode', encoding.encodingmode,
44 ('', 'encodingmode', encoding.encodingmode,
45 _('set the charset encoding mode'), _('MODE')),
45 _('set the charset encoding mode'), _('MODE')),
46 ('', 'traceback', None, _('always print a traceback on exception')),
46 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'time', None, _('time how long the command takes')),
47 ('', 'time', None, _('time how long the command takes')),
48 ('', 'profile', None, _('print command execution profile')),
48 ('', 'profile', None, _('print command execution profile')),
49 ('', 'version', None, _('output version information and exit')),
49 ('', 'version', None, _('output version information and exit')),
50 ('h', 'help', None, _('display help and exit')),
50 ('h', 'help', None, _('display help and exit')),
51 ]
51 ]
52
52
53 dryrunopts = [('n', 'dry-run', None,
53 dryrunopts = [('n', 'dry-run', None,
54 _('do not perform actions, just print output'))]
54 _('do not perform actions, just print output'))]
55
55
56 remoteopts = [
56 remoteopts = [
57 ('e', 'ssh', '',
57 ('e', 'ssh', '',
58 _('specify ssh command to use'), _('CMD')),
58 _('specify ssh command to use'), _('CMD')),
59 ('', 'remotecmd', '',
59 ('', 'remotecmd', '',
60 _('specify hg command to run on the remote side'), _('CMD')),
60 _('specify hg command to run on the remote side'), _('CMD')),
61 ('', 'insecure', None,
61 ('', 'insecure', None,
62 _('do not verify server certificate (ignoring web.cacerts config)')),
62 _('do not verify server certificate (ignoring web.cacerts config)')),
63 ]
63 ]
64
64
65 walkopts = [
65 walkopts = [
66 ('I', 'include', [],
66 ('I', 'include', [],
67 _('include names matching the given patterns'), _('PATTERN')),
67 _('include names matching the given patterns'), _('PATTERN')),
68 ('X', 'exclude', [],
68 ('X', 'exclude', [],
69 _('exclude names matching the given patterns'), _('PATTERN')),
69 _('exclude names matching the given patterns'), _('PATTERN')),
70 ]
70 ]
71
71
72 commitopts = [
72 commitopts = [
73 ('m', 'message', '',
73 ('m', 'message', '',
74 _('use text as commit message'), _('TEXT')),
74 _('use text as commit message'), _('TEXT')),
75 ('l', 'logfile', '',
75 ('l', 'logfile', '',
76 _('read commit message from file'), _('FILE')),
76 _('read commit message from file'), _('FILE')),
77 ]
77 ]
78
78
79 commitopts2 = [
79 commitopts2 = [
80 ('d', 'date', '',
80 ('d', 'date', '',
81 _('record the specified date as commit date'), _('DATE')),
81 _('record the specified date as commit date'), _('DATE')),
82 ('u', 'user', '',
82 ('u', 'user', '',
83 _('record the specified user as committer'), _('USER')),
83 _('record the specified user as committer'), _('USER')),
84 ]
84 ]
85
85
86 templateopts = [
86 templateopts = [
87 ('', 'style', '',
87 ('', 'style', '',
88 _('display using template map file'), _('STYLE')),
88 _('display using template map file'), _('STYLE')),
89 ('', 'template', '',
89 ('', 'template', '',
90 _('display with template'), _('TEMPLATE')),
90 _('display with template'), _('TEMPLATE')),
91 ]
91 ]
92
92
93 logopts = [
93 logopts = [
94 ('p', 'patch', None, _('show patch')),
94 ('p', 'patch', None, _('show patch')),
95 ('g', 'git', None, _('use git extended diff format')),
95 ('g', 'git', None, _('use git extended diff format')),
96 ('l', 'limit', '',
96 ('l', 'limit', '',
97 _('limit number of changes displayed'), _('NUM')),
97 _('limit number of changes displayed'), _('NUM')),
98 ('M', 'no-merges', None, _('do not show merges')),
98 ('M', 'no-merges', None, _('do not show merges')),
99 ('', 'stat', None, _('output diffstat-style summary of changes')),
99 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ] + templateopts
100 ] + templateopts
101
101
102 diffopts = [
102 diffopts = [
103 ('a', 'text', None, _('treat all files as text')),
103 ('a', 'text', None, _('treat all files as text')),
104 ('g', 'git', None, _('use git extended diff format')),
104 ('g', 'git', None, _('use git extended diff format')),
105 ('', 'nodates', None, _('omit dates from diff headers'))
105 ('', 'nodates', None, _('omit dates from diff headers'))
106 ]
106 ]
107
107
108 diffopts2 = [
108 diffopts2 = [
109 ('p', 'show-function', None, _('show which function each change is in')),
109 ('p', 'show-function', None, _('show which function each change is in')),
110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
111 ('w', 'ignore-all-space', None,
111 ('w', 'ignore-all-space', None,
112 _('ignore white space when comparing lines')),
112 _('ignore white space when comparing lines')),
113 ('b', 'ignore-space-change', None,
113 ('b', 'ignore-space-change', None,
114 _('ignore changes in the amount of white space')),
114 _('ignore changes in the amount of white space')),
115 ('B', 'ignore-blank-lines', None,
115 ('B', 'ignore-blank-lines', None,
116 _('ignore changes whose lines are all blank')),
116 _('ignore changes whose lines are all blank')),
117 ('U', 'unified', '',
117 ('U', 'unified', '',
118 _('number of lines of context to show'), _('NUM')),
118 _('number of lines of context to show'), _('NUM')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
120 ]
120 ]
121
121
122 mergetoolopts = [
122 mergetoolopts = [
123 ('t', 'tool', '', _('specify merge tool')),
123 ('t', 'tool', '', _('specify merge tool')),
124 ]
124 ]
125
125
126 similarityopts = [
126 similarityopts = [
127 ('s', 'similarity', '',
127 ('s', 'similarity', '',
128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
129 ]
129 ]
130
130
131 subrepoopts = [
131 subrepoopts = [
132 ('S', 'subrepos', None,
132 ('S', 'subrepos', None,
133 _('recurse into subrepositories'))
133 _('recurse into subrepositories'))
134 ]
134 ]
135
135
136 # Commands start here, listed alphabetically
136 # Commands start here, listed alphabetically
137
137
138 @command('^add',
138 @command('^add',
139 walkopts + subrepoopts + dryrunopts,
139 walkopts + subrepoopts + dryrunopts,
140 _('[OPTION]... [FILE]...'))
140 _('[OPTION]... [FILE]...'))
141 def add(ui, repo, *pats, **opts):
141 def add(ui, repo, *pats, **opts):
142 """add the specified files on the next commit
142 """add the specified files on the next commit
143
143
144 Schedule files to be version controlled and added to the
144 Schedule files to be version controlled and added to the
145 repository.
145 repository.
146
146
147 The files will be added to the repository at the next commit. To
147 The files will be added to the repository at the next commit. To
148 undo an add before that, see :hg:`forget`.
148 undo an add before that, see :hg:`forget`.
149
149
150 If no names are given, add all files to the repository.
150 If no names are given, add all files to the repository.
151
151
152 .. container:: verbose
152 .. container:: verbose
153
153
154 An example showing how new (unknown) files are added
154 An example showing how new (unknown) files are added
155 automatically by :hg:`add`::
155 automatically by :hg:`add`::
156
156
157 $ ls
157 $ ls
158 foo.c
158 foo.c
159 $ hg status
159 $ hg status
160 ? foo.c
160 ? foo.c
161 $ hg add
161 $ hg add
162 adding foo.c
162 adding foo.c
163 $ hg status
163 $ hg status
164 A foo.c
164 A foo.c
165
165
166 Returns 0 if all files are successfully added.
166 Returns 0 if all files are successfully added.
167 """
167 """
168
168
169 m = scmutil.match(repo[None], pats, opts)
169 m = scmutil.match(repo[None], pats, opts)
170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
171 opts.get('subrepos'), prefix="")
171 opts.get('subrepos'), prefix="")
172 return rejected and 1 or 0
172 return rejected and 1 or 0
173
173
174 @command('addremove',
174 @command('addremove',
175 similarityopts + walkopts + dryrunopts,
175 similarityopts + walkopts + dryrunopts,
176 _('[OPTION]... [FILE]...'))
176 _('[OPTION]... [FILE]...'))
177 def addremove(ui, repo, *pats, **opts):
177 def addremove(ui, repo, *pats, **opts):
178 """add all new files, delete all missing files
178 """add all new files, delete all missing files
179
179
180 Add all new files and remove all missing files from the
180 Add all new files and remove all missing files from the
181 repository.
181 repository.
182
182
183 New files are ignored if they match any of the patterns in
183 New files are ignored if they match any of the patterns in
184 ``.hgignore``. As with add, these changes take effect at the next
184 ``.hgignore``. As with add, these changes take effect at the next
185 commit.
185 commit.
186
186
187 Use the -s/--similarity option to detect renamed files. With a
187 Use the -s/--similarity option to detect renamed files. With a
188 parameter greater than 0, this compares every removed file with
188 parameter greater than 0, this compares every removed file with
189 every added file and records those similar enough as renames. This
189 every added file and records those similar enough as renames. This
190 option takes a percentage between 0 (disabled) and 100 (files must
190 option takes a percentage between 0 (disabled) and 100 (files must
191 be identical) as its parameter. Detecting renamed files this way
191 be identical) as its parameter. Detecting renamed files this way
192 can be expensive. After using this option, :hg:`status -C` can be
192 can be expensive. After using this option, :hg:`status -C` can be
193 used to check which files were identified as moved or renamed.
193 used to check which files were identified as moved or renamed.
194
194
195 Returns 0 if all files are successfully added.
195 Returns 0 if all files are successfully added.
196 """
196 """
197 try:
197 try:
198 sim = float(opts.get('similarity') or 100)
198 sim = float(opts.get('similarity') or 100)
199 except ValueError:
199 except ValueError:
200 raise util.Abort(_('similarity must be a number'))
200 raise util.Abort(_('similarity must be a number'))
201 if sim < 0 or sim > 100:
201 if sim < 0 or sim > 100:
202 raise util.Abort(_('similarity must be between 0 and 100'))
202 raise util.Abort(_('similarity must be between 0 and 100'))
203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
204
204
205 @command('^annotate|blame',
205 @command('^annotate|blame',
206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
207 ('', 'follow', None,
207 ('', 'follow', None,
208 _('follow copies/renames and list the filename (DEPRECATED)')),
208 _('follow copies/renames and list the filename (DEPRECATED)')),
209 ('', 'no-follow', None, _("don't follow copies and renames")),
209 ('', 'no-follow', None, _("don't follow copies and renames")),
210 ('a', 'text', None, _('treat all files as text')),
210 ('a', 'text', None, _('treat all files as text')),
211 ('u', 'user', None, _('list the author (long with -v)')),
211 ('u', 'user', None, _('list the author (long with -v)')),
212 ('f', 'file', None, _('list the filename')),
212 ('f', 'file', None, _('list the filename')),
213 ('d', 'date', None, _('list the date (short with -q)')),
213 ('d', 'date', None, _('list the date (short with -q)')),
214 ('n', 'number', None, _('list the revision number (default)')),
214 ('n', 'number', None, _('list the revision number (default)')),
215 ('c', 'changeset', None, _('list the changeset')),
215 ('c', 'changeset', None, _('list the changeset')),
216 ('l', 'line-number', None, _('show line number at the first appearance'))
216 ('l', 'line-number', None, _('show line number at the first appearance'))
217 ] + walkopts,
217 ] + walkopts,
218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
219 def annotate(ui, repo, *pats, **opts):
219 def annotate(ui, repo, *pats, **opts):
220 """show changeset information by line for each file
220 """show changeset information by line for each file
221
221
222 List changes in files, showing the revision id responsible for
222 List changes in files, showing the revision id responsible for
223 each line
223 each line
224
224
225 This command is useful for discovering when a change was made and
225 This command is useful for discovering when a change was made and
226 by whom.
226 by whom.
227
227
228 Without the -a/--text option, annotate will avoid processing files
228 Without the -a/--text option, annotate will avoid processing files
229 it detects as binary. With -a, annotate will annotate the file
229 it detects as binary. With -a, annotate will annotate the file
230 anyway, although the results will probably be neither useful
230 anyway, although the results will probably be neither useful
231 nor desirable.
231 nor desirable.
232
232
233 Returns 0 on success.
233 Returns 0 on success.
234 """
234 """
235 if opts.get('follow'):
235 if opts.get('follow'):
236 # --follow is deprecated and now just an alias for -f/--file
236 # --follow is deprecated and now just an alias for -f/--file
237 # to mimic the behavior of Mercurial before version 1.5
237 # to mimic the behavior of Mercurial before version 1.5
238 opts['file'] = True
238 opts['file'] = True
239
239
240 datefunc = ui.quiet and util.shortdate or util.datestr
240 datefunc = ui.quiet and util.shortdate or util.datestr
241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
242
242
243 if not pats:
243 if not pats:
244 raise util.Abort(_('at least one filename or pattern is required'))
244 raise util.Abort(_('at least one filename or pattern is required'))
245
245
246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
247 ('number', ' ', lambda x: str(x[0].rev())),
247 ('number', ' ', lambda x: str(x[0].rev())),
248 ('changeset', ' ', lambda x: short(x[0].node())),
248 ('changeset', ' ', lambda x: short(x[0].node())),
249 ('date', ' ', getdate),
249 ('date', ' ', getdate),
250 ('file', ' ', lambda x: x[0].path()),
250 ('file', ' ', lambda x: x[0].path()),
251 ('line_number', ':', lambda x: str(x[1])),
251 ('line_number', ':', lambda x: str(x[1])),
252 ]
252 ]
253
253
254 if (not opts.get('user') and not opts.get('changeset')
254 if (not opts.get('user') and not opts.get('changeset')
255 and not opts.get('date') and not opts.get('file')):
255 and not opts.get('date') and not opts.get('file')):
256 opts['number'] = True
256 opts['number'] = True
257
257
258 linenumber = opts.get('line_number') is not None
258 linenumber = opts.get('line_number') is not None
259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
260 raise util.Abort(_('at least one of -n/-c is required for -l'))
260 raise util.Abort(_('at least one of -n/-c is required for -l'))
261
261
262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
264
264
265 def bad(x, y):
265 def bad(x, y):
266 raise util.Abort("%s: %s" % (x, y))
266 raise util.Abort("%s: %s" % (x, y))
267
267
268 ctx = scmutil.revsingle(repo, opts.get('rev'))
268 ctx = scmutil.revsingle(repo, opts.get('rev'))
269 m = scmutil.match(ctx, pats, opts)
269 m = scmutil.match(ctx, pats, opts)
270 m.bad = bad
270 m.bad = bad
271 follow = not opts.get('no_follow')
271 follow = not opts.get('no_follow')
272 for abs in ctx.walk(m):
272 for abs in ctx.walk(m):
273 fctx = ctx[abs]
273 fctx = ctx[abs]
274 if not opts.get('text') and util.binary(fctx.data()):
274 if not opts.get('text') and util.binary(fctx.data()):
275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
276 continue
276 continue
277
277
278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
279 pieces = []
279 pieces = []
280
280
281 for f, sep in funcmap:
281 for f, sep in funcmap:
282 l = [f(n) for n, dummy in lines]
282 l = [f(n) for n, dummy in lines]
283 if l:
283 if l:
284 sized = [(x, encoding.colwidth(x)) for x in l]
284 sized = [(x, encoding.colwidth(x)) for x in l]
285 ml = max([w for x, w in sized])
285 ml = max([w for x, w in sized])
286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
287 for x, w in sized])
287 for x, w in sized])
288
288
289 if pieces:
289 if pieces:
290 for p, l in zip(zip(*pieces), lines):
290 for p, l in zip(zip(*pieces), lines):
291 ui.write("%s: %s" % ("".join(p), l[1]))
291 ui.write("%s: %s" % ("".join(p), l[1]))
292
292
293 @command('archive',
293 @command('archive',
294 [('', 'no-decode', None, _('do not pass files through decoders')),
294 [('', 'no-decode', None, _('do not pass files through decoders')),
295 ('p', 'prefix', '', _('directory prefix for files in archive'),
295 ('p', 'prefix', '', _('directory prefix for files in archive'),
296 _('PREFIX')),
296 _('PREFIX')),
297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
299 ] + subrepoopts + walkopts,
299 ] + subrepoopts + walkopts,
300 _('[OPTION]... DEST'))
300 _('[OPTION]... DEST'))
301 def archive(ui, repo, dest, **opts):
301 def archive(ui, repo, dest, **opts):
302 '''create an unversioned archive of a repository revision
302 '''create an unversioned archive of a repository revision
303
303
304 By default, the revision used is the parent of the working
304 By default, the revision used is the parent of the working
305 directory; use -r/--rev to specify a different revision.
305 directory; use -r/--rev to specify a different revision.
306
306
307 The archive type is automatically detected based on file
307 The archive type is automatically detected based on file
308 extension (or override using -t/--type).
308 extension (or override using -t/--type).
309
309
310 .. container:: verbose
310 .. container:: verbose
311
311
312 Examples:
312 Examples:
313
313
314 - create a zip file containing the 1.0 release::
314 - create a zip file containing the 1.0 release::
315
315
316 hg archive -r 1.0 project-1.0.zip
316 hg archive -r 1.0 project-1.0.zip
317
317
318 - create a tarball excluding .hg files::
318 - create a tarball excluding .hg files::
319
319
320 hg archive project.tar.gz -X ".hg*"
320 hg archive project.tar.gz -X ".hg*"
321
321
322 Valid types are:
322 Valid types are:
323
323
324 :``files``: a directory full of files (default)
324 :``files``: a directory full of files (default)
325 :``tar``: tar archive, uncompressed
325 :``tar``: tar archive, uncompressed
326 :``tbz2``: tar archive, compressed using bzip2
326 :``tbz2``: tar archive, compressed using bzip2
327 :``tgz``: tar archive, compressed using gzip
327 :``tgz``: tar archive, compressed using gzip
328 :``uzip``: zip archive, uncompressed
328 :``uzip``: zip archive, uncompressed
329 :``zip``: zip archive, compressed using deflate
329 :``zip``: zip archive, compressed using deflate
330
330
331 The exact name of the destination archive or directory is given
331 The exact name of the destination archive or directory is given
332 using a format string; see :hg:`help export` for details.
332 using a format string; see :hg:`help export` for details.
333
333
334 Each member added to an archive file has a directory prefix
334 Each member added to an archive file has a directory prefix
335 prepended. Use -p/--prefix to specify a format string for the
335 prepended. Use -p/--prefix to specify a format string for the
336 prefix. The default is the basename of the archive, with suffixes
336 prefix. The default is the basename of the archive, with suffixes
337 removed.
337 removed.
338
338
339 Returns 0 on success.
339 Returns 0 on success.
340 '''
340 '''
341
341
342 ctx = scmutil.revsingle(repo, opts.get('rev'))
342 ctx = scmutil.revsingle(repo, opts.get('rev'))
343 if not ctx:
343 if not ctx:
344 raise util.Abort(_('no working directory: please specify a revision'))
344 raise util.Abort(_('no working directory: please specify a revision'))
345 node = ctx.node()
345 node = ctx.node()
346 dest = cmdutil.makefilename(repo, dest, node)
346 dest = cmdutil.makefilename(repo, dest, node)
347 if os.path.realpath(dest) == repo.root:
347 if os.path.realpath(dest) == repo.root:
348 raise util.Abort(_('repository root cannot be destination'))
348 raise util.Abort(_('repository root cannot be destination'))
349
349
350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
351 prefix = opts.get('prefix')
351 prefix = opts.get('prefix')
352
352
353 if dest == '-':
353 if dest == '-':
354 if kind == 'files':
354 if kind == 'files':
355 raise util.Abort(_('cannot archive plain files to stdout'))
355 raise util.Abort(_('cannot archive plain files to stdout'))
356 dest = cmdutil.makefileobj(repo, dest)
356 dest = cmdutil.makefileobj(repo, dest)
357 if not prefix:
357 if not prefix:
358 prefix = os.path.basename(repo.root) + '-%h'
358 prefix = os.path.basename(repo.root) + '-%h'
359
359
360 prefix = cmdutil.makefilename(repo, prefix, node)
360 prefix = cmdutil.makefilename(repo, prefix, node)
361 matchfn = scmutil.match(ctx, [], opts)
361 matchfn = scmutil.match(ctx, [], opts)
362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
363 matchfn, prefix, subrepos=opts.get('subrepos'))
363 matchfn, prefix, subrepos=opts.get('subrepos'))
364
364
365 @command('backout',
365 @command('backout',
366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
367 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
367 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
368 ('r', 'rev', '', _('revision to backout'), _('REV')),
368 ('r', 'rev', '', _('revision to backout'), _('REV')),
369 ] + mergetoolopts + walkopts + commitopts + commitopts2,
369 ] + mergetoolopts + walkopts + commitopts + commitopts2,
370 _('[OPTION]... [-r] REV'))
370 _('[OPTION]... [-r] REV'))
371 def backout(ui, repo, node=None, rev=None, **opts):
371 def backout(ui, repo, node=None, rev=None, **opts):
372 '''reverse effect of earlier changeset
372 '''reverse effect of earlier changeset
373
373
374 Prepare a new changeset with the effect of REV undone in the
374 Prepare a new changeset with the effect of REV undone in the
375 current working directory.
375 current working directory.
376
376
377 If REV is the parent of the working directory, then this new changeset
377 If REV is the parent of the working directory, then this new changeset
378 is committed automatically. Otherwise, hg needs to merge the
378 is committed automatically. Otherwise, hg needs to merge the
379 changes and the merged result is left uncommitted.
379 changes and the merged result is left uncommitted.
380
380
381 By default, the pending changeset will have one parent,
381 By default, the pending changeset will have one parent,
382 maintaining a linear history. With --merge, the pending changeset
382 maintaining a linear history. With --merge, the pending changeset
383 will instead have two parents: the old parent of the working
383 will instead have two parents: the old parent of the working
384 directory and a new child of REV that simply undoes REV.
384 directory and a new child of REV that simply undoes REV.
385
385
386 Before version 1.7, the behavior without --merge was equivalent to
386 Before version 1.7, the behavior without --merge was equivalent to
387 specifying --merge followed by :hg:`update --clean .` to cancel
387 specifying --merge followed by :hg:`update --clean .` to cancel
388 the merge and leave the child of REV as a head to be merged
388 the merge and leave the child of REV as a head to be merged
389 separately.
389 separately.
390
390
391 See :hg:`help dates` for a list of formats valid for -d/--date.
391 See :hg:`help dates` for a list of formats valid for -d/--date.
392
392
393 Returns 0 on success.
393 Returns 0 on success.
394 '''
394 '''
395 if rev and node:
395 if rev and node:
396 raise util.Abort(_("please specify just one revision"))
396 raise util.Abort(_("please specify just one revision"))
397
397
398 if not rev:
398 if not rev:
399 rev = node
399 rev = node
400
400
401 if not rev:
401 if not rev:
402 raise util.Abort(_("please specify a revision to backout"))
402 raise util.Abort(_("please specify a revision to backout"))
403
403
404 date = opts.get('date')
404 date = opts.get('date')
405 if date:
405 if date:
406 opts['date'] = util.parsedate(date)
406 opts['date'] = util.parsedate(date)
407
407
408 cmdutil.bailifchanged(repo)
408 cmdutil.bailifchanged(repo)
409 node = scmutil.revsingle(repo, rev).node()
409 node = scmutil.revsingle(repo, rev).node()
410
410
411 op1, op2 = repo.dirstate.parents()
411 op1, op2 = repo.dirstate.parents()
412 a = repo.changelog.ancestor(op1, node)
412 a = repo.changelog.ancestor(op1, node)
413 if a != node:
413 if a != node:
414 raise util.Abort(_('cannot backout change on a different branch'))
414 raise util.Abort(_('cannot backout change on a different branch'))
415
415
416 p1, p2 = repo.changelog.parents(node)
416 p1, p2 = repo.changelog.parents(node)
417 if p1 == nullid:
417 if p1 == nullid:
418 raise util.Abort(_('cannot backout a change with no parents'))
418 raise util.Abort(_('cannot backout a change with no parents'))
419 if p2 != nullid:
419 if p2 != nullid:
420 if not opts.get('parent'):
420 if not opts.get('parent'):
421 raise util.Abort(_('cannot backout a merge changeset without '
421 raise util.Abort(_('cannot backout a merge changeset without '
422 '--parent'))
422 '--parent'))
423 p = repo.lookup(opts['parent'])
423 p = repo.lookup(opts['parent'])
424 if p not in (p1, p2):
424 if p not in (p1, p2):
425 raise util.Abort(_('%s is not a parent of %s') %
425 raise util.Abort(_('%s is not a parent of %s') %
426 (short(p), short(node)))
426 (short(p), short(node)))
427 parent = p
427 parent = p
428 else:
428 else:
429 if opts.get('parent'):
429 if opts.get('parent'):
430 raise util.Abort(_('cannot use --parent on non-merge changeset'))
430 raise util.Abort(_('cannot use --parent on non-merge changeset'))
431 parent = p1
431 parent = p1
432
432
433 # the backout should appear on the same branch
433 # the backout should appear on the same branch
434 branch = repo.dirstate.branch()
434 branch = repo.dirstate.branch()
435 hg.clean(repo, node, show_stats=False)
435 hg.clean(repo, node, show_stats=False)
436 repo.dirstate.setbranch(branch)
436 repo.dirstate.setbranch(branch)
437 revert_opts = opts.copy()
437 revert_opts = opts.copy()
438 revert_opts['date'] = None
438 revert_opts['date'] = None
439 revert_opts['all'] = True
439 revert_opts['all'] = True
440 revert_opts['rev'] = hex(parent)
440 revert_opts['rev'] = hex(parent)
441 revert_opts['no_backup'] = None
441 revert_opts['no_backup'] = None
442 revert(ui, repo, **revert_opts)
442 revert(ui, repo, **revert_opts)
443 if not opts.get('merge') and op1 != node:
443 if not opts.get('merge') and op1 != node:
444 try:
444 try:
445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
446 return hg.update(repo, op1)
446 return hg.update(repo, op1)
447 finally:
447 finally:
448 ui.setconfig('ui', 'forcemerge', '')
448 ui.setconfig('ui', 'forcemerge', '')
449
449
450 commit_opts = opts.copy()
450 commit_opts = opts.copy()
451 commit_opts['addremove'] = False
451 commit_opts['addremove'] = False
452 if not commit_opts['message'] and not commit_opts['logfile']:
452 if not commit_opts['message'] and not commit_opts['logfile']:
453 # we don't translate commit messages
453 # we don't translate commit messages
454 commit_opts['message'] = "Backed out changeset %s" % short(node)
454 commit_opts['message'] = "Backed out changeset %s" % short(node)
455 commit_opts['force_editor'] = True
455 commit_opts['force_editor'] = True
456 commit(ui, repo, **commit_opts)
456 commit(ui, repo, **commit_opts)
457 def nice(node):
457 def nice(node):
458 return '%d:%s' % (repo.changelog.rev(node), short(node))
458 return '%d:%s' % (repo.changelog.rev(node), short(node))
459 ui.status(_('changeset %s backs out changeset %s\n') %
459 ui.status(_('changeset %s backs out changeset %s\n') %
460 (nice(repo.changelog.tip()), nice(node)))
460 (nice(repo.changelog.tip()), nice(node)))
461 if opts.get('merge') and op1 != node:
461 if opts.get('merge') and op1 != node:
462 hg.clean(repo, op1, show_stats=False)
462 hg.clean(repo, op1, show_stats=False)
463 ui.status(_('merging with changeset %s\n')
463 ui.status(_('merging with changeset %s\n')
464 % nice(repo.changelog.tip()))
464 % nice(repo.changelog.tip()))
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.merge(repo, hex(repo.changelog.tip()))
467 return hg.merge(repo, hex(repo.changelog.tip()))
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470 return 0
470 return 0
471
471
472 @command('bisect',
472 @command('bisect',
473 [('r', 'reset', False, _('reset bisect state')),
473 [('r', 'reset', False, _('reset bisect state')),
474 ('g', 'good', False, _('mark changeset good')),
474 ('g', 'good', False, _('mark changeset good')),
475 ('b', 'bad', False, _('mark changeset bad')),
475 ('b', 'bad', False, _('mark changeset bad')),
476 ('s', 'skip', False, _('skip testing changeset')),
476 ('s', 'skip', False, _('skip testing changeset')),
477 ('e', 'extend', False, _('extend the bisect range')),
477 ('e', 'extend', False, _('extend the bisect range')),
478 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
478 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
479 ('U', 'noupdate', False, _('do not update to target'))],
479 ('U', 'noupdate', False, _('do not update to target'))],
480 _("[-gbsr] [-U] [-c CMD] [REV]"))
480 _("[-gbsr] [-U] [-c CMD] [REV]"))
481 def bisect(ui, repo, rev=None, extra=None, command=None,
481 def bisect(ui, repo, rev=None, extra=None, command=None,
482 reset=None, good=None, bad=None, skip=None, extend=None,
482 reset=None, good=None, bad=None, skip=None, extend=None,
483 noupdate=None):
483 noupdate=None):
484 """subdivision search of changesets
484 """subdivision search of changesets
485
485
486 This command helps to find changesets which introduce problems. To
486 This command helps to find changesets which introduce problems. To
487 use, mark the earliest changeset you know exhibits the problem as
487 use, mark the earliest changeset you know exhibits the problem as
488 bad, then mark the latest changeset which is free from the problem
488 bad, then mark the latest changeset which is free from the problem
489 as good. Bisect will update your working directory to a revision
489 as good. Bisect will update your working directory to a revision
490 for testing (unless the -U/--noupdate option is specified). Once
490 for testing (unless the -U/--noupdate option is specified). Once
491 you have performed tests, mark the working directory as good or
491 you have performed tests, mark the working directory as good or
492 bad, and bisect will either update to another candidate changeset
492 bad, and bisect will either update to another candidate changeset
493 or announce that it has found the bad revision.
493 or announce that it has found the bad revision.
494
494
495 As a shortcut, you can also use the revision argument to mark a
495 As a shortcut, you can also use the revision argument to mark a
496 revision as good or bad without checking it out first.
496 revision as good or bad without checking it out first.
497
497
498 If you supply a command, it will be used for automatic bisection.
498 If you supply a command, it will be used for automatic bisection.
499 Its exit status will be used to mark revisions as good or bad:
499 Its exit status will be used to mark revisions as good or bad:
500 status 0 means good, 125 means to skip the revision, 127
500 status 0 means good, 125 means to skip the revision, 127
501 (command not found) will abort the bisection, and any other
501 (command not found) will abort the bisection, and any other
502 non-zero exit status means the revision is bad.
502 non-zero exit status means the revision is bad.
503
503
504 .. container:: verbose
504 .. container:: verbose
505
505
506 Some examples:
506 Some examples:
507
507
508 - start a bisection with known bad revision 12, and good revision 34::
508 - start a bisection with known bad revision 12, and good revision 34::
509
509
510 hg bisect --bad 34
510 hg bisect --bad 34
511 hg bisect --good 12
511 hg bisect --good 12
512
512
513 - advance the current bisection by marking current revision as good or
513 - advance the current bisection by marking current revision as good or
514 bad::
514 bad::
515
515
516 hg bisect --good
516 hg bisect --good
517 hg bisect --bad
517 hg bisect --bad
518
518
519 - mark the current revision, or a known revision, to be skipped (eg. if
519 - mark the current revision, or a known revision, to be skipped (eg. if
520 that revision is not usable because of another issue)::
520 that revision is not usable because of another issue)::
521
521
522 hg bisect --skip
522 hg bisect --skip
523 hg bisect --skip 23
523 hg bisect --skip 23
524
524
525 - forget the current bisection::
525 - forget the current bisection::
526
526
527 hg bisect --reset
527 hg bisect --reset
528
528
529 - use 'make && make tests' to automatically find the first broken
529 - use 'make && make tests' to automatically find the first broken
530 revision::
530 revision::
531
531
532 hg bisect --reset
532 hg bisect --reset
533 hg bisect --bad 34
533 hg bisect --bad 34
534 hg bisect --good 12
534 hg bisect --good 12
535 hg bisect --command 'make && make tests'
535 hg bisect --command 'make && make tests'
536
536
537 - see all changesets whose states are already known in the current
537 - see all changesets whose states are already known in the current
538 bisection::
538 bisection::
539
539
540 hg log -r "bisect(pruned)"
540 hg log -r "bisect(pruned)"
541
541
542 - see all changesets that took part in the current bisection::
542 - see all changesets that took part in the current bisection::
543
543
544 hg log -r "bisect(range)"
544 hg log -r "bisect(range)"
545
545
546 - with the graphlog extension, you can even get a nice graph::
546 - with the graphlog extension, you can even get a nice graph::
547
547
548 hg log --graph -r "bisect(range)"
548 hg log --graph -r "bisect(range)"
549
549
550 See :hg:`help revsets` for more about the `bisect()` keyword.
550 See :hg:`help revsets` for more about the `bisect()` keyword.
551
551
552 Returns 0 on success.
552 Returns 0 on success.
553 """
553 """
554 def extendbisectrange(nodes, good):
554 def extendbisectrange(nodes, good):
555 # bisect is incomplete when it ends on a merge node and
555 # bisect is incomplete when it ends on a merge node and
556 # one of the parent was not checked.
556 # one of the parent was not checked.
557 parents = repo[nodes[0]].parents()
557 parents = repo[nodes[0]].parents()
558 if len(parents) > 1:
558 if len(parents) > 1:
559 side = good and state['bad'] or state['good']
559 side = good and state['bad'] or state['good']
560 num = len(set(i.node() for i in parents) & set(side))
560 num = len(set(i.node() for i in parents) & set(side))
561 if num == 1:
561 if num == 1:
562 return parents[0].ancestor(parents[1])
562 return parents[0].ancestor(parents[1])
563 return None
563 return None
564
564
565 def print_result(nodes, good):
565 def print_result(nodes, good):
566 displayer = cmdutil.show_changeset(ui, repo, {})
566 displayer = cmdutil.show_changeset(ui, repo, {})
567 if len(nodes) == 1:
567 if len(nodes) == 1:
568 # narrowed it down to a single revision
568 # narrowed it down to a single revision
569 if good:
569 if good:
570 ui.write(_("The first good revision is:\n"))
570 ui.write(_("The first good revision is:\n"))
571 else:
571 else:
572 ui.write(_("The first bad revision is:\n"))
572 ui.write(_("The first bad revision is:\n"))
573 displayer.show(repo[nodes[0]])
573 displayer.show(repo[nodes[0]])
574 extendnode = extendbisectrange(nodes, good)
574 extendnode = extendbisectrange(nodes, good)
575 if extendnode is not None:
575 if extendnode is not None:
576 ui.write(_('Not all ancestors of this changeset have been'
576 ui.write(_('Not all ancestors of this changeset have been'
577 ' checked.\nUse bisect --extend to continue the '
577 ' checked.\nUse bisect --extend to continue the '
578 'bisection from\nthe common ancestor, %s.\n')
578 'bisection from\nthe common ancestor, %s.\n')
579 % extendnode)
579 % extendnode)
580 else:
580 else:
581 # multiple possible revisions
581 # multiple possible revisions
582 if good:
582 if good:
583 ui.write(_("Due to skipped revisions, the first "
583 ui.write(_("Due to skipped revisions, the first "
584 "good revision could be any of:\n"))
584 "good revision could be any of:\n"))
585 else:
585 else:
586 ui.write(_("Due to skipped revisions, the first "
586 ui.write(_("Due to skipped revisions, the first "
587 "bad revision could be any of:\n"))
587 "bad revision could be any of:\n"))
588 for n in nodes:
588 for n in nodes:
589 displayer.show(repo[n])
589 displayer.show(repo[n])
590 displayer.close()
590 displayer.close()
591
591
592 def check_state(state, interactive=True):
592 def check_state(state, interactive=True):
593 if not state['good'] or not state['bad']:
593 if not state['good'] or not state['bad']:
594 if (good or bad or skip or reset) and interactive:
594 if (good or bad or skip or reset) and interactive:
595 return
595 return
596 if not state['good']:
596 if not state['good']:
597 raise util.Abort(_('cannot bisect (no known good revisions)'))
597 raise util.Abort(_('cannot bisect (no known good revisions)'))
598 else:
598 else:
599 raise util.Abort(_('cannot bisect (no known bad revisions)'))
599 raise util.Abort(_('cannot bisect (no known bad revisions)'))
600 return True
600 return True
601
601
602 # backward compatibility
602 # backward compatibility
603 if rev in "good bad reset init".split():
603 if rev in "good bad reset init".split():
604 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
604 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
605 cmd, rev, extra = rev, extra, None
605 cmd, rev, extra = rev, extra, None
606 if cmd == "good":
606 if cmd == "good":
607 good = True
607 good = True
608 elif cmd == "bad":
608 elif cmd == "bad":
609 bad = True
609 bad = True
610 else:
610 else:
611 reset = True
611 reset = True
612 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
612 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
613 raise util.Abort(_('incompatible arguments'))
613 raise util.Abort(_('incompatible arguments'))
614
614
615 if reset:
615 if reset:
616 p = repo.join("bisect.state")
616 p = repo.join("bisect.state")
617 if os.path.exists(p):
617 if os.path.exists(p):
618 os.unlink(p)
618 os.unlink(p)
619 return
619 return
620
620
621 state = hbisect.load_state(repo)
621 state = hbisect.load_state(repo)
622
622
623 if command:
623 if command:
624 changesets = 1
624 changesets = 1
625 try:
625 try:
626 while changesets:
626 while changesets:
627 # update state
627 # update state
628 status = util.system(command, out=ui.fout)
628 status = util.system(command, out=ui.fout)
629 if status == 125:
629 if status == 125:
630 transition = "skip"
630 transition = "skip"
631 elif status == 0:
631 elif status == 0:
632 transition = "good"
632 transition = "good"
633 # status < 0 means process was killed
633 # status < 0 means process was killed
634 elif status == 127:
634 elif status == 127:
635 raise util.Abort(_("failed to execute %s") % command)
635 raise util.Abort(_("failed to execute %s") % command)
636 elif status < 0:
636 elif status < 0:
637 raise util.Abort(_("%s killed") % command)
637 raise util.Abort(_("%s killed") % command)
638 else:
638 else:
639 transition = "bad"
639 transition = "bad"
640 ctx = scmutil.revsingle(repo, rev)
640 ctx = scmutil.revsingle(repo, rev)
641 rev = None # clear for future iterations
641 rev = None # clear for future iterations
642 state[transition].append(ctx.node())
642 state[transition].append(ctx.node())
643 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
643 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
644 check_state(state, interactive=False)
644 check_state(state, interactive=False)
645 # bisect
645 # bisect
646 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
646 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
647 # update to next check
647 # update to next check
648 cmdutil.bailifchanged(repo)
648 cmdutil.bailifchanged(repo)
649 hg.clean(repo, nodes[0], show_stats=False)
649 hg.clean(repo, nodes[0], show_stats=False)
650 finally:
650 finally:
651 hbisect.save_state(repo, state)
651 hbisect.save_state(repo, state)
652 print_result(nodes, good)
652 print_result(nodes, good)
653 return
653 return
654
654
655 # update state
655 # update state
656
656
657 if rev:
657 if rev:
658 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
658 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
659 else:
659 else:
660 nodes = [repo.lookup('.')]
660 nodes = [repo.lookup('.')]
661
661
662 if good or bad or skip:
662 if good or bad or skip:
663 if good:
663 if good:
664 state['good'] += nodes
664 state['good'] += nodes
665 elif bad:
665 elif bad:
666 state['bad'] += nodes
666 state['bad'] += nodes
667 elif skip:
667 elif skip:
668 state['skip'] += nodes
668 state['skip'] += nodes
669 hbisect.save_state(repo, state)
669 hbisect.save_state(repo, state)
670
670
671 if not check_state(state):
671 if not check_state(state):
672 return
672 return
673
673
674 # actually bisect
674 # actually bisect
675 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
675 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
676 if extend:
676 if extend:
677 if not changesets:
677 if not changesets:
678 extendnode = extendbisectrange(nodes, good)
678 extendnode = extendbisectrange(nodes, good)
679 if extendnode is not None:
679 if extendnode is not None:
680 ui.write(_("Extending search to changeset %d:%s\n"
680 ui.write(_("Extending search to changeset %d:%s\n"
681 % (extendnode.rev(), extendnode)))
681 % (extendnode.rev(), extendnode)))
682 if noupdate:
682 if noupdate:
683 return
683 return
684 cmdutil.bailifchanged(repo)
684 cmdutil.bailifchanged(repo)
685 return hg.clean(repo, extendnode.node())
685 return hg.clean(repo, extendnode.node())
686 raise util.Abort(_("nothing to extend"))
686 raise util.Abort(_("nothing to extend"))
687
687
688 if changesets == 0:
688 if changesets == 0:
689 print_result(nodes, good)
689 print_result(nodes, good)
690 else:
690 else:
691 assert len(nodes) == 1 # only a single node can be tested next
691 assert len(nodes) == 1 # only a single node can be tested next
692 node = nodes[0]
692 node = nodes[0]
693 # compute the approximate number of remaining tests
693 # compute the approximate number of remaining tests
694 tests, size = 0, 2
694 tests, size = 0, 2
695 while size <= changesets:
695 while size <= changesets:
696 tests, size = tests + 1, size * 2
696 tests, size = tests + 1, size * 2
697 rev = repo.changelog.rev(node)
697 rev = repo.changelog.rev(node)
698 ui.write(_("Testing changeset %d:%s "
698 ui.write(_("Testing changeset %d:%s "
699 "(%d changesets remaining, ~%d tests)\n")
699 "(%d changesets remaining, ~%d tests)\n")
700 % (rev, short(node), changesets, tests))
700 % (rev, short(node), changesets, tests))
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 return hg.clean(repo, node)
703 return hg.clean(repo, node)
704
704
705 @command('bookmarks',
705 @command('bookmarks',
706 [('f', 'force', False, _('force')),
706 [('f', 'force', False, _('force')),
707 ('r', 'rev', '', _('revision'), _('REV')),
707 ('r', 'rev', '', _('revision'), _('REV')),
708 ('d', 'delete', False, _('delete a given bookmark')),
708 ('d', 'delete', False, _('delete a given bookmark')),
709 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
709 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
710 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
710 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
711 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
711 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
712 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
712 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
713 rename=None, inactive=False):
713 rename=None, inactive=False):
714 '''track a line of development with movable markers
714 '''track a line of development with movable markers
715
715
716 Bookmarks are pointers to certain commits that move when
716 Bookmarks are pointers to certain commits that move when
717 committing. Bookmarks are local. They can be renamed, copied and
717 committing. Bookmarks are local. They can be renamed, copied and
718 deleted. It is possible to use bookmark names in :hg:`merge` and
718 deleted. It is possible to use bookmark names in :hg:`merge` and
719 :hg:`update` to merge and update respectively to a given bookmark.
719 :hg:`update` to merge and update respectively to a given bookmark.
720
720
721 You can use :hg:`bookmark NAME` to set a bookmark on the working
721 You can use :hg:`bookmark NAME` to set a bookmark on the working
722 directory's parent revision with the given name. If you specify
722 directory's parent revision with the given name. If you specify
723 a revision using -r REV (where REV may be an existing bookmark),
723 a revision using -r REV (where REV may be an existing bookmark),
724 the bookmark is assigned to that revision.
724 the bookmark is assigned to that revision.
725
725
726 Bookmarks can be pushed and pulled between repositories (see :hg:`help
726 Bookmarks can be pushed and pulled between repositories (see :hg:`help
727 push` and :hg:`help pull`). This requires both the local and remote
727 push` and :hg:`help pull`). This requires both the local and remote
728 repositories to support bookmarks. For versions prior to 1.8, this means
728 repositories to support bookmarks. For versions prior to 1.8, this means
729 the bookmarks extension must be enabled.
729 the bookmarks extension must be enabled.
730 '''
730 '''
731 hexfn = ui.debugflag and hex or short
731 hexfn = ui.debugflag and hex or short
732 marks = repo._bookmarks
732 marks = repo._bookmarks
733 cur = repo.changectx('.').node()
733 cur = repo.changectx('.').node()
734
734
735 if rename:
735 if rename:
736 if rename not in marks:
736 if rename not in marks:
737 raise util.Abort(_("bookmark '%s' does not exist") % rename)
737 raise util.Abort(_("bookmark '%s' does not exist") % rename)
738 if mark in marks and not force:
738 if mark in marks and not force:
739 raise util.Abort(_("bookmark '%s' already exists "
739 raise util.Abort(_("bookmark '%s' already exists "
740 "(use -f to force)") % mark)
740 "(use -f to force)") % mark)
741 if mark is None:
741 if mark is None:
742 raise util.Abort(_("new bookmark name required"))
742 raise util.Abort(_("new bookmark name required"))
743 marks[mark] = marks[rename]
743 marks[mark] = marks[rename]
744 if repo._bookmarkcurrent == rename and not inactive:
744 if repo._bookmarkcurrent == rename and not inactive:
745 bookmarks.setcurrent(repo, mark)
745 bookmarks.setcurrent(repo, mark)
746 del marks[rename]
746 del marks[rename]
747 bookmarks.write(repo)
747 bookmarks.write(repo)
748 return
748 return
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 mark is not None:
761 if mark is not None:
762 if "\n" in mark:
762 if "\n" in mark:
763 raise util.Abort(_("bookmark name cannot contain newlines"))
763 raise util.Abort(_("bookmark name cannot contain newlines"))
764 mark = mark.strip()
764 mark = mark.strip()
765 if not mark:
765 if not mark:
766 raise util.Abort(_("bookmark names cannot consist entirely of "
766 raise util.Abort(_("bookmark names cannot consist entirely of "
767 "whitespace"))
767 "whitespace"))
768 if inactive and mark == repo._bookmarkcurrent:
768 if inactive and mark == repo._bookmarkcurrent:
769 bookmarks.setcurrent(repo, None)
769 bookmarks.setcurrent(repo, None)
770 return
770 return
771 if mark in marks and not force:
771 if mark in marks and not force:
772 raise util.Abort(_("bookmark '%s' already exists "
772 raise util.Abort(_("bookmark '%s' already exists "
773 "(use -f to force)") % mark)
773 "(use -f to force)") % mark)
774 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
774 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
775 and not force):
775 and not force):
776 raise util.Abort(
776 raise util.Abort(
777 _("a bookmark cannot have the name of an existing branch"))
777 _("a bookmark cannot have the name of an existing branch"))
778 if rev:
778 if rev:
779 marks[mark] = repo.lookup(rev)
779 marks[mark] = repo.lookup(rev)
780 else:
780 else:
781 marks[mark] = repo.changectx('.').node()
781 marks[mark] = repo.changectx('.').node()
782 if not inactive and repo.changectx('.').node() == marks[mark]:
782 if not inactive and repo.changectx('.').node() == marks[mark]:
783 bookmarks.setcurrent(repo, mark)
783 bookmarks.setcurrent(repo, mark)
784 bookmarks.write(repo)
784 bookmarks.write(repo)
785 return
785 return
786
786
787 if mark is None:
787 if mark is None:
788 if rev:
788 if rev:
789 raise util.Abort(_("bookmark name required"))
789 raise util.Abort(_("bookmark name required"))
790 if len(marks) == 0:
790 if len(marks) == 0:
791 ui.status(_("no bookmarks set\n"))
791 ui.status(_("no bookmarks set\n"))
792 else:
792 else:
793 for bmark, n in sorted(marks.iteritems()):
793 for bmark, n in sorted(marks.iteritems()):
794 current = repo._bookmarkcurrent
794 current = repo._bookmarkcurrent
795 if bmark == current and n == cur:
795 if bmark == current and n == cur:
796 prefix, label = '*', 'bookmarks.current'
796 prefix, label = '*', 'bookmarks.current'
797 else:
797 else:
798 prefix, label = ' ', ''
798 prefix, label = ' ', ''
799
799
800 if ui.quiet:
800 if ui.quiet:
801 ui.write("%s\n" % bmark, label=label)
801 ui.write("%s\n" % bmark, label=label)
802 else:
802 else:
803 ui.write(" %s %-25s %d:%s\n" % (
803 ui.write(" %s %-25s %d:%s\n" % (
804 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
804 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
805 label=label)
805 label=label)
806 return
806 return
807
807
808 @command('branch',
808 @command('branch',
809 [('f', 'force', None,
809 [('f', 'force', None,
810 _('set branch name even if it shadows an existing branch')),
810 _('set branch name even if it shadows an existing branch')),
811 ('C', 'clean', None, _('reset branch name to parent branch name'))],
811 ('C', 'clean', None, _('reset branch name to parent branch name'))],
812 _('[-fC] [NAME]'))
812 _('[-fC] [NAME]'))
813 def branch(ui, repo, label=None, **opts):
813 def branch(ui, repo, label=None, **opts):
814 """set or show the current branch name
814 """set or show the current branch name
815
815
816 With no argument, show the current branch name. With one argument,
816 With no argument, show the current branch name. With one argument,
817 set the working directory branch name (the branch will not exist
817 set the working directory branch name (the branch will not exist
818 in the repository until the next commit). Standard practice
818 in the repository until the next commit). Standard practice
819 recommends that primary development take place on the 'default'
819 recommends that primary development take place on the 'default'
820 branch.
820 branch.
821
821
822 Unless -f/--force is specified, branch will not let you set a
822 Unless -f/--force is specified, branch will not let you set a
823 branch name that already exists, even if it's inactive.
823 branch name that already exists, even if it's inactive.
824
824
825 Use -C/--clean to reset the working directory branch to that of
825 Use -C/--clean to reset the working directory branch to that of
826 the parent of the working directory, negating a previous branch
826 the parent of the working directory, negating a previous branch
827 change.
827 change.
828
828
829 Use the command :hg:`update` to switch to an existing branch. Use
829 Use the command :hg:`update` to switch to an existing branch. Use
830 :hg:`commit --close-branch` to mark this branch as closed.
830 :hg:`commit --close-branch` to mark this branch as closed.
831
831
832 .. note::
832 .. note::
833
833
834 Branch names are permanent. Use :hg:`bookmark` to create a
834 Branch names are permanent. Use :hg:`bookmark` to create a
835 light-weight bookmark instead. See :hg:`help glossary` for more
835 light-weight bookmark instead. See :hg:`help glossary` for more
836 information about named branches and bookmarks.
836 information about named branches and bookmarks.
837
837
838 Returns 0 on success.
838 Returns 0 on success.
839 """
839 """
840
840
841 if opts.get('clean'):
841 if opts.get('clean'):
842 label = repo[None].p1().branch()
842 label = repo[None].p1().branch()
843 repo.dirstate.setbranch(label)
843 repo.dirstate.setbranch(label)
844 ui.status(_('reset working directory to branch %s\n') % label)
844 ui.status(_('reset working directory to branch %s\n') % label)
845 elif label:
845 elif label:
846 if not opts.get('force') and label in repo.branchtags():
846 if not opts.get('force') and label in repo.branchtags():
847 if label not in [p.branch() for p in repo.parents()]:
847 if label not in [p.branch() for p in repo.parents()]:
848 raise util.Abort(_('a branch of the same name already exists'),
848 raise util.Abort(_('a branch of the same name already exists'),
849 # i18n: "it" refers to an existing branch
849 # i18n: "it" refers to an existing branch
850 hint=_("use 'hg update' to switch to it"))
850 hint=_("use 'hg update' to switch to it"))
851 repo.dirstate.setbranch(label)
851 repo.dirstate.setbranch(label)
852 ui.status(_('marked working directory as branch %s\n') % label)
852 ui.status(_('marked working directory as branch %s\n') % label)
853 else:
853 else:
854 ui.write("%s\n" % repo.dirstate.branch())
854 ui.write("%s\n" % repo.dirstate.branch())
855
855
856 @command('branches',
856 @command('branches',
857 [('a', 'active', False, _('show only branches that have unmerged heads')),
857 [('a', 'active', False, _('show only branches that have unmerged heads')),
858 ('c', 'closed', False, _('show normal and closed branches'))],
858 ('c', 'closed', False, _('show normal and closed branches'))],
859 _('[-ac]'))
859 _('[-ac]'))
860 def branches(ui, repo, active=False, closed=False):
860 def branches(ui, repo, active=False, closed=False):
861 """list repository named branches
861 """list repository named branches
862
862
863 List the repository's named branches, indicating which ones are
863 List the repository's named branches, indicating which ones are
864 inactive. If -c/--closed is specified, also list branches which have
864 inactive. If -c/--closed is specified, also list branches which have
865 been marked closed (see :hg:`commit --close-branch`).
865 been marked closed (see :hg:`commit --close-branch`).
866
866
867 If -a/--active is specified, only show active branches. A branch
867 If -a/--active is specified, only show active branches. A branch
868 is considered active if it contains repository heads.
868 is considered active if it contains repository heads.
869
869
870 Use the command :hg:`update` to switch to an existing branch.
870 Use the command :hg:`update` to switch to an existing branch.
871
871
872 Returns 0.
872 Returns 0.
873 """
873 """
874
874
875 hexfunc = ui.debugflag and hex or short
875 hexfunc = ui.debugflag and hex or short
876 activebranches = [repo[n].branch() for n in repo.heads()]
876 activebranches = [repo[n].branch() for n in repo.heads()]
877 def testactive(tag, node):
877 def testactive(tag, node):
878 realhead = tag in activebranches
878 realhead = tag in activebranches
879 open = node in repo.branchheads(tag, closed=False)
879 open = node in repo.branchheads(tag, closed=False)
880 return realhead and open
880 return realhead and open
881 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
881 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
882 for tag, node in repo.branchtags().items()],
882 for tag, node in repo.branchtags().items()],
883 reverse=True)
883 reverse=True)
884
884
885 for isactive, node, tag in branches:
885 for isactive, node, tag in branches:
886 if (not active) or isactive:
886 if (not active) or isactive:
887 if ui.quiet:
887 if ui.quiet:
888 ui.write("%s\n" % tag)
888 ui.write("%s\n" % tag)
889 else:
889 else:
890 hn = repo.lookup(node)
890 hn = repo.lookup(node)
891 if isactive:
891 if isactive:
892 label = 'branches.active'
892 label = 'branches.active'
893 notice = ''
893 notice = ''
894 elif hn not in repo.branchheads(tag, closed=False):
894 elif hn not in repo.branchheads(tag, closed=False):
895 if not closed:
895 if not closed:
896 continue
896 continue
897 label = 'branches.closed'
897 label = 'branches.closed'
898 notice = _(' (closed)')
898 notice = _(' (closed)')
899 else:
899 else:
900 label = 'branches.inactive'
900 label = 'branches.inactive'
901 notice = _(' (inactive)')
901 notice = _(' (inactive)')
902 if tag == repo.dirstate.branch():
902 if tag == repo.dirstate.branch():
903 label = 'branches.current'
903 label = 'branches.current'
904 rev = str(node).rjust(31 - encoding.colwidth(tag))
904 rev = str(node).rjust(31 - encoding.colwidth(tag))
905 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
905 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
906 tag = ui.label(tag, label)
906 tag = ui.label(tag, label)
907 ui.write("%s %s%s\n" % (tag, rev, notice))
907 ui.write("%s %s%s\n" % (tag, rev, notice))
908
908
909 @command('bundle',
909 @command('bundle',
910 [('f', 'force', None, _('run even when the destination is unrelated')),
910 [('f', 'force', None, _('run even when the destination is unrelated')),
911 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
911 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
912 _('REV')),
912 _('REV')),
913 ('b', 'branch', [], _('a specific branch you would like to bundle'),
913 ('b', 'branch', [], _('a specific branch you would like to bundle'),
914 _('BRANCH')),
914 _('BRANCH')),
915 ('', 'base', [],
915 ('', 'base', [],
916 _('a base changeset assumed to be available at the destination'),
916 _('a base changeset assumed to be available at the destination'),
917 _('REV')),
917 _('REV')),
918 ('a', 'all', None, _('bundle all changesets in the repository')),
918 ('a', 'all', None, _('bundle all changesets in the repository')),
919 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
919 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
920 ] + remoteopts,
920 ] + remoteopts,
921 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
921 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
922 def bundle(ui, repo, fname, dest=None, **opts):
922 def bundle(ui, repo, fname, dest=None, **opts):
923 """create a changegroup file
923 """create a changegroup file
924
924
925 Generate a compressed changegroup file collecting changesets not
925 Generate a compressed changegroup file collecting changesets not
926 known to be in another repository.
926 known to be in another repository.
927
927
928 If you omit the destination repository, then hg assumes the
928 If you omit the destination repository, then hg assumes the
929 destination will have all the nodes you specify with --base
929 destination will have all the nodes you specify with --base
930 parameters. To create a bundle containing all changesets, use
930 parameters. To create a bundle containing all changesets, use
931 -a/--all (or --base null).
931 -a/--all (or --base null).
932
932
933 You can change compression method with the -t/--type option.
933 You can change compression method with the -t/--type option.
934 The available compression methods are: none, bzip2, and
934 The available compression methods are: none, bzip2, and
935 gzip (by default, bundles are compressed using bzip2).
935 gzip (by default, bundles are compressed using bzip2).
936
936
937 The bundle file can then be transferred using conventional means
937 The bundle file can then be transferred using conventional means
938 and applied to another repository with the unbundle or pull
938 and applied to another repository with the unbundle or pull
939 command. This is useful when direct push and pull are not
939 command. This is useful when direct push and pull are not
940 available or when exporting an entire repository is undesirable.
940 available or when exporting an entire repository is undesirable.
941
941
942 Applying bundles preserves all changeset contents including
942 Applying bundles preserves all changeset contents including
943 permissions, copy/rename information, and revision history.
943 permissions, copy/rename information, and revision history.
944
944
945 Returns 0 on success, 1 if no changes found.
945 Returns 0 on success, 1 if no changes found.
946 """
946 """
947 revs = None
947 revs = None
948 if 'rev' in opts:
948 if 'rev' in opts:
949 revs = scmutil.revrange(repo, opts['rev'])
949 revs = scmutil.revrange(repo, opts['rev'])
950
950
951 if opts.get('all'):
951 if opts.get('all'):
952 base = ['null']
952 base = ['null']
953 else:
953 else:
954 base = scmutil.revrange(repo, opts.get('base'))
954 base = scmutil.revrange(repo, opts.get('base'))
955 if base:
955 if base:
956 if dest:
956 if dest:
957 raise util.Abort(_("--base is incompatible with specifying "
957 raise util.Abort(_("--base is incompatible with specifying "
958 "a destination"))
958 "a destination"))
959 common = [repo.lookup(rev) for rev in base]
959 common = [repo.lookup(rev) for rev in base]
960 heads = revs and map(repo.lookup, revs) or revs
960 heads = revs and map(repo.lookup, revs) or revs
961 else:
961 else:
962 dest = ui.expandpath(dest or 'default-push', dest or 'default')
962 dest = ui.expandpath(dest or 'default-push', dest or 'default')
963 dest, branches = hg.parseurl(dest, opts.get('branch'))
963 dest, branches = hg.parseurl(dest, opts.get('branch'))
964 other = hg.peer(repo, opts, dest)
964 other = hg.peer(repo, opts, dest)
965 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
965 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
966 heads = revs and map(repo.lookup, revs) or revs
966 heads = revs and map(repo.lookup, revs) or revs
967 common, outheads = discovery.findcommonoutgoing(repo, other,
967 common, outheads = discovery.findcommonoutgoing(repo, other,
968 onlyheads=heads,
968 onlyheads=heads,
969 force=opts.get('force'))
969 force=opts.get('force'))
970
970
971 cg = repo.getbundle('bundle', common=common, heads=heads)
971 cg = repo.getbundle('bundle', common=common, heads=heads)
972 if not cg:
972 if not cg:
973 ui.status(_("no changes found\n"))
973 ui.status(_("no changes found\n"))
974 return 1
974 return 1
975
975
976 bundletype = opts.get('type', 'bzip2').lower()
976 bundletype = opts.get('type', 'bzip2').lower()
977 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
977 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
978 bundletype = btypes.get(bundletype)
978 bundletype = btypes.get(bundletype)
979 if bundletype not in changegroup.bundletypes:
979 if bundletype not in changegroup.bundletypes:
980 raise util.Abort(_('unknown bundle type specified with --type'))
980 raise util.Abort(_('unknown bundle type specified with --type'))
981
981
982 changegroup.writebundle(cg, fname, bundletype)
982 changegroup.writebundle(cg, fname, bundletype)
983
983
984 @command('cat',
984 @command('cat',
985 [('o', 'output', '',
985 [('o', 'output', '',
986 _('print output to file with formatted name'), _('FORMAT')),
986 _('print output to file with formatted name'), _('FORMAT')),
987 ('r', 'rev', '', _('print the given revision'), _('REV')),
987 ('r', 'rev', '', _('print the given revision'), _('REV')),
988 ('', 'decode', None, _('apply any matching decode filter')),
988 ('', 'decode', None, _('apply any matching decode filter')),
989 ] + walkopts,
989 ] + walkopts,
990 _('[OPTION]... FILE...'))
990 _('[OPTION]... FILE...'))
991 def cat(ui, repo, file1, *pats, **opts):
991 def cat(ui, repo, file1, *pats, **opts):
992 """output the current or given revision of files
992 """output the current or given revision of files
993
993
994 Print the specified files as they were at the given revision. If
994 Print the specified files as they were at the given revision. If
995 no revision is given, the parent of the working directory is used,
995 no revision is given, the parent of the working directory is used,
996 or tip if no revision is checked out.
996 or tip if no revision is checked out.
997
997
998 Output may be to a file, in which case the name of the file is
998 Output may be to a file, in which case the name of the file is
999 given using a format string. The formatting rules are the same as
999 given using a format string. The formatting rules are the same as
1000 for the export command, with the following additions:
1000 for the export command, with the following additions:
1001
1001
1002 :``%s``: basename of file being printed
1002 :``%s``: basename of file being printed
1003 :``%d``: dirname of file being printed, or '.' if in repository root
1003 :``%d``: dirname of file being printed, or '.' if in repository root
1004 :``%p``: root-relative path name of file being printed
1004 :``%p``: root-relative path name of file being printed
1005
1005
1006 Returns 0 on success.
1006 Returns 0 on success.
1007 """
1007 """
1008 ctx = scmutil.revsingle(repo, opts.get('rev'))
1008 ctx = scmutil.revsingle(repo, opts.get('rev'))
1009 err = 1
1009 err = 1
1010 m = scmutil.match(ctx, (file1,) + pats, opts)
1010 m = scmutil.match(ctx, (file1,) + pats, opts)
1011 for abs in ctx.walk(m):
1011 for abs in ctx.walk(m):
1012 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1012 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1013 pathname=abs)
1013 pathname=abs)
1014 data = ctx[abs].data()
1014 data = ctx[abs].data()
1015 if opts.get('decode'):
1015 if opts.get('decode'):
1016 data = repo.wwritedata(abs, data)
1016 data = repo.wwritedata(abs, data)
1017 fp.write(data)
1017 fp.write(data)
1018 fp.close()
1018 fp.close()
1019 err = 0
1019 err = 0
1020 return err
1020 return err
1021
1021
1022 @command('^clone',
1022 @command('^clone',
1023 [('U', 'noupdate', None,
1023 [('U', 'noupdate', None,
1024 _('the clone will include an empty working copy (only a repository)')),
1024 _('the clone will include an empty working copy (only a repository)')),
1025 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1025 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1026 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1026 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1027 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1027 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1028 ('', 'pull', None, _('use pull protocol to copy metadata')),
1028 ('', 'pull', None, _('use pull protocol to copy metadata')),
1029 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1029 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1030 ] + remoteopts,
1030 ] + remoteopts,
1031 _('[OPTION]... SOURCE [DEST]'))
1031 _('[OPTION]... SOURCE [DEST]'))
1032 def clone(ui, source, dest=None, **opts):
1032 def clone(ui, source, dest=None, **opts):
1033 """make a copy of an existing repository
1033 """make a copy of an existing repository
1034
1034
1035 Create a copy of an existing repository in a new directory.
1035 Create a copy of an existing repository in a new directory.
1036
1036
1037 If no destination directory name is specified, it defaults to the
1037 If no destination directory name is specified, it defaults to the
1038 basename of the source.
1038 basename of the source.
1039
1039
1040 The location of the source is added to the new repository's
1040 The location of the source is added to the new repository's
1041 ``.hg/hgrc`` file, as the default to be used for future pulls.
1041 ``.hg/hgrc`` file, as the default to be used for future pulls.
1042
1042
1043 Only local paths and ``ssh://`` URLs are supported as
1043 Only local paths and ``ssh://`` URLs are supported as
1044 destinations. For ``ssh://`` destinations, no working directory or
1044 destinations. For ``ssh://`` destinations, no working directory or
1045 ``.hg/hgrc`` will be created on the remote side.
1045 ``.hg/hgrc`` will be created on the remote side.
1046
1046
1047 To pull only a subset of changesets, specify one or more revisions
1047 To pull only a subset of changesets, specify one or more revisions
1048 identifiers with -r/--rev or branches with -b/--branch. The
1048 identifiers with -r/--rev or branches with -b/--branch. The
1049 resulting clone will contain only the specified changesets and
1049 resulting clone will contain only the specified changesets and
1050 their ancestors. These options (or 'clone src#rev dest') imply
1050 their ancestors. These options (or 'clone src#rev dest') imply
1051 --pull, even for local source repositories. Note that specifying a
1051 --pull, even for local source repositories. Note that specifying a
1052 tag will include the tagged changeset but not the changeset
1052 tag will include the tagged changeset but not the changeset
1053 containing the tag.
1053 containing the tag.
1054
1054
1055 To check out a particular version, use -u/--update, or
1055 To check out a particular version, use -u/--update, or
1056 -U/--noupdate to create a clone with no working directory.
1056 -U/--noupdate to create a clone with no working directory.
1057
1057
1058 .. container:: verbose
1058 .. container:: verbose
1059
1059
1060 For efficiency, hardlinks are used for cloning whenever the
1060 For efficiency, hardlinks are used for cloning whenever the
1061 source and destination are on the same filesystem (note this
1061 source and destination are on the same filesystem (note this
1062 applies only to the repository data, not to the working
1062 applies only to the repository data, not to the working
1063 directory). Some filesystems, such as AFS, implement hardlinking
1063 directory). Some filesystems, such as AFS, implement hardlinking
1064 incorrectly, but do not report errors. In these cases, use the
1064 incorrectly, but do not report errors. In these cases, use the
1065 --pull option to avoid hardlinking.
1065 --pull option to avoid hardlinking.
1066
1066
1067 In some cases, you can clone repositories and the working
1067 In some cases, you can clone repositories and the working
1068 directory using full hardlinks with ::
1068 directory using full hardlinks with ::
1069
1069
1070 $ cp -al REPO REPOCLONE
1070 $ cp -al REPO REPOCLONE
1071
1071
1072 This is the fastest way to clone, but it is not always safe. The
1072 This is the fastest way to clone, but it is not always safe. The
1073 operation is not atomic (making sure REPO is not modified during
1073 operation is not atomic (making sure REPO is not modified during
1074 the operation is up to you) and you have to make sure your
1074 the operation is up to you) and you have to make sure your
1075 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1075 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1076 so). Also, this is not compatible with certain extensions that
1076 so). Also, this is not compatible with certain extensions that
1077 place their metadata under the .hg directory, such as mq.
1077 place their metadata under the .hg directory, such as mq.
1078
1078
1079 Mercurial will update the working directory to the first applicable
1079 Mercurial will update the working directory to the first applicable
1080 revision from this list:
1080 revision from this list:
1081
1081
1082 a) null if -U or the source repository has no changesets
1082 a) null if -U or the source repository has no changesets
1083 b) if -u . and the source repository is local, the first parent of
1083 b) if -u . and the source repository is local, the first parent of
1084 the source repository's working directory
1084 the source repository's working directory
1085 c) the changeset specified with -u (if a branch name, this means the
1085 c) the changeset specified with -u (if a branch name, this means the
1086 latest head of that branch)
1086 latest head of that branch)
1087 d) the changeset specified with -r
1087 d) the changeset specified with -r
1088 e) the tipmost head specified with -b
1088 e) the tipmost head specified with -b
1089 f) the tipmost head specified with the url#branch source syntax
1089 f) the tipmost head specified with the url#branch source syntax
1090 g) the tipmost head of the default branch
1090 g) the tipmost head of the default branch
1091 h) tip
1091 h) tip
1092
1092
1093 Examples:
1093 Examples:
1094
1094
1095 - clone a remote repository to a new directory named hg/::
1095 - clone a remote repository to a new directory named hg/::
1096
1096
1097 hg clone http://selenic.com/hg
1097 hg clone http://selenic.com/hg
1098
1098
1099 - create a lightweight local clone::
1099 - create a lightweight local clone::
1100
1100
1101 hg clone project/ project-feature/
1101 hg clone project/ project-feature/
1102
1102
1103 - clone from an absolute path on an ssh server (note double-slash)::
1103 - clone from an absolute path on an ssh server (note double-slash)::
1104
1104
1105 hg clone ssh://user@server//home/projects/alpha/
1105 hg clone ssh://user@server//home/projects/alpha/
1106
1106
1107 - do a high-speed clone over a LAN while checking out a
1107 - do a high-speed clone over a LAN while checking out a
1108 specified version::
1108 specified version::
1109
1109
1110 hg clone --uncompressed http://server/repo -u 1.5
1110 hg clone --uncompressed http://server/repo -u 1.5
1111
1111
1112 - create a repository without changesets after a particular revision::
1112 - create a repository without changesets after a particular revision::
1113
1113
1114 hg clone -r 04e544 experimental/ good/
1114 hg clone -r 04e544 experimental/ good/
1115
1115
1116 - clone (and track) a particular named branch::
1116 - clone (and track) a particular named branch::
1117
1117
1118 hg clone http://selenic.com/hg#stable
1118 hg clone http://selenic.com/hg#stable
1119
1119
1120 See :hg:`help urls` for details on specifying URLs.
1120 See :hg:`help urls` for details on specifying URLs.
1121
1121
1122 Returns 0 on success.
1122 Returns 0 on success.
1123 """
1123 """
1124 if opts.get('noupdate') and opts.get('updaterev'):
1124 if opts.get('noupdate') and opts.get('updaterev'):
1125 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1125 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1126
1126
1127 r = hg.clone(ui, opts, source, dest,
1127 r = hg.clone(ui, opts, source, dest,
1128 pull=opts.get('pull'),
1128 pull=opts.get('pull'),
1129 stream=opts.get('uncompressed'),
1129 stream=opts.get('uncompressed'),
1130 rev=opts.get('rev'),
1130 rev=opts.get('rev'),
1131 update=opts.get('updaterev') or not opts.get('noupdate'),
1131 update=opts.get('updaterev') or not opts.get('noupdate'),
1132 branch=opts.get('branch'))
1132 branch=opts.get('branch'))
1133
1133
1134 return r is None
1134 return r is None
1135
1135
1136 @command('^commit|ci',
1136 @command('^commit|ci',
1137 [('A', 'addremove', None,
1137 [('A', 'addremove', None,
1138 _('mark new/missing files as added/removed before committing')),
1138 _('mark new/missing files as added/removed before committing')),
1139 ('', 'close-branch', None,
1139 ('', 'close-branch', None,
1140 _('mark a branch as closed, hiding it from the branch list')),
1140 _('mark a branch as closed, hiding it from the branch list')),
1141 ] + walkopts + commitopts + commitopts2,
1141 ] + walkopts + commitopts + commitopts2,
1142 _('[OPTION]... [FILE]...'))
1142 _('[OPTION]... [FILE]...'))
1143 def commit(ui, repo, *pats, **opts):
1143 def commit(ui, repo, *pats, **opts):
1144 """commit the specified files or all outstanding changes
1144 """commit the specified files or all outstanding changes
1145
1145
1146 Commit changes to the given files into the repository. Unlike a
1146 Commit changes to the given files into the repository. Unlike a
1147 centralized SCM, this operation is a local operation. See
1147 centralized SCM, this operation is a local operation. See
1148 :hg:`push` for a way to actively distribute your changes.
1148 :hg:`push` for a way to actively distribute your changes.
1149
1149
1150 If a list of files is omitted, all changes reported by :hg:`status`
1150 If a list of files is omitted, all changes reported by :hg:`status`
1151 will be committed.
1151 will be committed.
1152
1152
1153 If you are committing the result of a merge, do not provide any
1153 If you are committing the result of a merge, do not provide any
1154 filenames or -I/-X filters.
1154 filenames or -I/-X filters.
1155
1155
1156 If no commit message is specified, Mercurial starts your
1156 If no commit message is specified, Mercurial starts your
1157 configured editor where you can enter a message. In case your
1157 configured editor where you can enter a message. In case your
1158 commit fails, you will find a backup of your message in
1158 commit fails, you will find a backup of your message in
1159 ``.hg/last-message.txt``.
1159 ``.hg/last-message.txt``.
1160
1160
1161 See :hg:`help dates` for a list of formats valid for -d/--date.
1161 See :hg:`help dates` for a list of formats valid for -d/--date.
1162
1162
1163 Returns 0 on success, 1 if nothing changed.
1163 Returns 0 on success, 1 if nothing changed.
1164 """
1164 """
1165 extra = {}
1165 extra = {}
1166 if opts.get('close_branch'):
1166 if opts.get('close_branch'):
1167 if repo['.'].node() not in repo.branchheads():
1167 if repo['.'].node() not in repo.branchheads():
1168 # The topo heads set is included in the branch heads set of the
1168 # The topo heads set is included in the branch heads set of the
1169 # current branch, so it's sufficient to test branchheads
1169 # current branch, so it's sufficient to test branchheads
1170 raise util.Abort(_('can only close branch heads'))
1170 raise util.Abort(_('can only close branch heads'))
1171 extra['close'] = 1
1171 extra['close'] = 1
1172 e = cmdutil.commiteditor
1172 e = cmdutil.commiteditor
1173 if opts.get('force_editor'):
1173 if opts.get('force_editor'):
1174 e = cmdutil.commitforceeditor
1174 e = cmdutil.commitforceeditor
1175
1175
1176 def commitfunc(ui, repo, message, match, opts):
1176 def commitfunc(ui, repo, message, match, opts):
1177 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1177 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1178 editor=e, extra=extra)
1178 editor=e, extra=extra)
1179
1179
1180 branch = repo[None].branch()
1180 branch = repo[None].branch()
1181 bheads = repo.branchheads(branch)
1181 bheads = repo.branchheads(branch)
1182
1182
1183 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1183 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1184 if not node:
1184 if not node:
1185 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1185 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1186 if stat[3]:
1186 if stat[3]:
1187 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1187 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1188 % len(stat[3]))
1188 % len(stat[3]))
1189 else:
1189 else:
1190 ui.status(_("nothing changed\n"))
1190 ui.status(_("nothing changed\n"))
1191 return 1
1191 return 1
1192
1192
1193 ctx = repo[node]
1193 ctx = repo[node]
1194 parents = ctx.parents()
1194 parents = ctx.parents()
1195
1195
1196 if (bheads and node not in bheads and not
1196 if (bheads and node not in bheads and not
1197 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1197 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1198 ui.status(_('created new head\n'))
1198 ui.status(_('created new head\n'))
1199 # The message is not printed for initial roots. For the other
1199 # The message is not printed for initial roots. For the other
1200 # changesets, it is printed in the following situations:
1200 # changesets, it is printed in the following situations:
1201 #
1201 #
1202 # Par column: for the 2 parents with ...
1202 # Par column: for the 2 parents with ...
1203 # N: null or no parent
1203 # N: null or no parent
1204 # B: parent is on another named branch
1204 # B: parent is on another named branch
1205 # C: parent is a regular non head changeset
1205 # C: parent is a regular non head changeset
1206 # H: parent was a branch head of the current branch
1206 # H: parent was a branch head of the current branch
1207 # Msg column: whether we print "created new head" message
1207 # Msg column: whether we print "created new head" message
1208 # In the following, it is assumed that there already exists some
1208 # In the following, it is assumed that there already exists some
1209 # initial branch heads of the current branch, otherwise nothing is
1209 # initial branch heads of the current branch, otherwise nothing is
1210 # printed anyway.
1210 # printed anyway.
1211 #
1211 #
1212 # Par Msg Comment
1212 # Par Msg Comment
1213 # NN y additional topo root
1213 # NN y additional topo root
1214 #
1214 #
1215 # BN y additional branch root
1215 # BN y additional branch root
1216 # CN y additional topo head
1216 # CN y additional topo head
1217 # HN n usual case
1217 # HN n usual case
1218 #
1218 #
1219 # BB y weird additional branch root
1219 # BB y weird additional branch root
1220 # CB y branch merge
1220 # CB y branch merge
1221 # HB n merge with named branch
1221 # HB n merge with named branch
1222 #
1222 #
1223 # CC y additional head from merge
1223 # CC y additional head from merge
1224 # CH n merge with a head
1224 # CH n merge with a head
1225 #
1225 #
1226 # HH n head merge: head count decreases
1226 # HH n head merge: head count decreases
1227
1227
1228 if not opts.get('close_branch'):
1228 if not opts.get('close_branch'):
1229 for r in parents:
1229 for r in parents:
1230 if r.extra().get('close') and r.branch() == branch:
1230 if r.extra().get('close') and r.branch() == branch:
1231 ui.status(_('reopening closed branch head %d\n') % r)
1231 ui.status(_('reopening closed branch head %d\n') % r)
1232
1232
1233 if ui.debugflag:
1233 if ui.debugflag:
1234 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1234 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1235 elif ui.verbose:
1235 elif ui.verbose:
1236 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1236 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1237
1237
1238 @command('copy|cp',
1238 @command('copy|cp',
1239 [('A', 'after', None, _('record a copy that has already occurred')),
1239 [('A', 'after', None, _('record a copy that has already occurred')),
1240 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1240 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1241 ] + walkopts + dryrunopts,
1241 ] + walkopts + dryrunopts,
1242 _('[OPTION]... [SOURCE]... DEST'))
1242 _('[OPTION]... [SOURCE]... DEST'))
1243 def copy(ui, repo, *pats, **opts):
1243 def copy(ui, repo, *pats, **opts):
1244 """mark files as copied for the next commit
1244 """mark files as copied for the next commit
1245
1245
1246 Mark dest as having copies of source files. If dest is a
1246 Mark dest as having copies of source files. If dest is a
1247 directory, copies are put in that directory. If dest is a file,
1247 directory, copies are put in that directory. If dest is a file,
1248 the source must be a single file.
1248 the source must be a single file.
1249
1249
1250 By default, this command copies the contents of files as they
1250 By default, this command copies the contents of files as they
1251 exist in the working directory. If invoked with -A/--after, the
1251 exist in the working directory. If invoked with -A/--after, the
1252 operation is recorded, but no copying is performed.
1252 operation is recorded, but no copying is performed.
1253
1253
1254 This command takes effect with the next commit. To undo a copy
1254 This command takes effect with the next commit. To undo a copy
1255 before that, see :hg:`revert`.
1255 before that, see :hg:`revert`.
1256
1256
1257 Returns 0 on success, 1 if errors are encountered.
1257 Returns 0 on success, 1 if errors are encountered.
1258 """
1258 """
1259 wlock = repo.wlock(False)
1259 wlock = repo.wlock(False)
1260 try:
1260 try:
1261 return cmdutil.copy(ui, repo, pats, opts)
1261 return cmdutil.copy(ui, repo, pats, opts)
1262 finally:
1262 finally:
1263 wlock.release()
1263 wlock.release()
1264
1264
1265 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1265 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1266 def debugancestor(ui, repo, *args):
1266 def debugancestor(ui, repo, *args):
1267 """find the ancestor revision of two revisions in a given index"""
1267 """find the ancestor revision of two revisions in a given index"""
1268 if len(args) == 3:
1268 if len(args) == 3:
1269 index, rev1, rev2 = args
1269 index, rev1, rev2 = args
1270 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1270 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1271 lookup = r.lookup
1271 lookup = r.lookup
1272 elif len(args) == 2:
1272 elif len(args) == 2:
1273 if not repo:
1273 if not repo:
1274 raise util.Abort(_("there is no Mercurial repository here "
1274 raise util.Abort(_("there is no Mercurial repository here "
1275 "(.hg not found)"))
1275 "(.hg not found)"))
1276 rev1, rev2 = args
1276 rev1, rev2 = args
1277 r = repo.changelog
1277 r = repo.changelog
1278 lookup = repo.lookup
1278 lookup = repo.lookup
1279 else:
1279 else:
1280 raise util.Abort(_('either two or three arguments required'))
1280 raise util.Abort(_('either two or three arguments required'))
1281 a = r.ancestor(lookup(rev1), lookup(rev2))
1281 a = r.ancestor(lookup(rev1), lookup(rev2))
1282 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1282 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1283
1283
1284 @command('debugbuilddag',
1284 @command('debugbuilddag',
1285 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1285 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1286 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1286 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1287 ('n', 'new-file', None, _('add new file at each rev'))],
1287 ('n', 'new-file', None, _('add new file at each rev'))],
1288 _('[OPTION]... [TEXT]'))
1288 _('[OPTION]... [TEXT]'))
1289 def debugbuilddag(ui, repo, text=None,
1289 def debugbuilddag(ui, repo, text=None,
1290 mergeable_file=False,
1290 mergeable_file=False,
1291 overwritten_file=False,
1291 overwritten_file=False,
1292 new_file=False):
1292 new_file=False):
1293 """builds a repo with a given DAG from scratch in the current empty repo
1293 """builds a repo with a given DAG from scratch in the current empty repo
1294
1294
1295 The description of the DAG is read from stdin if not given on the
1295 The description of the DAG is read from stdin if not given on the
1296 command line.
1296 command line.
1297
1297
1298 Elements:
1298 Elements:
1299
1299
1300 - "+n" is a linear run of n nodes based on the current default parent
1300 - "+n" is a linear run of n nodes based on the current default parent
1301 - "." is a single node based on the current default parent
1301 - "." is a single node based on the current default parent
1302 - "$" resets the default parent to null (implied at the start);
1302 - "$" resets the default parent to null (implied at the start);
1303 otherwise the default parent is always the last node created
1303 otherwise the default parent is always the last node created
1304 - "<p" sets the default parent to the backref p
1304 - "<p" sets the default parent to the backref p
1305 - "*p" is a fork at parent p, which is a backref
1305 - "*p" is a fork at parent p, which is a backref
1306 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1306 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1307 - "/p2" is a merge of the preceding node and p2
1307 - "/p2" is a merge of the preceding node and p2
1308 - ":tag" defines a local tag for the preceding node
1308 - ":tag" defines a local tag for the preceding node
1309 - "@branch" sets the named branch for subsequent nodes
1309 - "@branch" sets the named branch for subsequent nodes
1310 - "#...\\n" is a comment up to the end of the line
1310 - "#...\\n" is a comment up to the end of the line
1311
1311
1312 Whitespace between the above elements is ignored.
1312 Whitespace between the above elements is ignored.
1313
1313
1314 A backref is either
1314 A backref is either
1315
1315
1316 - a number n, which references the node curr-n, where curr is the current
1316 - a number n, which references the node curr-n, where curr is the current
1317 node, or
1317 node, or
1318 - the name of a local tag you placed earlier using ":tag", or
1318 - the name of a local tag you placed earlier using ":tag", or
1319 - empty to denote the default parent.
1319 - empty to denote the default parent.
1320
1320
1321 All string valued-elements are either strictly alphanumeric, or must
1321 All string valued-elements are either strictly alphanumeric, or must
1322 be enclosed in double quotes ("..."), with "\\" as escape character.
1322 be enclosed in double quotes ("..."), with "\\" as escape character.
1323 """
1323 """
1324
1324
1325 if text is None:
1325 if text is None:
1326 ui.status(_("reading DAG from stdin\n"))
1326 ui.status(_("reading DAG from stdin\n"))
1327 text = ui.fin.read()
1327 text = ui.fin.read()
1328
1328
1329 cl = repo.changelog
1329 cl = repo.changelog
1330 if len(cl) > 0:
1330 if len(cl) > 0:
1331 raise util.Abort(_('repository is not empty'))
1331 raise util.Abort(_('repository is not empty'))
1332
1332
1333 # determine number of revs in DAG
1333 # determine number of revs in DAG
1334 total = 0
1334 total = 0
1335 for type, data in dagparser.parsedag(text):
1335 for type, data in dagparser.parsedag(text):
1336 if type == 'n':
1336 if type == 'n':
1337 total += 1
1337 total += 1
1338
1338
1339 if mergeable_file:
1339 if mergeable_file:
1340 linesperrev = 2
1340 linesperrev = 2
1341 # make a file with k lines per rev
1341 # make a file with k lines per rev
1342 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1342 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1343 initialmergedlines.append("")
1343 initialmergedlines.append("")
1344
1344
1345 tags = []
1345 tags = []
1346
1346
1347 tr = repo.transaction("builddag")
1347 tr = repo.transaction("builddag")
1348 try:
1348 try:
1349
1349
1350 at = -1
1350 at = -1
1351 atbranch = 'default'
1351 atbranch = 'default'
1352 nodeids = []
1352 nodeids = []
1353 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1353 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1354 for type, data in dagparser.parsedag(text):
1354 for type, data in dagparser.parsedag(text):
1355 if type == 'n':
1355 if type == 'n':
1356 ui.note('node %s\n' % str(data))
1356 ui.note('node %s\n' % str(data))
1357 id, ps = data
1357 id, ps = data
1358
1358
1359 files = []
1359 files = []
1360 fctxs = {}
1360 fctxs = {}
1361
1361
1362 p2 = None
1362 p2 = None
1363 if mergeable_file:
1363 if mergeable_file:
1364 fn = "mf"
1364 fn = "mf"
1365 p1 = repo[ps[0]]
1365 p1 = repo[ps[0]]
1366 if len(ps) > 1:
1366 if len(ps) > 1:
1367 p2 = repo[ps[1]]
1367 p2 = repo[ps[1]]
1368 pa = p1.ancestor(p2)
1368 pa = p1.ancestor(p2)
1369 base, local, other = [x[fn].data() for x in pa, p1, p2]
1369 base, local, other = [x[fn].data() for x in pa, p1, p2]
1370 m3 = simplemerge.Merge3Text(base, local, other)
1370 m3 = simplemerge.Merge3Text(base, local, other)
1371 ml = [l.strip() for l in m3.merge_lines()]
1371 ml = [l.strip() for l in m3.merge_lines()]
1372 ml.append("")
1372 ml.append("")
1373 elif at > 0:
1373 elif at > 0:
1374 ml = p1[fn].data().split("\n")
1374 ml = p1[fn].data().split("\n")
1375 else:
1375 else:
1376 ml = initialmergedlines
1376 ml = initialmergedlines
1377 ml[id * linesperrev] += " r%i" % id
1377 ml[id * linesperrev] += " r%i" % id
1378 mergedtext = "\n".join(ml)
1378 mergedtext = "\n".join(ml)
1379 files.append(fn)
1379 files.append(fn)
1380 fctxs[fn] = context.memfilectx(fn, mergedtext)
1380 fctxs[fn] = context.memfilectx(fn, mergedtext)
1381
1381
1382 if overwritten_file:
1382 if overwritten_file:
1383 fn = "of"
1383 fn = "of"
1384 files.append(fn)
1384 files.append(fn)
1385 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1385 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1386
1386
1387 if new_file:
1387 if new_file:
1388 fn = "nf%i" % id
1388 fn = "nf%i" % id
1389 files.append(fn)
1389 files.append(fn)
1390 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1390 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1391 if len(ps) > 1:
1391 if len(ps) > 1:
1392 if not p2:
1392 if not p2:
1393 p2 = repo[ps[1]]
1393 p2 = repo[ps[1]]
1394 for fn in p2:
1394 for fn in p2:
1395 if fn.startswith("nf"):
1395 if fn.startswith("nf"):
1396 files.append(fn)
1396 files.append(fn)
1397 fctxs[fn] = p2[fn]
1397 fctxs[fn] = p2[fn]
1398
1398
1399 def fctxfn(repo, cx, path):
1399 def fctxfn(repo, cx, path):
1400 return fctxs.get(path)
1400 return fctxs.get(path)
1401
1401
1402 if len(ps) == 0 or ps[0] < 0:
1402 if len(ps) == 0 or ps[0] < 0:
1403 pars = [None, None]
1403 pars = [None, None]
1404 elif len(ps) == 1:
1404 elif len(ps) == 1:
1405 pars = [nodeids[ps[0]], None]
1405 pars = [nodeids[ps[0]], None]
1406 else:
1406 else:
1407 pars = [nodeids[p] for p in ps]
1407 pars = [nodeids[p] for p in ps]
1408 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1408 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1409 date=(id, 0),
1409 date=(id, 0),
1410 user="debugbuilddag",
1410 user="debugbuilddag",
1411 extra={'branch': atbranch})
1411 extra={'branch': atbranch})
1412 nodeid = repo.commitctx(cx)
1412 nodeid = repo.commitctx(cx)
1413 nodeids.append(nodeid)
1413 nodeids.append(nodeid)
1414 at = id
1414 at = id
1415 elif type == 'l':
1415 elif type == 'l':
1416 id, name = data
1416 id, name = data
1417 ui.note('tag %s\n' % name)
1417 ui.note('tag %s\n' % name)
1418 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1418 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1419 elif type == 'a':
1419 elif type == 'a':
1420 ui.note('branch %s\n' % data)
1420 ui.note('branch %s\n' % data)
1421 atbranch = data
1421 atbranch = data
1422 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1422 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1423 tr.close()
1423 tr.close()
1424 finally:
1424 finally:
1425 ui.progress(_('building'), None)
1425 ui.progress(_('building'), None)
1426 tr.release()
1426 tr.release()
1427
1427
1428 if tags:
1428 if tags:
1429 repo.opener.write("localtags", "".join(tags))
1429 repo.opener.write("localtags", "".join(tags))
1430
1430
1431 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1431 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1432 def debugbundle(ui, bundlepath, all=None, **opts):
1432 def debugbundle(ui, bundlepath, all=None, **opts):
1433 """lists the contents of a bundle"""
1433 """lists the contents of a bundle"""
1434 f = url.open(ui, bundlepath)
1434 f = url.open(ui, bundlepath)
1435 try:
1435 try:
1436 gen = changegroup.readbundle(f, bundlepath)
1436 gen = changegroup.readbundle(f, bundlepath)
1437 if all:
1437 if all:
1438 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1438 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1439
1439
1440 def showchunks(named):
1440 def showchunks(named):
1441 ui.write("\n%s\n" % named)
1441 ui.write("\n%s\n" % named)
1442 chain = None
1442 chain = None
1443 while True:
1443 while True:
1444 chunkdata = gen.deltachunk(chain)
1444 chunkdata = gen.deltachunk(chain)
1445 if not chunkdata:
1445 if not chunkdata:
1446 break
1446 break
1447 node = chunkdata['node']
1447 node = chunkdata['node']
1448 p1 = chunkdata['p1']
1448 p1 = chunkdata['p1']
1449 p2 = chunkdata['p2']
1449 p2 = chunkdata['p2']
1450 cs = chunkdata['cs']
1450 cs = chunkdata['cs']
1451 deltabase = chunkdata['deltabase']
1451 deltabase = chunkdata['deltabase']
1452 delta = chunkdata['delta']
1452 delta = chunkdata['delta']
1453 ui.write("%s %s %s %s %s %s\n" %
1453 ui.write("%s %s %s %s %s %s\n" %
1454 (hex(node), hex(p1), hex(p2),
1454 (hex(node), hex(p1), hex(p2),
1455 hex(cs), hex(deltabase), len(delta)))
1455 hex(cs), hex(deltabase), len(delta)))
1456 chain = node
1456 chain = node
1457
1457
1458 chunkdata = gen.changelogheader()
1458 chunkdata = gen.changelogheader()
1459 showchunks("changelog")
1459 showchunks("changelog")
1460 chunkdata = gen.manifestheader()
1460 chunkdata = gen.manifestheader()
1461 showchunks("manifest")
1461 showchunks("manifest")
1462 while True:
1462 while True:
1463 chunkdata = gen.filelogheader()
1463 chunkdata = gen.filelogheader()
1464 if not chunkdata:
1464 if not chunkdata:
1465 break
1465 break
1466 fname = chunkdata['filename']
1466 fname = chunkdata['filename']
1467 showchunks(fname)
1467 showchunks(fname)
1468 else:
1468 else:
1469 chunkdata = gen.changelogheader()
1469 chunkdata = gen.changelogheader()
1470 chain = None
1470 chain = None
1471 while True:
1471 while True:
1472 chunkdata = gen.deltachunk(chain)
1472 chunkdata = gen.deltachunk(chain)
1473 if not chunkdata:
1473 if not chunkdata:
1474 break
1474 break
1475 node = chunkdata['node']
1475 node = chunkdata['node']
1476 ui.write("%s\n" % hex(node))
1476 ui.write("%s\n" % hex(node))
1477 chain = node
1477 chain = node
1478 finally:
1478 finally:
1479 f.close()
1479 f.close()
1480
1480
1481 @command('debugcheckstate', [], '')
1481 @command('debugcheckstate', [], '')
1482 def debugcheckstate(ui, repo):
1482 def debugcheckstate(ui, repo):
1483 """validate the correctness of the current dirstate"""
1483 """validate the correctness of the current dirstate"""
1484 parent1, parent2 = repo.dirstate.parents()
1484 parent1, parent2 = repo.dirstate.parents()
1485 m1 = repo[parent1].manifest()
1485 m1 = repo[parent1].manifest()
1486 m2 = repo[parent2].manifest()
1486 m2 = repo[parent2].manifest()
1487 errors = 0
1487 errors = 0
1488 for f in repo.dirstate:
1488 for f in repo.dirstate:
1489 state = repo.dirstate[f]
1489 state = repo.dirstate[f]
1490 if state in "nr" and f not in m1:
1490 if state in "nr" and f not in m1:
1491 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1491 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1492 errors += 1
1492 errors += 1
1493 if state in "a" and f in m1:
1493 if state in "a" and f in m1:
1494 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1494 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1495 errors += 1
1495 errors += 1
1496 if state in "m" and f not in m1 and f not in m2:
1496 if state in "m" and f not in m1 and f not in m2:
1497 ui.warn(_("%s in state %s, but not in either manifest\n") %
1497 ui.warn(_("%s in state %s, but not in either manifest\n") %
1498 (f, state))
1498 (f, state))
1499 errors += 1
1499 errors += 1
1500 for f in m1:
1500 for f in m1:
1501 state = repo.dirstate[f]
1501 state = repo.dirstate[f]
1502 if state not in "nrm":
1502 if state not in "nrm":
1503 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1503 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1504 errors += 1
1504 errors += 1
1505 if errors:
1505 if errors:
1506 error = _(".hg/dirstate inconsistent with current parent's manifest")
1506 error = _(".hg/dirstate inconsistent with current parent's manifest")
1507 raise util.Abort(error)
1507 raise util.Abort(error)
1508
1508
1509 @command('debugcommands', [], _('[COMMAND]'))
1509 @command('debugcommands', [], _('[COMMAND]'))
1510 def debugcommands(ui, cmd='', *args):
1510 def debugcommands(ui, cmd='', *args):
1511 """list all available commands and options"""
1511 """list all available commands and options"""
1512 for cmd, vals in sorted(table.iteritems()):
1512 for cmd, vals in sorted(table.iteritems()):
1513 cmd = cmd.split('|')[0].strip('^')
1513 cmd = cmd.split('|')[0].strip('^')
1514 opts = ', '.join([i[1] for i in vals[1]])
1514 opts = ', '.join([i[1] for i in vals[1]])
1515 ui.write('%s: %s\n' % (cmd, opts))
1515 ui.write('%s: %s\n' % (cmd, opts))
1516
1516
1517 @command('debugcomplete',
1517 @command('debugcomplete',
1518 [('o', 'options', None, _('show the command options'))],
1518 [('o', 'options', None, _('show the command options'))],
1519 _('[-o] CMD'))
1519 _('[-o] CMD'))
1520 def debugcomplete(ui, cmd='', **opts):
1520 def debugcomplete(ui, cmd='', **opts):
1521 """returns the completion list associated with the given command"""
1521 """returns the completion list associated with the given command"""
1522
1522
1523 if opts.get('options'):
1523 if opts.get('options'):
1524 options = []
1524 options = []
1525 otables = [globalopts]
1525 otables = [globalopts]
1526 if cmd:
1526 if cmd:
1527 aliases, entry = cmdutil.findcmd(cmd, table, False)
1527 aliases, entry = cmdutil.findcmd(cmd, table, False)
1528 otables.append(entry[1])
1528 otables.append(entry[1])
1529 for t in otables:
1529 for t in otables:
1530 for o in t:
1530 for o in t:
1531 if "(DEPRECATED)" in o[3]:
1531 if "(DEPRECATED)" in o[3]:
1532 continue
1532 continue
1533 if o[0]:
1533 if o[0]:
1534 options.append('-%s' % o[0])
1534 options.append('-%s' % o[0])
1535 options.append('--%s' % o[1])
1535 options.append('--%s' % o[1])
1536 ui.write("%s\n" % "\n".join(options))
1536 ui.write("%s\n" % "\n".join(options))
1537 return
1537 return
1538
1538
1539 cmdlist = cmdutil.findpossible(cmd, table)
1539 cmdlist = cmdutil.findpossible(cmd, table)
1540 if ui.verbose:
1540 if ui.verbose:
1541 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1541 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1542 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1542 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1543
1543
1544 @command('debugdag',
1544 @command('debugdag',
1545 [('t', 'tags', None, _('use tags as labels')),
1545 [('t', 'tags', None, _('use tags as labels')),
1546 ('b', 'branches', None, _('annotate with branch names')),
1546 ('b', 'branches', None, _('annotate with branch names')),
1547 ('', 'dots', None, _('use dots for runs')),
1547 ('', 'dots', None, _('use dots for runs')),
1548 ('s', 'spaces', None, _('separate elements by spaces'))],
1548 ('s', 'spaces', None, _('separate elements by spaces'))],
1549 _('[OPTION]... [FILE [REV]...]'))
1549 _('[OPTION]... [FILE [REV]...]'))
1550 def debugdag(ui, repo, file_=None, *revs, **opts):
1550 def debugdag(ui, repo, file_=None, *revs, **opts):
1551 """format the changelog or an index DAG as a concise textual description
1551 """format the changelog or an index DAG as a concise textual description
1552
1552
1553 If you pass a revlog index, the revlog's DAG is emitted. If you list
1553 If you pass a revlog index, the revlog's DAG is emitted. If you list
1554 revision numbers, they get labelled in the output as rN.
1554 revision numbers, they get labelled in the output as rN.
1555
1555
1556 Otherwise, the changelog DAG of the current repo is emitted.
1556 Otherwise, the changelog DAG of the current repo is emitted.
1557 """
1557 """
1558 spaces = opts.get('spaces')
1558 spaces = opts.get('spaces')
1559 dots = opts.get('dots')
1559 dots = opts.get('dots')
1560 if file_:
1560 if file_:
1561 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1561 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1562 revs = set((int(r) for r in revs))
1562 revs = set((int(r) for r in revs))
1563 def events():
1563 def events():
1564 for r in rlog:
1564 for r in rlog:
1565 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1565 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1566 if r in revs:
1566 if r in revs:
1567 yield 'l', (r, "r%i" % r)
1567 yield 'l', (r, "r%i" % r)
1568 elif repo:
1568 elif repo:
1569 cl = repo.changelog
1569 cl = repo.changelog
1570 tags = opts.get('tags')
1570 tags = opts.get('tags')
1571 branches = opts.get('branches')
1571 branches = opts.get('branches')
1572 if tags:
1572 if tags:
1573 labels = {}
1573 labels = {}
1574 for l, n in repo.tags().items():
1574 for l, n in repo.tags().items():
1575 labels.setdefault(cl.rev(n), []).append(l)
1575 labels.setdefault(cl.rev(n), []).append(l)
1576 def events():
1576 def events():
1577 b = "default"
1577 b = "default"
1578 for r in cl:
1578 for r in cl:
1579 if branches:
1579 if branches:
1580 newb = cl.read(cl.node(r))[5]['branch']
1580 newb = cl.read(cl.node(r))[5]['branch']
1581 if newb != b:
1581 if newb != b:
1582 yield 'a', newb
1582 yield 'a', newb
1583 b = newb
1583 b = newb
1584 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1584 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1585 if tags:
1585 if tags:
1586 ls = labels.get(r)
1586 ls = labels.get(r)
1587 if ls:
1587 if ls:
1588 for l in ls:
1588 for l in ls:
1589 yield 'l', (r, l)
1589 yield 'l', (r, l)
1590 else:
1590 else:
1591 raise util.Abort(_('need repo for changelog dag'))
1591 raise util.Abort(_('need repo for changelog dag'))
1592
1592
1593 for line in dagparser.dagtextlines(events(),
1593 for line in dagparser.dagtextlines(events(),
1594 addspaces=spaces,
1594 addspaces=spaces,
1595 wraplabels=True,
1595 wraplabels=True,
1596 wrapannotations=True,
1596 wrapannotations=True,
1597 wrapnonlinear=dots,
1597 wrapnonlinear=dots,
1598 usedots=dots,
1598 usedots=dots,
1599 maxlinewidth=70):
1599 maxlinewidth=70):
1600 ui.write(line)
1600 ui.write(line)
1601 ui.write("\n")
1601 ui.write("\n")
1602
1602
1603 @command('debugdata',
1603 @command('debugdata',
1604 [('c', 'changelog', False, _('open changelog')),
1604 [('c', 'changelog', False, _('open changelog')),
1605 ('m', 'manifest', False, _('open manifest'))],
1605 ('m', 'manifest', False, _('open manifest'))],
1606 _('-c|-m|FILE REV'))
1606 _('-c|-m|FILE REV'))
1607 def debugdata(ui, repo, file_, rev = None, **opts):
1607 def debugdata(ui, repo, file_, rev = None, **opts):
1608 """dump the contents of a data file revision"""
1608 """dump the contents of a data file revision"""
1609 if opts.get('changelog') or opts.get('manifest'):
1609 if opts.get('changelog') or opts.get('manifest'):
1610 file_, rev = None, file_
1610 file_, rev = None, file_
1611 elif rev is None:
1611 elif rev is None:
1612 raise error.CommandError('debugdata', _('invalid arguments'))
1612 raise error.CommandError('debugdata', _('invalid arguments'))
1613 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1613 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1614 try:
1614 try:
1615 ui.write(r.revision(r.lookup(rev)))
1615 ui.write(r.revision(r.lookup(rev)))
1616 except KeyError:
1616 except KeyError:
1617 raise util.Abort(_('invalid revision identifier %s') % rev)
1617 raise util.Abort(_('invalid revision identifier %s') % rev)
1618
1618
1619 @command('debugdate',
1619 @command('debugdate',
1620 [('e', 'extended', None, _('try extended date formats'))],
1620 [('e', 'extended', None, _('try extended date formats'))],
1621 _('[-e] DATE [RANGE]'))
1621 _('[-e] DATE [RANGE]'))
1622 def debugdate(ui, date, range=None, **opts):
1622 def debugdate(ui, date, range=None, **opts):
1623 """parse and display a date"""
1623 """parse and display a date"""
1624 if opts["extended"]:
1624 if opts["extended"]:
1625 d = util.parsedate(date, util.extendeddateformats)
1625 d = util.parsedate(date, util.extendeddateformats)
1626 else:
1626 else:
1627 d = util.parsedate(date)
1627 d = util.parsedate(date)
1628 ui.write("internal: %s %s\n" % d)
1628 ui.write("internal: %s %s\n" % d)
1629 ui.write("standard: %s\n" % util.datestr(d))
1629 ui.write("standard: %s\n" % util.datestr(d))
1630 if range:
1630 if range:
1631 m = util.matchdate(range)
1631 m = util.matchdate(range)
1632 ui.write("match: %s\n" % m(d[0]))
1632 ui.write("match: %s\n" % m(d[0]))
1633
1633
1634 @command('debugdiscovery',
1634 @command('debugdiscovery',
1635 [('', 'old', None, _('use old-style discovery')),
1635 [('', 'old', None, _('use old-style discovery')),
1636 ('', 'nonheads', None,
1636 ('', 'nonheads', None,
1637 _('use old-style discovery with non-heads included')),
1637 _('use old-style discovery with non-heads included')),
1638 ] + remoteopts,
1638 ] + remoteopts,
1639 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1639 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1640 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1640 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1641 """runs the changeset discovery protocol in isolation"""
1641 """runs the changeset discovery protocol in isolation"""
1642 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1642 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1643 remote = hg.peer(repo, opts, remoteurl)
1643 remote = hg.peer(repo, opts, remoteurl)
1644 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1644 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1645
1645
1646 # make sure tests are repeatable
1646 # make sure tests are repeatable
1647 random.seed(12323)
1647 random.seed(12323)
1648
1648
1649 def doit(localheads, remoteheads):
1649 def doit(localheads, remoteheads):
1650 if opts.get('old'):
1650 if opts.get('old'):
1651 if localheads:
1651 if localheads:
1652 raise util.Abort('cannot use localheads with old style discovery')
1652 raise util.Abort('cannot use localheads with old style discovery')
1653 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1653 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1654 force=True)
1654 force=True)
1655 common = set(common)
1655 common = set(common)
1656 if not opts.get('nonheads'):
1656 if not opts.get('nonheads'):
1657 ui.write("unpruned common: %s\n" % " ".join([short(n)
1657 ui.write("unpruned common: %s\n" % " ".join([short(n)
1658 for n in common]))
1658 for n in common]))
1659 dag = dagutil.revlogdag(repo.changelog)
1659 dag = dagutil.revlogdag(repo.changelog)
1660 all = dag.ancestorset(dag.internalizeall(common))
1660 all = dag.ancestorset(dag.internalizeall(common))
1661 common = dag.externalizeall(dag.headsetofconnecteds(all))
1661 common = dag.externalizeall(dag.headsetofconnecteds(all))
1662 else:
1662 else:
1663 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1663 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1664 common = set(common)
1664 common = set(common)
1665 rheads = set(hds)
1665 rheads = set(hds)
1666 lheads = set(repo.heads())
1666 lheads = set(repo.heads())
1667 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1667 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1668 if lheads <= common:
1668 if lheads <= common:
1669 ui.write("local is subset\n")
1669 ui.write("local is subset\n")
1670 elif rheads <= common:
1670 elif rheads <= common:
1671 ui.write("remote is subset\n")
1671 ui.write("remote is subset\n")
1672
1672
1673 serverlogs = opts.get('serverlog')
1673 serverlogs = opts.get('serverlog')
1674 if serverlogs:
1674 if serverlogs:
1675 for filename in serverlogs:
1675 for filename in serverlogs:
1676 logfile = open(filename, 'r')
1676 logfile = open(filename, 'r')
1677 try:
1677 try:
1678 line = logfile.readline()
1678 line = logfile.readline()
1679 while line:
1679 while line:
1680 parts = line.strip().split(';')
1680 parts = line.strip().split(';')
1681 op = parts[1]
1681 op = parts[1]
1682 if op == 'cg':
1682 if op == 'cg':
1683 pass
1683 pass
1684 elif op == 'cgss':
1684 elif op == 'cgss':
1685 doit(parts[2].split(' '), parts[3].split(' '))
1685 doit(parts[2].split(' '), parts[3].split(' '))
1686 elif op == 'unb':
1686 elif op == 'unb':
1687 doit(parts[3].split(' '), parts[2].split(' '))
1687 doit(parts[3].split(' '), parts[2].split(' '))
1688 line = logfile.readline()
1688 line = logfile.readline()
1689 finally:
1689 finally:
1690 logfile.close()
1690 logfile.close()
1691
1691
1692 else:
1692 else:
1693 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1693 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1694 opts.get('remote_head'))
1694 opts.get('remote_head'))
1695 localrevs = opts.get('local_head')
1695 localrevs = opts.get('local_head')
1696 doit(localrevs, remoterevs)
1696 doit(localrevs, remoterevs)
1697
1697
1698 @command('debugfileset', [], ('REVSPEC'))
1698 @command('debugfileset', [], ('REVSPEC'))
1699 def debugfileset(ui, repo, expr):
1699 def debugfileset(ui, repo, expr):
1700 '''parse and apply a fileset specification'''
1700 '''parse and apply a fileset specification'''
1701 if ui.verbose:
1701 if ui.verbose:
1702 tree = fileset.parse(expr)[0]
1702 tree = fileset.parse(expr)[0]
1703 ui.note(tree, "\n")
1703 ui.note(tree, "\n")
1704
1704
1705 for f in fileset.getfileset(repo[None], expr):
1705 for f in fileset.getfileset(repo[None], expr):
1706 ui.write("%s\n" % f)
1706 ui.write("%s\n" % f)
1707
1707
1708 @command('debugfsinfo', [], _('[PATH]'))
1708 @command('debugfsinfo', [], _('[PATH]'))
1709 def debugfsinfo(ui, path = "."):
1709 def debugfsinfo(ui, path = "."):
1710 """show information detected about current filesystem"""
1710 """show information detected about current filesystem"""
1711 util.writefile('.debugfsinfo', '')
1711 util.writefile('.debugfsinfo', '')
1712 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1712 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1713 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1713 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1714 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1714 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1715 and 'yes' or 'no'))
1715 and 'yes' or 'no'))
1716 os.unlink('.debugfsinfo')
1716 os.unlink('.debugfsinfo')
1717
1717
1718 @command('debuggetbundle',
1718 @command('debuggetbundle',
1719 [('H', 'head', [], _('id of head node'), _('ID')),
1719 [('H', 'head', [], _('id of head node'), _('ID')),
1720 ('C', 'common', [], _('id of common node'), _('ID')),
1720 ('C', 'common', [], _('id of common node'), _('ID')),
1721 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1721 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1722 _('REPO FILE [-H|-C ID]...'))
1722 _('REPO FILE [-H|-C ID]...'))
1723 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1723 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1724 """retrieves a bundle from a repo
1724 """retrieves a bundle from a repo
1725
1725
1726 Every ID must be a full-length hex node id string. Saves the bundle to the
1726 Every ID must be a full-length hex node id string. Saves the bundle to the
1727 given file.
1727 given file.
1728 """
1728 """
1729 repo = hg.peer(ui, opts, repopath)
1729 repo = hg.peer(ui, opts, repopath)
1730 if not repo.capable('getbundle'):
1730 if not repo.capable('getbundle'):
1731 raise util.Abort("getbundle() not supported by target repository")
1731 raise util.Abort("getbundle() not supported by target repository")
1732 args = {}
1732 args = {}
1733 if common:
1733 if common:
1734 args['common'] = [bin(s) for s in common]
1734 args['common'] = [bin(s) for s in common]
1735 if head:
1735 if head:
1736 args['heads'] = [bin(s) for s in head]
1736 args['heads'] = [bin(s) for s in head]
1737 bundle = repo.getbundle('debug', **args)
1737 bundle = repo.getbundle('debug', **args)
1738
1738
1739 bundletype = opts.get('type', 'bzip2').lower()
1739 bundletype = opts.get('type', 'bzip2').lower()
1740 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1740 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1741 bundletype = btypes.get(bundletype)
1741 bundletype = btypes.get(bundletype)
1742 if bundletype not in changegroup.bundletypes:
1742 if bundletype not in changegroup.bundletypes:
1743 raise util.Abort(_('unknown bundle type specified with --type'))
1743 raise util.Abort(_('unknown bundle type specified with --type'))
1744 changegroup.writebundle(bundle, bundlepath, bundletype)
1744 changegroup.writebundle(bundle, bundlepath, bundletype)
1745
1745
1746 @command('debugignore', [], '')
1746 @command('debugignore', [], '')
1747 def debugignore(ui, repo, *values, **opts):
1747 def debugignore(ui, repo, *values, **opts):
1748 """display the combined ignore pattern"""
1748 """display the combined ignore pattern"""
1749 ignore = repo.dirstate._ignore
1749 ignore = repo.dirstate._ignore
1750 includepat = getattr(ignore, 'includepat', None)
1750 includepat = getattr(ignore, 'includepat', None)
1751 if includepat is not None:
1751 if includepat is not None:
1752 ui.write("%s\n" % includepat)
1752 ui.write("%s\n" % includepat)
1753 else:
1753 else:
1754 raise util.Abort(_("no ignore patterns found"))
1754 raise util.Abort(_("no ignore patterns found"))
1755
1755
1756 @command('debugindex',
1756 @command('debugindex',
1757 [('c', 'changelog', False, _('open changelog')),
1757 [('c', 'changelog', False, _('open changelog')),
1758 ('m', 'manifest', False, _('open manifest')),
1758 ('m', 'manifest', False, _('open manifest')),
1759 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1759 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1760 _('[-f FORMAT] -c|-m|FILE'))
1760 _('[-f FORMAT] -c|-m|FILE'))
1761 def debugindex(ui, repo, file_ = None, **opts):
1761 def debugindex(ui, repo, file_ = None, **opts):
1762 """dump the contents of an index file"""
1762 """dump the contents of an index file"""
1763 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1763 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1764 format = opts.get('format', 0)
1764 format = opts.get('format', 0)
1765 if format not in (0, 1):
1765 if format not in (0, 1):
1766 raise util.Abort(_("unknown format %d") % format)
1766 raise util.Abort(_("unknown format %d") % format)
1767
1767
1768 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1768 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1769 if generaldelta:
1769 if generaldelta:
1770 basehdr = ' delta'
1770 basehdr = ' delta'
1771 else:
1771 else:
1772 basehdr = ' base'
1772 basehdr = ' base'
1773
1773
1774 if format == 0:
1774 if format == 0:
1775 ui.write(" rev offset length " + basehdr + " linkrev"
1775 ui.write(" rev offset length " + basehdr + " linkrev"
1776 " nodeid p1 p2\n")
1776 " nodeid p1 p2\n")
1777 elif format == 1:
1777 elif format == 1:
1778 ui.write(" rev flag offset length"
1778 ui.write(" rev flag offset length"
1779 " size " + basehdr + " link p1 p2 nodeid\n")
1779 " size " + basehdr + " link p1 p2 nodeid\n")
1780
1780
1781 for i in r:
1781 for i in r:
1782 node = r.node(i)
1782 node = r.node(i)
1783 if generaldelta:
1783 if generaldelta:
1784 base = r.deltaparent(i)
1784 base = r.deltaparent(i)
1785 else:
1785 else:
1786 base = r.chainbase(i)
1786 base = r.chainbase(i)
1787 if format == 0:
1787 if format == 0:
1788 try:
1788 try:
1789 pp = r.parents(node)
1789 pp = r.parents(node)
1790 except:
1790 except:
1791 pp = [nullid, nullid]
1791 pp = [nullid, nullid]
1792 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1792 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1793 i, r.start(i), r.length(i), base, r.linkrev(i),
1793 i, r.start(i), r.length(i), base, r.linkrev(i),
1794 short(node), short(pp[0]), short(pp[1])))
1794 short(node), short(pp[0]), short(pp[1])))
1795 elif format == 1:
1795 elif format == 1:
1796 pr = r.parentrevs(i)
1796 pr = r.parentrevs(i)
1797 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1797 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1798 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1798 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1799 base, r.linkrev(i), pr[0], pr[1], short(node)))
1799 base, r.linkrev(i), pr[0], pr[1], short(node)))
1800
1800
1801 @command('debugindexdot', [], _('FILE'))
1801 @command('debugindexdot', [], _('FILE'))
1802 def debugindexdot(ui, repo, file_):
1802 def debugindexdot(ui, repo, file_):
1803 """dump an index DAG as a graphviz dot file"""
1803 """dump an index DAG as a graphviz dot file"""
1804 r = None
1804 r = None
1805 if repo:
1805 if repo:
1806 filelog = repo.file(file_)
1806 filelog = repo.file(file_)
1807 if len(filelog):
1807 if len(filelog):
1808 r = filelog
1808 r = filelog
1809 if not r:
1809 if not r:
1810 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1810 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1811 ui.write("digraph G {\n")
1811 ui.write("digraph G {\n")
1812 for i in r:
1812 for i in r:
1813 node = r.node(i)
1813 node = r.node(i)
1814 pp = r.parents(node)
1814 pp = r.parents(node)
1815 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1815 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1816 if pp[1] != nullid:
1816 if pp[1] != nullid:
1817 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1817 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1818 ui.write("}\n")
1818 ui.write("}\n")
1819
1819
1820 @command('debuginstall', [], '')
1820 @command('debuginstall', [], '')
1821 def debuginstall(ui):
1821 def debuginstall(ui):
1822 '''test Mercurial installation
1822 '''test Mercurial installation
1823
1823
1824 Returns 0 on success.
1824 Returns 0 on success.
1825 '''
1825 '''
1826
1826
1827 def writetemp(contents):
1827 def writetemp(contents):
1828 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1828 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1829 f = os.fdopen(fd, "wb")
1829 f = os.fdopen(fd, "wb")
1830 f.write(contents)
1830 f.write(contents)
1831 f.close()
1831 f.close()
1832 return name
1832 return name
1833
1833
1834 problems = 0
1834 problems = 0
1835
1835
1836 # encoding
1836 # encoding
1837 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1837 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1838 try:
1838 try:
1839 encoding.fromlocal("test")
1839 encoding.fromlocal("test")
1840 except util.Abort, inst:
1840 except util.Abort, inst:
1841 ui.write(" %s\n" % inst)
1841 ui.write(" %s\n" % inst)
1842 ui.write(_(" (check that your locale is properly set)\n"))
1842 ui.write(_(" (check that your locale is properly set)\n"))
1843 problems += 1
1843 problems += 1
1844
1844
1845 # compiled modules
1845 # compiled modules
1846 ui.status(_("Checking installed modules (%s)...\n")
1846 ui.status(_("Checking installed modules (%s)...\n")
1847 % os.path.dirname(__file__))
1847 % os.path.dirname(__file__))
1848 try:
1848 try:
1849 import bdiff, mpatch, base85, osutil
1849 import bdiff, mpatch, base85, osutil
1850 except Exception, inst:
1850 except Exception, inst:
1851 ui.write(" %s\n" % inst)
1851 ui.write(" %s\n" % inst)
1852 ui.write(_(" One or more extensions could not be found"))
1852 ui.write(_(" One or more extensions could not be found"))
1853 ui.write(_(" (check that you compiled the extensions)\n"))
1853 ui.write(_(" (check that you compiled the extensions)\n"))
1854 problems += 1
1854 problems += 1
1855
1855
1856 # templates
1856 # templates
1857 ui.status(_("Checking templates...\n"))
1857 ui.status(_("Checking templates...\n"))
1858 try:
1858 try:
1859 import templater
1859 import templater
1860 templater.templater(templater.templatepath("map-cmdline.default"))
1860 templater.templater(templater.templatepath("map-cmdline.default"))
1861 except Exception, inst:
1861 except Exception, inst:
1862 ui.write(" %s\n" % inst)
1862 ui.write(" %s\n" % inst)
1863 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1863 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1864 problems += 1
1864 problems += 1
1865
1865
1866 # editor
1866 # editor
1867 ui.status(_("Checking commit editor...\n"))
1867 ui.status(_("Checking commit editor...\n"))
1868 editor = ui.geteditor()
1868 editor = ui.geteditor()
1869 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1869 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1870 if not cmdpath:
1870 if not cmdpath:
1871 if editor == 'vi':
1871 if editor == 'vi':
1872 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1872 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1873 ui.write(_(" (specify a commit editor in your configuration"
1873 ui.write(_(" (specify a commit editor in your configuration"
1874 " file)\n"))
1874 " file)\n"))
1875 else:
1875 else:
1876 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1876 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1877 ui.write(_(" (specify a commit editor in your configuration"
1877 ui.write(_(" (specify a commit editor in your configuration"
1878 " file)\n"))
1878 " file)\n"))
1879 problems += 1
1879 problems += 1
1880
1880
1881 # check username
1881 # check username
1882 ui.status(_("Checking username...\n"))
1882 ui.status(_("Checking username...\n"))
1883 try:
1883 try:
1884 ui.username()
1884 ui.username()
1885 except util.Abort, e:
1885 except util.Abort, e:
1886 ui.write(" %s\n" % e)
1886 ui.write(" %s\n" % e)
1887 ui.write(_(" (specify a username in your configuration file)\n"))
1887 ui.write(_(" (specify a username in your configuration file)\n"))
1888 problems += 1
1888 problems += 1
1889
1889
1890 if not problems:
1890 if not problems:
1891 ui.status(_("No problems detected\n"))
1891 ui.status(_("No problems detected\n"))
1892 else:
1892 else:
1893 ui.write(_("%s problems detected,"
1893 ui.write(_("%s problems detected,"
1894 " please check your install!\n") % problems)
1894 " please check your install!\n") % problems)
1895
1895
1896 return problems
1896 return problems
1897
1897
1898 @command('debugknown', [], _('REPO ID...'))
1898 @command('debugknown', [], _('REPO ID...'))
1899 def debugknown(ui, repopath, *ids, **opts):
1899 def debugknown(ui, repopath, *ids, **opts):
1900 """test whether node ids are known to a repo
1900 """test whether node ids are known to a repo
1901
1901
1902 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1902 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1903 indicating unknown/known.
1903 indicating unknown/known.
1904 """
1904 """
1905 repo = hg.peer(ui, opts, repopath)
1905 repo = hg.peer(ui, opts, repopath)
1906 if not repo.capable('known'):
1906 if not repo.capable('known'):
1907 raise util.Abort("known() not supported by target repository")
1907 raise util.Abort("known() not supported by target repository")
1908 flags = repo.known([bin(s) for s in ids])
1908 flags = repo.known([bin(s) for s in ids])
1909 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1909 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1910
1910
1911 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1911 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1912 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1912 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1913 '''access the pushkey key/value protocol
1913 '''access the pushkey key/value protocol
1914
1914
1915 With two args, list the keys in the given namespace.
1915 With two args, list the keys in the given namespace.
1916
1916
1917 With five args, set a key to new if it currently is set to old.
1917 With five args, set a key to new if it currently is set to old.
1918 Reports success or failure.
1918 Reports success or failure.
1919 '''
1919 '''
1920
1920
1921 target = hg.peer(ui, {}, repopath)
1921 target = hg.peer(ui, {}, repopath)
1922 if keyinfo:
1922 if keyinfo:
1923 key, old, new = keyinfo
1923 key, old, new = keyinfo
1924 r = target.pushkey(namespace, key, old, new)
1924 r = target.pushkey(namespace, key, old, new)
1925 ui.status(str(r) + '\n')
1925 ui.status(str(r) + '\n')
1926 return not r
1926 return not r
1927 else:
1927 else:
1928 for k, v in target.listkeys(namespace).iteritems():
1928 for k, v in target.listkeys(namespace).iteritems():
1929 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1929 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1930 v.encode('string-escape')))
1930 v.encode('string-escape')))
1931
1931
1932 @command('debugrebuildstate',
1932 @command('debugrebuildstate',
1933 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1933 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1934 _('[-r REV] [REV]'))
1934 _('[-r REV] [REV]'))
1935 def debugrebuildstate(ui, repo, rev="tip"):
1935 def debugrebuildstate(ui, repo, rev="tip"):
1936 """rebuild the dirstate as it would look like for the given revision"""
1936 """rebuild the dirstate as it would look like for the given revision"""
1937 ctx = scmutil.revsingle(repo, rev)
1937 ctx = scmutil.revsingle(repo, rev)
1938 wlock = repo.wlock()
1938 wlock = repo.wlock()
1939 try:
1939 try:
1940 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1940 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1941 finally:
1941 finally:
1942 wlock.release()
1942 wlock.release()
1943
1943
1944 @command('debugrename',
1944 @command('debugrename',
1945 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1945 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1946 _('[-r REV] FILE'))
1946 _('[-r REV] FILE'))
1947 def debugrename(ui, repo, file1, *pats, **opts):
1947 def debugrename(ui, repo, file1, *pats, **opts):
1948 """dump rename information"""
1948 """dump rename information"""
1949
1949
1950 ctx = scmutil.revsingle(repo, opts.get('rev'))
1950 ctx = scmutil.revsingle(repo, opts.get('rev'))
1951 m = scmutil.match(ctx, (file1,) + pats, opts)
1951 m = scmutil.match(ctx, (file1,) + pats, opts)
1952 for abs in ctx.walk(m):
1952 for abs in ctx.walk(m):
1953 fctx = ctx[abs]
1953 fctx = ctx[abs]
1954 o = fctx.filelog().renamed(fctx.filenode())
1954 o = fctx.filelog().renamed(fctx.filenode())
1955 rel = m.rel(abs)
1955 rel = m.rel(abs)
1956 if o:
1956 if o:
1957 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1957 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1958 else:
1958 else:
1959 ui.write(_("%s not renamed\n") % rel)
1959 ui.write(_("%s not renamed\n") % rel)
1960
1960
1961 @command('debugrevlog',
1961 @command('debugrevlog',
1962 [('c', 'changelog', False, _('open changelog')),
1962 [('c', 'changelog', False, _('open changelog')),
1963 ('m', 'manifest', False, _('open manifest')),
1963 ('m', 'manifest', False, _('open manifest')),
1964 ('d', 'dump', False, _('dump index data'))],
1964 ('d', 'dump', False, _('dump index data'))],
1965 _('-c|-m|FILE'))
1965 _('-c|-m|FILE'))
1966 def debugrevlog(ui, repo, file_ = None, **opts):
1966 def debugrevlog(ui, repo, file_ = None, **opts):
1967 """show data and statistics about a revlog"""
1967 """show data and statistics about a revlog"""
1968 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1968 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1969
1969
1970 if opts.get("dump"):
1970 if opts.get("dump"):
1971 numrevs = len(r)
1971 numrevs = len(r)
1972 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1972 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1973 " rawsize totalsize compression heads\n")
1973 " rawsize totalsize compression heads\n")
1974 ts = 0
1974 ts = 0
1975 heads = set()
1975 heads = set()
1976 for rev in xrange(numrevs):
1976 for rev in xrange(numrevs):
1977 dbase = r.deltaparent(rev)
1977 dbase = r.deltaparent(rev)
1978 if dbase == -1:
1978 if dbase == -1:
1979 dbase = rev
1979 dbase = rev
1980 cbase = r.chainbase(rev)
1980 cbase = r.chainbase(rev)
1981 p1, p2 = r.parentrevs(rev)
1981 p1, p2 = r.parentrevs(rev)
1982 rs = r.rawsize(rev)
1982 rs = r.rawsize(rev)
1983 ts = ts + rs
1983 ts = ts + rs
1984 heads -= set(r.parentrevs(rev))
1984 heads -= set(r.parentrevs(rev))
1985 heads.add(rev)
1985 heads.add(rev)
1986 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1986 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1987 (rev, p1, p2, r.start(rev), r.end(rev),
1987 (rev, p1, p2, r.start(rev), r.end(rev),
1988 r.start(dbase), r.start(cbase),
1988 r.start(dbase), r.start(cbase),
1989 r.start(p1), r.start(p2),
1989 r.start(p1), r.start(p2),
1990 rs, ts, ts / r.end(rev), len(heads)))
1990 rs, ts, ts / r.end(rev), len(heads)))
1991 return 0
1991 return 0
1992
1992
1993 v = r.version
1993 v = r.version
1994 format = v & 0xFFFF
1994 format = v & 0xFFFF
1995 flags = []
1995 flags = []
1996 gdelta = False
1996 gdelta = False
1997 if v & revlog.REVLOGNGINLINEDATA:
1997 if v & revlog.REVLOGNGINLINEDATA:
1998 flags.append('inline')
1998 flags.append('inline')
1999 if v & revlog.REVLOGGENERALDELTA:
1999 if v & revlog.REVLOGGENERALDELTA:
2000 gdelta = True
2000 gdelta = True
2001 flags.append('generaldelta')
2001 flags.append('generaldelta')
2002 if not flags:
2002 if not flags:
2003 flags = ['(none)']
2003 flags = ['(none)']
2004
2004
2005 nummerges = 0
2005 nummerges = 0
2006 numfull = 0
2006 numfull = 0
2007 numprev = 0
2007 numprev = 0
2008 nump1 = 0
2008 nump1 = 0
2009 nump2 = 0
2009 nump2 = 0
2010 numother = 0
2010 numother = 0
2011 nump1prev = 0
2011 nump1prev = 0
2012 nump2prev = 0
2012 nump2prev = 0
2013 chainlengths = []
2013 chainlengths = []
2014
2014
2015 datasize = [None, 0, 0L]
2015 datasize = [None, 0, 0L]
2016 fullsize = [None, 0, 0L]
2016 fullsize = [None, 0, 0L]
2017 deltasize = [None, 0, 0L]
2017 deltasize = [None, 0, 0L]
2018
2018
2019 def addsize(size, l):
2019 def addsize(size, l):
2020 if l[0] is None or size < l[0]:
2020 if l[0] is None or size < l[0]:
2021 l[0] = size
2021 l[0] = size
2022 if size > l[1]:
2022 if size > l[1]:
2023 l[1] = size
2023 l[1] = size
2024 l[2] += size
2024 l[2] += size
2025
2025
2026 numrevs = len(r)
2026 numrevs = len(r)
2027 for rev in xrange(numrevs):
2027 for rev in xrange(numrevs):
2028 p1, p2 = r.parentrevs(rev)
2028 p1, p2 = r.parentrevs(rev)
2029 delta = r.deltaparent(rev)
2029 delta = r.deltaparent(rev)
2030 if format > 0:
2030 if format > 0:
2031 addsize(r.rawsize(rev), datasize)
2031 addsize(r.rawsize(rev), datasize)
2032 if p2 != nullrev:
2032 if p2 != nullrev:
2033 nummerges += 1
2033 nummerges += 1
2034 size = r.length(rev)
2034 size = r.length(rev)
2035 if delta == nullrev:
2035 if delta == nullrev:
2036 chainlengths.append(0)
2036 chainlengths.append(0)
2037 numfull += 1
2037 numfull += 1
2038 addsize(size, fullsize)
2038 addsize(size, fullsize)
2039 else:
2039 else:
2040 chainlengths.append(chainlengths[delta] + 1)
2040 chainlengths.append(chainlengths[delta] + 1)
2041 addsize(size, deltasize)
2041 addsize(size, deltasize)
2042 if delta == rev - 1:
2042 if delta == rev - 1:
2043 numprev += 1
2043 numprev += 1
2044 if delta == p1:
2044 if delta == p1:
2045 nump1prev += 1
2045 nump1prev += 1
2046 elif delta == p2:
2046 elif delta == p2:
2047 nump2prev += 1
2047 nump2prev += 1
2048 elif delta == p1:
2048 elif delta == p1:
2049 nump1 += 1
2049 nump1 += 1
2050 elif delta == p2:
2050 elif delta == p2:
2051 nump2 += 1
2051 nump2 += 1
2052 elif delta != nullrev:
2052 elif delta != nullrev:
2053 numother += 1
2053 numother += 1
2054
2054
2055 numdeltas = numrevs - numfull
2055 numdeltas = numrevs - numfull
2056 numoprev = numprev - nump1prev - nump2prev
2056 numoprev = numprev - nump1prev - nump2prev
2057 totalrawsize = datasize[2]
2057 totalrawsize = datasize[2]
2058 datasize[2] /= numrevs
2058 datasize[2] /= numrevs
2059 fulltotal = fullsize[2]
2059 fulltotal = fullsize[2]
2060 fullsize[2] /= numfull
2060 fullsize[2] /= numfull
2061 deltatotal = deltasize[2]
2061 deltatotal = deltasize[2]
2062 deltasize[2] /= numrevs - numfull
2062 deltasize[2] /= numrevs - numfull
2063 totalsize = fulltotal + deltatotal
2063 totalsize = fulltotal + deltatotal
2064 avgchainlen = sum(chainlengths) / numrevs
2064 avgchainlen = sum(chainlengths) / numrevs
2065 compratio = totalrawsize / totalsize
2065 compratio = totalrawsize / totalsize
2066
2066
2067 basedfmtstr = '%%%dd\n'
2067 basedfmtstr = '%%%dd\n'
2068 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2068 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2069
2069
2070 def dfmtstr(max):
2070 def dfmtstr(max):
2071 return basedfmtstr % len(str(max))
2071 return basedfmtstr % len(str(max))
2072 def pcfmtstr(max, padding=0):
2072 def pcfmtstr(max, padding=0):
2073 return basepcfmtstr % (len(str(max)), ' ' * padding)
2073 return basepcfmtstr % (len(str(max)), ' ' * padding)
2074
2074
2075 def pcfmt(value, total):
2075 def pcfmt(value, total):
2076 return (value, 100 * float(value) / total)
2076 return (value, 100 * float(value) / total)
2077
2077
2078 ui.write('format : %d\n' % format)
2078 ui.write('format : %d\n' % format)
2079 ui.write('flags : %s\n' % ', '.join(flags))
2079 ui.write('flags : %s\n' % ', '.join(flags))
2080
2080
2081 ui.write('\n')
2081 ui.write('\n')
2082 fmt = pcfmtstr(totalsize)
2082 fmt = pcfmtstr(totalsize)
2083 fmt2 = dfmtstr(totalsize)
2083 fmt2 = dfmtstr(totalsize)
2084 ui.write('revisions : ' + fmt2 % numrevs)
2084 ui.write('revisions : ' + fmt2 % numrevs)
2085 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2085 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2086 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2086 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2087 ui.write('revisions : ' + fmt2 % numrevs)
2087 ui.write('revisions : ' + fmt2 % numrevs)
2088 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2088 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2089 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2089 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2090 ui.write('revision size : ' + fmt2 % totalsize)
2090 ui.write('revision size : ' + fmt2 % totalsize)
2091 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2091 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2092 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2092 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2093
2093
2094 ui.write('\n')
2094 ui.write('\n')
2095 fmt = dfmtstr(max(avgchainlen, compratio))
2095 fmt = dfmtstr(max(avgchainlen, compratio))
2096 ui.write('avg chain length : ' + fmt % avgchainlen)
2096 ui.write('avg chain length : ' + fmt % avgchainlen)
2097 ui.write('compression ratio : ' + fmt % compratio)
2097 ui.write('compression ratio : ' + fmt % compratio)
2098
2098
2099 if format > 0:
2099 if format > 0:
2100 ui.write('\n')
2100 ui.write('\n')
2101 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2101 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2102 % tuple(datasize))
2102 % tuple(datasize))
2103 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2103 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2104 % tuple(fullsize))
2104 % tuple(fullsize))
2105 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2105 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2106 % tuple(deltasize))
2106 % tuple(deltasize))
2107
2107
2108 if numdeltas > 0:
2108 if numdeltas > 0:
2109 ui.write('\n')
2109 ui.write('\n')
2110 fmt = pcfmtstr(numdeltas)
2110 fmt = pcfmtstr(numdeltas)
2111 fmt2 = pcfmtstr(numdeltas, 4)
2111 fmt2 = pcfmtstr(numdeltas, 4)
2112 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2112 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2113 if numprev > 0:
2113 if numprev > 0:
2114 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2114 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2115 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2115 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2116 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2116 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2117 if gdelta:
2117 if gdelta:
2118 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2118 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2119 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2119 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2120 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2120 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2121
2121
2122 @command('debugrevspec', [], ('REVSPEC'))
2122 @command('debugrevspec', [], ('REVSPEC'))
2123 def debugrevspec(ui, repo, expr):
2123 def debugrevspec(ui, repo, expr):
2124 '''parse and apply a revision specification'''
2124 '''parse and apply a revision specification'''
2125 if ui.verbose:
2125 if ui.verbose:
2126 tree = revset.parse(expr)[0]
2126 tree = revset.parse(expr)[0]
2127 ui.note(tree, "\n")
2127 ui.note(tree, "\n")
2128 newtree = revset.findaliases(ui, tree)
2128 newtree = revset.findaliases(ui, tree)
2129 if newtree != tree:
2129 if newtree != tree:
2130 ui.note(newtree, "\n")
2130 ui.note(newtree, "\n")
2131 func = revset.match(ui, expr)
2131 func = revset.match(ui, expr)
2132 for c in func(repo, range(len(repo))):
2132 for c in func(repo, range(len(repo))):
2133 ui.write("%s\n" % c)
2133 ui.write("%s\n" % c)
2134
2134
2135 @command('debugsetparents', [], _('REV1 [REV2]'))
2135 @command('debugsetparents', [], _('REV1 [REV2]'))
2136 def debugsetparents(ui, repo, rev1, rev2=None):
2136 def debugsetparents(ui, repo, rev1, rev2=None):
2137 """manually set the parents of the current working directory
2137 """manually set the parents of the current working directory
2138
2138
2139 This is useful for writing repository conversion tools, but should
2139 This is useful for writing repository conversion tools, but should
2140 be used with care.
2140 be used with care.
2141
2141
2142 Returns 0 on success.
2142 Returns 0 on success.
2143 """
2143 """
2144
2144
2145 r1 = scmutil.revsingle(repo, rev1).node()
2145 r1 = scmutil.revsingle(repo, rev1).node()
2146 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2146 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2147
2147
2148 wlock = repo.wlock()
2148 wlock = repo.wlock()
2149 try:
2149 try:
2150 repo.dirstate.setparents(r1, r2)
2150 repo.dirstate.setparents(r1, r2)
2151 finally:
2151 finally:
2152 wlock.release()
2152 wlock.release()
2153
2153
2154 @command('debugstate',
2154 @command('debugstate',
2155 [('', 'nodates', None, _('do not display the saved mtime')),
2155 [('', 'nodates', None, _('do not display the saved mtime')),
2156 ('', 'datesort', None, _('sort by saved mtime'))],
2156 ('', 'datesort', None, _('sort by saved mtime'))],
2157 _('[OPTION]...'))
2157 _('[OPTION]...'))
2158 def debugstate(ui, repo, nodates=None, datesort=None):
2158 def debugstate(ui, repo, nodates=None, datesort=None):
2159 """show the contents of the current dirstate"""
2159 """show the contents of the current dirstate"""
2160 timestr = ""
2160 timestr = ""
2161 showdate = not nodates
2161 showdate = not nodates
2162 if datesort:
2162 if datesort:
2163 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2163 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2164 else:
2164 else:
2165 keyfunc = None # sort by filename
2165 keyfunc = None # sort by filename
2166 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2166 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2167 if showdate:
2167 if showdate:
2168 if ent[3] == -1:
2168 if ent[3] == -1:
2169 # Pad or slice to locale representation
2169 # Pad or slice to locale representation
2170 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2170 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2171 time.localtime(0)))
2171 time.localtime(0)))
2172 timestr = 'unset'
2172 timestr = 'unset'
2173 timestr = (timestr[:locale_len] +
2173 timestr = (timestr[:locale_len] +
2174 ' ' * (locale_len - len(timestr)))
2174 ' ' * (locale_len - len(timestr)))
2175 else:
2175 else:
2176 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2176 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2177 time.localtime(ent[3]))
2177 time.localtime(ent[3]))
2178 if ent[1] & 020000:
2178 if ent[1] & 020000:
2179 mode = 'lnk'
2179 mode = 'lnk'
2180 else:
2180 else:
2181 mode = '%3o' % (ent[1] & 0777)
2181 mode = '%3o' % (ent[1] & 0777)
2182 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2182 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2183 for f in repo.dirstate.copies():
2183 for f in repo.dirstate.copies():
2184 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2184 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2185
2185
2186 @command('debugsub',
2186 @command('debugsub',
2187 [('r', 'rev', '',
2187 [('r', 'rev', '',
2188 _('revision to check'), _('REV'))],
2188 _('revision to check'), _('REV'))],
2189 _('[-r REV] [REV]'))
2189 _('[-r REV] [REV]'))
2190 def debugsub(ui, repo, rev=None):
2190 def debugsub(ui, repo, rev=None):
2191 ctx = scmutil.revsingle(repo, rev, None)
2191 ctx = scmutil.revsingle(repo, rev, None)
2192 for k, v in sorted(ctx.substate.items()):
2192 for k, v in sorted(ctx.substate.items()):
2193 ui.write('path %s\n' % k)
2193 ui.write('path %s\n' % k)
2194 ui.write(' source %s\n' % v[0])
2194 ui.write(' source %s\n' % v[0])
2195 ui.write(' revision %s\n' % v[1])
2195 ui.write(' revision %s\n' % v[1])
2196
2196
2197 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2197 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2198 def debugwalk(ui, repo, *pats, **opts):
2198 def debugwalk(ui, repo, *pats, **opts):
2199 """show how files match on given patterns"""
2199 """show how files match on given patterns"""
2200 m = scmutil.match(repo[None], pats, opts)
2200 m = scmutil.match(repo[None], pats, opts)
2201 items = list(repo.walk(m))
2201 items = list(repo.walk(m))
2202 if not items:
2202 if not items:
2203 return
2203 return
2204 fmt = 'f %%-%ds %%-%ds %%s' % (
2204 fmt = 'f %%-%ds %%-%ds %%s' % (
2205 max([len(abs) for abs in items]),
2205 max([len(abs) for abs in items]),
2206 max([len(m.rel(abs)) for abs in items]))
2206 max([len(m.rel(abs)) for abs in items]))
2207 for abs in items:
2207 for abs in items:
2208 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2208 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2209 ui.write("%s\n" % line.rstrip())
2209 ui.write("%s\n" % line.rstrip())
2210
2210
2211 @command('debugwireargs',
2211 @command('debugwireargs',
2212 [('', 'three', '', 'three'),
2212 [('', 'three', '', 'three'),
2213 ('', 'four', '', 'four'),
2213 ('', 'four', '', 'four'),
2214 ('', 'five', '', 'five'),
2214 ('', 'five', '', 'five'),
2215 ] + remoteopts,
2215 ] + remoteopts,
2216 _('REPO [OPTIONS]... [ONE [TWO]]'))
2216 _('REPO [OPTIONS]... [ONE [TWO]]'))
2217 def debugwireargs(ui, repopath, *vals, **opts):
2217 def debugwireargs(ui, repopath, *vals, **opts):
2218 repo = hg.peer(ui, opts, repopath)
2218 repo = hg.peer(ui, opts, repopath)
2219 for opt in remoteopts:
2219 for opt in remoteopts:
2220 del opts[opt[1]]
2220 del opts[opt[1]]
2221 args = {}
2221 args = {}
2222 for k, v in opts.iteritems():
2222 for k, v in opts.iteritems():
2223 if v:
2223 if v:
2224 args[k] = v
2224 args[k] = v
2225 # run twice to check that we don't mess up the stream for the next command
2225 # run twice to check that we don't mess up the stream for the next command
2226 res1 = repo.debugwireargs(*vals, **args)
2226 res1 = repo.debugwireargs(*vals, **args)
2227 res2 = repo.debugwireargs(*vals, **args)
2227 res2 = repo.debugwireargs(*vals, **args)
2228 ui.write("%s\n" % res1)
2228 ui.write("%s\n" % res1)
2229 if res1 != res2:
2229 if res1 != res2:
2230 ui.warn("%s\n" % res2)
2230 ui.warn("%s\n" % res2)
2231
2231
2232 @command('^diff',
2232 @command('^diff',
2233 [('r', 'rev', [], _('revision'), _('REV')),
2233 [('r', 'rev', [], _('revision'), _('REV')),
2234 ('c', 'change', '', _('change made by revision'), _('REV'))
2234 ('c', 'change', '', _('change made by revision'), _('REV'))
2235 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2235 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2236 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2236 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2237 def diff(ui, repo, *pats, **opts):
2237 def diff(ui, repo, *pats, **opts):
2238 """diff repository (or selected files)
2238 """diff repository (or selected files)
2239
2239
2240 Show differences between revisions for the specified files.
2240 Show differences between revisions for the specified files.
2241
2241
2242 Differences between files are shown using the unified diff format.
2242 Differences between files are shown using the unified diff format.
2243
2243
2244 .. note::
2244 .. note::
2245 diff may generate unexpected results for merges, as it will
2245 diff may generate unexpected results for merges, as it will
2246 default to comparing against the working directory's first
2246 default to comparing against the working directory's first
2247 parent changeset if no revisions are specified.
2247 parent changeset if no revisions are specified.
2248
2248
2249 When two revision arguments are given, then changes are shown
2249 When two revision arguments are given, then changes are shown
2250 between those revisions. If only one revision is specified then
2250 between those revisions. If only one revision is specified then
2251 that revision is compared to the working directory, and, when no
2251 that revision is compared to the working directory, and, when no
2252 revisions are specified, the working directory files are compared
2252 revisions are specified, the working directory files are compared
2253 to its parent.
2253 to its parent.
2254
2254
2255 Alternatively you can specify -c/--change with a revision to see
2255 Alternatively you can specify -c/--change with a revision to see
2256 the changes in that changeset relative to its first parent.
2256 the changes in that changeset relative to its first parent.
2257
2257
2258 Without the -a/--text option, diff will avoid generating diffs of
2258 Without the -a/--text option, diff will avoid generating diffs of
2259 files it detects as binary. With -a, diff will generate a diff
2259 files it detects as binary. With -a, diff will generate a diff
2260 anyway, probably with undesirable results.
2260 anyway, probably with undesirable results.
2261
2261
2262 Use the -g/--git option to generate diffs in the git extended diff
2262 Use the -g/--git option to generate diffs in the git extended diff
2263 format. For more information, read :hg:`help diffs`.
2263 format. For more information, read :hg:`help diffs`.
2264
2264
2265 .. container:: verbose
2265 .. container:: verbose
2266
2266
2267 Examples:
2267 Examples:
2268
2268
2269 - compare a file in the current working directory to its parent::
2269 - compare a file in the current working directory to its parent::
2270
2270
2271 hg diff foo.c
2271 hg diff foo.c
2272
2272
2273 - compare two historical versions of a directory, with rename info::
2273 - compare two historical versions of a directory, with rename info::
2274
2274
2275 hg diff --git -r 1.0:1.2 lib/
2275 hg diff --git -r 1.0:1.2 lib/
2276
2276
2277 - get change stats relative to the last change on some date::
2277 - get change stats relative to the last change on some date::
2278
2278
2279 hg diff --stat -r "date('may 2')"
2279 hg diff --stat -r "date('may 2')"
2280
2280
2281 - diff all newly-added files that contain a keyword::
2281 - diff all newly-added files that contain a keyword::
2282
2282
2283 hg diff "set:added() and grep(GNU)"
2283 hg diff "set:added() and grep(GNU)"
2284
2284
2285 - compare a revision and its parents::
2285 - compare a revision and its parents::
2286
2286
2287 hg diff -c 9353 # compare against first parent
2287 hg diff -c 9353 # compare against first parent
2288 hg diff -r 9353^:9353 # same using revset syntax
2288 hg diff -r 9353^:9353 # same using revset syntax
2289 hg diff -r 9353^2:9353 # compare against the second parent
2289 hg diff -r 9353^2:9353 # compare against the second parent
2290
2290
2291 Returns 0 on success.
2291 Returns 0 on success.
2292 """
2292 """
2293
2293
2294 revs = opts.get('rev')
2294 revs = opts.get('rev')
2295 change = opts.get('change')
2295 change = opts.get('change')
2296 stat = opts.get('stat')
2296 stat = opts.get('stat')
2297 reverse = opts.get('reverse')
2297 reverse = opts.get('reverse')
2298
2298
2299 if revs and change:
2299 if revs and change:
2300 msg = _('cannot specify --rev and --change at the same time')
2300 msg = _('cannot specify --rev and --change at the same time')
2301 raise util.Abort(msg)
2301 raise util.Abort(msg)
2302 elif change:
2302 elif change:
2303 node2 = scmutil.revsingle(repo, change, None).node()
2303 node2 = scmutil.revsingle(repo, change, None).node()
2304 node1 = repo[node2].p1().node()
2304 node1 = repo[node2].p1().node()
2305 else:
2305 else:
2306 node1, node2 = scmutil.revpair(repo, revs)
2306 node1, node2 = scmutil.revpair(repo, revs)
2307
2307
2308 if reverse:
2308 if reverse:
2309 node1, node2 = node2, node1
2309 node1, node2 = node2, node1
2310
2310
2311 diffopts = patch.diffopts(ui, opts)
2311 diffopts = patch.diffopts(ui, opts)
2312 m = scmutil.match(repo[node2], pats, opts)
2312 m = scmutil.match(repo[node2], pats, opts)
2313 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2313 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2314 listsubrepos=opts.get('subrepos'))
2314 listsubrepos=opts.get('subrepos'))
2315
2315
2316 @command('^export',
2316 @command('^export',
2317 [('o', 'output', '',
2317 [('o', 'output', '',
2318 _('print output to file with formatted name'), _('FORMAT')),
2318 _('print output to file with formatted name'), _('FORMAT')),
2319 ('', 'switch-parent', None, _('diff against the second parent')),
2319 ('', 'switch-parent', None, _('diff against the second parent')),
2320 ('r', 'rev', [], _('revisions to export'), _('REV')),
2320 ('r', 'rev', [], _('revisions to export'), _('REV')),
2321 ] + diffopts,
2321 ] + diffopts,
2322 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2322 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2323 def export(ui, repo, *changesets, **opts):
2323 def export(ui, repo, *changesets, **opts):
2324 """dump the header and diffs for one or more changesets
2324 """dump the header and diffs for one or more changesets
2325
2325
2326 Print the changeset header and diffs for one or more revisions.
2326 Print the changeset header and diffs for one or more revisions.
2327
2327
2328 The information shown in the changeset header is: author, date,
2328 The information shown in the changeset header is: author, date,
2329 branch name (if non-default), changeset hash, parent(s) and commit
2329 branch name (if non-default), changeset hash, parent(s) and commit
2330 comment.
2330 comment.
2331
2331
2332 .. note::
2332 .. note::
2333 export may generate unexpected diff output for merge
2333 export may generate unexpected diff output for merge
2334 changesets, as it will compare the merge changeset against its
2334 changesets, as it will compare the merge changeset against its
2335 first parent only.
2335 first parent only.
2336
2336
2337 Output may be to a file, in which case the name of the file is
2337 Output may be to a file, in which case the name of the file is
2338 given using a format string. The formatting rules are as follows:
2338 given using a format string. The formatting rules are as follows:
2339
2339
2340 :``%%``: literal "%" character
2340 :``%%``: literal "%" character
2341 :``%H``: changeset hash (40 hexadecimal digits)
2341 :``%H``: changeset hash (40 hexadecimal digits)
2342 :``%N``: number of patches being generated
2342 :``%N``: number of patches being generated
2343 :``%R``: changeset revision number
2343 :``%R``: changeset revision number
2344 :``%b``: basename of the exporting repository
2344 :``%b``: basename of the exporting repository
2345 :``%h``: short-form changeset hash (12 hexadecimal digits)
2345 :``%h``: short-form changeset hash (12 hexadecimal digits)
2346 :``%m``: first line of the commit message (only alphanumeric characters)
2346 :``%m``: first line of the commit message (only alphanumeric characters)
2347 :``%n``: zero-padded sequence number, starting at 1
2347 :``%n``: zero-padded sequence number, starting at 1
2348 :``%r``: zero-padded changeset revision number
2348 :``%r``: zero-padded changeset revision number
2349
2349
2350 Without the -a/--text option, export will avoid generating diffs
2350 Without the -a/--text option, export will avoid generating diffs
2351 of files it detects as binary. With -a, export will generate a
2351 of files it detects as binary. With -a, export will generate a
2352 diff anyway, probably with undesirable results.
2352 diff anyway, probably with undesirable results.
2353
2353
2354 Use the -g/--git option to generate diffs in the git extended diff
2354 Use the -g/--git option to generate diffs in the git extended diff
2355 format. See :hg:`help diffs` for more information.
2355 format. See :hg:`help diffs` for more information.
2356
2356
2357 With the --switch-parent option, the diff will be against the
2357 With the --switch-parent option, the diff will be against the
2358 second parent. It can be useful to review a merge.
2358 second parent. It can be useful to review a merge.
2359
2359
2360 .. container:: verbose
2360 .. container:: verbose
2361
2361
2362 Examples:
2362 Examples:
2363
2363
2364 - use export and import to transplant a bugfix to the current
2364 - use export and import to transplant a bugfix to the current
2365 branch::
2365 branch::
2366
2366
2367 hg export -r 9353 | hg import -
2367 hg export -r 9353 | hg import -
2368
2368
2369 - export all the changesets between two revisions to a file with
2369 - export all the changesets between two revisions to a file with
2370 rename information::
2370 rename information::
2371
2371
2372 hg export --git -r 123:150 > changes.txt
2372 hg export --git -r 123:150 > changes.txt
2373
2373
2374 - split outgoing changes into a series of patches with
2374 - split outgoing changes into a series of patches with
2375 descriptive names::
2375 descriptive names::
2376
2376
2377 hg export -r "outgoing()" -o "%n-%m.patch"
2377 hg export -r "outgoing()" -o "%n-%m.patch"
2378
2378
2379 Returns 0 on success.
2379 Returns 0 on success.
2380 """
2380 """
2381 changesets += tuple(opts.get('rev', []))
2381 changesets += tuple(opts.get('rev', []))
2382 if not changesets:
2382 if not changesets:
2383 raise util.Abort(_("export requires at least one changeset"))
2383 raise util.Abort(_("export requires at least one changeset"))
2384 revs = scmutil.revrange(repo, changesets)
2384 revs = scmutil.revrange(repo, changesets)
2385 if len(revs) > 1:
2385 if len(revs) > 1:
2386 ui.note(_('exporting patches:\n'))
2386 ui.note(_('exporting patches:\n'))
2387 else:
2387 else:
2388 ui.note(_('exporting patch:\n'))
2388 ui.note(_('exporting patch:\n'))
2389 cmdutil.export(repo, revs, template=opts.get('output'),
2389 cmdutil.export(repo, revs, template=opts.get('output'),
2390 switch_parent=opts.get('switch_parent'),
2390 switch_parent=opts.get('switch_parent'),
2391 opts=patch.diffopts(ui, opts))
2391 opts=patch.diffopts(ui, opts))
2392
2392
2393 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2393 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2394 def forget(ui, repo, *pats, **opts):
2394 def forget(ui, repo, *pats, **opts):
2395 """forget the specified files on the next commit
2395 """forget the specified files on the next commit
2396
2396
2397 Mark the specified files so they will no longer be tracked
2397 Mark the specified files so they will no longer be tracked
2398 after the next commit.
2398 after the next commit.
2399
2399
2400 This only removes files from the current branch, not from the
2400 This only removes files from the current branch, not from the
2401 entire project history, and it does not delete them from the
2401 entire project history, and it does not delete them from the
2402 working directory.
2402 working directory.
2403
2403
2404 To undo a forget before the next commit, see :hg:`add`.
2404 To undo a forget before the next commit, see :hg:`add`.
2405
2405
2406 .. container:: verbose
2406 .. container:: verbose
2407
2407
2408 Examples:
2408 Examples:
2409
2409
2410 - forget newly-added binary files::
2410 - forget newly-added binary files::
2411
2411
2412 hg forget "set:added() and binary()"
2412 hg forget "set:added() and binary()"
2413
2413
2414 - forget files that would be excluded by .hgignore::
2414 - forget files that would be excluded by .hgignore::
2415
2415
2416 hg forget "set:hgignore()"
2416 hg forget "set:hgignore()"
2417
2417
2418 Returns 0 on success.
2418 Returns 0 on success.
2419 """
2419 """
2420
2420
2421 if not pats:
2421 if not pats:
2422 raise util.Abort(_('no files specified'))
2422 raise util.Abort(_('no files specified'))
2423
2423
2424 m = scmutil.match(repo[None], pats, opts)
2424 m = scmutil.match(repo[None], pats, opts)
2425 s = repo.status(match=m, clean=True)
2425 s = repo.status(match=m, clean=True)
2426 forget = sorted(s[0] + s[1] + s[3] + s[6])
2426 forget = sorted(s[0] + s[1] + s[3] + s[6])
2427 errs = 0
2427 errs = 0
2428
2428
2429 for f in m.files():
2429 for f in m.files():
2430 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2430 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2431 if os.path.exists(m.rel(f)):
2431 if os.path.exists(m.rel(f)):
2432 ui.warn(_('not removing %s: file is already untracked\n')
2432 ui.warn(_('not removing %s: file is already untracked\n')
2433 % m.rel(f))
2433 % m.rel(f))
2434 errs = 1
2434 errs = 1
2435
2435
2436 for f in forget:
2436 for f in forget:
2437 if ui.verbose or not m.exact(f):
2437 if ui.verbose or not m.exact(f):
2438 ui.status(_('removing %s\n') % m.rel(f))
2438 ui.status(_('removing %s\n') % m.rel(f))
2439
2439
2440 repo[None].forget(forget)
2440 repo[None].forget(forget)
2441 return errs
2441 return errs
2442
2442
2443 @command('grep',
2443 @command('grep',
2444 [('0', 'print0', None, _('end fields with NUL')),
2444 [('0', 'print0', None, _('end fields with NUL')),
2445 ('', 'all', None, _('print all revisions that match')),
2445 ('', 'all', None, _('print all revisions that match')),
2446 ('a', 'text', None, _('treat all files as text')),
2446 ('a', 'text', None, _('treat all files as text')),
2447 ('f', 'follow', None,
2447 ('f', 'follow', None,
2448 _('follow changeset history,'
2448 _('follow changeset history,'
2449 ' or file history across copies and renames')),
2449 ' or file history across copies and renames')),
2450 ('i', 'ignore-case', None, _('ignore case when matching')),
2450 ('i', 'ignore-case', None, _('ignore case when matching')),
2451 ('l', 'files-with-matches', None,
2451 ('l', 'files-with-matches', None,
2452 _('print only filenames and revisions that match')),
2452 _('print only filenames and revisions that match')),
2453 ('n', 'line-number', None, _('print matching line numbers')),
2453 ('n', 'line-number', None, _('print matching line numbers')),
2454 ('r', 'rev', [],
2454 ('r', 'rev', [],
2455 _('only search files changed within revision range'), _('REV')),
2455 _('only search files changed within revision range'), _('REV')),
2456 ('u', 'user', None, _('list the author (long with -v)')),
2456 ('u', 'user', None, _('list the author (long with -v)')),
2457 ('d', 'date', None, _('list the date (short with -q)')),
2457 ('d', 'date', None, _('list the date (short with -q)')),
2458 ] + walkopts,
2458 ] + walkopts,
2459 _('[OPTION]... PATTERN [FILE]...'))
2459 _('[OPTION]... PATTERN [FILE]...'))
2460 def grep(ui, repo, pattern, *pats, **opts):
2460 def grep(ui, repo, pattern, *pats, **opts):
2461 """search for a pattern in specified files and revisions
2461 """search for a pattern in specified files and revisions
2462
2462
2463 Search revisions of files for a regular expression.
2463 Search revisions of files for a regular expression.
2464
2464
2465 This command behaves differently than Unix grep. It only accepts
2465 This command behaves differently than Unix grep. It only accepts
2466 Python/Perl regexps. It searches repository history, not the
2466 Python/Perl regexps. It searches repository history, not the
2467 working directory. It always prints the revision number in which a
2467 working directory. It always prints the revision number in which a
2468 match appears.
2468 match appears.
2469
2469
2470 By default, grep only prints output for the first revision of a
2470 By default, grep only prints output for the first revision of a
2471 file in which it finds a match. To get it to print every revision
2471 file in which it finds a match. To get it to print every revision
2472 that contains a change in match status ("-" for a match that
2472 that contains a change in match status ("-" for a match that
2473 becomes a non-match, or "+" for a non-match that becomes a match),
2473 becomes a non-match, or "+" for a non-match that becomes a match),
2474 use the --all flag.
2474 use the --all flag.
2475
2475
2476 Returns 0 if a match is found, 1 otherwise.
2476 Returns 0 if a match is found, 1 otherwise.
2477 """
2477 """
2478 reflags = 0
2478 reflags = 0
2479 if opts.get('ignore_case'):
2479 if opts.get('ignore_case'):
2480 reflags |= re.I
2480 reflags |= re.I
2481 try:
2481 try:
2482 regexp = re.compile(pattern, reflags)
2482 regexp = re.compile(pattern, reflags)
2483 except re.error, inst:
2483 except re.error, inst:
2484 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2484 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2485 return 1
2485 return 1
2486 sep, eol = ':', '\n'
2486 sep, eol = ':', '\n'
2487 if opts.get('print0'):
2487 if opts.get('print0'):
2488 sep = eol = '\0'
2488 sep = eol = '\0'
2489
2489
2490 getfile = util.lrucachefunc(repo.file)
2490 getfile = util.lrucachefunc(repo.file)
2491
2491
2492 def matchlines(body):
2492 def matchlines(body):
2493 begin = 0
2493 begin = 0
2494 linenum = 0
2494 linenum = 0
2495 while True:
2495 while True:
2496 match = regexp.search(body, begin)
2496 match = regexp.search(body, begin)
2497 if not match:
2497 if not match:
2498 break
2498 break
2499 mstart, mend = match.span()
2499 mstart, mend = match.span()
2500 linenum += body.count('\n', begin, mstart) + 1
2500 linenum += body.count('\n', begin, mstart) + 1
2501 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2501 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2502 begin = body.find('\n', mend) + 1 or len(body)
2502 begin = body.find('\n', mend) + 1 or len(body)
2503 lend = begin - 1
2503 lend = begin - 1
2504 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2504 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2505
2505
2506 class linestate(object):
2506 class linestate(object):
2507 def __init__(self, line, linenum, colstart, colend):
2507 def __init__(self, line, linenum, colstart, colend):
2508 self.line = line
2508 self.line = line
2509 self.linenum = linenum
2509 self.linenum = linenum
2510 self.colstart = colstart
2510 self.colstart = colstart
2511 self.colend = colend
2511 self.colend = colend
2512
2512
2513 def __hash__(self):
2513 def __hash__(self):
2514 return hash((self.linenum, self.line))
2514 return hash((self.linenum, self.line))
2515
2515
2516 def __eq__(self, other):
2516 def __eq__(self, other):
2517 return self.line == other.line
2517 return self.line == other.line
2518
2518
2519 matches = {}
2519 matches = {}
2520 copies = {}
2520 copies = {}
2521 def grepbody(fn, rev, body):
2521 def grepbody(fn, rev, body):
2522 matches[rev].setdefault(fn, [])
2522 matches[rev].setdefault(fn, [])
2523 m = matches[rev][fn]
2523 m = matches[rev][fn]
2524 for lnum, cstart, cend, line in matchlines(body):
2524 for lnum, cstart, cend, line in matchlines(body):
2525 s = linestate(line, lnum, cstart, cend)
2525 s = linestate(line, lnum, cstart, cend)
2526 m.append(s)
2526 m.append(s)
2527
2527
2528 def difflinestates(a, b):
2528 def difflinestates(a, b):
2529 sm = difflib.SequenceMatcher(None, a, b)
2529 sm = difflib.SequenceMatcher(None, a, b)
2530 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2530 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2531 if tag == 'insert':
2531 if tag == 'insert':
2532 for i in xrange(blo, bhi):
2532 for i in xrange(blo, bhi):
2533 yield ('+', b[i])
2533 yield ('+', b[i])
2534 elif tag == 'delete':
2534 elif tag == 'delete':
2535 for i in xrange(alo, ahi):
2535 for i in xrange(alo, ahi):
2536 yield ('-', a[i])
2536 yield ('-', a[i])
2537 elif tag == 'replace':
2537 elif tag == 'replace':
2538 for i in xrange(alo, ahi):
2538 for i in xrange(alo, ahi):
2539 yield ('-', a[i])
2539 yield ('-', a[i])
2540 for i in xrange(blo, bhi):
2540 for i in xrange(blo, bhi):
2541 yield ('+', b[i])
2541 yield ('+', b[i])
2542
2542
2543 def display(fn, ctx, pstates, states):
2543 def display(fn, ctx, pstates, states):
2544 rev = ctx.rev()
2544 rev = ctx.rev()
2545 datefunc = ui.quiet and util.shortdate or util.datestr
2545 datefunc = ui.quiet and util.shortdate or util.datestr
2546 found = False
2546 found = False
2547 filerevmatches = {}
2547 filerevmatches = {}
2548 def binary():
2548 def binary():
2549 flog = getfile(fn)
2549 flog = getfile(fn)
2550 return util.binary(flog.read(ctx.filenode(fn)))
2550 return util.binary(flog.read(ctx.filenode(fn)))
2551
2551
2552 if opts.get('all'):
2552 if opts.get('all'):
2553 iter = difflinestates(pstates, states)
2553 iter = difflinestates(pstates, states)
2554 else:
2554 else:
2555 iter = [('', l) for l in states]
2555 iter = [('', l) for l in states]
2556 for change, l in iter:
2556 for change, l in iter:
2557 cols = [fn, str(rev)]
2557 cols = [fn, str(rev)]
2558 before, match, after = None, None, None
2558 before, match, after = None, None, None
2559 if opts.get('line_number'):
2559 if opts.get('line_number'):
2560 cols.append(str(l.linenum))
2560 cols.append(str(l.linenum))
2561 if opts.get('all'):
2561 if opts.get('all'):
2562 cols.append(change)
2562 cols.append(change)
2563 if opts.get('user'):
2563 if opts.get('user'):
2564 cols.append(ui.shortuser(ctx.user()))
2564 cols.append(ui.shortuser(ctx.user()))
2565 if opts.get('date'):
2565 if opts.get('date'):
2566 cols.append(datefunc(ctx.date()))
2566 cols.append(datefunc(ctx.date()))
2567 if opts.get('files_with_matches'):
2567 if opts.get('files_with_matches'):
2568 c = (fn, rev)
2568 c = (fn, rev)
2569 if c in filerevmatches:
2569 if c in filerevmatches:
2570 continue
2570 continue
2571 filerevmatches[c] = 1
2571 filerevmatches[c] = 1
2572 else:
2572 else:
2573 before = l.line[:l.colstart]
2573 before = l.line[:l.colstart]
2574 match = l.line[l.colstart:l.colend]
2574 match = l.line[l.colstart:l.colend]
2575 after = l.line[l.colend:]
2575 after = l.line[l.colend:]
2576 ui.write(sep.join(cols))
2576 ui.write(sep.join(cols))
2577 if before is not None:
2577 if before is not None:
2578 if not opts.get('text') and binary():
2578 if not opts.get('text') and binary():
2579 ui.write(sep + " Binary file matches")
2579 ui.write(sep + " Binary file matches")
2580 else:
2580 else:
2581 ui.write(sep + before)
2581 ui.write(sep + before)
2582 ui.write(match, label='grep.match')
2582 ui.write(match, label='grep.match')
2583 ui.write(after)
2583 ui.write(after)
2584 ui.write(eol)
2584 ui.write(eol)
2585 found = True
2585 found = True
2586 return found
2586 return found
2587
2587
2588 skip = {}
2588 skip = {}
2589 revfiles = {}
2589 revfiles = {}
2590 matchfn = scmutil.match(repo[None], pats, opts)
2590 matchfn = scmutil.match(repo[None], pats, opts)
2591 found = False
2591 found = False
2592 follow = opts.get('follow')
2592 follow = opts.get('follow')
2593
2593
2594 def prep(ctx, fns):
2594 def prep(ctx, fns):
2595 rev = ctx.rev()
2595 rev = ctx.rev()
2596 pctx = ctx.p1()
2596 pctx = ctx.p1()
2597 parent = pctx.rev()
2597 parent = pctx.rev()
2598 matches.setdefault(rev, {})
2598 matches.setdefault(rev, {})
2599 matches.setdefault(parent, {})
2599 matches.setdefault(parent, {})
2600 files = revfiles.setdefault(rev, [])
2600 files = revfiles.setdefault(rev, [])
2601 for fn in fns:
2601 for fn in fns:
2602 flog = getfile(fn)
2602 flog = getfile(fn)
2603 try:
2603 try:
2604 fnode = ctx.filenode(fn)
2604 fnode = ctx.filenode(fn)
2605 except error.LookupError:
2605 except error.LookupError:
2606 continue
2606 continue
2607
2607
2608 copied = flog.renamed(fnode)
2608 copied = flog.renamed(fnode)
2609 copy = follow and copied and copied[0]
2609 copy = follow and copied and copied[0]
2610 if copy:
2610 if copy:
2611 copies.setdefault(rev, {})[fn] = copy
2611 copies.setdefault(rev, {})[fn] = copy
2612 if fn in skip:
2612 if fn in skip:
2613 if copy:
2613 if copy:
2614 skip[copy] = True
2614 skip[copy] = True
2615 continue
2615 continue
2616 files.append(fn)
2616 files.append(fn)
2617
2617
2618 if fn not in matches[rev]:
2618 if fn not in matches[rev]:
2619 grepbody(fn, rev, flog.read(fnode))
2619 grepbody(fn, rev, flog.read(fnode))
2620
2620
2621 pfn = copy or fn
2621 pfn = copy or fn
2622 if pfn not in matches[parent]:
2622 if pfn not in matches[parent]:
2623 try:
2623 try:
2624 fnode = pctx.filenode(pfn)
2624 fnode = pctx.filenode(pfn)
2625 grepbody(pfn, parent, flog.read(fnode))
2625 grepbody(pfn, parent, flog.read(fnode))
2626 except error.LookupError:
2626 except error.LookupError:
2627 pass
2627 pass
2628
2628
2629 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2629 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2630 rev = ctx.rev()
2630 rev = ctx.rev()
2631 parent = ctx.p1().rev()
2631 parent = ctx.p1().rev()
2632 for fn in sorted(revfiles.get(rev, [])):
2632 for fn in sorted(revfiles.get(rev, [])):
2633 states = matches[rev][fn]
2633 states = matches[rev][fn]
2634 copy = copies.get(rev, {}).get(fn)
2634 copy = copies.get(rev, {}).get(fn)
2635 if fn in skip:
2635 if fn in skip:
2636 if copy:
2636 if copy:
2637 skip[copy] = True
2637 skip[copy] = True
2638 continue
2638 continue
2639 pstates = matches.get(parent, {}).get(copy or fn, [])
2639 pstates = matches.get(parent, {}).get(copy or fn, [])
2640 if pstates or states:
2640 if pstates or states:
2641 r = display(fn, ctx, pstates, states)
2641 r = display(fn, ctx, pstates, states)
2642 found = found or r
2642 found = found or r
2643 if r and not opts.get('all'):
2643 if r and not opts.get('all'):
2644 skip[fn] = True
2644 skip[fn] = True
2645 if copy:
2645 if copy:
2646 skip[copy] = True
2646 skip[copy] = True
2647 del matches[rev]
2647 del matches[rev]
2648 del revfiles[rev]
2648 del revfiles[rev]
2649
2649
2650 return not found
2650 return not found
2651
2651
2652 @command('heads',
2652 @command('heads',
2653 [('r', 'rev', '',
2653 [('r', 'rev', '',
2654 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2654 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2655 ('t', 'topo', False, _('show topological heads only')),
2655 ('t', 'topo', False, _('show topological heads only')),
2656 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2656 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2657 ('c', 'closed', False, _('show normal and closed branch heads')),
2657 ('c', 'closed', False, _('show normal and closed branch heads')),
2658 ] + templateopts,
2658 ] + templateopts,
2659 _('[-ac] [-r STARTREV] [REV]...'))
2659 _('[-ac] [-r STARTREV] [REV]...'))
2660 def heads(ui, repo, *branchrevs, **opts):
2660 def heads(ui, repo, *branchrevs, **opts):
2661 """show current repository heads or show branch heads
2661 """show current repository heads or show branch heads
2662
2662
2663 With no arguments, show all repository branch heads.
2663 With no arguments, show all repository branch heads.
2664
2664
2665 Repository "heads" are changesets with no child changesets. They are
2665 Repository "heads" are changesets with no child changesets. They are
2666 where development generally takes place and are the usual targets
2666 where development generally takes place and are the usual targets
2667 for update and merge operations. Branch heads are changesets that have
2667 for update and merge operations. Branch heads are changesets that have
2668 no child changeset on the same branch.
2668 no child changeset on the same branch.
2669
2669
2670 If one or more REVs are given, only branch heads on the branches
2670 If one or more REVs are given, only branch heads on the branches
2671 associated with the specified changesets are shown. This means
2671 associated with the specified changesets are shown. This means
2672 that you can use :hg:`heads foo` to see the heads on a branch
2672 that you can use :hg:`heads foo` to see the heads on a branch
2673 named ``foo``.
2673 named ``foo``.
2674
2674
2675 If -c/--closed is specified, also show branch heads marked closed
2675 If -c/--closed is specified, also show branch heads marked closed
2676 (see :hg:`commit --close-branch`).
2676 (see :hg:`commit --close-branch`).
2677
2677
2678 If STARTREV is specified, only those heads that are descendants of
2678 If STARTREV is specified, only those heads that are descendants of
2679 STARTREV will be displayed.
2679 STARTREV will be displayed.
2680
2680
2681 If -t/--topo is specified, named branch mechanics will be ignored and only
2681 If -t/--topo is specified, named branch mechanics will be ignored and only
2682 changesets without children will be shown.
2682 changesets without children will be shown.
2683
2683
2684 Returns 0 if matching heads are found, 1 if not.
2684 Returns 0 if matching heads are found, 1 if not.
2685 """
2685 """
2686
2686
2687 start = None
2687 start = None
2688 if 'rev' in opts:
2688 if 'rev' in opts:
2689 start = scmutil.revsingle(repo, opts['rev'], None).node()
2689 start = scmutil.revsingle(repo, opts['rev'], None).node()
2690
2690
2691 if opts.get('topo'):
2691 if opts.get('topo'):
2692 heads = [repo[h] for h in repo.heads(start)]
2692 heads = [repo[h] for h in repo.heads(start)]
2693 else:
2693 else:
2694 heads = []
2694 heads = []
2695 for branch in repo.branchmap():
2695 for branch in repo.branchmap():
2696 heads += repo.branchheads(branch, start, opts.get('closed'))
2696 heads += repo.branchheads(branch, start, opts.get('closed'))
2697 heads = [repo[h] for h in heads]
2697 heads = [repo[h] for h in heads]
2698
2698
2699 if branchrevs:
2699 if branchrevs:
2700 branches = set(repo[br].branch() for br in branchrevs)
2700 branches = set(repo[br].branch() for br in branchrevs)
2701 heads = [h for h in heads if h.branch() in branches]
2701 heads = [h for h in heads if h.branch() in branches]
2702
2702
2703 if opts.get('active') and branchrevs:
2703 if opts.get('active') and branchrevs:
2704 dagheads = repo.heads(start)
2704 dagheads = repo.heads(start)
2705 heads = [h for h in heads if h.node() in dagheads]
2705 heads = [h for h in heads if h.node() in dagheads]
2706
2706
2707 if branchrevs:
2707 if branchrevs:
2708 haveheads = set(h.branch() for h in heads)
2708 haveheads = set(h.branch() for h in heads)
2709 if branches - haveheads:
2709 if branches - haveheads:
2710 headless = ', '.join(b for b in branches - haveheads)
2710 headless = ', '.join(b for b in branches - haveheads)
2711 msg = _('no open branch heads found on branches %s')
2711 msg = _('no open branch heads found on branches %s')
2712 if opts.get('rev'):
2712 if opts.get('rev'):
2713 msg += _(' (started at %s)' % opts['rev'])
2713 msg += _(' (started at %s)' % opts['rev'])
2714 ui.warn((msg + '\n') % headless)
2714 ui.warn((msg + '\n') % headless)
2715
2715
2716 if not heads:
2716 if not heads:
2717 return 1
2717 return 1
2718
2718
2719 heads = sorted(heads, key=lambda x: -x.rev())
2719 heads = sorted(heads, key=lambda x: -x.rev())
2720 displayer = cmdutil.show_changeset(ui, repo, opts)
2720 displayer = cmdutil.show_changeset(ui, repo, opts)
2721 for ctx in heads:
2721 for ctx in heads:
2722 displayer.show(ctx)
2722 displayer.show(ctx)
2723 displayer.close()
2723 displayer.close()
2724
2724
2725 @command('help',
2725 @command('help',
2726 [('e', 'extension', None, _('show only help for extensions')),
2726 [('e', 'extension', None, _('show only help for extensions')),
2727 ('c', 'command', None, _('show only help for commands'))],
2727 ('c', 'command', None, _('show only help for commands'))],
2728 _('[-ec] [TOPIC]'))
2728 _('[-ec] [TOPIC]'))
2729 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2729 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2730 """show help for a given topic or a help overview
2730 """show help for a given topic or a help overview
2731
2731
2732 With no arguments, print a list of commands with short help messages.
2732 With no arguments, print a list of commands with short help messages.
2733
2733
2734 Given a topic, extension, or command name, print help for that
2734 Given a topic, extension, or command name, print help for that
2735 topic.
2735 topic.
2736
2736
2737 Returns 0 if successful.
2737 Returns 0 if successful.
2738 """
2738 """
2739
2739
2740 textwidth = min(ui.termwidth(), 80) - 2
2740 textwidth = min(ui.termwidth(), 80) - 2
2741
2741
2742 def optrst(options):
2742 def optrst(options):
2743 data = []
2743 data = []
2744 multioccur = False
2744 multioccur = False
2745 for option in options:
2745 for option in options:
2746 if len(option) == 5:
2746 if len(option) == 5:
2747 shortopt, longopt, default, desc, optlabel = option
2747 shortopt, longopt, default, desc, optlabel = option
2748 else:
2748 else:
2749 shortopt, longopt, default, desc = option
2749 shortopt, longopt, default, desc = option
2750 optlabel = _("VALUE") # default label
2750 optlabel = _("VALUE") # default label
2751
2751
2752 if _("DEPRECATED") in desc and not ui.verbose:
2752 if _("DEPRECATED") in desc and not ui.verbose:
2753 continue
2753 continue
2754
2754
2755 so = ''
2755 so = ''
2756 if shortopt:
2756 if shortopt:
2757 so = '-' + shortopt
2757 so = '-' + shortopt
2758 lo = '--' + longopt
2758 lo = '--' + longopt
2759 if default:
2759 if default:
2760 desc += _(" (default: %s)") % default
2760 desc += _(" (default: %s)") % default
2761
2761
2762 if isinstance(default, list):
2762 if isinstance(default, list):
2763 lo += " %s [+]" % optlabel
2763 lo += " %s [+]" % optlabel
2764 multioccur = True
2764 multioccur = True
2765 elif (default is not None) and not isinstance(default, bool):
2765 elif (default is not None) and not isinstance(default, bool):
2766 lo += " %s" % optlabel
2766 lo += " %s" % optlabel
2767
2767
2768 data.append((so, lo, desc))
2768 data.append((so, lo, desc))
2769
2769
2770 rst = minirst.maketable(data, 1)
2770 rst = minirst.maketable(data, 1)
2771
2771
2772 if multioccur:
2772 if multioccur:
2773 rst += _("\n[+] marked option can be specified multiple times")
2773 rst += _("\n[+] marked option can be specified multiple times")
2774
2774
2775 return rst
2775 return rst
2776
2776
2777 # list all option lists
2777 # list all option lists
2778 def opttext(optlist, width):
2778 def opttext(optlist, width):
2779 rst = ''
2779 rst = ''
2780 if not optlist:
2780 if not optlist:
2781 return ''
2781 return ''
2782
2782
2783 for title, options in optlist:
2783 for title, options in optlist:
2784 rst += '\n%s\n\n' % title
2784 rst += '\n%s\n\n' % title
2785 rst += optrst(options)
2785 rst += optrst(options)
2786 rst += '\n'
2786 rst += '\n'
2787
2787
2788 return '\n' + minirst.format(rst, width)
2788 return '\n' + minirst.format(rst, width)
2789
2789
2790 def addglobalopts(optlist, aliases):
2790 def addglobalopts(optlist, aliases):
2791 if ui.quiet:
2791 if ui.quiet:
2792 return []
2792 return []
2793
2793
2794 if ui.verbose:
2794 if ui.verbose:
2795 optlist.append((_("global options:"), globalopts))
2795 optlist.append((_("global options:"), globalopts))
2796 if name == 'shortlist':
2796 if name == 'shortlist':
2797 optlist.append((_('use "hg help" for the full list '
2797 optlist.append((_('use "hg help" for the full list '
2798 'of commands'), ()))
2798 'of commands'), ()))
2799 else:
2799 else:
2800 if name == 'shortlist':
2800 if name == 'shortlist':
2801 msg = _('use "hg help" for the full list of commands '
2801 msg = _('use "hg help" for the full list of commands '
2802 'or "hg -v" for details')
2802 'or "hg -v" for details')
2803 elif name and not full:
2803 elif name and not full:
2804 msg = _('use "hg help %s" to show the full help text' % name)
2804 msg = _('use "hg help %s" to show the full help text' % name)
2805 elif aliases:
2805 elif aliases:
2806 msg = _('use "hg -v help%s" to show builtin aliases and '
2806 msg = _('use "hg -v help%s" to show builtin aliases and '
2807 'global options') % (name and " " + name or "")
2807 'global options') % (name and " " + name or "")
2808 else:
2808 else:
2809 msg = _('use "hg -v help %s" to show global options') % name
2809 msg = _('use "hg -v help %s" to show global options') % name
2810 optlist.append((msg, ()))
2810 optlist.append((msg, ()))
2811
2811
2812 def helpcmd(name):
2812 def helpcmd(name):
2813 optlist = []
2813 optlist = []
2814 try:
2814 try:
2815 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2815 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2816 except error.AmbiguousCommand, inst:
2816 except error.AmbiguousCommand, inst:
2817 # py3k fix: except vars can't be used outside the scope of the
2817 # py3k fix: except vars can't be used outside the scope of the
2818 # except block, nor can be used inside a lambda. python issue4617
2818 # except block, nor can be used inside a lambda. python issue4617
2819 prefix = inst.args[0]
2819 prefix = inst.args[0]
2820 select = lambda c: c.lstrip('^').startswith(prefix)
2820 select = lambda c: c.lstrip('^').startswith(prefix)
2821 helplist(select)
2821 helplist(select)
2822 return
2822 return
2823
2823
2824 # check if it's an invalid alias and display its error if it is
2824 # check if it's an invalid alias and display its error if it is
2825 if getattr(entry[0], 'badalias', False):
2825 if getattr(entry[0], 'badalias', False):
2826 if not unknowncmd:
2826 if not unknowncmd:
2827 entry[0](ui)
2827 entry[0](ui)
2828 return
2828 return
2829
2829
2830 # synopsis
2830 # synopsis
2831 if len(entry) > 2:
2831 if len(entry) > 2:
2832 if entry[2].startswith('hg'):
2832 if entry[2].startswith('hg'):
2833 ui.write("%s\n" % entry[2])
2833 ui.write("%s\n" % entry[2])
2834 else:
2834 else:
2835 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2835 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2836 else:
2836 else:
2837 ui.write('hg %s\n' % aliases[0])
2837 ui.write('hg %s\n' % aliases[0])
2838
2838
2839 # aliases
2839 # aliases
2840 if full and not ui.quiet and len(aliases) > 1:
2840 if full and not ui.quiet and len(aliases) > 1:
2841 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2841 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2842
2842
2843 # description
2843 # description
2844 doc = gettext(entry[0].__doc__)
2844 doc = gettext(entry[0].__doc__)
2845 if not doc:
2845 if not doc:
2846 doc = _("(no help text available)")
2846 doc = _("(no help text available)")
2847 if util.safehasattr(entry[0], 'definition'): # aliased command
2847 if util.safehasattr(entry[0], 'definition'): # aliased command
2848 if entry[0].definition.startswith('!'): # shell alias
2848 if entry[0].definition.startswith('!'): # shell alias
2849 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2849 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2850 else:
2850 else:
2851 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2851 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2852 if ui.quiet or not full:
2852 if ui.quiet or not full:
2853 doc = doc.splitlines()[0]
2853 doc = doc.splitlines()[0]
2854 keep = ui.verbose and ['verbose'] or []
2854 keep = ui.verbose and ['verbose'] or []
2855 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2855 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2856 ui.write("\n%s" % formatted)
2856 ui.write("\n%s" % formatted)
2857 if pruned:
2857 if pruned:
2858 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2858 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2859
2859
2860 if not ui.quiet:
2860 if not ui.quiet:
2861 # options
2861 # options
2862 if entry[1]:
2862 if entry[1]:
2863 optlist.append((_("options:\n"), entry[1]))
2863 optlist.append((_("options:\n"), entry[1]))
2864
2864
2865 # check if this command shadows a non-trivial (multi-line)
2865 # check if this command shadows a non-trivial (multi-line)
2866 # extension help text
2866 # extension help text
2867 try:
2867 try:
2868 mod = extensions.find(name)
2868 mod = extensions.find(name)
2869 doc = gettext(mod.__doc__) or ''
2869 doc = gettext(mod.__doc__) or ''
2870 if '\n' in doc.strip():
2870 if '\n' in doc.strip():
2871 msg = _('use "hg help -e %s" to show help for '
2871 msg = _('use "hg help -e %s" to show help for '
2872 'the %s extension') % (name, name)
2872 'the %s extension') % (name, name)
2873 ui.write('\n%s\n' % msg)
2873 ui.write('\n%s\n' % msg)
2874 except KeyError:
2874 except KeyError:
2875 pass
2875 pass
2876
2876
2877 addglobalopts(optlist, False)
2877 addglobalopts(optlist, False)
2878 ui.write(opttext(optlist, textwidth))
2878 ui.write(opttext(optlist, textwidth))
2879
2879
2880 def helplist(select=None):
2880 def helplist(select=None):
2881 # list of commands
2881 # list of commands
2882 if name == "shortlist":
2882 if name == "shortlist":
2883 header = _('basic commands:\n\n')
2883 header = _('basic commands:\n\n')
2884 else:
2884 else:
2885 header = _('list of commands:\n\n')
2885 header = _('list of commands:\n\n')
2886
2886
2887 h = {}
2887 h = {}
2888 cmds = {}
2888 cmds = {}
2889 for c, e in table.iteritems():
2889 for c, e in table.iteritems():
2890 f = c.split("|", 1)[0]
2890 f = c.split("|", 1)[0]
2891 if select and not select(f):
2891 if select and not select(f):
2892 continue
2892 continue
2893 if (not select and name != 'shortlist' and
2893 if (not select and name != 'shortlist' and
2894 e[0].__module__ != __name__):
2894 e[0].__module__ != __name__):
2895 continue
2895 continue
2896 if name == "shortlist" and not f.startswith("^"):
2896 if name == "shortlist" and not f.startswith("^"):
2897 continue
2897 continue
2898 f = f.lstrip("^")
2898 f = f.lstrip("^")
2899 if not ui.debugflag and f.startswith("debug"):
2899 if not ui.debugflag and f.startswith("debug"):
2900 continue
2900 continue
2901 doc = e[0].__doc__
2901 doc = e[0].__doc__
2902 if doc and 'DEPRECATED' in doc and not ui.verbose:
2902 if doc and 'DEPRECATED' in doc and not ui.verbose:
2903 continue
2903 continue
2904 doc = gettext(doc)
2904 doc = gettext(doc)
2905 if not doc:
2905 if not doc:
2906 doc = _("(no help text available)")
2906 doc = _("(no help text available)")
2907 h[f] = doc.splitlines()[0].rstrip()
2907 h[f] = doc.splitlines()[0].rstrip()
2908 cmds[f] = c.lstrip("^")
2908 cmds[f] = c.lstrip("^")
2909
2909
2910 if not h:
2910 if not h:
2911 ui.status(_('no commands defined\n'))
2911 ui.status(_('no commands defined\n'))
2912 return
2912 return
2913
2913
2914 ui.status(header)
2914 ui.status(header)
2915 fns = sorted(h)
2915 fns = sorted(h)
2916 m = max(map(len, fns))
2916 m = max(map(len, fns))
2917 for f in fns:
2917 for f in fns:
2918 if ui.verbose:
2918 if ui.verbose:
2919 commands = cmds[f].replace("|",", ")
2919 commands = cmds[f].replace("|",", ")
2920 ui.write(" %s:\n %s\n"%(commands, h[f]))
2920 ui.write(" %s:\n %s\n"%(commands, h[f]))
2921 else:
2921 else:
2922 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2922 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2923 initindent=' %-*s ' % (m, f),
2923 initindent=' %-*s ' % (m, f),
2924 hangindent=' ' * (m + 4))))
2924 hangindent=' ' * (m + 4))))
2925
2925
2926 if not name:
2926 if not name:
2927 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2927 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2928 if text:
2928 if text:
2929 ui.write("\n%s" % minirst.format(text, textwidth))
2929 ui.write("\n%s" % minirst.format(text, textwidth))
2930
2930
2931 ui.write(_("\nadditional help topics:\n\n"))
2931 ui.write(_("\nadditional help topics:\n\n"))
2932 topics = []
2932 topics = []
2933 for names, header, doc in help.helptable:
2933 for names, header, doc in help.helptable:
2934 topics.append((sorted(names, key=len, reverse=True)[0], header))
2934 topics.append((sorted(names, key=len, reverse=True)[0], header))
2935 topics_len = max([len(s[0]) for s in topics])
2935 topics_len = max([len(s[0]) for s in topics])
2936 for t, desc in topics:
2936 for t, desc in topics:
2937 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2937 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2938
2938
2939 optlist = []
2939 optlist = []
2940 addglobalopts(optlist, True)
2940 addglobalopts(optlist, True)
2941 ui.write(opttext(optlist, textwidth))
2941 ui.write(opttext(optlist, textwidth))
2942
2942
2943 def helptopic(name):
2943 def helptopic(name):
2944 for names, header, doc in help.helptable:
2944 for names, header, doc in help.helptable:
2945 if name in names:
2945 if name in names:
2946 break
2946 break
2947 else:
2947 else:
2948 raise error.UnknownCommand(name)
2948 raise error.UnknownCommand(name)
2949
2949
2950 # description
2950 # description
2951 if not doc:
2951 if not doc:
2952 doc = _("(no help text available)")
2952 doc = _("(no help text available)")
2953 if util.safehasattr(doc, '__call__'):
2953 if util.safehasattr(doc, '__call__'):
2954 doc = doc()
2954 doc = doc()
2955
2955
2956 ui.write("%s\n\n" % header)
2956 ui.write("%s\n\n" % header)
2957 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2957 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2958 try:
2958 try:
2959 cmdutil.findcmd(name, table)
2959 cmdutil.findcmd(name, table)
2960 ui.write(_('\nuse "hg help -c %s" to see help for '
2960 ui.write(_('\nuse "hg help -c %s" to see help for '
2961 'the %s command\n') % (name, name))
2961 'the %s command\n') % (name, name))
2962 except error.UnknownCommand:
2962 except error.UnknownCommand:
2963 pass
2963 pass
2964
2964
2965 def helpext(name):
2965 def helpext(name):
2966 try:
2966 try:
2967 mod = extensions.find(name)
2967 mod = extensions.find(name)
2968 doc = gettext(mod.__doc__) or _('no help text available')
2968 doc = gettext(mod.__doc__) or _('no help text available')
2969 except KeyError:
2969 except KeyError:
2970 mod = None
2970 mod = None
2971 doc = extensions.disabledext(name)
2971 doc = extensions.disabledext(name)
2972 if not doc:
2972 if not doc:
2973 raise error.UnknownCommand(name)
2973 raise error.UnknownCommand(name)
2974
2974
2975 if '\n' not in doc:
2975 if '\n' not in doc:
2976 head, tail = doc, ""
2976 head, tail = doc, ""
2977 else:
2977 else:
2978 head, tail = doc.split('\n', 1)
2978 head, tail = doc.split('\n', 1)
2979 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2979 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2980 if tail:
2980 if tail:
2981 ui.write(minirst.format(tail, textwidth))
2981 ui.write(minirst.format(tail, textwidth))
2982 ui.status('\n')
2982 ui.status('\n')
2983
2983
2984 if mod:
2984 if mod:
2985 try:
2985 try:
2986 ct = mod.cmdtable
2986 ct = mod.cmdtable
2987 except AttributeError:
2987 except AttributeError:
2988 ct = {}
2988 ct = {}
2989 modcmds = set([c.split('|', 1)[0] for c in ct])
2989 modcmds = set([c.split('|', 1)[0] for c in ct])
2990 helplist(modcmds.__contains__)
2990 helplist(modcmds.__contains__)
2991 else:
2991 else:
2992 ui.write(_('use "hg help extensions" for information on enabling '
2992 ui.write(_('use "hg help extensions" for information on enabling '
2993 'extensions\n'))
2993 'extensions\n'))
2994
2994
2995 def helpextcmd(name):
2995 def helpextcmd(name):
2996 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2996 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2997 doc = gettext(mod.__doc__).splitlines()[0]
2997 doc = gettext(mod.__doc__).splitlines()[0]
2998
2998
2999 msg = help.listexts(_("'%s' is provided by the following "
2999 msg = help.listexts(_("'%s' is provided by the following "
3000 "extension:") % cmd, {ext: doc}, indent=4)
3000 "extension:") % cmd, {ext: doc}, indent=4)
3001 ui.write(minirst.format(msg, textwidth))
3001 ui.write(minirst.format(msg, textwidth))
3002 ui.write('\n')
3002 ui.write('\n')
3003 ui.write(_('use "hg help extensions" for information on enabling '
3003 ui.write(_('use "hg help extensions" for information on enabling '
3004 'extensions\n'))
3004 'extensions\n'))
3005
3005
3006 if name and name != 'shortlist':
3006 if name and name != 'shortlist':
3007 i = None
3007 i = None
3008 if unknowncmd:
3008 if unknowncmd:
3009 queries = (helpextcmd,)
3009 queries = (helpextcmd,)
3010 elif opts.get('extension'):
3010 elif opts.get('extension'):
3011 queries = (helpext,)
3011 queries = (helpext,)
3012 elif opts.get('command'):
3012 elif opts.get('command'):
3013 queries = (helpcmd,)
3013 queries = (helpcmd,)
3014 else:
3014 else:
3015 queries = (helptopic, helpcmd, helpext, helpextcmd)
3015 queries = (helptopic, helpcmd, helpext, helpextcmd)
3016 for f in queries:
3016 for f in queries:
3017 try:
3017 try:
3018 f(name)
3018 f(name)
3019 i = None
3019 i = None
3020 break
3020 break
3021 except error.UnknownCommand, inst:
3021 except error.UnknownCommand, inst:
3022 i = inst
3022 i = inst
3023 if i:
3023 if i:
3024 raise i
3024 raise i
3025 else:
3025 else:
3026 # program name
3026 # program name
3027 ui.status(_("Mercurial Distributed SCM\n"))
3027 ui.status(_("Mercurial Distributed SCM\n"))
3028 ui.status('\n')
3028 ui.status('\n')
3029 helplist()
3029 helplist()
3030
3030
3031
3031
3032 @command('identify|id',
3032 @command('identify|id',
3033 [('r', 'rev', '',
3033 [('r', 'rev', '',
3034 _('identify the specified revision'), _('REV')),
3034 _('identify the specified revision'), _('REV')),
3035 ('n', 'num', None, _('show local revision number')),
3035 ('n', 'num', None, _('show local revision number')),
3036 ('i', 'id', None, _('show global revision id')),
3036 ('i', 'id', None, _('show global revision id')),
3037 ('b', 'branch', None, _('show branch')),
3037 ('b', 'branch', None, _('show branch')),
3038 ('t', 'tags', None, _('show tags')),
3038 ('t', 'tags', None, _('show tags')),
3039 ('B', 'bookmarks', None, _('show bookmarks'))],
3039 ('B', 'bookmarks', None, _('show bookmarks'))],
3040 _('[-nibtB] [-r REV] [SOURCE]'))
3040 _('[-nibtB] [-r REV] [SOURCE]'))
3041 def identify(ui, repo, source=None, rev=None,
3041 def identify(ui, repo, source=None, rev=None,
3042 num=None, id=None, branch=None, tags=None, bookmarks=None):
3042 num=None, id=None, branch=None, tags=None, bookmarks=None):
3043 """identify the working copy or specified revision
3043 """identify the working copy or specified revision
3044
3044
3045 Print a summary identifying the repository state at REV using one or
3045 Print a summary identifying the repository state at REV using one or
3046 two parent hash identifiers, followed by a "+" if the working
3046 two parent hash identifiers, followed by a "+" if the working
3047 directory has uncommitted changes, the branch name (if not default),
3047 directory has uncommitted changes, the branch name (if not default),
3048 a list of tags, and a list of bookmarks.
3048 a list of tags, and a list of bookmarks.
3049
3049
3050 When REV is not given, print a summary of the current state of the
3050 When REV is not given, print a summary of the current state of the
3051 repository.
3051 repository.
3052
3052
3053 Specifying a path to a repository root or Mercurial bundle will
3053 Specifying a path to a repository root or Mercurial bundle will
3054 cause lookup to operate on that repository/bundle.
3054 cause lookup to operate on that repository/bundle.
3055
3055
3056 .. container:: verbose
3056 .. container:: verbose
3057
3057
3058 Examples:
3058 Examples:
3059
3059
3060 - generate a build identifier for the working directory::
3060 - generate a build identifier for the working directory::
3061
3061
3062 hg id --id > build-id.dat
3062 hg id --id > build-id.dat
3063
3063
3064 - find the revision corresponding to a tag::
3064 - find the revision corresponding to a tag::
3065
3065
3066 hg id -n -r 1.3
3066 hg id -n -r 1.3
3067
3067
3068 - check the most recent revision of a remote repository::
3068 - check the most recent revision of a remote repository::
3069
3069
3070 hg id -r tip http://selenic.com/hg/
3070 hg id -r tip http://selenic.com/hg/
3071
3071
3072 Returns 0 if successful.
3072 Returns 0 if successful.
3073 """
3073 """
3074
3074
3075 if not repo and not source:
3075 if not repo and not source:
3076 raise util.Abort(_("there is no Mercurial repository here "
3076 raise util.Abort(_("there is no Mercurial repository here "
3077 "(.hg not found)"))
3077 "(.hg not found)"))
3078
3078
3079 hexfunc = ui.debugflag and hex or short
3079 hexfunc = ui.debugflag and hex or short
3080 default = not (num or id or branch or tags or bookmarks)
3080 default = not (num or id or branch or tags or bookmarks)
3081 output = []
3081 output = []
3082 revs = []
3082 revs = []
3083
3083
3084 if source:
3084 if source:
3085 source, branches = hg.parseurl(ui.expandpath(source))
3085 source, branches = hg.parseurl(ui.expandpath(source))
3086 repo = hg.peer(ui, {}, source)
3086 repo = hg.peer(ui, {}, source)
3087 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3087 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3088
3088
3089 if not repo.local():
3089 if not repo.local():
3090 if num or branch or tags:
3090 if num or branch or tags:
3091 raise util.Abort(
3091 raise util.Abort(
3092 _("can't query remote revision number, branch, or tags"))
3092 _("can't query remote revision number, branch, or tags"))
3093 if not rev and revs:
3093 if not rev and revs:
3094 rev = revs[0]
3094 rev = revs[0]
3095 if not rev:
3095 if not rev:
3096 rev = "tip"
3096 rev = "tip"
3097
3097
3098 remoterev = repo.lookup(rev)
3098 remoterev = repo.lookup(rev)
3099 if default or id:
3099 if default or id:
3100 output = [hexfunc(remoterev)]
3100 output = [hexfunc(remoterev)]
3101
3101
3102 def getbms():
3102 def getbms():
3103 bms = []
3103 bms = []
3104
3104
3105 if 'bookmarks' in repo.listkeys('namespaces'):
3105 if 'bookmarks' in repo.listkeys('namespaces'):
3106 hexremoterev = hex(remoterev)
3106 hexremoterev = hex(remoterev)
3107 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3107 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3108 if bmr == hexremoterev]
3108 if bmr == hexremoterev]
3109
3109
3110 return bms
3110 return bms
3111
3111
3112 if bookmarks:
3112 if bookmarks:
3113 output.extend(getbms())
3113 output.extend(getbms())
3114 elif default and not ui.quiet:
3114 elif default and not ui.quiet:
3115 # multiple bookmarks for a single parent separated by '/'
3115 # multiple bookmarks for a single parent separated by '/'
3116 bm = '/'.join(getbms())
3116 bm = '/'.join(getbms())
3117 if bm:
3117 if bm:
3118 output.append(bm)
3118 output.append(bm)
3119 else:
3119 else:
3120 if not rev:
3120 if not rev:
3121 ctx = repo[None]
3121 ctx = repo[None]
3122 parents = ctx.parents()
3122 parents = ctx.parents()
3123 changed = ""
3123 changed = ""
3124 if default or id or num:
3124 if default or id or num:
3125 changed = util.any(repo.status()) and "+" or ""
3125 changed = util.any(repo.status()) and "+" or ""
3126 if default or id:
3126 if default or id:
3127 output = ["%s%s" %
3127 output = ["%s%s" %
3128 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3128 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3129 if num:
3129 if num:
3130 output.append("%s%s" %
3130 output.append("%s%s" %
3131 ('+'.join([str(p.rev()) for p in parents]), changed))
3131 ('+'.join([str(p.rev()) for p in parents]), changed))
3132 else:
3132 else:
3133 ctx = scmutil.revsingle(repo, rev)
3133 ctx = scmutil.revsingle(repo, rev)
3134 if default or id:
3134 if default or id:
3135 output = [hexfunc(ctx.node())]
3135 output = [hexfunc(ctx.node())]
3136 if num:
3136 if num:
3137 output.append(str(ctx.rev()))
3137 output.append(str(ctx.rev()))
3138
3138
3139 if default and not ui.quiet:
3139 if default and not ui.quiet:
3140 b = ctx.branch()
3140 b = ctx.branch()
3141 if b != 'default':
3141 if b != 'default':
3142 output.append("(%s)" % b)
3142 output.append("(%s)" % b)
3143
3143
3144 # multiple tags for a single parent separated by '/'
3144 # multiple tags for a single parent separated by '/'
3145 t = '/'.join(ctx.tags())
3145 t = '/'.join(ctx.tags())
3146 if t:
3146 if t:
3147 output.append(t)
3147 output.append(t)
3148
3148
3149 # multiple bookmarks for a single parent separated by '/'
3149 # multiple bookmarks for a single parent separated by '/'
3150 bm = '/'.join(ctx.bookmarks())
3150 bm = '/'.join(ctx.bookmarks())
3151 if bm:
3151 if bm:
3152 output.append(bm)
3152 output.append(bm)
3153 else:
3153 else:
3154 if branch:
3154 if branch:
3155 output.append(ctx.branch())
3155 output.append(ctx.branch())
3156
3156
3157 if tags:
3157 if tags:
3158 output.extend(ctx.tags())
3158 output.extend(ctx.tags())
3159
3159
3160 if bookmarks:
3160 if bookmarks:
3161 output.extend(ctx.bookmarks())
3161 output.extend(ctx.bookmarks())
3162
3162
3163 ui.write("%s\n" % ' '.join(output))
3163 ui.write("%s\n" % ' '.join(output))
3164
3164
3165 @command('import|patch',
3165 @command('import|patch',
3166 [('p', 'strip', 1,
3166 [('p', 'strip', 1,
3167 _('directory strip option for patch. This has the same '
3167 _('directory strip option for patch. This has the same '
3168 'meaning as the corresponding patch option'), _('NUM')),
3168 'meaning as the corresponding patch option'), _('NUM')),
3169 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3169 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3170 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3170 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3171 ('', 'no-commit', None,
3171 ('', 'no-commit', None,
3172 _("don't commit, just update the working directory")),
3172 _("don't commit, just update the working directory")),
3173 ('', 'bypass', None,
3173 ('', 'bypass', None,
3174 _("apply patch without touching the working directory")),
3174 _("apply patch without touching the working directory")),
3175 ('', 'exact', None,
3175 ('', 'exact', None,
3176 _('apply patch to the nodes from which it was generated')),
3176 _('apply patch to the nodes from which it was generated')),
3177 ('', 'import-branch', None,
3177 ('', 'import-branch', None,
3178 _('use any branch information in patch (implied by --exact)'))] +
3178 _('use any branch information in patch (implied by --exact)'))] +
3179 commitopts + commitopts2 + similarityopts,
3179 commitopts + commitopts2 + similarityopts,
3180 _('[OPTION]... PATCH...'))
3180 _('[OPTION]... PATCH...'))
3181 def import_(ui, repo, patch1, *patches, **opts):
3181 def import_(ui, repo, patch1, *patches, **opts):
3182 """import an ordered set of patches
3182 """import an ordered set of patches
3183
3183
3184 Import a list of patches and commit them individually (unless
3184 Import a list of patches and commit them individually (unless
3185 --no-commit is specified).
3185 --no-commit is specified).
3186
3186
3187 If there are outstanding changes in the working directory, import
3187 If there are outstanding changes in the working directory, import
3188 will abort unless given the -f/--force flag.
3188 will abort unless given the -f/--force flag.
3189
3189
3190 You can import a patch straight from a mail message. Even patches
3190 You can import a patch straight from a mail message. Even patches
3191 as attachments work (to use the body part, it must have type
3191 as attachments work (to use the body part, it must have type
3192 text/plain or text/x-patch). From and Subject headers of email
3192 text/plain or text/x-patch). From and Subject headers of email
3193 message are used as default committer and commit message. All
3193 message are used as default committer and commit message. All
3194 text/plain body parts before first diff are added to commit
3194 text/plain body parts before first diff are added to commit
3195 message.
3195 message.
3196
3196
3197 If the imported patch was generated by :hg:`export`, user and
3197 If the imported patch was generated by :hg:`export`, user and
3198 description from patch override values from message headers and
3198 description from patch override values from message headers and
3199 body. Values given on command line with -m/--message and -u/--user
3199 body. Values given on command line with -m/--message and -u/--user
3200 override these.
3200 override these.
3201
3201
3202 If --exact is specified, import will set the working directory to
3202 If --exact is specified, import will set the working directory to
3203 the parent of each patch before applying it, and will abort if the
3203 the parent of each patch before applying it, and will abort if the
3204 resulting changeset has a different ID than the one recorded in
3204 resulting changeset has a different ID than the one recorded in
3205 the patch. This may happen due to character set problems or other
3205 the patch. This may happen due to character set problems or other
3206 deficiencies in the text patch format.
3206 deficiencies in the text patch format.
3207
3207
3208 Use --bypass to apply and commit patches directly to the
3208 Use --bypass to apply and commit patches directly to the
3209 repository, not touching the working directory. Without --exact,
3209 repository, not touching the working directory. Without --exact,
3210 patches will be applied on top of the working directory parent
3210 patches will be applied on top of the working directory parent
3211 revision.
3211 revision.
3212
3212
3213 With -s/--similarity, hg will attempt to discover renames and
3213 With -s/--similarity, hg will attempt to discover renames and
3214 copies in the patch in the same way as 'addremove'.
3214 copies in the patch in the same way as 'addremove'.
3215
3215
3216 To read a patch from standard input, use "-" as the patch name. If
3216 To read a patch from standard input, use "-" as the patch name. If
3217 a URL is specified, the patch will be downloaded from it.
3217 a URL is specified, the patch will be downloaded from it.
3218 See :hg:`help dates` for a list of formats valid for -d/--date.
3218 See :hg:`help dates` for a list of formats valid for -d/--date.
3219
3219
3220 .. container:: verbose
3220 .. container:: verbose
3221
3221
3222 Examples:
3222 Examples:
3223
3223
3224 - import a traditional patch from a website and detect renames::
3224 - import a traditional patch from a website and detect renames::
3225
3225
3226 hg import -s 80 http://example.com/bugfix.patch
3226 hg import -s 80 http://example.com/bugfix.patch
3227
3227
3228 - import a changeset from an hgweb server::
3228 - import a changeset from an hgweb server::
3229
3229
3230 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3230 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3231
3231
3232 - import all the patches in an Unix-style mbox::
3232 - import all the patches in an Unix-style mbox::
3233
3233
3234 hg import incoming-patches.mbox
3234 hg import incoming-patches.mbox
3235
3235
3236 - attempt to exactly restore an exported changeset (not always
3236 - attempt to exactly restore an exported changeset (not always
3237 possible)::
3237 possible)::
3238
3238
3239 hg import --exact proposed-fix.patch
3239 hg import --exact proposed-fix.patch
3240
3240
3241 Returns 0 on success.
3241 Returns 0 on success.
3242 """
3242 """
3243 patches = (patch1,) + patches
3243 patches = (patch1,) + patches
3244
3244
3245 date = opts.get('date')
3245 date = opts.get('date')
3246 if date:
3246 if date:
3247 opts['date'] = util.parsedate(date)
3247 opts['date'] = util.parsedate(date)
3248
3248
3249 update = not opts.get('bypass')
3249 update = not opts.get('bypass')
3250 if not update and opts.get('no_commit'):
3250 if not update and opts.get('no_commit'):
3251 raise util.Abort(_('cannot use --no-commit with --bypass'))
3251 raise util.Abort(_('cannot use --no-commit with --bypass'))
3252 try:
3252 try:
3253 sim = float(opts.get('similarity') or 0)
3253 sim = float(opts.get('similarity') or 0)
3254 except ValueError:
3254 except ValueError:
3255 raise util.Abort(_('similarity must be a number'))
3255 raise util.Abort(_('similarity must be a number'))
3256 if sim < 0 or sim > 100:
3256 if sim < 0 or sim > 100:
3257 raise util.Abort(_('similarity must be between 0 and 100'))
3257 raise util.Abort(_('similarity must be between 0 and 100'))
3258 if sim and not update:
3258 if sim and not update:
3259 raise util.Abort(_('cannot use --similarity with --bypass'))
3259 raise util.Abort(_('cannot use --similarity with --bypass'))
3260
3260
3261 if (opts.get('exact') or not opts.get('force')) and update:
3261 if (opts.get('exact') or not opts.get('force')) and update:
3262 cmdutil.bailifchanged(repo)
3262 cmdutil.bailifchanged(repo)
3263
3263
3264 d = opts["base"]
3264 base = opts["base"]
3265 strip = opts["strip"]
3265 strip = opts["strip"]
3266 wlock = lock = None
3266 wlock = lock = None
3267 msgs = []
3267 msgs = []
3268
3268
3269 def checkexact(repo, n, nodeid):
3269 def checkexact(repo, n, nodeid):
3270 if opts.get('exact') and hex(n) != nodeid:
3270 if opts.get('exact') and hex(n) != nodeid:
3271 repo.rollback()
3271 repo.rollback()
3272 raise util.Abort(_('patch is damaged or loses information'))
3272 raise util.Abort(_('patch is damaged or loses information'))
3273
3273
3274 def tryone(ui, hunk, parents):
3274 def tryone(ui, hunk, parents):
3275 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3275 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3276 patch.extract(ui, hunk)
3276 patch.extract(ui, hunk)
3277
3277
3278 if not tmpname:
3278 if not tmpname:
3279 return (None, None)
3279 return (None, None)
3280 msg = _('applied to working directory')
3280 msg = _('applied to working directory')
3281
3281
3282 try:
3282 try:
3283 cmdline_message = cmdutil.logmessage(ui, opts)
3283 cmdline_message = cmdutil.logmessage(ui, opts)
3284 if cmdline_message:
3284 if cmdline_message:
3285 # pickup the cmdline msg
3285 # pickup the cmdline msg
3286 message = cmdline_message
3286 message = cmdline_message
3287 elif message:
3287 elif message:
3288 # pickup the patch msg
3288 # pickup the patch msg
3289 message = message.strip()
3289 message = message.strip()
3290 else:
3290 else:
3291 # launch the editor
3291 # launch the editor
3292 message = None
3292 message = None
3293 ui.debug('message:\n%s\n' % message)
3293 ui.debug('message:\n%s\n' % message)
3294
3294
3295 if len(parents) == 1:
3295 if len(parents) == 1:
3296 parents.append(repo[nullid])
3296 parents.append(repo[nullid])
3297 if opts.get('exact'):
3297 if opts.get('exact'):
3298 if not nodeid or not p1:
3298 if not nodeid or not p1:
3299 raise util.Abort(_('not a Mercurial patch'))
3299 raise util.Abort(_('not a Mercurial patch'))
3300 p1 = repo[p1]
3300 p1 = repo[p1]
3301 p2 = repo[p2 or nullid]
3301 p2 = repo[p2 or nullid]
3302 elif p2:
3302 elif p2:
3303 try:
3303 try:
3304 p1 = repo[p1]
3304 p1 = repo[p1]
3305 p2 = repo[p2]
3305 p2 = repo[p2]
3306 except error.RepoError:
3306 except error.RepoError:
3307 p1, p2 = parents
3307 p1, p2 = parents
3308 else:
3308 else:
3309 p1, p2 = parents
3309 p1, p2 = parents
3310
3310
3311 n = None
3311 n = None
3312 if update:
3312 if update:
3313 if opts.get('exact') and p1 != parents[0]:
3313 if opts.get('exact') and p1 != parents[0]:
3314 hg.clean(repo, p1.node())
3314 hg.clean(repo, p1.node())
3315 if p1 != parents[0] and p2 != parents[1]:
3315 if p1 != parents[0] and p2 != parents[1]:
3316 repo.dirstate.setparents(p1.node(), p2.node())
3316 repo.dirstate.setparents(p1.node(), p2.node())
3317
3317
3318 if opts.get('exact') or opts.get('import_branch'):
3318 if opts.get('exact') or opts.get('import_branch'):
3319 repo.dirstate.setbranch(branch or 'default')
3319 repo.dirstate.setbranch(branch or 'default')
3320
3320
3321 files = set()
3321 files = set()
3322 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3322 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3323 eolmode=None, similarity=sim / 100.0)
3323 eolmode=None, similarity=sim / 100.0)
3324 files = list(files)
3324 files = list(files)
3325 if opts.get('no_commit'):
3325 if opts.get('no_commit'):
3326 if message:
3326 if message:
3327 msgs.append(message)
3327 msgs.append(message)
3328 else:
3328 else:
3329 if opts.get('exact'):
3329 if opts.get('exact'):
3330 m = None
3330 m = None
3331 else:
3331 else:
3332 m = scmutil.matchfiles(repo, files or [])
3332 m = scmutil.matchfiles(repo, files or [])
3333 n = repo.commit(message, opts.get('user') or user,
3333 n = repo.commit(message, opts.get('user') or user,
3334 opts.get('date') or date, match=m,
3334 opts.get('date') or date, match=m,
3335 editor=cmdutil.commiteditor)
3335 editor=cmdutil.commiteditor)
3336 checkexact(repo, n, nodeid)
3336 checkexact(repo, n, nodeid)
3337 # Force a dirstate write so that the next transaction
3337 # Force a dirstate write so that the next transaction
3338 # backups an up-to-date file.
3338 # backups an up-to-date file.
3339 repo.dirstate.write()
3339 repo.dirstate.write()
3340 else:
3340 else:
3341 if opts.get('exact') or opts.get('import_branch'):
3341 if opts.get('exact') or opts.get('import_branch'):
3342 branch = branch or 'default'
3342 branch = branch or 'default'
3343 else:
3343 else:
3344 branch = p1.branch()
3344 branch = p1.branch()
3345 store = patch.filestore()
3345 store = patch.filestore()
3346 try:
3346 try:
3347 files = set()
3347 files = set()
3348 try:
3348 try:
3349 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3349 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3350 files, eolmode=None)
3350 files, eolmode=None)
3351 except patch.PatchError, e:
3351 except patch.PatchError, e:
3352 raise util.Abort(str(e))
3352 raise util.Abort(str(e))
3353 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3353 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3354 message,
3354 message,
3355 opts.get('user') or user,
3355 opts.get('user') or user,
3356 opts.get('date') or date,
3356 opts.get('date') or date,
3357 branch, files, store,
3357 branch, files, store,
3358 editor=cmdutil.commiteditor)
3358 editor=cmdutil.commiteditor)
3359 repo.savecommitmessage(memctx.description())
3359 repo.savecommitmessage(memctx.description())
3360 n = memctx.commit()
3360 n = memctx.commit()
3361 checkexact(repo, n, nodeid)
3361 checkexact(repo, n, nodeid)
3362 finally:
3362 finally:
3363 store.close()
3363 store.close()
3364 if n:
3364 if n:
3365 msg = _('created %s') % short(n)
3365 msg = _('created %s') % short(n)
3366 return (msg, n)
3366 return (msg, n)
3367 finally:
3367 finally:
3368 os.unlink(tmpname)
3368 os.unlink(tmpname)
3369
3369
3370 try:
3370 try:
3371 wlock = repo.wlock()
3371 wlock = repo.wlock()
3372 lock = repo.lock()
3372 lock = repo.lock()
3373 parents = repo.parents()
3373 parents = repo.parents()
3374 for p in patches:
3374 for patchurl in patches:
3375 pf = os.path.join(d, p)
3375 patchurl = os.path.join(base, patchurl)
3376
3376 if patchurl == '-':
3377 if pf == '-':
3377 ui.status(_('applying patch from stdin\n'))
3378 ui.status(_("applying patch from stdin\n"))
3378 patchfile = ui.fin
3379 pf = ui.fin
3380 else:
3379 else:
3381 ui.status(_("applying %s\n") % p)
3380 ui.status(_('applying %s\n') % patchurl)
3382 pf = url.open(ui, pf)
3381 patchfile = url.open(ui, patchurl)
3383
3382
3384 haspatch = False
3383 haspatch = False
3385 for hunk in patch.split(pf):
3384 for hunk in patch.split(patchfile):
3386 (msg, node) = tryone(ui, hunk, parents)
3385 (msg, node) = tryone(ui, hunk, parents)
3387 if msg:
3386 if msg:
3388 haspatch = True
3387 haspatch = True
3389 ui.note(msg + '\n')
3388 ui.note(msg + '\n')
3390 if update or opts.get('exact'):
3389 if update or opts.get('exact'):
3391 parents = repo.parents()
3390 parents = repo.parents()
3392 else:
3391 else:
3393 parents = [repo[node]]
3392 parents = [repo[node]]
3394
3393
3395 if not haspatch:
3394 if not haspatch:
3396 raise util.Abort(_('no diffs found'))
3395 raise util.Abort(_('no diffs found'))
3397
3396
3398 if msgs:
3397 if msgs:
3399 repo.savecommitmessage('\n* * *\n'.join(msgs))
3398 repo.savecommitmessage('\n* * *\n'.join(msgs))
3400 finally:
3399 finally:
3401 release(lock, wlock)
3400 release(lock, wlock)
3402
3401
3403 @command('incoming|in',
3402 @command('incoming|in',
3404 [('f', 'force', None,
3403 [('f', 'force', None,
3405 _('run even if remote repository is unrelated')),
3404 _('run even if remote repository is unrelated')),
3406 ('n', 'newest-first', None, _('show newest record first')),
3405 ('n', 'newest-first', None, _('show newest record first')),
3407 ('', 'bundle', '',
3406 ('', 'bundle', '',
3408 _('file to store the bundles into'), _('FILE')),
3407 _('file to store the bundles into'), _('FILE')),
3409 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3408 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3410 ('B', 'bookmarks', False, _("compare bookmarks")),
3409 ('B', 'bookmarks', False, _("compare bookmarks")),
3411 ('b', 'branch', [],
3410 ('b', 'branch', [],
3412 _('a specific branch you would like to pull'), _('BRANCH')),
3411 _('a specific branch you would like to pull'), _('BRANCH')),
3413 ] + logopts + remoteopts + subrepoopts,
3412 ] + logopts + remoteopts + subrepoopts,
3414 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3413 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3415 def incoming(ui, repo, source="default", **opts):
3414 def incoming(ui, repo, source="default", **opts):
3416 """show new changesets found in source
3415 """show new changesets found in source
3417
3416
3418 Show new changesets found in the specified path/URL or the default
3417 Show new changesets found in the specified path/URL or the default
3419 pull location. These are the changesets that would have been pulled
3418 pull location. These are the changesets that would have been pulled
3420 if a pull at the time you issued this command.
3419 if a pull at the time you issued this command.
3421
3420
3422 For remote repository, using --bundle avoids downloading the
3421 For remote repository, using --bundle avoids downloading the
3423 changesets twice if the incoming is followed by a pull.
3422 changesets twice if the incoming is followed by a pull.
3424
3423
3425 See pull for valid source format details.
3424 See pull for valid source format details.
3426
3425
3427 Returns 0 if there are incoming changes, 1 otherwise.
3426 Returns 0 if there are incoming changes, 1 otherwise.
3428 """
3427 """
3429 if opts.get('bundle') and opts.get('subrepos'):
3428 if opts.get('bundle') and opts.get('subrepos'):
3430 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3429 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3431
3430
3432 if opts.get('bookmarks'):
3431 if opts.get('bookmarks'):
3433 source, branches = hg.parseurl(ui.expandpath(source),
3432 source, branches = hg.parseurl(ui.expandpath(source),
3434 opts.get('branch'))
3433 opts.get('branch'))
3435 other = hg.peer(repo, opts, source)
3434 other = hg.peer(repo, opts, source)
3436 if 'bookmarks' not in other.listkeys('namespaces'):
3435 if 'bookmarks' not in other.listkeys('namespaces'):
3437 ui.warn(_("remote doesn't support bookmarks\n"))
3436 ui.warn(_("remote doesn't support bookmarks\n"))
3438 return 0
3437 return 0
3439 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3438 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3440 return bookmarks.diff(ui, repo, other)
3439 return bookmarks.diff(ui, repo, other)
3441
3440
3442 repo._subtoppath = ui.expandpath(source)
3441 repo._subtoppath = ui.expandpath(source)
3443 try:
3442 try:
3444 return hg.incoming(ui, repo, source, opts)
3443 return hg.incoming(ui, repo, source, opts)
3445 finally:
3444 finally:
3446 del repo._subtoppath
3445 del repo._subtoppath
3447
3446
3448
3447
3449 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3448 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3450 def init(ui, dest=".", **opts):
3449 def init(ui, dest=".", **opts):
3451 """create a new repository in the given directory
3450 """create a new repository in the given directory
3452
3451
3453 Initialize a new repository in the given directory. If the given
3452 Initialize a new repository in the given directory. If the given
3454 directory does not exist, it will be created.
3453 directory does not exist, it will be created.
3455
3454
3456 If no directory is given, the current directory is used.
3455 If no directory is given, the current directory is used.
3457
3456
3458 It is possible to specify an ``ssh://`` URL as the destination.
3457 It is possible to specify an ``ssh://`` URL as the destination.
3459 See :hg:`help urls` for more information.
3458 See :hg:`help urls` for more information.
3460
3459
3461 Returns 0 on success.
3460 Returns 0 on success.
3462 """
3461 """
3463 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3462 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3464
3463
3465 @command('locate',
3464 @command('locate',
3466 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3465 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3467 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3466 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3468 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3467 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3469 ] + walkopts,
3468 ] + walkopts,
3470 _('[OPTION]... [PATTERN]...'))
3469 _('[OPTION]... [PATTERN]...'))
3471 def locate(ui, repo, *pats, **opts):
3470 def locate(ui, repo, *pats, **opts):
3472 """locate files matching specific patterns
3471 """locate files matching specific patterns
3473
3472
3474 Print files under Mercurial control in the working directory whose
3473 Print files under Mercurial control in the working directory whose
3475 names match the given patterns.
3474 names match the given patterns.
3476
3475
3477 By default, this command searches all directories in the working
3476 By default, this command searches all directories in the working
3478 directory. To search just the current directory and its
3477 directory. To search just the current directory and its
3479 subdirectories, use "--include .".
3478 subdirectories, use "--include .".
3480
3479
3481 If no patterns are given to match, this command prints the names
3480 If no patterns are given to match, this command prints the names
3482 of all files under Mercurial control in the working directory.
3481 of all files under Mercurial control in the working directory.
3483
3482
3484 If you want to feed the output of this command into the "xargs"
3483 If you want to feed the output of this command into the "xargs"
3485 command, use the -0 option to both this command and "xargs". This
3484 command, use the -0 option to both this command and "xargs". This
3486 will avoid the problem of "xargs" treating single filenames that
3485 will avoid the problem of "xargs" treating single filenames that
3487 contain whitespace as multiple filenames.
3486 contain whitespace as multiple filenames.
3488
3487
3489 Returns 0 if a match is found, 1 otherwise.
3488 Returns 0 if a match is found, 1 otherwise.
3490 """
3489 """
3491 end = opts.get('print0') and '\0' or '\n'
3490 end = opts.get('print0') and '\0' or '\n'
3492 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3491 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3493
3492
3494 ret = 1
3493 ret = 1
3495 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3494 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3496 m.bad = lambda x, y: False
3495 m.bad = lambda x, y: False
3497 for abs in repo[rev].walk(m):
3496 for abs in repo[rev].walk(m):
3498 if not rev and abs not in repo.dirstate:
3497 if not rev and abs not in repo.dirstate:
3499 continue
3498 continue
3500 if opts.get('fullpath'):
3499 if opts.get('fullpath'):
3501 ui.write(repo.wjoin(abs), end)
3500 ui.write(repo.wjoin(abs), end)
3502 else:
3501 else:
3503 ui.write(((pats and m.rel(abs)) or abs), end)
3502 ui.write(((pats and m.rel(abs)) or abs), end)
3504 ret = 0
3503 ret = 0
3505
3504
3506 return ret
3505 return ret
3507
3506
3508 @command('^log|history',
3507 @command('^log|history',
3509 [('f', 'follow', None,
3508 [('f', 'follow', None,
3510 _('follow changeset history, or file history across copies and renames')),
3509 _('follow changeset history, or file history across copies and renames')),
3511 ('', 'follow-first', None,
3510 ('', 'follow-first', None,
3512 _('only follow the first parent of merge changesets')),
3511 _('only follow the first parent of merge changesets')),
3513 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3512 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3514 ('C', 'copies', None, _('show copied files')),
3513 ('C', 'copies', None, _('show copied files')),
3515 ('k', 'keyword', [],
3514 ('k', 'keyword', [],
3516 _('do case-insensitive search for a given text'), _('TEXT')),
3515 _('do case-insensitive search for a given text'), _('TEXT')),
3517 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3516 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3518 ('', 'removed', None, _('include revisions where files were removed')),
3517 ('', 'removed', None, _('include revisions where files were removed')),
3519 ('m', 'only-merges', None, _('show only merges')),
3518 ('m', 'only-merges', None, _('show only merges')),
3520 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3519 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3521 ('', 'only-branch', [],
3520 ('', 'only-branch', [],
3522 _('show only changesets within the given named branch (DEPRECATED)'),
3521 _('show only changesets within the given named branch (DEPRECATED)'),
3523 _('BRANCH')),
3522 _('BRANCH')),
3524 ('b', 'branch', [],
3523 ('b', 'branch', [],
3525 _('show changesets within the given named branch'), _('BRANCH')),
3524 _('show changesets within the given named branch'), _('BRANCH')),
3526 ('P', 'prune', [],
3525 ('P', 'prune', [],
3527 _('do not display revision or any of its ancestors'), _('REV')),
3526 _('do not display revision or any of its ancestors'), _('REV')),
3528 ('', 'hidden', False, _('show hidden changesets')),
3527 ('', 'hidden', False, _('show hidden changesets')),
3529 ] + logopts + walkopts,
3528 ] + logopts + walkopts,
3530 _('[OPTION]... [FILE]'))
3529 _('[OPTION]... [FILE]'))
3531 def log(ui, repo, *pats, **opts):
3530 def log(ui, repo, *pats, **opts):
3532 """show revision history of entire repository or files
3531 """show revision history of entire repository or files
3533
3532
3534 Print the revision history of the specified files or the entire
3533 Print the revision history of the specified files or the entire
3535 project.
3534 project.
3536
3535
3537 If no revision range is specified, the default is ``tip:0`` unless
3536 If no revision range is specified, the default is ``tip:0`` unless
3538 --follow is set, in which case the working directory parent is
3537 --follow is set, in which case the working directory parent is
3539 used as the starting revision.
3538 used as the starting revision.
3540
3539
3541 File history is shown without following rename or copy history of
3540 File history is shown without following rename or copy history of
3542 files. Use -f/--follow with a filename to follow history across
3541 files. Use -f/--follow with a filename to follow history across
3543 renames and copies. --follow without a filename will only show
3542 renames and copies. --follow without a filename will only show
3544 ancestors or descendants of the starting revision.
3543 ancestors or descendants of the starting revision.
3545
3544
3546 By default this command prints revision number and changeset id,
3545 By default this command prints revision number and changeset id,
3547 tags, non-trivial parents, user, date and time, and a summary for
3546 tags, non-trivial parents, user, date and time, and a summary for
3548 each commit. When the -v/--verbose switch is used, the list of
3547 each commit. When the -v/--verbose switch is used, the list of
3549 changed files and full commit message are shown.
3548 changed files and full commit message are shown.
3550
3549
3551 .. note::
3550 .. note::
3552 log -p/--patch may generate unexpected diff output for merge
3551 log -p/--patch may generate unexpected diff output for merge
3553 changesets, as it will only compare the merge changeset against
3552 changesets, as it will only compare the merge changeset against
3554 its first parent. Also, only files different from BOTH parents
3553 its first parent. Also, only files different from BOTH parents
3555 will appear in files:.
3554 will appear in files:.
3556
3555
3557 .. note::
3556 .. note::
3558 for performance reasons, log FILE may omit duplicate changes
3557 for performance reasons, log FILE may omit duplicate changes
3559 made on branches and will not show deletions. To see all
3558 made on branches and will not show deletions. To see all
3560 changes including duplicates and deletions, use the --removed
3559 changes including duplicates and deletions, use the --removed
3561 switch.
3560 switch.
3562
3561
3563 .. container:: verbose
3562 .. container:: verbose
3564
3563
3565 Some examples:
3564 Some examples:
3566
3565
3567 - changesets with full descriptions and file lists::
3566 - changesets with full descriptions and file lists::
3568
3567
3569 hg log -v
3568 hg log -v
3570
3569
3571 - changesets ancestral to the working directory::
3570 - changesets ancestral to the working directory::
3572
3571
3573 hg log -f
3572 hg log -f
3574
3573
3575 - last 10 commits on the current branch::
3574 - last 10 commits on the current branch::
3576
3575
3577 hg log -l 10 -b .
3576 hg log -l 10 -b .
3578
3577
3579 - changesets showing all modifications of a file, including removals::
3578 - changesets showing all modifications of a file, including removals::
3580
3579
3581 hg log --removed file.c
3580 hg log --removed file.c
3582
3581
3583 - all changesets that touch a directory, with diffs, excluding merges::
3582 - all changesets that touch a directory, with diffs, excluding merges::
3584
3583
3585 hg log -Mp lib/
3584 hg log -Mp lib/
3586
3585
3587 - all revision numbers that match a keyword::
3586 - all revision numbers that match a keyword::
3588
3587
3589 hg log -k bug --template "{rev}\\n"
3588 hg log -k bug --template "{rev}\\n"
3590
3589
3591 - check if a given changeset is included is a tagged release::
3590 - check if a given changeset is included is a tagged release::
3592
3591
3593 hg log -r "a21ccf and ancestor(1.9)"
3592 hg log -r "a21ccf and ancestor(1.9)"
3594
3593
3595 - find all changesets by some user in a date range::
3594 - find all changesets by some user in a date range::
3596
3595
3597 hg log -k alice -d "may 2008 to jul 2008"
3596 hg log -k alice -d "may 2008 to jul 2008"
3598
3597
3599 - summary of all changesets after the last tag::
3598 - summary of all changesets after the last tag::
3600
3599
3601 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3600 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3602
3601
3603 See :hg:`help dates` for a list of formats valid for -d/--date.
3602 See :hg:`help dates` for a list of formats valid for -d/--date.
3604
3603
3605 See :hg:`help revisions` and :hg:`help revsets` for more about
3604 See :hg:`help revisions` and :hg:`help revsets` for more about
3606 specifying revisions.
3605 specifying revisions.
3607
3606
3608 Returns 0 on success.
3607 Returns 0 on success.
3609 """
3608 """
3610
3609
3611 matchfn = scmutil.match(repo[None], pats, opts)
3610 matchfn = scmutil.match(repo[None], pats, opts)
3612 limit = cmdutil.loglimit(opts)
3611 limit = cmdutil.loglimit(opts)
3613 count = 0
3612 count = 0
3614
3613
3615 endrev = None
3614 endrev = None
3616 if opts.get('copies') and opts.get('rev'):
3615 if opts.get('copies') and opts.get('rev'):
3617 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3616 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3618
3617
3619 df = False
3618 df = False
3620 if opts["date"]:
3619 if opts["date"]:
3621 df = util.matchdate(opts["date"])
3620 df = util.matchdate(opts["date"])
3622
3621
3623 branches = opts.get('branch', []) + opts.get('only_branch', [])
3622 branches = opts.get('branch', []) + opts.get('only_branch', [])
3624 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3623 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3625
3624
3626 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3625 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3627 def prep(ctx, fns):
3626 def prep(ctx, fns):
3628 rev = ctx.rev()
3627 rev = ctx.rev()
3629 parents = [p for p in repo.changelog.parentrevs(rev)
3628 parents = [p for p in repo.changelog.parentrevs(rev)
3630 if p != nullrev]
3629 if p != nullrev]
3631 if opts.get('no_merges') and len(parents) == 2:
3630 if opts.get('no_merges') and len(parents) == 2:
3632 return
3631 return
3633 if opts.get('only_merges') and len(parents) != 2:
3632 if opts.get('only_merges') and len(parents) != 2:
3634 return
3633 return
3635 if opts.get('branch') and ctx.branch() not in opts['branch']:
3634 if opts.get('branch') and ctx.branch() not in opts['branch']:
3636 return
3635 return
3637 if not opts.get('hidden') and ctx.hidden():
3636 if not opts.get('hidden') and ctx.hidden():
3638 return
3637 return
3639 if df and not df(ctx.date()[0]):
3638 if df and not df(ctx.date()[0]):
3640 return
3639 return
3641 if opts['user'] and not [k for k in opts['user']
3640 if opts['user'] and not [k for k in opts['user']
3642 if k.lower() in ctx.user().lower()]:
3641 if k.lower() in ctx.user().lower()]:
3643 return
3642 return
3644 if opts.get('keyword'):
3643 if opts.get('keyword'):
3645 for k in [kw.lower() for kw in opts['keyword']]:
3644 for k in [kw.lower() for kw in opts['keyword']]:
3646 if (k in ctx.user().lower() or
3645 if (k in ctx.user().lower() or
3647 k in ctx.description().lower() or
3646 k in ctx.description().lower() or
3648 k in " ".join(ctx.files()).lower()):
3647 k in " ".join(ctx.files()).lower()):
3649 break
3648 break
3650 else:
3649 else:
3651 return
3650 return
3652
3651
3653 copies = None
3652 copies = None
3654 if opts.get('copies') and rev:
3653 if opts.get('copies') and rev:
3655 copies = []
3654 copies = []
3656 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3655 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3657 for fn in ctx.files():
3656 for fn in ctx.files():
3658 rename = getrenamed(fn, rev)
3657 rename = getrenamed(fn, rev)
3659 if rename:
3658 if rename:
3660 copies.append((fn, rename[0]))
3659 copies.append((fn, rename[0]))
3661
3660
3662 revmatchfn = None
3661 revmatchfn = None
3663 if opts.get('patch') or opts.get('stat'):
3662 if opts.get('patch') or opts.get('stat'):
3664 if opts.get('follow') or opts.get('follow_first'):
3663 if opts.get('follow') or opts.get('follow_first'):
3665 # note: this might be wrong when following through merges
3664 # note: this might be wrong when following through merges
3666 revmatchfn = scmutil.match(repo[None], fns, default='path')
3665 revmatchfn = scmutil.match(repo[None], fns, default='path')
3667 else:
3666 else:
3668 revmatchfn = matchfn
3667 revmatchfn = matchfn
3669
3668
3670 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3669 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3671
3670
3672 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3671 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3673 if count == limit:
3672 if count == limit:
3674 break
3673 break
3675 if displayer.flush(ctx.rev()):
3674 if displayer.flush(ctx.rev()):
3676 count += 1
3675 count += 1
3677 displayer.close()
3676 displayer.close()
3678
3677
3679 @command('manifest',
3678 @command('manifest',
3680 [('r', 'rev', '', _('revision to display'), _('REV')),
3679 [('r', 'rev', '', _('revision to display'), _('REV')),
3681 ('', 'all', False, _("list files from all revisions"))],
3680 ('', 'all', False, _("list files from all revisions"))],
3682 _('[-r REV]'))
3681 _('[-r REV]'))
3683 def manifest(ui, repo, node=None, rev=None, **opts):
3682 def manifest(ui, repo, node=None, rev=None, **opts):
3684 """output the current or given revision of the project manifest
3683 """output the current or given revision of the project manifest
3685
3684
3686 Print a list of version controlled files for the given revision.
3685 Print a list of version controlled files for the given revision.
3687 If no revision is given, the first parent of the working directory
3686 If no revision is given, the first parent of the working directory
3688 is used, or the null revision if no revision is checked out.
3687 is used, or the null revision if no revision is checked out.
3689
3688
3690 With -v, print file permissions, symlink and executable bits.
3689 With -v, print file permissions, symlink and executable bits.
3691 With --debug, print file revision hashes.
3690 With --debug, print file revision hashes.
3692
3691
3693 If option --all is specified, the list of all files from all revisions
3692 If option --all is specified, the list of all files from all revisions
3694 is printed. This includes deleted and renamed files.
3693 is printed. This includes deleted and renamed files.
3695
3694
3696 Returns 0 on success.
3695 Returns 0 on success.
3697 """
3696 """
3698 if opts.get('all'):
3697 if opts.get('all'):
3699 if rev or node:
3698 if rev or node:
3700 raise util.Abort(_("can't specify a revision with --all"))
3699 raise util.Abort(_("can't specify a revision with --all"))
3701
3700
3702 res = []
3701 res = []
3703 prefix = "data/"
3702 prefix = "data/"
3704 suffix = ".i"
3703 suffix = ".i"
3705 plen = len(prefix)
3704 plen = len(prefix)
3706 slen = len(suffix)
3705 slen = len(suffix)
3707 lock = repo.lock()
3706 lock = repo.lock()
3708 try:
3707 try:
3709 for fn, b, size in repo.store.datafiles():
3708 for fn, b, size in repo.store.datafiles():
3710 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3709 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3711 res.append(fn[plen:-slen])
3710 res.append(fn[plen:-slen])
3712 finally:
3711 finally:
3713 lock.release()
3712 lock.release()
3714 for f in sorted(res):
3713 for f in sorted(res):
3715 ui.write("%s\n" % f)
3714 ui.write("%s\n" % f)
3716 return
3715 return
3717
3716
3718 if rev and node:
3717 if rev and node:
3719 raise util.Abort(_("please specify just one revision"))
3718 raise util.Abort(_("please specify just one revision"))
3720
3719
3721 if not node:
3720 if not node:
3722 node = rev
3721 node = rev
3723
3722
3724 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3723 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3725 ctx = scmutil.revsingle(repo, node)
3724 ctx = scmutil.revsingle(repo, node)
3726 for f in ctx:
3725 for f in ctx:
3727 if ui.debugflag:
3726 if ui.debugflag:
3728 ui.write("%40s " % hex(ctx.manifest()[f]))
3727 ui.write("%40s " % hex(ctx.manifest()[f]))
3729 if ui.verbose:
3728 if ui.verbose:
3730 ui.write(decor[ctx.flags(f)])
3729 ui.write(decor[ctx.flags(f)])
3731 ui.write("%s\n" % f)
3730 ui.write("%s\n" % f)
3732
3731
3733 @command('^merge',
3732 @command('^merge',
3734 [('f', 'force', None, _('force a merge with outstanding changes')),
3733 [('f', 'force', None, _('force a merge with outstanding changes')),
3735 ('r', 'rev', '', _('revision to merge'), _('REV')),
3734 ('r', 'rev', '', _('revision to merge'), _('REV')),
3736 ('P', 'preview', None,
3735 ('P', 'preview', None,
3737 _('review revisions to merge (no merge is performed)'))
3736 _('review revisions to merge (no merge is performed)'))
3738 ] + mergetoolopts,
3737 ] + mergetoolopts,
3739 _('[-P] [-f] [[-r] REV]'))
3738 _('[-P] [-f] [[-r] REV]'))
3740 def merge(ui, repo, node=None, **opts):
3739 def merge(ui, repo, node=None, **opts):
3741 """merge working directory with another revision
3740 """merge working directory with another revision
3742
3741
3743 The current working directory is updated with all changes made in
3742 The current working directory is updated with all changes made in
3744 the requested revision since the last common predecessor revision.
3743 the requested revision since the last common predecessor revision.
3745
3744
3746 Files that changed between either parent are marked as changed for
3745 Files that changed between either parent are marked as changed for
3747 the next commit and a commit must be performed before any further
3746 the next commit and a commit must be performed before any further
3748 updates to the repository are allowed. The next commit will have
3747 updates to the repository are allowed. The next commit will have
3749 two parents.
3748 two parents.
3750
3749
3751 ``--tool`` can be used to specify the merge tool used for file
3750 ``--tool`` can be used to specify the merge tool used for file
3752 merges. It overrides the HGMERGE environment variable and your
3751 merges. It overrides the HGMERGE environment variable and your
3753 configuration files. See :hg:`help merge-tools` for options.
3752 configuration files. See :hg:`help merge-tools` for options.
3754
3753
3755 If no revision is specified, the working directory's parent is a
3754 If no revision is specified, the working directory's parent is a
3756 head revision, and the current branch contains exactly one other
3755 head revision, and the current branch contains exactly one other
3757 head, the other head is merged with by default. Otherwise, an
3756 head, the other head is merged with by default. Otherwise, an
3758 explicit revision with which to merge with must be provided.
3757 explicit revision with which to merge with must be provided.
3759
3758
3760 :hg:`resolve` must be used to resolve unresolved files.
3759 :hg:`resolve` must be used to resolve unresolved files.
3761
3760
3762 To undo an uncommitted merge, use :hg:`update --clean .` which
3761 To undo an uncommitted merge, use :hg:`update --clean .` which
3763 will check out a clean copy of the original merge parent, losing
3762 will check out a clean copy of the original merge parent, losing
3764 all changes.
3763 all changes.
3765
3764
3766 Returns 0 on success, 1 if there are unresolved files.
3765 Returns 0 on success, 1 if there are unresolved files.
3767 """
3766 """
3768
3767
3769 if opts.get('rev') and node:
3768 if opts.get('rev') and node:
3770 raise util.Abort(_("please specify just one revision"))
3769 raise util.Abort(_("please specify just one revision"))
3771 if not node:
3770 if not node:
3772 node = opts.get('rev')
3771 node = opts.get('rev')
3773
3772
3774 if not node:
3773 if not node:
3775 branch = repo[None].branch()
3774 branch = repo[None].branch()
3776 bheads = repo.branchheads(branch)
3775 bheads = repo.branchheads(branch)
3777 if len(bheads) > 2:
3776 if len(bheads) > 2:
3778 raise util.Abort(_("branch '%s' has %d heads - "
3777 raise util.Abort(_("branch '%s' has %d heads - "
3779 "please merge with an explicit rev")
3778 "please merge with an explicit rev")
3780 % (branch, len(bheads)),
3779 % (branch, len(bheads)),
3781 hint=_("run 'hg heads .' to see heads"))
3780 hint=_("run 'hg heads .' to see heads"))
3782
3781
3783 parent = repo.dirstate.p1()
3782 parent = repo.dirstate.p1()
3784 if len(bheads) == 1:
3783 if len(bheads) == 1:
3785 if len(repo.heads()) > 1:
3784 if len(repo.heads()) > 1:
3786 raise util.Abort(_("branch '%s' has one head - "
3785 raise util.Abort(_("branch '%s' has one head - "
3787 "please merge with an explicit rev")
3786 "please merge with an explicit rev")
3788 % branch,
3787 % branch,
3789 hint=_("run 'hg heads' to see all heads"))
3788 hint=_("run 'hg heads' to see all heads"))
3790 msg = _('there is nothing to merge')
3789 msg = _('there is nothing to merge')
3791 if parent != repo.lookup(repo[None].branch()):
3790 if parent != repo.lookup(repo[None].branch()):
3792 msg = _('%s - use "hg update" instead') % msg
3791 msg = _('%s - use "hg update" instead') % msg
3793 raise util.Abort(msg)
3792 raise util.Abort(msg)
3794
3793
3795 if parent not in bheads:
3794 if parent not in bheads:
3796 raise util.Abort(_('working directory not at a head revision'),
3795 raise util.Abort(_('working directory not at a head revision'),
3797 hint=_("use 'hg update' or merge with an "
3796 hint=_("use 'hg update' or merge with an "
3798 "explicit revision"))
3797 "explicit revision"))
3799 node = parent == bheads[0] and bheads[-1] or bheads[0]
3798 node = parent == bheads[0] and bheads[-1] or bheads[0]
3800 else:
3799 else:
3801 node = scmutil.revsingle(repo, node).node()
3800 node = scmutil.revsingle(repo, node).node()
3802
3801
3803 if opts.get('preview'):
3802 if opts.get('preview'):
3804 # find nodes that are ancestors of p2 but not of p1
3803 # find nodes that are ancestors of p2 but not of p1
3805 p1 = repo.lookup('.')
3804 p1 = repo.lookup('.')
3806 p2 = repo.lookup(node)
3805 p2 = repo.lookup(node)
3807 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3806 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3808
3807
3809 displayer = cmdutil.show_changeset(ui, repo, opts)
3808 displayer = cmdutil.show_changeset(ui, repo, opts)
3810 for node in nodes:
3809 for node in nodes:
3811 displayer.show(repo[node])
3810 displayer.show(repo[node])
3812 displayer.close()
3811 displayer.close()
3813 return 0
3812 return 0
3814
3813
3815 try:
3814 try:
3816 # ui.forcemerge is an internal variable, do not document
3815 # ui.forcemerge is an internal variable, do not document
3817 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3816 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3818 return hg.merge(repo, node, force=opts.get('force'))
3817 return hg.merge(repo, node, force=opts.get('force'))
3819 finally:
3818 finally:
3820 ui.setconfig('ui', 'forcemerge', '')
3819 ui.setconfig('ui', 'forcemerge', '')
3821
3820
3822 @command('outgoing|out',
3821 @command('outgoing|out',
3823 [('f', 'force', None, _('run even when the destination is unrelated')),
3822 [('f', 'force', None, _('run even when the destination is unrelated')),
3824 ('r', 'rev', [],
3823 ('r', 'rev', [],
3825 _('a changeset intended to be included in the destination'), _('REV')),
3824 _('a changeset intended to be included in the destination'), _('REV')),
3826 ('n', 'newest-first', None, _('show newest record first')),
3825 ('n', 'newest-first', None, _('show newest record first')),
3827 ('B', 'bookmarks', False, _('compare bookmarks')),
3826 ('B', 'bookmarks', False, _('compare bookmarks')),
3828 ('b', 'branch', [], _('a specific branch you would like to push'),
3827 ('b', 'branch', [], _('a specific branch you would like to push'),
3829 _('BRANCH')),
3828 _('BRANCH')),
3830 ] + logopts + remoteopts + subrepoopts,
3829 ] + logopts + remoteopts + subrepoopts,
3831 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3830 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3832 def outgoing(ui, repo, dest=None, **opts):
3831 def outgoing(ui, repo, dest=None, **opts):
3833 """show changesets not found in the destination
3832 """show changesets not found in the destination
3834
3833
3835 Show changesets not found in the specified destination repository
3834 Show changesets not found in the specified destination repository
3836 or the default push location. These are the changesets that would
3835 or the default push location. These are the changesets that would
3837 be pushed if a push was requested.
3836 be pushed if a push was requested.
3838
3837
3839 See pull for details of valid destination formats.
3838 See pull for details of valid destination formats.
3840
3839
3841 Returns 0 if there are outgoing changes, 1 otherwise.
3840 Returns 0 if there are outgoing changes, 1 otherwise.
3842 """
3841 """
3843
3842
3844 if opts.get('bookmarks'):
3843 if opts.get('bookmarks'):
3845 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3844 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3846 dest, branches = hg.parseurl(dest, opts.get('branch'))
3845 dest, branches = hg.parseurl(dest, opts.get('branch'))
3847 other = hg.peer(repo, opts, dest)
3846 other = hg.peer(repo, opts, dest)
3848 if 'bookmarks' not in other.listkeys('namespaces'):
3847 if 'bookmarks' not in other.listkeys('namespaces'):
3849 ui.warn(_("remote doesn't support bookmarks\n"))
3848 ui.warn(_("remote doesn't support bookmarks\n"))
3850 return 0
3849 return 0
3851 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3850 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3852 return bookmarks.diff(ui, other, repo)
3851 return bookmarks.diff(ui, other, repo)
3853
3852
3854 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3853 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3855 try:
3854 try:
3856 return hg.outgoing(ui, repo, dest, opts)
3855 return hg.outgoing(ui, repo, dest, opts)
3857 finally:
3856 finally:
3858 del repo._subtoppath
3857 del repo._subtoppath
3859
3858
3860 @command('parents',
3859 @command('parents',
3861 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3860 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3862 ] + templateopts,
3861 ] + templateopts,
3863 _('[-r REV] [FILE]'))
3862 _('[-r REV] [FILE]'))
3864 def parents(ui, repo, file_=None, **opts):
3863 def parents(ui, repo, file_=None, **opts):
3865 """show the parents of the working directory or revision
3864 """show the parents of the working directory or revision
3866
3865
3867 Print the working directory's parent revisions. If a revision is
3866 Print the working directory's parent revisions. If a revision is
3868 given via -r/--rev, the parent of that revision will be printed.
3867 given via -r/--rev, the parent of that revision will be printed.
3869 If a file argument is given, the revision in which the file was
3868 If a file argument is given, the revision in which the file was
3870 last changed (before the working directory revision or the
3869 last changed (before the working directory revision or the
3871 argument to --rev if given) is printed.
3870 argument to --rev if given) is printed.
3872
3871
3873 Returns 0 on success.
3872 Returns 0 on success.
3874 """
3873 """
3875
3874
3876 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3875 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3877
3876
3878 if file_:
3877 if file_:
3879 m = scmutil.match(ctx, (file_,), opts)
3878 m = scmutil.match(ctx, (file_,), opts)
3880 if m.anypats() or len(m.files()) != 1:
3879 if m.anypats() or len(m.files()) != 1:
3881 raise util.Abort(_('can only specify an explicit filename'))
3880 raise util.Abort(_('can only specify an explicit filename'))
3882 file_ = m.files()[0]
3881 file_ = m.files()[0]
3883 filenodes = []
3882 filenodes = []
3884 for cp in ctx.parents():
3883 for cp in ctx.parents():
3885 if not cp:
3884 if not cp:
3886 continue
3885 continue
3887 try:
3886 try:
3888 filenodes.append(cp.filenode(file_))
3887 filenodes.append(cp.filenode(file_))
3889 except error.LookupError:
3888 except error.LookupError:
3890 pass
3889 pass
3891 if not filenodes:
3890 if not filenodes:
3892 raise util.Abort(_("'%s' not found in manifest!") % file_)
3891 raise util.Abort(_("'%s' not found in manifest!") % file_)
3893 fl = repo.file(file_)
3892 fl = repo.file(file_)
3894 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3893 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3895 else:
3894 else:
3896 p = [cp.node() for cp in ctx.parents()]
3895 p = [cp.node() for cp in ctx.parents()]
3897
3896
3898 displayer = cmdutil.show_changeset(ui, repo, opts)
3897 displayer = cmdutil.show_changeset(ui, repo, opts)
3899 for n in p:
3898 for n in p:
3900 if n != nullid:
3899 if n != nullid:
3901 displayer.show(repo[n])
3900 displayer.show(repo[n])
3902 displayer.close()
3901 displayer.close()
3903
3902
3904 @command('paths', [], _('[NAME]'))
3903 @command('paths', [], _('[NAME]'))
3905 def paths(ui, repo, search=None):
3904 def paths(ui, repo, search=None):
3906 """show aliases for remote repositories
3905 """show aliases for remote repositories
3907
3906
3908 Show definition of symbolic path name NAME. If no name is given,
3907 Show definition of symbolic path name NAME. If no name is given,
3909 show definition of all available names.
3908 show definition of all available names.
3910
3909
3911 Option -q/--quiet suppresses all output when searching for NAME
3910 Option -q/--quiet suppresses all output when searching for NAME
3912 and shows only the path names when listing all definitions.
3911 and shows only the path names when listing all definitions.
3913
3912
3914 Path names are defined in the [paths] section of your
3913 Path names are defined in the [paths] section of your
3915 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3914 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3916 repository, ``.hg/hgrc`` is used, too.
3915 repository, ``.hg/hgrc`` is used, too.
3917
3916
3918 The path names ``default`` and ``default-push`` have a special
3917 The path names ``default`` and ``default-push`` have a special
3919 meaning. When performing a push or pull operation, they are used
3918 meaning. When performing a push or pull operation, they are used
3920 as fallbacks if no location is specified on the command-line.
3919 as fallbacks if no location is specified on the command-line.
3921 When ``default-push`` is set, it will be used for push and
3920 When ``default-push`` is set, it will be used for push and
3922 ``default`` will be used for pull; otherwise ``default`` is used
3921 ``default`` will be used for pull; otherwise ``default`` is used
3923 as the fallback for both. When cloning a repository, the clone
3922 as the fallback for both. When cloning a repository, the clone
3924 source is written as ``default`` in ``.hg/hgrc``. Note that
3923 source is written as ``default`` in ``.hg/hgrc``. Note that
3925 ``default`` and ``default-push`` apply to all inbound (e.g.
3924 ``default`` and ``default-push`` apply to all inbound (e.g.
3926 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3925 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3927 :hg:`bundle`) operations.
3926 :hg:`bundle`) operations.
3928
3927
3929 See :hg:`help urls` for more information.
3928 See :hg:`help urls` for more information.
3930
3929
3931 Returns 0 on success.
3930 Returns 0 on success.
3932 """
3931 """
3933 if search:
3932 if search:
3934 for name, path in ui.configitems("paths"):
3933 for name, path in ui.configitems("paths"):
3935 if name == search:
3934 if name == search:
3936 ui.status("%s\n" % util.hidepassword(path))
3935 ui.status("%s\n" % util.hidepassword(path))
3937 return
3936 return
3938 if not ui.quiet:
3937 if not ui.quiet:
3939 ui.warn(_("not found!\n"))
3938 ui.warn(_("not found!\n"))
3940 return 1
3939 return 1
3941 else:
3940 else:
3942 for name, path in ui.configitems("paths"):
3941 for name, path in ui.configitems("paths"):
3943 if ui.quiet:
3942 if ui.quiet:
3944 ui.write("%s\n" % name)
3943 ui.write("%s\n" % name)
3945 else:
3944 else:
3946 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3945 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3947
3946
3948 def postincoming(ui, repo, modheads, optupdate, checkout):
3947 def postincoming(ui, repo, modheads, optupdate, checkout):
3949 if modheads == 0:
3948 if modheads == 0:
3950 return
3949 return
3951 if optupdate:
3950 if optupdate:
3952 try:
3951 try:
3953 return hg.update(repo, checkout)
3952 return hg.update(repo, checkout)
3954 except util.Abort, inst:
3953 except util.Abort, inst:
3955 ui.warn(_("not updating: %s\n" % str(inst)))
3954 ui.warn(_("not updating: %s\n" % str(inst)))
3956 return 0
3955 return 0
3957 if modheads > 1:
3956 if modheads > 1:
3958 currentbranchheads = len(repo.branchheads())
3957 currentbranchheads = len(repo.branchheads())
3959 if currentbranchheads == modheads:
3958 if currentbranchheads == modheads:
3960 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3959 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3961 elif currentbranchheads > 1:
3960 elif currentbranchheads > 1:
3962 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3961 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3963 else:
3962 else:
3964 ui.status(_("(run 'hg heads' to see heads)\n"))
3963 ui.status(_("(run 'hg heads' to see heads)\n"))
3965 else:
3964 else:
3966 ui.status(_("(run 'hg update' to get a working copy)\n"))
3965 ui.status(_("(run 'hg update' to get a working copy)\n"))
3967
3966
3968 @command('^pull',
3967 @command('^pull',
3969 [('u', 'update', None,
3968 [('u', 'update', None,
3970 _('update to new branch head if changesets were pulled')),
3969 _('update to new branch head if changesets were pulled')),
3971 ('f', 'force', None, _('run even when remote repository is unrelated')),
3970 ('f', 'force', None, _('run even when remote repository is unrelated')),
3972 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3971 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3973 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3972 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3974 ('b', 'branch', [], _('a specific branch you would like to pull'),
3973 ('b', 'branch', [], _('a specific branch you would like to pull'),
3975 _('BRANCH')),
3974 _('BRANCH')),
3976 ] + remoteopts,
3975 ] + remoteopts,
3977 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3976 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3978 def pull(ui, repo, source="default", **opts):
3977 def pull(ui, repo, source="default", **opts):
3979 """pull changes from the specified source
3978 """pull changes from the specified source
3980
3979
3981 Pull changes from a remote repository to a local one.
3980 Pull changes from a remote repository to a local one.
3982
3981
3983 This finds all changes from the repository at the specified path
3982 This finds all changes from the repository at the specified path
3984 or URL and adds them to a local repository (the current one unless
3983 or URL and adds them to a local repository (the current one unless
3985 -R is specified). By default, this does not update the copy of the
3984 -R is specified). By default, this does not update the copy of the
3986 project in the working directory.
3985 project in the working directory.
3987
3986
3988 Use :hg:`incoming` if you want to see what would have been added
3987 Use :hg:`incoming` if you want to see what would have been added
3989 by a pull at the time you issued this command. If you then decide
3988 by a pull at the time you issued this command. If you then decide
3990 to add those changes to the repository, you should use :hg:`pull
3989 to add those changes to the repository, you should use :hg:`pull
3991 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3990 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3992
3991
3993 If SOURCE is omitted, the 'default' path will be used.
3992 If SOURCE is omitted, the 'default' path will be used.
3994 See :hg:`help urls` for more information.
3993 See :hg:`help urls` for more information.
3995
3994
3996 Returns 0 on success, 1 if an update had unresolved files.
3995 Returns 0 on success, 1 if an update had unresolved files.
3997 """
3996 """
3998 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3997 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3999 other = hg.peer(repo, opts, source)
3998 other = hg.peer(repo, opts, source)
4000 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3999 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4001 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4000 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4002
4001
4003 if opts.get('bookmark'):
4002 if opts.get('bookmark'):
4004 if not revs:
4003 if not revs:
4005 revs = []
4004 revs = []
4006 rb = other.listkeys('bookmarks')
4005 rb = other.listkeys('bookmarks')
4007 for b in opts['bookmark']:
4006 for b in opts['bookmark']:
4008 if b not in rb:
4007 if b not in rb:
4009 raise util.Abort(_('remote bookmark %s not found!') % b)
4008 raise util.Abort(_('remote bookmark %s not found!') % b)
4010 revs.append(rb[b])
4009 revs.append(rb[b])
4011
4010
4012 if revs:
4011 if revs:
4013 try:
4012 try:
4014 revs = [other.lookup(rev) for rev in revs]
4013 revs = [other.lookup(rev) for rev in revs]
4015 except error.CapabilityError:
4014 except error.CapabilityError:
4016 err = _("other repository doesn't support revision lookup, "
4015 err = _("other repository doesn't support revision lookup, "
4017 "so a rev cannot be specified.")
4016 "so a rev cannot be specified.")
4018 raise util.Abort(err)
4017 raise util.Abort(err)
4019
4018
4020 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4019 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4021 bookmarks.updatefromremote(ui, repo, other)
4020 bookmarks.updatefromremote(ui, repo, other)
4022 if checkout:
4021 if checkout:
4023 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4022 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4024 repo._subtoppath = source
4023 repo._subtoppath = source
4025 try:
4024 try:
4026 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4025 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4027
4026
4028 finally:
4027 finally:
4029 del repo._subtoppath
4028 del repo._subtoppath
4030
4029
4031 # update specified bookmarks
4030 # update specified bookmarks
4032 if opts.get('bookmark'):
4031 if opts.get('bookmark'):
4033 for b in opts['bookmark']:
4032 for b in opts['bookmark']:
4034 # explicit pull overrides local bookmark if any
4033 # explicit pull overrides local bookmark if any
4035 ui.status(_("importing bookmark %s\n") % b)
4034 ui.status(_("importing bookmark %s\n") % b)
4036 repo._bookmarks[b] = repo[rb[b]].node()
4035 repo._bookmarks[b] = repo[rb[b]].node()
4037 bookmarks.write(repo)
4036 bookmarks.write(repo)
4038
4037
4039 return ret
4038 return ret
4040
4039
4041 @command('^push',
4040 @command('^push',
4042 [('f', 'force', None, _('force push')),
4041 [('f', 'force', None, _('force push')),
4043 ('r', 'rev', [],
4042 ('r', 'rev', [],
4044 _('a changeset intended to be included in the destination'),
4043 _('a changeset intended to be included in the destination'),
4045 _('REV')),
4044 _('REV')),
4046 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4045 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4047 ('b', 'branch', [],
4046 ('b', 'branch', [],
4048 _('a specific branch you would like to push'), _('BRANCH')),
4047 _('a specific branch you would like to push'), _('BRANCH')),
4049 ('', 'new-branch', False, _('allow pushing a new branch')),
4048 ('', 'new-branch', False, _('allow pushing a new branch')),
4050 ] + remoteopts,
4049 ] + remoteopts,
4051 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4050 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4052 def push(ui, repo, dest=None, **opts):
4051 def push(ui, repo, dest=None, **opts):
4053 """push changes to the specified destination
4052 """push changes to the specified destination
4054
4053
4055 Push changesets from the local repository to the specified
4054 Push changesets from the local repository to the specified
4056 destination.
4055 destination.
4057
4056
4058 This operation is symmetrical to pull: it is identical to a pull
4057 This operation is symmetrical to pull: it is identical to a pull
4059 in the destination repository from the current one.
4058 in the destination repository from the current one.
4060
4059
4061 By default, push will not allow creation of new heads at the
4060 By default, push will not allow creation of new heads at the
4062 destination, since multiple heads would make it unclear which head
4061 destination, since multiple heads would make it unclear which head
4063 to use. In this situation, it is recommended to pull and merge
4062 to use. In this situation, it is recommended to pull and merge
4064 before pushing.
4063 before pushing.
4065
4064
4066 Use --new-branch if you want to allow push to create a new named
4065 Use --new-branch if you want to allow push to create a new named
4067 branch that is not present at the destination. This allows you to
4066 branch that is not present at the destination. This allows you to
4068 only create a new branch without forcing other changes.
4067 only create a new branch without forcing other changes.
4069
4068
4070 Use -f/--force to override the default behavior and push all
4069 Use -f/--force to override the default behavior and push all
4071 changesets on all branches.
4070 changesets on all branches.
4072
4071
4073 If -r/--rev is used, the specified revision and all its ancestors
4072 If -r/--rev is used, the specified revision and all its ancestors
4074 will be pushed to the remote repository.
4073 will be pushed to the remote repository.
4075
4074
4076 Please see :hg:`help urls` for important details about ``ssh://``
4075 Please see :hg:`help urls` for important details about ``ssh://``
4077 URLs. If DESTINATION is omitted, a default path will be used.
4076 URLs. If DESTINATION is omitted, a default path will be used.
4078
4077
4079 Returns 0 if push was successful, 1 if nothing to push.
4078 Returns 0 if push was successful, 1 if nothing to push.
4080 """
4079 """
4081
4080
4082 if opts.get('bookmark'):
4081 if opts.get('bookmark'):
4083 for b in opts['bookmark']:
4082 for b in opts['bookmark']:
4084 # translate -B options to -r so changesets get pushed
4083 # translate -B options to -r so changesets get pushed
4085 if b in repo._bookmarks:
4084 if b in repo._bookmarks:
4086 opts.setdefault('rev', []).append(b)
4085 opts.setdefault('rev', []).append(b)
4087 else:
4086 else:
4088 # if we try to push a deleted bookmark, translate it to null
4087 # if we try to push a deleted bookmark, translate it to null
4089 # this lets simultaneous -r, -b options continue working
4088 # this lets simultaneous -r, -b options continue working
4090 opts.setdefault('rev', []).append("null")
4089 opts.setdefault('rev', []).append("null")
4091
4090
4092 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4091 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4093 dest, branches = hg.parseurl(dest, opts.get('branch'))
4092 dest, branches = hg.parseurl(dest, opts.get('branch'))
4094 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4093 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4095 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4094 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4096 other = hg.peer(repo, opts, dest)
4095 other = hg.peer(repo, opts, dest)
4097 if revs:
4096 if revs:
4098 revs = [repo.lookup(rev) for rev in revs]
4097 revs = [repo.lookup(rev) for rev in revs]
4099
4098
4100 repo._subtoppath = dest
4099 repo._subtoppath = dest
4101 try:
4100 try:
4102 # push subrepos depth-first for coherent ordering
4101 # push subrepos depth-first for coherent ordering
4103 c = repo['']
4102 c = repo['']
4104 subs = c.substate # only repos that are committed
4103 subs = c.substate # only repos that are committed
4105 for s in sorted(subs):
4104 for s in sorted(subs):
4106 if not c.sub(s).push(opts.get('force')):
4105 if not c.sub(s).push(opts.get('force')):
4107 return False
4106 return False
4108 finally:
4107 finally:
4109 del repo._subtoppath
4108 del repo._subtoppath
4110 result = repo.push(other, opts.get('force'), revs=revs,
4109 result = repo.push(other, opts.get('force'), revs=revs,
4111 newbranch=opts.get('new_branch'))
4110 newbranch=opts.get('new_branch'))
4112
4111
4113 result = (result == 0)
4112 result = (result == 0)
4114
4113
4115 if opts.get('bookmark'):
4114 if opts.get('bookmark'):
4116 rb = other.listkeys('bookmarks')
4115 rb = other.listkeys('bookmarks')
4117 for b in opts['bookmark']:
4116 for b in opts['bookmark']:
4118 # explicit push overrides remote bookmark if any
4117 # explicit push overrides remote bookmark if any
4119 if b in repo._bookmarks:
4118 if b in repo._bookmarks:
4120 ui.status(_("exporting bookmark %s\n") % b)
4119 ui.status(_("exporting bookmark %s\n") % b)
4121 new = repo[b].hex()
4120 new = repo[b].hex()
4122 elif b in rb:
4121 elif b in rb:
4123 ui.status(_("deleting remote bookmark %s\n") % b)
4122 ui.status(_("deleting remote bookmark %s\n") % b)
4124 new = '' # delete
4123 new = '' # delete
4125 else:
4124 else:
4126 ui.warn(_('bookmark %s does not exist on the local '
4125 ui.warn(_('bookmark %s does not exist on the local '
4127 'or remote repository!\n') % b)
4126 'or remote repository!\n') % b)
4128 return 2
4127 return 2
4129 old = rb.get(b, '')
4128 old = rb.get(b, '')
4130 r = other.pushkey('bookmarks', b, old, new)
4129 r = other.pushkey('bookmarks', b, old, new)
4131 if not r:
4130 if not r:
4132 ui.warn(_('updating bookmark %s failed!\n') % b)
4131 ui.warn(_('updating bookmark %s failed!\n') % b)
4133 if not result:
4132 if not result:
4134 result = 2
4133 result = 2
4135
4134
4136 return result
4135 return result
4137
4136
4138 @command('recover', [])
4137 @command('recover', [])
4139 def recover(ui, repo):
4138 def recover(ui, repo):
4140 """roll back an interrupted transaction
4139 """roll back an interrupted transaction
4141
4140
4142 Recover from an interrupted commit or pull.
4141 Recover from an interrupted commit or pull.
4143
4142
4144 This command tries to fix the repository status after an
4143 This command tries to fix the repository status after an
4145 interrupted operation. It should only be necessary when Mercurial
4144 interrupted operation. It should only be necessary when Mercurial
4146 suggests it.
4145 suggests it.
4147
4146
4148 Returns 0 if successful, 1 if nothing to recover or verify fails.
4147 Returns 0 if successful, 1 if nothing to recover or verify fails.
4149 """
4148 """
4150 if repo.recover():
4149 if repo.recover():
4151 return hg.verify(repo)
4150 return hg.verify(repo)
4152 return 1
4151 return 1
4153
4152
4154 @command('^remove|rm',
4153 @command('^remove|rm',
4155 [('A', 'after', None, _('record delete for missing files')),
4154 [('A', 'after', None, _('record delete for missing files')),
4156 ('f', 'force', None,
4155 ('f', 'force', None,
4157 _('remove (and delete) file even if added or modified')),
4156 _('remove (and delete) file even if added or modified')),
4158 ] + walkopts,
4157 ] + walkopts,
4159 _('[OPTION]... FILE...'))
4158 _('[OPTION]... FILE...'))
4160 def remove(ui, repo, *pats, **opts):
4159 def remove(ui, repo, *pats, **opts):
4161 """remove the specified files on the next commit
4160 """remove the specified files on the next commit
4162
4161
4163 Schedule the indicated files for removal from the current branch.
4162 Schedule the indicated files for removal from the current branch.
4164
4163
4165 This command schedules the files to be removed at the next commit.
4164 This command schedules the files to be removed at the next commit.
4166 To undo a remove before that, see :hg:`revert`. To undo added
4165 To undo a remove before that, see :hg:`revert`. To undo added
4167 files, see :hg:`forget`.
4166 files, see :hg:`forget`.
4168
4167
4169 .. container:: verbose
4168 .. container:: verbose
4170
4169
4171 -A/--after can be used to remove only files that have already
4170 -A/--after can be used to remove only files that have already
4172 been deleted, -f/--force can be used to force deletion, and -Af
4171 been deleted, -f/--force can be used to force deletion, and -Af
4173 can be used to remove files from the next revision without
4172 can be used to remove files from the next revision without
4174 deleting them from the working directory.
4173 deleting them from the working directory.
4175
4174
4176 The following table details the behavior of remove for different
4175 The following table details the behavior of remove for different
4177 file states (columns) and option combinations (rows). The file
4176 file states (columns) and option combinations (rows). The file
4178 states are Added [A], Clean [C], Modified [M] and Missing [!]
4177 states are Added [A], Clean [C], Modified [M] and Missing [!]
4179 (as reported by :hg:`status`). The actions are Warn, Remove
4178 (as reported by :hg:`status`). The actions are Warn, Remove
4180 (from branch) and Delete (from disk):
4179 (from branch) and Delete (from disk):
4181
4180
4182 ======= == == == ==
4181 ======= == == == ==
4183 A C M !
4182 A C M !
4184 ======= == == == ==
4183 ======= == == == ==
4185 none W RD W R
4184 none W RD W R
4186 -f R RD RD R
4185 -f R RD RD R
4187 -A W W W R
4186 -A W W W R
4188 -Af R R R R
4187 -Af R R R R
4189 ======= == == == ==
4188 ======= == == == ==
4190
4189
4191 Note that remove never deletes files in Added [A] state from the
4190 Note that remove never deletes files in Added [A] state from the
4192 working directory, not even if option --force is specified.
4191 working directory, not even if option --force is specified.
4193
4192
4194 Returns 0 on success, 1 if any warnings encountered.
4193 Returns 0 on success, 1 if any warnings encountered.
4195 """
4194 """
4196
4195
4197 ret = 0
4196 ret = 0
4198 after, force = opts.get('after'), opts.get('force')
4197 after, force = opts.get('after'), opts.get('force')
4199 if not pats and not after:
4198 if not pats and not after:
4200 raise util.Abort(_('no files specified'))
4199 raise util.Abort(_('no files specified'))
4201
4200
4202 m = scmutil.match(repo[None], pats, opts)
4201 m = scmutil.match(repo[None], pats, opts)
4203 s = repo.status(match=m, clean=True)
4202 s = repo.status(match=m, clean=True)
4204 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4203 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4205
4204
4206 for f in m.files():
4205 for f in m.files():
4207 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4206 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4208 if os.path.exists(m.rel(f)):
4207 if os.path.exists(m.rel(f)):
4209 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4208 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4210 ret = 1
4209 ret = 1
4211
4210
4212 if force:
4211 if force:
4213 list = modified + deleted + clean + added
4212 list = modified + deleted + clean + added
4214 elif after:
4213 elif after:
4215 list = deleted
4214 list = deleted
4216 for f in modified + added + clean:
4215 for f in modified + added + clean:
4217 ui.warn(_('not removing %s: file still exists (use -f'
4216 ui.warn(_('not removing %s: file still exists (use -f'
4218 ' to force removal)\n') % m.rel(f))
4217 ' to force removal)\n') % m.rel(f))
4219 ret = 1
4218 ret = 1
4220 else:
4219 else:
4221 list = deleted + clean
4220 list = deleted + clean
4222 for f in modified:
4221 for f in modified:
4223 ui.warn(_('not removing %s: file is modified (use -f'
4222 ui.warn(_('not removing %s: file is modified (use -f'
4224 ' to force removal)\n') % m.rel(f))
4223 ' to force removal)\n') % m.rel(f))
4225 ret = 1
4224 ret = 1
4226 for f in added:
4225 for f in added:
4227 ui.warn(_('not removing %s: file has been marked for add'
4226 ui.warn(_('not removing %s: file has been marked for add'
4228 ' (use forget to undo)\n') % m.rel(f))
4227 ' (use forget to undo)\n') % m.rel(f))
4229 ret = 1
4228 ret = 1
4230
4229
4231 for f in sorted(list):
4230 for f in sorted(list):
4232 if ui.verbose or not m.exact(f):
4231 if ui.verbose or not m.exact(f):
4233 ui.status(_('removing %s\n') % m.rel(f))
4232 ui.status(_('removing %s\n') % m.rel(f))
4234
4233
4235 wlock = repo.wlock()
4234 wlock = repo.wlock()
4236 try:
4235 try:
4237 if not after:
4236 if not after:
4238 for f in list:
4237 for f in list:
4239 if f in added:
4238 if f in added:
4240 continue # we never unlink added files on remove
4239 continue # we never unlink added files on remove
4241 try:
4240 try:
4242 util.unlinkpath(repo.wjoin(f))
4241 util.unlinkpath(repo.wjoin(f))
4243 except OSError, inst:
4242 except OSError, inst:
4244 if inst.errno != errno.ENOENT:
4243 if inst.errno != errno.ENOENT:
4245 raise
4244 raise
4246 repo[None].forget(list)
4245 repo[None].forget(list)
4247 finally:
4246 finally:
4248 wlock.release()
4247 wlock.release()
4249
4248
4250 return ret
4249 return ret
4251
4250
4252 @command('rename|move|mv',
4251 @command('rename|move|mv',
4253 [('A', 'after', None, _('record a rename that has already occurred')),
4252 [('A', 'after', None, _('record a rename that has already occurred')),
4254 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4253 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4255 ] + walkopts + dryrunopts,
4254 ] + walkopts + dryrunopts,
4256 _('[OPTION]... SOURCE... DEST'))
4255 _('[OPTION]... SOURCE... DEST'))
4257 def rename(ui, repo, *pats, **opts):
4256 def rename(ui, repo, *pats, **opts):
4258 """rename files; equivalent of copy + remove
4257 """rename files; equivalent of copy + remove
4259
4258
4260 Mark dest as copies of sources; mark sources for deletion. If dest
4259 Mark dest as copies of sources; mark sources for deletion. If dest
4261 is a directory, copies are put in that directory. If dest is a
4260 is a directory, copies are put in that directory. If dest is a
4262 file, there can only be one source.
4261 file, there can only be one source.
4263
4262
4264 By default, this command copies the contents of files as they
4263 By default, this command copies the contents of files as they
4265 exist in the working directory. If invoked with -A/--after, the
4264 exist in the working directory. If invoked with -A/--after, the
4266 operation is recorded, but no copying is performed.
4265 operation is recorded, but no copying is performed.
4267
4266
4268 This command takes effect at the next commit. To undo a rename
4267 This command takes effect at the next commit. To undo a rename
4269 before that, see :hg:`revert`.
4268 before that, see :hg:`revert`.
4270
4269
4271 Returns 0 on success, 1 if errors are encountered.
4270 Returns 0 on success, 1 if errors are encountered.
4272 """
4271 """
4273 wlock = repo.wlock(False)
4272 wlock = repo.wlock(False)
4274 try:
4273 try:
4275 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4274 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4276 finally:
4275 finally:
4277 wlock.release()
4276 wlock.release()
4278
4277
4279 @command('resolve',
4278 @command('resolve',
4280 [('a', 'all', None, _('select all unresolved files')),
4279 [('a', 'all', None, _('select all unresolved files')),
4281 ('l', 'list', None, _('list state of files needing merge')),
4280 ('l', 'list', None, _('list state of files needing merge')),
4282 ('m', 'mark', None, _('mark files as resolved')),
4281 ('m', 'mark', None, _('mark files as resolved')),
4283 ('u', 'unmark', None, _('mark files as unresolved')),
4282 ('u', 'unmark', None, _('mark files as unresolved')),
4284 ('n', 'no-status', None, _('hide status prefix'))]
4283 ('n', 'no-status', None, _('hide status prefix'))]
4285 + mergetoolopts + walkopts,
4284 + mergetoolopts + walkopts,
4286 _('[OPTION]... [FILE]...'))
4285 _('[OPTION]... [FILE]...'))
4287 def resolve(ui, repo, *pats, **opts):
4286 def resolve(ui, repo, *pats, **opts):
4288 """redo merges or set/view the merge status of files
4287 """redo merges or set/view the merge status of files
4289
4288
4290 Merges with unresolved conflicts are often the result of
4289 Merges with unresolved conflicts are often the result of
4291 non-interactive merging using the ``internal:merge`` configuration
4290 non-interactive merging using the ``internal:merge`` configuration
4292 setting, or a command-line merge tool like ``diff3``. The resolve
4291 setting, or a command-line merge tool like ``diff3``. The resolve
4293 command is used to manage the files involved in a merge, after
4292 command is used to manage the files involved in a merge, after
4294 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4293 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4295 working directory must have two parents).
4294 working directory must have two parents).
4296
4295
4297 The resolve command can be used in the following ways:
4296 The resolve command can be used in the following ways:
4298
4297
4299 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4298 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4300 files, discarding any previous merge attempts. Re-merging is not
4299 files, discarding any previous merge attempts. Re-merging is not
4301 performed for files already marked as resolved. Use ``--all/-a``
4300 performed for files already marked as resolved. Use ``--all/-a``
4302 to select all unresolved files. ``--tool`` can be used to specify
4301 to select all unresolved files. ``--tool`` can be used to specify
4303 the merge tool used for the given files. It overrides the HGMERGE
4302 the merge tool used for the given files. It overrides the HGMERGE
4304 environment variable and your configuration files.
4303 environment variable and your configuration files.
4305
4304
4306 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4305 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4307 (e.g. after having manually fixed-up the files). The default is
4306 (e.g. after having manually fixed-up the files). The default is
4308 to mark all unresolved files.
4307 to mark all unresolved files.
4309
4308
4310 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4309 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4311 default is to mark all resolved files.
4310 default is to mark all resolved files.
4312
4311
4313 - :hg:`resolve -l`: list files which had or still have conflicts.
4312 - :hg:`resolve -l`: list files which had or still have conflicts.
4314 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4313 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4315
4314
4316 Note that Mercurial will not let you commit files with unresolved
4315 Note that Mercurial will not let you commit files with unresolved
4317 merge conflicts. You must use :hg:`resolve -m ...` before you can
4316 merge conflicts. You must use :hg:`resolve -m ...` before you can
4318 commit after a conflicting merge.
4317 commit after a conflicting merge.
4319
4318
4320 Returns 0 on success, 1 if any files fail a resolve attempt.
4319 Returns 0 on success, 1 if any files fail a resolve attempt.
4321 """
4320 """
4322
4321
4323 all, mark, unmark, show, nostatus = \
4322 all, mark, unmark, show, nostatus = \
4324 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4323 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4325
4324
4326 if (show and (mark or unmark)) or (mark and unmark):
4325 if (show and (mark or unmark)) or (mark and unmark):
4327 raise util.Abort(_("too many options specified"))
4326 raise util.Abort(_("too many options specified"))
4328 if pats and all:
4327 if pats and all:
4329 raise util.Abort(_("can't specify --all and patterns"))
4328 raise util.Abort(_("can't specify --all and patterns"))
4330 if not (all or pats or show or mark or unmark):
4329 if not (all or pats or show or mark or unmark):
4331 raise util.Abort(_('no files or directories specified; '
4330 raise util.Abort(_('no files or directories specified; '
4332 'use --all to remerge all files'))
4331 'use --all to remerge all files'))
4333
4332
4334 ms = mergemod.mergestate(repo)
4333 ms = mergemod.mergestate(repo)
4335 m = scmutil.match(repo[None], pats, opts)
4334 m = scmutil.match(repo[None], pats, opts)
4336 ret = 0
4335 ret = 0
4337
4336
4338 for f in ms:
4337 for f in ms:
4339 if m(f):
4338 if m(f):
4340 if show:
4339 if show:
4341 if nostatus:
4340 if nostatus:
4342 ui.write("%s\n" % f)
4341 ui.write("%s\n" % f)
4343 else:
4342 else:
4344 ui.write("%s %s\n" % (ms[f].upper(), f),
4343 ui.write("%s %s\n" % (ms[f].upper(), f),
4345 label='resolve.' +
4344 label='resolve.' +
4346 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4345 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4347 elif mark:
4346 elif mark:
4348 ms.mark(f, "r")
4347 ms.mark(f, "r")
4349 elif unmark:
4348 elif unmark:
4350 ms.mark(f, "u")
4349 ms.mark(f, "u")
4351 else:
4350 else:
4352 wctx = repo[None]
4351 wctx = repo[None]
4353 mctx = wctx.parents()[-1]
4352 mctx = wctx.parents()[-1]
4354
4353
4355 # backup pre-resolve (merge uses .orig for its own purposes)
4354 # backup pre-resolve (merge uses .orig for its own purposes)
4356 a = repo.wjoin(f)
4355 a = repo.wjoin(f)
4357 util.copyfile(a, a + ".resolve")
4356 util.copyfile(a, a + ".resolve")
4358
4357
4359 try:
4358 try:
4360 # resolve file
4359 # resolve file
4361 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4360 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4362 if ms.resolve(f, wctx, mctx):
4361 if ms.resolve(f, wctx, mctx):
4363 ret = 1
4362 ret = 1
4364 finally:
4363 finally:
4365 ui.setconfig('ui', 'forcemerge', '')
4364 ui.setconfig('ui', 'forcemerge', '')
4366
4365
4367 # replace filemerge's .orig file with our resolve file
4366 # replace filemerge's .orig file with our resolve file
4368 util.rename(a + ".resolve", a + ".orig")
4367 util.rename(a + ".resolve", a + ".orig")
4369
4368
4370 ms.commit()
4369 ms.commit()
4371 return ret
4370 return ret
4372
4371
4373 @command('revert',
4372 @command('revert',
4374 [('a', 'all', None, _('revert all changes when no arguments given')),
4373 [('a', 'all', None, _('revert all changes when no arguments given')),
4375 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4374 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4376 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4375 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4377 ('C', 'no-backup', None, _('do not save backup copies of files')),
4376 ('C', 'no-backup', None, _('do not save backup copies of files')),
4378 ] + walkopts + dryrunopts,
4377 ] + walkopts + dryrunopts,
4379 _('[OPTION]... [-r REV] [NAME]...'))
4378 _('[OPTION]... [-r REV] [NAME]...'))
4380 def revert(ui, repo, *pats, **opts):
4379 def revert(ui, repo, *pats, **opts):
4381 """restore files to their checkout state
4380 """restore files to their checkout state
4382
4381
4383 .. note::
4382 .. note::
4384 To check out earlier revisions, you should use :hg:`update REV`.
4383 To check out earlier revisions, you should use :hg:`update REV`.
4385 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4384 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4386
4385
4387 With no revision specified, revert the specified files or directories
4386 With no revision specified, revert the specified files or directories
4388 to the contents they had in the parent of the working directory.
4387 to the contents they had in the parent of the working directory.
4389 This restores the contents of files to an unmodified
4388 This restores the contents of files to an unmodified
4390 state and unschedules adds, removes, copies, and renames. If the
4389 state and unschedules adds, removes, copies, and renames. If the
4391 working directory has two parents, you must explicitly specify a
4390 working directory has two parents, you must explicitly specify a
4392 revision.
4391 revision.
4393
4392
4394 Using the -r/--rev or -d/--date options, revert the given files or
4393 Using the -r/--rev or -d/--date options, revert the given files or
4395 directories to their states as of a specific revision. Because
4394 directories to their states as of a specific revision. Because
4396 revert does not change the working directory parents, this will
4395 revert does not change the working directory parents, this will
4397 cause these files to appear modified. This can be helpful to "back
4396 cause these files to appear modified. This can be helpful to "back
4398 out" some or all of an earlier change. See :hg:`backout` for a
4397 out" some or all of an earlier change. See :hg:`backout` for a
4399 related method.
4398 related method.
4400
4399
4401 Modified files are saved with a .orig suffix before reverting.
4400 Modified files are saved with a .orig suffix before reverting.
4402 To disable these backups, use --no-backup.
4401 To disable these backups, use --no-backup.
4403
4402
4404 See :hg:`help dates` for a list of formats valid for -d/--date.
4403 See :hg:`help dates` for a list of formats valid for -d/--date.
4405
4404
4406 Returns 0 on success.
4405 Returns 0 on success.
4407 """
4406 """
4408
4407
4409 if opts.get("date"):
4408 if opts.get("date"):
4410 if opts.get("rev"):
4409 if opts.get("rev"):
4411 raise util.Abort(_("you can't specify a revision and a date"))
4410 raise util.Abort(_("you can't specify a revision and a date"))
4412 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4411 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4413
4412
4414 parent, p2 = repo.dirstate.parents()
4413 parent, p2 = repo.dirstate.parents()
4415 if not opts.get('rev') and p2 != nullid:
4414 if not opts.get('rev') and p2 != nullid:
4416 # revert after merge is a trap for new users (issue2915)
4415 # revert after merge is a trap for new users (issue2915)
4417 raise util.Abort(_('uncommitted merge with no revision specified'),
4416 raise util.Abort(_('uncommitted merge with no revision specified'),
4418 hint=_('use "hg update" or see "hg help revert"'))
4417 hint=_('use "hg update" or see "hg help revert"'))
4419
4418
4420 ctx = scmutil.revsingle(repo, opts.get('rev'))
4419 ctx = scmutil.revsingle(repo, opts.get('rev'))
4421 node = ctx.node()
4420 node = ctx.node()
4422
4421
4423 if not pats and not opts.get('all'):
4422 if not pats and not opts.get('all'):
4424 msg = _("no files or directories specified")
4423 msg = _("no files or directories specified")
4425 if p2 != nullid:
4424 if p2 != nullid:
4426 hint = _("uncommitted merge, use --all to discard all changes,"
4425 hint = _("uncommitted merge, use --all to discard all changes,"
4427 " or 'hg update -C .' to abort the merge")
4426 " or 'hg update -C .' to abort the merge")
4428 raise util.Abort(msg, hint=hint)
4427 raise util.Abort(msg, hint=hint)
4429 dirty = util.any(repo.status())
4428 dirty = util.any(repo.status())
4430 if node != parent:
4429 if node != parent:
4431 if dirty:
4430 if dirty:
4432 hint = _("uncommitted changes, use --all to discard all"
4431 hint = _("uncommitted changes, use --all to discard all"
4433 " changes, or 'hg update %s' to update") % ctx.rev()
4432 " changes, or 'hg update %s' to update") % ctx.rev()
4434 else:
4433 else:
4435 hint = _("use --all to revert all files,"
4434 hint = _("use --all to revert all files,"
4436 " or 'hg update %s' to update") % ctx.rev()
4435 " or 'hg update %s' to update") % ctx.rev()
4437 elif dirty:
4436 elif dirty:
4438 hint = _("uncommitted changes, use --all to discard all changes")
4437 hint = _("uncommitted changes, use --all to discard all changes")
4439 else:
4438 else:
4440 hint = _("use --all to revert all files")
4439 hint = _("use --all to revert all files")
4441 raise util.Abort(msg, hint=hint)
4440 raise util.Abort(msg, hint=hint)
4442
4441
4443 mf = ctx.manifest()
4442 mf = ctx.manifest()
4444 if node == parent:
4443 if node == parent:
4445 pmf = mf
4444 pmf = mf
4446 else:
4445 else:
4447 pmf = None
4446 pmf = None
4448
4447
4449 # need all matching names in dirstate and manifest of target rev,
4448 # need all matching names in dirstate and manifest of target rev,
4450 # so have to walk both. do not print errors if files exist in one
4449 # so have to walk both. do not print errors if files exist in one
4451 # but not other.
4450 # but not other.
4452
4451
4453 names = {}
4452 names = {}
4454
4453
4455 wlock = repo.wlock()
4454 wlock = repo.wlock()
4456 try:
4455 try:
4457 # walk dirstate.
4456 # walk dirstate.
4458
4457
4459 m = scmutil.match(repo[None], pats, opts)
4458 m = scmutil.match(repo[None], pats, opts)
4460 m.bad = lambda x, y: False
4459 m.bad = lambda x, y: False
4461 for abs in repo.walk(m):
4460 for abs in repo.walk(m):
4462 names[abs] = m.rel(abs), m.exact(abs)
4461 names[abs] = m.rel(abs), m.exact(abs)
4463
4462
4464 # walk target manifest.
4463 # walk target manifest.
4465
4464
4466 def badfn(path, msg):
4465 def badfn(path, msg):
4467 if path in names:
4466 if path in names:
4468 return
4467 return
4469 path_ = path + '/'
4468 path_ = path + '/'
4470 for f in names:
4469 for f in names:
4471 if f.startswith(path_):
4470 if f.startswith(path_):
4472 return
4471 return
4473 ui.warn("%s: %s\n" % (m.rel(path), msg))
4472 ui.warn("%s: %s\n" % (m.rel(path), msg))
4474
4473
4475 m = scmutil.match(repo[node], pats, opts)
4474 m = scmutil.match(repo[node], pats, opts)
4476 m.bad = badfn
4475 m.bad = badfn
4477 for abs in repo[node].walk(m):
4476 for abs in repo[node].walk(m):
4478 if abs not in names:
4477 if abs not in names:
4479 names[abs] = m.rel(abs), m.exact(abs)
4478 names[abs] = m.rel(abs), m.exact(abs)
4480
4479
4481 m = scmutil.matchfiles(repo, names)
4480 m = scmutil.matchfiles(repo, names)
4482 changes = repo.status(match=m)[:4]
4481 changes = repo.status(match=m)[:4]
4483 modified, added, removed, deleted = map(set, changes)
4482 modified, added, removed, deleted = map(set, changes)
4484
4483
4485 # if f is a rename, also revert the source
4484 # if f is a rename, also revert the source
4486 cwd = repo.getcwd()
4485 cwd = repo.getcwd()
4487 for f in added:
4486 for f in added:
4488 src = repo.dirstate.copied(f)
4487 src = repo.dirstate.copied(f)
4489 if src and src not in names and repo.dirstate[src] == 'r':
4488 if src and src not in names and repo.dirstate[src] == 'r':
4490 removed.add(src)
4489 removed.add(src)
4491 names[src] = (repo.pathto(src, cwd), True)
4490 names[src] = (repo.pathto(src, cwd), True)
4492
4491
4493 def removeforget(abs):
4492 def removeforget(abs):
4494 if repo.dirstate[abs] == 'a':
4493 if repo.dirstate[abs] == 'a':
4495 return _('forgetting %s\n')
4494 return _('forgetting %s\n')
4496 return _('removing %s\n')
4495 return _('removing %s\n')
4497
4496
4498 revert = ([], _('reverting %s\n'))
4497 revert = ([], _('reverting %s\n'))
4499 add = ([], _('adding %s\n'))
4498 add = ([], _('adding %s\n'))
4500 remove = ([], removeforget)
4499 remove = ([], removeforget)
4501 undelete = ([], _('undeleting %s\n'))
4500 undelete = ([], _('undeleting %s\n'))
4502
4501
4503 disptable = (
4502 disptable = (
4504 # dispatch table:
4503 # dispatch table:
4505 # file state
4504 # file state
4506 # action if in target manifest
4505 # action if in target manifest
4507 # action if not in target manifest
4506 # action if not in target manifest
4508 # make backup if in target manifest
4507 # make backup if in target manifest
4509 # make backup if not in target manifest
4508 # make backup if not in target manifest
4510 (modified, revert, remove, True, True),
4509 (modified, revert, remove, True, True),
4511 (added, revert, remove, True, False),
4510 (added, revert, remove, True, False),
4512 (removed, undelete, None, False, False),
4511 (removed, undelete, None, False, False),
4513 (deleted, revert, remove, False, False),
4512 (deleted, revert, remove, False, False),
4514 )
4513 )
4515
4514
4516 for abs, (rel, exact) in sorted(names.items()):
4515 for abs, (rel, exact) in sorted(names.items()):
4517 mfentry = mf.get(abs)
4516 mfentry = mf.get(abs)
4518 target = repo.wjoin(abs)
4517 target = repo.wjoin(abs)
4519 def handle(xlist, dobackup):
4518 def handle(xlist, dobackup):
4520 xlist[0].append(abs)
4519 xlist[0].append(abs)
4521 if (dobackup and not opts.get('no_backup') and
4520 if (dobackup and not opts.get('no_backup') and
4522 os.path.lexists(target)):
4521 os.path.lexists(target)):
4523 bakname = "%s.orig" % rel
4522 bakname = "%s.orig" % rel
4524 ui.note(_('saving current version of %s as %s\n') %
4523 ui.note(_('saving current version of %s as %s\n') %
4525 (rel, bakname))
4524 (rel, bakname))
4526 if not opts.get('dry_run'):
4525 if not opts.get('dry_run'):
4527 util.rename(target, bakname)
4526 util.rename(target, bakname)
4528 if ui.verbose or not exact:
4527 if ui.verbose or not exact:
4529 msg = xlist[1]
4528 msg = xlist[1]
4530 if not isinstance(msg, basestring):
4529 if not isinstance(msg, basestring):
4531 msg = msg(abs)
4530 msg = msg(abs)
4532 ui.status(msg % rel)
4531 ui.status(msg % rel)
4533 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4532 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4534 if abs not in table:
4533 if abs not in table:
4535 continue
4534 continue
4536 # file has changed in dirstate
4535 # file has changed in dirstate
4537 if mfentry:
4536 if mfentry:
4538 handle(hitlist, backuphit)
4537 handle(hitlist, backuphit)
4539 elif misslist is not None:
4538 elif misslist is not None:
4540 handle(misslist, backupmiss)
4539 handle(misslist, backupmiss)
4541 break
4540 break
4542 else:
4541 else:
4543 if abs not in repo.dirstate:
4542 if abs not in repo.dirstate:
4544 if mfentry:
4543 if mfentry:
4545 handle(add, True)
4544 handle(add, True)
4546 elif exact:
4545 elif exact:
4547 ui.warn(_('file not managed: %s\n') % rel)
4546 ui.warn(_('file not managed: %s\n') % rel)
4548 continue
4547 continue
4549 # file has not changed in dirstate
4548 # file has not changed in dirstate
4550 if node == parent:
4549 if node == parent:
4551 if exact:
4550 if exact:
4552 ui.warn(_('no changes needed to %s\n') % rel)
4551 ui.warn(_('no changes needed to %s\n') % rel)
4553 continue
4552 continue
4554 if pmf is None:
4553 if pmf is None:
4555 # only need parent manifest in this unlikely case,
4554 # only need parent manifest in this unlikely case,
4556 # so do not read by default
4555 # so do not read by default
4557 pmf = repo[parent].manifest()
4556 pmf = repo[parent].manifest()
4558 if abs in pmf:
4557 if abs in pmf:
4559 if mfentry:
4558 if mfentry:
4560 # if version of file is same in parent and target
4559 # if version of file is same in parent and target
4561 # manifests, do nothing
4560 # manifests, do nothing
4562 if (pmf[abs] != mfentry or
4561 if (pmf[abs] != mfentry or
4563 pmf.flags(abs) != mf.flags(abs)):
4562 pmf.flags(abs) != mf.flags(abs)):
4564 handle(revert, False)
4563 handle(revert, False)
4565 else:
4564 else:
4566 handle(remove, False)
4565 handle(remove, False)
4567
4566
4568 if not opts.get('dry_run'):
4567 if not opts.get('dry_run'):
4569 def checkout(f):
4568 def checkout(f):
4570 fc = ctx[f]
4569 fc = ctx[f]
4571 repo.wwrite(f, fc.data(), fc.flags())
4570 repo.wwrite(f, fc.data(), fc.flags())
4572
4571
4573 audit_path = scmutil.pathauditor(repo.root)
4572 audit_path = scmutil.pathauditor(repo.root)
4574 for f in remove[0]:
4573 for f in remove[0]:
4575 if repo.dirstate[f] == 'a':
4574 if repo.dirstate[f] == 'a':
4576 repo.dirstate.drop(f)
4575 repo.dirstate.drop(f)
4577 continue
4576 continue
4578 audit_path(f)
4577 audit_path(f)
4579 try:
4578 try:
4580 util.unlinkpath(repo.wjoin(f))
4579 util.unlinkpath(repo.wjoin(f))
4581 except OSError:
4580 except OSError:
4582 pass
4581 pass
4583 repo.dirstate.remove(f)
4582 repo.dirstate.remove(f)
4584
4583
4585 normal = None
4584 normal = None
4586 if node == parent:
4585 if node == parent:
4587 # We're reverting to our parent. If possible, we'd like status
4586 # We're reverting to our parent. If possible, we'd like status
4588 # to report the file as clean. We have to use normallookup for
4587 # to report the file as clean. We have to use normallookup for
4589 # merges to avoid losing information about merged/dirty files.
4588 # merges to avoid losing information about merged/dirty files.
4590 if p2 != nullid:
4589 if p2 != nullid:
4591 normal = repo.dirstate.normallookup
4590 normal = repo.dirstate.normallookup
4592 else:
4591 else:
4593 normal = repo.dirstate.normal
4592 normal = repo.dirstate.normal
4594 for f in revert[0]:
4593 for f in revert[0]:
4595 checkout(f)
4594 checkout(f)
4596 if normal:
4595 if normal:
4597 normal(f)
4596 normal(f)
4598
4597
4599 for f in add[0]:
4598 for f in add[0]:
4600 checkout(f)
4599 checkout(f)
4601 repo.dirstate.add(f)
4600 repo.dirstate.add(f)
4602
4601
4603 normal = repo.dirstate.normallookup
4602 normal = repo.dirstate.normallookup
4604 if node == parent and p2 == nullid:
4603 if node == parent and p2 == nullid:
4605 normal = repo.dirstate.normal
4604 normal = repo.dirstate.normal
4606 for f in undelete[0]:
4605 for f in undelete[0]:
4607 checkout(f)
4606 checkout(f)
4608 normal(f)
4607 normal(f)
4609
4608
4610 finally:
4609 finally:
4611 wlock.release()
4610 wlock.release()
4612
4611
4613 @command('rollback', dryrunopts +
4612 @command('rollback', dryrunopts +
4614 [('f', 'force', False, _('ignore safety measures'))])
4613 [('f', 'force', False, _('ignore safety measures'))])
4615 def rollback(ui, repo, **opts):
4614 def rollback(ui, repo, **opts):
4616 """roll back the last transaction (dangerous)
4615 """roll back the last transaction (dangerous)
4617
4616
4618 This command should be used with care. There is only one level of
4617 This command should be used with care. There is only one level of
4619 rollback, and there is no way to undo a rollback. It will also
4618 rollback, and there is no way to undo a rollback. It will also
4620 restore the dirstate at the time of the last transaction, losing
4619 restore the dirstate at the time of the last transaction, losing
4621 any dirstate changes since that time. This command does not alter
4620 any dirstate changes since that time. This command does not alter
4622 the working directory.
4621 the working directory.
4623
4622
4624 Transactions are used to encapsulate the effects of all commands
4623 Transactions are used to encapsulate the effects of all commands
4625 that create new changesets or propagate existing changesets into a
4624 that create new changesets or propagate existing changesets into a
4626 repository. For example, the following commands are transactional,
4625 repository. For example, the following commands are transactional,
4627 and their effects can be rolled back:
4626 and their effects can be rolled back:
4628
4627
4629 - commit
4628 - commit
4630 - import
4629 - import
4631 - pull
4630 - pull
4632 - push (with this repository as the destination)
4631 - push (with this repository as the destination)
4633 - unbundle
4632 - unbundle
4634
4633
4635 It's possible to lose data with rollback: commit, update back to
4634 It's possible to lose data with rollback: commit, update back to
4636 an older changeset, and then rollback. The update removes the
4635 an older changeset, and then rollback. The update removes the
4637 changes you committed from the working directory, and rollback
4636 changes you committed from the working directory, and rollback
4638 removes them from history. To avoid data loss, you must pass
4637 removes them from history. To avoid data loss, you must pass
4639 --force in this case.
4638 --force in this case.
4640
4639
4641 This command is not intended for use on public repositories. Once
4640 This command is not intended for use on public repositories. Once
4642 changes are visible for pull by other users, rolling a transaction
4641 changes are visible for pull by other users, rolling a transaction
4643 back locally is ineffective (someone else may already have pulled
4642 back locally is ineffective (someone else may already have pulled
4644 the changes). Furthermore, a race is possible with readers of the
4643 the changes). Furthermore, a race is possible with readers of the
4645 repository; for example an in-progress pull from the repository
4644 repository; for example an in-progress pull from the repository
4646 may fail if a rollback is performed.
4645 may fail if a rollback is performed.
4647
4646
4648 Returns 0 on success, 1 if no rollback data is available.
4647 Returns 0 on success, 1 if no rollback data is available.
4649 """
4648 """
4650 return repo.rollback(dryrun=opts.get('dry_run'),
4649 return repo.rollback(dryrun=opts.get('dry_run'),
4651 force=opts.get('force'))
4650 force=opts.get('force'))
4652
4651
4653 @command('root', [])
4652 @command('root', [])
4654 def root(ui, repo):
4653 def root(ui, repo):
4655 """print the root (top) of the current working directory
4654 """print the root (top) of the current working directory
4656
4655
4657 Print the root directory of the current repository.
4656 Print the root directory of the current repository.
4658
4657
4659 Returns 0 on success.
4658 Returns 0 on success.
4660 """
4659 """
4661 ui.write(repo.root + "\n")
4660 ui.write(repo.root + "\n")
4662
4661
4663 @command('^serve',
4662 @command('^serve',
4664 [('A', 'accesslog', '', _('name of access log file to write to'),
4663 [('A', 'accesslog', '', _('name of access log file to write to'),
4665 _('FILE')),
4664 _('FILE')),
4666 ('d', 'daemon', None, _('run server in background')),
4665 ('d', 'daemon', None, _('run server in background')),
4667 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4666 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4668 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4667 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4669 # use string type, then we can check if something was passed
4668 # use string type, then we can check if something was passed
4670 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4669 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4671 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4670 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4672 _('ADDR')),
4671 _('ADDR')),
4673 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4672 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4674 _('PREFIX')),
4673 _('PREFIX')),
4675 ('n', 'name', '',
4674 ('n', 'name', '',
4676 _('name to show in web pages (default: working directory)'), _('NAME')),
4675 _('name to show in web pages (default: working directory)'), _('NAME')),
4677 ('', 'web-conf', '',
4676 ('', 'web-conf', '',
4678 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4677 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4679 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4678 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4680 _('FILE')),
4679 _('FILE')),
4681 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4680 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4682 ('', 'stdio', None, _('for remote clients')),
4681 ('', 'stdio', None, _('for remote clients')),
4683 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4682 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4684 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4683 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4685 ('', 'style', '', _('template style to use'), _('STYLE')),
4684 ('', 'style', '', _('template style to use'), _('STYLE')),
4686 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4685 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4687 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4686 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4688 _('[OPTION]...'))
4687 _('[OPTION]...'))
4689 def serve(ui, repo, **opts):
4688 def serve(ui, repo, **opts):
4690 """start stand-alone webserver
4689 """start stand-alone webserver
4691
4690
4692 Start a local HTTP repository browser and pull server. You can use
4691 Start a local HTTP repository browser and pull server. You can use
4693 this for ad-hoc sharing and browsing of repositories. It is
4692 this for ad-hoc sharing and browsing of repositories. It is
4694 recommended to use a real web server to serve a repository for
4693 recommended to use a real web server to serve a repository for
4695 longer periods of time.
4694 longer periods of time.
4696
4695
4697 Please note that the server does not implement access control.
4696 Please note that the server does not implement access control.
4698 This means that, by default, anybody can read from the server and
4697 This means that, by default, anybody can read from the server and
4699 nobody can write to it by default. Set the ``web.allow_push``
4698 nobody can write to it by default. Set the ``web.allow_push``
4700 option to ``*`` to allow everybody to push to the server. You
4699 option to ``*`` to allow everybody to push to the server. You
4701 should use a real web server if you need to authenticate users.
4700 should use a real web server if you need to authenticate users.
4702
4701
4703 By default, the server logs accesses to stdout and errors to
4702 By default, the server logs accesses to stdout and errors to
4704 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4703 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4705 files.
4704 files.
4706
4705
4707 To have the server choose a free port number to listen on, specify
4706 To have the server choose a free port number to listen on, specify
4708 a port number of 0; in this case, the server will print the port
4707 a port number of 0; in this case, the server will print the port
4709 number it uses.
4708 number it uses.
4710
4709
4711 Returns 0 on success.
4710 Returns 0 on success.
4712 """
4711 """
4713
4712
4714 if opts["stdio"] and opts["cmdserver"]:
4713 if opts["stdio"] and opts["cmdserver"]:
4715 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4714 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4716
4715
4717 def checkrepo():
4716 def checkrepo():
4718 if repo is None:
4717 if repo is None:
4719 raise error.RepoError(_("There is no Mercurial repository here"
4718 raise error.RepoError(_("There is no Mercurial repository here"
4720 " (.hg not found)"))
4719 " (.hg not found)"))
4721
4720
4722 if opts["stdio"]:
4721 if opts["stdio"]:
4723 checkrepo()
4722 checkrepo()
4724 s = sshserver.sshserver(ui, repo)
4723 s = sshserver.sshserver(ui, repo)
4725 s.serve_forever()
4724 s.serve_forever()
4726
4725
4727 if opts["cmdserver"]:
4726 if opts["cmdserver"]:
4728 checkrepo()
4727 checkrepo()
4729 s = commandserver.server(ui, repo, opts["cmdserver"])
4728 s = commandserver.server(ui, repo, opts["cmdserver"])
4730 return s.serve()
4729 return s.serve()
4731
4730
4732 # this way we can check if something was given in the command-line
4731 # this way we can check if something was given in the command-line
4733 if opts.get('port'):
4732 if opts.get('port'):
4734 opts['port'] = util.getport(opts.get('port'))
4733 opts['port'] = util.getport(opts.get('port'))
4735
4734
4736 baseui = repo and repo.baseui or ui
4735 baseui = repo and repo.baseui or ui
4737 optlist = ("name templates style address port prefix ipv6"
4736 optlist = ("name templates style address port prefix ipv6"
4738 " accesslog errorlog certificate encoding")
4737 " accesslog errorlog certificate encoding")
4739 for o in optlist.split():
4738 for o in optlist.split():
4740 val = opts.get(o, '')
4739 val = opts.get(o, '')
4741 if val in (None, ''): # should check against default options instead
4740 if val in (None, ''): # should check against default options instead
4742 continue
4741 continue
4743 baseui.setconfig("web", o, val)
4742 baseui.setconfig("web", o, val)
4744 if repo and repo.ui != baseui:
4743 if repo and repo.ui != baseui:
4745 repo.ui.setconfig("web", o, val)
4744 repo.ui.setconfig("web", o, val)
4746
4745
4747 o = opts.get('web_conf') or opts.get('webdir_conf')
4746 o = opts.get('web_conf') or opts.get('webdir_conf')
4748 if not o:
4747 if not o:
4749 if not repo:
4748 if not repo:
4750 raise error.RepoError(_("There is no Mercurial repository"
4749 raise error.RepoError(_("There is no Mercurial repository"
4751 " here (.hg not found)"))
4750 " here (.hg not found)"))
4752 o = repo.root
4751 o = repo.root
4753
4752
4754 app = hgweb.hgweb(o, baseui=ui)
4753 app = hgweb.hgweb(o, baseui=ui)
4755
4754
4756 class service(object):
4755 class service(object):
4757 def init(self):
4756 def init(self):
4758 util.setsignalhandler()
4757 util.setsignalhandler()
4759 self.httpd = hgweb.server.create_server(ui, app)
4758 self.httpd = hgweb.server.create_server(ui, app)
4760
4759
4761 if opts['port'] and not ui.verbose:
4760 if opts['port'] and not ui.verbose:
4762 return
4761 return
4763
4762
4764 if self.httpd.prefix:
4763 if self.httpd.prefix:
4765 prefix = self.httpd.prefix.strip('/') + '/'
4764 prefix = self.httpd.prefix.strip('/') + '/'
4766 else:
4765 else:
4767 prefix = ''
4766 prefix = ''
4768
4767
4769 port = ':%d' % self.httpd.port
4768 port = ':%d' % self.httpd.port
4770 if port == ':80':
4769 if port == ':80':
4771 port = ''
4770 port = ''
4772
4771
4773 bindaddr = self.httpd.addr
4772 bindaddr = self.httpd.addr
4774 if bindaddr == '0.0.0.0':
4773 if bindaddr == '0.0.0.0':
4775 bindaddr = '*'
4774 bindaddr = '*'
4776 elif ':' in bindaddr: # IPv6
4775 elif ':' in bindaddr: # IPv6
4777 bindaddr = '[%s]' % bindaddr
4776 bindaddr = '[%s]' % bindaddr
4778
4777
4779 fqaddr = self.httpd.fqaddr
4778 fqaddr = self.httpd.fqaddr
4780 if ':' in fqaddr:
4779 if ':' in fqaddr:
4781 fqaddr = '[%s]' % fqaddr
4780 fqaddr = '[%s]' % fqaddr
4782 if opts['port']:
4781 if opts['port']:
4783 write = ui.status
4782 write = ui.status
4784 else:
4783 else:
4785 write = ui.write
4784 write = ui.write
4786 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4785 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4787 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4786 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4788
4787
4789 def run(self):
4788 def run(self):
4790 self.httpd.serve_forever()
4789 self.httpd.serve_forever()
4791
4790
4792 service = service()
4791 service = service()
4793
4792
4794 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4793 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4795
4794
4796 @command('showconfig|debugconfig',
4795 @command('showconfig|debugconfig',
4797 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4796 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4798 _('[-u] [NAME]...'))
4797 _('[-u] [NAME]...'))
4799 def showconfig(ui, repo, *values, **opts):
4798 def showconfig(ui, repo, *values, **opts):
4800 """show combined config settings from all hgrc files
4799 """show combined config settings from all hgrc files
4801
4800
4802 With no arguments, print names and values of all config items.
4801 With no arguments, print names and values of all config items.
4803
4802
4804 With one argument of the form section.name, print just the value
4803 With one argument of the form section.name, print just the value
4805 of that config item.
4804 of that config item.
4806
4805
4807 With multiple arguments, print names and values of all config
4806 With multiple arguments, print names and values of all config
4808 items with matching section names.
4807 items with matching section names.
4809
4808
4810 With --debug, the source (filename and line number) is printed
4809 With --debug, the source (filename and line number) is printed
4811 for each config item.
4810 for each config item.
4812
4811
4813 Returns 0 on success.
4812 Returns 0 on success.
4814 """
4813 """
4815
4814
4816 for f in scmutil.rcpath():
4815 for f in scmutil.rcpath():
4817 ui.debug('read config from: %s\n' % f)
4816 ui.debug('read config from: %s\n' % f)
4818 untrusted = bool(opts.get('untrusted'))
4817 untrusted = bool(opts.get('untrusted'))
4819 if values:
4818 if values:
4820 sections = [v for v in values if '.' not in v]
4819 sections = [v for v in values if '.' not in v]
4821 items = [v for v in values if '.' in v]
4820 items = [v for v in values if '.' in v]
4822 if len(items) > 1 or items and sections:
4821 if len(items) > 1 or items and sections:
4823 raise util.Abort(_('only one config item permitted'))
4822 raise util.Abort(_('only one config item permitted'))
4824 for section, name, value in ui.walkconfig(untrusted=untrusted):
4823 for section, name, value in ui.walkconfig(untrusted=untrusted):
4825 value = str(value).replace('\n', '\\n')
4824 value = str(value).replace('\n', '\\n')
4826 sectname = section + '.' + name
4825 sectname = section + '.' + name
4827 if values:
4826 if values:
4828 for v in values:
4827 for v in values:
4829 if v == section:
4828 if v == section:
4830 ui.debug('%s: ' %
4829 ui.debug('%s: ' %
4831 ui.configsource(section, name, untrusted))
4830 ui.configsource(section, name, untrusted))
4832 ui.write('%s=%s\n' % (sectname, value))
4831 ui.write('%s=%s\n' % (sectname, value))
4833 elif v == sectname:
4832 elif v == sectname:
4834 ui.debug('%s: ' %
4833 ui.debug('%s: ' %
4835 ui.configsource(section, name, untrusted))
4834 ui.configsource(section, name, untrusted))
4836 ui.write(value, '\n')
4835 ui.write(value, '\n')
4837 else:
4836 else:
4838 ui.debug('%s: ' %
4837 ui.debug('%s: ' %
4839 ui.configsource(section, name, untrusted))
4838 ui.configsource(section, name, untrusted))
4840 ui.write('%s=%s\n' % (sectname, value))
4839 ui.write('%s=%s\n' % (sectname, value))
4841
4840
4842 @command('^status|st',
4841 @command('^status|st',
4843 [('A', 'all', None, _('show status of all files')),
4842 [('A', 'all', None, _('show status of all files')),
4844 ('m', 'modified', None, _('show only modified files')),
4843 ('m', 'modified', None, _('show only modified files')),
4845 ('a', 'added', None, _('show only added files')),
4844 ('a', 'added', None, _('show only added files')),
4846 ('r', 'removed', None, _('show only removed files')),
4845 ('r', 'removed', None, _('show only removed files')),
4847 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4846 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4848 ('c', 'clean', None, _('show only files without changes')),
4847 ('c', 'clean', None, _('show only files without changes')),
4849 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4848 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4850 ('i', 'ignored', None, _('show only ignored files')),
4849 ('i', 'ignored', None, _('show only ignored files')),
4851 ('n', 'no-status', None, _('hide status prefix')),
4850 ('n', 'no-status', None, _('hide status prefix')),
4852 ('C', 'copies', None, _('show source of copied files')),
4851 ('C', 'copies', None, _('show source of copied files')),
4853 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4852 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4854 ('', 'rev', [], _('show difference from revision'), _('REV')),
4853 ('', 'rev', [], _('show difference from revision'), _('REV')),
4855 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4854 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4856 ] + walkopts + subrepoopts,
4855 ] + walkopts + subrepoopts,
4857 _('[OPTION]... [FILE]...'))
4856 _('[OPTION]... [FILE]...'))
4858 def status(ui, repo, *pats, **opts):
4857 def status(ui, repo, *pats, **opts):
4859 """show changed files in the working directory
4858 """show changed files in the working directory
4860
4859
4861 Show status of files in the repository. If names are given, only
4860 Show status of files in the repository. If names are given, only
4862 files that match are shown. Files that are clean or ignored or
4861 files that match are shown. Files that are clean or ignored or
4863 the source of a copy/move operation, are not listed unless
4862 the source of a copy/move operation, are not listed unless
4864 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4863 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4865 Unless options described with "show only ..." are given, the
4864 Unless options described with "show only ..." are given, the
4866 options -mardu are used.
4865 options -mardu are used.
4867
4866
4868 Option -q/--quiet hides untracked (unknown and ignored) files
4867 Option -q/--quiet hides untracked (unknown and ignored) files
4869 unless explicitly requested with -u/--unknown or -i/--ignored.
4868 unless explicitly requested with -u/--unknown or -i/--ignored.
4870
4869
4871 .. note::
4870 .. note::
4872 status may appear to disagree with diff if permissions have
4871 status may appear to disagree with diff if permissions have
4873 changed or a merge has occurred. The standard diff format does
4872 changed or a merge has occurred. The standard diff format does
4874 not report permission changes and diff only reports changes
4873 not report permission changes and diff only reports changes
4875 relative to one merge parent.
4874 relative to one merge parent.
4876
4875
4877 If one revision is given, it is used as the base revision.
4876 If one revision is given, it is used as the base revision.
4878 If two revisions are given, the differences between them are
4877 If two revisions are given, the differences between them are
4879 shown. The --change option can also be used as a shortcut to list
4878 shown. The --change option can also be used as a shortcut to list
4880 the changed files of a revision from its first parent.
4879 the changed files of a revision from its first parent.
4881
4880
4882 The codes used to show the status of files are::
4881 The codes used to show the status of files are::
4883
4882
4884 M = modified
4883 M = modified
4885 A = added
4884 A = added
4886 R = removed
4885 R = removed
4887 C = clean
4886 C = clean
4888 ! = missing (deleted by non-hg command, but still tracked)
4887 ! = missing (deleted by non-hg command, but still tracked)
4889 ? = not tracked
4888 ? = not tracked
4890 I = ignored
4889 I = ignored
4891 = origin of the previous file listed as A (added)
4890 = origin of the previous file listed as A (added)
4892
4891
4893 .. container:: verbose
4892 .. container:: verbose
4894
4893
4895 Examples:
4894 Examples:
4896
4895
4897 - show changes in the working directory relative to a changeset:
4896 - show changes in the working directory relative to a changeset:
4898
4897
4899 hg status --rev 9353
4898 hg status --rev 9353
4900
4899
4901 - show all changes including copies in an existing changeset::
4900 - show all changes including copies in an existing changeset::
4902
4901
4903 hg status --copies --change 9353
4902 hg status --copies --change 9353
4904
4903
4905 - get a NUL separated list of added files, suitable for xargs::
4904 - get a NUL separated list of added files, suitable for xargs::
4906
4905
4907 hg status -an0
4906 hg status -an0
4908
4907
4909 Returns 0 on success.
4908 Returns 0 on success.
4910 """
4909 """
4911
4910
4912 revs = opts.get('rev')
4911 revs = opts.get('rev')
4913 change = opts.get('change')
4912 change = opts.get('change')
4914
4913
4915 if revs and change:
4914 if revs and change:
4916 msg = _('cannot specify --rev and --change at the same time')
4915 msg = _('cannot specify --rev and --change at the same time')
4917 raise util.Abort(msg)
4916 raise util.Abort(msg)
4918 elif change:
4917 elif change:
4919 node2 = repo.lookup(change)
4918 node2 = repo.lookup(change)
4920 node1 = repo[node2].p1().node()
4919 node1 = repo[node2].p1().node()
4921 else:
4920 else:
4922 node1, node2 = scmutil.revpair(repo, revs)
4921 node1, node2 = scmutil.revpair(repo, revs)
4923
4922
4924 cwd = (pats and repo.getcwd()) or ''
4923 cwd = (pats and repo.getcwd()) or ''
4925 end = opts.get('print0') and '\0' or '\n'
4924 end = opts.get('print0') and '\0' or '\n'
4926 copy = {}
4925 copy = {}
4927 states = 'modified added removed deleted unknown ignored clean'.split()
4926 states = 'modified added removed deleted unknown ignored clean'.split()
4928 show = [k for k in states if opts.get(k)]
4927 show = [k for k in states if opts.get(k)]
4929 if opts.get('all'):
4928 if opts.get('all'):
4930 show += ui.quiet and (states[:4] + ['clean']) or states
4929 show += ui.quiet and (states[:4] + ['clean']) or states
4931 if not show:
4930 if not show:
4932 show = ui.quiet and states[:4] or states[:5]
4931 show = ui.quiet and states[:4] or states[:5]
4933
4932
4934 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4933 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4935 'ignored' in show, 'clean' in show, 'unknown' in show,
4934 'ignored' in show, 'clean' in show, 'unknown' in show,
4936 opts.get('subrepos'))
4935 opts.get('subrepos'))
4937 changestates = zip(states, 'MAR!?IC', stat)
4936 changestates = zip(states, 'MAR!?IC', stat)
4938
4937
4939 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4938 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4940 ctxn = repo[nullid]
4939 ctxn = repo[nullid]
4941 ctx1 = repo[node1]
4940 ctx1 = repo[node1]
4942 ctx2 = repo[node2]
4941 ctx2 = repo[node2]
4943 added = stat[1]
4942 added = stat[1]
4944 if node2 is None:
4943 if node2 is None:
4945 added = stat[0] + stat[1] # merged?
4944 added = stat[0] + stat[1] # merged?
4946
4945
4947 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4946 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4948 if k in added:
4947 if k in added:
4949 copy[k] = v
4948 copy[k] = v
4950 elif v in added:
4949 elif v in added:
4951 copy[v] = k
4950 copy[v] = k
4952
4951
4953 for state, char, files in changestates:
4952 for state, char, files in changestates:
4954 if state in show:
4953 if state in show:
4955 format = "%s %%s%s" % (char, end)
4954 format = "%s %%s%s" % (char, end)
4956 if opts.get('no_status'):
4955 if opts.get('no_status'):
4957 format = "%%s%s" % end
4956 format = "%%s%s" % end
4958
4957
4959 for f in files:
4958 for f in files:
4960 ui.write(format % repo.pathto(f, cwd),
4959 ui.write(format % repo.pathto(f, cwd),
4961 label='status.' + state)
4960 label='status.' + state)
4962 if f in copy:
4961 if f in copy:
4963 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4962 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4964 label='status.copied')
4963 label='status.copied')
4965
4964
4966 @command('^summary|sum',
4965 @command('^summary|sum',
4967 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4966 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4968 def summary(ui, repo, **opts):
4967 def summary(ui, repo, **opts):
4969 """summarize working directory state
4968 """summarize working directory state
4970
4969
4971 This generates a brief summary of the working directory state,
4970 This generates a brief summary of the working directory state,
4972 including parents, branch, commit status, and available updates.
4971 including parents, branch, commit status, and available updates.
4973
4972
4974 With the --remote option, this will check the default paths for
4973 With the --remote option, this will check the default paths for
4975 incoming and outgoing changes. This can be time-consuming.
4974 incoming and outgoing changes. This can be time-consuming.
4976
4975
4977 Returns 0 on success.
4976 Returns 0 on success.
4978 """
4977 """
4979
4978
4980 ctx = repo[None]
4979 ctx = repo[None]
4981 parents = ctx.parents()
4980 parents = ctx.parents()
4982 pnode = parents[0].node()
4981 pnode = parents[0].node()
4983 marks = []
4982 marks = []
4984
4983
4985 for p in parents:
4984 for p in parents:
4986 # label with log.changeset (instead of log.parent) since this
4985 # label with log.changeset (instead of log.parent) since this
4987 # shows a working directory parent *changeset*:
4986 # shows a working directory parent *changeset*:
4988 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4987 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4989 label='log.changeset')
4988 label='log.changeset')
4990 ui.write(' '.join(p.tags()), label='log.tag')
4989 ui.write(' '.join(p.tags()), label='log.tag')
4991 if p.bookmarks():
4990 if p.bookmarks():
4992 marks.extend(p.bookmarks())
4991 marks.extend(p.bookmarks())
4993 if p.rev() == -1:
4992 if p.rev() == -1:
4994 if not len(repo):
4993 if not len(repo):
4995 ui.write(_(' (empty repository)'))
4994 ui.write(_(' (empty repository)'))
4996 else:
4995 else:
4997 ui.write(_(' (no revision checked out)'))
4996 ui.write(_(' (no revision checked out)'))
4998 ui.write('\n')
4997 ui.write('\n')
4999 if p.description():
4998 if p.description():
5000 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4999 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5001 label='log.summary')
5000 label='log.summary')
5002
5001
5003 branch = ctx.branch()
5002 branch = ctx.branch()
5004 bheads = repo.branchheads(branch)
5003 bheads = repo.branchheads(branch)
5005 m = _('branch: %s\n') % branch
5004 m = _('branch: %s\n') % branch
5006 if branch != 'default':
5005 if branch != 'default':
5007 ui.write(m, label='log.branch')
5006 ui.write(m, label='log.branch')
5008 else:
5007 else:
5009 ui.status(m, label='log.branch')
5008 ui.status(m, label='log.branch')
5010
5009
5011 if marks:
5010 if marks:
5012 current = repo._bookmarkcurrent
5011 current = repo._bookmarkcurrent
5013 ui.write(_('bookmarks:'), label='log.bookmark')
5012 ui.write(_('bookmarks:'), label='log.bookmark')
5014 if current is not None:
5013 if current is not None:
5015 try:
5014 try:
5016 marks.remove(current)
5015 marks.remove(current)
5017 ui.write(' *' + current, label='bookmarks.current')
5016 ui.write(' *' + current, label='bookmarks.current')
5018 except ValueError:
5017 except ValueError:
5019 # current bookmark not in parent ctx marks
5018 # current bookmark not in parent ctx marks
5020 pass
5019 pass
5021 for m in marks:
5020 for m in marks:
5022 ui.write(' ' + m, label='log.bookmark')
5021 ui.write(' ' + m, label='log.bookmark')
5023 ui.write('\n', label='log.bookmark')
5022 ui.write('\n', label='log.bookmark')
5024
5023
5025 st = list(repo.status(unknown=True))[:6]
5024 st = list(repo.status(unknown=True))[:6]
5026
5025
5027 c = repo.dirstate.copies()
5026 c = repo.dirstate.copies()
5028 copied, renamed = [], []
5027 copied, renamed = [], []
5029 for d, s in c.iteritems():
5028 for d, s in c.iteritems():
5030 if s in st[2]:
5029 if s in st[2]:
5031 st[2].remove(s)
5030 st[2].remove(s)
5032 renamed.append(d)
5031 renamed.append(d)
5033 else:
5032 else:
5034 copied.append(d)
5033 copied.append(d)
5035 if d in st[1]:
5034 if d in st[1]:
5036 st[1].remove(d)
5035 st[1].remove(d)
5037 st.insert(3, renamed)
5036 st.insert(3, renamed)
5038 st.insert(4, copied)
5037 st.insert(4, copied)
5039
5038
5040 ms = mergemod.mergestate(repo)
5039 ms = mergemod.mergestate(repo)
5041 st.append([f for f in ms if ms[f] == 'u'])
5040 st.append([f for f in ms if ms[f] == 'u'])
5042
5041
5043 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5042 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5044 st.append(subs)
5043 st.append(subs)
5045
5044
5046 labels = [ui.label(_('%d modified'), 'status.modified'),
5045 labels = [ui.label(_('%d modified'), 'status.modified'),
5047 ui.label(_('%d added'), 'status.added'),
5046 ui.label(_('%d added'), 'status.added'),
5048 ui.label(_('%d removed'), 'status.removed'),
5047 ui.label(_('%d removed'), 'status.removed'),
5049 ui.label(_('%d renamed'), 'status.copied'),
5048 ui.label(_('%d renamed'), 'status.copied'),
5050 ui.label(_('%d copied'), 'status.copied'),
5049 ui.label(_('%d copied'), 'status.copied'),
5051 ui.label(_('%d deleted'), 'status.deleted'),
5050 ui.label(_('%d deleted'), 'status.deleted'),
5052 ui.label(_('%d unknown'), 'status.unknown'),
5051 ui.label(_('%d unknown'), 'status.unknown'),
5053 ui.label(_('%d ignored'), 'status.ignored'),
5052 ui.label(_('%d ignored'), 'status.ignored'),
5054 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5053 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5055 ui.label(_('%d subrepos'), 'status.modified')]
5054 ui.label(_('%d subrepos'), 'status.modified')]
5056 t = []
5055 t = []
5057 for s, l in zip(st, labels):
5056 for s, l in zip(st, labels):
5058 if s:
5057 if s:
5059 t.append(l % len(s))
5058 t.append(l % len(s))
5060
5059
5061 t = ', '.join(t)
5060 t = ', '.join(t)
5062 cleanworkdir = False
5061 cleanworkdir = False
5063
5062
5064 if len(parents) > 1:
5063 if len(parents) > 1:
5065 t += _(' (merge)')
5064 t += _(' (merge)')
5066 elif branch != parents[0].branch():
5065 elif branch != parents[0].branch():
5067 t += _(' (new branch)')
5066 t += _(' (new branch)')
5068 elif (parents[0].extra().get('close') and
5067 elif (parents[0].extra().get('close') and
5069 pnode in repo.branchheads(branch, closed=True)):
5068 pnode in repo.branchheads(branch, closed=True)):
5070 t += _(' (head closed)')
5069 t += _(' (head closed)')
5071 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5070 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5072 t += _(' (clean)')
5071 t += _(' (clean)')
5073 cleanworkdir = True
5072 cleanworkdir = True
5074 elif pnode not in bheads:
5073 elif pnode not in bheads:
5075 t += _(' (new branch head)')
5074 t += _(' (new branch head)')
5076
5075
5077 if cleanworkdir:
5076 if cleanworkdir:
5078 ui.status(_('commit: %s\n') % t.strip())
5077 ui.status(_('commit: %s\n') % t.strip())
5079 else:
5078 else:
5080 ui.write(_('commit: %s\n') % t.strip())
5079 ui.write(_('commit: %s\n') % t.strip())
5081
5080
5082 # all ancestors of branch heads - all ancestors of parent = new csets
5081 # all ancestors of branch heads - all ancestors of parent = new csets
5083 new = [0] * len(repo)
5082 new = [0] * len(repo)
5084 cl = repo.changelog
5083 cl = repo.changelog
5085 for a in [cl.rev(n) for n in bheads]:
5084 for a in [cl.rev(n) for n in bheads]:
5086 new[a] = 1
5085 new[a] = 1
5087 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5086 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5088 new[a] = 1
5087 new[a] = 1
5089 for a in [p.rev() for p in parents]:
5088 for a in [p.rev() for p in parents]:
5090 if a >= 0:
5089 if a >= 0:
5091 new[a] = 0
5090 new[a] = 0
5092 for a in cl.ancestors(*[p.rev() for p in parents]):
5091 for a in cl.ancestors(*[p.rev() for p in parents]):
5093 new[a] = 0
5092 new[a] = 0
5094 new = sum(new)
5093 new = sum(new)
5095
5094
5096 if new == 0:
5095 if new == 0:
5097 ui.status(_('update: (current)\n'))
5096 ui.status(_('update: (current)\n'))
5098 elif pnode not in bheads:
5097 elif pnode not in bheads:
5099 ui.write(_('update: %d new changesets (update)\n') % new)
5098 ui.write(_('update: %d new changesets (update)\n') % new)
5100 else:
5099 else:
5101 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5100 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5102 (new, len(bheads)))
5101 (new, len(bheads)))
5103
5102
5104 if opts.get('remote'):
5103 if opts.get('remote'):
5105 t = []
5104 t = []
5106 source, branches = hg.parseurl(ui.expandpath('default'))
5105 source, branches = hg.parseurl(ui.expandpath('default'))
5107 other = hg.peer(repo, {}, source)
5106 other = hg.peer(repo, {}, source)
5108 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5107 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5109 ui.debug('comparing with %s\n' % util.hidepassword(source))
5108 ui.debug('comparing with %s\n' % util.hidepassword(source))
5110 repo.ui.pushbuffer()
5109 repo.ui.pushbuffer()
5111 commoninc = discovery.findcommonincoming(repo, other)
5110 commoninc = discovery.findcommonincoming(repo, other)
5112 _common, incoming, _rheads = commoninc
5111 _common, incoming, _rheads = commoninc
5113 repo.ui.popbuffer()
5112 repo.ui.popbuffer()
5114 if incoming:
5113 if incoming:
5115 t.append(_('1 or more incoming'))
5114 t.append(_('1 or more incoming'))
5116
5115
5117 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5116 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5118 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5117 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5119 if source != dest:
5118 if source != dest:
5120 other = hg.peer(repo, {}, dest)
5119 other = hg.peer(repo, {}, dest)
5121 commoninc = None
5120 commoninc = None
5122 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5121 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5123 repo.ui.pushbuffer()
5122 repo.ui.pushbuffer()
5124 common, outheads = discovery.findcommonoutgoing(repo, other,
5123 common, outheads = discovery.findcommonoutgoing(repo, other,
5125 commoninc=commoninc)
5124 commoninc=commoninc)
5126 repo.ui.popbuffer()
5125 repo.ui.popbuffer()
5127 o = repo.changelog.findmissing(common=common, heads=outheads)
5126 o = repo.changelog.findmissing(common=common, heads=outheads)
5128 if o:
5127 if o:
5129 t.append(_('%d outgoing') % len(o))
5128 t.append(_('%d outgoing') % len(o))
5130 if 'bookmarks' in other.listkeys('namespaces'):
5129 if 'bookmarks' in other.listkeys('namespaces'):
5131 lmarks = repo.listkeys('bookmarks')
5130 lmarks = repo.listkeys('bookmarks')
5132 rmarks = other.listkeys('bookmarks')
5131 rmarks = other.listkeys('bookmarks')
5133 diff = set(rmarks) - set(lmarks)
5132 diff = set(rmarks) - set(lmarks)
5134 if len(diff) > 0:
5133 if len(diff) > 0:
5135 t.append(_('%d incoming bookmarks') % len(diff))
5134 t.append(_('%d incoming bookmarks') % len(diff))
5136 diff = set(lmarks) - set(rmarks)
5135 diff = set(lmarks) - set(rmarks)
5137 if len(diff) > 0:
5136 if len(diff) > 0:
5138 t.append(_('%d outgoing bookmarks') % len(diff))
5137 t.append(_('%d outgoing bookmarks') % len(diff))
5139
5138
5140 if t:
5139 if t:
5141 ui.write(_('remote: %s\n') % (', '.join(t)))
5140 ui.write(_('remote: %s\n') % (', '.join(t)))
5142 else:
5141 else:
5143 ui.status(_('remote: (synced)\n'))
5142 ui.status(_('remote: (synced)\n'))
5144
5143
5145 @command('tag',
5144 @command('tag',
5146 [('f', 'force', None, _('force tag')),
5145 [('f', 'force', None, _('force tag')),
5147 ('l', 'local', None, _('make the tag local')),
5146 ('l', 'local', None, _('make the tag local')),
5148 ('r', 'rev', '', _('revision to tag'), _('REV')),
5147 ('r', 'rev', '', _('revision to tag'), _('REV')),
5149 ('', 'remove', None, _('remove a tag')),
5148 ('', 'remove', None, _('remove a tag')),
5150 # -l/--local is already there, commitopts cannot be used
5149 # -l/--local is already there, commitopts cannot be used
5151 ('e', 'edit', None, _('edit commit message')),
5150 ('e', 'edit', None, _('edit commit message')),
5152 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5151 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5153 ] + commitopts2,
5152 ] + commitopts2,
5154 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5153 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5155 def tag(ui, repo, name1, *names, **opts):
5154 def tag(ui, repo, name1, *names, **opts):
5156 """add one or more tags for the current or given revision
5155 """add one or more tags for the current or given revision
5157
5156
5158 Name a particular revision using <name>.
5157 Name a particular revision using <name>.
5159
5158
5160 Tags are used to name particular revisions of the repository and are
5159 Tags are used to name particular revisions of the repository and are
5161 very useful to compare different revisions, to go back to significant
5160 very useful to compare different revisions, to go back to significant
5162 earlier versions or to mark branch points as releases, etc. Changing
5161 earlier versions or to mark branch points as releases, etc. Changing
5163 an existing tag is normally disallowed; use -f/--force to override.
5162 an existing tag is normally disallowed; use -f/--force to override.
5164
5163
5165 If no revision is given, the parent of the working directory is
5164 If no revision is given, the parent of the working directory is
5166 used, or tip if no revision is checked out.
5165 used, or tip if no revision is checked out.
5167
5166
5168 To facilitate version control, distribution, and merging of tags,
5167 To facilitate version control, distribution, and merging of tags,
5169 they are stored as a file named ".hgtags" which is managed similarly
5168 they are stored as a file named ".hgtags" which is managed similarly
5170 to other project files and can be hand-edited if necessary. This
5169 to other project files and can be hand-edited if necessary. This
5171 also means that tagging creates a new commit. The file
5170 also means that tagging creates a new commit. The file
5172 ".hg/localtags" is used for local tags (not shared among
5171 ".hg/localtags" is used for local tags (not shared among
5173 repositories).
5172 repositories).
5174
5173
5175 Tag commits are usually made at the head of a branch. If the parent
5174 Tag commits are usually made at the head of a branch. If the parent
5176 of the working directory is not a branch head, :hg:`tag` aborts; use
5175 of the working directory is not a branch head, :hg:`tag` aborts; use
5177 -f/--force to force the tag commit to be based on a non-head
5176 -f/--force to force the tag commit to be based on a non-head
5178 changeset.
5177 changeset.
5179
5178
5180 See :hg:`help dates` for a list of formats valid for -d/--date.
5179 See :hg:`help dates` for a list of formats valid for -d/--date.
5181
5180
5182 Since tag names have priority over branch names during revision
5181 Since tag names have priority over branch names during revision
5183 lookup, using an existing branch name as a tag name is discouraged.
5182 lookup, using an existing branch name as a tag name is discouraged.
5184
5183
5185 Returns 0 on success.
5184 Returns 0 on success.
5186 """
5185 """
5187
5186
5188 rev_ = "."
5187 rev_ = "."
5189 names = [t.strip() for t in (name1,) + names]
5188 names = [t.strip() for t in (name1,) + names]
5190 if len(names) != len(set(names)):
5189 if len(names) != len(set(names)):
5191 raise util.Abort(_('tag names must be unique'))
5190 raise util.Abort(_('tag names must be unique'))
5192 for n in names:
5191 for n in names:
5193 if n in ['tip', '.', 'null']:
5192 if n in ['tip', '.', 'null']:
5194 raise util.Abort(_("the name '%s' is reserved") % n)
5193 raise util.Abort(_("the name '%s' is reserved") % n)
5195 if not n:
5194 if not n:
5196 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5195 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5197 if opts.get('rev') and opts.get('remove'):
5196 if opts.get('rev') and opts.get('remove'):
5198 raise util.Abort(_("--rev and --remove are incompatible"))
5197 raise util.Abort(_("--rev and --remove are incompatible"))
5199 if opts.get('rev'):
5198 if opts.get('rev'):
5200 rev_ = opts['rev']
5199 rev_ = opts['rev']
5201 message = opts.get('message')
5200 message = opts.get('message')
5202 if opts.get('remove'):
5201 if opts.get('remove'):
5203 expectedtype = opts.get('local') and 'local' or 'global'
5202 expectedtype = opts.get('local') and 'local' or 'global'
5204 for n in names:
5203 for n in names:
5205 if not repo.tagtype(n):
5204 if not repo.tagtype(n):
5206 raise util.Abort(_("tag '%s' does not exist") % n)
5205 raise util.Abort(_("tag '%s' does not exist") % n)
5207 if repo.tagtype(n) != expectedtype:
5206 if repo.tagtype(n) != expectedtype:
5208 if expectedtype == 'global':
5207 if expectedtype == 'global':
5209 raise util.Abort(_("tag '%s' is not a global tag") % n)
5208 raise util.Abort(_("tag '%s' is not a global tag") % n)
5210 else:
5209 else:
5211 raise util.Abort(_("tag '%s' is not a local tag") % n)
5210 raise util.Abort(_("tag '%s' is not a local tag") % n)
5212 rev_ = nullid
5211 rev_ = nullid
5213 if not message:
5212 if not message:
5214 # we don't translate commit messages
5213 # we don't translate commit messages
5215 message = 'Removed tag %s' % ', '.join(names)
5214 message = 'Removed tag %s' % ', '.join(names)
5216 elif not opts.get('force'):
5215 elif not opts.get('force'):
5217 for n in names:
5216 for n in names:
5218 if n in repo.tags():
5217 if n in repo.tags():
5219 raise util.Abort(_("tag '%s' already exists "
5218 raise util.Abort(_("tag '%s' already exists "
5220 "(use -f to force)") % n)
5219 "(use -f to force)") % n)
5221 if not opts.get('local'):
5220 if not opts.get('local'):
5222 p1, p2 = repo.dirstate.parents()
5221 p1, p2 = repo.dirstate.parents()
5223 if p2 != nullid:
5222 if p2 != nullid:
5224 raise util.Abort(_('uncommitted merge'))
5223 raise util.Abort(_('uncommitted merge'))
5225 bheads = repo.branchheads()
5224 bheads = repo.branchheads()
5226 if not opts.get('force') and bheads and p1 not in bheads:
5225 if not opts.get('force') and bheads and p1 not in bheads:
5227 raise util.Abort(_('not at a branch head (use -f to force)'))
5226 raise util.Abort(_('not at a branch head (use -f to force)'))
5228 r = scmutil.revsingle(repo, rev_).node()
5227 r = scmutil.revsingle(repo, rev_).node()
5229
5228
5230 if not message:
5229 if not message:
5231 # we don't translate commit messages
5230 # we don't translate commit messages
5232 message = ('Added tag %s for changeset %s' %
5231 message = ('Added tag %s for changeset %s' %
5233 (', '.join(names), short(r)))
5232 (', '.join(names), short(r)))
5234
5233
5235 date = opts.get('date')
5234 date = opts.get('date')
5236 if date:
5235 if date:
5237 date = util.parsedate(date)
5236 date = util.parsedate(date)
5238
5237
5239 if opts.get('edit'):
5238 if opts.get('edit'):
5240 message = ui.edit(message, ui.username())
5239 message = ui.edit(message, ui.username())
5241
5240
5242 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5241 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5243
5242
5244 @command('tags', [], '')
5243 @command('tags', [], '')
5245 def tags(ui, repo):
5244 def tags(ui, repo):
5246 """list repository tags
5245 """list repository tags
5247
5246
5248 This lists both regular and local tags. When the -v/--verbose
5247 This lists both regular and local tags. When the -v/--verbose
5249 switch is used, a third column "local" is printed for local tags.
5248 switch is used, a third column "local" is printed for local tags.
5250
5249
5251 Returns 0 on success.
5250 Returns 0 on success.
5252 """
5251 """
5253
5252
5254 hexfunc = ui.debugflag and hex or short
5253 hexfunc = ui.debugflag and hex or short
5255 tagtype = ""
5254 tagtype = ""
5256
5255
5257 for t, n in reversed(repo.tagslist()):
5256 for t, n in reversed(repo.tagslist()):
5258 if ui.quiet:
5257 if ui.quiet:
5259 ui.write("%s\n" % t, label='tags.normal')
5258 ui.write("%s\n" % t, label='tags.normal')
5260 continue
5259 continue
5261
5260
5262 hn = hexfunc(n)
5261 hn = hexfunc(n)
5263 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5262 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5264 rev = ui.label(r, 'log.changeset')
5263 rev = ui.label(r, 'log.changeset')
5265 spaces = " " * (30 - encoding.colwidth(t))
5264 spaces = " " * (30 - encoding.colwidth(t))
5266
5265
5267 tag = ui.label(t, 'tags.normal')
5266 tag = ui.label(t, 'tags.normal')
5268 if ui.verbose:
5267 if ui.verbose:
5269 if repo.tagtype(t) == 'local':
5268 if repo.tagtype(t) == 'local':
5270 tagtype = " local"
5269 tagtype = " local"
5271 tag = ui.label(t, 'tags.local')
5270 tag = ui.label(t, 'tags.local')
5272 else:
5271 else:
5273 tagtype = ""
5272 tagtype = ""
5274 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5273 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5275
5274
5276 @command('tip',
5275 @command('tip',
5277 [('p', 'patch', None, _('show patch')),
5276 [('p', 'patch', None, _('show patch')),
5278 ('g', 'git', None, _('use git extended diff format')),
5277 ('g', 'git', None, _('use git extended diff format')),
5279 ] + templateopts,
5278 ] + templateopts,
5280 _('[-p] [-g]'))
5279 _('[-p] [-g]'))
5281 def tip(ui, repo, **opts):
5280 def tip(ui, repo, **opts):
5282 """show the tip revision
5281 """show the tip revision
5283
5282
5284 The tip revision (usually just called the tip) is the changeset
5283 The tip revision (usually just called the tip) is the changeset
5285 most recently added to the repository (and therefore the most
5284 most recently added to the repository (and therefore the most
5286 recently changed head).
5285 recently changed head).
5287
5286
5288 If you have just made a commit, that commit will be the tip. If
5287 If you have just made a commit, that commit will be the tip. If
5289 you have just pulled changes from another repository, the tip of
5288 you have just pulled changes from another repository, the tip of
5290 that repository becomes the current tip. The "tip" tag is special
5289 that repository becomes the current tip. The "tip" tag is special
5291 and cannot be renamed or assigned to a different changeset.
5290 and cannot be renamed or assigned to a different changeset.
5292
5291
5293 Returns 0 on success.
5292 Returns 0 on success.
5294 """
5293 """
5295 displayer = cmdutil.show_changeset(ui, repo, opts)
5294 displayer = cmdutil.show_changeset(ui, repo, opts)
5296 displayer.show(repo[len(repo) - 1])
5295 displayer.show(repo[len(repo) - 1])
5297 displayer.close()
5296 displayer.close()
5298
5297
5299 @command('unbundle',
5298 @command('unbundle',
5300 [('u', 'update', None,
5299 [('u', 'update', None,
5301 _('update to new branch head if changesets were unbundled'))],
5300 _('update to new branch head if changesets were unbundled'))],
5302 _('[-u] FILE...'))
5301 _('[-u] FILE...'))
5303 def unbundle(ui, repo, fname1, *fnames, **opts):
5302 def unbundle(ui, repo, fname1, *fnames, **opts):
5304 """apply one or more changegroup files
5303 """apply one or more changegroup files
5305
5304
5306 Apply one or more compressed changegroup files generated by the
5305 Apply one or more compressed changegroup files generated by the
5307 bundle command.
5306 bundle command.
5308
5307
5309 Returns 0 on success, 1 if an update has unresolved files.
5308 Returns 0 on success, 1 if an update has unresolved files.
5310 """
5309 """
5311 fnames = (fname1,) + fnames
5310 fnames = (fname1,) + fnames
5312
5311
5313 lock = repo.lock()
5312 lock = repo.lock()
5314 wc = repo['.']
5313 wc = repo['.']
5315 try:
5314 try:
5316 for fname in fnames:
5315 for fname in fnames:
5317 f = url.open(ui, fname)
5316 f = url.open(ui, fname)
5318 gen = changegroup.readbundle(f, fname)
5317 gen = changegroup.readbundle(f, fname)
5319 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5318 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5320 lock=lock)
5319 lock=lock)
5321 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5320 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5322 finally:
5321 finally:
5323 lock.release()
5322 lock.release()
5324 return postincoming(ui, repo, modheads, opts.get('update'), None)
5323 return postincoming(ui, repo, modheads, opts.get('update'), None)
5325
5324
5326 @command('^update|up|checkout|co',
5325 @command('^update|up|checkout|co',
5327 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5326 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5328 ('c', 'check', None,
5327 ('c', 'check', None,
5329 _('update across branches if no uncommitted changes')),
5328 _('update across branches if no uncommitted changes')),
5330 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5329 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5331 ('r', 'rev', '', _('revision'), _('REV'))],
5330 ('r', 'rev', '', _('revision'), _('REV'))],
5332 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5331 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5333 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5332 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5334 """update working directory (or switch revisions)
5333 """update working directory (or switch revisions)
5335
5334
5336 Update the repository's working directory to the specified
5335 Update the repository's working directory to the specified
5337 changeset. If no changeset is specified, update to the tip of the
5336 changeset. If no changeset is specified, update to the tip of the
5338 current named branch.
5337 current named branch.
5339
5338
5340 If the changeset is not a descendant of the working directory's
5339 If the changeset is not a descendant of the working directory's
5341 parent, the update is aborted. With the -c/--check option, the
5340 parent, the update is aborted. With the -c/--check option, the
5342 working directory is checked for uncommitted changes; if none are
5341 working directory is checked for uncommitted changes; if none are
5343 found, the working directory is updated to the specified
5342 found, the working directory is updated to the specified
5344 changeset.
5343 changeset.
5345
5344
5346 Update sets the working directory's parent revison to the specified
5345 Update sets the working directory's parent revison to the specified
5347 changeset (see :hg:`help parents`).
5346 changeset (see :hg:`help parents`).
5348
5347
5349 The following rules apply when the working directory contains
5348 The following rules apply when the working directory contains
5350 uncommitted changes:
5349 uncommitted changes:
5351
5350
5352 1. If neither -c/--check nor -C/--clean is specified, and if
5351 1. If neither -c/--check nor -C/--clean is specified, and if
5353 the requested changeset is an ancestor or descendant of
5352 the requested changeset is an ancestor or descendant of
5354 the working directory's parent, the uncommitted changes
5353 the working directory's parent, the uncommitted changes
5355 are merged into the requested changeset and the merged
5354 are merged into the requested changeset and the merged
5356 result is left uncommitted. If the requested changeset is
5355 result is left uncommitted. If the requested changeset is
5357 not an ancestor or descendant (that is, it is on another
5356 not an ancestor or descendant (that is, it is on another
5358 branch), the update is aborted and the uncommitted changes
5357 branch), the update is aborted and the uncommitted changes
5359 are preserved.
5358 are preserved.
5360
5359
5361 2. With the -c/--check option, the update is aborted and the
5360 2. With the -c/--check option, the update is aborted and the
5362 uncommitted changes are preserved.
5361 uncommitted changes are preserved.
5363
5362
5364 3. With the -C/--clean option, uncommitted changes are discarded and
5363 3. With the -C/--clean option, uncommitted changes are discarded and
5365 the working directory is updated to the requested changeset.
5364 the working directory is updated to the requested changeset.
5366
5365
5367 Use null as the changeset to remove the working directory (like
5366 Use null as the changeset to remove the working directory (like
5368 :hg:`clone -U`).
5367 :hg:`clone -U`).
5369
5368
5370 If you want to revert just one file to an older revision, use
5369 If you want to revert just one file to an older revision, use
5371 :hg:`revert [-r REV] NAME`.
5370 :hg:`revert [-r REV] NAME`.
5372
5371
5373 See :hg:`help dates` for a list of formats valid for -d/--date.
5372 See :hg:`help dates` for a list of formats valid for -d/--date.
5374
5373
5375 Returns 0 on success, 1 if there are unresolved files.
5374 Returns 0 on success, 1 if there are unresolved files.
5376 """
5375 """
5377 if rev and node:
5376 if rev and node:
5378 raise util.Abort(_("please specify just one revision"))
5377 raise util.Abort(_("please specify just one revision"))
5379
5378
5380 if rev is None or rev == '':
5379 if rev is None or rev == '':
5381 rev = node
5380 rev = node
5382
5381
5383 # if we defined a bookmark, we have to remember the original bookmark name
5382 # if we defined a bookmark, we have to remember the original bookmark name
5384 brev = rev
5383 brev = rev
5385 rev = scmutil.revsingle(repo, rev, rev).rev()
5384 rev = scmutil.revsingle(repo, rev, rev).rev()
5386
5385
5387 if check and clean:
5386 if check and clean:
5388 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5387 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5389
5388
5390 if check:
5389 if check:
5391 # we could use dirty() but we can ignore merge and branch trivia
5390 # we could use dirty() but we can ignore merge and branch trivia
5392 c = repo[None]
5391 c = repo[None]
5393 if c.modified() or c.added() or c.removed():
5392 if c.modified() or c.added() or c.removed():
5394 raise util.Abort(_("uncommitted local changes"))
5393 raise util.Abort(_("uncommitted local changes"))
5395
5394
5396 if date:
5395 if date:
5397 if rev is not None:
5396 if rev is not None:
5398 raise util.Abort(_("you can't specify a revision and a date"))
5397 raise util.Abort(_("you can't specify a revision and a date"))
5399 rev = cmdutil.finddate(ui, repo, date)
5398 rev = cmdutil.finddate(ui, repo, date)
5400
5399
5401 if clean or check:
5400 if clean or check:
5402 ret = hg.clean(repo, rev)
5401 ret = hg.clean(repo, rev)
5403 else:
5402 else:
5404 ret = hg.update(repo, rev)
5403 ret = hg.update(repo, rev)
5405
5404
5406 if brev in repo._bookmarks:
5405 if brev in repo._bookmarks:
5407 bookmarks.setcurrent(repo, brev)
5406 bookmarks.setcurrent(repo, brev)
5408
5407
5409 return ret
5408 return ret
5410
5409
5411 @command('verify', [])
5410 @command('verify', [])
5412 def verify(ui, repo):
5411 def verify(ui, repo):
5413 """verify the integrity of the repository
5412 """verify the integrity of the repository
5414
5413
5415 Verify the integrity of the current repository.
5414 Verify the integrity of the current repository.
5416
5415
5417 This will perform an extensive check of the repository's
5416 This will perform an extensive check of the repository's
5418 integrity, validating the hashes and checksums of each entry in
5417 integrity, validating the hashes and checksums of each entry in
5419 the changelog, manifest, and tracked files, as well as the
5418 the changelog, manifest, and tracked files, as well as the
5420 integrity of their crosslinks and indices.
5419 integrity of their crosslinks and indices.
5421
5420
5422 Returns 0 on success, 1 if errors are encountered.
5421 Returns 0 on success, 1 if errors are encountered.
5423 """
5422 """
5424 return hg.verify(repo)
5423 return hg.verify(repo)
5425
5424
5426 @command('version', [])
5425 @command('version', [])
5427 def version_(ui):
5426 def version_(ui):
5428 """output version and copyright information"""
5427 """output version and copyright information"""
5429 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5428 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5430 % util.version())
5429 % util.version())
5431 ui.status(_(
5430 ui.status(_(
5432 "(see http://mercurial.selenic.com for more information)\n"
5431 "(see http://mercurial.selenic.com for more information)\n"
5433 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5432 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5434 "This is free software; see the source for copying conditions. "
5433 "This is free software; see the source for copying conditions. "
5435 "There is NO\nwarranty; "
5434 "There is NO\nwarranty; "
5436 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5435 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5437 ))
5436 ))
5438
5437
5439 norepo = ("clone init version help debugcommands debugcomplete"
5438 norepo = ("clone init version help debugcommands debugcomplete"
5440 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5439 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5441 " debugknown debuggetbundle debugbundle")
5440 " debugknown debuggetbundle debugbundle")
5442 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5441 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5443 " debugdata debugindex debugindexdot debugrevlog")
5442 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now