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